一、控制器简介
Kubernetes
中内建了很多controller
(控制器),这些相当于一个状态机,用来控制Pod
的具体状态和行为。 控制器大致分为如下介绍六种:
二、ReplicationController和ReplicaSet
ReplicationController
(RC
)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod
来替代;而如果异常多出来的容器也会自动回收;
在新版本的Kubernetes
中建议使用ReplicaSet
来取代RC
。ReplicaSet
跟 RC
没有本质的不同,只是名字不一样,并且ReplicaSet
支持集合式的selector
。
案例:
#编辑rs的yaml文件
[root@master resource]# vim rs.yaml
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
template:
metadata:
labels:
tier: frontend
spec:
containers:
- name: myapp
image: hub.hc.com/library/myapp:v1
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 80
[root@master resource]# kubectl create -f rs.yaml
[root@master resource]# kubectl get pod
NAME READY STATUS RESTARTS AGE
frontend-44vbw 1/1 Running 0 21s
frontend-9lx78 1/1 Running 0 21s
frontend-q54pf 1/1 Running 0 21s
[root@master resource]# kubectl get rs
NAME DESIRED CURRENT READY AGE
frontend 3 3 3 60s
#手动删除其中一个pod,验证副本功能
[root@master resource]# kubectl delete pod frontend-44vbw
pod "frontend-44vbw" deleted
#根据副本数会自动创建新的pod
[root@master resource]# kubectl get pod
NAME READY STATUS RESTARTS AGE
frontend-9lx78 1/1 Running 0 15m
frontend-q54pf 1/1 Running 0 15m
frontend-scbzb 1/1 Running 0 14s
三、Deployment
3.1 Deployment介绍和使用
Deployment
为Pod
和ReplicaSet
提供了一个声明式定义 (declarative
) 方法,用来替代以前的RC
来方便的管理应用。
典型的应用场景包括:
- 定义
Deployment
来创建Pod
和ReplicaSet
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续
Deployment
RS
与Deployment
的关联:
案例:
#编辑depolyment的yaml文件
[root@master resource]# vim deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: hub.hc.com/library/myapp:v1
ports:
- containerPort: 80
#创建Deploy,--record参数可以记录命令,我们可以很方便的查看每次 revision 的变化
[root@master resource]# kubectl create -f deployment.yaml --record
deployment.extensions/nginx-deployment created
[root@master resource]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 13s
[root@master resource]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-6b4dcdb44b 3 3 3 6m50s
[root@master resource]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6b4dcdb44b-bwzwq 1/1 Running 0 6m28s
nginx-deployment-6b4dcdb44b-kmv66 1/1 Running 0 6m28s
nginx-deployment-6b4dcdb44b-xmpcf 1/1 Running 0 6m28s
3.2 扩容
案例:
#扩展指定副本数为5
[root@master resource]# kubectl scale deployment nginx-deployment --replicas=5
deployment.extensions/nginx-deployment scaled
[root@master resource]# kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 5/5 5 5 20m
[root@master resource]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-6b4dcdb44b-b9knj 1/1 Running 0 43s
nginx-deployment-6b4dcdb44b-bwzwq 1/1 Running 0 20m
nginx-deployment-6b4dcdb44b-j278k 1/1 Running 0 43s
nginx-deployment-6b4dcdb44b-kmv66 1/1 Running 0 20m
nginx-deployment-6b4dcdb44b-xmpcf 1/1 Running 0 20m
如果集群支持horizontal pod autoscaling
的话,还可以为Deployment
设置自动扩展:
kubectl autoscale deployment nginx-deployment --min=10 --max=15 --cpu-percent=80
3.3 更新
案例:
#查看当前版本
[root@master resource]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6b4dcdb44b-b9knj 1/1 Running 0 5m58s 10.244.2.20 worker2 <none> <none>
nginx-deployment-6b4dcdb44b-bwzwq 1/1 Running 0 26m 10.244.2.18 worker2 <none> <none>
nginx-deployment-6b4dcdb44b-j278k 1/1 Running 0 5m58s 10.244.1.15 worker1 <none> <none>
nginx-deployment-6b4dcdb44b-kmv66 1/1 Running 0 26m 10.244.1.14 worker1 <none> <none>
nginx-deployment-6b4dcdb44b-xmpcf 1/1 Running 0 26m 10.244.2.19 worker2 <none> <none>
[root@master resource]# curl 10.244.2.20
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
#更改deployment中的nginx容器镜像版本
[root@master resource]# kubectl set image deployment/nginx-deployment nginx=wangyanglinux/myapp:v2
deployment.extensions/nginx-deployment image updated
#更新以后会创建新的rs
[root@master resource]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-5c478875d8 5 5 5 72s
nginx-deployment-6b4dcdb44b 0 0 0 31m
[root@master resource]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-5c478875d8-b5kh2 1/1 Running 0 83s 10.244.2.21 worker2 <none> <none>
nginx-deployment-5c478875d8-hrzl8 1/1 Running 0 65s 10.244.1.17 worker1 <none> <none>
nginx-deployment-5c478875d8-jvvbz 1/1 Running 0 83s 10.244.1.16 worker1 <none> <none>
nginx-deployment-5c478875d8-nm2cf 1/1 Running 0 64s 10.244.2.22 worker2 <none> <none>
nginx-deployment-5c478875d8-wj5w5 1/1 Running 0 52s 10.244.1.18 worker1 <none> <none>
[root@master resource]# curl 10.244.2.21
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
#同样可以使用edit命令来编辑Deployment
[root@master resource]# kubectl edit deployment/nginx-deployment
Deployment更新策略:
Deployment
可以保证在升级时只有一定数量的Pod
是down
的。默认的,它会确保至少有比期望的Pod
数量少一个是up
状态(最多一个不可用)
Deployment
同时也可以确保只创建出超过期望数量的一定数量的Pod
。默认的,它会确保最多比期望的Pod
数量多一个的Pod
是up
的(最多1个surge
)
未来的Kuberentes
版本中,将从1-1变成25%-25%
3.4 回滚
案例:
#执行回滚,默认回滚至上一次的版本
[root@master resource]# kubectl rollout undo deployment/nginx-deployment
deployment.extensions/nginx-deployment rolled back
[root@master resource]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-5c478875d8 0 0 0 5m34s
nginx-deployment-6b4dcdb44b 5 5 5 35m
[root@master resource]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6b4dcdb44b-5qk6n 1/1 Running 0 45s 10.244.2.23 worker2 <none> <none>
nginx-deployment-6b4dcdb44b-72zvc 1/1 Running 0 43s 10.244.2.24 worker2 <none> <none>
nginx-deployment-6b4dcdb44b-c2dls 1/1 Running 0 43s 10.244.1.20 worker1 <none> <none>
nginx-deployment-6b4dcdb44b-d8mwz 1/1 Running 0 42s 10.244.2.25 worker2 <none> <none>
nginx-deployment-6b4dcdb44b-p8ttm 1/1 Running 0 44s 10.244.1.19 worker1 <none> <none>
[root@master resource]# curl 10.244.2.25
Hello MyApp | Version: v1 | <a href="hostname.html">Pod Name</a>
#查看 rollout 的状态
[root@master resource]# kubectl rollout status deployment/nginx-deployment
deployment "nginx-deployment" successfully rolled out
Deployment回滚策略(多个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
都创建完成后才开始改变航道
更多回滚操作:
# 查看版本历史
$ kubectl rollout history deployment/nginx-deployment
#可以使用--revision参数指定某个历史版本
$ kubectl rollout undo deployment/nginx-deployment --to-revision=2
# 暂停 deployment 的更新
$ kubectl rollout pause deployment/nginx-deployment
清理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
,例如Prometheus Node Exporter
、collectd
、Datadog
代理、New Relic
代理,或Ganglia gmond
案例:
[root@master resource]# vim daemonset.yaml
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: hub.hc.com/library/myapp:v1
[root@master resource]# kubectl create -f daemonset.yaml
daemonset.apps/deamonset-example created
[root@master resource]# kubectl get pod
NAME READY STATUS RESTARTS AGE
deamonset-example-jjd5z 1/1 Running 0 7s
deamonset-example-nltnz 1/1 Running 0 7s
# 每个node都将部署daemonset
[root@master resource]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
deamonset-example-jjd5z 1/1 Running 0 14s 10.244.2.26 worker2 <none> <none>
deamonset-example-nltnz 1/1 Running 0 14s 10.244.1.21 worker1 <none> <none>
五、Job/CronJob
Job
负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod
成功结束。
Job
使用注意事项:
RestartPolicy
仅支持Never
或OnFailure
- 单个
Pod
时,默认Pod
成功运行后Job
即结束 .spec.completions
标志Job
结束需要成功运行的Pod
个数,默认为1.spec.parallelism
标志并行运行的Pod
的个数,默认为1spec.activeDeadlineSeconds
标志失败Pod
的重试最大时间,超过这个时间不会继续重试
案例:
#创建job的yaml
[root@master resource]# 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
[root@master resource]# kubectl create -f job.yaml
job.batch/pi created
[root@master resource]# kubectl get job
NAME COMPLETIONS DURATION AGE
pi 0/1 5s 5s
[root@master resource]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pi-g694b 1/1 Running 0 9s
# pod 的状态变成completed时查看日志
[root@master resource]# kubectl get pod
NAME READY STATUS RESTARTS AGE
pi-g694b 0/1 Completed 0 28s
[root@master resource]# kubectl log pi-g694b
log is DEPRECATED and will be removed in a future version. Use logs instead.
3.14159265358979323846264338327950288419716939937510582097494...
Cron Job
管理基于时间的Job
,即:在给定时间点只运行一次 && 周期性地在给定时间点运行。
使用前提条件:当前使用的Kubernetes
集群,版本 >= 1.8(对CronJob
);对于先前版本的集群,版本 <1.8,启动API Server
时,通过传递选项--runtime-config=batch/v2alpha1=true
可以开启batch/v2alpha1API
。
典型的用法如下所示:
- 在给定的时间点调度
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的yaml文件
[root@master resource]# vim cronjob.yaml
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
[root@master resource]# kubectl create -f cronjob.yaml
cronjob.batch/hello created
[root@master resource]# kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello */1 * * * * False 1 13s 15s
[root@master resource]# kubectl get jobs
NAME COMPLETIONS DURATION AGE
hello-1574487960 0/1 11s 11s
[root@master resource]# pods=$(kubectl get pods --selector=job-name=hello-1574487960 --output=jsonpath={.items..metadata.name})
[root@master resource]# kubectl logs $pods
Sat Nov 23 05:46:27 UTC 2019
Hello from the Kubernetes cluster
六、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)
七、Horizontal Pod Autoscaling
应用的资源使用率通常都有高峰和低谷的时候,如何削峰填谷,提高集群的整体资源利用率,让service
中的Pod
个数自动调整呢?这就有赖于Horizontal Pod Autoscaling
了,顾名思义,使Pod
水平自动缩放。