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