04-K8S之pod控制器

pod控制器类型

ReplicationController: 最初的控制器,一个控制器实现所有的功能,过于庞大。已被废弃
ReplicaSet:
Deployment: 并不直接管理pod,而是工作在ReplicaSet之上,通过控制ReplicaSet来控制pod,帮我们管理无状态应用的。比ReplicaSet强大,支持扩缩容,滚动更新和回滚,以及声明式更新配置的功能(创建资源可以根据声明式的逻辑来控制,改变我们在apiserver定义的目标状态,只要这个状态支持动态运行时修改,不像kubectl create)。

DaemonSet:在集群中的每一个节点之上都运行一个pod,pod挂了,会自动重启,在新加入的节点上也会自动创建一个DaemonSet管理的pod。使用场景比如:运行一个代理,日志收集器(filebeat、flunted)

Job:一次性作业的pod
CronJob:周期性地运行pod,有明确的退出时间

StatefulSet:管理有状态应用,每一个pod副本都是被单独管理的,它拥有着自己独有的标识和数据集,一旦这个节点或pod出现故障,在重新加入集群或者重新启动pod,需要做很多初始化的操作,场景:redis集群,集群中的每一个主机是按照槽位实现分布的,并且集群中的每一个redis主机的槽位是固定的,比如:redis1槽位:1-5000,redis2槽位:5001-10000,redis3槽位:10001-16384;每一个redis主机都不能被取代
'''
1.不论是Deployment,还是DaemonSet,这些服务管理的pod无状态(无状态应用)的,通常用于只关注群体,而不关注个体的场景;
2.不论是Deployment,还是DaemonSet,这种服务是守护进程类的,必须持续运行在后台,没有终止的那一刻,不繁忙的时候在忙着监听(文件的变动、用户对某个套接字的访问请求)。
3.有时候需要对数据库做备份操作,可以启动一个定时任务来备份,也可以、启动一个pod来实现,当备份结束之后停止运行,也没必要重启(pod只运行一次)。这时,Deployment,DaemonSet控制器是不适合的,因为它们始终保持pod处于运行状态。需要使用Job控制器

4. Cronjob控制器,如果一个任务在当前周期内没有处理完,pod终止了,该怎么办?所以CronJob控制器还需要处理此类问题。好处就是Job和CronJob不需要持续后台运行。
'''

1.ReplicaSet控制器

先看一个示例:

vim pod-rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: replicaset-pod  # 控制器名称,也是pod的名称,最好定义控制器、pod模板中名称、container的名称一致
  namespace: default
spec: # 控制器的spec
  replicas: 2
  selector:
    matchLabels:
      app: myapp
      release: canary
  template:
    metadata:
      name: myapp-pod # pod模板里定义的这个名称是不起作用的,创建出来的pod的名称是 控制器名称+随机串
      labels:   # 这里定义的标签要和上面selector定义的标签一致,不然创建的pod的标签和选择器标签不一致,会一直创建下去,k8s会被撑爆。这里的标签是给pod贴的标签。
        app: myapp
        release: canary
        environment: qa # 可以创建标签选择器之外的其他标签
    spec: # 创建pod的spec
      containers:
      - name: myapp-container
        image: nginx:1.20
        ports:
        - name: http
          containerPort: 80

replicaset控制器通过标签选择器控制我们定义的副本数量,如果这时我们强行修改别的pod的标签和replicaset控制器标签完全一样,那么我们原本的pod将被杀死1个。

可以在pod前面加一个负载均衡service,而service是通过自身定义的标签选择器中的标签来选择带有符合标签的pod,进行流量转发,和控制器的选择器标签没有关系。比如:

replicaset1:
selector:
  matchLabels:
    app: myapp
    release: canary

replicaset2:
selector:
  matchLabels:
    app: myapp
    release: prod

而service的selector为:
service:
    selector:
        app: myqpp

则此service对replicaset1和replicaset2控制器控制的pod副本都能进行流量转发。当然这种需要一定的场景,一般根据标签的唯一性,只选取某一个控制器控制的pod进行流量转发。

使用控制器动态扩缩容副本数

