Kubernetes 是 docker 容器編排系統(tǒng), 用于協(xié)調(diào)高可用的計算機集群,并在這個集群上以更有效的方式自動分發(fā)和調(diào)度應(yīng)用程序。由于kubernetes本地安裝比較復(fù)雜,所以社區(qū)推出了Minikube。Minikube 是在本地的虛擬機中運行一個單節(jié)點的kubernetes集群。
本文將會介紹Minikube的安裝,在kubernetes集群上部署一個應(yīng)用,并且簡單擴容以及通過rolling update更新鏡像。最后會簡單介紹一下 kubernetes dashboard的簡單使用。
搭建kubernetes環(huán)境
安裝Minikube
Minikube 可以安裝在linux、mac和windows上。我們只介紹在mac 以及 ubuntu 14.04上的安裝。更多關(guān)于安裝Minikube請參考官方教程。
Minikube是使用go開發(fā)生成的二進制文件,下載并放到/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。更多關(guān)于vm的安裝,請參考下面的安裝指導(dǎo)。
// 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上的應(yīng)用??梢愿鶕?jù)自己的操作系統(tǒng),按照官網(wǎng)教程安裝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. 更改執(zhí)行權(quán)限 并移到指定位置。
$ 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"}
這里有可能會出現(xiàn)下面的錯誤狀況。
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?
這里只有客戶端的信息,沒有服務(wù)端的信息,那是因為我們的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交互??梢栽?code>~/.kube/config中查看。通過以下指令指定context。
kubectl config use-context minikube
默認就是minikube。
部署應(yīng)用
啟動kubernetes cluster之后,就可以部署應(yīng)用到集群上。部署一個應(yīng)用需要創(chuàng)建一個Deployment。Deployment 負責創(chuàng)建和更新應(yīng)用程序?qū)嵗?chuàng)建Deployment之后,kubernetes master 會將創(chuàng)建的應(yīng)用程序調(diào)度到各個node上。
創(chuàng)建應(yīng)用實例后,kubernetes deploymentController 會監(jiān)視這些實例,如果某個節(jié)點不可用或者刪除,會自動替換實例。
創(chuàng)建部署時,通常需要指定應(yīng)用程序的鏡像和副本數(shù)。以下部署一個簡單的node應(yīng)用。
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里一直拉取不了鏡像。正確的方式應(yīng)該是搭建一個private docker registry。但折騰中還有點不明白之處,所以這里先不做具體介紹,直接push到docker hub。后續(xù)會介紹更多關(guān)于docker registry的搭建,到時候順便再一起解釋。
也可以使用minikube VM的docker來拉鏡像。
$ eval $(minikube docker-env)
如果不需要使用minikube的docker,可以再恢復(fù)。
$ eval $(minikube docker-env -u)
使用kubectl run 創(chuàng)建一個部署。
$ kubectl run docker-demo --image=docker_demo --port=1226
image指定鏡像,port指定端口。這里要注意的是,啟動的容器名docker-demo,只能是小寫字母、數(shù)字和加 - 橫線。
這樣我們就部署了一個應(yīng)用到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,然后拉取對應(yīng)鏡像。
$ minikube ssh
$ docker pull dennisge/docker_demo
這時,可以看到我們的pod的狀態(tài)是running。到此,我們就成功部署了我們的應(yīng)用。
基本概念和指令
Kubernetes 集群由兩種類型的資源組成:master 和 Nodes。 master是集群的調(diào)度節(jié)點,nodes則是應(yīng)用程序?qū)嶋H運行的工作節(jié)點。類似于nginx的 master 和 worker。
部署應(yīng)用時需要創(chuàng)建deployment。每個deployment 會根據(jù)指定的副本數(shù),創(chuàng)建相應(yīng)的pod來托管我們的應(yīng)用實例。Pod可以理解為應(yīng)用實例特定的邏輯主機,表示一個或多個容器組和這些容器的共享資源,包共用卷、唯一的集群IP和容器運行的信息,如端口等。
而Node是kubernetes的工作機器(物理機或虛擬機)。Node由master管理,可以在一個node上部署多個pod。每個node至少需要兩種組件,kubelet 和 容器運行時(docker)。kubelet是負責master和所有節(jié)點間的通信進程,管理機器上運行的pod和容器。容器運行時負責從registry拉取鏡像,解包鏡像并運行應(yīng)用實例。
kubectl 有一系列指令管理實例的運行情況。
// 查看deployment
kubectl get deployments
// 刪除deployment,會自動刪除相應(yīng)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
發(fā)布應(yīng)用
通過上面部署的應(yīng)用,在主機外訪問不了(可以通過kubectl proxy的方式訪問)。還要需要將其發(fā)布為service。 service是一組相同邏輯的pods和一個訪問它們的策略。一組pods通常由label選擇器確定??梢栽赟erviceSpec 中指定類型以不同的方式暴露服務(wù)。
- Cluster IP(默認): 只有集群內(nèi)部訪問。
- NodePort: 使用NAT方式,在集群中每個選定的節(jié)點的同一端口上暴露服務(wù)??梢栽诩和獠吭L問服務(wù)。
- LoadBalancer:創(chuàng)建外部負載均衡。
- ExternalName:使用任意名稱顯示服務(wù)。
可以通過kubectl expose命令來發(fā)布服務(wù)。
$ kubectl expose deployment/<deployment name> --type=NodePort --port 1226
這樣就expose了一個服務(wù),就可以外部訪問了??梢酝ㄟ^一下指令得到url。
$ minikube service <service name> --url
http://192.168.64.2:32354
$ curl http://192.168.64.2:32354
{"success":true,"msg":"hello kubernetes"}
擴容和更新
根據(jù)線上需求,擴容和縮容是常會遇到的問題。Scaling 是通過更改 Deployment 中的副本數(shù)量實現(xiàn)的。一旦您有應(yīng)用程序的多個實例,您將能夠滾動更新,而不會停止服務(wù)。通過kubectl scale指令來擴容和縮容。
// 擴充到3個實例
kubectl scale deployments/docker-demo --replicas=3
// 縮小到1個實例
kubectl scale deployments/docker-demo --replicas=1
我們都是期望應(yīng)用24/7運行,但又需要頻繁部署。這我們就需要rolling update(滾動更新)。 Rolling updates 允許通過使用新的 Pods 實例逐個更新來實現(xiàn)零停機的部署更新。新的 Pods 會被調(diào)度到可用資源的 Node 節(jié)點上。可以通過set image修改鏡像。
$ kubectl set image deployments/<部署名> <部署名>=鏡像名:tag
如我們的第二版鏡像。
kubectl set image deployments/docker-demo docker-demo=dennisge/docker_demo:v2
重新設(shè)置鏡像之后,就會執(zhí)行滾動更新。
以上我們就成功部署了自己的應(yīng)用。但是都是通過指令來進行的,下面我們將介紹一下部署kubernetes dashboard,并通過web ui的方式部署、刪除和修改相關(guān)應(yīng)用等。
kubenetes dashboard
Kubernetes dashboard是一個基于web UI的用戶接口,可以再界面上完成上面的部署應(yīng)用、擴容縮容和滾動更新等一系列操作,也可以查看cluster的運行情況。
如果沒GFW的原因,minikube會下載和部署一些組件的,運行在 kube-system namespace 下??梢圆榭寸R像看看這些組件。
$ 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,并進行相關(guān)的操作。
但這里通常會遇到dashboard 和 kube-addon-manager出現(xiàn)ImagePullBackOff的情況。這個問題就是我們無法拉取google的鏡像??梢詤⒖歼@個方法來解決。
這個方法主要是冒充原來的鏡像。可以查看對應(yīng)deployment的鏡像,然后在別的地方如阿里鏡像等拉取對應(yīng)鏡像,或者拉取鏡像放到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
這樣就可以看到這些組件的狀態(tài)變?yōu)閞unning。
這樣的dashboard還是很樸素,如下圖:

這就需要安裝heapster插件??梢圆榭船F(xiàn)在的addons 列表。
$ minikube addons list
- registry: disabled
- dashboard: enabled
- kube-dns: enabled
- heapster: disabled
- ingress: disabled
- addon-manager: enabled
- default-storageclass: enabled
- registry-creds: disabled
發(fā)現(xiàn)heapster是關(guān)閉的??梢园阉_啟。
$ minikube addons enable heapter
我們會看到已經(jīng)部署了相關(guān)的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上下載相應(yīng)鏡像push到我的docker hub。然后下載docker hub的鏡像,再重命名需要的鏡像。這樣我們的heapster就正常運行了,可以看到漂亮的圖表。
就可以愉快的使用dashboard了。

總結(jié)
Kubernetes是docker的重要編排工具。我們通過Minikube來部署一個應(yīng)用,來了解kubernetes的一些基本使用。
本文介紹了在mac和linux的Minikube安裝、kubectl安裝,以及基于VM來啟動minikube集群。然后通過部署一個node應(yīng)用,并成功地伸縮擴容并通過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