LEMON

记录站

0%

Controllers控制器(五)

Controllers 控制器

kubernetes不会直接创建pod,而是通过controller来管理pod的,所以controller负责维护集群的状态,比如故障检测、自动扩展、滚动更新。

Kubernetes中会有很多的controller(控制器),这些就相当于一个状态机(快照),用来控制Pod的具体状态和行为。

1. ReplicationController

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

2. ReplicaSet

在新版本的 Kubernetes 中建议使用 ReplicaSet来取代 ReplicationController 。ReplicaSet 跟ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector;

创建 ReplicaSet.yaml

在新版本的 Kubernetes 中建议使用 ReplicaSet来取代 ReplicationController 。ReplicaSet 跟ReplicationController 没有本质的不同,只是名字不一样,并且 ReplicaSet 支持集合式的 selector;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: web
template:
metadata:
labels:
tier: web
spec:
containers:
- name: nginx
image: nginx:latest
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80

简单使用下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
frontend-d8rs5 1/1 Running 0 29s tier=web
frontend-gczvb 1/1 Running 0 29s tier=web
frontend-twj7z 1/1 Running 0 29s tier=web

$ kubectl label pod frontend-d8rs5 tier=lemon --overwrite=true
pod/frontend-d8rs5 labeled
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
frontend-d8rs5 1/1 Running 0 3m3s tier=lemon
frontend-gczvb 1/1 Running 0 3m3s tier=web
frontend-mrm8n 1/1 Running 0 10s tier=web
frontend-twj7z 1/1 Running 0 3m3s tier=web

$ kubectl delete pod --all
pod "frontend-d8rs5" deleted
pod "frontend-gczvb" deleted
pod "frontend-mrm8n" deleted
pod "frontend-twj7z" deleted
$ kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
frontend-26xlj 1/1 Running 0 11s tier=web
frontend-m4vhl 1/1 Running 0 11s tier=web
frontend-zs9tk 1/1 Running 0 11s tier=web

# 删除 RS
$ kubectl delete rs frontend -n default

3. Deployment

Deployments(无状态,守护进程类,只关注群体不关注个体)

  • 一个 Deployment 控制器为 Pods和 ReplicaSets 提供声明式的更新能力。
  • 虽然 ReplicaSet可以独立使用,但一般还是建议使用 Deployment来自动管理ReplicaSe,这样就无需担心跟其他机制的不兼容问题(比如 ReplicaSe不支持rolling-update 但 Deployment支持)。

Deployment 为 Pod 和 ReplicaSet 提供了一个声明式定义 (declarative) 方法,用来替代以前的ReplicationController 来方便的管理应用。典型的应用场景包括;

  • 定义 Deployment 来创建 Pod 和 ReplicaSet
  • 应用扩容和缩容
  • 滚动升级和回滚
  • 暂停和继续 Deployment

3.1 创建一个 deployment 对象

Deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

检查应用状态

1
2
3
4
5
6
7
8
9
10
11
12
13
$ kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 62s

$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-687dc75df7 3 3 3 65s

$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-687dc75df7-88tkk 1/1 Running 0 68s
nginx-deployment-687dc75df7-b6whp 1/1 Running 0 68s
nginx-deployment-687dc75df7-ljh46 1/1 Running 0 68s

3.2 Deployment 扩容缩

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ kubectl scale deployment nginx-deployment --replicas=5
deployment.extensions/nginx-deployment scaled
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-687dc75df7-88tkk 1/1 Running 0 7m22s
nginx-deployment-687dc75df7-b6whp 1/1 Running 0 7m22s
nginx-deployment-687dc75df7-ljh46 1/1 Running 0 7m22s
nginx-deployment-687dc75df7-rnjzt 1/1 Running 0 8s
nginx-deployment-687dc75df7-wfx74 1/1 Running 0 8s

$ kubectl scale deployment nginx-deployment --replicas=2
deployment.extensions/nginx-deployment scaled
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-687dc75df7-88tkk 1/1 Running 0 8m18s
nginx-deployment-687dc75df7-ljh46 1/1 Running 0 8m18s

如果集群支持 horizontal pod autoscaling 的话,还可以为Deployment设置自动扩展

1
kubectl autoscale deployment nginx-deployment --min=10--max=15--cpu-percent=80

3.3 滚动升级和回滚

Deployment 更新策略

Deployment 可以保证在升级时只有一定数量的 Pod 是 down 的。默认的,它会确保至少有比期望的Pod数量少一个是up状态(最多一个不可用)。

Deployment 同时也可以确保只创建出超过期望数量的一定数量的 Pod。默认的,它会确保最多比期望的Pod数量多一个的 Pod 是 up 的(最多1个 surge )。

未来的 Kuberentes 版本中,将从1-1变成25%-25% 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 滚动升级
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.9.1
$ kubectl describe deploy nginx-deployment | grep -i 'image'
Image: nginx:1.9.1

# 回滚
$ kubectl rollout undo deployment/nginx-deployment
$ kubectl describe deploy nginx-deployment | grep -i 'image'
Image: nginx:1.7.9

