k8s 中 Pod 的控制器
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控制器/
k8s 中 Pod 的控制器的更多相关文章
- K8s中Pod健康检查源代码分析
了解k8s中的Liveness和Readiness Liveness: 表明是否容器正在运行.如果liveness探测为fail,则kubelet会kill掉容器,并且会触发restart设置的策略. ...
- k8s中pod内dns无法解析的问题
用k8s创建了pod,然后进入pod后,发现在pod中无法解析www.baidu.com,也就是出现了无法解析外面的域名的问题.经过高人指点,做个小总结.操作如下. 一,将CoreDNS 的Confi ...
- Jenkins和Gitlab CI/CD自动更新k8s中pod使用的镜像说明
Jenkins 使用Jenkins的话,完成的工作主要有如下步骤: 1.从Gogs或Gitlab仓库上拉取代码 2.使用Maven编译代码,打包成jar文件 3.根据jar文件使用相对应的Docker ...
- k8s中pod的yaml文件全面解读
apiVersion: v1 #必选,版本号,例如v1,版本号必须可以用 kubectl api-versions 查询到 . kind: Pod #必选,Pod metadata: #必选,元数据 ...
- k8s中pod的容器日志查看命令
如果容器已经崩溃停止,您可以仍然使用 kubectl logs --previous 获取该容器的日志,只不过需要添加参数 --previous. 如果 Pod 中包含多个容器,而您想要看其中某一个容 ...
- 延申三大问题中的第二个问题处理---收集查看k8s中pod的控制台日志
1.不使用logstash 2.步骤: 2.1 先获取一个文件的日志 2.2 再获取多个文件的日志 2.3 批量获取文件日志 pod日志文件路径 [root@worker hkd-eureka]# p ...
- K8S中POD节点状态ContainerCreating原因排查
现象: # kubectl get pods -n kube-system |grep dashboard kubernetes-dashboard-6685cb584f-dqkwk 0/1 Cont ...
- k8s中ingress,service,depoyment,pod如何关联
k8s中pod通过label标签名称来识别关联,它们的label name一定是一样的.ingress,service,depoyment通过selector 中app:name来关联 1.查询发布 ...
- k8s 中的 Pod 细节了解
k8s中Pod的理解 基本概念 k8s 为什么使用 Pod 作为最小的管理单元 如何使用 Pod 1.自主式 Pod 2.控制器管理的 Pod 静态 Pod Pod的生命周期 Pod 如何直接暴露服务 ...
随机推荐
- jdbc 10:jdbc事务
jdbc连接mysql,涉及到的事务问题 package com.examples.jdbc.o10_jdbc事务; import java.sql.Connection; import java.s ...
- Git上传仓库
上传代码到gitee 方法1 1. 将远程仓库克隆到本地 git clone https://gitee.com/abc/aaa.git 2. 添加或修改本地文件 3. 将本地代码push到远程仓库 ...
- linux docker .net core 从建立网站到预览
docker的安装在网上一搜一大把,windows安装的就是exe双击,linux安装需要执行语句 ps:需要准备xftp.xshell.vs 2019.linux服务器.docker账号密码 例如: ...
- vscode 个人配置 settings.json
{ "workbench.colorTheme": "Default Dark+", "workbench.iconTheme&quo ...
- Python3.7+Django2.0.4配合Mongodb打造高性能高扩展标签云存储方案
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_141 书接上回,之前有一篇文章提到了标签云系统的构建:Python3.7+jieba(结巴分词)配合Wordcloud2.js来构 ...
- 人工智能不过尔尔,基于Python3深度学习库Keras/TensorFlow打造属于自己的聊天机器人(ChatRobot)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_178 聊天机器人(ChatRobot)的概念我们并不陌生,也许你曾经在百无聊赖之下和Siri打情骂俏过,亦或是闲暇之余与小爱同学谈 ...
- 小白之Python基础(二)
一.字符串 1.字符串编码发展: 1)ASCII码: 一个字节去表示 (8个比特(bit)作为一个字节(byte),因此,一个字节能表示的最大的整数就是255(二进制11111111 = 十进制255 ...
- Apache DolphinScheduler 社区呼唤志愿者
DolphinScheduler是什么? Apache DolphinScheduler 是一个分布式.易扩展并带有强大的可视化界面的大数据工作流调度系统. 2021 年 03 月 18 日正式成为 ...
- identity4 系列————启航篇[二]
前言 开始identity的介绍了. 正文 前文介绍了一些概念,如果概念不清的话,可以去前文查看. https://www.cnblogs.com/aoximin/p/13475444.html 对一 ...
- docker启动失败问题
内核3.10,systemctl start docker 被阻塞,没有返回,查看状态为启动中. 某兄弟机器安装docker之后,发现systemctl start docker的时候阻塞,由于排查走 ...