菜单
本页目录

4 Kubernetes-控制器

一 概念

pod分类:
			自主式pod(静态pod)
			控制器管理的pod



控制器:对pod的管理,控制pod的具体状态和行为

控制器类型:
        - ReplicationController 和 ReplicaSet
        - Deployment
        - DaemonSet
        - StateFulSet
        - Job/CronJob
        - Horizontal Pod Autoscaling 

二 RC与RS与Deployment关联

1)RC控制器

ReplicationController:确保容器应用的副本数,始终保持在用户定义的副本数
						(即:若容器有异常退出,会自动创建pod来代替;异常多出来的容器也会自动回收)

注意:控制器中的spec中的pod创建,可用之前的静态pod的yaml文件(单纯复制yaml文件后,注意缩进)
			标签对应,确保pod由同一个控制器管理

实验:创建RC控制器

1、根据 2.rc.yaml 文件创建RC控制器
#2.rc.yaml文件详解
指定apiversion,为core/v1
使用资源类别为:ReplicationController(也可用RC代替,用命令: kubectl explain rc 查看全称)
定义元数据:
		定义当前的rc控制器名称为:frontend
定义期望:
	replicas指定创建的副本数量,三个
	selector指定标签选择器:app:nginx
	template指定创建副本的模板:
			定义元数据,定义pod的期望:
						容器名,申明环境变量,申明重要端口,存活探测
[root@k8s-master01 3]# cd /root/3/
[root@k8s-master01 3]# vim 2.rc.yaml 
[root@k8s-master01 3]# cat 2.rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: php-redis
        image: wangyanglinux/myapp:v1
        env:
        - name: GET_HOSTS_FROM
          value: dns
          name: zhangsan
          value: "123"
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:
            port: 80
            path: /index.html
          initialDelaySeconds: 1
          periodSeconds: 3
          timeoutSeconds: 3


[root@k8s-master01 3]# kubectl create -f 2.rc.yaml

[root@k8s-master01 3]# kubectl get rc
NAME       DESIRED   CURRENT   READY   AGE
frontend   3         3         3       11s
[root@k8s-master01 3]# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
frontend-99hdk   1/1     Running   0          13s
frontend-mphqt   1/1     Running   0          13s
frontend-mwc5c   1/1     Running   0          13s
2、测试

删除pod后,控制器会重新创建一个pod

[root@k8s-master01 3]# kubectl get pod						
NAME             READY   STATUS    RESTARTS   AGE
frontend-99hdk   1/1     Running   0          13s
frontend-mphqt   1/1     Running   0          13s
frontend-mwc5c   1/1     Running   0          13s

[root@k8s-master01 3]# kubectl delete pod frontend-99hdk		#删除第一个pod
pod "frontend-99hdk" deleted
[root@k8s-master01 3]# kubectl get pod							#再次查看pod,会发现rc控制器自动创建了一个新的pod
NAME             READY   STATUS    RESTARTS   AGE
frontend-bhfdm   1/1     Running   0          5s
frontend-mphqt   1/1     Running   0          2m37s
frontend-mwc5c   1/1     Running   0          2m37s

控制器管理的pod中,若容器出现损坏,会让pod重建其中的一个容器

[root@k8s-master01 3]# kubectl exec -it frontend-bhfdm -c php-redis -- /bin/sh			#手动模拟容器文件损坏
/ # rm -rf /usr/share/nginx/html/index.html 
/ # command terminated with exit code 137

[root@k8s-master01 3]# kubectl exec -it frontend-bhfdm -c php-redis -- /bin/sh			#控制器让pod自动重建容器
/ # ls /usr/share/nginx/html/
50x.html    index.html

[root@k8s-master01 3]# kubectl get pod
NAME             READY   STATUS    RESTARTS   AGE
frontend-bhfdm   1/1     Running   1          5m12s
frontend-mphqt   1/1     Running   0          7m44s
frontend-mwc5c   1/1     Running   0          7m44s
3、注意标签的对应

​ 创建一个 3.rc.yaml 文件,其中的标签不对应,会导致无法创建

[root@k8s-master01 3]# cp -a 2.rc.yaml 3.rc.yaml 
[root@k8s-master01 3]# vim 3.rc.yaml 
[root@k8s-master01 3]# cat 3.rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    app: nginx
  template:
    metadata:
      labels:
        app: nginx1
    spec:
      containers:
      - name: php-redis
        image: wangyanglinux/myapp:v1
        env:
        - name: GET_HOSTS_FROM
          value: dns
          name: zhangsan
          value: "123"
        ports:
        - containerPort: 80
        livenessProbe:
          httpGet:
            port: 80
            path: /index.html
          initialDelaySeconds: 1
          periodSeconds: 3
          timeoutSeconds: 3
[root@k8s-master01 3]# kubectl create -f 3.rc.yaml 
The ReplicationController "frontend" is invalid: spec.template.metadata.labels: Invalid value: map[string]string{"app":"nginx1"}: `selector` does not match template `labels`
4、手动创建对应标签的pod

​ 会被rc控制器自动删除(若容器有异常退出,会自动创建pod来代替;异常多出来的容器也会自动回收)

[root@k8s-master01 3]# vim 4.pod.yaml 
[root@k8s-master01 3]# cat 4.pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
  labels:
    app: nginx
spec:
  containers:
  - name: lifecycle-demo
    image: wangyanglinux/myapp:v1
  
[root@k8s-master01 3]# kubectl create -f 4.pod.yaml ;kubectl get pod
pod/lifecycle-demo created
NAME             READY   STATUS        RESTARTS   AGE
frontend-bhfdm   1/1     Running       1          17m
frontend-mphqt   1/1     Running       0          19m
frontend-mwc5c   1/1     Running       0          19m
lifecycle-demo   0/1     Terminating   0          0s

5、对已管理的pod,修改标签

​ 拓展:修改pod的标签

# 标签
$ kubectl label 资源类别  对象名称
	kubectl label pod pod-demo  version=v1   # 添加标签
	kubectl label pod pod-demo  app=tomcat --overwrite 	# 修改存在的标签

​ 控制器会退出对修改标签pod的管理,并重新创建一个受管理pod

[root@k8s-master01 3]# kubectl label pod frontend-bhfdm app=tomcat --overwrite
pod/frontend-bhfdm labeled

[root@k8s-master01 3]# kubectl get pod --show-labels
NAME             READY   STATUS    RESTARTS   AGE   LABELS
frontend-bhfdm   1/1     Running   1          27m   app=tomcat			#不受控制器管理的pod
frontend-mphqt   1/1     Running   0          29m   app=nginx
frontend-mwc5c   1/1     Running   0          29m   app=nginx
frontend-wjgpk   1/1     Running   0          13s   app=nginx			#新创建,收控制器管理的pod