kubectl edit rs replicaset-pod # 在线编辑副本控制器的配置,更新副本数量

2.deployment控制器

三层结构:deployment控制replicaSet,replicaSet控制pod

重要字段

kubectl explain deployment.spec
	strategy <Object> # 更新策略 maxSurge和maxUnavailable不能同时为零。
    	rollingUpdate	<Object> # 定义滚动更新方式(控制粒度)
            maxSurge	<string>  # 定义滚动更新pod数量可以超出当前值多少,可以是具体数字,亦可以是百分比。(先更新,再删除)
            maxUnavailable	<string>  # 定义滚动更新最大不可用的pod数量,可以是具体数字,亦可以是百分比。(先删除,再更新)
        type	<string>
			"Recreate" or "RollingUpdate",Default is RollingUpdate.
			Recreate:删除一个pod,创建一个新的pod,删除一个,创建一个,直到所有副本全部更新
             RollingUpdate:滚动更新,如果type定义为Recreate类型,rollingUpdate将不起作用。
	
    revisionHistoryLimit	<integer> # 支持回滚的老replicaSet版本的数量,默认是10个
	paused	<boolean> # 暂停deployment立马更新的动作。不定义此字段默认,立马更新。

定义一个deployment示例

vim pod-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy-controll
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app:myapp
      release: canary
  template:
    metadata:
      name: myapp-deploy-controll
      labels:
        app: myapp
        release: canary
    spec:
      containers:
      - name: myapp
        image: nginx:1.20
        ports:
        - name: http
          containerPort: 80

kubectl apply -f pod-deploy-controll.yaml # 及支持创建pod,也支持更新pod,可以重复apply 下图1

# 通过编辑配置文件修改副本数,再次apply yaml文件,每一次yaml文件的变化,当apiserver发现当前的状态与etcd中的不同,都会通过apiserver同步到etcd当中。同时修改现有状态到期望状态。 下图2
	replicas: 3 

# 查看deploy状态信息  下图3
kubectl  describe deploy myapp-deploy-controll

图1:

图2:

图3:

imagePullPolicy:镜像拉取策略
restartPolicy:容器重启策略
strategy:滚动更新pod策略


1.该配置清单文件直接更新
vim pod-deploy-controll.yaml 
# 修改镜像版本:
image: nginx:1.20 --> image: nginx:1.20.2
                
kubectl get pods -l app=myapp,release=canary -w # 下图1
kubectl apply -f pod-deploy-controll.yaml 

kubectl get pods -l app=myapp,release=canary # 查看新镜像的pod 图2
kubectl get rs -o wide  # 图3 老的replicaSet管控的pod副本全部迁移到使用新镜像重新创建的replicaSet上了,但是老版本会保留10,随时等待用户回滚。
kubectl get deploy -o wide
kubectl describe deploy myapp-deploy-controll # 图4
kubectl rollout history deploy myapp-deploy-controll # 图5 查看可以滚动的所有保留的历史版本,默认保留10个最近版本


2.使用kubectl patch打补丁的方式更新,后跟json格式的字符串; # 比如:修改配置清单参数strategy、replicas,比如:滚动更新策略(strategy), maxSurge,minUnavailable
kubectl patch --help
# 打补丁方式增加副本数(扩容)
kubectl patch deployment myapp-deploy-controll -p '{"spec":{"replicas":5}}' # 图6

# 通过修改strategy的maxSurge和minUnavailavle,比如:最多不可用0,最大超出个数为1;在更新这1个的时候,让它暂停下来,当前更新的这1个是中间迭代版本,暂停的时候还没来得及删除老的一个版本,这样一共就有6个pod了,这就是我们设置最多不可用0,最大超出个数为1的作用;这样就实现了灰度发布,新增的这个pod就是我们放的金丝雀。。。。
实现方式:
# 使用命令
1) kubectl rollout pause  --help 
# 1.首先使用打补丁的方式修改滚动更新策略
kubectl patch  deployment myapp-deploy-controll -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
kubectl describe deployment  myapp-deploy-controll # 图7
'''
Waiting for deployment "myapp-deploy-controll" rollout to finish: 1 out of 5 new replicas have been updated...
'''
# 2.根据更新策略,监听pod的更新变动情况
kubectl get po -l app=myapp,release=canary -w # 图8
或者使用:
kubectl rollout status deployment myapp-deploy-controll
# 3.放出一个金丝雀,并暂停deployment控制器
kubectl set image deploment myapp-deploy-controll myapp=nginx:1.21.4 && kubectl rollout pause deployment myapp-deploy-controll
    '''
    deployment.apps/myapp-deploy-controll image updated
	deployment.apps/myapp-deploy-controll paused
    '''
