k8s03-Replication-Controller-ReplicaSet-有状态-无状态-daemonset
- Replication Controller和ReplicaSet
- 无状态应用管理Deployment
- 有状态应用管理StatefuSet
- 守护进程集DaemonSet
kubernets调度基础
1.1 RC 和RS
Replication Controller(复制控制器,RC)和ReplicaSet(复制集,RS)是两种简单部署Pod的方式,因为在生产环境中,主要使用更高级的Deployment等方式进行Pod的管理和部署,简单了解即可
1.Replication Controller
【第一代副本控制器,现在可能没人在用了】
-Replication Controller(简称 RC),可确保Pod副本数达到期望值,也就是RC定义的数量。
换句话说,Replication Controller 可确保一个pod 或者一组同类Pod总是可用
如果存在的Pod大于设定的值,则Replication Controller 将终止额外的Pod,如果太小则启动更多的Pod用于 保证达到期望值,
与手动创建Pod不同的是,用Replication Controller维护Pod在失败,删除,终止时会自动替换,因此使用程序只需一个Pod,也应该使用Replication Controller或者其它管理方式,Replication Controller 类似于进程管理程序,但是Replication Controller 不是监视单个节点上的各个进程,而是监视多个节点上的多个Pod
总结:RC用于控制pod的数量。
定义一个Replication Controller的示例如下
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
1.2 RepicaSet
ReplicaSet 是支持基于集合标签选择器的下一代 Replication Controller,它主要作用Deployment协调创建,
删除和更新Pod,和Replication Controller唯一区别就是,ReplicaSet 支持标签选择器,在实际应用中,虽然ReplicaSet可以单独使用,但是一般建议使用Deployment来自动管理ReplicaSet,除非自定义的Pod不需要更新或者其它编排等
总结:基于集合标签选择器的,RS是RC的下一代副本控制,支持标签选择,配合deployment使用
定义一个ReplicaSet的示例如下
ApiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app:guestbook
tier:frontend
spec:
# modify replicas according to your case
replicas: 3
selector:
metchLabels:
tier:frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/goole_samples/gb-frontend:v3
resources:
cpu: 100m
memory: 100Mi
evn:
- name: GET_HOSTS_FROM
value: dns
# If your cluster config does not include a dns service, then to
# instead access environment variables to find service host
# info, comment out the 'value: dns' line above, and uncomment the
# line below.
# value: env
ports:
- containerPor: 80
Replication Controller 和 ReplicaSet 的创建删除和 Pod 并无太大区别,Replication Controller
目前几乎已经不在生产环境中使用,ReplicaSet 也很少单独被使用,都是使用更高级的资源
Deployment、DaemonSet、StatefulSet 进行管理 Pod。
2.无状态应用管理-Deployment
deployment部署过程
deployment一般用于部署公司的无状态服务,这个也是最常用的控制器,因为企业内部现在都是以微服务为主,而且微服务实现无状态化也是最佳实践,可以利用Deployment的高级功能做到无缝迁移,自动扩容缩容,自动灾难恢复,一键回滚等功能
java
go
vue
PHP等业务容器
其它需要任何状态的服务
2.1 创建deployment
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: nginx:1.18.9
ports:
- containerPort: 80
注意,从k8s 1.16版本开始,彻底废弃了其它的APIVersion,只能使用app/v1,1.16以下的版本可以使用extension等
上述例子解析:
apiVersion apps/v1必须指定该字段;
nginx-deployment: Deployment的名称;
replicas 创建pod的副本数
selector: 定义Deployment如何找到要管理的Pod,与template的label(标签对应),
template字段包含以下字段:
app: nginx使用label(标签)标记Pod;
spec: 表示Pod运行一个名字为nginx的容器
image: 运行此Pod使用的镜像.
Port:容器用于发送和接受;流量的接口
kubectl create 创建此Deployment
# kubectl create -f dp-nginx.yaml
使用 kubectl get 或者 kubectl describe 查看此 Deployment 的状态:
#kubectl get deploy
==================================
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 0/3 3 0 8s
NAME: 集群中 Deployment的名称:
READY:Pod 就绪个数和总副本数;
UP-TO-DATE 显示已达到期望状态的被更新的副本数
AVAILABLE 显示用户已经使用的应用程序副本数,当前为0,说明目前还没有达到期望的Pod
AGE: 显示运行的时间
可以使用rollout命令查看整个Deployment创建的状态
#kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out
当rollout结束时,再次查看此Deployment,可以看到AVAILABLE的数量和yaml文件中定义的replicas相同
# kubectl get deploy
==================================
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 10m
查看此Deployment 当前对应的ReplicaSet:
#kubectl get rs -l app=nginx
NAME DESIRED CURRENT READY AGE
nginx-deployment-5c689d88bb 3 3 3 12mq
DESIRED 应用程序的副本数
CURRENT 当前正在运行的副本数
当Deployment有过更新,对应的RS可能不止一个,可以通过-o yaml获取当前对应的RS是那个,其余的RS为保留的实力版本,用于回滚等操作
查看Deployment创建的Pod,可以看到Pod的hash值为5c689d88bb,和上述Deployment对应的ReplicaSet的hash值一致:
# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deployment-5c689d88bb-6b95k 1/1 Running 0 13m
app=nginx,pod-template-hash=5c689d88bb
nginx-deployment-5c689d88bb-9z5z2 1/1 Running 0 13m
app=nginx,pod-template-hash=5c689d88bb
nginx-deployment-5c689d88bb-jc8hr 1/1 Running 0 13m
app=nginx,pod-template-hash=5c689d88bb
2.2更新Deployment
注意:当且仅当Deployment的pod模板(即.spec.template)更改时,才会触发Deployment更新,例如更改内存,CPU配置,或者容器的image
(更新内容图)
更新流程: 比如启动3个副本,
集群会先启动一个新的副本,完成后,关闭删除一个副本。
集群再启动第二个新副本,然后再关闭一个的副本。
集群启动第三个新副本,然后关闭最后一个副本。
可通过kubectl describe deploy nginx 命令查看
(副本更新流程图)
更新总结:deployment 的yaml文件中,只能修改属于template内的,不过切记不能修改template下的标签
例如更新Nginx Pod的image使用nginx:latest,并使用--recode记录当前更改的参数,后期回滚时可以查看到对应的信息:
更新命令:
#kubectl set image deployment nginx-deployment nginx=nginx:1.9.1 --record
deployment.extensions/nginx-deployment image updated
当然也可以使用edit命令直接编辑deployment,效果相同
==============第二种更新命令=================================
#kubectl edit deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment edited
=====不推荐=========第三种更新命令[修改]=================================
修改nginx.yaml
然后修改完成后kubectl apply -f nginx.yaml
===============第四种思维更新命令方式===================================================
或者重新把运行的deployment中的pod重新导出成yaml文件
删掉status以下整个字段
删掉 uid
删掉resourceVersion
删掉deployment
删掉kubernetes.io 等一系列的没用的元数据
导出命令: kubectl get deploy nginx -oyaml >nginx.yaml
(kubectl edit命令更新)
同样可以使用 kubectl rollout startus 查看更新过程:
#kubectl rollout status deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment edited
同样可以使用 kubectl rollout status 查看更新过程
#kubectl rollout status deployment.v1.apps/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 1 out of 3
new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3
new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3
new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3
new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old
replicas are pending termination...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old
replicas are pending termination...
deployment "nginx-deployment" successfully rolled out
可以看出更新过程为新旧交替更新,首先新建一个Pod,当Pod状态为Running时,删除一个旧的Pod,同时在创建一个心的Pod,当触发一个更新后,会有新的ReplicaSet产生,旧的ReplicaSet会被保存,查看此时ReplicaSet,可以从AGE或READY看出来新旧ReplicaSet:
#kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-5c689d88bb 0 0 0 34m
nginx-deployment-6987cdb55b 3 3 3 5m14s
通过describe查看Deployment的详细信息
# kubectl describe deploy nginx-deployment
Name: nginx-deployment
Namespace: default
...
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-6987cdb55b (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 36m deployment-controller Scaled up
replica set nginx-deployment-5c689d88bb to 3
Normal ScalingReplicaSet 7m16s deployment-controller Scaled up
replica set nginx-deployment-6987cdb55b to 1
Normal ScalingReplicaSet 5m18s deployment-controller Scaled down
replica set nginx-deployment-5c689d88bb to 2
Normal ScalingReplicaSet 5m18s deployment-controller Scaled up
replica set nginx-deployment-6987cdb55b to 2
Normal ScalingReplicaSet 4m35s deployment-controller Scaled down
replica set nginx-deployment-5c689d88bb to 1
Normal ScalingReplicaSet 4m34s deployment-controller Scaled up
replica set nginx-deployment-6987cdb55b to 3
Normal ScalingReplicaSet 3m30s deployment-controller Scaled down
replica set nginx-deployment-5c689d88bb to 0
在describe种可以看出,第一次创建时,它创建了一个名为nginx-deployment-5c689d88bb的ReplicaSet,并直接扩展为3个副本,更新部署时,它创建一个新的ReplicaSet,命名为nginx-deployment-6987cdb55b,并将其副本数扩展为1,然后将旧的ReplicaSet缩小为2,这样至少可以有2个Pod用,最多创建了4个Pod,以此类推,使用相同的滚动更新策略向上和向下扩展新旧ReplicaSet,最终新的ReplicaSet可以拥有3个副本,并将旧的ReplicaSet缩小为0.
2.3 回滚Deployment
当更新了版本不稳定或者配置不合理时,可以对其进行回滚操作,假设我们又进行了几次更新(此处以更新镜像版本触发更新,更改配置效果类似)
一般我们回滚到上一个稳定版本
# kubectl set image deployment nginx-deployment nginx=dotbalo/canary:v1
--record
# kubectl set image deployment nginx-deployment nginx=dotbalo/canary:v2
--record
使用kubectl rollout history 查看更新历史
# kubectl rollout history deployment/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deployment nginx-deployment nginx=nginx:1.9.1
--record=true
3 kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v1 --record=true
4 kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v2 --record=true
查看Deployment 某次更新的详细信息,使用--revision 指定某次更新版本号
# kubectl rollout history deployment/nginx-deployment --revision=3
deployment.apps/nginx-deployment with revision #3
Pod Template:
Labels: app=nginx
pod-template-hash=645959bf6b
Annotations: kubernetes.io/change-cause: kubectl set image deployment
nginx-deployment nginx=dotbalo/canary:v1 --record=true
Containers:
nginx:
Image: dotbalo/canary:v1
Port: 80/TCP
Host Port: 0/TCP
Environment:<none>
Mounts: <none>
Volumes: <none>
如果只需要回滚上一个稳定版本,使用kubectl rollout undo即可
#kubectl rollout undo deployment/nginx-deployment
deployment.apps/nginx-deployment
再次查看更新历史,发现REVISIONS回到了canary:v1
# kubectl rollout history deployment/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deployment nginx-deployment nginx=nginx:1.9.1
--record=true
4 kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v2 --record=true
5 kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v1 --record=true
如果要回滚到指定版本,使用--to-revision参数
# kubectl rollout undo deployment/nginx-deployment --to-revision=2
deployment.extensions/nginx-deployment
2.4 扩容Deployment
当公司访问量变大,或者有预期内的活动时,三个Pod可能已无法支撑业务时,可以提前对其进行扩展
使用kubectl scale 动态调正Pod的副本数,比如增加Pod为5个
# kubectl scale deployment.v1.apps/nginx-deployment --replicas=5
deployment.apps/nginx-deployment scaled
查看Pod,此时Pod已经变成了5个
# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-5f89547d9c-5r56b 1/1 Running 0 90s
nginx-deployment-5f89547d9c-htmn7 1/1 Running 0 25s
nginx-deployment-5f89547d9c-nwxs2 1/1 Running 0 99s
nginx-deployment-5f89547d9c-rpwlg 1/1 Running 0 25s
nginx-deployment-5f89547d9c-vlr5p 1/1 Running 0 95s
2.5 暂停和恢复 Deployment 更新
上述演示的均为更改某一处的配置,更改后立即触发更新,大多数情况下可能需要针对一个资源文件更改多处地方,而并不需要多次触发更新,此时可以使用Deployment暂停功能,临时禁用更新操作,对Deployment进行多次修改后在进行更新
使用kubectl rollout pause 命令即可暂停Deployment更新
#kubectl rollout pause deployment/nginx-deployment
deployment.extensions/nginx-deployment paused
然后对Deployment进行相关更新操作,比如先更新镜像,然后对其资源进行限制(如果使用的kubectl edit命令,可以直接进行多次修改,无需暂停更新,kubectl set 命令一般会集成在CICD流水线中)
#kubectl set image deployment.v1.apps/nginx-deployment
nginx=nginx:1.9.1
deployment.apps/nginx-deployment image updated
# kubectl set resources deployment.v1.apps/nginx-deployment -c=nginx --
limits=cpu=200m,memory=512Mi
deployment.apps/nginx-deployment resource requirements updated
通过 rollout history 可以看到没有新的更新
#kubectl rollout history deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
5 kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v1 --record=true
7 kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v2 --record=true
8 kubectl set image deployment nginx-deployment
nginx=dotbalo/canary:v2 --record=truem
进行完最后一处配置更改后,使用kubectl rollout resume 恢复Deployment 更新
# kubectl rollout resume deployment.v1.apps/nginx-deployment
deployment.apps/nginx-deployment resumed
可以查看恢复更新的Deployment 创建了一个新的RS(ReplicaSet缩写)
# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-57895845b8 5 5 4 11s
可以查看 Deployment 的 image(镜像)已经变为 nginx:1.9.1
# kubectl describe deploy nginx-deployment
Name: nginx-deployment
Namespace: default
...
Annotations: deployment.kubernetes.io/revision: 9
kubernetes.io/change-cause: kubectl set image
deployment nginx-deployment nginx=dotbalo/canary:v2 --record=true
Selector: app=nginx
Replicas: 5 desired | 5 updated | 5 total | 5 available | 0
unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.9.1
Port: 80/TCP
Host Port: 0/TCP
2.6更新Deployment的注意事项
- 历史版本清理策略:
在默认情况下,revision 保留 10 个旧的 ReplicaSet,其余的将在后台进行垃圾回收,可以
在.spec.revisionHistoryLimit 设置保留 ReplicaSet 的个数。当设置为 0 时,不保留历史记录。
更新策略: - .spec.strategy.type==Recreate,表示重建,先删掉旧的Pod再创建新的Pod;
- .spec.strategy.type==RollingUpdate,表示滚动更新,可以指定maxUnavailable和maxSurge
来控制滚动更新过程;
.spec.strategy.rollingUpdate.maxUnavailable,指定在回滚更新时最大不可用的Pod数量,
可选字段,默认为25%,可以设置为数字或百分比,如果maxSurge为0,则该值不能
为0;
.spec.strategy.rollingUpdate.maxSurge可以超过期望值的最大Pod数,可选字段,默认为
25%,可以设置成数字或百分比,如果maxUnavailable为0,则该值不能为0。
Ready 策略:
.spec.minReadySeconds 是可选参数,指定新创建的 Pod 应该在没有任何容器崩溃的情况下
视为 Ready(就绪)状态的最小秒数,默认为 0,即一旦被创建就视为可用,通常和容器探针连
用。
3.有状态应用管理StatefulSet
StatefulSet创建过程
1.在default命名空间下,会依次创建副本,例如,创建三个nginx副本,会依次创建,当第一个创建完成时,会创建第二个,第二个创建失败时,会停止创建第三个。
2.statefulset 也是具有namespace隔离性的,在default命名空间下创建的,在其它命名空间是操作不了的
3.1什么是StatefulSet?
statefulSet(有状态集,缩写为sts)常用于部署有状态的,且需要有序启动的应用程序,
比如在进行部署springCloud项目容器化时,Eureka的部署是比较适用的
statefulSet部署的方式可以给每个Eureka实例创建一个唯一且固定的标识符,
并且每个eureka实例无需配置多余的Service,其余Spring Boot应用可以直接通过
Eureka的Headless Service 即可进行注册
Eureka集群
MongoDB
elasticsearch
redis
kafka
其它需要具有状态的服务
特点:
需要稳定的独一无二的网络标识符
需要持久化数据
需要有序的,优雅的部署和扩展
需要有序的自动滚动更新
3.2 Headless Service
Headless Service 需要提前创建
和deployment类似,一个stateful 也同样管理者基于相同容器规范的Pod
不同的是,statefulset为每个pod 维护了一个粘性标识
而statefulSet创建的pod 一般使用headless Service(无头服务) 进行pod之间的通信
和普通的service的区别在于Headless service没用clusterIP,它使用的是Endpoint进行互相通信,
Headless Service 没有ClusterIP,它使用的是Endpoint进行相互通信,Headless一般格式为
statefulSetName-{0...N-1}.serviceName.namespace.svc.cluster.local
-serviceName 为Headless Service的名字,创建statefulSet时,必须指定Headless Service名称
0..N-1 为Pod所在的序号,从0开始到N-1
statefulSetName 为StatefulSet的名字
namespace 为服务所在的命名空间
.cluster.local为Cluster Domain(集群域)
3.3 定义一个StatefulSet资源文件
定义一个简单的StatefulSet的示例如下
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
serviceName: "nginx"
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
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
3.4创建StatefulSet
创建statefulSet
# kubectl create -f sts-web.yaml # 也可以使用-n 部署到其他 namespace
service/nginx created
statefulset.apps/web created
# kubectl get sts
NAME DESIRED CURRENT AGE
web 2 2 12s
# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d2h
nginx ClusterIP None <none> 80/TCP 16s
# kubectl get po -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2m5s
web-1 1/1 Running 0 115s
3.5 statefulSet创建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。在 web0 处于 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 突然失败,那么在 web0 未恢复成 Running 或者 Ready 时,web-1 不会被删除。 - 总结: 如上图,statefulSet 创建的时候,是依次平滑创建,当副本创建出现问题后,则停止创建。删除跟创建流程顺序相反,依次删除。
3.6 statefulSet扩容和缩容
和Deployment类似,可以通过更新replicas字段扩容/缩容 StatefulSet,
也可以使用kubectl scale,kubectl edit 和kubectl patch 来扩容/缩容一个StatefulSet
(1) 扩容
将上述创建的sts副本增加到5个
#kubectl scale sts web --replicas=5
statefulset.apps/web scaled
查看扩容后Pod的状态
#kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 2m58s
web-1 1/1 Running 0 2m48s
web-2 1/1 Running 0 116s
web-3 1/1 Running 0 79s
web-4 1/1 Running 0 53s
也可以使用以下命令动态查看
kubectl get pods -w -l app=nginx
(2) 缩容
首先打开另一个终端动态查看缩容的流程
#kubectl get pods -w -l app=nginx
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 4m37s
web-1 1/1 Running 0 4m27s
web-2 1/1 Running 0 3m35s
web-3 1/1 Running 0 2m58s
web-4 1/1 Running 0 2m32s
在另一个终端副本数改为3(此处演示的为patch命令,patch和edit和scale稍复杂)
kubectl patch sts web -P '{"spec":{"replicas":3}}'
statefulset.apps/web patched
此时可以看到第一个终端显示web-4 和web-3正在被有序的删除或者终止
3.7 StatefulSet更新策略
(1)On Delete 策略
OnDelete 更新策略实现了传统(1.7 版本之前)的行为,它也是默认的更新策略。当我们选
择这个更新策略并修改 StatefulSet 的.spec.template 字段时,StatefulSet 控制器不会自动更新 Pod,
必须手动删除 Pod 才能使控制器创建新的 Pod。
(2)RollingUpdate 策略
RollingUpdate(滚动更新)更新策略会自动更新一个 StatefulSet 中所有的 Pod,采用与序号
索引相反的顺序进行滚动更新。
比如更改一个名称为 web 的 StatefulSet 使用 RollingUpdate 方式更新
# kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":
"RollingUpdate"}}}'
statefulset.apps/web patched
查看更改后的StatefulSet
#kubectl get sts web -o yaml |grep -A 1 "updateStrategy
updateStrategy:
type: RollingUpdate
改变容器的镜像触发滚动更新(此处使用的jsonPath的方式更改的资源配置,
可以使用set或edit减少复杂度)
# kubectl patch statefulset web --type='json' -p='[{"op": "replace",
"path": "/spec/template/spec/containers/0/image",
"value":"dotbalo/canary:v1"}]'
statefulset.apps/web patched
在更新过程中可以使用kubectl rollout status sts/
#kubectl rollout status sts/web
Waiting for 1 pods to be ready...
waiting for statefulset rolling update to complete 1 pods at revision
web-56b5798f76...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
waiting for statefulset rolling update to complete 2 pods at revision
web-56b5798f76...
Waiting for 1 pods to be ready...
Waiting for 1 pods to be ready...
statefulset rolling update complete 3 pods at revision web-56b5798f76...
查看更新后的镜像
# for p in 0 1 2; do kubectl get po web-$p --template '{{range $i,
$c := .spec.containers}}{{$c.image}}{{end}}'; echo; done
dotbalo/canary:v1
dotbalo/canary:v1
dotbalo/canary:v1
3.8分段更新
比如我们定义一个分区"partition:3",可以使用patch 或者edit 直接对statefulSet进行设置:
# kubectl patch statefulset web -p
'{"spec":{"updateStrategy":{"type":"RollingUpdate",
"rollingUpdate":{"partition":3}}}}'
statefulset "web" patched
然后再次使用patch改变容器的镜像:
# kubectl patch statefulset web --type='json' -p='[{"op": "replace",
"path": "/spec/template/spec/containers/0/image", "value":"k8s.gcr.io/nginxslim:0.7"}]'
statefulset "web" patched
删除Pod触发更新
kubectl delete po web-2
pod "web-2" deleted
此时因为Pod web-2的序号小于分区3 ,所以Pod不会会被更新,还是会使用以前的容器恢复Pod
将分区改为2,此时会自动更新web-2(因为之前更改了更新策略,但是不会更新web-0,和web-1)
# kubectl patch statefulset web -p
'{"spec":{"updateStrategy":{"type":"RollingUpdate",
"rollingUpdate":{"partition":2}}}}'
statefulset "web" patched
按照上述方式,可以实现分阶段更新,类似于灰度/金丝雀发布。查看最终的结果如下:
# for p in 0 1 2; do kubectl get po web-$p --template '{{range $i,
$c := .spec.containers}}{{$c.image}}{{end}}'; echo; done
dotbalo/canary:v1
dotbalo/canary:v1
dotbalo/canary:v2
3.9 删除StatefulSet
删除StatefulSet有两种方式,即级联删除和非级联删除。使用非级联方式删除 StatefulSet时,
StatefulSet 的 Pod 不会被删除;使用级联删除时,StatefulSet 和它的 Pod 都会被删除。
(1)非级联删除
使用kubectl delete sts xxx 删除StatefulSet时,只需提供 --cascade=false参数,就会采用非级联删除,此时删除StatefulSet不会删除它的Pod
# kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 16m
web-1 1/1 Running 0 16m
web-2 1/1 Running 0 11m
# kubectl delete statefulset web --cascade=false # 采用非级联删除
statefulset.apps "web" deleted
# kubectl get sts # 查看此时 sts 已经被删除
No resources found.
# kubectl get po # 该 StatefulSet 管理的 Pod 并未被删除
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 16m
web-1 1/1 Running 0 16m
web-2 1/1 Running 0 11m
由于此时删除了StatefulSet,它管理的Pod变成了孤儿,Pod因此单独删除了Pod时,Pod
不会被重建
# kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 16m
web-1 1/1 Running 0 16m
web-2 1/1 Running 0 11m
# kubectl delete po web-0
pod "web-0" deleted
# kubectl get po
NAME READY STATUS RESTARTS AGE
web-1 1/1 Running 0 18m
web-2 1/1 Running 0 12m
再次创建sts
# kubectl apply -f sts-web.yaml
statefulset.apps/web created
# kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 32s
web-1 1/1 Running 0 19m
(2)级联删除
省略 --cascade = false 参数即为级联删除
# kubectl delete statefulset web
statefulset.apps "web" deleted
# kubectl get po
No resources found.
也可以使用-f 指定创建StatefulSet 和Service 的yaml 文件,直接删除StatefulSet和service
(此文件将StatefulSet和Service写在了一起)
# kubectl delete -f sts-web.yaml
service "nginx" deleted
Error from server (NotFound): error when deleting "sts-web.yaml":
statefulsets.apps "web" not found # 因为 StatefulSet 已经被删除,所以会提示该
StatefulSet 不存在
4守护进程集 DaemonSet
4.1 定义一个daemonSet
创建一个daemonSet和Deployment 类似,比如创建一个nginx的daemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
app: nginx
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:1.15.12
imagePullPolicy: IfNotPresent
name: nginx
(1)必须字段
和其它所有kubenetes配置一样,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 表示一个对象,它由如下两个字段组成
(4)指定节点部署Pod
如果指定了.spec.template.spec.nodeSelector,DaemonSet Controller 将在Node Selector(节点选择器)匹配的节点上创建Pod,比如部署在磁盘类型ssd的节点上(需要提前给节点定义标签Label)
标签Label
nodeSelector:
disktype: ssd
4.2 创建DaemonSet
比如创建一个nginx
# pwd
# kubectl create -f nginx-ds.yaml
此时会在每个节点上创建一个Pod
# kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-6ssvl 1/1 Running 0 56s
nginx-8ddgd 1/1 Running 0 36s
nginx-cfx5d 1/1 Running 0 9s
nginx-k48bt 1/1 Running 0 46s
nginx-p84ng 1/1 Running 0 11s
# 使用-o wide 可以查看 Pod 所在的节点时
# kubectl get po -o wide
4.3 更新和回滚 DameonSet
如果添加了新节点或修改节点标签(Label),DaemonSet 将立刻向新匹配的节点添加Pod,
子k8s 1,6以后的版本中,可以在DaemonSet上执行滚动更新,未来的K8S版本将支持节点可控更新
DaemonSet 滚动更新可参考
DaemonSet 更新策略和StatefulSet类似,也有OnDelete 和rolling Update两种方式
查看上一节创建的DaemonSet更新方式
# kubectl get ds nginx-ds -o gotemplate='{{.spec.updateStrategy.type}}{{"\n"}}'
RollingUpdate
命令式更新,和之前Deployment,StatefulSet 方式一致
kubectl edit ds/<daemonset-name>
kubectl patch ds/<daemonset-name> -p=<strategic-merge-patch>
更新镜像
kubectl set image ds/<daemonset-name><container-name>= <container-newimage> --record=true
查看更新状态
kubectl rollout status ds/<daemonset-name>
列出所有修订版本
kubectl rollout history daemonset <daemonset-name>
回滚到指定revision
kubectl rollout undo daemonset <daemonset-name> --to-revision=<revision>
DaemonSet 的更新和回滚与 Deployment 类似,此处不再演示