#拓展:若修改的标签不存在,则会自动添加
[root@k8s-master01 3]# kubectl label pod frontend-bhfdm version=v1
pod/frontend-bhfdm labeled
[root@k8s-master01 3]# kubectl get pod --show-labels
NAME             READY   STATUS    RESTARTS   AGE    LABELS
frontend-bhfdm   1/1     Running   1          28m    app=tomcat,version=v1
frontend-mphqt   1/1     Running   0          31m    app=nginx
frontend-mwc5c   1/1     Running   0          31m    app=nginx
frontend-wjgpk   1/1     Running   0          2m5s   app=nginx

​ 若将修改后的标签,再改回来,此pod仍会被rc管理,之前新管理的pod会被删除

[root@k8s-master01 3]# kubectl label pod frontend-bhfdm app=nginx --overwrite
pod/frontend-bhfdm labeled

[root@k8s-master01 3]# kubectl get pod --show-labels
NAME             READY   STATUS    RESTARTS   AGE   LABELS
frontend-bhfdm   1/1     Running   1          37m   app=nginx,version=v1
frontend-mphqt   1/1     Running   0          39m   app=nginx
frontend-mwc5c   1/1     Running   0          39m   app=nginx
frontend-wjgpk   0/1     Terminating   0          8m54s

2)RS控制器

​ 官方建议RS(ReplicaSet)替代RC进行部署,RS与RC没有本质的不同,RS对比RC,RS有更高级的匹配方式(新增了运算符匹配

实验1:根据 5.rs.yaml 文件创建rs控制器

再次强调标签的重要性

拓展:kubectl命令

​ 删除pod是同步完成,删除控制器是异步完成的

#5.rs.yaml文件详解
指定api版本:app/v1
指定资源类别:ReplicaSet
指定元数据:
		rs名称为:frontend
指定rs期望:
		replicas指定创建副本:三个
		selector指定标签选择器:(运算符匹配)
					matchLabels
		template指定创建副本的模板:
				模板的元数据定义标签
				模板的期望定义容器相关信息
[root@k8s-master01 3]# vim 5.rs.yaml
[root@k8s-master01 3]# cat 5.rs.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
spec:
  replicas: 3
  selector:
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: wangyanglinux/myapp:v1
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 80

[root@k8s-master01 3]# kubectl create -f 5.rs.yaml
[root@k8s-master01 3]# kubectl get pod --show-labels
NAME             READY   STATUS    RESTARTS   AGE   LABELS
frontend-7cbcv   1/1     Running   0          95s   tier=frontend
frontend-9w8rm   1/1     Running   0          95s   tier=frontend
frontend-swp5t   1/1     Running   0          95s   tier=frontend

实验2、展现RS控制器的特性

​ rs 在标签选择器上,除了可以定义键值对的选择形式,还支持 matchExpressions 字段,可以提供多种选择。目前支持的操作包括:

  • In:label 的值在某个列表中
  • NotIn:label 的值不在某个列表中
  • Exists:某个 label 存在
  • DoesNotExist:某个 label 不存在
运算符匹配1:

​ 只要存在app为key即满足标签匹配(存在运算符)

​ 只要存在app不为key即满足标签匹配(不存在运算符)

6.rs.yaml 文件:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs-demo
spec:
  selector:
    matchExpressions:
      - key: app
        operator: Exists
  template:
    metadata:
      labels:
        app: spring-k8s
    spec:
      containers:
        - name: rs-c1
          image: wangyanglinux/myapp:v1
          ports:
            - containerPort: 80
详细实验:
1、创建rs控制器
[root@k8s-master01 3]# vim 6.rs.yaml
[root@k8s-master01 3]# kubectl create -f 6.rs.yaml

[root@k8s-master01 3]# kubectl get rs
NAME      DESIRED   CURRENT   READY   AGE
rs-demo   1         1         1       3s
[root@k8s-master01 3]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE   LABELS
rs-demo-9hmn5   1/1     Running   0          12s   app=spring-k8s

2、修改副本数量:
# 调整控制器的副本数量
$ kubectl scale 资源类别  对象名称  --replicas=副本数
	kubectl scale rs rs-demo --replicas=10
	
# 修改资源对象,操作方式同 vim 一致
$ kubectl edit 资源类别  对象名称
	如果,修改完成后保存,但是回退,代表此资源无法修改

具体修改:

# 调整控制器的副本数量
[root@k8s-master01 3]# kubectl scale rs rs-demo --replicas=10
replicaset.extensions/rs-demo scaled
[root@k8s-master01 3]# kubectl get rs
NAME      DESIRED   CURRENT   READY   AGE
rs-demo   10        10        10      6m20s
[root@k8s-master01 3]# kubectl scale rs rs-demo --replicas=5
replicaset.extensions/rs-demo scaled
[root@k8s-master01 3]# kubectl get rs
NAME      DESIRED   CURRENT   READY   AGE
rs-demo   5         5         5       6m43s


# 修改资源对象,操作方式同 vim 一致
[root@k8s-master01 3]# kubectl edit rs rs-demo		#将replicas改为3
replicaset.extensions/rs-demo edited
[root@k8s-master01 3]# kubectl get rs
NAME      DESIRED   CURRENT   READY   AGE
rs-demo   3         3         3       11m

**注意:**若 kubectl edit 修改完后保存,但是回退,代表此资源无法修改

​ 若kubectl edit 修改完保存后,比如版本,没生效为正常,需要重建所有容器,因为此处不支持声明式表达(后面会介绍)

3、测试存在运算符的特性

​ 此特性,可以结合svc的特性,实现:一个控制器管理多个pod,这些pod中给不同的环境访问

#使用存在运算符后(此处表示只要存在app为key,即匹配),更改key的value值也会归rs管理
[root@k8s-master01 3]# kubectl label pod rs-demo-czbx7 app=yangqin --overwrite
pod/rs-demo-czbx7 labeled
[root@k8s-master01 3]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE     LABELS
rs-demo-czbx7   1/1     Running   0          8m11s   app=yangqin
rs-demo-h29vn   1/1     Running   0          8m11s   app=spring-k8s
rs-demo-q9nxr   1/1     Running   0          8m11s   app=spring-k8s
运算符匹配2:

​ 指定key后,只要值在定义的列表中,即满足标签匹配(在列表内运算符)

​ 指定key后,只要值不在定义的列表中,即满足标签匹配(不在列表内运算符)

7.rs.yaml 文件:(此处定义了不在列表内运算符,指定了app为key,只要value不为定义的两个值就满足匹配)

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: rs-demo
spec:
  selector:
    matchExpressions:
      - key: app
        operator: NotIn
        values:
        - spring-k8s
        - hahahah
  template:
    metadata:
      labels:
        app: sg-k8s
    spec:
      containers:
        - name: rs-c1
          image: wangyanglinux/myapp:v1
          ports:
            - containerPort: 80
详细实现:
1、创建rs控制器

​ 标签key为:app,value只要不是spring-k8s、hahahah就满足匹配

[root@k8s-master01 3]# vim 7.rs.yaml
[root@k8s-master01 3]# kubectl create -f 7.rs.yaml 
replicaset.apps/rs-demo created
[root@k8s-master01 3]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE   LABELS
rs-demo-2nhr8   1/1     Running   0          9s    app=sg-k8s

2、修改标签

​ 修改标签为:app=yangqin,满足匹配

[root@k8s-master01 3]# kubectl label pod rs-demo-2nhr8 app=yangqin --overwrite
pod/rs-demo-2nhr8 labeled
[root@k8s-master01 3]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE   LABELS
rs-demo-2nhr8   1/1     Running   0          88s   app=yangqin

​ 修改标签为:app=hahahaa,不满足匹配,RS控制器会重建一个pod

[root@k8s-master01 3]# kubectl label pod rs-demo-2nhr8 app=hahahah --overwrite
pod/rs-demo-2nhr8 labeled

[root@k8s-master01 3]# kubectl get pod --show-labels
NAME            READY   STATUS    RESTARTS   AGE   LABELS
rs-demo-2nhr8   1/1     Running   1          9h    app=hahahah
rs-demo-bv6w5   1/1     Running   0          10s   app=sg-k8s

3)Deployment控制器

