Kubernetes 應用版本號
在 Kubernetes 里,版本更新使用的不是 API 對象,而是兩個命令:kubectl apply 和 kubectl rollout,當然它們也要搭配部署應用所需要的 Deployment、DaemonSet 等 YAML 文件。
在 Kubernetes 里應用都是以 Pod 的形式運行的,而 Pod 通常又會被 Deployment 等對象來管理,所以應用的“版本更新”實際上更新的是整個 Pod。
Pod 是由 YAML 描述文件來確定的,更準確地說,是 Deployment 等對象里的字段 template。
所以 Kubernetes 就使用了“摘要”功能,用摘要算法計算 template 的 Hash 值作為“版本號”。
#獲取ngx的pod
kubectl get pod
#刪除其中一個
kubectl delete pod ngx-dep-6796688696-9zwxh
#再獲取ngx的pod,查看變化
kubectl get pod
可以看到,Pod 名字里的那串隨機數“6796……”是沒有變化的,變化的是數字后面的pod編號的隨機字符。中間的隨機數字就是 Pod 模板的 Hash 值,也就是 Pod 的“版本號”。
如果變動了 Pod YAML 描述,比如把鏡像改成 nginx:stable-alpine會生成一個新的應用版本,kubectl apply 后就會重新創建 Pod。
命令操作
#刪除pod
kubectl delete -f nginx-deploy.yml
#查看刪除結果
kubectl get pod
# 不改yaml,再次生成pod
kubectl apply -f nginx-deploy.yml
#查看生成pod的版本號是否改變
kubectl get pod
#刪除pod
kubectl delete -f nginx-deploy.yml
#查看刪除結果
kubectl get pod
#編輯pod yaml,修改版本號
vim nginx-deploy.yml
# 重新生成pod
kubectl apply -f nginx-deploy.yml
#查看生成pod的版本號是否改變
kubectl get pod
更改后的yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: ngx-depspec:replicas: 2selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-depspec:volumes:- name: ngx-conf-volconfigMap:name: ngx-confcontainers:- image: nginx:stable-alpinename: nginxports:- containerPort: 80volumeMounts:- mountPath: /etc/nginx/conf.dname: ngx-conf-vol
~
不改變yaml,重新生成的pod的版本號還是6796688696
更改了yaml后,生成的pod的版本號就變成了574d5f9d4d
Kubernetes 實現應用更新
修改 ConfigMap,讓它輸出 Nginx 的版本號,方便 curl 查看版本:
nginx-config-cm.yml
apiVersion: v1
kind: ConfigMap
metadata:name: ngx-confdata:default.conf: |server {listen 80;location / {default_type text/plain;return 200'ver : $nginx_version\nsrv : $server_addr:$server_port\nhost: $hostname\n';}}
執行命令
# 編輯configMap內容
vim nginx-config-cm.yml
# 更新 ConfigMap
kubectl apply -f nginx-config-cm.yml
創建 Pod 鏡像,明確地指定版本號是 1.21-alpine,實例數設置為 4 個
nginx-deploy-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: ngx-depspec:replicas: 4 selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-depspec:volumes:- name: ngx-conf-volconfigMap:name: ngx-confcontainers:- image: nginx:1.21-alpinename: nginxports:- containerPort: 80volumeMounts:- mountPath: /etc/nginx/conf.dname: ngx-conf-vol
執行命令
# 刪除現有的nginx pod
kubectl delete -f nginx-deploy.yml
# 創建新版本的nginx yml
vim nginx-deploy-v1.yml
# 生成4個pod
kubectl apply -f nginx-deploy-v1.yml
# 查看生成pod
kubectl get pod
本地端口轉發到 Kubernetes 集群中的服務
# 查看service服務
kubectl get svc
# 綁定到svc service 轉發請求來查看狀態
kubectl port-forward svc/ngx-svc 8080:80 &
# 測試轉發
curl 127.1:8080
- kubectl port-forward: 這個命令將本地端口轉發到 Kubernetes 集群中的某個資源(如 Pod 或 Service)。(只會將流量發送到一個特定的端點,而不是通過服務的負載均衡機制)
- svc/ngx-svc: 指定要轉發的目標資源,這里是名為 ngx-svc 的 Service。
- 8080:80: 將本地的 8080 端口轉發到 ngx-svc 服務的 80 端口。
- &: 將該命令放入后臺運行,這樣可以繼續在終端中執行其他命令。
鏡像升級到 nginx:1.22-alpine
為了能夠觀察到應用更新的過程,我們還需要添加一個字段 minReadySeconds,讓 Kubernetes 在更新過程中等待一點時間,確認 Pod 沒問題才繼續其余 Pod 的創建工作。
minReadySeconds 這個字段不屬于 Pod 模板,所以它不會影響 Pod 版本
nginx-deploy-v2.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: ngx-depspec:minReadySeconds: 15 # 確認Pod就緒的等待時間replicas: 4selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-depspec:volumes:- name: ngx-conf-volconfigMap:name: ngx-confcontainers:- image: nginx:1.22-alpinename: nginxports:- containerPort: 80volumeMounts:- mountPath: /etc/nginx/conf.dname: ngx-conf-vol
~
執行命令
# 創建文件內容,把上面內容copy進來
vim nginx-deploy-v2.yml
# 更新成的新的pod
kubectl apply -f nginx-deploy-v2.yml
# 查看滾動更新過程
kubectl rollout status deployment ngx-dep
# 綁定到svc service 轉發請求來查看狀態
kubectl port-forward svc/ngx-svc 8080:80 &
# 測試轉發
curl 127.1:8080
# 查看滾動詳情信息
kubectl describe deploy ngx-dep
- 一開始的時候 V1 Pod(即 ngx-dep-54b865d75)的數量是 4;
- 當“滾動更新”開始的時候,Kubernetes 創建 1 個 V2 Pod(即 ngx-dep-d575d5776),并且把 V1 Pod 數量減少到 3;
- 接著再增加 V2 Pod 的數量到 2,同時 V1 Pod 的數量變成了 1;
- 最后 V2 Pod 的數量達到預期值 4,V1 Pod 的數量變成了 0,整個更新過程就結束了。
滾動更新”就是由 Deployment 控制的兩個同步進行的“應用伸縮”操作,老版本縮容到 0,同時新版本擴容到指定值,是一個“此消彼長”的過程。
Kubernetes管理應用更新
如果更新過程中發生了錯誤或者更新后發現有 Bug,可以隨時使用 kubectl rollout pause 來暫停更新,檢查、修改 Pod,或者測試驗證,如果確認沒問題,再用 kubectl rollout resume 來繼續更新。
注意:它們只支持 Deployment,不能用在 DaemonSet、StatefulSet 上( 1.24 之后支持了 StatefulSet 的滾動更新)
Kubernetes應用版本回退
查看更新歷史使用的命令是 kubectl rollout history
#查看有哪些版本
kubectl rollout history deployment ngx-dep
#查看每個版本的詳細信息
kubectl rollout history deployment ngx-dep --revision=2
# 回退到上一個版本
kubectl rollout undo deploy ngx-dep
# 回退到指定版本(--to-revision=1不能有空格)
kubectl rollout undo deploy ngx-dep --to-revision=1
kubectl rollout undo 的操作過程其實和 kubectl apply 是一樣的,執行的仍然是“滾動更新”,只不過使用的是舊版本 Pod 模板,把新版本 Pod 數量收縮到 0,同時把老版本 Pod 擴展到指定值。
Kubernetes 添加更新描述
在Deployment 的 metadata 里加上一個新的字段 annotations。annotations 字段的含義是“注解”“注釋”,形式上和 labels 一樣,都是 Key-Value,也都是給 API 對象附加一些額外的信息,但是用途上區別很大。
- annotations 添加的信息一般是給 Kubernetes 內部的各種對象使用的,有點像是“擴展屬性”;
- labels 主要面對的是 Kubernetes 外部的用戶,用來篩選、過濾對象的。
annotations 里的值可以任意寫,Kubernetes 會自動忽略不理解的 Key-Value,但要編寫更新說明就需要使用特定的字段 kubernetes.io/change-cause。
創建 2 個版本的 Nginx 應用,同時添加更新說明:
nginx-deploy-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: ngx-depannotations: kubernetes.io/change-cause: v1, ngx=1.21spec:replicas: 4 selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-depspec:volumes:- name: ngx-conf-volconfigMap:name: ngx-confcontainers:- image: nginx:1.21-alpinename: nginxports:- containerPort: 80volumeMounts:- mountPath: /etc/nginx/conf.dname: ngx-conf-vol
nginx-deploy-v2.yml
deployment.apps/ngx-dep
REVISION CHANGE-CAUSE
3 v1, ngx=1.21
4 update to v2, ngx=1.22[root@iZbp12ghzy6koox6fqt0svZ ~]# cat nginx-deploy-v2.yml
apiVersion: apps/v1
kind: Deployment
metadata:name: ngx-depannotations: kubernetes.io/change-cause: update to v2, ngx=1.22spec:minReadySeconds: 15 # 確認Pod就緒的等待時間replicas: 4 selector:matchLabels:app: ngx-deptemplate:metadata:labels:app: ngx-depspec:volumes:- name: ngx-conf-volconfigMap:name: ngx-confcontainers:- image: nginx:1.22-alpinename: nginxports:- containerPort: 80volumeMounts:- mountPath: /etc/nginx/conf.dname: ngx-conf-vol
執行命令
vim nginx-deploy-v1.yml
kubectl apply -f nginx-deploy-v1.yml
vim nginx-deploy-v2.yml
kubectl apply -f nginx-deploy-v2.yml
#查看滾動更新
kubectl rollout status deployment ngx-dep
#查看一下更新歷史:
kubectl rollout history deployment ngx-dep