容器化,雲原生越演越烈,新概念很是之多。信息爆炸的同時,帶來層層迷霧。我嘗試從擴容出發理解其脈路,通過實踐探索,整理造成一個入門教程,包括下面四篇文章。html
這是第三篇,kubernetes編排應用。node
Kubernetes是一個開源的,用於管理雲平臺中多個主機上的容器化的應用,Kubernetes的目標是讓部署容器化的應用簡單而且高效(powerful),Kubernetes提供了應用部署,規劃,更新,維護的一種機制。python
Kubernetes在希臘語中意思是船長或領航員,這也剛好與它在容器集羣管理中的做用吻合,即做爲裝載了集裝箱(Container)的衆多貨船的指揮者,負擔着全局調度和運行監控的職責。由於Kubernetes在k和s之間有8個字母,因此又簡稱k8slinux
快速體驗k8s,可使用Docker for mac中集成的k8s。nginx
啓動k8s後,等待其初始化完成,而後 docker ps
能夠看到k8s啓動了一系列的容器:git
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
17a693617137 docker/kube-compose-controller "/compose-controller…" 3 days ago Up 3 days k8s_compose_compose-74649b4db6-szsqz_docker_4f5997b7-5c47-11e9-95b9-025000000001_0
a9b666b48815 docker/kube-compose-api-server "/api-server --kubec…" 3 days ago Up 3 days k8s_compose_compose-api-5d754cdd89-ncwrq_docker_131b4d65-04e7-11e9-837c-025000000001_0
f4b05eefc73a 6f7f2dc7fab5 "/sidecar --v=2 --lo…" 3 days ago Up 3 days k8s_sidecar_kube-dns-86f4d74b45-zh6qc_kube-system_f669bc59-04e6-11e9-837c-025000000001_0
867f8f040258 c2ce1ffb51ed "/dnsmasq-nanny -v=2…" 3 days ago Up 3 days k8s_dnsmasq_kube-dns-86f4d74b45-zh6qc_kube-system_f669bc59-04e6-11e9-837c-025000000001_0
17f26a6e91d2 80cc5ea4b547 "/kube-dns --domain=…" 3 days ago Up 3 days k8s_kubedns_kube-dns-86f4d74b45-zh6qc_kube-system_f669bc59-04e6-11e9-837c-025000000001_0
...
複製代碼
kubectl version
查看集羣版本:github
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.11", GitCommit:"637c7e288581ee40ab4ca210618a89a555b6e7e9", GitTreeState:"clean", BuildDate:"2018-11-26T14:38:32Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.11", GitCommit:"637c7e288581ee40ab4ca210618a89a555b6e7e9", GitTreeState:"clean", BuildDate:"2018-11-26T14:25:46Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
複製代碼
kubectl get nodes
查看k8s集羣節點:redis
NAME STATUS ROLES AGE VERSION
docker-for-desktop Ready master 123d v1.10.11
複製代碼
kubectl get service
查看k8s默認啓動的服務:docker
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 123d
複製代碼
k8s/flaskapp.yaml
apiVersion: v1
kind: Service
metadata:
name: flaskapp
spec:
ports:
- port: 5000
selector:
name: flaskapp
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: flaskapp
spec:
replicas: 1
template:
metadata:
labels:
name: flaskapp
spec:
containers:
- image: flaskapp:0.0.2
name: flaskapp
ports:
- containerPort: 5000
複製代碼
瞭解這個部署文件,須要先大概瞭解一下k8s的運做方式。k8s經過api server提供restful接口,用於集羣交互。每個部署對象,都有apiVersion
,kind
, metadata
, spec
這幾個關鍵字。flask
k8s/redis.yaml
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
ports:
- port: 6379
selector:
name: redis
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
template:
metadata:
labels:
name: redis
spec:
containers:
- image: redis:4-alpine3.8
name: redis
ports:
- containerPort: 6379
複製代碼
redis的部署文件和flaskapp的部署文件相似。
k8s/nginx.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-config
data:
default.conf: |
upstream flaskapp {
server flaskapp:5000;
}
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
location / {
proxy_pass http://flaskapp;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
}
---
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
ports:
- port: 80
selector:
name: nginx
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
template:
metadata:
labels:
name: nginx
spec:
containers:
- image: nginx:1.15.8-alpine
name: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/conf.d/default.conf
subPath: default.conf
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config
複製代碼
nginx的部署文件,變化在:
nginx\default.conf
一致。使用kubectl apply -f k8s
命令將編寫yaml文件提交到k8s集羣,集羣會自動根據yaml文件的聲明,進行部署。
service "flaskapp" created
deployment.extensions "flaskapp" created
configmap "nginx-config" created
service "nginx" created
deployment.extensions "nginx" created
service "redis" created
deployment.extensions "redis" created
複製代碼
這裏的
kubectl apply -f k8s
表示將k8s目錄下的文件都提交給k8s集羣。固然,也能夠逐個文件提交kubectl apply -f k8s/redis.yaml
。
先kubectl get service
檢查一下k8s內的服務:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flaskapp ClusterIP 10.110.202.47 <none> 5000/TCP 31s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 123d
nginx NodePort 10.100.233.149 <none> 80:30457/TCP 31s
redis ClusterIP 10.106.55.214 <none> 6379/TCP 31s
複製代碼
注意nginx服務部分的PORTS爲80:30457/TCP,這表示將容器的80端口暴露到本機網絡的30457端口,和咱們以前的docker啓動時候的-p 80:80
參數相似。
服務是由Pod提供的,繼續檢查一下pods的情況kubectl get pods
:
NAME READY STATUS RESTARTS AGE
flaskapp-6c4fccdf99-v6w2v 1/1 Running 0 2m
nginx-85fb469b96-lr982 1/1 Running 0 2m
redis-5b44bb8d97-wwmll 1/1 Running 0 2m
複製代碼
固然,也能夠直接查看docker的容器docker ps
:
➜ docker2istio docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ad7377ae7196 ae70b17240ec "docker-entrypoint.s…" About an hour ago Up About an hour k8s_redis_redis-5b44bb8d97-wwmll_default_2907f4a3-6639-11e9-b8cb-025000000001_0
c01108b49076 1a61773c4c07 "python flaskapp.py" About an hour ago Up About an hour k8s_flaskapp_flaskapp-6c4fccdf99-xcmwb_default_28fbe1b1-6639-11e9-b8cb-025000000001_0
11d1fa3f182b 315798907716 "nginx -g 'daemon of…" About an hour ago Up About an hour k8s_nginx_nginx-85fb469b96-lr982_default_28fbdeee-6639-11e9-b8cb-025000000001_0
c28032a4b068 k8s.gcr.io/pause-amd64:3.1 "/pause" About an hour ago Up About an hour k8s_POD_redis-5b44bb8d97-wwmll_default_2907f4a3-6639-11e9-b8cb-025000000001_0
7091657acfbc k8s.gcr.io/pause-amd64:3.1 "/pause" About an hour ago Up About an hour k8s_POD_flaskapp-6c4fccdf99-xcmwb_default_28fbe1b1-6639-11e9-b8cb-025000000001_0
97007670c247 k8s.gcr.io/pause-amd64:3.1 "/pause" About an hour ago Up About an hour k8s_POD_nginx-85fb469b96-lr982_default_28fbdeee-6639-11e9-b8cb-025000000001_0
...
複製代碼
!!!注意: pod並不等同於docker的容器,Pod纔是k8s操做的最小單元。簡單的說,一個Pod可能包含多個容器,從yaml文件中containers:這個關鍵字能夠看出。仔細觀察
docker ps
的輸出,能夠發現每一個pod除了用戶自定義的容器外,還有鏡像爲k8s.gcr.io/pause-amd64:3.1的系統容器。
最後使用 curl http://127.0.0.1:30457
訪問服務
Hello World by 10.1.0.21 from 192.168.65.3 ! 該頁面已被訪問 1 次。
複製代碼
k8s集羣下,擴容很是簡單
➜ docker2istio kubectl edit deployment/flaskapp
deployment.extensions "flaskapp" edited
複製代碼
修改其中的** replicas: 3 **。
也能夠修改
k8s\flaskapp.yaml
中的值,而後kubectl apply -f k8s\flaskapp.yaml
另外,若是鏡像有更新,也是採用修改flaskapp.yaml文件而後apply的方式。
kubectl get pods -o wide
檢查擴容結果, 這裏使用了 -o wide
,能夠顯示更多信息
NAME READY STATUS RESTARTS AGE IP NODE
flaskapp-6c4fccdf99-9xsjl 1/1 Running 0 3m 10.1.0.23 docker-for-desktop
flaskapp-6c4fccdf99-xcmwb 1/1 Running 0 1h 10.1.0.21 docker-for-desktop
flaskapp-6c4fccdf99-zp8mk 1/1 Running 0 3m 10.1.0.24 docker-for-desktop
nginx-85fb469b96-lr982 1/1 Running 0 1h 10.1.0.19 docker-for-desktop
redis-5b44bb8d97-wwmll 1/1 Running 0 1h 10.1.0.22 docker-for-desktop
複製代碼
屢次訪問服務:
➜ docker2istio curl http://127.0.0.1:30457
Hello World by 10.1.0.21 from 192.168.65.3 ! 該頁面已被訪問 2 次。
➜ docker2istio curl http://127.0.0.1:30457
Hello World by 10.1.0.23 from 192.168.65.3 ! 該頁面已被訪問 3 次。
➜ docker2istio curl http://127.0.0.1:30457
Hello World by 10.1.0.24 from 192.168.65.3 ! 該頁面已被訪問 4 次。
➜ docker2istio curl http://127.0.0.1:30457
複製代碼
結合前面看到的flaskapp的IP,能夠比較清晰的看到請求會自動負載到不一樣的Pod。
k8s下的容器清理也很是簡單, 使用 kubectl delete -f k8s
:
service "flaskapp" deleted
deployment.extensions "flaskapp" deleted
configmap "nginx-config" deleted
service "nginx" deleted
deployment.extensions "nginx" deleted
service "redis" deleted
deployment.extensions "redis" deleted
複製代碼
實際上,k8s集羣在多集羣狀況下,會自動將Pod調度到合適的節點,這就是容器編排的概念。這種能力,主要有2個方式。
咱們的k8s演示集羣節點狀況以下:
[tyhall51@192-168-10-21 k8s]$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
192-168-10-14 Ready <none> 13d v1.14.0
192-168-10-18 Ready <none> 130d v1.14.0
192-168-10-21 Ready master 131d v1.14.0
複製代碼
部署示例應用到k8s演示集羣:
[tyhall51@192-168-10-21 docker2istio]$ kubectl apply -f k8s -n docker2istio
service/flaskapp created
deployment.extensions/flaskapp created
configmap/nginx-config created
service/nginx created
deployment.extensions/nginx created
service/redis created
deployment.extensions/redis created
複製代碼
!!!注意 爲了避免和別的服務發生名稱衝突,這裏部署時候使用了
-n docker2istio
參數,建立了一個獨立的名稱空間。名稱空間可使用kubectl create namespace docker2istio
命令建立。
查看名稱空間下的服務:
[tyhall51@192-168-10-21 docker2istio]$ kubectl get service -n docker2istio
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
flaskapp ClusterIP 10.101.127.107 <none> 5000/TCP 47s
nginx NodePort 10.103.147.187 <none> 80:30387/TCP 46s
redis ClusterIP 10.106.162.13 <none> 6379/TCP 46s
複製代碼
查看名稱空間下的pod:
[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
flaskapp-589c4cdf86-sftr9 1/1 Running 0 81s 10.244.2.30 192-168-10-14 <none> <none>
nginx-55b87f44ff-b4x88 1/1 Running 0 81s 10.244.2.31 192-168-10-14 <none> <none>
redis-7fc7fc64fb-2nzjq 1/1 Running 0 81s 10.244.1.195 192-168-10-18 <none> <none>
複製代碼
參考前文,修改副本數量參數replicas,對flaskapp進行擴容:
[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
flaskapp-589c4cdf86-8jzwx 1/1 Running 0 4s 10.244.1.197 192-168-10-18 <none> <none>
flaskapp-589c4cdf86-sftr9 1/1 Running 0 3m10s 10.244.2.30 192-168-10-14 <none> <none>
flaskapp-589c4cdf86-tz98x 1/1 Running 0 4s 10.244.1.196 192-168-10-18 <none> <none>
nginx-55b87f44ff-b4x88 1/1 Running 0 3m10s 10.244.2.31 192-168-10-14 <none> <none>
redis-7fc7fc64fb-2nzjq 1/1 Running 0 3m10s 10.244.1.195 192-168-10-18 <none> <none>
複製代碼
這裏就能夠看到,擴容完成後,flaskapp的3個pod會自動調度到192-168-10-18和192-168-10-182個業務節點。
192-168-10-14節點的磁盤使用的是高速ssd,io性能會更好一些,咱們但願redis可以調度到該節點。
首先,給192-168-10-14節點打上storage=ssd
的標籤:
[tyhall51@192-168-10-21 docker2istio]$ kubectl label nodes 192-168-10-14 storage=ssd
node/192-168-10-14 labeled
複製代碼
檢查標籤是否正常標記:
[tyhall51@192-168-10-21 docker2istio]$ kubectl get nodes --show-labels | grep ssd
192-168-10-14 Ready <none> 13d v1.14.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=192-168-10-14,kubernetes.io/os=linux,storage=ssd
複製代碼
而後修改k8s/redis.yaml
,增長nodeSelector
數值,其值爲storage: ssd
, 修改完成的deployment以下:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
template:
metadata:
labels:
name: redis
spec:
containers:
- image: redis:4-alpine3.8
name: redis
ports:
- containerPort: 6379
nodeSelector:
storage: ssd
複製代碼
使用kubectl apply -f k8s/redis.yaml -n docker2istio
應用修改。查看docker2istio的pod分佈狀況:
[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
flaskapp-589c4cdf86-8jzwx 1/1 Running 0 11m 10.244.1.197 192-168-10-18 <none> <none>
flaskapp-589c4cdf86-sftr9 1/1 Running 0 14m 10.244.2.30 192-168-10-14 <none> <none>
flaskapp-589c4cdf86-tz98x 1/1 Running 0 11m 10.244.1.196 192-168-10-18 <none> <none>
nginx-55b87f44ff-b4x88 1/1 Running 0 14m 10.244.2.31 192-168-10-14 <none> <none>
redis-66f66896b6-7666t 1/1 Running 0 4s 10.244.2.35 192-168-10-14 <none> <none>
複製代碼
可見redis節點從新被調度到192-168-10-14節點,表現出了節點標籤的親和力。
在k8s演示集羣中192-168-10-21是master節點,默認不會調度業務pod,這種能力是採用節點污點實現的。 取消192-168-10-21調度污點:
kubectl taint node 192-168-10-21 node-role.kubernetes.io/master:NoSchedule-
複製代碼
而後擴容flaskapp的副本數到6個,觀察pod分佈狀況:
[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
flaskapp-589c4cdf86-8jzwx 1/1 Running 0 20m 10.244.1.197 192-168-10-18 <none> <none>
flaskapp-589c4cdf86-92rm5 1/1 Running 0 5s 10.244.2.36 192-168-10-14 <none> <none>
flaskapp-589c4cdf86-bfhs8 1/1 Running 0 5s 10.244.0.26 192-168-10-21 <none> <none>
flaskapp-589c4cdf86-sftr9 1/1 Running 0 23m 10.244.2.30 192-168-10-14 <none> <none>
flaskapp-589c4cdf86-srv25 1/1 Running 0 5s 10.244.0.25 192-168-10-21 <none> <none>
flaskapp-589c4cdf86-tz98x 1/1 Running 0 20m 10.244.1.196 192-168-10-18 <none> <none>
nginx-55b87f44ff-b4x88 1/1 Running 0 23m 10.244.2.31 192-168-10-14 <none> <none>
redis-66f66896b6-7666t 1/1 Running 0 9m30s 10.244.2.35 192-168-10-14 <none> <none>
複製代碼
這裏能夠看到,有2個pod被調到到192-168-10-21節點了。
從新設置污點:
[tyhall51@192-168-10-21 docker2istio]$ kubectl taint node 192-168-10-21 node-role.kubernetes.io/master=:NoSchedule
node/192-168-10-21 tainted
複製代碼
刪除在192-168-10-21上的2個pod:
kubectl delete pod/flaskapp-589c4cdf86-bfhs8 -n docker2istio
kubectl delete pod/flaskapp-589c4cdf86-srv25 -n docker2istio
複製代碼
觀察pod分佈狀況:
[tyhall51@192-168-10-21 docker2istio]$ kubectl get pods -o wide -n docker2istio
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
flaskapp-589c4cdf86-8jzwx 1/1 Running 0 25m 10.244.1.197 192-168-10-18 <none> <none>
flaskapp-589c4cdf86-92rm5 1/1 Running 0 4m40s 10.244.2.36 192-168-10-14 <none> <none>
flaskapp-589c4cdf86-fp5w4 1/1 Running 0 73s 10.244.2.37 192-168-10-14 <none> <none>
flaskapp-589c4cdf86-lv2ch 1/1 Running 0 73s 10.244.1.199 192-168-10-18 <none> <none>
flaskapp-589c4cdf86-p9kb6 1/1 Running 0 7s 10.244.2.38 192-168-10-14 <none> <none>
flaskapp-589c4cdf86-sftr9 1/1 Running 0 28m 10.244.2.30 192-168-10-14 <none> <none>
nginx-55b87f44ff-b4x88 1/1 Running 0 28m 10.244.2.31 192-168-10-14 <none> <none>
redis-66f66896b6-7666t 1/1 Running 0 14m 10.244.2.35 192-168-10-14 <none> <none>
複製代碼
能夠看到刪除後的pod,在192-168-10-18和192-168-10-14這2個業務節點上重建了。
k8s相對於compose:
etcd 是一個分佈式鍵值對存儲,設計用來可靠而快速的保存關鍵數據並提供訪問。經過分佈式鎖,leader選舉和寫屏障(write barriers)來實現可靠的分佈式協做。etcd集羣是爲高可用,持久性數據存儲和檢索而準備。k8s中使用etcd做爲集羣信息存儲。
EFK (Elasticsearch + Fluentd + Kibana) 是kubernetes官方推薦的日誌收集方案
Helm helps you manage Kubernetes applications — Helm Charts help you define, install, and upgrade even the most complex Kubernetes application.
File, Block, and Object Storage Services for your Cloud-Native Environments
...
...