1、概念

Deployment支持声明式表达,用来替代RC,方便管理应用

主要应用场景:

​ 定义Deployment创建pod和RS

​ 滚动升级和回滚应用

​ 扩容、缩容

​ 暂停和继续Deployment

命令开发:

声明式命令:仅提供需求即可
			create apply -f 
			deployment
			SQL命令
表达式命令:详细说明所有过程
			shell命令
			RC、RS
			kubectl create -f

Deployment 创建pod的原理:

​ Deployment控制器先创建RS,再由RS去创建pod

image-20230118184505455

滚动更新:

​ 在更新时,仍能给用户提供访问

image-20230116230803739

回滚:

​ 由V2版降到V1,控制器调用回之前的RS(当版本出现问题,需要降级时)

image-20230118185554610

2、deployment部署一个nginx

Ⅰ 根据8.deployment.yaml文件创建deployment控制器
#8.deployment.yaml详解
指定接口组版本:extensions/v1beta1
指定资源类型为:Deployment
指定元数据信息:
			定义deployment名为:nginx-deployment
定义控制器的期望:
			标签选择器 app:nginx
			定义副本数量为3个
			定义副本模板:
					元数据中定义标签 app:nginx
					副本期望:
							创建一个nginx容器
							声明容器的80端口

使用 kubectl create 创建控制器(表达式创建)

[root@k8s-master01 3]# vim 8.deployment.yaml
[root@k8s-master01 3]# cat 8.deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: wangyanglinux/myapp:v1
        ports:
        - containerPort: 80

使用 kubectl apply 创建控制器(声明式创建)

测试更新

[root@k8s-master01 3]# kubectl delete deployment --all

[root@k8s-master01 3]# kubectl apply -f 8.deployment.yaml

[root@k8s-master01 3]# kubectl get pod -o wide					#查询其中一个pod的ip

[root@k8s-master01 3]# curl 172.100.2.40						#访问得到,版本为v1
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>

[root@k8s-master01 3]# vim 8.deployment.yaml 					#修改yaml文件使用的镜像版本为v2
[root@k8s-master01 3]# grep "v2" 8.deployment.yaml
        image: wangyanglinux/myapp:v2
        
[root@k8s-master01 3]# kubectl apply -f 8.deployment.yaml 		#用apply再次创建

[root@k8s-master01 3]# kubectl get pod -o wide					#查询其中一个pod的ip

[root@k8s-master01 3]# curl 172.100.2.41						#访问得到,版本为v2
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>

Ⅱ 扩容
[root@k8s-master01 3]# pwd
/root/3
[root@k8s-master01 3]# kubectl delete deployment --all
[root@k8s-master01 3]# kubectl apply -f 8.deployment.yaml --record

[root@k8s-master01 3]# kubectl scale deployment nginx-deployment --replicas=10 --record
Ⅲ 若集群支持HPA,可为控制器设置自动扩展(后续介绍)

​ K8S中提供了新功能(HPA),可根据当前pod资源使用情况,自动扩展pod数量

# 给deployment控制器设置自动扩展,若pod的cpu使用率超过80%,则创建pod,最少为10个,最多到15个
	(后续介绍完HELM以后,会与此对应)
$ kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
Ⅳ 更新镜像
# 通过命令,修改控制器创建的pod中创建容器的镜像(可以使用新的yaml文件,apply更新)
$ kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v1
[root@k8s-master01 3]# kubectl get pod -o wide |tail -n1 		#找一个正常运行的pod,访问查看版本
nginx-deployment-5c478875d8-x92zf   1/1     Running   0          78s    172.100.2.68   k8s-node02   <none>           <none>
[root@k8s-master01 3]# curl 172.100.2.68
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>


#修改镜像版本
[root@k8s-master01 3]# kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v3 --record

[root@k8s-master01 3]# kubectl get pod -o wide |tail -n1		#找一个正常运行的pod,访问查看版本
nginx-deployment-68bbd86499-zxsvz   1/1     Running   0          53s   172.100.1.79   k8s-node01   <none>           <none>
[root@k8s-master01 3]# curl 172.100.1.79
Hello MyApp | Version: v3 | <a href="hostname.html">Pod Name</a>


#查看RS,有两个RS,验证了deployment控制器管理pod的机制
[root@k8s-master01 3]# kubectl get rs 
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5c478875d8   0         0         0       4m30s
nginx-deployment-68bbd86499   10        10        10      2m2s

[root@k8s-master01 3]# kubectl get rs nginx-deployment-5c478875d8 -o yaml |grep image
      - image: wangyanglinux/myapp:v2
        imagePullPolicy: IfNotPresent
[root@k8s-master01 3]# kubectl get rs nginx-deployment-68bbd86499 -o yaml |grep image
    kubernetes.io/change-cause: kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v3
      - image: wangyanglinux/myapp:v3
        imagePullPolicy: IfNotPresent
Ⅴ 回滚

​ 官方准备的命令(可以使用不同yaml实现回滚)

# 回退到上一个deployment控制器的版本
$ kubectl rellout undo deployment/nginx-deployment
#回退到上一个版本,睡眠一秒,然后查看RS变化过程(验证了回滚机制)
[root@k8s-master01 3]# kubectl rollout undo deployment/nginx-deployment;sleep 1 ;kubectl get rs
deployment.extensions/nginx-deployment rolled back
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5c478875d8   2         2         0       11m
nginx-deployment-68bbd86499   9         9         9       8m56s

​ 注意:此处的回滚命令仅能回滚到上一个版本

