Kubernetes调度基础(二)

网友投稿 280 2022-09-09

Kubernetes调度基础(二)

3 有状态应用管理 StatefulSet

3.1 什么是 StatefulSet?

StatefulSet主要用于管理有状态应用程序的工作负载API对象。比如在生产环境中,可以部署ElasticSearch集群、MongoDB集群或者需要持久化的RabbitMQ集群、Redis集群、Kafka集群和ZooKeeper集群等。

3.2 Headless Service

而StatefulSet创建的Pod一般使用Headless Service(无头服务)进行通信,和普通的Service的区别在于Headless Service没有ClusterIP,它使用的是Endpoint进行互相通信,Headless一般的格式为

statefulSetName-{0..N-1}.serviceName.namespace.svc.cluster. local。

说明:

serviceName为Headless Service的名字。 0..N-1为Pod所在的序号,从0开始到N-1。statefulSetName为StatefulSet的名字。namespace为服务所在的命名空间。.cluster.local为Cluster Domain(集群域)。

3.3 定义一个 StatefulSet 资源文件

apiVersion: v1kind: Servicemetadata: name: nginx labels: app: nginxspec: ports: - port: 80 name: web clusterIP: None selector: app: nginx---apiVersion: apps/v1kind: StatefulSetmetadata: name: webspec: 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

# kubectl create -f sts-web.yaml # 也可以使用-n 部署到其他 namespaceservice/nginx createdstatefulset.apps/web created# kubectl get stsNAME DESIRED CURRENT AGEweb 2 2 12s# kubectl get svcNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEkubernetes ClusterIP 10.96.0.1 443/TCP 7d2hnginx ClusterIP None 80/TCP 16s# kubectl get po -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 2m5sweb-1 1/1 Running 0 115s

3.5 StatefulSet 创建 Pod 流程

StatefulSet 管理的 Pod 部署和扩展规则如下:

1. 对于具有N个副本的StatefulSet,将按顺序从0到N-1开始创建Pod;

2. 当删除Pod时,将按照N-1到0的反顺序终止;

3. 在缩放Pod之前,必须保证当前的Pod是Running(运行中)或者Ready(就绪);

4. 在终止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 不会被删除。

3.6 StatefulSet 扩容和缩容

和 Deployment 类似,可以通过更新 replicas 字段扩容/缩容 StatefulSet,也可以使用 kubectl scale、kubectl edit 和 kubectl patch 来扩容/缩容一个 StatefulSet。

(1)扩容

将上述创建的 sts 副本增加到 5 个:

# kubectl scale sts web --replicas=5statefulset.apps/web scaled

查看扩容后 Pod 的状态:

# kubectl get poNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 2m58sweb-1 1/1 Running 0 2m48sweb-2 1/1 Running 0 116sweb-3 1/1 Running 0 79sweb-4 1/1 Running 0 53s

也可使用以下命令动态查看:

kubectl get pods -w -l app=nginx

(2)缩容

首先打开另一个终端动态查看缩容的流程:

# kubectl get pods -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 4m37sweb-1 1/1 Running 0 4m27sweb-2 1/1 Running 0 3m35sweb-3 1/1 Running 0 2m58sweb-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 的 Pod 正在被有序的删除(或终止):

# kubectl get pods -w -l app=nginxNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 4m37sweb-1 1/1 Running 0 4m27sweb-2 1/1 Running 0 3m35sweb-3 1/1 Running 0 2m58sweb-4 1/1 Running 0 2m32sweb-0 1/1 Running 0 5m8sweb-0 1/1 Running 0 5m11sweb-4 1/1 Terminating 0 3m36sweb-4 0/1 Terminating 0 3m38sweb-4 0/1 Terminating 0 3m47sweb-4 0/1 Terminating 0 3m47sweb-3 1/1 Terminating 0 4m13sweb-3 0/1 Terminating 0 4m14sweb-3 0/1 Terminating 0 4m22sweb-3 0/1 Terminating 0 4m22s

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/webWaiting 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; donedotbalo/canary:v1dotbalo/canary:v1dotbalo/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-2pod "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; donedotbalo/canary:v1dotbalo/canary:v1dotbalo/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 AGEweb-0 1/1 Running 0 16mweb-1 1/1 Running 0 16mweb-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 AGEweb-0 1/1 Running 0 16mweb-1 1/1 Running 0 16mweb-2 1/1 Running 0 11m

由于此时删除了 StatefulSet,它管理的 Pod 变成了“孤儿”Pod,因此单独删除 Pod 时,该 Pod 不会被重建:

# kubectl get poNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 16mweb-1 1/1 Running 0 16mweb-2 1/1 Running 0 11m# kubectl delete po web-0pod "web-0" deleted# kubectl get poNAME READY STATUS RESTARTS AGEweb-1 1/1 Running 0 18mweb-2 1/1 Running 0 12m

再次创建 sts:

# kubectl apply -f sts-web.yaml statefulset.apps/web created# kubectl get poNAME READY STATUS RESTARTS AGEweb-0 1/1 Running 0 32sweb-1 1/1 Running 0 19m

(2)级联删除

省略--cascade=false 参数即为级联删除:

# kubectl delete statefulset webstatefulset.apps "web" deleted# kubectl get poNo resources found.

也可以使用-f 指定创建 StatefulSet 和 Service 的 yaml 文件,直接删除 StatefulSet 和 Service (此文件将 StatefulSet 和 Service 写在了一起):

# kubectl delete -f sts-web.yaml service "nginx" deletedError 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/v1kind: DaemonSetmetadata: labels: app: nginx name: nginxspec: selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - image: nginx:1.15.12 imagePullPolicy: IfNotPresent name: nginx

(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 表示一个对象,它由如下两个字段组成:

(4)指定节点部署 Pod 如果指定了.spec.template.spec.nodeSelector,DaemonSet Controller 将在与 Node Selector(节 点选择器)匹配的节点上创建 Pod,比如部署在磁盘类型为 ssd 的节点上(需要提前给节点定义 标签 Label):

nodeSelector: disktype: ssd

4.2 创建 DaemonSet

比如创建一个 nginx:

# pwd# kubectl create -f nginx-ds.yaml

此时会在每个节点创建一个 Pod:

# kubectl get poNAME READY STATUS RESTARTS AGEnginx-6ssvl 1/1 Running 0 56snginx-8ddgd 1/1 Running 0 36snginx-cfx5d 1/1 Running 0 9snginx-k48bt 1/1 Running 0 46snginx-p84ng 1/1 Running 0 11s# 使用-o wide 可以查看 Pod 所在的节点时# kubectl get po -o wide

4.3 更新和回滚 DaemonSet

如果添加了新节点或修改了节点标签(Label),DaemonSet 将立刻向新匹配上的节点添加 Pod,同时删除不能匹配的节点上的 Pod。

在 Kubernetes 1.6 以后的版本中,可以在 DaemonSet 上执行滚动更新,未来的 Kubernetes 版 本将支持节点的可控更新。

DaemonSet 滚动更新可参考:​​​更新策略和 StatefulSet 类似,也有 OnDelete 和 RollingUpdate 两种方式。

查看上一节创建的 DaemonSet 更新方式:

# kubectl get ds nginx-ds -o gotemplate='{{.spec.updateStrategy.type}}{{"\n"}}'RollingUpdate

命令式更新,和之前 Deployment、StatefulSet 方式一致

kubectl edit ds/kubectl patch ds/ -p=

更新镜像

kubectl set image ds/= --record=true

查看更新状态

kubectl rollout status ds/

列出所有修订版本

kubectl rollout history daemonset

回滚到指定 revision

kubectl rollout undo daemonset --to-revision=

DaemonSet 的更新和回滚与 Deployment 类似,此处不再演示。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:王一博刚走又请蔡徐坤 掉队的燕京啤酒深陷“追星”式营销!
下一篇:Etcd可视化工具:Kstone简介(一)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~