# 也可以使用edit命令来编辑 Deployment
$ kubectl edit deployment nginx-deployment
40 - image: nginx:latest
deployment.extensions/nginx-deployment edited
$ kubectl describe deploy nginx-deployment | grep -i 'image'
Image: nginx:latest

# 更新镜像实际上就是重新创建了一个rs
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-5458686b99 2 2 2 23s
nginx-deployment-687dc75df7 0 0 0 18m
nginx-deployment-6df444bb79 0 0 0 5m55s

Rollover(多个rollout并行)

假如您创建了一个有5个niginx:1.7.9 replica的 Deployment,但是当还只有3个nginx:1.7.9的 replica 创建出来的时候您就开始更新含有5个nginx:1.9.1 replica 的 Deployment。在这种情况下,Deployment 会立即杀掉已创建的3个nginx:1.7.9的 Pod,并开始创建nginx:1.9.1的 Pod。它不会等到所有的5个nginx:1.7.9的Pod 都创建完成后才开始改变航道。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ kubectl rollout history deployment nginx-deployment
deployment.extensions/nginx-deployment
REVISION CHANGE-CAUSE
2 <none>
3 <none>
4 <none>

# 可以使用 --revision参数指定某个历史版本
$ kubectl rollout undo deployment nginx-deployment --to-revision=2
deployment.extensions/nginx-deployment rolled back
$ kubectl describe deploy nginx-deployment | grep -i 'image'
Image: nginx:1.9.1


$ ps: kubectl rollout pause deployment nginx-deployment ## 暂停 deployment 的更新

# 删除DeployMent
$ kubectl delete deployment nginx-deployment -n default

清理 Policy

可以通过设置.spec.revisonHistoryLimit项来指定 deployment 最多保留多少 revision 历史记录。默认的会保留所有的 revision;如果将该项设置为0,Deployment 就不允许回退了

4. DaemonSet

DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个Pod 。当有 Node 从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod

使用 DaemonSet 的一些典型用法:

  • 运行集群存储 daemon,例如在每个 Node 上运行glusterd、ceph
  • 在每个 Node 上运行日志收集 daemon,例如fluentd、logstash
  • 在每个 Node 上运行监控 daemon,例如Prometheus Node Exporter、collectd、Datadog 代理、New Relic 代理,或 Ganglia gmond

创建DaemonSet.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: deamonset-example
labels:
app: daemonset
spec:
selector:
matchLabels:
name: deamonset-example
template:
metadata:
labels:
name: deamonset-example
spec:
containers:
- name: daemonset-example
image: nginx:latest

看下是不是在所有node节点上都运行了

1
2
3
4
5
6
7
$ kubectl get pod -owide
NAME READY STATUS RESTARTS AGE
deamonset-example-tqmfx 1/1 Running 0 94s
deamonset-example-wqvsm 1/1 Running 0 94s

# 删除 DaemonSet
$ kubectl delete daemonset deamonset-example -n default

5. Jobs 一次性任务

一次性任务,运行完成后pod销毁,不再重新启动新容器。还可以任务定时运行。

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

特殊说明:

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

创建 Job.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

简单使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ kubectl get job
NAME COMPLETIONS DURATION AGE
pi 1/1 3m26s 8m54s

$ kubectl get pod
NAME READY STATUS RESTARTS AGE
pi-bfmq8 0/1 Completed 0 9m1s

$ kubectl log -f pi-bfmq8
log is DEPRECATED and will be removed in a future version. Use logs instead.
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275905

# 删除 Job
$ kubectl delete job pi -n default

6. CronJob 定时任务

cronjob 其实就是在job的基础上加上了时间调度,可以:在给定的时间点运行一个任务,也可以周期性的在给定时间点运行。(与linux中的crontab类似)

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

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

使用前提条件:当前使用的Kubernetes集群,版本 >= 1.8(对 CronJob)。对于先前版本的集群,版本 <1.8,启动 API Server时,通过传递选项–runtime-config=batch/v2alpha1=true可以开启 batch/v2alpha1API。

典型的用法如下所示:

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

特殊说明:

  • spec.template 格式同 Pod

  • RestartPolicy 仅支持 Never 或 OnFailure

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

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

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

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

  • 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.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure

简单使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 1 10s 22s

$ kubectl get job
NAME COMPLETIONS DURATION AGE
hello-1614322500 1/1 3s 62s
hello-1614322560 0/1 2s 2s

$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-1614322500-p7wmh 0/1 Completed 0 6s
hello-1614322560-vsz58 0/1 Completed 0 27s

$ kubectl logs -f hello-1614322500-p7wmh
Sat Mar 20 13:03:17 UTC 2021
Hello from the Kubernetes cluster

# 删除 cronjob
$ kubectl delete cronjob hello -n default

7. StateFulSet

StatefulSets(管理有状态应用) 作为 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)。

Ps 该控制器会在PV章节讲到。

8. Horizontal Pod Autoscaler

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

-------------本文结束感谢您的阅读-------------