利用Minikube来部署一个nodejs应用

Kubernetes 是 docker 容器编排系统, 用于协调高可用的计算机集群,并在这个集群上以更有效的方式自动分发和调度应用程序。由于kubernetes本地安装比较复杂,所以社区推出了Minikube。Minikube 是在本地的虚拟机中运行一个单节点的kubernetes集群。
本文将会介绍Minikube的安装,在kubernetes集群上部署一个应用,并且简单扩容以及通过rolling update更新镜像。最后会简单介绍一下 kubernetes dashboard的简单使用。

搭建kubernetes环境

安装Minikube

Minikube 可以安装在linux、mac和windows上。我们只介绍在mac 以及 ubuntu 14.04上的安装。更多关于安装Minikube请参考官方教程
Minikube是使用go开发生成的二进制文件,下载并放到/usr/local/bin即可。

// linux 下安装
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/ 
// mac
brew cask install minikube //可能不是最新
// 也可以下面的方式
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.21.0/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/

验证安装成功。

$ minikube version
minikube version: v0.21.0

安装vm

因为Minikube是在host上启动一个VM来运行Kubernetes集群的,所以还要安装一个VM。
下面介绍mac下安装xhyve和 linux下安装virtual box。更多关于vm的安装,请参考下面的安装指导

// linux virtualbox
sudo apt-get install virtualbox

// macos xhyxhyve
brew install docker-machine-driver-xhyve
sudo chown root:wheel $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve
sudo chmod u+s $(brew --prefix)/opt/docker-machine-driver-xhyve/bin/docker-machine-driver-xhyve

安装kubectl

Kubectl是kubernetes的命令行工具,用来 管理部署在kubernetes上的应用。可以根据自己的操作系统,按照官网教程安装kubectl。

// 1. 下载
// linux 
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
// mac
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
或者
$ brew install kubectl

// 2. 更改执行权限 并移到指定位置。
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl

验证kubectl是否安装成功。

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-06-29T23:15:59Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.0", GitCommit:"d3ada0119e776222f11ec7945e6d860061339aad", GitTreeState:"clean", BuildDate:"2017-07-26T00:12:31Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}

这里有可能会出现下面的错误状况。

Client Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.2", GitCommit:"922a86cfcd65915a9b2f69f3f193b8907d741d9c", GitTreeState:"clean", BuildDate:"2017-07-21T19:06:19Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"darwin/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?

这里只有客户端的信息,没有服务端的信息,那是因为我们的Minikube还没有启动,下面我们就启动Minikube。

启动Minikube

安装上面的工具之后,就可以通过minikube start来启动。

$ minikube start
Starting local Kubernetes v1.7.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Starting cluster components...
Connecting to cluster...
Setting up kubeconfig...
Kubectl is now configured to use the cluster.

也可以通过--vm-driver指定虚拟机启动。

minikube start --vm-driver xhyve

这样minikube就启动了。可以通过kubectl cluster-info查看集群的信息。

$ kubectl cluster-info
Kubernetes master is running at https://192.168.99.100:8443

可以看到一个运行的master。
也可以通过kubectl get nodes查看运行的node(目前只有一个)。

$kubectl get nodes
NAME       STATUS    AGE       VERSION
minikube   Ready     13m       v1.7.0

这里还要介绍个概念就是context。context决定kubectl与哪个cluster交互。可以在~/.kube/config中查看。通过以下指令指定context。

kubectl config use-context minikube

默认就是minikube。

部署应用

启动kubernetes cluster之后,就可以部署应用到集群上。部署一个应用需要创建一个Deployment。Deployment 负责创建和更新应用程序实例。创建Deployment之后,kubernetes master 会将创建的应用程序调度到各个node上。
创建应用实例后,kubernetes deploymentController 会监视这些实例,如果某个节点不可用或者删除,会自动替换实例。
创建部署时,通常需要指定应用程序的镜像副本数。以下部署一个简单的node应用。

const express = require('express');
const http = require('http');

const app = express();

app.get('/', (req, res) => {
  return res.send({ success: true, msg: 'hello kubernetes'});
});

http.createServer(app).listen(1226, () => {
  console.log('Server is listening on port 1226');
});

这个镜像我push到了docker hub

这里因为刚开始试的时候,Minikube里一直拉取不了镜像。正确的方式应该是搭建一个private docker registry。但折腾中还有点不明白之处,所以这里先不做具体介绍,直接push到docker hub。后续会介绍更多关于docker registry的搭建,到时候顺便再一起解释。

也可以使用minikube VM的docker来拉镜像。

$ eval $(minikube docker-env)

如果不需要使用minikube的docker,可以再恢复。

$ eval $(minikube docker-env -u)

使用kubectl run 创建一个部署。

$ kubectl run docker-demo --image=docker_demo --port=1226

image指定镜像,port指定端口。这里要注意的是,启动的容器名docker-demo,只能是小写字母、数字和加 - 横线。
这样我们就部署了一个应用到node上。通过kubectl get deployments查看。

$ kubectl get deployments
NAME          DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
docker-demo   1         1         1            0           22s

如果pods一直处于ContainerCreating阶段,可能还是还不能拉取镜像。

可以通过minikube ssh进入vm,然后拉取对应镜像。

$ minikube ssh
$ docker pull dennisge/docker_demo

这时,可以看到我们的pod的状态是running。到此,我们就成功部署了我们的应用。

基本概念和指令

Kubernetes 集群由两种类型的资源组成:masterNodes。 master是集群的调度节点,nodes则是应用程序实际运行的工作节点。类似于nginx的 master 和 worker。
部署应用时需要创建deployment。每个deployment 会根据指定的副本数,创建相应的pod来托管我们的应用实例。Pod可以理解为应用实例特定的逻辑主机,表示一个或多个容器组和这些容器的共享资源,包共用卷、唯一的集群IP和容器运行的信息,如端口等。
Node是kubernetes的工作机器(物理机或虚拟机)。Node由master管理,可以在一个node上部署多个pod。每个node至少需要两种组件,kubelet容器运行时(docker)。kubelet是负责master和所有节点间的通信进程,管理机器上运行的pod和容器。容器运行时负责从registry拉取镜像,解包镜像并运行应用实例。
kubectl 有一系列指令管理实例的运行情况。

// 查看deployment
kubectl get deployments 
// 删除deployment,会自动删除相应pods
kubectl delete deployment <部署名> 


// 查看pods
// 查看当前namespace下的pods
kubectl get pods  
// 查看所有pods
kubectl get pods --all-namespaces 
// 查看pods的具体信息
kubectl describe pod <pod name>
//特定namespace下的,需要指定namespace
kubectl describe pod <pod name> --namespace=kube-system

// 查看pod日志
kubectl logs pod <pod name>
// 进入pod
kubectl exec -it <pod name> bash

发布应用

通过上面部署的应用,在主机外访问不了(可以通过kubectl proxy的方式访问)。还要需要将其发布为service。 service是一组相同逻辑的pods和一个访问它们的策略。一组pods通常由label选择器确定。可以在ServiceSpec 中指定类型以不同的方式暴露服务。

  • Cluster IP(默认): 只有集群内部访问。
  • NodePort: 使用NAT方式,在集群中每个选定的节点的同一端口上暴露服务。可以在集群外部访问服务。
  • LoadBalancer:创建外部负载均衡。
  • ExternalName:使用任意名称显示服务。

可以通过kubectl expose命令来发布服务。

$ kubectl expose deployment/<deployment name> --type=NodePort --port 1226

这样就expose了一个服务,就可以外部访问了。可以通过一下指令得到url。

$ minikube service <service name> --url
http://192.168.64.2:32354

$ curl http://192.168.64.2:32354
{"success":true,"msg":"hello kubernetes"}

扩容和更新

根据线上需求,扩容和缩容是常会遇到的问题。Scaling 是通过更改 Deployment 中的副本数量实现的。一旦您有应用程序的多个实例,您将能够滚动更新,而不会停止服务。通过kubectl scale指令来扩容和缩容。

// 扩充到3个实例
kubectl scale deployments/docker-demo --replicas=3
// 缩小到1个实例
kubectl scale deployments/docker-demo --replicas=1

我们都是期望应用24/7运行,但又需要频繁部署。这我们就需要rolling update(滚动更新)。 Rolling updates 允许通过使用新的 Pods 实例逐个更新来实现零停机的部署更新。新的 Pods 会被调度到可用资源的 Node 节点上。可以通过set image修改镜像。

$ kubectl set image deployments/<部署名> <部署名>=镜像名:tag

如我们的第二版镜像。

kubectl set image deployments/docker-demo docker-demo=dennisge/docker_demo:v2

重新设置镜像之后,就会执行滚动更新。

以上我们就成功部署了自己的应用。但是都是通过指令来进行的,下面我们将介绍一下部署kubernetes dashboard,并通过web ui的方式部署、删除和修改相关应用等。

kubenetes dashboard

Kubernetes dashboard是一个基于web UI的用户接口,可以再界面上完成上面的部署应用、扩容缩容和滚动更新等一系列操作,也可以查看cluster的运行情况。
如果没GFW的原因,minikube会下载和部署一些组件的,运行在 kube-system namespace 下。可以查看镜像看看这些组件。

$ docker images
REPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZE

gcr.io/google_containers/k8s-dns-kube-dns-amd64        1.14.4              a8e00546bcf3        5 weeks ago         49.4MB
gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64   1.14.4              f7f45b9cb733        5 weeks ago         41.4MB
gcr.io/google-containers/kube-addon-manager            v6.4-beta.2         0a951668696f        7 weeks ago         79.2MB
gcr.io/google_containers/kubernetes-dashboard-amd64    v1.6.1              71dfe833ce74        2 months ago        134MB
gcr.io/google_containers/pause-amd64                   3.0                 99e59f495ffa        15 months ago       747kB

安装好之后,就可以通过以下指令获得dashboard的访问地址。

$ minikube dashboard --url

这样就可以访问dashboard,并进行相关的操作。
但这里通常会遇到dashboard 和 kube-addon-manager出现ImagePullBackOff的情况。这个问题就是我们无法拉取google的镜像。可以参考这个方法来解决。
这个方法主要是冒充原来的镜像。可以查看对应deployment的镜像,然后在别的地方如阿里镜像等拉取对应镜像,或者拉取镜像放到docker hub。再登陆Minikube,拉取该镜像,再重新tag为原deployment需要的镜像。
以kube-addon-manager 为例。

$ minikube ssh
$ docker pull registry.cn-hangzhou.aliyuncs.com/google-containers/kube-addon-manager-amd64:v6.1
$ docker tag registry.cn-hangzhou.aliyuncs.com/google-containers/kube-addon-manager-amd64:v6.1 gcr.io/google-containers/kube-addon-manager:v6.1

这样就可以看到这些组件的状态变为running。
这样的dashboard还是很朴素,如下图:

kubernetes-dashboard

这就需要安装heapster插件。可以查看现在的addons 列表。

$ minikube addons list
- registry: disabled
- dashboard: enabled
- kube-dns: enabled
- heapster: disabled
- ingress: disabled
- addon-manager: enabled
- default-storageclass: enabled
- registry-creds: disabled

发现heapster是关闭的。可以把它开启。

$ minikube addons enable heapter

我们会看到已经部署了相关的pod。

$ kubectl get pods --namespace=kube-system
NAME                          READY     STATUS             RESTARTS   AGE
heapster-jgzf2                1/1       Running            0          12h
influxdb-grafana-lqdtk        2/2       Running            0          12h

这通常会遇到ImagePullBackOff 问题,无法拉取镜像。这里需要以下几个镜像。

gcr.io/google_containers/heapster_influxdb:v0.6
gcr.io/google_containers/heapster_grafana:v2.6.0-2
gcr.io/google_containers/heapster_influxdb:v0.6

可以安装上面介绍的镜像冒充的方法解决这个问题。我是在我的aws上下载相应镜像push到我的docker hub。然后下载docker hub的镜像,再重命名需要的镜像。这样我们的heapster就正常运行了,可以看到漂亮的图表。
就可以愉快的使用dashboard了。

kubernetes-dashboard-heapster

总结

Kubernetes是docker的重要编排工具。我们通过Minikube来部署一个应用,来了解kubernetes的一些基本使用。
本文介绍了在mac和linux的Minikube安装、kubectl安装,以及基于VM来启动minikube集群。然后通过部署一个node应用,并成功地伸缩扩容并通过rolling update更新镜像。在这个过程中,我们也了解了node、deployment、pod、service等概念。最后我们介绍了一下kubernetes dashboard的安装、heapster插件安装以及可能遇到的问题及解决方案。

参考

[1] kubernetes tutorial
[2] 利用 Minikube 运行 Kubernetes
[3] Driver plugin installation
[4] minikube github
[5] mac安装kubernetes并运行echoserver
[6]Heapster Addon

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容