# 4.此时deployment 和 replicaSet的情况 下图9
kubectl get deploy -o wide
kubectl get rs -o wide

# 从deployment控制器的暂停状态恢复到滚动更新状态
kubectl rollout resume deployment myapp-deploy-controll
kubectl get po -l app=myapp,release=canary -w  # 执行resume命令后,剩下5个老的5个副本的滚动更新情况,并最终达到我们的期望的5个副本全部更新为新镜像的pod。
kubectl get po -l app=myapp,release=canary # 图11


# 版本回滚,不指定版本号,默认回滚到上衣版本
kubectl rollout undo --help  # --to-revision=REVISION
kubectl get po -l app=myapp,release=canary -w # 发现所有副本都回滚到 v1版本。
kubectl rollout history deployment myapp-deploy-controll
'''
deployment.apps/myapp-deploy-controll 
REVISION  CHANGE-CAUSE
1         <none>
2         <none>
3         <none>
4         <none>
'''
# 现在我们从当前版本REVISION:4,回滚到REVISION:1
kubectl rollout undo deployment myapp-deploy-controll  --to-revision=1
'''
deployment.apps/myapp-deploy-controll rolled back
'''
kubectl get rs -o wide # 下图12
kubectl get po -l app=myapp,release=canary -o wide
kubectl rollout history deployment myapp-deploy-controll # 当前的v5就是我们回滚的v1版本,原v1被v5取代。
'''
REVISION  CHANGE-CAUSE
2         <none>
3         <none>
4         <none>
5         <none>
'''

2)修改配置清单的pause字段 # 下图13

3.如果只是更新镜像文件,也可以使用 kubectl set image 的方式进行更新

图1:

图2:

图3:

图4:

图5:

图6:

图7:

图8:

图9:

图10:

图11:

图12:

图13:

3.daemonSet控制器

kubectl explain daemonSet
docker pull elastic/filebeat:6.8.15
docker image inspect elastic/filebeat:6.8.15 # 查看镜像内部的封装结构,比如:查看内部定义的环境变量

[root@master01 controll]# vim pod-daemonset-controll.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
      role: logstor
  template:
    metadata:
      labels:
        app: redis
        role: logstor
    spec:
      containers:
      - name: redis
        image: redis:6.0.3
        ports: 
        - name: redis
          containerPort: 6379

---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: pod-daemonset
  namespace: default
spec: # 控制器的spec
  selector: 
    matchLabels:
      app: filebeat
      release: stable
  template:
    metadata: 
      name: filebeat
      labels:   # 这里定义的标签要和上面selector定义的标签一致,不然创建的pod的标签和选择器标签不一致,会一直创建下去,k8s会被撑爆。
        app: filebeat
        release: stable
    spec: # 创建pod的spec
      containers:
      - name: filebeat
        image: elastic/filebeat:6.8.15
        env: 
        - name: REDIS_HOST
          value: redis.default.svc.cluster.local
        - name: REDIS_LOG_LEVEL
          value: info                 
kubectl apply  -f pod-daemonset-controll.yaml  # 图1
kubectl get po
kubectl exec -it pod-daemonset-sbfs5 -- /bin/sh # 图2

# 给redis暴露端口(添加一个service)
kubectl expose deployment redis --port=6379
kubectl exec -it redis-67cb65d499-24jdl -- /bin/sh # 查看filebeat发送到redis pod的日志收集其概况 ls /data

图1:

图2:

posted on 2021-12-20 09:34  jueyuanfengsheng  阅读(325)  评论(0编辑  收藏  举报