k8s 中 Pod 的控制器 - ZhanLi
source link: https://www.cnblogs.com/ricklz/p/16743702.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
k8s 中 Pod 的控制器
Pod 是 Kubernetes 集群中能够被创建和管理的最小部署单元。所以需要有工具去操作和管理它们的生命周期,这里就需要用到控制器了。
Pod 控制器由 master 的 kube-controller-manager
组件提供,常见的此类控制器有 Replication Controller、ReplicaSet、Deployment、DaemonSet、StatefulSet、Job
和 CronJob 等,它们分别以不同的方式管理 Pod 资源对象。
Replication Controller
RC 是 k8s 集群中最早的保证 Pod 高可用的 API 对象。它的作用就是保证集群中有指定数目的 pod 运行。
当前运行的 pod 数目少于指定的数目,RC 就会启动新的 pod 副本,保证运行 pod 数量等于指定数目。
当前运行的 pod 数目大于指定的数目,RC 就会杀死多余的 pod 副本。
直接上栗子
cat <<EOF >./pod-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
EOF
在新版的 Kubernetes 中建议使用 ReplicaSet (RS)来取代 ReplicationController。
ReplicaSet 跟 ReplicationController 没有本质的不同,只是名字不一样,但 ReplicaSet 支持集合式 selector。
关于 ReplicationController 这里也不展开讨论了,主要看下 ReplicaSet。
ReplicaSet
RS 是新一代 RC,提供同样的高可用能力,区别主要在于 RS 后来居上,能支持支持集合式 selector。
副本集对象一般不单独使用,而是作为 Deployment 的理想状态参数使用。
下面看下 Deployment 中是如何使用 ReplicaSet 的。
Deployment
一个 Deployment 为 Pod 和 ReplicaSet 提供声明式的更新能力,每一个 Deployment 都对应集群中的一次部署。
一般使用 Deployment 来管理 RS,可以用来创建一个新的服务,更新一个新的服务,也可以用来滚动升级一个服务。
滚动升级一个服务,滚动升级一个服务,实际是创建一个新的 RS,然后逐渐将新 RS 中副本数增加到理想状态,将旧 RS 中的副本数减小到 0 的复合操作;这样一个复合操作用一个 RS 是不太好描述的,所以用一个更通用的 Deployment 来描述。
cat <<EOF >./nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels: # 这里定义需要管理的 pod,通过 Pod 的标签进行匹配
app: nginx
template:
metadata:
labels: # 运行的 pod 的标签
app: nginx
spec:
containers: # pod 中运行的容器
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
EOF
$ kubectl apply -f nginx-deployment.yaml -n study-k8s
deployment.apps/nginx-deployment created
$ study-k8s kubectl describe deployment nginx-deployment -n study-k8s
Name: nginx-deployment
Namespace: study-k8s
CreationTimestamp: Mon, 26 Sep 2022 09:06:16 +0800
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 1 available | 2 unavailable
StrategyType: RollingUpdate # 默认是滚动更新
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge # 滚动更新的策略,最大 25% 不可用,最大 25% 增加
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 False MinimumReplicasUnavailable
Progressing True ReplicaSetUpdated
OldReplicaSets: <none>
NewReplicaSet: nginx-deployment-66b6c48dd5 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 3s deployment-controller Scaled up replica set nginx-deployment-66b6c48dd5 to 3
可以看到 Deployment 中默认的更新方式滚动更新,并且默认的滚动更新的策略是 最大 25% 不可用,最大 25% 增加。
更新 Deployment
1、直接更新
$ kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.20.1 -n study-k8s
# 或者
$ kubectl set image deployment/nginx-deployment nginx=nginx:1.20.1 -n study-k8s
2、对 Deployment 执行 edit 操作
$ kubectl get deployment -n study-k8s
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 18m
$ kubectl edit deployment -n study-k8s
# 修改对应的镜像版本,保存即可
spec:
containers:
- image: nginx:1.20.3
imagePullPolicy: IfNotPresent
name: nginx
3、直接编辑部署的 YAML 文件,然后重新 Apply
$ kubectl apply -f nginx-deployment.yaml -n study-k8s
deployment.apps/nginx-deployment configured
$ kubectl get pods -n study-k8s
NAME READY STATUS RESTARTS AGE
nginx-deployment-6bcf8f4884-dxxxg 1/1 Running 0 38s
nginx-deployment-6bcf8f4884-plbkh 0/1 ContainerCreating 0 13s
nginx-deployment-cc4b758d6-lzlxl 1/1 Running 0 7m25s
nginx-deployment-cc4b758d6-r5rkb 1/1 Running 0 7m11s
回滚 deployment
了解了如何更新 deployment,那么当部署出现问题,如果回滚呢,下面来详细介绍下
查看之前部署的版本
$ kubectl rollout history deployment/nginx-deployment -n study-k8s
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 <none>
2 <none>
3 <none>
4 <none>
5 <none>
6 <none>
7 image updated to 1.21.1
REVISION:就是之前部署的版本信息;
CHANGE-CAUSE:变动的备注信息。
$ kubectl apply -f nginx-deployment.yaml -n study-k8s --record
加上 --record
,或者每次部署完之后,使用
$ kubectl annotate deployment/nginx-deployment kubernetes.io/change-cause="image updated to 1.21.1" -n study-k8s
CHANGE-CAUSE 信息就会被记录
查看历史版本的详细详细
$ kubectl rollout history deployment/nginx-deployment --revision=6 -n study-k8s
deployment.apps/nginx-deployment with revision #6
Pod Template:
Labels: app=nginx
pod-template-hash=d985dd8bf
Containers:
nginx:
Image: nginx:1.20.3
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
# 回滚到上一个版本
$ kubectl rollout undo deployment/nginx-deployment -n study-k8s
# 回滚到指定的版本
$ kubectl rollout undo deployment/nginx-deployment --to-revision=5 -n study-k8s
缩放 Deployment
$ kubectl scale deployment/nginx-deployment --replicas=10 -n study-k8s
$ kubectl get pods -n study-k8s
NAME READY STATUS RESTARTS AGE
nginx-deployment-66b6c48dd5-5scbj 1/1 Running 0 44s
nginx-deployment-66b6c48dd5-7nmtp 1/1 Running 0 44s
nginx-deployment-66b6c48dd5-f5xsg 1/1 Running 0 12m
nginx-deployment-66b6c48dd5-fnpnb 1/1 Running 0 12m
nginx-deployment-66b6c48dd5-gg4ng 1/1 Running 0 44s
nginx-deployment-66b6c48dd5-qd5z7 1/1 Running 0 44s
nginx-deployment-66b6c48dd5-qqh4m 1/1 Running 0 44s
nginx-deployment-66b6c48dd5-xww49 1/1 Running 0 44s
nginx-deployment-66b6c48dd5-zndlh 1/1 Running 0 44s
nginx-deployment-66b6c48dd5-zp45g 1/1 Running 0 12m
关于使用 deployment 实现 k8s 中的几种部署策略,可参见Kubernetes 部署策略详解
StatefulSet
StatefulSet 用来管理有状态的应用。
在 Pods 管理的基础上,保证 Pods 的顺序和一致性。与 Deployment一样,StatefulSet 也是使用容器的 Spec 来创建Pod,与之不同 StatefulSet 创建的 Pods 在生命周期中会保持持久的标记(例如Pod Name)。
StatefulSet 适用于具有以下特点的应用:
1、稳定的、唯一的网络标识符;
2、稳定的、持久的存储;
3、有序的、优雅的部署和扩缩;
4、有序的、自动的滚动更新。
那么什么是有状态服务什么是无状态服务呢?
无状态服务
无状态服务不会在本地存储持久化数据。多个服务实例对于同一个用户请求的响应结果是完全一致的。这种多服务实例之间是没有依赖关系,比如web应用,在k8s控制器 中动态启停无状态服务的pod并不会对其它的pod产生影响。
有状态服务
有状态服务需要在本地存储持久化数据,典型的是分布式数据库的应用,分布式节点实例之间有依赖的拓扑关系。
比如,主从关系。 如果 K8S 停止分布式集群中任 一实例 pod,就可能会导致数据丢失或者集群的 crash。
cat <<EOF >./pod-statefulSet.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx
labels:
app: nginx
spec:
ports:
- port: 80
name: web
clusterIP: None
selector:
app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx # 必须匹配 .spec.template.metadata.labels
serviceName: "nginx"
replicas: 3 # 默认值是 1
template:
metadata:
labels:
app: nginx # 必须匹配 .spec.selector.matchLabels
spec:
terminationGracePeriodSeconds: 10
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
name: web
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumeClaimTemplates:
- metadata:
name: www
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
EOF
DaemonSet
DaemonSet:主要是用来保证集群中的每个节点只运行一个 Pod,且保证只有一个 Pod,这非常适合一些系统层面的应用,例如日志收集、资源监控等,这类应用需要每个节点都运行,且不需要太多实例,一个比较好的例子就是 Kubernetes 的 kube-proxy。
当有节点加入集群时, 也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。
DaemonSet 的应用场景:
1、在每个节点上运行集群守护进程;
2、在每个节点上运行日志收集守护进程;
3、在每个节点上运行监控守护进程。
cat <<EOF >./nginx-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
labels:
app: nginx-daemonset
spec:
selector:
matchLabels:
app: nginx-daemonset
template:
metadata:
labels:
app: nginx-daemonset
spec:
containers:
- name: nginx-daemonset
image: nginx:alpine
resources:
limits:
cpu: 250m
memory: 512Mi
requests:
cpu: 250m
memory: 512Mi
imagePullSecrets:
- name: default-secret
EOF
这样就能在每个节点中部署一个 Pod 了,不过 DaemonSet 也支持通过 label 来选择部署的目标节点
cat <<EOF >./nginx-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: nginx-daemonset
labels:
app: nginx-daemonset
spec:
selector:
matchLabels:
app: nginx-daemonset
template:
metadata:
labels:
app: nginx-daemonset
spec:
nodeSelector: # 节点选择,当节点拥有nodeName=node7时才在节点上创建Pod
nodeName: node7
containers:
- name: nginx-daemonset
image: nginx:alpine
resources:
limits:
cpu: 250m
memory: 512Mi
requests:
cpu: 250m
memory: 512Mi
imagePullSecrets:
- name: default-secret
EOF
Job 和 CronJob
Job 和 CronJob 是负责处理定时任务的。
两者的区别主要在于:
Job 负责处理一次性的定时任务,即仅需执行一次的任务;
CronJob 是基于时间的 Job,就类似于 Linux 系统的 crontab 文件中的一行,在指定的时间周期运行指定的 Job。
首先来创建一个 Job
cat <<EOF >./job-demo.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: job-demo
spec:
template:
metadata:
name: job-demo
spec:
restartPolicy: Never
containers:
- name: counter
image: busybox
command:
- "bin/sh"
- "-c"
- "echo hello"
EOF
$ kubectl apply -f job-demo.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
job-demo-8qrd9 0/1 Completed 0 40s
$ study-k8s kubectl get job
NAME COMPLETIONS DURATION AGE
job-demo 1/1 36s 45s
$ kubectl logs -f job-demo-8qrd9
hello
再来看下 CronJob
cat <<EOF >./cronJob-demo.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: "* * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox:1.28
imagePullPolicy: IfNotPresent
command:
- /bin/sh
- -c
- date; echo Hello
restartPolicy: OnFailure
EOF
通过 kubectl get jobs --watch
就能查看 CronJob 的调度
$ kubectl get jobs --watch
NAME COMPLETIONS DURATION AGE
hello-1664449860 1/1 2s 4s
hello-1664449920 0/1 0s
hello-1664449920 0/1 0s 0s
hello-1664449920 1/1 2s 2s
关于 pod 中的几个控制器最常用的就是 Deployment 和 ReplicaSet;
使用 Deployment 来管理 RS,来实现服务的部署,更新和滚动升级;
StatefulSet 主要用来管理无状态应用;
DaemonSet:主要是用来保证集群中的每个节点只运行一个 Pod,且保证只有一个 Pod,这非常适合一些系统层面的应用,例如日志收集、资源监控等,这类应用需要每个节点都运行,且不需要太多实例,一个比较好的例子就是 Kubernetes 的 kube-proxy;
Job 和 CronJob 是负责处理定时任务的;
Job 负责处理一次性的定时任务,即仅需执行一次的任务;
CronJob 是基于时间的 Job,就类似于 Linux 系统的 crontab 文件中的一行,在指定的时间周期运行指定的 Job。
【Deployments】https://kubernetes.io/zh-cn/docs/concepts/workloads/controllers/deployment/
【Kubernetes 部署策略详解】https://www.qikqiak.com/post/k8s-deployment-strategies/
【StatefulSet 和 Deployment 区别及选择方式】https://blog.csdn.net/nickDaDa/article/details/90401635
【K8S: 有状态 vs 无状态服务】https://zhuanlan.zhihu.com/p/390440336
【StatefulSet】https://support.huaweicloud.com/basics-cce/kubernetes_0015.html
【k8s 中 Pod 的控制器】https://boilingfrog.github.io/2022/09/30/k8s中Pod控制器/
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK