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部署过程

image

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

image

​ (更新内容图)

更新流程: 比如启动3个副本,

集群会先启动一个新的副本,完成后,关闭删除一个副本。

集群再启动第二个新副本,然后再关闭一个的副本。

集群启动第三个新副本,然后关闭最后一个副本。

​ 可通过kubectl describe deploy nginx 命令查看

image

​ (副本更新流程图)

更新总结: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

image

​ (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

image

​ 当更新了版本不稳定或者配置不合理时,可以对其进行回滚操作,假设我们又进行了几次更新(此处以更新镜像版本触发更新,更改配置效果类似)

一般我们回滚到上一个稳定版本

# 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的注意事项

  1. 历史版本清理策略:
    在默认情况下,revision 保留 10 个旧的 ReplicaSet,其余的将在后台进行垃圾回收,可以
    在.spec.revisionHistoryLimit 设置保留 ReplicaSet 的个数。当设置为 0 时,不保留历史记录。
    更新策略:
  2. .spec.strategy.type==Recreate,表示重建,先删掉旧的Pod再创建新的Pod;
  3. .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命名空间下创建的,在其它命名空间是操作不了的

image

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流程

image

​ (创建流程)、

image

​ (删除流程)

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。在 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 不会被删除。
  5. 总结: 如上图,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 类似,此处不再演示

posted @ 2022-11-10 17:11  名字长的像一只老山羊  阅读(73)  评论(0编辑  收藏  举报