5、Kubernetes核心技术 - Controller控制器工作负载
我们看到,最下面的Scaled up replica set nginx-deployment-85996f8dbd to 3,其实就是运行三个副本的Pod,在k8s中它是通过ReplicaSet(副本集)来实现的,当我们创建一个deployment的时候,会自动创建一个ReplicaSet来管理pod的副本数量。在实际的场景中,并不能满足所有应用,尤其是分布式应用,会部署多个实例,这些实例之间往
目录
一、Deployments - 控制器应用
Deployment 表示用户对 K8S 集群的一次更新操作。Deployment 控制器可以部署无状态应用,管理 Pod 和 ReplicaSet、部署,滚动升级等功能。
下面是一个 Deployment 示例。
其中创建了一个 ReplicaSet,负责启动三个 nginx Pod:
vim simple-deployment.yam
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment # 后续创建 ReplicaSet 和 Pod 的命名基础
labels:
app: nginx
spec:
replicas: 3 # pod的副本数量
selector:
matchLabels:
app: nginx # 定义所创建的 ReplicaSet 如何查找要管理的 Pod
template:
metadata:
labels:
app: nginx # pod模板标签
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
创建Deployment:
$ kubectl create -f simple-deployment.yaml
deployment.apps/nginx-deployment created
# 查看deployment是否创建
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 13s
注意 Deployment 已创建全部三个副本,并且所有副本都是最新的(它们包含最新的 Pod 模板) 并且可用。字段说明:
- NAME 列出了名字空间中 Deployment 的名称。
- READY 显示应用程序的可用的“副本”数。显示的模式是“就绪个数/期望个数”。
- UP-TO-DATE 显示为了达到期望状态已经更新的副本数。
- AVAILABLE 显示应用可供用户使用的副本数。
- AGE 显示应用程序运行的时间。
我们可以通过kubectl describe [deployment-name]查看deployment的相关事件:
$ kubectl describe deploy nginx-deployment
Name: nginx-deployment
Namespace: default
CreationTimestamp: Mon, 06 Feb 2023 06:58:59 +0000
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=nginx
Containers:
nginx:
Image: nginx:1.14.2
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: nginx-deployment-85996f8dbd (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 101s deployment-controller Scaled up replica set nginx-deployment-85996f8dbd to 3
我们看到,最下面的Scaled up replica set nginx-deployment-85996f8dbd to 3,其实就是运行三个副本的Pod,在k8s中deployment是通过ReplicaSet(副本集)来实现的,当我们创建一个deployment的时候,会自动创建一个ReplicaSet来管理pod的副本数量。
查看 Deployment 创建的 ReplicaSet(rs):
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deployment-85996f8dbd 3 3 3 3m13s
ReplicaSet 输出中包含以下字段:
- NAME 列出名字空间中 ReplicaSet 的名称;
- DESIRED 显示应用的期望副本个数,即在创建 Deployment 时所定义的值。 此为期望状态;
- CURRENT 显示当前运行状态中的副本个数;
- READY 显示应用中有多少副本可以为用户提供服务;
- AGE 显示应用已经运行的时间长度。
注意 ReplicaSet 的名称格式始终为 [Deployment 名称]-[哈希]。 该名称将成为所创建的 Pod 的命名基础。 其中的哈希字符串与 ReplicaSet 上的 pod-template-hash 标签一致。
查看ReplicaSet相关事件:
$ kubectl describe rs nginx-deployment-85996f8dbd
Name: nginx-deployment-85996f8dbd
Namespace: default
Selector: app=nginx,pod-template-hash=85996f8dbd
Labels: app=nginx
pod-template-hash=85996f8dbd
Annotations: deployment.kubernetes.io/desired-replicas: 3
deployment.kubernetes.io/max-replicas: 4
deployment.kubernetes.io/revision: 1
Controlled By: Deployment/nginx-deployment
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: app=nginx
pod-template-hash=85996f8dbd
Containers:
nginx:
Image: nginx:1.14.2
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 3m24s replicaset-controller Created pod: nginx-deployment-85996f8dbd-q9plt
Normal SuccessfulCreate 3m24s replicaset-controller Created pod: nginx-deployment-85996f8dbd-knwkv
Normal SuccessfulCreate 3m24s replicaset-controller Created pod: nginx-deployment-85996f8dbd-vcs8d
可以看到,replicaset-controller负责创建三个nginx的Pod。
二、Deployment升级回滚和弹性收缩
- 升级: 假设从版本为 1.14 升级到 1.15 ,这就叫应用的升级【升级可以保证服务不中断】;
- 回滚:从版本 1.15 变成 1.14,这就叫应用的回滚;
- 弹性伸缩:我们根据不同的业务场景,来改变 Pod 的数量对外提供服务,这就是弹性伸缩;
2.1、创建一个 1.14 版本的 pod
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: web
name: web
spec:
replicas: 1
selector:
matchLabels:
app: web
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: web
spec:
containers:
# 修改 nginx 版本 1.14
- image: nginx:1.14
name: nginx
resources: {}
status: {}
创建pod:
$ kubectl apply -f nginx.yaml
如上图,可以看到, 当前运行的nginx容器的镜像版本是1.14。
2.2、应用升级
$ kubectl set image deployment web nginx=nginx:1.15
升级过程:
$ kubectl set image deployment web nginx=nginx:1.15
deployment.apps/web image updated
# 首先是开始的 nginx 1.14 版本的 Pod 在运行,然后 1.15 版本的在创建
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
web-66bf4959f5-qhzsd 1/1 Running 0 52s
web-bbcf684cb-bbmqv 0/1 ContainerCreating 0 3s
# 然后在 1.15 版本创建完成后,就会暂停 1.14 版本
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
web-66bf4959f5-qhzsd 1/1 Terminating 0 67s
web-bbcf684cb-bbmqv 1/1 Running 0 18s
# 最后把 1.14 版本的 Pod 移除,完成我们的升级
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
web-bbcf684cb-bbmqv 1/1 Running 0 33s
我们在下载 1.15 版本,容器就处于 ContainerCreating 状态,然后下载完成后,就用 1.15 版本去替换 1.14 版本了,这么做的好处就是:升级可以保证服务不中断。
2.3、查看升级状态
$ kubectl rollout status deployment web
deployment "web" successfully rolled out
2.4、查看历史版本
$ kubectl rollout history deployment web
deployment.apps/web
REVISION CHANGE-CAUSE
1 <none>
2 <none>
2.5、应用回滚
# 回滚到上一版本
$ kubectl rollout undo deployment web
# 回滚到指定版本
$ kubectl rollout undo deployment web --to-revision=2
如上图,可以看到,通过kubectl rollout undo成功回滚到上一个版本,镜像版本又变成1.14了。当然还可以指定--to-revision回滚到指定的版本。
2.6、弹性伸缩
# 创建5个pod副本
$ kubectl scale deployment web --replicas=5
deployment.apps/web scaled
# 输出结果,等一会就会全部 Running
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
web-5b9d46fdff-2v2rt 1/1 Running 0 24s
web-5b9d46fdff-4lz7w 1/1 Running 0 24s
web-5b9d46fdff-7tq9x 1/1 Running 0 3m42s
web-5b9d46fdff-mfqhb 1/1 Running 0 24s
web-5b9d46fdff-sfx6q 1/1 Running 0 24s
三、StatefulSet - 有状态应用
Deployment控制器设计原则:管理的所有Pod一模一样,提供同一个服务,也不考虑在哪台Node 运行,可随意扩容和缩容。这种应用称为“无状态”,例如Web服务。
在实际的场景中,并不能满足所有应用,尤其是分布式应用,会部署多个实例,这些实例之间往往有依赖关系,例如主从关系、主备关系,这种应用称为“有状态”,例如MySQL主从、Etcd集群。
这时候就需要有状态部署了,有状态部署有以下几个特点:
- 1、每个pod角色不同(不对等)
- 2、pod之间有连接关系
- 3、每个pod都有独立的存储
StatefulSet控制器用于部署有状态应用,满足一些有状态应用的需求:
• Pod有序的部署、扩容、删除和停止;
• Pod分配一个稳定的且唯一的网络标识;
• Pod分配一个独享的存储;
稳定的Pod网络标识:使用Headless Service(相比普通Service只是将spec.clusterIP定义为None)。
维护Pod网络身份,会为每个Pod分配一个数字编号并且按照编号顺序部署。
稳定主要体现在主机名和Pod A记录:
• 主机名:<statefulset名称>-<编号>
• Pod DNS A记录:<statefulset名称-编号>.<service-name> .<namespace>.svc.cluster.local
通过一个StatefulSet有状态应用的例子来说明:
准备sta.yaml文件:
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
labels:
app: nginx
spec:
clusterIP: None
ports:
- port: 80
name: nginx
protocol: TCP
targetPort: 80
selector:
app: nginx
type: ClusterIP
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
spec:
serviceName: nginx
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
创建并查看pod:
$ kubectl apply -f sta.yaml
service/nginx created
statefulset.apps/nginx-statefulset created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-statefulset-0 1/1 Running 0 62s
nginx-statefulset-1 1/1 Running 0 43s
nginx-statefulset-2 1/1 Running 0 39s
可以看到,每个pod都有一个唯一的名称。
[root@localhost ~]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m
nginx ClusterIP None <none> 80/TCP 110s
可以看到,CULSTER-IP为None,说明这是一个Headless Service。
四、DaemonSet - 守护进程
DaemonSet 确保全部节点上都运行一个 Pod 的副本。 当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的一些典型用法:
- 在每个节点上运行集群守护进程
- 在每个节点上运行日志收集守护进程
- 在每个节点上运行监控守护进程
一种简单的用法是为每种类型的守护进程在所有的节点上都启动一个 DaemonSet。 一个稍微复杂的用法是为同一种守护进程部署多个 DaemonSet;每个具有不同的标志, 并且对不同硬件类型具有不同的内存、CPU 要求。
DaemonSet示例:
vim daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
创建并查看pod:
# 当前集群中存在两个节点
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
controlplane Ready control-plane 2d17h v1.26.0
node01 Ready <none> 2d16h v1.26.0
$ kubectl apply -f daemonset.yaml
daemonset.apps/nginx created
# nginx pod在两个节点都处于运行状态
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-frmjc 1/1 Running 0 6s 192.168.1.4 node01 <none> <none>
nginx-qdb7s 1/1 Running 0 6s 192.168.0.8 controlplane <none> <none>
五、Job - 单次任务
Job 会创建一个或者多个 Pod,并将继续重试 Pod 的执行,直到指定数量的 Pod 成功终止。 随着 Pod 成功结束,Job 跟踪记录成功完成的 Pod 个数。 当数量达到指定的成功个数阈值时,任务(即 Job)结束。 删除 Job 的操作会清除所创建的全部 Pod。 挂起 Job 的操作会删除 Job 的所有活跃 Pod,直到 Job 被再次恢复执行。
示例 Job:下面是一个 Job 配置示例。它负责计算 π 到小数点后 2000 位,并将结果打印出来。 此计算大约需要 10 秒钟完成。
vim job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: pi-job
spec:
template:
spec:
containers:
- name: pi
image: perl:5.34.0
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: Never
backoffLimit: 4
创建并查看job:
$ kubectl apply -f job.yaml
job.batch/pi-job created
$ kubectl get job
NAME COMPLETIONS DURATION AGE
pi-job 1/1 30s 82s
$ kubectl describe job pi-job
Name: pi-job
Namespace: default
Selector: controller-uid=63b08866-0f04-4326-98ac-08118ec419d7
Labels: controller-uid=63b08866-0f04-4326-98ac-08118ec419d7
job-name=pi-job
Annotations: batch.kubernetes.io/job-tracking:
Parallelism: 1
Completions: 1
Completion Mode: NonIndexed
Start Time: Sun, 29 Jan 2023 07:48:01 +0000
Completed At: Sun, 29 Jan 2023 07:48:31 +0000
Duration: 30s
Pods Statuses: 0 Active (0 Ready) / 1 Succeeded / 0 Failed
Pod Template:
Labels: controller-uid=63b08866-0f04-4326-98ac-08118ec419d7
job-name=pi-job
Containers:
pi:
Image: perl:5.34.0
Port: <none>
Host Port: <none>
Command:
perl
-Mbignum=bpi
-wle
print bpi(2000)
Environment: <none>
Mounts: <none>
Volumes: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 84s job-controller Created pod: pi-job-q7h7c
Normal Completed 54s job-controller Job completed
要查看 Job 对应的已完成的 Pod,可以执行 kubectl get pod:
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
pi-job-q7h7c 0/1 Completed 0 117s
# 查看Pod的标准输出
$ kubectl logs pi-job-q7h7c
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788659361533818279682303019520353018529689957736225994138912497217752834791315155748572424541506959508295331168617278558890750983817546374649393192550604009277016711390098488240128583616035637076601047101819429555961989467678374494482553797747268471040475346462080466842590694912933136770289891521047521620569660240580381501935112533824300355876402474964732639141992726042699227967823547816360093417216412199245863150302861829745557067498385054945885869269956909272107975093029553211653449872027559602364806654991198818347977535663698074265425278625518184175746728909777727938000816470600161452491921732172147723501414419735685481613611573525521334757418494684385233239073941433345477624168625189835694855620992192221842725502542568876717904946016534668049886272327917860857843838279679766814541009538837863609506800642251252051173929848960841284886269456042419652850222106611863067442786220391949450471237137869609563643719172874677646575739624138908658326459958133904780275901
六、Cronjob - 定时任务
CronJob 创建基于时隔重复调度的 Job。
CronJob 用于执行排期操作,例如备份、生成报告等。 一个 CronJob 对象就像 Unix 系统上的 crontab(cron table)文件中的一行。 它用 Cron 格式进行编写, 并周期性地在给定的调度时间执行 Job。
CronJob示例:下面的 CronJob 示例清单会在每分钟打印出当前时间和问候消息
vim cronjob.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: hello-cronjob
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: busybox
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
创建并查看cronjob:
$ kubectl create -f cronjob.yaml
cronjob.batch/hello-cronjob created
$ kubectl get cronjob
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
hello-cronjob * * * * * False 0 <none> 6s
$ kubectl describe cronjob hello-cronjob
Name: hello-cronjob
Namespace: default
Labels: <none>
Annotations: <none>
Schedule: * * * * *
Concurrency Policy: Allow
Suspend: False
Successful Job History Limit: 3
Failed Job History Limit: 1
Starting Deadline Seconds: <unset>
Selector: <unset>
Parallelism: <unset>
Completions: <unset>
Pod Template:
Labels: <none>
Containers:
busybox:
Image: busybox:1.28
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
date; echo Hello from the Kubernetes cluster
Environment: <none>
Mounts: <none>
Volumes: <none>
Last Schedule Time: Sun, 29 Jan 2023 07:57:00 +0000
Active Jobs: hello-cronjob-27916317
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 1s cronjob-controller Created job hello-cronjob-27916317
查看cronjob生成的pod:
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-cronjob-27916317-zdc9d 0/1 Completed 0 100s
hello-cronjob-27916318-nx65t 0/1 Completed 0 40s
$ kubectl logs hello-cronjob-27916317-zdc9d
Sun Jan 29 07:57:02 UTC 2023
Hello from the Kubernetes cluster
$ kubectl logs hello-cronjob-27916318-nx65t
Sun Jan 29 07:58:00 UTC 2023
Hello from the Kubernetes cluster
可以看到,cronjob每分钟就会生成一个对应的pod,然后日志输出当前时间和对应的提示消息。
更多推荐
所有评论(0)