1.kubernetes调度基础 1.1replication controller和replicaset(了解即可) Replication Controller(复制控制器,RC)和 ReplicaSet(复制集,RS)是两种简单部署 Pod的方式。因为在生产环境中,主要使用更高级的 Deployment 等方式进行 Pod 的管理和部署,所以只需要简单了解即可。
1.1.1Replication Controller Replication Controller(简称 RC)可确保 Pod 副本数达到期望值,也就是 RC 定义的数量。换句话说,Replication Controller 可确保一个 Pod 或一组同类 Pod 总是可用。如果存在的 Pod 大于设定的值,则 Replication Controller 将终止额外的 Pod。如果太小,Replication Controller 将启动更多的 Pod 用于保证达到期望值。与手动创建 Pod 不同的是,用Replication Controller 维护的 Pod 在失败、删除或终止时会自动替换。因此即使应用程序只需要一个 Pod,也应该使用 Replication Controller 或其他方式管理。Replication Controller 类似于进程管理程序,但是 Replication Controller 不是监视单个节点上的各个进程,而是监视多个节点上的多个 Pod。
定义一个 Replication Controller 的示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apiVersion: v1 kind: ReplicationController metadata: name: nginx spec: replicas: 3 selector: app: nginx template: metadata: name: nginx labels: app: nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
5.1.2ReplicaSet ReplicaSet 是支持基于集合的标签选择器的下一代 Replication Controller,它主要用作Deployment 协调创建、删除和更新 Pod,和 Replication Controller 唯一的区别是,ReplicaSet 支持标签选择器。在实际应用中,虽然 ReplicaSet 可以单独使用,但是一般建议使用 Deployment 来自动管理 ReplicaSet,除非自定义的 Pod 不需要更新或有其他编排等。
定义一个 ReplicaSet 的示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 apiVersion: apps/v1 kind: ReplicaSet metadata: name: frontend labels: app: guestbook tier: frontend spec: replicas: 3 selector: matchLabels: tier: frontend template: metadata: labels: tier: frontend spec: containers: - name: php-redis image: gcr.io/google_samples/gb-frontend:v3
Replication Controller 和 ReplicaSet 的创建删除和 Pod 并无太大区别,Replication Controller目前几乎已经不在生产环境中使用,ReplicaSet 也很少单独被使用,都是使用更高级的资源Deployment、DaemonSet、StatefulSet 进行管理 Pod。
1.2 Deployment(无状态应用管理) 无状态的应用 是指应用程序在处理每个请求时,不依赖于以前的请求或状态信息。每个请求都是独立的,服务器不会存储任何关于客户端的会话信息。
有状态的应用 是指应用程序在处理请求时依赖于以前的请求或会话信息。服务器会记住客户端的状态信息,以便为后续请求提供正确的响应。
Deployment一般用于部署公司的无状态服务,这个也是最常用的控制器,因为企业内部现在都是以微服务为主,而微服务实现无状态化也是最佳实践,可以利用deployment的高级功能做到无缝迁移、自动扩容缩容、自动灾难恢复、一键回滚等功能。
常见的无状态应用:java、go、vue、php等业务容器
1.2.1创建deployment 创建一个deployment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine ports: - containerPort: 80
使用命令创建一个deployment的模板文件:
1 2 3 4 5 6 7 8 9 10 # 使用 kubectl create 命令创建 Deployment kubectl create deployment nginx-deployment --image=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine --replicas=3 -oyaml --dry-run=client >nginx-deployment.yaml # 使用 kubectl create deployment 命令来创建一个新的 Deployment 资源。 # nginx-deployment 是 要创建的Deployment 的名称。 # --image=nginx:1.14.2:指定使用的 nginx:1.14.2 镜像来运行容器。 # --replicas=3:创建 3 个 Pod 副本。 # -oyaml 以yaml格式显示 # --dry-run=client 不需要真正创建这个deployment # >nginx-deployment.yaml 将输出重定向到nginx-deployment.yaml文件里
创建这个deployment:
1 2 [root@k8s-master01 pra]# kubectl create -f nginx-deployment.yaml deployment.apps/nginx-deployment created
查看创建的deployment状态:
1 2 3 4 5 6 7 8 9 10 11 # 注意,如果指定了命名空间记得要使用 -n 指定命名空间,pod、rs和deploy都有命名空间隔离性 [root@k8s-master01 pra]# kubectl get deploy NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 3 3 20s # NAME列:表示deployment对象的名称,这里deployment的名字是nginx-deployment # READY列:表示当前deploy中当前就绪状态的pod数量/总pod数量, # UP-TO-DATE:这一列显示了当前正在运行的 Pod 中与最新版本的 Pod 一致的 Pod 的数量。在 Deployment 进行滚动更新时,这个数字会告诉你有多少 Pod 已经升级到了最新版本。 # AVAILABLE:这一列显示了可以使用的(可用的) Pod 的数量。它通常与 READY 的数字相同,除非有 Pod 因为某些原因(如资源限制、节点故障等)而无法接收流量。 # AGE:显示应用程序运行的时间。 综上所述,通过 kubectl get deploy 命令返回的结果可以快速了解到每个 Deployment 的基本状态信息,包括名称、就绪状态、更新状态以及创建时间。
查看rs和po的信息:
1 2 3 4 5 6 7 8 9 10 [root@k8s-master01 pra]# kubectl get rs NAME DESIRED CURRENT READY AGE cluster-test-66bb44bd88 1 1 1 18d nginx-deployment-66bb646879 3 3 3 2m38s [root@k8s-master01 pra]# kubectl get po -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES cluster-test-66bb44bd88-7kct4 1/1 Running 141 (23m ago) 18d 172.16.195.3 k8s-master03 <none> <none> nginx-deployment-66bb646879-2h2xw 1/1 Running 0 3m39s 172.16.195.5 k8s-master03 <none> <none> nginx-deployment-66bb646879-gscpf 1/1 Running 0 3m38s 172.16.85.226 k8s-node01 <none> <none> nginx-deployment-66bb646879-qsjf4 1/1 Running 0 3m39s 172.16.122.135 k8s-master02 <none> <none>
查看此deployment创建的pod的标签:
1 2 3 4 5 6 # 查看此 Deployment 创建的Pod,可以看到Pod的hash 值 66bb646879 和上述 Deployment对应的ReplicaSet的hash 值一致: [root@k8s-master01 pra]# kubectl get po --show-labels NAME READY STATUS RESTARTS AGE LABELS nginx-deployment-66bb646879-2h2xw 1/1 Running 0 31m app=nginx,pod-template-hash=66bb646879 nginx-deployment-66bb646879-gscpf 1/1 Running 0 31m app=nginx,pod-template-hash=66bb646879 nginx-deployment-66bb646879-qsjf4 1/1 Running 0 31m app=nginx,pod-template-hash=66bb646879
1.2.2更新deployment 注意:当且仅当deployment的pod模板(即.spec.)更改时,才会触发deployment的更新,例如更改内存、cpu或者容器的image,但是不要更改template.metadata.lables中的标签。
可以使用以下方法更新deploy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 # 方法一:使用set 命令 # 假如更新上述创建的deploy中 Nginx Pod 的 image 使用 nginx:latest,并使用--record 记录当前更改的参数,后期回滚时可以查看到对应的信息: # kubectl 是 Kubernetes 的命令行工具,set image 用于更新 Deployment、DaemonSet 或 StatefulSet 中的容器镜像。 # Deployment 指定要更新的资源类型 # nginx-deployment 指定更新的deployment的名称 # nginx 表示更新 Deployment 中名为 nginx 的容器 # registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest 指定镜像 # --record 用于记录更新,方便查看历史操作 ,也方便后期回滚 [root@k8s-master01 pra]# kubectl set image deployment nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record # 查看deployment的更新状态 [root@k8s-master01 pra]# kubectl rollout status deployment/nginx-deployment deployment "nginx-deployment" successfully rolled out # 查看 Deployment 详细信息: [root@k8s-master01 pra]# kubectl describe deployment nginx-deployment 返回信息中 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 4m5s deployment-controller Scaled up replica set nginx-deployment-85c7b546bd to 1 Normal ScalingReplicaSet 3m52s deployment-controller Scaled down replica set nginx-deployment-66bb646879 to 2 from 3 Normal ScalingReplicaSet 3m52s deployment-controller Scaled up replica set nginx-deployment-85c7b546bd to 2 from 1 Normal ScalingReplicaSet 3m39s deployment-controller Scaled down replica set nginx-deployment-66bb646879 to 1 from 2 Normal ScalingReplicaSet 3m39s deployment-controller Scaled up replica set nginx-deployment-85c7b546bd to 3 from 2 Normal ScalingReplicaSet 3m25s deployment-controller Scaled down replica set nginx-deployment-66bb646879 to 0 from 1 # 翻译: 正常 ScalingReplicaSet 4m5s 部署控制器 将副本集 nginx-deployment-85c7b546bd 扩大到 1 正常 ScalingReplicaSet 3m52s 部署控制器 将副本集 nginx-deployment-66bb646879 从 3 缩小到 2 正常 ScalingReplicaSet 3m52s 部署控制器 将副本集 nginx-deployment-85c7b546bd 从 1 扩大到 2 正常 ScalingReplicaSet 3m39s 部署控制器 将副本集 nginx-deployment-66bb646879 从 2 缩小到 1 正常 ScalingReplicaSet 3m39s 部署控制器 将副本集 nginx-deployment-85c7b546bd 从 2 扩大到 3 正常 ScalingReplicaSet 3m25s部署控制器将副本集 nginx-deployment-66bb646879 从 1 缩减为 0 pod的更新过程:会创建一个新的rs,将新的rs副本数扩大为1,将旧的rs副本数从3缩小到2 再将新的rs副本数从1扩大到2,将旧的rs副本数从2缩小到1 再将新的rs副本数从2扩大到3,将旧的rs副本数从1缩小到0 --------------------------------------------------------------------------------------- # 方法二:使用edit命令 # edit用于编辑资源的命令 # deploy指定资源的类型 # nginx-deployment 指定要编辑的deployment的名字,这里名字是nginx-deployment的deployment # 该命令跟vim操作一样,编辑完可以使用:wq保存退出,也可以使用shift +zz保存退出 [root@k8s-master01 pra]# kubectl edit deploy nginx-deployment # 方法三:编辑deploy的yaml文件,重新apply,但是需要注意的是正在运行的deploy和yaml文件一致
可以看出更新过程为新旧交替更新,首先新建一个 Pod,当 Pod 状态为 Running 时,删除一个旧的 Pod,同时再创建一个新的 Pod。当触发一个更新后,会有新的 ReplicaSet 产生,旧的ReplicaSet 会被保存,查看此时ReplicaSet,可以从 AGE 或 READY 看出来新旧 ReplicaSet:
1 2 3 4 5 [root@k8s-master01 pra]# kubectl get rs NAME DESIRED CURRENT READY AGE cluster-test-66bb44bd88 1 1 1 18d nginx-deployment-66bb646879 0 0 0 139m nginx-deployment-85c7b546bd 3 3 3 23m
在describe中可以看出,第一次创建时,它创建了一个名为nginx-deployment-66bb646879 的ReplicaSet,并将其扩展为3个副本。更新部署时,它创建了一个新的ReplicaSet(nginx-deployment-85c7b546bd ),并将其副本数扩展为 1,然后将旧的 ReplicaSet(nginx-deployment-66bb646879)副本从3 缩小为 2,以此类推完成更新。
正常 ScalingReplicaSet 4m5s 部署控制器 将副本集 nginx-deployment-85c7b546bd 扩大到 1 正常 ScalingReplicaSet 3m52s 部署控制器 将副本集 nginx-deployment-66bb646879 从 3 缩小到 2 正常 ScalingReplicaSet 3m52s 部署控制器 将副本集 nginx-deployment-85c7b546bd 从 1 扩大到 2 正常 ScalingReplicaSet 3m39s 部署控制器 将副本集 nginx-deployment-66bb646879 从 2 缩小到 1 正常 ScalingReplicaSet 3m39s 部署控制器 将副本集 nginx-deployment-85c7b546bd 从 2 扩大到 3 正常 ScalingReplicaSet 3m25s部署控制器将副本集 nginx-deployment-66bb646879 从 1 缩减为 0
1.2.3回滚deployment 当更新了版本不稳定或配置不合理时,可以对其进行回滚操作,假设我们又进行了几次更新(此处以更新镜像版本触发更新,更改配置效果类似):
假设我们进行了更新操作:
1 2 3 4 5 6 7 8 9 # 假设更新了镜像,第一次将镜像版本更新为nginx:1.10.0 [root@k8s-master01 ~]# kubectl set image deployment nginx-deployment nginx=nginx:1.10.0 --record Flag --record has been deprecated, --record will be removed in the future deployment.apps/nginx-deployment image updated # 第二次将镜像版本更新为nginx:1.10.1 [root@k8s-master01 ~]# kubectl set image deployment nginx-deployment nginx=nginx:1.10.1 --record Flag --record has been deprecated, --record will be removed in the future deployment.apps/nginx-deployment image updated
kubectl rollout history
命令用于查看 Kubernetes 中资源的历史版本记录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 案例:查看deployment资源中nginx-deployment的更新历史 [root@k8s-master01 ~]# kubectl get deployment NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 3/3 1 3 14h # 查看更新记录 # rollout 指令提供查看、暂停、继续、撤销(回滚)和回滚资源更新的功能。 [root@k8s-master01 ~]# kubectl rollout history deployment nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 2 kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record=true 3 kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record=true 4 kubectl set image deployment nginx-deployment nginx=nginx:1.10.0 --record=true 5 kubectl set image deployment nginx-deployment nginx=nginx:1.10.1 --record=true
查看 Deployment 某次更新的详细信息,使用–revision 指定某次更新版本号:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 例如查看第4次更新的详细信息 [root@k8s-master01 ~]# kubectl rollout history deployment nginx-deployment --revision=4 deployment.apps/nginx-deployment with revision #4 Pod Template: Labels: app=nginx pod-template-hash=d4c4895f8 Annotations: kubernetes.io/change-cause: kubectl set image deployment nginx-deployment nginx=nginx:1.10.0 --record=true Containers: nginx: Image: nginx:1.10.0- Port: 80/TCP Host Port: 0/TCP Environment: <none> Mounts: <none> Volumes: <none>
回滚到上一个版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 使用下面命令看到当前nginx-deployment使用的镜像是官方的nginx:1.10.1 [root@k8s-master01 ~]# kubectl get deployment nginx-deployment -oyaml|grep image kubernetes.io/change-cause: kubectl set image deployment nginx-deployment nginx=nginx:1.10.1 - image: nginx:1.10.1 imagePullPolicy: IfNotPresent # kubectl rollout history 查看版本更新记录 [root@k8s-master01 ~]# kubectl rollout history deployment nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 2 kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record=true 3 kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record=true 4 kubectl set image deployment nginx-deployment nginx=nginx:1.10.0 --record=true 5 kubectl set image deployment nginx-deployment nginx=nginx:1.10.1 --record=true # 使用kubectl rollout undo指定来回滚到上一个版本,上一个版本用的镜像是nginx:1.10.0 # undo表示撤销、回滚 # deployment表示资源的类型 # nginx-deployment表示资源的名称 [root@k8s-master01 ~]# kubectl rollout undo deployment nginx-deployment deployment.apps/nginx-deployment rolled back
回滚到指定版本:(使用参数: –to-revision)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 回滚到指定版本使用 --to-revision=2,例如先查看更新历史,在通过回滚操作,回滚到2版本 [root@k8s-master01 ~]# kubectl rollout history deployment nginx-deployment deployment.apps/nginx-deployment REVISION CHANGE-CAUSE 2 kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record=true 3 kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record=true 4 kubectl set image deployment nginx-deployment nginx=nginx:1.10.0 --record=true 5 kubectl set image deployment nginx-deployment nginx=nginx:1.10.1 --record=true # 回滚到3,通过上述更新历史可以看出2版本使用的镜像是nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest [root@k8s-master01 ~]# kubectl rollout undo deployment nginx-deployment --to-revision=3 deployment.apps/nginx-deployment rolled back # 查看运行的资源使用的镜像是否是nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest [root@k8s-master01 ~]# kubectl get deploy nginx-deployment -oyaml|grep image kubernetes.io/change-cause: kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest imagePullPolicy: IfNotPresent
1.2.4扩容deployment 当公司访问量变大,或者有预期内的活动时,三个 Pod 可能已无法支撑业务时,可以提前对其进行扩展。
扩缩容有两种方式:方式一使用edit直接编辑副本数;方式二使用scal命令
方式一:edit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # 这里使用edit演示缩容 # 此时nginx-deployment管理了三个pod [root@k8s-master01 ~]# kubectl get po --show-labels|grep app=nginx nginx-deployment-85c7b546bd-4zk96 1/1 Running 0 18m app=nginx,pod-template-hash=85c7b546bd nginx-deployment-85c7b546bd-7xxls 1/1 Running 0 18m app=nginx,pod-template-hash=85c7b546bd nginx-deployment-85c7b546bd-m78f4 1/1 Running 0 18m app=nginx,pod-template-hash=85c7b546bd # 先缩容,缩减到1个pod [root@k8s-master01 ~]# kubectl edit deploy nginx-deployment # 找到replicas参数将值设为1 replicas: 1 # 在查看pod的数量,此时就剩下1个pod [root@k8s-master01 ~]# kubectl get po --show-labels|grep app=nginx nginx-deployment-85c7b546bd-4zk96 1/1 Running 0 21m app=nginx,pod-template-hash=85c7b546bd # 注意扩容和缩容不会记录到版本更新记录中,因为replicas的修改不会触发更新,哪些会触发更新见5.2.2
方式二:使用 kubectl scale 动态调整 Pod 的副本数,比如增加 Pod 为 5 个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # 使用命令对资源惊醒扩容 # scale是扩容缩容的指令 # deployment 要操作的资源类型,这里是deployment # nginx-deployment是deployment的名字 # --replicas=5指定副本的数量 # 意思是将名字是nginx-deployment的deployment的副本数量设置为5个 [root@k8s-master01 ~]# kubectl scale deployment nginx-deployment --replicas=5 deployment.apps/nginx-deployment scaled # 此时查看pod的数量已经扩增到5个 [root@k8s-master01 ~]# kubectl get po NAME READY STATUS RESTARTS AGE cluster-test-66bb44bd88-7kct4 1/1 Running 148 (26m ago) 18d nginx-deployment-85c7b546bd-2m2pz 1/1 Running 0 3s nginx-deployment-85c7b546bd-4zk96 1/1 Running 0 43m nginx-deployment-85c7b546bd-8bmf6 1/1 Running 0 3s nginx-deployment-85c7b546bd-952gd 1/1 Running 0 3s nginx-deployment-85c7b546bd-gqvfq 0/1 ContainerCreating 0 3s
注意:无状态的资源可以缩容,但是有状态的服务不要随便缩容,会出现问题(例如statefulset)
1.2.5暂停和恢复deployment更新 上述演示的均为更改某一处的配置,更改后立即触发更新,大多数情况下可能需要针对一个资源文件更改多处地方,而并不需要多次触发更新,此时可以使用 Deployment 暂停功能,临时禁用更新操作,对 Deployment 进行多次修改后在进行更新。
流程就是先对资源进行暂停,在对资源进行编辑,编辑完成在执行恢复指令
①使用 kubectl rollout pause 命令即可暂停 Deployment 更新:
1 2 3 # 暂停名为 nginx-deployment 的 Deployment 资源的更新 [root@k8s-master01 ~]# kubectl rollout pause deployment nginx-deployment deployment.apps/nginx-deployment paused
②然后对 Deployment 进行相关更新操作,比如先更新镜像版本为nginx:1.19.0,然后对其资源进行限制(如果使用的是 kubectl edit 命令,可以直接进行多次修改,无需暂停更新,kubectlset 命令一般会集成在CICD 流水线中):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 修改镜像的版本 [root@k8s-master01 ~]# kubectl set image deploy nginx-deployment nginx=nginx:1.19.0 deployment.apps/nginx-deployment image updated # 再次修改,增加内存和cpu的配置 # kubectl set resources 命令用于设置 Kubernetes 中资源的请求和限制。 # deploy:资源类型的缩写,指 Deployment # nginx-deployment指定要设置资源的具体 Deployment 资源名称是nginx-deployment # -c nginx指定在 nginx-deployment 中的容器名字是nginx,要为那个容器配置。 # --limits=cpu=200m,memory=512Mi:为容器设置 CPU 和内存的限制。 # cpu=200m:设置 CPU 限制为 200 毫核(0.2 个 CPU 核心)。memory=512Mi:设置内存限制为 512 MiB(兆字节)。 kubectl set resources deploy nginx-deployment -c nginx --limits=cpu=200m,memory=512Mi # 可以用kubectl describe deploy指令查看deploy的状态Progressing # 注意 Progressing 条目,它应该显示 DeploymentPaused 状态。 [root@k8s-master01 ~]# kubectl describe deploy nginx-deployment |grep Progressing Progressing Unknown DeploymentPaused # kubectl get deployments也可以看到nginx-deployment的UP-TO-DATE为0,也就是说没有达到期望的pod,恢复后这里会变成5 [root@k8s-master01 ~]# kubectl get deployments.apps NAME READY UP-TO-DATE AVAILABLE AGE cluster-test 1/1 1 1 19d nginx-deployment 5/5 0 5 18h
③恢复更新:进行完最后一处配置更改后,使用 kubectl rollout resume 恢复 Deployment 更新:
1 2 3 #使用kubectl rollout resume指令恢复更新 [root@k8s-master01 ~]# kubectl rollout resume deployment nginx-deployment deployment.apps/nginx-deployment resumed
可以查看到恢复更新的 Deployment 创建了一个新的 RS(ReplicaSet 缩写):nginx-deployment-55dfd6f8b7
1 2 3 4 [root@k8s-master01 ~]# kubectl get rs NAME DESIRED CURRENT READY AGE cluster-test-66bb44bd88 1 1 1 19d nginx-deployment-55dfd6f8b7 3 3 0 2m53s
可以查看 Deployment 的 image(镜像)已经变为 nginx:1.19.0,资源限制也有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 [root@k8s-master01 ~]# kubectl get deploy nginx-deployment -oyaml apiVersion: apps/v1 kind: Deployment metadata: annotations: deployment.kubernetes.io/revision: "9" kubernetes.io/change-cause: kubectl set image deploy nginx-deployment nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest --record=true generation: 14 labels: app: nginx name: nginx-deployment spec: progressDeadlineSeconds: 600 replicas: 5 revisionHistoryLimit: 10 selector: matchLabels: app: nginx strategy: rollingUpdate: maxSurge: 25% maxUnavailable: 25% type: RollingUpdate template: metadata: creationTimestamp: null labels: app: nginx spec: containers: - image: nginx:1.19.0 imagePullPolicy: IfNotPresent name: nginx ports: - containerPort: 80 protocol: TCP resources: limits: cpu: 200m memory: 512Mi requests: cpu: 100m memory: 100Mi
1.2.6更新deployment的注意事项 历史版本清理策略:
在默认情况下,revision 保留 10 个旧的 ReplicaSet,其余的将在后台进行垃圾回收,可以在.spec.revisionHistoryLimit 设置保留 ReplicaSet 的个数。当设置为 0 时,不保留历史记录。
1 2 3 4 5 6 7 8 9 10 11 12 [root@k8s-master01 ~]# kubectl get deployments.apps nginx-deployment -oyaml|grep revisionHistoryLimit revisionHistoryLimit: 10 # 最多保留10个rs [root@k8s-master01 ~]# kubectl get rs NAME DESIRED CURRENT READY AGE cluster-test-66bb44bd88 1 1 1 19d nginx-deployment-55dfd6f8b7 3 3 0 38m nginx-deployment-66bb646879 0 0 0 19h nginx-deployment-85c7b546bd 4 4 4 17h nginx-deployment-9ffdcf9 0 0 0 5h25m nginx-deployment-d4c4895f8 0 0 0 5h26m
更新策略:
.spec.strategy.type==Recreate,表示重建,先删掉旧的Pod再创建新的Pod(一次性对所有pod进行删除和创建);
.spec.strategy.type==RollingUpdate,表示滚动更新,可以指定maxUnavailable和maxSurge:
配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 apiVersion: apps/v1 kind: Deployment metadata: name: my-deployment spec: replicas: 5 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 #在更新过程中允许的最大不可用 Pod 数量 maxSurge: 2 # 在更新过程中允许的最大超出期望数量的 Pod 数量。这里副本设置5,所以允许最多创建7个pod template: metadata: labels: app: my-app spec: containers: - name: my-container image: my-image:latest
.spec.strategy.rollingUpdate.maxUnavailable,指定在回滚更新时最大不可用的Pod数量,可选字段,默认为25%,可以设置为数字或百分比,如果maxSurge为0,则该值不能为0;
.spec.strategy.rollingUpdate.maxSurge可以超过期望值的最大Pod数,可选字段,默认为25%,可以设置成数字或百分比,如果maxUnavailable为0,则该值不能为0。来控制滚动更新过程;
注意:maxUnavailable=0
意思是不能有任何 Pod 被标记为不可用,maxSurge: 0表示没有任何额外的 Pod 被允许创建。会导致更新死锁以及服务中断的风险
Ready 策略:(保持默认值即可)
.spec.minReadySeconds 是可选参数,指定新创建的 Pod 应该在没有任何容器崩溃的情况下视为 Ready(就绪)状态的最小秒数,默认为 0,即一旦被创建就视为可用,通常和容器探针连用。
1.3StatefulSet(有状态应用管理) 1.3.1什么是StatefulSet 无状态的应用 是指应用程序在处理每个请求时,不依赖于以前的请求或状态信息。每个请求都是独立的,服务器不会存储任何关于客户端的会话信息。
有状态的应用 是指应用程序在处理请求时依赖于以前的请求或会话信息。服务器会记住客户端的状态信息,以便为后续请求提供正确的响应。
1.3.2StatefulSet部署过程
1.3.3headless service和普通service
在 Kubernetes 的环境中,”headless service” 和普通的 “service” 都是用来管理对一组 pod 的访问的,但它们在功能上有一些区别。
Service :
Kubernetes 中的 Service 是用来提供一个抽象层,允许外部访问 Pod 集群。Service 通过一个固定的 IP 地址和 DNS 名称对外提供服务,并且通过轮询等方式分配外部请求到后端的多个 Pod。
Service 通常有一个虚拟的 IP 地址(ClusterIP),请求首先到达这个 IP 地址,然后再由 Service 转发到后端的 Pod。
Headless Service :
Headless Service 在 Kubernetes 中用于当你不需要 Service 提供负载均衡时。设置 headless service 时,你可以在 Service 的定义中指定 clusterIP: None
,这样 Service 就不会有虚拟 IP。
Headless Service 的主要用途是允许直接访问 Pod,通常用于需要 Pod 稳定网络标识的应用,比如分布式数据库。DNS 查询会直接返回后端 Pod 的 IP 地址列表,而不是单个 Service IP。
如何定义这两种service:
1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: v1 kind: Service metadata: name: my-headless-service spec: clusterIP: None # 指定为 None 使得这个 Service 成为 Headless;不配置clusterIP选项默认是普通service selector: app: my-app ports: - protocol: TCP port: 80 targetPort: 9376
1.3.4定义一个 StatefulSet 资源文件 定义一个简单的 StatefulSet 的示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 apiVersion: v1 kind: Service #定义资源的类型 metadata: name: nginx #这里定义的是service的名字 labels: app: nginx #给service定义的标签 spec: ports: - port: 80 #定义service的端口,客户端访问service时使用的端口 name: web #端口的名称,方便管理和引用端口 clusterIP: None #None表示这是一个headless service selector: #选择器,选择带有app=nginx标签的pod进行管理 app: nginx --- apiVersion: apps/v1 kind: StatefulSet #定义资源的类型 metadata: #定义资源的元数据 name: web #StatefulSet 的名称 spec: selector: #标签选择器 matchLabels: #匹配标签 app: nginx # 必须匹配 .spec.template.metadata.labels,选择带有 app: nginx标签的pod serviceName: "nginx" #关联的 Headless Service 名称,也就是定义service中metadata.name的值 replicas: 3 # 默认值是 1,期望pod的副本数量 minReadySeconds: 10 # 默认值是 0 template: metadata: labels: #标签 app: nginx # 必须匹配 .spec.selector.matchLabels,给pod定义打上app:nginx的标签 spec: terminationGracePeriodSeconds: 10 containers: - name: nginx #容器的名称 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine ports: - containerPort: 80 #容器内部监听的端口 name: web #端口的名称,方便引用和管理端口
kind: Service定义了一个名字为Nginx的Headless Service,创建的Service格式为nginx-0.nginx.default.svc.cluster.local,其他的类似,因为没有指定Namespace(命名空间),所以默认部署在default;
kind: StatefulSet定义了一个名字为web的StatefulSet,replicas表示部署Pod的副本数,本实例为2。
在 StatefulSet 中 必 须 设 置 Pod 选择器( .spec.selector ) 用 来 匹 配 其 标 签(.spec.template.metadata.labels)。在 1.8 版本之前,如果未配置该字段(.spec.selector),将被设置为默认值,在 1.8 版本之后,如果未指定匹配 Pod Selector,则会导致StatefulSet 创建错误。
当 StatefulSet 控制器创建 Pod 时,它会添加一个标签 statefulset.kubernetes.io/pod-name,该标签的值为 Pod 的名称,用于匹配 Service。
内部pod访问方式:pod名字.svc名字.命名空间
1.3.5创建StatefulSet 利用5.3.2的yaml文件内容创建StatefulSet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 [root@k8s-master01 pra]# kubectl create -f statefulset.yaml service/nginx created statefulset.apps/web created # 查看创建的service [root@k8s-master01 pra]# kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 22d nginx ClusterIP None <none> 80/TCP 35s # 查看创建的statefulset,可以缩写为sts [root@k8s-master01 pra]# kubectl get sts NAME READY AGE web 3/3 6m57s # 查看创建的pod [root@k8s-master01 pra]# kubectl get po NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 51s web-1 1/1 Running 0 31s web-2 1/1 Running 0 11s
1.3.6StatefulSet 创建 Pod 流程 StatefulSet 管理的 Pod 部署和扩展规则如下:
对于具有N个副本的StatefulSet,将按顺序从0到N-1开始创建Pod;
当删除Pod时,将按照N-1到0的反顺序终止;
在缩放Pod之前,必须保证当前的Pod是Running(运行中)或者Ready(就绪);
在终止Pod之前,它所有的继任者必须是完全关闭状态。
StatefulSet 的 pod.Spec.TerminationGracePeriodSeconds(终止 Pod 的等待时间)不应该指定0,设置为 0 对 StatefulSet 的 Pod 是极其不安全的做法,优雅地删除 StatefulSet 的 Pod 是非常有必要的,而且是安全的,因为它可以确保在 Kubelet 从 APIServer 删除之前,让 Pod 正常关闭。
当创建上面的 Nginx 实例时,Pod 将按 web-0、web-1、web-2 的顺序部署 3 个 Pod。在 web-0 处于 Running 或者 Ready 之前,web-1 不会被部署,相同的,web-2 在 web-1 未处于 Running和 Ready 之前也不会被部署。如果在 web-1 处于 Running 和 Ready 状态时,web-0 变成 Failed(失败)状态,那么 web-2 将不会被启动,直到 web-0 恢复为 Running 和 Ready 状态。
如果用户将 StatefulSet 的 replicas 设置为 1,那么 web-2 将首先被终止,在完全关闭并删除web-2 之前,不会删除 web-1。如果 web-2 终止并且完全关闭后,web-0 突然失败,那么在 web-0 未恢复成 Running 或者 Ready 时,web-1 不会被删除。
1.3.7StatefulSet 扩容和缩容 和 Deployment 类似,可以通过更新 replicas 字段扩容/缩容 StatefulSet,也可以使用 kubectl scale、kubectl edit 和 kubectl patch 来扩容/缩容一个 StatefulSet。
扩容 将上述创建的 sts 副本增加到 5 个:使用scale命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 # 当前的pod副本数量是3个 [root@k8s-master01 pra]# kubectl get po NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 10m web-1 1/1 Running 0 10m web-2 1/1 Running 0 9m48s # 将sts管理的pod副本数扩容为5 # scale是扩容缩容指令 # statefulset是你要操作的资源类型 # web资源的名字,这里是名字叫web的statefulset # --replicas=5 是将pod的副本扩容成5个 [root@k8s-master01 pra]# kubectl scale statefulset web --replicas=5 # 可以使用-w参数实时查看创建pod的过程 [root@k8s-master01 pra]# kubectl get po -w NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 31m web-1 1/1 Running 0 30m web-2 1/1 Running 0 30m web-3 1/1 Running 0 5s web-4 0/1 Pending 0 0s web-4 0/1 Pending 0 0s web-4 0/1 ContainerCreating 0 0s web-4 0/1 ContainerCreating 0 1s web-4 1/1 Running 0 3s # 此时在检查pod数量,已经是5个了 [root@k8s-master01 pra]# kubectl get po NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 43m web-1 1/1 Running 0 43m web-2 1/1 Running 0 42m web-3 1/1 Running 0 12m web-4 1/1 Running 0 12m
缩容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # 缩容这里使用编辑文件,然后apply形式 [root@k8s-master01 pra]# vim statefulset.yaml # 将replicas的值改为1 replicas: 1 # # 使用replace重新应用一下文件,使其生效 [root@k8s-master01 pra]# kubectl replace -f statefulset.yaml # 执行-w实时查看删除动态,可以看出是pod正在有序的被删除 [root@k8s-master01 pra]# kubectl get po -w NAME READY STATUS RESTARTS AGE web-4 1/1 Terminating 0 49s web-4 0/1 Terminating 0 50s web-3 1/1 Terminating 0 70s web-3 0/1 Terminating 0 72s web-2 1/1 Terminating 0 92s web-2 0/1 Terminating 0 93s web-1 1/1 Terminating 0 113s web-1 0/1 Terminating 0 115s
1.3.8StatefulSet更新策略
On Delete 策略
OnDelete 更新策略实现了传统(1.7 版本之前)的行为,它也是默认的更新策略。当我们选择这个更新策略并修改 StatefulSet 的.spec.template 字段时,StatefulSet 控制器不会自动更新 Pod,必须手动删除 Pod 才能使控制器创建新的 Pod。
1 2 3 4 spec: updateStrategy: type: OnDelete
RollingUpdate 策略
RollingUpdate(滚动更新)更新策略会自动更新一个 StatefulSet 中所有的 Pod,采用与序号索引相反的顺序进行滚动更新。
1 2 3 4 5 6 7 8 spec: updateStrategy: rollingUpdate: partition: 0 type: RollingUpdate
updateStrategy
参数应该配置在spec.updateStrategy
区域,而不是spec.template.updateStrategy
。这是因为它控制的是StatefulSet整体的Pod更新策略,而不是Pod模板中的单独配置项。
1.3.9StatefulSet分段更新(灰度发布) 比如我们定义一个分区”partition”:3,可以使用 patch 或 edit 直接对 StatefulSet 进行设置:partition参数只能用在RollingUpdate
当partition: 3时,只有下标>=3的pod会被更新,而小于 partition
的 Pod 将保持不变如下图:
案例演示:statefulset.yaml的文件内容如下,RollingUpdate中配置partition: 3,pod副本为5;然后更改镜像版本为nginx:1.27,执行更新操作后观察结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 [root@k8s-master01 pra]# cat statefulset.yaml apiVersion: v1 kind: Service #定义资源的类型 metadata: name: nginx #这里定义的是service的名字 labels: app: nginx #给service定义的标签 spec: ports: - port: 80 #定义service的端口,客户端访问service时使用的端口 name: web #端口的名称,方便管理和引用端口 clusterIP: None #None表示这是一个headless service selector: #选择器,选择带有app=nginx标签的pod进行管理 app: nginx --- apiVersion: apps/v1 kind: StatefulSet #定义资源的类型 metadata: #这个资源的元数据 name: web #StatefulSet 的名称 spec: updateStrategy: #更新策略 rollingUpdate: #滚动更新 partition: 3 #分区更新,控制从第几个pod开始更新,如果是3,那表示第0,1,2个pod不更新 type: RollingUpdate #类型:滚动更新 selector: #标签选择器 matchLabels: #匹配标签 app: nginx # 必须匹配 .spec.template.metadata.labels,选择带有 app: nginx标签的pod serviceName: "nginx" #关联的 Headless Service 名称,也就是定义service中metadata.name的值 replicas: 5 # 默认值是 1,期望pod的副本数量 minReadySeconds: 10 # 默认值是 0 template: metadata: labels: #标签 app: nginx # 必须匹配 .spec.selector.matchLabels,给pod定义打上app:nginx的标签 spec: terminationGracePeriodSeconds: 10 containers: - name: nginx #容器的名称 image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine ports: - containerPort: 80 #容器内部监听的端口 name: web #端口的名称,方便引用和管理端口
当前5个pod,镜像都是registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [root@k8s-master01 pra]# kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 20h web-1 1/1 Running 0 16m web-2 1/1 Running 0 15m web-3 1/1 Running 0 15m web-4 1/1 Running 0 15m # 查看pod的镜像 [root@k8s-master01 pra]# kubectl get pod -oyaml|grep image - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imagePullPolicy: IfNotPresent image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imageID: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx@sha256:a97dd748c61782687030e80daa151d829843b57d3d2afe72ad6b63d7c3e37402 - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imagePullPolicy: IfNotPresent image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imageID: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx@sha256:a97dd748c61782687030e80daa151d829843b57d3d2afe72ad6b63d7c3e37402 - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imagePullPolicy: IfNotPresent image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imageID: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx@sha256:a97dd748c61782687030e80daa151d829843b57d3d2afe72ad6b63d7c3e37402 - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imagePullPolicy: IfNotPresent image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imageID: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx@sha256:a97dd748c61782687030e80daa151d829843b57d3d2afe72ad6b63d7c3e37402 - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imagePullPolicy: IfNotPresent image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine imageID: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx@sha256:a97dd748c61782687030e80daa151d829843b57d3d2afe72ad6b63d7c3e37402
更改sts的镜像为registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:lastest,这里使用edit直接编辑
1 2 3 4 5 6 7 # 使用edit编辑名字是web的statefulset [root@k8s-master01 pra]# kubectl edit sts web spec: containers: - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx #修改这里的版本 imagePullPolicy: IfNotPresent name: nginx
查看更新结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 #可以看出,1、2、3号pod的镜像还是nginx:1.27-alpine,4、5号pod的镜像已经被更新为最新版本nginx:latest [root@k8s-master01 ~]# kubectl get po -oyaml|grep image: - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest #这里镜像已更改 - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:latest #这里镜像已更改
总结:按照上述方式,可以实现分阶段更新,类似于灰度/金丝雀发布,先更新部分的pod看下效果,没有问题在更新所有的pod,更新其他pod的方式是执行下edit命令将partition的值改为0就会更新之前没有更新的pod(想更新哪些只需要根据partition值修改即可)
1.3.10删除StatefulSet 删除StatefulSet有两种方式:即级联删除和非级联删除。
使用非级联方式删除 StatefulSet时,StatefulSet 管理的 Pod 不会被删除;
使用级联删除时,StatefulSet 和它管理的 Pod 都会被删除;
非级联删除 使用 kubectl delete sts xxx 删除 StatefulSet 时,只需提供–cascade=false 参数,就会采用非级联删除,此时删除 StatefulSet 不会删除它管理的 Pod:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # 查看sts [root@k8s-master01 pra]# kubectl get sts NAME READY AGE web 5/5 60m # 查看pod [root@k8s-master01 pra]# kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 40m web-1 1/1 Running 0 41m web-2 1/1 Running 0 41m web-3 1/1 Running 0 58m web-4 1/1 Running 0 58m # 通过上述命令可以看到名字是web的sts管理了5个pod # 使用非级联删除sts [root@k8s-master01 pra]# kubectl delete sts web --cascade=false # warning提示 --cascade=false 已经被弃用,改用 --cascade=orphan warning: --cascade=false is deprecated (boolean value) and can be replaced with --cascade=orphan. statefulset.apps "web" deleted # 此时在查看sts和pod,发现sts已经被删除,但是StatefulSet管理的pod还在 [root@k8s-master01 pra]# kubectl get sts No resources found in default namespace. [root@k8s-master01 pra]# kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 44m web-1 1/1 Running 0 45m web-2 1/1 Running 0 45m web-3 1/1 Running 0 62m web-4 1/1 Running 0 62m
总结:由于此时删除了 StatefulSet,它管理的 Pod 变成了“孤儿”Pod,pod已经不受调度资源管理,因此单独删除 Pod 时,该Pod 不会被重建。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [root@k8s-master01 pra]# kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 44m web-1 1/1 Running 0 45m web-2 1/1 Running 0 45m web-3 1/1 Running 0 62m web-4 1/1 Running 0 62m [root@k8s-master01 pra]# kubectl delete po web-4 pod "web-4" deleted [root@k8s-master01 pra]# kubectl get pod NAME READY STATUS RESTARTS AGE web-0 1/1 Running 0 48m web-1 1/1 Running 0 48m web-2 1/1 Running 0 48m web-3 1/1 Running 0 65m
级联删除 不使用–cascade=false 参数就是级联删除
也可以使用-f 指定创建 StatefulSet 和 Service 的 yaml 文件,直接删除 StatefulSet 和 Service(此文件将 StatefulSet 和 Service 写在了一起):
1 2 3 4 [root@k8s-master01 pra]# kubectl delete -f statefulset.yaml service "nginx" deleted #这里的报错是由于上面演示非级联删除操作时已经删除了sts,所以这里报错找不到名字是web的statefulsets Error from server (NotFound): error when deleting "statefulset.yaml": statefulsets.apps "web" not found
由于已经删除了sts,在执行kubectl delete -f statefulset.yaml时pod不会被删除
1 2 3 4 5 6 # 删除本命名空间下的所有pod,使用--all参数 [root@k8s-master01 pra]# kubectl delete pod --all pod "web-0" deleted pod "web-1" deleted pod "web-2" deleted pod "web-3" deleted
1.4DaemonSet守护进程集
1.4.1定义一个DaemonSet 创建一个 DaemonSet 和 Deployment 类似,比如创建一个 nginx 的 DaemonSet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@k8s-master01 pra]# vim daemonset.yaml apiVersion: apps/v1 kind: DaemonSet #定义资源的类型 metadata: #元数据 labels: #定义标签 app: nginx #这里是具体的标签,这是为DaemonSet资源打标签 name: nginx-daemonset #定义DaemonSet这个资源的名字 spec: #定义DaemonSet的规格和行为 selector: #选择器,选择什么样的pod进行管理 matchLabels: #标签匹配,用于匹配pod的标签,对pod进行管理 app: nginx #选择具有 app=nginx 标签的pod管理 template: #定义pod的模板,意思是DaemonSet使用这个模板创建pod metadata: #pod的元数据 labels: #pod的标签,必须与 selector 中的标签匹配 app: nginx #为DaemonSet管理的每个pod添加app=nginx的标签。 spec: #定义pod的规格和行为 containers: #容器列表 - name: nginx #容器的名字是nginx image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #容器使用的镜像
DaemonSet.yaml文件中定义的所要管理的pod的标签在该命名空间中不能有其他pod也有,否则DaemonSet无法管理,会报错。
(1)必需字段
和其他所有 Kubernetes 配置一样,DaemonSet 需要 apiVersion、kind 和 metadata 字段,同时也需要一个.spec 配置段。
(2)Pod 模板
.spec 唯一需要的字段是.spec.template。.spec.template 是一个 Pod 模板,它与 Pod 具有相同的配置方式,但它不具有 apiVersion 和 kind 字段。
除了 Pod 必需的字段外,在 DaemonSet 中的 Pod 模板必须指定合理的标签。
(3)Pod Selector
.spec.selector 字段表示 Pod Selector,它与其他资源的.spec.selector 的作用相同。
.spec.selector 表示一个对象,它由如下两个字段组成:
1.4.2创建DaemonSet 利用上述的yaml文件创建daemonset
1 2 3 4 5 6 7 8 9 10 11 12 # 使用create命令创建daemonset [root@k8s-master01 pra]# kubectl create -f ds-nginx.yaml daemonset.apps/nginx-daemonset created # 查看pod是否被创建,可以看出每个节点中都运行了一个pod [root@k8s-master01 pra]# kubectl get po -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-daemonset-92vqb 1/1 Running 0 26s 172.16.32.151 k8s-master01 <none> <none> nginx-daemonset-ltl2x 1/1 Running 0 26s 172.16.58.210 k8s-node02 <none> <none> nginx-daemonset-mq5g7 1/1 Running 0 26s 172.16.195.15 k8s-master03 <none> <none> nginx-daemonset-pc5v7 1/1 Running 0 26s 172.16.85.242 k8s-node01 <none> <none> nginx-daemonset-rkjt7 1/1 Running 0 26s 172.16.122.151 k8s-master02 <none> <none>
1.4.3指定节点部署pod 默认情况下daemonset会在每个节点上部署一个pod,可以利用标签的方式,让daemonset在指定的节点上创建,而不是在所有的节点上创建。
具体流程:先给要部署的节点打上相应的标签,然后配置yaml参数,指定选择具有什么样标签的节点部署pod。创建后的pod就会根据标签选择相应的noe节点上运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 # 查看所有节点的标签 [root@k8s-master01 pra]# kubectl get node --show-labels NAME STATUS ROLES AGE VERSION LABELS k8s-master01 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-master02 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master02,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-master03 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master03,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-node01 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-node02 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux,node.kubernetes.io/node= # 给node01和node02节点打上disktype=ssd标签 # 可以一次指定多个节点名称 [root@k8s-master01 pra]# kubectl label nodes k8s-node01 k8s-node02 disktype=ssd node/k8s-node01 labeled node/k8s-node02 labeled # 验证k8s-node01和k8s-node02节点是否有disktype=ssd标签 [root@k8s-master01 pra]# kubectl get nodes --show-labels NAME STATUS ROLES AGE VERSION LABELS k8s-master01 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master01,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-master02 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master02,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-master03 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-master03,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-node01 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node01,kubernetes.io/os=linux,node.kubernetes.io/node= k8s-node02 Ready <none> 24d v1.28.11 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,disktype=ssd,kubernetes.io/arch=amd64,kubernetes.io/hostname=k8s-node02,kubernetes.io/os=linux,node.kubernetes.io/node= # 指定了.spec.template.spec.nodeSelector,DaemonSet Controller 将在与 Node Selector(节点选择器)匹配的节点上创建 Pod,比如部署在磁盘类型为 ssd 的节点上(需要提前给节点定义标签 Label): [root@k8s-master01 pra]# cat ds-nginx.yaml apiVersion: apps/v1 kind: DaemonSet #定义资源的类型 metadata: #元数据 labels: #定义标签 app: nginx #这里是具体的标签,这是为DaemonSet资源打标签 name: nginx-daemonset #定义DaemonSet这个资源的名字 spec: #定义DaemonSet的规格和行为 selector: #选择器,选择什么样的pod进行管理 matchLabels: #标签匹配,用于匹配pod的标签,对pod进行管理 app: nginx #选择具有 app=nginx 标签的pod管理 template: #定义pod的模板,意思是DaemonSet使用这个模板创建pod metadata: #pod的元数据 labels: #pod的标签,必须与 selector 中的标签匹配 app: nginx #为DaemonSet管理的每个pod添加app=nginx的标签。 spec: #定义pod的规格和行为 containers: #容器列表 - name: nginx #容器的名字是nginx image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine #容器使用的镜像 nodeSelector: #节点选择器,由于该配置项是定义pod的调度策略的,所以应该在spec.template.spec中配置 disktype: ssd #选择带有disktype=ssd标签的节点进行部署pod # 注意:由于 `nodeSelector` 是 Pod 的调度策略,因此它必须放在描述 Pod 规格的 `spec.template.spec` 中,而不是更高层级的DaemonSet `spec` 中。 # 创建pod [root@k8s-master01 pra]# kubectl replace -f ds-nginx.yaml daemonset.apps/nginx-daemonset replaced # 验证pod是否只在k8s-node01和k8s-node02节点上创建 [root@k8s-master01 pra]# kubectl get po -owide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-daemonset-xq5xt 1/1 Running 0 34s 172.16.85.243 k8s-node01 <none> <none> nginx-daemonset-zlmhr 1/1 Running 0 31s 172.16.58.211 k8s-node02 <none> <none>
补充:当你想在其他节点上也创建pod,只需给其他节点上加上disktype=ssd标签即可,pod会自动进行创建
1 2 3 4 5 6 7 [root@k8s-master01 pra]# kubectl label nodes k8s-master03 disktype=ssd node/k8s-master03 labeled [root@k8s-master01 pra]# kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-daemonset-8dlt6 1/1 Running 0 6s 172.16.195.16 k8s-master03 <none> <none> nginx-daemonset-xq5xt 1/1 Running 0 5m41s 172.16.85.243 k8s-node01 <none> <none> nginx-daemonset-zlmhr 1/1 Running 0 5m38s 172.16.58.211 k8s-node02 <none> <none>
1.4.4DaemonSet更新和回滚 如果添加了新节点或修改了节点标签(Label),DaemonSet 将立刻向新匹配上的节点添加Pod,同时删除不能匹配的节点上的 Pod。
在 Kubernetes 1.6 以后的版本中,可以在 DaemonSet 上执行滚动更新,未来的 Kubernetes 版本将支持节点的可控更新。
DaemonSet 滚动更新可参考:https://kubernetes.io/zh-cn/docs/tasks/manage-daemon/update-daemon-set/
查看上一节创建的 DaemonSet 更新方式:RollingUpdate
1 2 [root@k8s-master01 pra]# kubectl get ds/nginx-daemonset -o go-template='{{.spec.updateStrategy.type}}{{"\n"}}' RollingUpdate
命令式更新,和之前 Deployment、StatefulSet 方式一致:
1 2 # 命令格式:kubectl edit ds /<daemonset-name> [root@k8s-master01 pra]# kubectl edit ds nginx-daemonset
更新镜像:
1 2 3 4 5 6 7 8 9 10 11 12 # 命令格式 kubectl set image ds <daemonset-name> -c <container-name>= <container-newimage> --record=true # kubectl set image更新镜像的命令 # ds表示更新的资源类型是daemonset # --record=true 表示记录此次更新 [root@k8s-master01 pra]# kubectl set image ds nginx-daemonset nginx=registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine --record=true Flag --record has been deprecated, --record will be removed in the future daemonset.apps/nginx-daemonset image updated # 验证镜像是否更新为registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine [root@k8s-master01 pra]# kubectl get ds nginx-daemonset -oyaml|grep image: - image: registry.cn-beijing.aliyuncs.com/k8s-liujunwei/nginx:1.27-alpine
daemonset不像deployment,每次更新会记录在rs中,daemonset的更新是记录在controllerrevision
1 2 3 4 5 6 7 8 9 10 11 [root@k8s-master01 pra]# kubectl get controllerrevision NAME CONTROLLER REVISION AGE nginx-daemonset-6f5d44b8cb daemonset.apps/nginx-daemonset 5 13m nginx-daemonset-776cfb4bf6 daemonset.apps/nginx-daemonset 3 94m nginx-daemonset-7966c9fb86 daemonset.apps/nginx-daemonset 6 37m web-7c8457974 daemonset.apps/nginx-daemonset 1 4h50m web-8f8db7cb daemonset.apps/nginx-daemonset 2 4h47m 具体更新内容通过controllerrevision查看,例如: [root@k8s-master01 pra]# kubectl get controllerrevision nginx-daemonset-7966c9fb86 -oyaml
1.5HPA(Horizontal Pod Autoscaler) HPA(Horizontal Pod Autoscaler)是 Kubernetes 中用于根据工作负载的实时情况自动调整 Pod 副本数量的控制器。HPA 可以根据 CPU 使用率、内存使用率、或者其他自定义的指标(如应用程序特定的指标)来动态地扩展或缩减 Pod 的数量,从而提高应用程序的弹性和资源利用效率。
HPA 的主要功能:
自动扩展 :根据实时指标自动增加 Pod 副本数量,以应对高负载情况,从而确保应用程序的性能和可用性。
自动缩减 :当负载减少时,自动减少 Pod 副本数量,以节省资源和成本。
1.5.1HPA自动扩缩容实践 待补充