K8S基础知识:DaemonSet、Deployment、StatefulSet的用法区别
在 K8s 中,DaemonSet、Deployment 和 StatefulSet 都是用于管理 Pod 的资源对象,但它们的设计目的和适用场景有所不同,以下是它们用法的详细区别:
一、deployment
Deployment 用于管理无状态应用的多个 Pod 副本,它提供了声明式的方式来创建、更新和删除 Pod。Deployment 通过控制 ReplicaSet 来确保指定数量的 Pod 副本始终处于运行状态。
适用场景:
- Web 应用:适合部署 Web 服务器、API 服务等无状态应用。这些应用可以通过水平扩展来处理更多的流量, 可以方便地进行副本数量的调整和版本的更新。
- 微服务架构:在微服务架构中,Deployment 可以用于管理各个微服务的 Pod,实现微服务的快速部署和更新。
作用:
- 管理 Pod 副本:通过 Deployment 可以轻松地指定 Pod 的副本数量 replicas,确保应用程序具有足够的实例来处理负载。
- 滚动更新:支持对应用程序进行滚动更新,即在不中断服务的情况下逐步替换旧版本的 Pod 为新版本。
- 回滚:如果在更新过程中发现问题,Deployment 允许快速回滚到上一个稳定版本。Kubernetes 会自动将 Pod 恢复到之前的状态,确保服务的稳定性。
- 标签选择器:通过标签选择器来关联 Pod,能够方便地对一组具有相同标签的 Pod 进行管理和操作。例如,通过标签选择器
app: my-app
可以选中所有属于该应用的 Pod,进行统一的升级、扩缩容等操作。
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
spec:
replicas: 3 // 期望有 3 个副本
selector:
matchLabels:
apps: my-app // Deployment 会管理所有带有标签 apps: my-app标签的 Pod
template:
metadata:
labels:
apps: my-app // Pod 的标签的,跟上面 Deployment 标签关联
spec:
containers:
- name: my-container
image: my-image:latest
ports:
- containerPort: 80
常用操作:
以下是一个完整的示例,通过更新一个 Nginx 应用来展示相关操作:
# 查看当前Deployment
kubectl get deployments -n your-namespace
# 编辑Deployment
kubectl edit deployment nginx-deployment -n your-namespace
# 修改镜像版本
# 在编辑器中找到并修改 image 字段为新的版本
# image: nginx:1.21.0
# 保存并退出编辑器
# 监控滚动更新过程
kubectl rollout status deployment nginx-deployment -n your-namespace
# 查看Deployment历史版本
kubectl rollout history deployment nginx-deployment -n your-namespace
# 若需要回滚更新
kubectl rollout undo deployment nginx-deployment -n your-namespace
二、StatefulSet
StatefulSet 用于管理有状态应用的 Pod,它为每个 Pod 提供了稳定的网络标识和持久存储。StatefulSet 中的 Pod 有固定的名称和顺序,并且在删除和重新创建时会保留其状态。
适用场景:
- 数据库:适合部署有状态的数据库,如 MySQL、MongoDB 等。这些数据库需要稳定的网络标识和持久存储来保证数据的一致性和可靠性。
- 分布式系统:在分布式系统中,一些节点需要有固定的身份和顺序,如 ZooKeeper、Kafka 等,StatefulSet 可以满足这些需求。
特点:
- Pod 命名的稳定性:StatefulSet 中的每个 Pod 都有一个稳定且唯一的名称,名称格式为
<statefulset名称>-<序号>
,例如mysql-0
、mysql-1
等。这个稳定的命名在关联 PVC 时起到关键作用,即使 Pod 被删除和重新创建,名称也不会改变。 - PVC 命名规则:StatefulSet 使用 PVC 模板(
volumeClaimTemplates
)为每个 Pod 创建 PVC,PVC 的命名也与 Pod 相关联。通常 PVC 的名称格式为<PVC模板名称>-<Pod名称>
,比如mysql-pvc-mysql-0
。由于 Pod 名称稳定,重新创建 Pod 时,Kubernetes 会根据这个规则找到对应的 PVC。
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: zookeeper
# namespace: kafka
spec:
serviceName: zookeeper
replicas: 3 # 副本数
selector:
matchLabels:
app: zookeeper # StatefulSet 也会管理所有带有标签 app: zookeeper 标签的 Pod
template:
metadata:
labels:
app: zookeeper # pod标签
spec:
containers:
- name: zookeeper
image: bitnami/zookeeper:3.9.2
ports:
- containerPort: 2181
name: client
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
env:
- name: ALLOW_ANONYMOUS_LOGIN
value: "yes"
volumeMounts:
- name: zookeeper-data
mountPath: /bitnami/zookeeper # 定义了挂载到容器中的持久卷的名称及在容器内的挂载路径
restartPolicy: Always # 可选 ,默认Always:无论如何停止,都会自动重启pod容器
securityContext:
runAsUser: 0
fsGroup: 0
volumeClaimTemplates: # PVC模版
- metadata:
name: zookeeper-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
常用操作:
# 查看特定命名空间下的所有 StatefulSet:
kubectl get statefulsets -n your-namespace
# 使用 kubectl edit 命令编辑 StatefulSet 的 YAML 文件:
kubectl edit statefulset your-statefulset-name -n your-namespace
# 用以下命令监控更新进度:
kubectl rollout status statefulset your-statefulset-name -n your-namespace
# 若在更新过程中发现问题,可以使用以下命令回滚到上一个稳定版本:
kubectl rollout undo statefulset your-statefulset-name -n your-namespace
# 如果需要回滚到指定版本,可以添加 --to-revision 参数:
kubectl rollout undo statefulset your-statefulset-name --to-revision=2 -n your-namespace
三、DaemonSet
DaemonSet 的主要目的是确保在集群中的每个节点(或满足特定条件的节点)上都运行一个且仅运行一个 Pod 副本。每当有新节点加入集群时,DaemonSet 会自动在该节点上创建一个 Pod;当节点从集群中移除时,对应的 Pod 也会被自动删除。
适用场景:
- 系统层面服务:适合部署一些需要在每个节点上运行的系统级服务,如日志收集器(Fluentd、Filebeat)、监控代理(Prometheus Node Exporter)等。这些服务需要收集每个节点的日志或监控数据,因此需要在每个节点上都有一个实例。
- 存储服务:在某些情况下,需要在每个节点上运行存储相关的服务,如分布式存储系统的客户端,以确保每个节点都能访问存储资源。
特点:
- 每个节点运行一个实例:DaemonSet 的核心特点是确保在集群中的每个符合条件的节点上都运行一个且仅运行一个指定的 Pod 副本。当有新节点加入集群时,DaemonSet 会自动在该节点上创建对应的 Pod;而当节点从集群中移除时,该节点上的 Pod 也会被自动删除。。
- 节点选择:可以通过节点选择器(Node Selector)或节点亲和性(Node Affinity)来指定 DaemonSet 中的 Pod 应该运行在哪些特定的节点上。比如,你可以根据节点的标签(如节点的角色、硬件特性等)来筛选节点,让 Pod 只在具有特定标签的节点上运行。
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: logger-agent
labels:
apps: logger-agent
spec:
selector:
matchLabels:
apps: logger-agent-pod
template:
metadata:
labels:
apps: logger-agent-pod
spec:
tolerations: # pod 配置添加容忍 Master节点的污点 (也就是说,即使master节点有污点,也会被调度)( tolerations是一个列表字段,用于指定 Pod 可以容忍的节点污点)
- key: "node-role.kubernetes.io/master" # 这里定义了要容忍的污点的 key 值
operator: "Exists" # 定义了污点的操作符,Exists 表示节点必须存在这个污点才能被容忍,而 NoSchedule 表示节点不能被调度到。
# value: "NoSchedule" # 定义了要容忍的污点的 value 值,可以为空。
effect: "NoSchedule" # 定义了容忍的效果,即 Pod 可以调度到那些设置了 NoSchedule 效果的污点的节点上
volumes: # 映射Pod对外的挂载
- name: logger-agent-log # Pod要挂载的名称指代,即指向volumeMounts的name
hostPath: # 采用主机目录的挂载方式
path: /data/log/ac-logger-agent
type: DirectoryOrCreate #没有的话,会自动创建目录
- name: log-path
hostPath:
path: /data/log/
type: DirectoryOrCreate
containers:
- name: logger-agent
image: logger-agent:v1.02
imagePullPolicy: IfNotPresent
ports:
- name: http
protocol: TCP
containerPort: 5046
volumeMounts: # Pod的数据卷挂载
- name: logger-agent-log
mountPath: /log
- name: log-path
mountPath: /data/log/
env:
- name: LOG_DIR
value: /data/log/
- name: LOG_LEVEL # 日志打印级别
value: INFO
envFrom:
- configMapRef:
name: access-env
四、StatefulSet 与 Deployment 的滚动更新差异
- 更新顺序:StatefulSet 默认采用顺序更新,即从编号最大的 Pod 开始逐个更新,这是为了保证有状态应用的稳定性。而 Deployment 的滚动更新可以根据配置并行更新多个 Pod。
- 网络标识和存储:StatefulSet 中的每个 Pod 有稳定的网络标识和持久存储,更新过程中这些标识和存储会得到保留。而 Deployment 管理的无状态 Pod 在更新时通常不会关注这些特性。
- 更新策略:StatefulSet 支持
OnDelete
和RollingUpdate
两种更新策略。OnDelete
策略下,需要手动删除 Pod 才会触发更新;RollingUpdate
则会自动进行滚动更新。Deployment 默认使用RollingUpdate
策略。