​ 如果V1升级到V2,V2升级到V3。此时,第一次回滚为V2,第二次回滚为V3

Ⅵ 生产环境中的滚动更新、回滚(一般不用的方法)
# 监控滚动状态,成功的返回码为0,可以通过返回码确认滚动是否成功
$ kubectl rollout status deployments nginx-deployment

# 查看滚动的历史记录
$  kubectl rollout history deployment/nginx-deployment

​ 详细滚动升级,并查看历史更新记录:

[root@k8s-master01 3]# kubectl apply -f 8.deployment.yaml --record

[root@k8s-master01 3]# kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v2 --record

[root@k8s-master01 3]# kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v3 --record

[root@k8s-master01 3]# kubectl rollout history deployment/nginx-deployment
deployment.extensions/nginx-deployment 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=8.deployment.yaml --record=true
2         kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v2 --record=true
3         kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v3 --record=true

​ 使用命令滚动升级的总结:(需要每次操作都加 --record选项)

​ 1、若更新deployment版本信息时,没有加 --record,则不会记录到历史中

​ 2、若需要记录到历史中,需要加 --record

​ 3、若之前加入了 --record,而后有一次未加,则会使用上一次的操作信息

# 指定版本回滚,指定回滚到1版本(可以通过 kubectl rollout history 查看每一个对应的版本)
$ kubectl rollout undo deployment/nginx-deployment --to-revision=1

[root@k8s-master01 3]# kubectl rollout undo deployment/nginx-deployment --to-revision=1

#验证指定回滚到1版本
[root@k8s-master01 3]# kubectl rollout status deployment nginx-deployment
[root@k8s-master01 3]# kubectl get pod -o wide |tail -n1
nginx-deployment-7c678675fc-rwtgz   1/1     Running   0          29s   172.100.2.92    k8s-node02   <none>           <none>
[root@k8s-master01 3]# curl 172.100.2.92
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
Ⅶ 暂停、恢复更新
# 核心命令
$ kubectl rollout pause deployment/nginx-deployment		#暂停更新
$ kubectl rollout resume deployment/nginx-deployment		#回复更新

创建一个svc,访问集群ip更观察到所有pod的负载,写一个循环查看

image-20230118222824461

暂停更新:

# 更新版本后,马上暂停更新
[root@k8s-master01 3]# kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v2 && kubectl rollout pause deployment/nginx-deployment

[root@k8s-master01 3]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-5c478875d8-9h6jv   1/1     Running   0          30s
nginx-deployment-5c478875d8-lzgx6   1/1     Running   0          30s
nginx-deployment-7c678675fc-nqrzj   1/1     Running   0          13m
nginx-deployment-7c678675fc-rwtgz   1/1     Running   0          13m

​ 发现多出一个有四个pod,两个V2,两个V1。

​ 因为执行更改命令后:控制器创建了一个V2版,再在删除一个旧版的同时,创建一个新版

image-20230118223021263

回复更新:

[root@k8s-master01 3]# kubectl rollout resume deployment/nginx-deployment

3、生产环境中的滚动更新、回滚(常用)

直接根据不同的yaml文件,kubectl apply 实现变化

​ 拓展:清理policy(不需要保留deployment控制器创建的每一个RS版本,降低了ETCD存储压力)

​ 让版本变化时,不保留RS,降低了ETCD的存储压力

​ deployment.spec.revisionHistoryLimit:0

#使用不同yaml,实现控制器变化,且能用文件的形式保留变化
[root@k8s-master01 3]# mkdir new
[root@k8s-master01 3]# cp -a 8.deployment.yaml new/deployment.yaml
[root@k8s-master01 3]# cd new/
[root@k8s-master01 new]# ls
deployment.yaml
[root@k8s-master01 new]# kubectl apply -f deployment.yaml 

#扩容
[root@k8s-master01 new]# cp -a deployment.yaml deployment-scale10.yaml 
[root@k8s-master01 new]# vim deployment-scale10.yaml 
[root@k8s-master01 new]# grep "replicas" deployment-scale10.yaml 
  replicas: 10
[root@k8s-master01 new]# kubectl apply -f deployment-scale10.yaml 

#升级版本
[root@k8s-master01 new]# cp -a deployment-scale10.yaml deployment-toversionv2.yaml
[root@k8s-master01 new]# vim deployment-toversionv2.yaml 
[root@k8s-master01 new]# grep "image" deployment-toversionv2.yaml 
        image: wangyanglinux/myapp:v2
[root@k8s-master01 new]# kubectl apply -f deployment-toversionv2.yaml 

#回滚
[root@k8s-master01 new]# 
[root@k8s-master01 new]# ll
总用量 12
-rw-r--r-- 1 root root 338 1月  18 22:57 deployment-scale10.yaml
-rw-r--r-- 1 root root 338 1月  18 22:58 deployment-toversionv2.yaml
-rw-r--r-- 1 root root 337 1月  18 22:06 deployment.yaml
[root@k8s-master01 new]# kubectl apply -f deployment-scale10.yaml 
[root@k8s-master01 new]# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-5c478875d8   0         0         0       8m51s
nginx-deployment-7c678675fc   10        10        10      11m



# 清理policy
	spec.revisionHistoryLimit 项来指定 deployment 最多保留多少 revision 历史记录
	默认的会保留所有的 revision;如果将该项设置为0,Deployment 就不允许回退了
# 再每一个yaml文件中,对控制器的期望加入一项 revisionHistoryLimit: 0
[root@k8s-master01 new]# vim deployment.yaml 
[root@k8s-master01 new]# grep "revision" deployment.yaml
  revisionHistoryLimit: 0
[root@k8s-master01 new]# vim deployment-scale10.yaml 
[root@k8s-master01 new]# grep "revision" deployment-scale10.yaml 
  revisionHistoryLimit: 0
[root@k8s-master01 new]# vim deployment-toversionv2.yaml 
[root@k8s-master01 new]# grep "revision" deployment-toversionv2.yaml
  revisionHistoryLimit: 0

#进行扩容、更新、回滚
[root@k8s-master01 new]# kubectl apply -f deployment.yaml 
[root@k8s-master01 new]# kubectl apply -f deployment-scale10.yaml 
[root@k8s-master01 new]# kubectl apply -f deployment-toversionv2.yaml 
[root@k8s-master01 new]# kubectl apply -f deployment-scale10.yaml

#执行完毕以后,没有保留多余的rs
[root@k8s-master01 new]# kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-7c678675fc   10        10        10      18s

4、开发环境中,一般不会保留RS

​ 直接通过 kubectl edit 更改即可

5、deployment 更新策略

​ 更新时,需要比期望副本数量多或者少的副本数量,实现滚动式更新

​ 可以根据参数决定:更新时,允许多指定几个,少指定几个

​ 未来的K8S中,将从 1-1 变成25%-25%

更新策略声明:

kubectl explain deploy.spec.strategy.type

  • Recreate #重建(将整个集群都退出,再部署,过程中用户的访问是中断的)

  • rollingUpdate #滚动更新(默认更新策略)

    • maxSurge:指定超出副本数量个数,两种方式:1、指定数量;2、百分比
    • maxUnavailable:最多有几个不可用
kubectl patch deployment nginx-deployment -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":1,"maxUnavailable":0}}}}'
实验:更改deployment的更新策略

注意:若控制器中的期望中,不指定标签选择器,默认指定匹配后面的标签

​ 此处的更改更新时最多数量,结合更新暂停可实现金丝雀部署

#准备
[root@k8s-master01 ~]# mkdir 4
[root@k8s-master01 ~]# cd 4/
[root@k8s-master01 4]# cat /root/3/8.deployment.yaml > 1.deployment.yaml
[root@k8s-master01 4]# cat 1.deployment.yaml 
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: wangyanglinux/myapp:v1
        ports:
        - containerPort: 80


#删除所有控制器,根据 1.deployment.yaml 文件创建控制器
[root@k8s-master01 4]# kubectl apply -f 1.deployment.yaml 

[root@k8s-master01 4]# kubectl get pod,deployment
NAME                                    READY   STATUS    RESTARTS   AGE
pod/nginx-deployment-7c678675fc-hzsxq   1/1     Running   0          9s
pod/nginx-deployment-7c678675fc-s8bjk   1/1     Running   0          9s
pod/nginx-deployment-7c678675fc-tmgjp   1/1     Running   0          9s

NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/nginx-deployment   3/3     3            3           9s


#查询当前的控制器更新策略
[root@k8s-master01 4]# kubectl get deployment nginx-deployment -o yaml |egrep "maxSurge|maxUnavailable"
      maxSurge: 1
      maxUnavailable: 1


#更改更新策略
[root@k8s-master01 4]# kubectl get deployment -o yaml |egrep "maxSurge|maxUnavailable"
        maxSurge: 1
        maxUnavailable: 0

6、rollover(多个rollout并行)

​ 若现有100个V1版本,在实现更新到V2版本的时候,已经更新完成一半。此时又将版本更新到V3版。这时候,V2更新到V3,V1会直接更新到V3。

​ 原理图:

​ ![image-20230119200129233

4)更新策略 --- 金丝雀部署

滚动更新:

​ 删除其中一个旧版脱离集群,修改新版替代以后加入集群,再进行下一个服务器替换

​ 优点:在尽可能保证用户访问的前提下,实现更新

​ 缺点:若版本更新大,在短暂时间内,用户会出现访问反差

​ 总结:1.更新尽量更改底层的东西,对前端更改较少

​ 2.将一个用户绑定到指定的服务,进行访问

image-20230119174550789

蓝绿部署:

​ 搭建不同的负载集群,更新时直接切换集群

​ 优点:稳定性强

​ 缺点:需要更多的服务器数量

image-20230119175916322

金丝雀部署:

​ 先让一小部分实现升级(内测),一段时间测试没有问题以后,再全部升级

image-20230119180409194

实验1:deployment控制器---金丝雀部署(命令实现)

(deployment更新策略+更新暂停实现金丝雀部署)

在更新时,先让部分进行访问测试,若一段时间后没有问题,在恢复即可(即金丝雀部署)

#核心命令
$ kubectl set image deployment nginx-deployment nginx=wangyanglinux/myapp:v2 && kubectl rollout pause deployment nginx-deployment

$ kubectl rollout resume deployment nginx-deploymnet
1、实验详细:
# 第一个终端创建deployment控制器,创建svc方便集群访问
# 并写入循环访问
[root@k8s-master01 4]# pwd
/root/4
[root@k8s-master01 4]# vim 1.deployment.yaml 
[root@k8s-master01 4]# cat 1.deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 5
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: wangyanglinux/myapp:v1
        ports:
        - containerPort: 80
[root@k8s-master01 4]# kubectl apply -f 1.deployment.yaml 
deployment.extensions/nginx-deployment created
[root@k8s-master01 4]# kubectl create svc clusterip nginx --tcp=80:80
service/nginx created
[root@k8s-master01 4]# kubectl get deployment,svc
NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/nginx-deployment   5/5     5            5           27s

NAME                 TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1       <none>        443/TCP   9d
service/nginx        ClusterIP   10.109.178.32   <none>        80/TCP    8s
[root@k8s-master01 4]# while true;do curl 10.109.178.32 ;sleep 1;done



# 第二个终端更改deployment更新策略
			指定超出副本数量个数为3,最大不可用副本数为0
# 更新版本的同时,马上暂停更新,实现金丝雀部署
[root@k8s-master01 4]# kubectl patch deployment nginx-deployment -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge":3,"maxUnavailable":0}}}}'
[root@k8s-master01 4]# kubectl set image deployment nginx-deployment nginx=wangyanglinux/myapp:v2 && kubectl rollout pause deployment nginx-deployment
deployment.extensions/nginx-deployment image updated
deployment.extensions/nginx-deployment paused

2、测试验证

​ 查看循环的输出结果,查看pod数量

image-20230119190727015

​ pod数量也有8个,与循环输出的结果对应

image-20230119190846122

3、恢复更新

​ 若访问测试没有问题,则恢复更新

​ 若访问测试有问题,回滚即可 kubectl rollout undo

$ kubectl rollout resume deployment nginx-deployment

image-20230119191419821

实验2:deployment控制器---金丝雀部署(yaml文件实现)

原理图:

​ 利用svc匹配不同的标签,创建不同的deployment,实现金丝雀部署

image-20230119191806714

1、创建第一版deployment控制器和svc
[root@k8s-master01 4]# ls
1.deployment.yaml
[root@k8s-master01 4]# mkdir 2           
[root@k8s-master01 4]# cp -a /root/3/8.deployment.yaml deployment.yaml
[root@k8s-master01 4]# vim deployment.yaml 
[root@k8s-master01 4]# cat deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment-v1
spec:
  selector:
    matchLabels:
      app: nginx
      version: v1
  replicas: 10
  template:
    metadata:
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: wangyanglinux/myapp:v1
        ports:
        - containerPort: 80
[root@k8s-master01 4]# kubectl apply -f deployment.yaml 
deployment.extensions/nginx-deployment-v1 created
[root@k8s-master01 4]# kubectl create svc clusterip nginx --tcp=80:80
service/nginx created

[root@k8s-master01 4]# kubectl get svc,deployment
NAME                 TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   9d
service/nginx        ClusterIP   10.98.50.152   <none>        80/TCP    14s

NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/nginx-deployment-v1   10/10   10           10          30s

2、查询集群VIP,并写循环访问
[root@k8s-master01 4]# kubectl get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   9d
nginx        ClusterIP   10.98.50.152   <none>        80/TCP    107s
[root@k8s-master01 4]# while true;do curl 10.98.50.152;sleep 1;done

