k8s系列五——资源控制器
控制器的必要性
自主式Pod
对象由调度器调度到目标工作节点后即由相应节点上的kubelet
负责监控其容器的存活状态,容器主进程崩溃后,kubelet
能够自动重启相应的容器。但对出现非主进程崩溃类的容器错误却无从感知,这便依赖于pod
资源对象定义的存活探测,以便kubelet
能够探知到此类故障。但若pod
被删除或者工作节点自身发生故障(工作节点上都有kubelet
,kubelet
不可用,因此其健康状态便无法保证),则便需要控制器来处理相应的容器重启和配置。
什么是控制器
Kubernetes 中内建了很多 controller(控制器),这些相当于一个状态机,用来控制 Pod 的具体状态和行为
控制器类型
-
ReplicationController:用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来替代;而如果异常多出来的容器也会自动回收;
-
**ReplicaSet:**代用户创建指定数量的
pod
副本数量,确保pod
副本数量符合预期状态,并且支持滚动式自动扩容和缩容功能 -
Deployment:工作在
ReplicaSet
之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。定义 Deployment 来创建 Pod 和 ReplicaSet
滚动升级和回滚应用
扩容和缩容
暂停和继续 Deployment
-
DaemonSet:用于确保集群中的每一个节点只运行特定的
pod
副本,常用于实现系统级后台任务。比如ELK
服务DaemonSet 确保全部(或者一些,根据调度策略或者污点定义)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod使用 DaemonSet 的一些典型用法:
运行集群存储 daemon,例如在每个 Node 上运行 glusterd 、 ceph
在每个 Node 上运行日志收集 daemon,例如 fluentd 、 logstash
在每个 Node 上运行监控 daemon,例如 zabbix agent、Prometheus Node Exporter、 collectd 、Datadog 代理、New Relic 代理,或 Ganglia gmond -
**StatefulSet:**管理有状态应用
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) -
**Job:**只要完成就立即退出,不需要重启或重建
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束(跟linux crontab比有纠错功能)倾向脚本运行机制
-
**CronJob:**周期性任务控制,不需要持续后台运行
使用前提条件: 当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)。对于先前版本的集群,版本 <1.8,启动 API Server时,通过传递选项 --runtime-config=batch/v2alpha1=true 可以开启 batch/v2alpha1API
-
Horizontal Pod Autoscaling :(可以理解为并不是一个控制器,而是一个控制器的附属品,以其他控制器作为模板)
应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让service中的Pod个数自动调整呢?这就有赖于Horizontal Pod Autoscaling了,顾名思义,使Pod水平自动缩放
ReplicaSet控制器
在新版本的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 。ReplicaSet 跟ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector(标签);
ReplicaSet
能够实现以下功能:
-
确保Pod资源对象的数量精确反映期望值:
ReplicaSet
需要确保由其控制运行的Pod副本数量精确吻合配置中定义的期望值,否则就会自动补足所缺或终止所余。ReplicaSet
控制器资源启动后会查找集群中匹配器标签选择器的Pod
资源对象,当前活动对象的数量与期望的数量不吻合时,多则删除,少则通过Pod
模板创建以补足。简而言之就是通过标签选择器来控制副本数量的
-
**确保Pod健康运行:**探测到由其管控的
Pod
对象因其所在的工作节点故障而不可用时,自动请求由调度器于其他工作节点创建缺失的Pod
副本。 -
**弹性伸缩:**可通过
ReplicaSet
控制器动态扩容或者缩容Pod
资源对象的数量。必要时还可以通过HPA
控制器实现Pod
资源规模的自动伸缩。
创建ReplicaSet
核心字段
spec字段一般嵌套使用以下几个属性字段:
replicas <integer>:指定期望的Pod对象副本数量
selector <Object>:当前控制器匹配Pod对象副本的标签选择器,支持matchLabels和matchExpressions两种匹配机制
template <Object>:用于定义Pod时的Pod资源信息
minReadySeconds <integer>:用于定义Pod启动后多长时间为可用状态,默认为0秒
ReplicaSet示例
#(1)命令行查看ReplicaSet清单定义规则
[root@k8s-master ~]# kubectl explain rs
[root@k8s-master ~]# kubectl explain rs.spec
[root@k8s-master ~]# kubectl explain rs.spec.template
#(2)创建ReplicaSet示例
[root@k8s-master ~]# vim manfests/rs-demo.yaml
apiVersion: apps/v1 #api版本定义
kind: ReplicaSet #定义资源类型为ReplicaSet
metadata: #元数据定义
name: myapp
namespace: default
spec: #ReplicaSet的规格定义
replicas: 2 #定义副本数量为2个
selector: #标签选择器,定义匹配Pod的标签
matchLabels:
app: myapp
release: canary
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: myapp-pod #自定义Pod的名称
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: myapp
release: canary
spec: #Pod的规格定义
containers: #容器定义
- name: myapp-containers #容器名称
image: ikubernetes/myapp:v1 #容器镜像
imagePullPolicy: IfNotPresent #拉取镜像的规则
ports: #暴露端口
- name: http #端口名称
containerPort: 80
#(3)创建ReplicaSet定义的Pod
[root@k8s-master ~]# kubectl apply -f manfests/rs-demo.yaml
replicaset.apps/myapp created
[root@k8s-master ~]# kubectl get rs #查看创建的ReplicaSet控制器
NAME DESIRED CURRENT READY AGE
myapp 2 2 2 3m23s
[root@k8s-master ~]# kubectl get pods #通过查看pod可以看出pod命令是规则是前面是replicaset控制器的名称加随机生成的字符串
NAME READY STATUS RESTARTS AGE
myapp-bln4v 1/1 Running 0 6s
myapp-bxpzt 1/1 Running 0 6s
#(4)修改Pod的副本数量
[root@k8s-master ~]# kubectl edit rs myapp
replicas: 4
[root@k8s-master ~]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
myapp 4 4 4 2m50s myapp-containers ikubernetes/myapp:v2 app=myapp,release=canary
[root@k8s-master ~]# kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-8hkcr 1/1 Running 0 2m2s app=myapp,release=canary
myapp-bln4v 1/1 Running 0 3m40s app=myapp,release=canary
myapp-bxpzt 1/1 Running 0 3m40s app=myapp,release=canary
myapp-ql2wk 1/1 Running 0 2m2s app=myapp,release=canary
# (5)删除所有pod之后,rs又会重新拉起
[root@k8s-master ~]# kubectl delete pod --all
pod "myapp-8hkcr" deleted
pod "myapp-bln4v" deleted
pod "myapp-bxpzt" deleted
pod "myapp-ql2wk" deleted
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE LABELS
myapp-8hkcr 1/1 Running 0 2m2s app=myapp,release=canary
myapp-bln4v 1/1 Running 0 3m40s app=myapp,release=canary
myapp-bxpzt 1/1 Running 0 3m40s app=myapp,release=canary
myapp-ql2wk 1/1 Running 0 2m2s app=myapp,release=canary
# (6) 更改其中一个pod标签后,rs又会拉起一个,保证pod数量与期望值一致
[root@k8s-master ~]# kubectl label pod myapp-8hkcr app=myapp22 --overwrite=true
pod/myapp-8hkcr labeled
[root@k8s-master ~]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-8hkcr 1/1 Running 0 2m2s app=myapp22,release=canary
myapp-bln4v 1/1 Running 0 3m40s app=myapp,release=canary
myapp-bxpzt 1/1 Running 0 3m40s app=myapp,release=canary
myapp-ql2wk 1/1 Running 0 2m2s app=myapp,release=canary
myapp-qwe2 1/1 Running 0 2m2s app=myapp,release=canary
# (7)当我们删除rs后,只会删除标签为myapp的pod,myapp22标签的pod则还存在
[root@k8s-master ~]# kubectl delete rs -all
[root@k8s-master ~]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
myapp-8hkcr 1/1 Running 0 2m2s app=myapp22,release=canary
myapp-bln4v 1/1 Terminating 0 3m40s app=myapp,release=canary
myapp-bxpzt 1/1 Terminating 0 3m40s app=myapp,release=canary
myapp-ql2wk 1/1 Terminating 0 2m2s app=myapp,release=canary
myapp-qwe2 1/1 Terminating 0 2m2s app=myapp,release=canary
更新ReplicaSet控制器
修改Pod模板:升级应用
修改上面创建的replicaset
示例文件,将镜像ikubernetes/myapp:v1
改为v2
版本
[root@k8s-master ~]# vim manfests/rs-demo.yaml
spec: #Pod的规格定义
containers: #容器定义
- name: myapp-containers #容器名称
image: ikubernetes/myapp:v2 #容器镜像
imagePullPolicy: IfNotPresent #拉取镜像的规则
ports: #暴露端口
- name: http #端口名称
containerPort: 80
[root@k8s-master ~]# kubectl apply -f manfests/rs-demo.yaml #执行apply让其重载
[root@k8s-master ~]# kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
Name Image
myapp-bln4v ikubernetes/myapp:v1
myapp-bxpzt ikubernetes/myapp:v1
#说明:这里虽然重载了,但是已有的pod所使用的镜像仍然是v1版本的,只是新建pod时才会使用v2版本,这里测试先手动删除已有的pod。
[root@k8s-master ~]# kubectl delete pods -l app=myapp #删除标签app=myapp的pod资源
pod "myapp-bln4v" deleted
pod "myapp-bxpzt" deleted
[root@k8s-master ~]# kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image #再次查看通过ReplicaSet新建的pod资源对象。镜像已使用v2版本
Name Image
myapp-mdn8j ikubernetes/myapp:v2
myapp-v5bgr ikubernetes/myapp:v2
扩容和缩容
可以直接通过vim
编辑清单文件修改replicas
字段,也可以通过kubect edit
命令去编辑。kubectl
还提供了一个专用的子命令scale
用于实现应用规模的伸缩,支持从资源清单文件中获取新的目标副本数量,也可以直接在命令行通过“--replicas”
选项进行读取。
[root@k8s-master ~]# kubectl get rs #查看ReplicaSet
NAME DESIRED CURRENT READY AGE
myapp 2 2 2 154m
[root@k8s-master ~]# kubectl get pods #查看Pod
NAME READY STATUS RESTARTS AGE
myapp-mdn8j 1/1 Running 0 5m26s
myapp-v5bgr 1/1 Running 0 5m26s
#扩容
[root@k8s-master ~]# kubectl scale replicasets myapp --replicas=5 #将上面的Deployments控制器myapp的Pod副本数量提升为5个
replicaset.extensions/myapp scaled
[root@k8s-master ~]# kubectl get rs #查看ReplicaSet
NAME DESIRED CURRENT READY AGE
myapp 5 5 5 156m
[root@k8s-master ~]# kubectl get pods #查看Pod
NAME READY STATUS RESTARTS AGE
myapp-lrrp8 1/1 Running 0 8s
myapp-mbqf8 1/1 Running 0 8s
myapp-mdn8j 1/1 Running 0 6m48s
myapp-ttmf5 1/1 Running 0 8s
myapp-v5bgr 1/1 Running 0 6m48s
#收缩
[root@k8s-master ~]# kubectl scale replicasets myapp --replicas=3
replicaset.extensions/myapp scaled
[root@k8s-master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp 3 3 3 159m
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-mdn8j 1/1 Running 0 10m
myapp-ttmf5 1/1 Running 0 3m48s
myapp-v5bgr 1/1 Running 0 10m
删除ReplicaSet控制器资源
使用Kubectl delete
命令删除ReplicaSet
对象时默认会一并删除其管控的各Pod
对象,有时,考虑到这些Pod
资源未必由其创建,或者即便由其创建也并非自身的组成部分,这时候可以添加“--cascade=false”
选项,取消级联关系。
[root@k8s-master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
myapp 3 3 3 162m
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-mdn8j 1/1 Running 0 12m
myapp-ttmf5 1/1 Running 0 6m18s
myapp-v5bgr 1/1 Running 0 12m
[root@k8s-master ~]# kubectl delete replicasets myapp --cascade=false
replicaset.extensions "myapp" deleted
[root@k8s-master ~]# kubectl get rs
No resources found.
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-mdn8j 1/1 Running 0 13m
myapp-ttmf5 1/1 Running 0 7m
myapp-v5bgr 1/1 Running 0 13m
#通过上面的示例可以看出,添加--cascade=false参数后再删除ReplicaSet资源对象时并没有将其管控的Pod资源对象一并删除。
Deployment控制器
Deployment
(简写为deploy
)是kubernetes
控制器的又一种实现,它构建于ReplicaSet
控制器之上,可为Pod
和ReplicaSet
资源提供声明式更新。
Deployment
控制器资源的主要职责是为了保证Pod
资源的健康运行,其大部分功能均可通过调用ReplicaSet
实现,同时还增添部分特性。
-
滚动升级和回滚应用
升级方案:
一是
Recreate
,即重建更新机制,全面停止、删除旧有的Pod
后用新版本替代;另一个是
RollingUpdate
,即滚动升级机制,逐步替换旧有的Pod
至新的版本。回滚:
升级操作完成后发现问题时,支持使用回滚机制将应用返回到前一个或由用户指定的历史记录中的版本上
-
暂停和继续Deployment
对于每一次升级,都能够随时暂停和启动。
创建Deployment
#(1)命令行查看ReplicaSet清单定义规则
[root@k8s-master ~]# kubectl explain deployment
[root@k8s-master ~]# kubectl explain deployment.spec
[root@k8s-master ~]# kubectl explain deployment.spec.template
#(2)创建Deployment示例
[root@k8s-master ~]# vim manfests/deploy-demo.yaml
apiVersion: apps/v1 #api版本定义
kind: Deployment #定义资源类型为Deploymant
metadata: #元数据定义
name: deploy-demo #deployment控制器名称
namespace: default #名称空间
spec: #deployment控制器的规格定义
replicas: 2 #定义副本数量为2个
selector: #标签选择器,定义匹配Pod的标签
matchLabels:
app: deploy-app
release: canary
template: #Pod的模板定义
metadata: #Pod的元数据定义
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: deploy-app
release: canary
spec: #Pod的规格定义
containers: #容器定义
- name: myapp #容器名称
image: ikubernetes/myapp:v1 #容器镜像
ports: #暴露端口
- name: http #端口名称
containerPort: 80
#(3)创建Deployment对象
[root@k8s-master ~]# kubectl apply -f manfests/deploy-demo.yaml
deployment.apps/deploy-demo created
#(4)查看资源对象
[root@k8s-master ~]# kubectl get deployment #查看Deployment资源对象
NAME READY UP-TO-DATE AVAILABLE AGE
deploy-demo 2/2 2 2 10s
[root@k8s-master ~]# kubectl get replicaset #查看ReplicaSet资源对象
NAME DESIRED CURRENT READY AGE
deploy-demo-78c84d4449 2 2 2 20s
[root@k8s-master ~]# kubectl get pods #查看Pod资源对象
NAME READY STATUS RESTARTS AGE
deploy-demo-78c84d4449-22btc 1/1 Running 0 23s
deploy-demo-78c84d4449-5fn2k 1/1 Running 0 23s
---
# 说明:
#通过查看资源对象可以看出,Deployment会自动创建相关的ReplicaSet控制器资源,并以"[DEPLOYMENT-name]-[POD-TEMPLATE-HASH-VALUE]"格式为其命名,其中的hash值由Deployment自动生成。而Pod名则是以ReplicaSet控制器的名称为前缀,后跟5位随机字符。
更新策略
ReplicaSet控制器的应用更新需要手动分成多步并以特定的次序进行,过程繁杂且容易出错,而Deployment却只需要由用户指定在Pod模板中要改动的内容,(如镜像文件的版本),余下的步骤便会由其自动完成。Pod副本数量也是一样。
Deployment控制器支持两种更新策略:滚动更新(rollingUpdate)和重建创新(Recreate),默认为滚动更新
-
滚动更新(rollingUpdate):即在删除一部分旧版本Pod资源的同时,补充创建一部分新版本的Pod对象进行应用升级,其优势是升级期间,容器中应用提供的服务不会中断,但更新期间,不同客户端得到的相应内容可能会来自不同版本的应用。
-
重新创建(Recreate):即首先删除现有的Pod对象,而后由控制器基于新模板重行创建出新版本的资源对象。
Deployment控制器的滚动更新操作并非在同一个ReplicaSet控制器对象下删除并创建Pod资源,新控制器的Pod对象数量不断增加,直到旧控制器不再拥有Pod对象,而新控制器的副本数量变得完全符合期望值为止。如图所示
滚动更新时,应用还要确保可用的Pod对象数量不低于某阀值以确保可以持续处理客户端的服务请求,变动的方式和Pod对象的数量范围将通过kubectl explain deployment.spec.strategy.rollingUpdate.maxSurge
和kubectl explain deployment.spec.strategy.rollingUpdate.maxUnavailable
两个属性同时进行定义。其功能如下:
-
maxSurge:指定升级期间存在的总
Pod
对象数量最多可超出期望值的个数,其值可以是0
或正整数,也可以是一个期望值的百分比;例如,如果期望值为3
,当前的属性值为1
,则表示Pod
对象的总数不能超过4
个。 -
maxUnavailable:升级期间正常可用的
Pod
副本数(包括新旧版本)最多不能低于期望值的个数,其值可以是0
或正整数,也可以是期望值的百分比;默认值为1
,该值意味着如果期望值是3
,则升级期间至少要有两个Pod
对象处于正常提供服务的状态。
maxSurge
和maxUnavailable
属性的值不可同时为0
,否则Pod
对象的副本数量在符合用户期望的数量后无法做出合理变动以进行滚动更新操作。
Deployment控制器可以保留其更新历史中的旧ReplicaSet对象版本,所保存的历史版本数量由kubectl explain deployment.spec.revisionHistoryLimit
参数指定。只有保存于revision
历史中的ReplicaSet
版本可用于回滚。
注:为了保存版本升级的历史,需要在创建Deployment
对象时于命令中使用“--record”
选项。
Deployment更新升级
修改Pod
模板相关的配置参数便能完成Deployment
控制器资源的更新。由于是声明式配置,因此对Deployment
控制器资源的修改尤其适合使用apply
和patch
命令来进行;如果仅只是修改容器镜像,“set image”
命令更为易用。
1)首先通过set image
命令将上面创建的Deployment
对象的镜像版本改为v2
版本
#打开1个终端进行升级
[root@k8s-master ~]# kubectl set image deployment/deploy-demo myapp=ikubernetes/myapp:v2
deployment.extensions/deploy-demo image updated
#同时打开终端2进行查看pod资源对象升级过程
[root@k8s-master ~]# kubectl get pods -l app=deploy-app -w
NAME READY STATUS RESTARTS AGE
deploy-demo-78c84d4449-2rvxr 1/1 Running 0 33s
deploy-demo-78c84d4449-nd7rr 1/1 Running 0 33s
deploy-demo-7c66dbf45b-7k4xz 0/1 Pending 0 0s
deploy-demo-7c66dbf45b-7k4xz 0/1 Pending 0 0s
deploy-demo-7c66dbf45b-7k4xz 0/1 ContainerCreating 0 0s
deploy-demo-7c66dbf45b-7k4xz 1/1 Running 0 2s
deploy-demo-78c84d4449-2rvxr 1/1 Terminating 0 49s
deploy-demo-7c66dbf45b-r88qr 0/1 Pending 0 0s
deploy-demo-7c66dbf45b-r88qr 0/1 Pending 0 0s
deploy-demo-7c66dbf45b-r88qr 0/1 ContainerCreating 0 0s
deploy-demo-7c66dbf45b-r88qr 1/1 Running 0 1s
deploy-demo-78c84d4449-2rvxr 0/1 Terminating 0 50s
deploy-demo-78c84d4449-nd7rr 1/1 Terminating 0 51s
deploy-demo-78c84d4449-nd7rr 0/1 Terminating 0 51s
deploy-demo-78c84d4449-nd7rr 0/1 Terminating 0 57s
deploy-demo-78c84d4449-nd7rr 0/1 Terminating 0 57s
deploy-demo-78c84d4449-2rvxr 0/1 Terminating 0 60s
deploy-demo-78c84d4449-2rvxr 0/1 Terminating 0 60s
#同时打开终端3进行查看pod资源对象变更过程
[root@k8s-master ~]# kubectl get deployment deploy-demo -w
NAME READY UP-TO-DATE AVAILABLE AGE
deploy-demo 2/2 2 2 37s
deploy-demo 2/2 2 2 47s
deploy-demo 2/2 2 2 47s
deploy-demo 2/2 0 2 47s
deploy-demo 2/2 1 2 47s
deploy-demo 3/2 1 3 49s
deploy-demo 2/2 1 2 49s
deploy-demo 2/2 2 2 49s
deploy-demo 3/2 2 3 50s
deploy-demo 2/2 2 2 51s
# 升级完成再次查看rs的情况,以下可以看到原的rs作为备份,而现在启动的是新的rs
[root@k8s-master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
deploy-demo-78c84d4449 0 0 0 4m41s
deploy-demo-7c66dbf45b 2 2 2 3m54s
2)Deployment
扩容
#1、使用kubectl scale命令扩容
[root@k8s-master ~]# kubectl scale deployment deploy-demo --replicas=3
deployment.extensions/deploy-demo scaled
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
deploy-demo-7c66dbf45b-7k4xz 1/1 Running 0 10m
deploy-demo-7c66dbf45b-gq2tw 1/1 Running 0 3s
deploy-demo-7c66dbf45b-r88qr 1/1 Running 0 10m
#2、使用直接修改配置清单方式进行扩容
[root@k8s-master ~]# vim manfests/deploy-demo.yaml
spec: #deployment控制器的规格定义
replicas: 4 #定义副本数量为2个
[root@k8s-master ~]# kubectl apply -f manfests/deploy-demo.yaml
deployment.apps/deploy-demo configured
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
deploy-demo-78c84d4449-6rmnm 1/1 Running 0 61s
deploy-demo-78c84d4449-9xfp9 1/1 Running 0 58s
deploy-demo-78c84d4449-c2m6h 1/1 Running 0 61s
deploy-demo-78c84d4449-sfxps 1/1 Running 0 57s
#3、使用kubectl patch打补丁的方式进行扩容
[root@k8s-master ~]# kubectl patch deployment deploy-demo -p '{"spec":{"replicas":5}}'
deployment.extensions/deploy-demo patched
[root@k8s-master ~]#
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
deploy-demo-78c84d4449-6rmnm 1/1 Running 0 3m44s
deploy-demo-78c84d4449-9xfp9 1/1 Running 0 3m41s
deploy-demo-78c84d4449-c2m6h 1/1 Running 0 3m44s
deploy-demo-78c84d4449-sfxps 1/1 Running 0 3m40s
deploy-demo-78c84d4449-t7jxb 1/1 Running 0 3s
回滚Deployment控制器下的应用发布
若因各种原因导致滚动更新无法正常进行,如镜像文件获取失败,等等;则应该将应用回滚到之前的版本,或者回滚到指定的历史记录中的版本。则通过kubectl rollout undo
命令完成。如果回滚到指定版本则需要添加--to-revision
选项
1)回到上一个版本
[root@k8s-master ~]# kubectl rollout undo deployment/deploy-demo
deployment.extensions/deploy-demo rolled back
# 回滚状态
[root@k8s-master ~]#kubectl rollout status deployment/deploy-demo
[root@k8s-master ~]# kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
Name Image
deploy-demo-78c84d4449-2xspz ikubernetes/myapp:v1
deploy-demo-78c84d4449-f8p46 ikubernetes/myapp:v1
deploy-demo-78c84d4449-mnmvc ikubernetes/myapp:v1
deploy-demo-78c84d4449-tsl7r ikubernetes/myapp:v1
deploy-demo-78c84d4449-xdt8j ikubernetes/myapp:v1
2)回滚到指定版本
#通过该命令查看更新历史记录
[root@k8s-master ~]# kubectl rollout history deployment/deploy-demo
deployment.extensions/deploy-demo
REVISION CHANGE-CAUSE
2 <none>
4 <none>
5 <none>
#回滚到版本2
[root@k8s-master ~]# kubectl rollout undo deployment/deploy-demo --to-revision=2
deployment.extensions/deploy-demo rolled back
[root@k8s-master ~]# kubectl get pods -o custom-columns=Name:metadata.name,Image:spec.containers[0].image
Name Image
deploy-demo-7c66dbf45b-42nj4 ikubernetes/myapp:v2
deploy-demo-7c66dbf45b-8zhf5 ikubernetes/myapp:v2
deploy-demo-7c66dbf45b-bxw7x ikubernetes/myapp:v2
deploy-demo-7c66dbf45b-gmq8x ikubernetes/myapp:v2
deploy-demo-7c66dbf45b-mrfdb ikubernetes/myapp:v2
清理 Policy
您可以通过设置 .spec.revisonHistoryLimit 项来指定 deployment 最多保留多少 revision 历史记录。默认的会
保留所有的 revision;如果将该项设置为0,Deployment 就不允许回退了
DaemonSet控制器
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod
使用 DaemonSet 的一些典型用法:
运行集群存储 daemon,例如在每个 Node 上运行 glusterd 、 ceph
在每个 Node 上运行日志收集 daemon,例如 fluentd 、 logstash
在每个 Node 上运行监控 daemon,例如 Zabbix agent、 Prometheus Node Exporter、 collectd 、Datadog 代理、New Relic 代理,或 Ganglia gmond
创建DaemonSet
DaemonSet
控制器的spec
字段中嵌套使用的相同字段selector
、template
和minReadySeconds
,并且功能和用法基本相同,但它不支持replicas
,因为毕竟不能通过期望值来确定Pod
资源的数量,而是基于节点数量。
这里使用nginx
来示例,生产环境就比如使用上面提到的logstash
等。
#(1) 定义清单文件
[root@k8s-master ~]# vim manfests/daemonset-demo.yaml
apiVersion: apps/v1 #api版本定义
kind: DaemonSet #定义资源类型为DaemonSet
metadata: #元数据定义
name: daemset-nginx #daemonset控制器名称
namespace: default #名称空间
labels: #设置daemonset的标签
app: daem-nginx
spec: #DaemonSet控制器的规格定义
selector: #指定匹配pod的标签
matchLabels: #指定匹配pod的标签
app: daem-nginx #注意:这里需要和template中定义的标签一样
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: nginx
labels: #定义Pod的标签,需要和上面的标签选择器内匹配规则中定义的标签一致,可以多出其他标签
app: daem-nginx
spec: #Pod的规格定义
containers: #容器定义
- name: nginx-pod #容器名字
image: nginx:1.12 #容器镜像
ports: #暴露端口
- name: http #端口名称
containerPort: 80 #暴露的端口
#(2)创建上面定义的daemonset控制器
[root@k8s-master ~]# kubectl apply -f manfests/daemonset-demo.yaml
daemonset.apps/daemset-nginx created
#(3)查看验证
[root@k8s-master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
daemset-nginx-7s474 1/1 Running 0 80s 10.244.1.61 k8s-node1 <none> <none>
daemset-nginx-kxpl2 1/1 Running 0 94s 10.244.2.58 k8s-node2 <none> <none>
[root@k8s-master ~]# kubectl describe daemonset/daemset-nginx
......
Name: daemset-nginx
Selector: app=daem-nginx
Node-Selector: <none>
......
Desired Number of Nodes Scheduled: 2
Current Number of Nodes Scheduled: 2
Number of Nodes Scheduled with Up-to-date Pods: 2
Number of Nodes Scheduled with Available Pods: 2
Number of Nodes Misscheduled: 0
Pods Status: 2 Running / 0 Waiting / 0 Succeeded / 0 Failed
......
通过上面验证查看,Node-Selector
字段的值为空,表示它需要运行在集群中的每个节点之上。而当前的节点数是2
个,所以其期望的Pod
副本数(Desired Number of Nodes Scheduled
)为2
,而当前也已经创建了2
个相关的Pod
对象。
注意
对于特殊的硬件的节点来说,可能有的运行程序只需要在某一些节点上运行,那么通过Pod
模板的spec
字段中嵌套使用nodeSelector
字段,并确保其值定义的标签选择器与部分特定工作节点的标签匹配即可。
更新DaemonSet对象
DaemonSet
自Kubernetes1.6
版本起也开始支持更新机制,相关配置嵌套在kubectl explain daemonset.spec.updateStrategy
字段中。其支持RollingUpdate(滚动更新)
和OnDelete(删除时更新)
两种策略,滚动更新为默认的更新策略。
#(1)查看镜像版本
[root@k8s-master ~]# kubectl get pods -l app=daem-nginx -o custom-columns=NAME:metadata.name,NODE:spec.nodeName,Image:spec.containers[0].image
NAME NODE Image
daemset-nginx-7s474 k8s-node1 nginx:1.12
daemset-nginx-kxpl2 k8s-node2 nginx:1.12
#(2)更新
[root@k8s-master ~]# kubectl set image daemonset/daemset-nginx nginx-pod=nginx:1.14
[root@k8s-master ~]# kubectl get pods -l app=daem-nginx -o custom-columns=NAME:metadata.name,NODE:spec.nodeName,Image:spec.containers[0].image #再次查看
NAME NODE Image
daemset-nginx-74c95 k8s-node2 nginx:1.14
daemset-nginx-nz6n9 k8s-node1 nginx:1.14
#(3)查坎详细信息
[root@k8s-master ~]# kubectl describe daemonset daemset-nginx
......
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 49m daemonset-controller Created pod: daemset-nginx-6kzg6
Normal SuccessfulCreate 49m daemonset-controller Created pod: daemset-nginx-jjnc2
Normal SuccessfulDelete 40m daemonset-controller Deleted pod: daemset-nginx-jjnc2
Normal SuccessfulCreate 40m daemonset-controller Created pod: daemset-nginx-kxpl2
Normal SuccessfulDelete 40m daemonset-controller Deleted pod: daemset-nginx-6kzg6
Normal SuccessfulCreate 40m daemonset-controller Created pod: daemset-nginx-7s474
Normal SuccessfulDelete 15s daemonset-controller Deleted pod: daemset-nginx-7s474
Normal SuccessfulCreate 8s daemonset-controller Created pod: daemset-nginx-nz6n9
Normal SuccessfulDelete 5s daemonset-controller Deleted pod: daemset-nginx-kxpl2
通过上面查看可以看出,默认的滚动更新策略是一次删除一个工作节点上的Pod
资源,待其最新版本Pod
重建完成后再开始操作另一个工作节点上的Pod
资源。
DaemonSet
控制器的滚动更新机制也可以借助于minReadySeconds
字段控制滚动节奏;必要时也可以执行暂停和继续操作。其也可以进行回滚操作。
Job控制器
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。
特殊说明:
- spec.template格式同Pod
- RestartPolicy仅支持Never或OnFailure
- 单个Pod时,默认Pod成功运行后Job即结束
- .spec.completions 标志Job结束需要成功运行的Pod个数,默认为1
- .spec.parallelism 标志并行运行的Pod的个数,默认为1
- spec.activeDeadlineSeconds 标志失败Pod的重试最大时间,超过这个时间不会继续重试
创建Job
[root@k8s-master ~]# vim manfests/job-demo.yaml
apiVersion: batch/v1 #api版本定义
kind: Job
metadata: #元数据定义
name: pi
spec:
template: #Pod的模板定义
metadata: #Pod的元数据定义
name: pi
spec: #Pod的规格定义
containers: #容器定义
- name: pi #容器名字
image: perl #容器镜像
command: ["perl","-Mbignum=bpi","-wle","pring bpi(2000)"]
restartPolicy: Never
[root@k8s-master ~]# kubectl create -f job.yaml
job.batch/pi created
计算Pi2000位(根据机器性能可以调小点)
kubectl get pod
kubectl describe pod pi-lbrh5
正在下镜像,太慢了,手动导入
yum -y install lrzsz
perl.tar.gz
[root@k8s-master01 ~]# tar xvf perl.tar.gz
[root@k8s-master01 ~]# docker load -i perl.tar
[root@k8s-master01 ~]# scp perl.tar root@k8s-node01:/root
[root@k8s-master01 ~]# scp perl.tar root@k8s-node02:/root
[root@k8s-node01 ~]# docker load -i perl.tar
[root@k8s-node02 ~]# docker load -i perl.tar
kubectl get pod
时间比较久,已经ImagePullBackOff了,删除,自己重建。
kubectl get pod -o wide
等待
kubectl get pod
已经Completed了
kubectl get pod job
作业完成
查看日志
已经将圆周率推算到2000位,如果运行太慢,修改yaml文件将数字改小,删除后然后重新创建。
CronJob Spec
spec.template格式同Pod
RestartPolicy仅支持Never或OnFailure
单个Pod时,默认Pod成功运行后Job即结束
.spec.completions 标志Job结束需要成功运行的Pod个数,默认为1
.spec.parallelism 标志并行运行的Pod的个数,默认为1
spec.activeDeadlineSeconds 标志失败Pod的重试最大时间,超过这个时间不会继续重试
CronJob控制器
Cron Job 管理基于时间的 Job,即:
- 在给定时间点只运行一次
- 周期性地在给定时间点运行
使用条件:当前使用的 Kubernetes 集群,版本 >= 1.8(对 CronJob)
典型的用法如下所示:
- 在给定的时间点调度 Job 运行
- 创建周期性运行的 Job,例如:数据库备份、发送邮件
CronJob Spec
-
.spec.schedule :调度,必需字段,指定任务运行周期,格式同 Cron
-
.spec.jobTemplate :Job 模板,必需字段,指定需要运行的任务,格式同 Job
-
.spec.startingDeadlineSeconds :启动 Job 的期限(秒级别),该字段是可选的。如果因为任何原因而错过了被调度的时间,那么错过执行时间的 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。默认情况下,它们分别设置为 3 和 1 。设置限制的值为 0 ,相关类型的 Job 完成后将不会被保留。
创建cronJob
[root@k8s-master ~]# vim manfests/cronJob-demo.yaml
apiVersion: batch/v1beta1 #api版本定义
kind: CronJob
metadata: #元数据定义
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec: #Pod的规格定义
template:
spec:
containers: #容器定义
- name: hello #容器名字
image: busybox #容器镜像
args:
- /bin/sh
- -c
- date;echo Hello from the Kubenetes cluster
restartPolicy: OnFailure
[root@k8s-master ~]# kubectl apply -f cronjob.yaml
cronjob.batch/hello created
[root@k8s-master ~]# kubectl get cronjob
[root@k8s-master ~]# kubectl get job
[root@k8s-master ~]# kubectl log hello-1605656340-gbf95
CrondJob 本身的一些限制
创建 Job 操作应该是 幂等 的