控制器
- Pod 的分类:
- 自主式 Pod:Pod 退出后不会被创建
- 控制器管理的 Pod:在控制器的生命周期里,始终要维持 Pod 的副本数目
- 控制器类型:
- Replication Controller和ReplicaSet
- Deployment
- DaemonSet
- StatefulSet
- Job //定时任务
- CronJob //重复任务
- HPA全称Horizontal Pod Autoscaler
Replication Controller和ReplicaSet
- ReplicaSet 是下一代的 Replication Controller,官方推荐使用ReplicaSet。
- ReplicaSet 和 Replication Controller 的唯一区别是选择器的支持,ReplicaSet支持新的基于集合的选择器需求。
- ReplicaSet 确保任何时间都有指定数量的 Pod 副本在运行。
- 虽然 ReplicaSets 可以独立使用,但今天它主要被Deployments 用作协调 Pod 创
建、删除和更新的机制。
Deployment
- Deployment 为 Pod 和 ReplicaSet 提供了一个申明式的定义方法。
典型的应用场景:
- 用来创建Pod和ReplicaSet
- 滚动更新和回滚
- 扩容和缩容
- 暂停与恢复
DaemonSet
- DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时, 也会为他们新增一个 Pod 。当有节点从集群移除时,这些Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的典型用法:
- 在每个节点上运行集群存储 DaemonSet,例如 glusterd、ceph。
- 在每个节点上运行日志收集 DaemonSet,例如 fluentd、logstash。
- 在每个节点上运行监控 DaemonSet,例如 Prometheus Nodexporter、zabbix agent等
- 一个简单的用法是在所有的节点上都启动一个 DaemonSet,将被作为每种
类型的 daemon 使用。 - 一个稍微复杂的用法是单独对每种 daemon 类型使用多个 DaemonSet,
但具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。
StatefulSet
- StatefulSet 是用来管理有状态应用的工作负载 API 对象。实例之间有不对
等关系,以及实例对外部数据有依赖关系的应用,称为“有状态应用” - StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod
提供序号和唯一性保证。 - StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值:
- 稳定的、唯一的网络标识符。
- 稳定的、持久的存储。
- 有序的、优雅的部署和缩放。
- 有序的、自动的滚动更新。
Job
- 执行批处理任务,仅执行一次任务,保证任务的一个或多个Pod成功结束。
CronJob
- Cron Job 创建基于时间调度的 Jobs。
- 一个 CronJob 对象就像 crontab (cron table) 文件中的一行,它用 Cron
格式进行编写,并周期性地在给定的调度时间执行 Job。
HPA
- 根据资源利用率自动调整service中Pod数量,实现Pod水平自动缩放。
Replicaset控制器示例
[root@server2 manifest]# vim rs.yml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-example
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
[root@server2 manifest]# kubectl apply -f rs.yml
replicaset.apps/replicaset-example created
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
replicaset-example-dcrwh 1/1 Running 0 16s 10.244.2.38 server4 <none> <none>
replicaset-example-l8gw8 1/1 Running 0 16s 10.244.1.63 server3 <none> <none>
replicaset-example-mlx8p 1/1 Running 0 16s 10.244.2.39 server4 <none> <none>
[root@server2 manifest]# vim rs.yml
spec:
replicas: 2
[root@server2 manifest]# kubectl apply -f rs.yml 直接应用,不用删除之前的副本
replicaset.apps/replicaset-example configured
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
replicaset-example-dcrwh 1/1 Running 0 2m19s 10.244.2.38 server4 <none> <none>
replicaset-example-l8gw8 1/1 Running 0 2m19s 10.244.1.63 server3 <none> <none>
replicaset-example-mlx8p 0/1 Terminating 0 2m19s 10.244.2.39 server4 <none> <none>
//这个正在回收,默认会回收最新的pod
[root@server2 manifest]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/replicaset-example-dcrwh 1/1 Running 0 9m11s
pod/replicaset-example-l8gw8 1/1 Running 0 9m11s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
NAME DESIRED CURRENT READY AGE
replicaset.apps/replicaset-example 2 2 2 9m11s
// 多了一个控制器在前面
那我们让副本数不变,更换镜像哪?
spec:
replicas: 2
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2 // 改成v2
[root@server2 manifest]# kubectl apply -f rs.yml
replicaset.apps/replicaset-example configured
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
replicaset-example-dcrwh 1/1 Running 0 11m
replicaset-example-l8gw8 1/1 Running 0 11m
// 还是这两个pod,没有变。
[root@server2 manifest]# vim rs.yml
replicas: 4 //再将副本改称4个
...
image: myapp:v2
[root@server2 manifest]# kubectl apply -f rs.yml
replicaset.apps/replicaset-example configured
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
replicaset-example-bsckv 1/1 Running 0 2m 10.244.1.64 server3 <none> <none>
replicaset-example-dcrwh 1/1 Running 0 15m 10.244.2.38 server4 <none> <none>
replicaset-example-jkvfb 1/1 Running 0 2m 10.244.2.40 server4 <none> <none>
replicaset-example-l8gw8 1/1 Running 0 15m 10.244.1.63 server3 <none> <none>
// 新开起了两个容器,我们进行访问:
[root@server2 manifest]# curl 10.244.2.40
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@server2 manifest]# curl 10.244.1.64
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@server2 manifest]# curl 10.244.1.63
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
[root@server2 manifest]# curl 10.244.2.38
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
//通过访问我们发现,副本数不变更改镜像,不会发生改变,增加副本数改变镜像,新增的副本使用改变后的镜像。
若要想直接全部更新,就需要使用deployment
控制器了。
Deployment控制器
[root@server2 manifest]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment //和rs控制器写法一致,只有这里改变,因为deployment调用的底层就是rs控制器
metadata:
name: deployment-example
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
[root@server2 manifest]# kubectl apply -f deployment.yml
deployment.apps/deployment-example created
[root@server2 manifest]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deployment-example-7449b5b68f-cnxsw 1/1 Running 0 18s
pod/deployment-example-7449b5b68f-kv7zb 1/1 Running 0 18s
pod/deployment-example-7449b5b68f-rfbtf 1/1 Running 0 18s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment-example 3/3 3 3 18s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-example-7449b5b68f 3 3 3 18s
我们可以看到不止有deployment控制器
,还有rs控制器
。
pod/deployment-example-7449b5b68f-cnxsw
这个pod的名称是由 pod 名 + rs名 + pod唯一标示
组成的.
[root@server2 manifest]# vim deployment.yml
...
spec:
containers:
- name: myapp
image: myapp:v2 //将镜像换为v2
[root@server2 manifest]# kubectl apply -f deployment.yml
kubec deployment.apps/deployment-example configured
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-67764dd8bd-bqxt4 1/1 Running 0 7s
deployment-example-67764dd8bd-z8mf4 1/1 Running 0 5s
deployment-example-67764dd8bd-zwdgr 0/1 ContainerCreating 0 2s
deployment-example-7449b5b68f-cnxsw 0/1 Terminating 0 7m32s
deployment-example-7449b5b68f-kv7zb 1/1 Running 0 7m32s
deployment-example-7449b5b68f-rfbtf 1/1 Terminating 0 7m32s
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-67764dd8bd-bqxt4 1/1 Running 0 16s
deployment-example-67764dd8bd-z8mf4 1/1 Running 0 14s
deployment-example-67764dd8bd-zwdgr 1/1 Running 0 11s
现在我们在更换镜像的时候会直接删除原来的三个容器,重新打开三个pod。
而且:
[root@server2 manifest]# kubectl get all
...
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment-example 3/3 3 3 10m
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-example-67764dd8bd 3 3 3 3m4s
replicaset.apps/deployment-example-7449b5b68f 0 0 0 10m
生成了一个新的rs控制器,但是原来的rs还保留着,这是用于回滚的。
新生成的三个pod都使用的是新的rs控制器生成的。
- 回滚
[root@server2 manifest]# vim deployment.yml
...
spec:
containers:
- name: myapp
image: myapp:v1 //改回v1
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-7449b5b68f-c94st 1/1 Running 0 23s
deployment-example-7449b5b68f-f59mw 1/1 Running 0 20s
deployment-example-7449b5b68f-lwq2k 1/1 Running 0 17s
它就会使用原来的那个rs。
- pod更新
当我们发现一个pod的状态不正常时,我们可以直接删除这个pod,控制器回自动的拉取一个新的pod:
[root@server2 manifest]# kubectl delete pod deployment-example-7449b5b68f-c94st
pod "deployment-example-7449b5b68f-c94st" deleted
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deployment-example-7449b5b68f-f59mw 1/1 Running 0 4m14s //新pod
deployment-example-7449b5b68f-lwq2k 1/1 Running 0 4m11s
deployment-example-7449b5b68f-wwpgp 1/1 Running 0 17s
- pod删除
[root@server2 manifest]# kubectl delete -f deployment.yml
deployment.apps "deployment-example" deleted
[root@server2 manifest]# kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
// 连同控制器,rs,pod一块删除了
多个控制器
多个控制器和多个资源的放时一样,用—分割开就行了
[root@server2 manifest]# vim deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-v1
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v1
--- //分割线
apiVersion: apps/v1
kind: Deployment
metadata:
name: deployment-v2
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:v2
[root@server2 manifest]# kubectl apply -f deployment.yml
deployment.apps/deployment-v1 created
deployment.apps/deployment-v2 created
[root@server2 manifest]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
deployment-v1 3/3 3 3 10s
deployment-v2 3/3 3 3 10s
[root@server2 manifest]# kubectl get rs
NAME DESIRED CURRENT READY AGE
deployment-v1-7449b5b68f 3 3 3 105s
deployment-v2-67764dd8bd 3 3 3 105s
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-v1-7449b5b68f-csldb 1/1 Running 0 119s 10.244.1.73 server3 <none> <none>
deployment-v1-7449b5b68f-srkxx 1/1 Running 0 119s 10.244.2.49 server4 <none> <none>
deployment-v1-7449b5b68f-x5c59 1/1 Running 0 119s 10.244.2.50 server4 <none> <none>
deployment-v2-67764dd8bd-bmmrc 1/1 Running 0 119s 10.244.2.51 server4 <none> <none>
deployment-v2-67764dd8bd-m5c2g 1/1 Running 0 119s 10.244.1.75 server3 <none> <none>
deployment-v2-67764dd8bd-zf8wx 1/1 Running 0 119s 10.244.1.74 server3 <none> <none>
- 删除
[root@server2 manifest]# kubectl delete deployments.apps deployment-v1
deployment.apps "deployment-v1" deleted
[root@server2 manifest]# kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deployment-v1-7449b5b68f-g2s28 1/1 Terminating 0 87s
pod/deployment-v1-7449b5b68f-l4z8q 0/1 Terminating 0 87s
pod/deployment-v1-7449b5b68f-mqkqc 1/1 Terminating 0 87s
pod/deployment-v2-67764dd8bd-89t2z 1/1 Running 0 87s
pod/deployment-v2-67764dd8bd-rqsjn 1/1 Running 0 87s
pod/deployment-v2-67764dd8bd-sqrzg 1/1 Running 0 87s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 8d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deployment-v2 3/3 3 3 87s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deployment-v2-67764dd8bd 3 3 3 87s
删除v1,v2还在。
Daemonset控制器
Daemonset控制器适用于每个节点运行一个的pod。
我们之前使用的控制器不是在每个结点运行一个的,而是有可能都再一个结点运行:
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deployment-v1-7449b5b68f-jz5h9 0/1 ContainerCreating 0 3s <none> server4 <none> <none>
deployment-v1-7449b5b68f-lmksm 0/1 ContainerCreating 0 3s <none> server4 <none> <none>
deployment-v1-7449b5b68f-v9d64 0/1 ContainerCreating 0 3s <none> server4 <none> <none>
[root@server2 manifest]# vim daemonset.yml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: daemonset-example
labels:
k8s-app: zabbix-agent
spec:
selector:
matchLabels:
name: zabbix-agent
template:
metadata:
labels:
name: zabbix-agent
spec:
containers:
- name: zabbix-agent
image: zabbix-agent
[root@server2 manifest]# kubectl apply -f daemonset.yml
daemonset.apps/daemonset-example created
[root@server2 manifest]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
daemonset-example-67tmd 1/1 Running 0 6s 10.244.1.78 server3 <none> <none>
daemonset-example-qjtks 1/1 Running 0 6s 10.244.2.56 server4 <none> <none>
//一个结点一个,新加入的结点页回自动拉起一个这个pod
job控制器
[root@server2 manifest]# vim job.yml
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
template:
metadata:
name: example-job
spec:
containers:
- name: pi
image: perl
command: ["perl"]
args: ["-Mbignum=bpi", "-wle", "print bpi(2000)"] //计算pi的值.2000位
restartPolicy: Never
[root@server2 manifest]# kubectl apply -f job.yml
job.batch/example-job created
[root@server2 manifest]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
example-job-9vzb9 0/1 ContainerCreating 0 42s //正在拉取镜像,比较大
example-job-9vzb9 1/1 Running 0 50s //正在计算
example-job-9vzb9 0/1 Completed 0 54s //计算完毕
[root@server2 manifest]# kubectl logs example-job-9vzb9
3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384
[root@server2 manifest]# kubectl get job
NAME COMPLETIONS DURATION AGE
example-job 1/1 54s 3m16s
[root@server2 manifest]# kubectl delete -f job.yml
job.batch "example-job" deleted
[root@server2 manifest]# kubectl get job
No resources found in default namespace.
cronjob控制器
执行周期性任务。
[root@server2 manifest]# vim cronjob.yml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: cronjob-example
spec:
schedule: "* * * * *" //每分钟
jobTemplate:
spec:
template:
spec:
containers:
- name: cronjob
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from k8s cluster
restartPolicy: OnFailure
[root@server2 manifest]# kubectl apply -f cronjob.yml
cronjob.batch/cronjob-example created
No resources found in default namespace.
[root@server2 manifest]# kubectl get pod //每分钟执行一次,所以等待一分钟
No resources found in default namespace.
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
cronjob-example-1593239100-hd4mk 0/1 Completed 0 3s
[root@server2 manifest]# kubectl logs cronjob-example-1593239100-hd4mk
Sat Jun 27 06:25:03 UTC 2020
Hello from k8s cluster
//再等待一分钟
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
cronjob-example-1593239100-hd4mk 0/1 Completed 0 60s
[root@server2 manifest]# kubectl get pod
NAME READY STATUS RESTARTS AGE
cronjob-example-1593239100-hd4mk 0/1 Completed 0 66s
cronjob-example-1593239160-mzwrz 0/1 Completed 0 5s //又拉起一个