3、创建新的yaml文件,进行更新
[root@k8s-master01 4]# cp -a deployment.yaml deployment.yaml-v2
[root@k8s-master01 4]# vim deployment.yaml-v2 
[root@k8s-master01 4]# cat deployment.yaml-v2
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx-deployment-v2
spec:
  selector:
    matchLabels:
      app: nginx
      version: v2
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
        version: v2
    spec:
      containers:
      - name: nginx
        image: wangyanglinux/myapp:v2
        ports:
        - containerPort: 80

[root@k8s-master01 4]# kubectl apply -f deployment.yaml-v2 
deployment.extensions/nginx-deployment-v2 created
[root@k8s-master01 4]# kubectl get pod		#查看pod信息,发现新创建了两个pod,这两个pod即金丝雀

4、查看循环访问的结果

​ 发现有两个V2版,十个V1版,这两个V2版即为金丝雀

image-20230119193250565

​ 若后续发现测试版有问题,将第二个控制器删除即可

​ 若后续发现测试版没有问题,将第二个控制器副本数量,将第一个控制器副本数量调低最后删除即可

[root@k8s-master01 4]# kubectl scale deployment nginx-deployment-v2 --replicas=10 && kubectl scale deployment nginx-deployment-v1 --replicas=1 && sleep 1 && kubectl delete -f deployment.yaml

image-20230119193826234

三 DaemonSet 控制器

保证每个节点,有且仅有一个,此控制器管理的一个pod运行,且能实现动态调整

动态调整:当有节点加入时,自动为其创建pod;当有节点损坏时,自动回收pod

典型用法:

  • MFS等集群部署
  • 日志收集
  • 监控

实验:创建daemonset控制器

[root@k8s-master01 4]# mv deployment.yaml* 2/
[root@k8s-master01 4]# ls
1.deployment.yaml  2

[root@k8s-master01 4]# vim 3.daemonset.yaml
[root@k8s-master01 4]# cat 3.daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: daemonset-example
  labels:
    app: daemonset
spec:
  selector:
    matchLabels:
      name: daemonset-example
  template:
    metadata:
      labels:
        name: daemonset-example
    spec:
      containers:
      - name: daemonset-example
        image: wangyanglinux/myapp:v1
        
        
[root@k8s-master01 4]# kubectl apply -f 3.daemonset.yaml

#满足每一个节点,有且仅有daemonset控制器管理的一个pod
[root@k8s-master01 4]# kubectl get pod -o wide
NAME                      READY   STATUS    RESTARTS   AGE   IP              NODE         NOMINATED NODE   READINESS GATES
daemonset-example-dkfmj   1/1     Running   0          32s   172.100.2.163   k8s-node02   <none>           <none>
daemonset-example-jk2bq   1/1     Running   0          32s   172.100.1.169   k8s-node01   <none>           <none>

拓展1:K8S正常运行的条件

​ kube-system 所有的pod正常运行

拓展2:污点。让节点不运行pod

​ kube-proxy、calico组件就是通过daemonset控制器实现的

[root@k8s-master01 4]# kubectl get daemonset -n kube-system
NAME          DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE
calico-node   3         3         3       3            3           beta.kubernetes.io/os=linux   9d
kube-proxy    3         3         3       3            3           beta.kubernetes.io/os=linux   9d

​ master01节点中,有一个选项 master: Noschedule。导致自定义的damonset控制器不会在master节点中创建pod。

[root@k8s-master01 4]# kubectl describe node k8s-master01 |grep Taints
Taints:             node-role.kubernetes.io/master:NoSchedule

​ 而kube-proxy、calico组件能在master节点中创建pod,是因为容忍了污点

四 Job、cronJob

1)控制器分类:

守护进程类:一直运行
                RC:将当前的pod副本数目尽力保持与期望值一致
                RS:与RC概念相同,但是多了标签运算符
                Deployment:定义了一个声明式创建pod与RS的方法
                DaemonSet:保证每个节点有且仅运行一个pod,且能动态调整
批处理类:仅执行指定次数的任务
                Job:仅执行指定次数的任务
                cronJob:定时仅执行指定次数的任务

2)Job

Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束

特殊说明

  • spec.template格式同Pod

  • RestartPolicy仅支持Never或OnFailure

    ​ 不能用always。如果设置为always,pod的容器无论是否正常运行结束,都会重建容器。与Job控制器的执行指定次数运行机制,相违背

  • 单个Pod时,默认Pod成功运行后Job即结束

  • .spec.completions标志Job结束需要成功运行的Pod个数,默认为1

  • .spec.parallelism标志并行运行的Pod的个数,默认为1

    ​ 并行数默认为1:所有任务1个1个的完成,直到最后。比如:数据库备份

    ​ 并行数大于1:几个任务同时运行,任务之间不会发生冲突。比如:发送邮件、网页访问

  • spec.activeDeadlineSeconds标志失败Pod的重试最大时间,超过这个时间不会继续重试

实验:求 π 值

算法:马青公式

操作逻辑:

​ Ⅰ 拿到开发代码测试

​ Ⅱ 将源代码封装到镜像中

​ Ⅲ 将镜像推送到公司内网的镜像仓库

​ Ⅳ 编写控制器

​ Ⅴ 基于K8S运行

1、测试python代码运行
[root@k8s-master01 4]# mkdir 4
[root@k8s-master01 4]# cd 4/
[root@k8s-master01 4]# pwd
/root/4/4
[root@k8s-master01 4]# vim main.py
[root@k8s-master01 4]# cat main.py
# -*- coding: utf-8 -*-
from __future__ import division
# 导入时间模块
import time
# 计算当前时间
time1=time.time()
# 算法根据马青公式计算圆周率 #
number = 1000
# 多计算10位,防止尾数取舍的影响
number1 = number+10
# 算到小数点后number1位
b = 10**number1
# 求含4/5的首项
x1 = b*4//5
# 求含1/239的首项
x2 = b // -239
# 求第一大项
he = x1+x2
#设置下面循环的终点,即共计算n项
number *= 2
#循环初值=3,末值2n,步长=2
for i in xrange(3,number,2):
  # 求每个含1/5的项及符号
  x1 //= -25
  # 求每个含1/239的项及符号
  x2 //= -57121
  # 求两项之和
  x = (x1+x2) // i
  # 求总和
  he += x
# 求出π
pai = he*4
#舍掉后十位
pai //= 10**10
# 输出圆周率π的值
paistring=str(pai)
result=paistring[0]+str('.')+paistring[1:len(paistring)]
print result
time2=time.time()
print u'Total time:' + str(time2 - time1) + 's'

[root@k8s-master01 4]# python main.py
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989
Total time:0.00169897079468s

