资源控制器
一、简介
Controller Manager 由 kube-controller-manager 和 cloud-controller-manager 组成, 是Kubernetes 的大脑, 它通过 apiserver 监控整个集群的状态, 并确保集群处于预期的工作状态。
kube-controller-manager 由一系列的控制器组成
Replication Controller
Node Controller
CronJob Controller
DaemonSet Controller
Deployment Controller
Endpoint Controller
Garbage Collector
Namespace Controller
Job Controller
Pod AutoScaler
RelicaSet
Service Controller
ServiceAccount Controller
StatefulSet Controller
Volume Controller
Resource quota Controller
cloud-controller-manager 在 Kubernetes 启用 Cloud Provider 的时候才需要, 用来配合云服务提供商的控制, 也包括一系列的控制器
Node Controller
Route Controller
Service Controller
二、常见控制器
控制器 | 场景 | 描述 |
---|---|---|
ReplicaSet | 适合无状态的服务部署 | 用户创建指定数量的pod副本数量,确保pod副本数量符合预期状态,并且支持滚动式自动扩容和 缩容功能。 ReplicaSet主要三个组件组成: (1)用户期望的pod副本数量 (2)标签选择器,判断哪个pod归自己管理 (3)当现存的pod数量不足,会根据pod资源模板进行新建 帮助用户管理无状态的pod资源,精确反应用户定义的目标数量,但是RelicaSet不是直接使用的控制器,而是使用Deployment。 |
deployment | 适合无状态的服务部署 | 工作在ReplicaSet之上,用于管理无状态应用,目前来说最好的控制器。支持滚动更新和回滚功能,还提供声明式配置。 |
StatefullSet | 适合有状态的服务部署 | 和存储卷相关 |
DaemonSet | 一次部署,所有的node节点都会部署 | 一些典型的应用场景: 运行集群存储 daemon,例如在每个Node上运行 glusterd、ceph 在每个Node上运行日志收集 daemon,例如 fluentd、 logstash 在每个Node上运行监控 daemon,例如 Prometheus Node Exporter 用于确保集群中的每一个节点只运行特定的pod副本,通常用于实现系统级后台任务。比如ELK服务 特性:服务是无状态的 服务必须是守护进程 |
Job | 一次性的执行任务 | 只要完成就立即退出,不需要重启或重建 |
Cronjob | 周期性的执行任务 | 周期性任务控制,不需要持续后台运行 |
三、控制器详情
0. replication controller
replication controller简称RC,是kubernetes系统中的核心概念之一,简单来说,它其实定义了一个期望的场景,即声明某种pod的副本数量在任意时刻都复合某个预期值,所以RC的定义包含以下部分:
- pod期待的副本数量
- 用于筛选目标pod的Label Selector
- 当pod的副本数量小于期望值时,用于创建新的pod的pod模板(template)
1. replicaSet
扩容、缩容
ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收。 在新版本的Kubernetes中建议使用ReplicaSet来取代ReplicationController。ReplicaSet跟ReplicationController没有本质的不同,只是名字不一样,并且ReplicaSet支持集合式的selector。 虽然ReplicaSet可以独立使用,但一般还是建议使用 Deployment 来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但Deployment支持)。
模板说明
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
environment: qa
spec: #pod的规格定义
containers: #容器定义
- name: myapp-container #容器名称
image: nginx:1.17.10-alpine #容器镜像
ports: #暴露端口
- name: http
containerPort: 80
比较
# 我们之前是通过 deployment cmd 操作的扩容 (官方推荐)
# kubectl scale deployment nginx-app --replicas=10
# 也可以通过 replicaset 去操作 (官方不推荐)
kubectl scale replicaset nginx-app --replicas=10
# 通过配置文件
kubectl edit replicasets.app nginx-app
# 操作上边命令后 会有类似 vim 的效果,展示出所有yaml 的文件内容, 然后我们可以移动光标找到 要修改的 数值,修改后 使用 `:wq` 保存
#---------------------------
...
replicas: 8 # 我们修改扩容、缩容数量,然后`:wq` 保存,退出
#---------------------------
总结
通常我们不会直接操作pod 或 replicaSet。我们一般通过deployment 来管控pod 或 replicaSet; 后面我们会对deployment进行详细的介绍。
kubectl命令行工具适用于RC的绝大部分命令同样适用于ReplicaSet,此外,我们当前很少单独适用ReplicaSet,它主要被Deployment这个更高层的资源对象所使用,从而形成一整套Pod创建,删除,更新的编排机制,我们在使用Deployment时无需关心它是如何维护和创建ReplicaSet的,这一切都是自动发生的 最后,总结一下RC(ReplicaSet)的一些特性和作用:
- 在绝大多数情况下,我们通过定义一个RC实现Pod的创建及副本数量的自动控制
- 在RC里包括完整的Pod定义模板
- RC通过Label Selector机制实现对Pod副本的自动控制
- 通过改变RC里的Pod副本数量,可以实现Pod的扩容和缩容
- 通过改变RC里Pod模板中的镜像版本,可以实现滚动升级
2. deployment
资源管控和配置
Deployment是kubernetes在1.2版本中引入的新概念,用于更好的解决Pod的编排问题,为此,Deployment在内部使用了ReplicaSet来实现目的,我们可以把Deployment理解为ReplicaSet的一次升级,两者的相似度超过90%。
Deployment的使用场景:
- 创建一个Deployment对象来生成对应的ReplicaSet并完成Pod副本的创建
- 检查Deployment的状态来看部署动作是否完成(Pod副本数量是否达到了预期的值)
- 更新Deployment以创建新的Pod(比如镜像升级)
- 如果当前Deployment不稳定,可以回滚到一个早先的Deployment版本
- 暂停Deployment以便于一次性修改多个PodTemplateSpec的配置项,之后在恢复Deployment,
- 进行新的发布
- 扩展Deployment以应对高负载
- 查看Deployment的状态,以此作为发布是否成功的标志
- 清理不在需要的旧版本ReplicaSet
模板说明
# 通过命令获取更多的详细信息
kubectl explain deploy
deploymentdemo1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploymentdemo1
labels:
app: deploymentdemo1
spec:
selector: #定义标签选择器
matchLabels: #定义匹配的标签,必须要设置
app: deploymentdemo1 #匹配的目标标签
replicas: 10 #开启Pod的数量
template: #定义模板,必须定义,模板是起到描述要创建的pod的作用
metadata: #定义模板元数据
labels: #定义模板label,Deployment.spec.template.metadata.labels
app : deploymentdemo1 #定义标签,必须等于 matchLabels 定义的标签
spec:
containers:
- image: nginx:1.17.10-alpine # 要拉取的镜像名称
name: nginx-v1-17-10 #镜像名称 注意这里,针对命名格式有要求,只允许"字母、数字和-"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80 #定义容器使用的端口
restartPolicy: Always
运行deploymentdemo1.yaml 之前我们已经操作过, 这里简单说下
# 运行
kubectl apply -f deployment.yml
# 查看deployment 的两种命令
kubectl get rs
#---------------------
NAME DESIRED CURRENT READY AGE
nginx-app-74d589986c 5 5 5 3d19h
#---------------------
kubectl get deployment
#---------------------
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-app 5/5 5 5 3d19h
#---------------------
# 查看pod
kubectl get pod
镜像版本升级方式
这里我们只介绍yaml更新方式。 通过命令行的更新方式官方不推荐,也不好维护。
# 升级nginx 镜像版本为1.19.2-alpine
kubectl edit deployments deploymentdemo1
# 在输出的信息中找到 'spec.spec.containers[0].image' 并修改版本
# 和 vim 差不多,进入后即可编辑,将光标移动到要修改的属性上,修改后使用:wq 退出,保存并执行
#------------------------------
...
spec:
...
spec:
containers:
- image: nginx:1.19.2-alpine
#------------------------------
# 查看pod升级情况
kubectl get pods
#---------------------
NAME READY STATUS RESTARTS AGE
deploymentdemo1-5bc649f558-4m4s4 1/1 Running 0 41s
deploymentdemo1-5bc649f558-87plz 1/1 Running 0 62s
deploymentdemo1-5bc649f558-d465w 1/1 Running 0 62s
deploymentdemo1-5bc649f558-hr69v 1/1 Running 0 50s
deploymentdemo1-5bc649f558-lk5gb 1/1 Running 0 40s
deploymentdemo1-5bc649f558-ln8lq 1/1 Running 0 62s
deploymentdemo1-5bc649f558-nh99g 1/1 Running 0 62s
deploymentdemo1-5bc649f558-nt6vx 1/1 Running 0 51s
deploymentdemo1-5bc649f558-qcgv5 1/1 Running 0 39s
deploymentdemo1-5bc649f558-slkk9 1/1 Running 0 62s
nginx-app-74d589986c-bdf66 1/1 Running 0 3d20h
nginx-app-74d589986c-gfmsd 1/1 Running 0 3d20h
nginx-app-74d589986c-kdq6r 1/1 Running 0 3d20h
nginx-app-74d589986c-p4mbl 1/1 Running 0 3d20h
nginx-app-74d589986c-slszp 1/1 Running 0 3d20h
#---------------------
# 进去某一个pod内部,查看nginx升级版本信息
kubectl exec -it deploymentdemo1-5bc649f558-4m4s4 sh
# 下面我们进入了容器内,执行命令 查看nginx 版本
nginx -v
# nginx version: nginx/1.19.2
# 退出容器,或 ctrl + D
exit
扩容缩容
# 扩容缩容操作之前我们已经说过一次,这里简单带过下
# 升级nginx 镜像版本为1.19.2-alpine
kubectl edit deployments deploymentdemo1
# 在输出的信息中找到 'spec.replicas' 并修改版本
# 和 vim 差不多,进入后即可编辑,将光标移动到要修改的属性上,修改后使用:wq 退出,保存并执行
#------------------------------
...
spec:
replicas: 8
#------------------------------
# 查看pod升级情况
kubectl get pods
# 查看副本数
kubectl get deployment
滚动更新
概述
下面我们简单说下常用的微服务部署方式:
蓝绿部署: 不停老版本,部署新版本然后进行测试,确认没问题,再将流量切到新版本,然后老版本同时也升级到新版本。蓝绿部署无需停机,且风险小。
滚动发布:一般是取出一个或多个服务器停止服务,执行更新,并重新将其投入使用。周而复始,知道集群中所有实例都更新成新版本。这种方式相对蓝绿部署,更加节约资源---- 它不需要运行两个集群、两倍的实例数、 我们可以部分升级,例如每次只取出集群的20%进行升级。
灰度发布:是指在黑与白之间,能够平滑过渡的一种发布方式。 AB测试就是一种灰度发布的方式。让一部分用户继续用A版本,一部分用户开始用B版本,如果B用户没有什么反对意见或问题,那么逐步扩大范围,把所有用户都迁移到B上面。 灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证较小范围内的影响度,我们说的金丝雀发布也是灰度发布的一种。
金丝雀发布--(滚动更新)
Deployment控制器支持自定义控制更新过程中的滚动节奏,如“暂停(pause)”或“继续(resume)”更新操作。比如等待第一批新的Pod资源创建完成后立即暂停更新过程,此时,仅存在一部分新版本的应用,主体部分还是旧的版本。然后,再筛选一小部分的用户请求路由到新版本的Pod应用,继续观察能否稳定地按期望的方式运行。确定没问题之后再继续完成余下的Pod资源滚动更新,否则立即回滚更新操作。这就是所谓的金丝雀发布(Canary Release)
滚动更新-自动
# 下面我们来实现滚动更新
# 我们新建一个yaml,保留原有的yaml 方便我们做比对
# 在新建的yaml中我们添加了 `滚动更新策略`
vim deploymentdemo2-rollingupdate.yaml
#--------------------------
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploymentdemo1
labels:
app: deploymentdemo1
spec:
selector: #定义标签选择器
matchLabels: #定义匹配的标签,必须要设置
app: deploymentdemo1 #匹配的目标标签
replicas: 10 #开启Pod的数量
template: #定义模板,必须定义,模板是起到描述要创建的pod的作用
metadata: #定义模板元数据
labels: #定义模板label,Deployment.spec.template.metadata.labels
app : deploymentdemo1 #定义标签,必须等于 matchLabels 定义的标签
spec:
containers:
- image: nginx:1.19.2-alpine # 我们升级nginx 版本
name: nginx-v1-17-10 #镜像名称
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80 #定义容器使用的端口
restartPolicy: Always
# ------------ 滚动更新策略配置
minReadySeconds: 5 # 最小等待时间,默认0;kubernetes在等待设置的时间后才进行升级,如果没有设置值 会立即启动,极端情况下可能造成服务不正常
strategy:
type: RollingUpdate # 服务更新策略: 默认RollingUpdate 滚动更新;还有一个recreate : 重建式更新,删一个建一个。先删除现有pod,然后控制器基于新模板进行创建
rollingUpdate:
maxSurge: 1 # 表示升级过程中最多可以比原先设置的允许多出的pod数量;例如 maxSurge=1,replicas=5 标识kubernetes会先启动一个新的pod,然后再删除一个旧的pod,整个过程中最多有 (5 +1) 个pod
maxUnavailable: 1 # 表示升级过程中最多有多少个pod出于无法提供服务的状态,当maxSurge不为0时,改制也不能为0; maxUnavailable=1 代表升级过程中最多有一个pod出于无法服务状态
#--------------------------
# 下面我们就可以执行 yaml 进行滚动更新了
kubectl apply -f deploymentdemo2-rollingupdate.yaml
# 查看滚动更新状态
kubectl rollout status deployment/deploymentdemo1
#------------------------
Waiting for deployment "deploymentdemo1" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "deploymentdemo1" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "deploymentdemo1" rollout to finish: 8 out of 10 new replicas have been updated...
Waiting for deployment "deploymentdemo1" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "deploymentdemo1" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "deploymentdemo1" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "deploymentdemo1" rollout to finish: 1 old replicas are pending termination...
deployment "deploymentdemo1" successfully rolled out
#------------------------
# 查看rs,我们发现 `deploymentdemo1-6fcd98fbfc` 的数量变成了 0 / 0; `deploymentdemo1-5bc649f558`是我们滚动更新后新创建的 10 / 10
kubectl get rs
#---------------------------
NAME DESIRED CURRENT READY AGE
deploymentdemo1-5bc649f558 10 10 10 83m
deploymentdemo1-6fcd98fbfc 0 0 0 171m
#---------------------------
# 查看详细信息
kubectl describe deployment deploymentdemo1
#---------------------------
Name: deploymentdemo1
Namespace: default
CreationTimestamp: Mon, 04 Jul 2022 11:14:07 +0800
Labels: app=deploymentdemo1
Annotations: deployment.kubernetes.io/revision: 4
Selector: app=deploymentdemo1
Replicas: 10 desired | 10 updated | 10 total | 10 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 5
RollingUpdateStrategy: 1 max unavailable, 1 max surge
Pod Template:
Labels: app=deploymentdemo1
Containers:
nginx-v1-17-10:
Image: nginx:1.19.2-alpine
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: deploymentdemo1-5bc649f558 (10/10 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 21m deployment-controller Scaled up replica set deploymentdemo1-5bc649f558 to 2
Normal ScalingReplicaSet 21m deployment-controller Scaled up replica set deploymentdemo1-5bc649f558 to 1
Normal ScalingReplicaSet 21m deployment-controller Scaled down replica set deploymentdemo1-6fcd98fbfc to 9
Normal ScalingReplicaSet 21m deployment-controller Scaled up replica set deploymentdemo1-5bc649f558 to 4
Normal ScalingReplicaSet 21m (x2 over 103m) deployment-controller Scaled down replica set deploymentdemo1-6fcd98fbfc to 7
Normal ScalingReplicaSet 20m (x2 over 103m) deployment-controller Scaled down replica set deploymentdemo1-6fcd98fbfc to 5
Normal ScalingReplicaSet 20m (x2 over 103m) deployment-controller Scaled up replica set deploymentdemo1-5bc649f558 to 6
Normal ScalingReplicaSet 20m (x2 over 103m) deployment-controller Scaled up replica set deploymentdemo1-5bc649f558 to 8
Normal ScalingReplicaSet 20m deployment-controller Scaled down replica set deploymentdemo1-6fcd98fbfc to 3
#---------------------------
# 通过上边的信息我们可以看到 当前的 nginx image == `Image: nginx:1.19.2-alpine`
滚动更新--手动
手动更新主要通过pause
和resume
命令来实现
# 在我们上边自动更新的基础上,我们通过下面命令对更新步骤进行处理
# ...
# kubectl apply -f deploymentdemo2-rollingupdate.yaml
# 在上述命令执行之后
# 暂停升级
kubectl rollout pause deployment deploymentdemo1
# 恢复升级
kubectl rollout resume deployment deploymentdemo1
版本回退
默认情况下,kubernetes 会在系统中保存前两次的 Deployment 的 rollout 历史记录,以便可以随时回退(您可以修改 revision history limit 来更改保存的revision数)。
注意: 只要 Deployment 的 rollout 被触发就会创建一个 revision。也就是说当且仅当Deployment 的 Pod template(如 .spec.template )被更改,例如更新template 中的 label 和容器镜像时,就会创建出一个新的 revision。 其他的更新,比如扩容 Deployment 不会创建 revision——因此我们可以很方便的手动或者自动扩容。 这意味着当您回退到历史 revision 时,只有 Deployment 中的 Pod template 部分才会回退。
rollout常见命令
子命令 | 说明 |
---|---|
history | 查看rollout操作历史 (如果未在资源文件中配置,默认记录数量limit=2) |
pause | 将提供的资源设定为暂停状态 |
restart | 重启某资源 |
resume | 将某资源从暂停状态恢复正常 |
status | 查看rollout操作状态 |
undo | 回滚前一rollout |
history查询
# history 查询
kubectl rollout history deployment deploymentdemo1
# ----------------------------
deployment.apps/deploymentdemo1
REVISION CHANGE-CAUSE
3 <none>
4 <none>
# ----------------------------
status查询
# 查看status
kubectl rollout status deployment deploymentdemo1
# ----------------------------
deployment "deploymentdemo1" successfully rolled out
# ----------------------------
回滚
注意: 默认只保留2条历史记录;如果要保留多个历史版本,需要在资源配置文件中添加
spec.revisionHistoryLimit=10
属性。
# 回滚到上一个版本
kubectl rollout undo deployment deploymentdemo1
# 如果要回滚到指定版本我们需要新执行history 确认要回滚的版本号,然后运行下面的命令
# kubectl rollout undo deployment deploymentdemo1 --to-revision=你要回滚的版本号
# kubectl rollout undo deployment deploymentdemo1 --to-revision=2
# ----------------------------
deployment.apps/deploymentdemo1 rolled back
# ----------------------------
# 查看pod状态, 可以加 -w 效果类似 tail -f 动态刷新
kubectl get pods
# 查看rs
kubectl get rs
# ----------------------------
NAME DESIRED CURRENT READY AGE
deploymentdemo1-5bc649f558 0 0 0 115m
deploymentdemo1-6fcd98fbfc 10 10 10 3h23m
nginx-app-74d589986c 5 5 5 3d23h
# ----------------------------
# 我们发现 `deploymentdemo1-5bc649f558` 的数量变成了 0/0, 而我们上一个版本`deploymentdemo1-6fcd98fbfc` 的数量变成了 10 / 10
3. daemonSet
DaemonSet 确保全部Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有Pod。
在每一个node节点上只调度一个Pod,因此无需指定replicas的个数,比如:
- 在每个node上都运行一个日志采集程序,负责收集node节点本身和node节点之上的各个Pod所产生的日志
- 在每个node上都运行一个性能监控程序,采集该node的运行性能数据
DaemonSet 中的 Pod 可以使用 hostPort,从而可以通过节点 IP 访问到 Pod;因为DaemonSet模式下Pod不会被调度到其他节点。使用示例如下:
ports:
- name: httpd
containerPort: 80
#除非绝对必要,否则不要为 Pod 指定 hostPort。 将 Pod 绑定到hostPort时,它会限制 Pod 可以调度的位置数;DaemonSet除外
#一般情况下 containerPort与hostPort值相同
hostPort: 8090 #可以通过宿主机+hostPort的方式访问该Pod。例如:pod在/调度到了k8s-node02【172.16.1.112】,那么该Pod可以通过172.16.1.112:8090方式进行访问。
protocol: TCP
模板说明
# 新建demon_set.yaml文件
vim demon_set.yaml
# -------------------
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: demonsetdemo
labels:
app: demonsetdemo
spec:
template:
metadata:
name: demonsetdemo
labels:
app: demonsetdemo
spec:
containers:
- name: demonsetdemo
image: nginx:1.17.10-alpine
imagePullPolicy: IfNotPresent
restartPolicy: Always
selector:
matchLabels:
app: demonsetdemo
# -------------------
# 运行
kubectl apply -f demon_set.yaml
#--------------------
daemonset.apps/demonsetdemo created
#--------------------
# 查看pod
kubectl get pod -o wide
#--------------------
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
demonsetdemo-bgtgc 1/1 Running 0 2m8s 10.244.220.246 k8s-slave02 <none> <none>
demonsetdemo-xnnf6 1/1 Running 0 2m8s 10.244.211.253 k8s-slave03 <none> <none>
deploymentdemo1-5bc649f558-92bc9 1/1 Running 0 36m 10.244.211.248 k8s-slave03 <none> <none>
deploymentdemo1-5bc649f558-fwhdr 1/1 Running 0 36m 10.244.220.241 k8s-slave02 <none> <none>
deploymentdemo1-5bc649f558-gmpzz 1/1 Running 0 36m 10.244.220.242 k8s-slave02 <none> <none>
deploymentdemo1-5bc649f558-pzvmd 1/1 Running 0 36m 10.244.220.243 k8s-slave02 <none> <none>
deploymentdemo1-5bc649f558-qtt4r 1/1 Running 0 36m 10.244.211.252 k8s-slave03 <none> <none>
deploymentdemo1-5bc649f558-slg5r 1/1 Running 0 36m 10.244.220.244 k8s-slave02 <none> <none>
deploymentdemo1-5bc649f558-vskqr 1/1 Running 0 36m 10.244.211.249 k8s-slave03 <none> <none>
deploymentdemo1-5bc649f558-xtp9s 1/1 Running 0 36m 10.244.211.251 k8s-slave03 <none> <none>
deploymentdemo1-5bc649f558-xwt2s 1/1 Running 0 36m 10.244.220.245 k8s-slave02 <none> <none>
deploymentdemo1-5bc649f558-z5xhr 1/1 Running 0 36m 10.244.211.250 k8s-slave03 <none> <none>
nginx-app-74d589986c-bdf66 1/1 Running 0 3d22h 10.244.211.209 k8s-slave03 <none> <none>
nginx-app-74d589986c-gfmsd 1/1 Running 0 3d22h 10.244.211.212 k8s-slave03 <none> <none>
nginx-app-74d589986c-kdq6r 1/1 Running 0 3d22h 10.244.220.201 k8s-slave02 <none> <none>
nginx-app-74d589986c-p4mbl 1/1 Running 0 3d23h 10.244.211.208 k8s-slave03 <none> <none>
nginx-app-74d589986c-slszp 1/1 Running 0 3d22h 10.244.211.211 k8s-slave03 <none> <none>
#--------------------
# 我们发现 pod 有两个`demonsetdemo-xxx` 的节点,分别在 node `k8s-slave02` 和 node `k8s-slave03` 上
只有工作节点node创建pod,master节点不会创建
daemonSet 有两种更新策略:
- OnDelete:这是向后兼容性的默认更新策略。使用 OnDelete 更新策略,在更新DaemonSet模板后,只有在手动删除旧的DaemonSet pod时才会创建新的DaemonSet pod。这与Kubernetes1.5或更早版本中DaemonSet的行为相同。
- RollingUpdate:使用 RollingUpdate 更新策略,在更新DaemonSet模板后,旧的DaemonSetpod将被终止,并且将以受控方式自动创建新的DaemonSet pod。
# 更新demon_set.yaml
#-------------------------
...
updateStrategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
...
#-------------------------
# 执行更新策略并更新
kubectl apply -f demon_set.yaml
4. job
一次性执行任务,类似Linux中的job
应用场景:如离线数据处理,视频解码等业务
spec.template格式同Pod。
RestartPolicy仅支持Never或OnFailure。
单个Pod时,默认Pod成功运行后Job即结束。
.spec.completions标志Job结束需要成功运行的Pod个数,默认为1。
.spec.parallelism标志并行运行的Pod的个数,默认为1。
spec.activeDeadlineSeconds标志失败Pod的重试最大时间,超过这个时间不会继续重试
模板说明
vim job.yaml
#----------------------------
apiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4 # job 容错次数。默认值6;当job运行的pod失败次数达到设置值后,job controller 不再创建新pod,直接停止运行job,并将运行结果标记为Failure。另外pod 运行失败后再次运行的时间呈现递增状态 10s、20s、40s 直至300S
# 指定存活时长
activeDeadlineSeconds: 100
#----------------------------
kubectl apply -f job.yaml
job "pi" created
$ pods=$(kubectl get pods --selector=job-name=pi --output=jsonpath={.items..metadata.name})
$ kubectl logs $pods
3.141592653589793238462643383279502...
5. cron job
cron Job是基于时间进行调度的,CronJob对象就像一行crontab文件,它会在给定的时间定期(以cron格式编写)地运行一个Job。一个Cron Job创建Job对象基于它的调度执行时间,当然也有可能0个或2个Job会被创建,这些目前都不是确定的,因此Job之间应该保证幂等性,startingDeadlineSeconds
设置为大一点的值或者不设置让其默认且concurrencyPolicy
设置为Allow
,Job应该至少运行一次。对于CronJob,CronJob Controller将会检查从上一次调度到现在将会错过多少调度,如果错过超过了100个,那它将不会再启动Job并记录错误:Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew.
。如果startingDeadlineSeconds
字段设置了但不是nil
,Controller从startingDeadlineSeconds
开始计算直到现在(即之前的时间内,并不是上次调度到现在)。比如,如果startingDeadlineSeconds
设置为200
,控制器将会计算在刚刚过去的200s中错失了多少Job。
CronJob是从它在调度时间内创建失败进行计算的,比如,concurrencyPolicy
设置为Forbid
,CronJob将会尝试调度,如果之前的调度仍在运行,那么它将被视为错过。
6. statefulSet
这块只做简单介绍,数据高级应用的部分。需要花费精力较多。挂上一篇比较好的文章:k8s之StatefulSet详解
在kubernetes系统中,Pod的管理对象RC,Deployment,DaemonSet和Job都面向无状态的服务,但现实中有很多服务时有状态的,比如一些集群服务,例如mysql集群,集群一般都会有这四个特点:
- 每个节点都是有固定的身份ID,集群中的成员可以相互发现并通信
- 集群的规模是比较固定的,集群规模不能随意变动
- 集群中的每个节点都是有状态的,通常会持久化数据到永久存储中
- 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损
如果你通过RC或Deployment控制Pod副本数量来实现上述有状态的集群,就会发现第一点是无法满足 的,因为Pod名称和ip是随机产生的,并且各Pod中的共享存储中的数据不能都动,因此StatefulSet在这种情况下就派上用场了,那么StatefulSet具有以下特性:
- StatefulSet里的每个Pod都有稳定,唯一的网络标识,可以用来发现集群内的其它成员,假设,StatefulSet的名称为lagou,那么第1个Pod叫lagou-0,第2个叫lagou-1,以此类推
- StatefulSet控制的Pod副本的启停顺序是受控的,操作第N个Pod时,前N-1个Pod已经是运行且准备状态、
- StatefulSet里的Pod采用稳定的持久化存储卷,通过PV或PVC来实现,删除Pod时默认不会删除与StatefulSet相关的存储卷(为了保证数据的安全)
StatefulSet除了要与PV卷捆绑使用以存储Pod的状态数据,还要与Headless,Service配合使用,每个StatefulSet定义中都要生命它属于哪个Handless Service,Handless Service与普通Service的关键区别在于,它没有Cluster IP。
什么是无状态?
组成一个应用的pod是对等的,它们之前没有关联和依赖关系,不依赖外部存储。
即我们上篇小作文中deployment创建的nginx pod ,他们是完全一样的,任何一个pod 被移除后依然可以正常工作。由于不依赖外部存储,它们可以被轻易的调度到任何 node 上。
什么是有状态?
显然无状态的反面就是有状态了,pod之间可能包含主从、主备的相互依赖关系,甚至对启动顺序也有要求。更关键的是这些pod 需要外部存储,一旦pod被清除或调度后,怎么把pod 和原来的外部数据联系起来?这就是StatefulSet厉害的地方。
StatefulSet将这些状态应用进行记录,在需要的时候恢复。