2、封装镜像
[root@k8s-master01 4]# vim Dockerfile 
[root@k8s-master01 4]# cat Dockerfile
FROM hub.c.163.com/public/python:2.7
ADD ./main.py /root
CMD /usr/bin/python /root/main.py

[root@k8s-master01 4]# docker build -t maqing:v1 .			#制作镜像


#将镜像导入到每一个节点(后续直接导入私有镜像仓库即可,每个节点如果需要镜像,直接从仓库获取)
[root@k8s-master01 4]# docker save -o maqing.tar maqing:v1
[root@k8s-master01 4]# scp maqing.tar root@n1:/root/

[root@k8s-master01 4]# scp maqing.tar root@n2:/root/

#进入node1节点导入镜像
[root@k8s-node01 ~]# docker load -i maqing.tar

#进入node2节点导入镜像
[root@k8s-node02 ~]# docker load -i maqing.tar
3、创建job控制器

​ 使用默认成功数量1,默认并行1,默认最大尝试个数6

[root@k8s-master01 4]# kubectl apply -f job.yaml 
job.batch/pi created
[root@k8s-master01 4]# kubectl get pod 
NAME       READY   STATUS      RESTARTS   AGE
pi-8spbf   0/1     Completed   0          4s
[root@k8s-master01 4]# kubectl get job
NAME   COMPLETIONS   DURATION   AGE
pi     1/1           2s         8s

​ 发现job控制器创建的pod,运行完成以后即退出

4、根据容器名查看运行结果
[root@k8s-master01 4]# kubectl logs pi-8spbf
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989
Total time:0.0015549659729s
5、测试10个成功数量,并行1
[root@k8s-master01 4]# cp -a job.yaml job.yaml-2
[root@k8s-master01 4]# vim job.yaml-2
[root@k8s-master01 4]# cat job.yaml-2
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  backoffLimit: 6
  completions: 10
  parallelism: 1
  template:
    metadata:
      name: pi
    spec:
      containers:
      - name: pi
        image: maqing:v1
      restartPolicy: Never
[root@k8s-master01 4]# kubectl delete job --all

[root@k8s-master01 4]# kubectl apply -f job.yaml-2 


[root@k8s-master01 4]# kubectl get pod |grep Completed |wc -l
10
[root@k8s-master01 4]# kubectl get job
NAME   COMPLETIONS   DURATION   AGE
pi     10/10         11s        53s

6、测试10个成功数量,并行3
[root@k8s-master01 4]# cp -a job.yaml-2 job.yaml-3
[root@k8s-master01 4]# vim job.yaml-3
[root@k8s-master01 4]# cat job.yaml-3
apiVersion: batch/v1
kind: Job
metadata:
  name: pi
spec:
  backoffLimit: 6
  completions: 10
  parallelism: 3
  template:
    metadata:
      name: pi
    spec:
      containers:
      - name: pi
        image: maqing:v1
      restartPolicy: Never
[root@k8s-master01 4]# kubectl delete job --all

#创建job控制器后,马上查看pod,发现并行了3个
[root@k8s-master01 4]# kubectl apply -f job.yaml-3 ;kubectl get pod
job.batch/pi created
NAME       READY   STATUS              RESTARTS   AGE
pi-p548j   0/1     ContainerCreating   0          0s
pi-whtpv   0/1     ContainerCreating   0          0s
pi-z7d9f   0/1     ContainerCreating   0          0s

[root@k8s-master01 4]# kubectl get job
NAME   COMPLETIONS   DURATION   AGE
pi     10/10         5s         7s

7、测试pod最大重试时间

验证job控制器管理的pod,运行完成后,返回码为0,才能算作成功

[root@k8s-master01 4]# tar -xf randexit-job.gz 
[root@k8s-master01 4]# ls
6  Dockerfile  job.yaml  job.yaml-2  job.yaml-3  main.py  maqing.tar  randexit-job.gz
[root@k8s-master01 4]# cd 6/
[root@k8s-master01 6]# ls
job1.yaml  job.yaml

[root@k8s-master01 6]# cat job.yaml 			#每次创建的容器,运行完,返回码定义为1
apiVersion: batch/v1
kind: Job
metadata:
  name: rand
spec:
  template:
    metadata:
      name: rand
    spec:
      containers:
      - name: rand
        image: wangyanglinux/tools:randexitv1
        args: ["--exitcode=1"]
      restartPolicy: Never
      
[root@k8s-master01 6]# kubectl apply -f job.yaml 

#等待一段时间后,查看job控制器成功的pod依旧为0
[root@k8s-master01 6]# kubectl get job
NAME   COMPLETIONS   DURATION   AGE
rand   0/1           2m38s      2m38s

#pod返回码一直为1,所以标记错误
[root@k8s-master01 6]# kubectl get pod 
NAME         READY   STATUS   RESTARTS   AGE
rand-4rnmt   0/1     Error    0          2m14s
rand-b99b4   0/1     Error    0          2m54s
rand-hstrm   0/1     Error    0          3m11s
rand-qfz6v   0/1     Error    0          54s
rand-t5s4t   0/1     Error    0          3m4s
8、利用随机返回码程序,指定成功数量

​ 会发现job控制器管理的pod,会出现失败的状态,但不会记录成功数

[root@k8s-master01 6]# pwd
/root/4/4/6
[root@k8s-master01 6]# vim job1.yaml 
[root@k8s-master01 6]# cat job1.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: rand
spec:
  completions: 5
  template:
    metadata:
      name: rand
    spec:
      containers:
      - name: rand
        image: wangyanglinux/tools:randexitv1
      restartPolicy: Never
[root@k8s-master01 6]# kubectl apply -f job1.yaml 

# 一段时间后查看pod状态、查看job状态
# 会发现job控制器管理的pod,会出现失败的状态,但不会记录成功数
[root@k8s-master01 6]# kubectl get pod
NAME         READY   STATUS      RESTARTS   AGE
rand-84pkl   0/1     Error       0          27s
rand-dj7rt   0/1     Error       0          17s
rand-f8sl9   0/1     Completed   0          62s
rand-kplmf   0/1     Error       0          34s
rand-lhwzl   0/1     Completed   0          55s
rand-zfd9n   0/1     Completed   0          48s
rand-zjbh5   0/1     Completed   0          41s
[root@k8s-master01 6]# kubectl get job
NAME   COMPLETIONS   DURATION   AGE
rand   4/5           65s        65s

3)cronJob

对比 Job 与 cronjob:

​ Job 控制器直接创建管理 pod

​ cronJob 控制器 Job,再由 Job 创建管理pod

Cron Job 管理基于时间的 Job,即:

  • 在给定时间点只运行一次
  • 周期性地在给定时间点运行

使用条件:当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)

典型的用法如下所示:

  • 在给定的时间点调度 Job 运行
  • 创建周期性运行的 Job,例如:数据库备份、发送邮件

CronJob Spec (与 Job 的一样)

  • spec.template 格式同 Pod
  • RestartPolicy仅支持Never或OnFailure
  • 单个Pod时,默认Pod成功运行后Job即结束
  • .spec.completions标志Job结束需要成功运行的Pod个数,默认为1
  • .spec.parallelism标志并行运行的Pod的个数,默认为1
  • spec.activeDeadlineSeconds标志失败Pod的重试最大时间,超过这个时间不会继续重试

CronJob Spec (与 Job 差异的)

  • .spec.schedule

    ​ 调度,必需字段,指定任务运行周期,格式同 Cron

  • .spec.jobTemplate

    ​ Job 模板,必需字段,指定需要运行的任务,格式同 Job

  • .spec.startingDeadlineSeconds

    ​ 启动 Job 的期限(秒级别),该字段是可选的。

    ​ 若在指定时间执行任务,未完成,超过这个时间仍未完成,则标记失败

  • .spec.concurrencyPolicy

    ​ 并发策略,该字段也是可选的

    ​ 它指定了如何处理被 Cron Job 创建的 Job 的并发执行。只允许指定下面策略中的一种:

    • Allow(默认):允许并发运行 Job
    • Forbid:禁止并发运行,如果前一个还没有完成,则直接跳过下一个
    • Replace:取消当前正在运行的 Job,用一个新的来替换

    注意,当前策略只能应用于同一个 Cron Job 创建的 Job。如果存在多个 Cron Job,它们创建的 Job 之间总是允许并发运行。

  • .spec.suspend

    ​ 挂起,该字段也是可选的

    ​ 如果设置为 true,后续所有执行都会被挂起。它对已经开始执行的 Job 不起作用。默认值为 false

  • .spec.successfulJobsHistoryLimit.spec.failedJobsHistoryLimit

    ​ 成功的job历史限制、失败的job历史限制。可选字段

    ​ 它们指定了可以保留多少完成和失败的 Job

    ​ 默认情况下,它们分别设置为 31。若设置限制的值为 0,相关类型的 Job 完成后将不会被保留。

CrondJob 本身的一些限制

创建 Job 操作应该是 幂等的()

实验:创建cronjob控制器

1、根据yaml文件创建cronjob控制器

​ 每分钟创建一个job,这个job再去创建运行一个pod

​ **注意:**此处,在创建完成cronjob以后,第一次创建job的时间是在一分钟内的随机

​ 但是往后cronjob再创建job,其中的间隔为1分钟

[root@k8s-master01 4]# pwd
/root/4
[root@k8s-master01 4]# vim cronjob.yaml 
[root@k8s-master01 4]# cat cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      completions: 1
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.35.0
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
[root@k8s-master01 4]# kubectl apply -f cronjob.yaml

​ 查看cronjob、job、pod信息

# cronjob未处在挂起状态
[root@k8s-master01 4]# kubectl get cronjob
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   False     0        64s             3m28s


# job 、pod 保留的信息都为默认三条
# 也可以通过修改yaml文件中的选项进行数量修改
        .spec.successfulJobsHistoryLimit		#成功的job历史保留限制
        .spec.failedJobsHistoryLimit			#失败的job历史保留限制
[root@k8s-master01 4]# kubectl get job
NAME               COMPLETIONS   DURATION   AGE
hello-1674141840   1/1           1s         2m30s
hello-1674141900   1/1           1s         90s
hello-1674141960   1/1           1s         30s
[root@k8s-master01 4]# kubectl get pod 
NAME                     READY   STATUS      RESTARTS   AGE
hello-1674141840-6vn7r   0/1     Completed   0          2m33s
hello-1674141900-trqgj   0/1     Completed   0          93s
hello-1674141960-h6dts   0/1     Completed   0          33s


# 每一个pod创建间隔一分钟
[root@k8s-master01 4]# kubectl logs hello-1674141900-trqgj
Thu Jan 19 15:25:06 UTC 2023
Hello from the Kubernetes cluster
[root@k8s-master01 4]# kubectl logs hello-1674141960-h6dts
Thu Jan 19 15:26:06 UTC 2023
Hello from the Kubernetes cluster
2、更新每个job创建的pod数为3

​ 创建完成以后,等待cronjob创建job,job再去创建pod运行。此时发现运行了三个pod

[root@k8s-master01 4]# cp -a cronjob.yaml cronjob.yaml-2
[root@k8s-master01 4]# vim cronjob.yaml-2
[root@k8s-master01 4]# cat cronjob.yaml-2
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      completions: 3
      template:
        spec:
          containers:
          - name: hello
            image: busybox:1.35.0
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure
[root@k8s-master01 4]# kubectl delete cronjob --all

[root@k8s-master01 4]# kubectl apply -f cronjob.yaml-2 

[root@k8s-master01 4]# kubectl get cronjob,job,pod
NAME                  SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/hello   */1 * * * *   False     0        17s             67s

NAME                         COMPLETIONS   DURATION   AGE
job.batch/hello-1674142260   3/3           4s         11s

NAME                         READY   STATUS      RESTARTS   AGE
pod/hello-1674142260-2f4pq   0/1     Completed   0          11s
pod/hello-1674142260-h7csz   0/1     Completed   0          9s
pod/hello-1674142260-k44lr   0/1     Completed   0          8s

3、挂起 cronjob

​ 采用kubectl edit cronjob更改控制器。

​ 注意:更改具体选项时,建议同时也将 annotations选项也对应修改(如果有的话)

$ kubectl edit cronjob hello

image-20230119233527413

等待一段时间后,会发现:没有新的job创建,cronjob被挂起

# cronjob最新的一次创建job时间,超过一分钟
[root@k8s-master01 4]# kubectl get cronjob
NAME    SCHEDULE      SUSPEND   ACTIVE   LAST SCHEDULE   AGE
hello   */1 * * * *   True      0        2m54s           7m44s

五 StatefulSet

针对有状态服务部署的控制器(后续会和这里对应)

拓展1:有、无状态服务

​ 有状态服务:(需要数据持久化)

​ 当脱离运行环境一段时间后,回来无法正常运行。比如:数据库服务

​ 无状态服务:(不需要数据持久化)

​ 当脱离运行环境一段时间后,回来仍然能正常运行。比如:有后台存储的 web服务

拓展2:中心、去中心化服务

​ 中心化服务:由一个中心提供、管理服务

​ 去中心化服务:每一个点都可以是提供、管理服务

StatefulSet 作为 Controller 为 Pod 提供唯一的标识。它可以保证部署和 scale 的顺序

StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的网络标志,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
  • 有序收缩,有序删除(即从N-1到0)

六 HPA

元数据信息。能根据当前的负载量,进行横向扩容缩容(与后续的资源监控对应)

应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让 service 中的Pod个数自动调整呢?这就有赖于 HPA (Horizontal Pod Autoscaling)了,顾名思义,使 Pod 水平自动缩放