文章目录
- 前言
- 一、 有状态应用与StatefulSet
- StatefulSet与Deployment的核心区别是什么?适用场景?
- 如何通过StatefulSet保证Pod的唯一性和顺序性?
- StatefulSet的持久化存储如何实现?(结合PVC/PV)
- 什么是Headless Service?为何StatefulSet需要它?
- StatefulSet的滚动更新策略与Deployment有何不同?
- 如何手动扩缩容StatefulSet的副本数?
- 如何为StatefulSet的每个Pod分配独立的存储?
- 解释StatefulSet的podManagementPolicy参数(OrderedReady与Parallel)。
- StatefulSet的Pod名称规则是什么?
- 如何通过StatefulSet部署有状态数据库(如MySQL主从)?
- 二、DaemonSet与Job/CronJob
- 总结
前言
工作多年,最近面试一直被问k8s相关的知识。k8s几年前搞过,最近几年一直在做开源项目相关的工作,又不是专业运维,好多知识点早已经模糊了。但是面试又喜欢问,叫什么,是什么,如何实现的,有没有这样的功能,原理是什么,原理的原理是什么,等等吧。
下面准备100道k8s面试题,不知道有没有人能顶得住。
一、 有状态应用与StatefulSet
StatefulSet与Deployment的核心区别是什么?适用场景?
核心区别:
维度 | Deployment | StatefulSet |
---|---|---|
设计目标 | 无状态应用(如Web服务、API网关) | 有状态应用(如MySQL、Redis、Zookeeper) |
Pod标识 | 动态随机名称(如nginx-xxxx) | 固定名称+序号(如mysql-0、mysql-1) |
存储管理 | 临时存储,需手动配置PVC | 自动创建独立PVC(通过VolumeClaimTemplate)。 |
扩缩容 | 并行扩缩容,无顺序约束 | 默认顺序启停(RederedReady),可配置并行。 |
网络标识 | 通过Service负载均衡 | 依赖Headless Service 提供唯一DNS记录 |
适用场景:
Deployment:Web应用、微服务、无状态计算任务、如Flink无状态节点。
StatefulSet:数据库集群(Mysql主从)、分布式存储(Ceph)、
消息队列(kafka)等需要持久化状态的应用。
如何通过StatefulSet保证Pod的唯一性和顺序性?
唯一性:Pod名称固定(如web-0、web-1),重建后名称不变。
顺序性:
启动顺序:按序号顺序创建
终止顺序:按逆序删除
滚动更新:默认按逆序更新(需手动配置策略)
StatefulSet的持久化存储如何实现?(结合PVC/PV)
VolumeClaimTemplate:自动为每个Pod创建独立PVC,名称格式为-statefulsetName-ordinal
spec:
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
什么是Headless Service?为何StatefulSet需要它?
DNS解析:为每个Pod生成唯一DNS记录。
无负载均衡:不分配ClusterIP,直接暴露Pod IP。
服务复现:通过DNS SRV记录支持有状态应用内部通信。
StatefulSet可以为每个Pod生成DNS名称,代替IP地址。通过DNS发现节点变化。这样Headless Service的Pod重启之后,还可以通过DNS绑定到Pod。不影响前台业务。
# Headless Service
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
clusterIP: None # Headless 模式
ports:
- port: 6379
selector:
app: redis
# StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis # 关联 Headless Service
replicas: 3
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7.0
args: ["--cluster-announce-ip", "$(POD_NAME).redis.default.svc.cluster.local"] # 使用 DNS 名称
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
StatefulSet的滚动更新策略与Deployment有何不同?
Deployment:支持RollingUpdate(并行)和Recreate(全停挂起)。
StatefulSet:默认按顺序滚动更新,可通过spec.updateStrategy配置为Parallel。
如何手动扩缩容StatefulSet的副本数?
kubectl scale statefulsets <name> --replicas=5
# 或通过编辑 YAML 修改 spec.replicas:ml-citation{ref="6,8" data="citationList"}
如何为StatefulSet的每个Pod分配独立的存储?
- 每个 Pod 自动绑定独立 PVC,存储与 Pod 生命周期解耦
- 示例:mysql-0 绑定 data-mysql-0,mysql-1 绑定 data-mysql-1
解释StatefulSet的podManagementPolicy参数(OrderedReady与Parallel)。
- OrderedReady(默认):顺序启停,保证强一致性。
- Paraller:并行启停,提升速度但牺牲顺序性。
StatefulSet的Pod名称规则是什么?
StatefulSet 管理的 Pod 名称遵循固定模式:statefulset-name-ordinal-index
statefulset-name
:StatefulSet 对象的名称(如 web、mysql)
ordinal-index
:从 0 开始的递增序号(如 0、1、2)。
示例:若 StatefulSet 名为 redis 且副本数为 3,Pod 名称为 redis-0、redis-1、redis-2。
如何通过StatefulSet部署有状态数据库(如MySQL主从)?
- 创建Headless Service
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
clusterIP: None
ports:
- port: 3306
selector:
app: mysql
- 定义StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql"
replicas: 3
template:
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
value: "root"
volumeMounts:
- name: data
mountPath: /var/lib/mysql
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi
- 主从配置:
初始化脚本:通过 Init Container 根据 Pod 序号(如 mysql-0 为主节点)生成配置文件。
数据同步:使用 MySQL Group Replication 或主从复制协议。
二、DaemonSet与Job/CronJob
DaemonSet的作用是什么?举例典型使用场景。
作用:DaemonSet确保集群中所有节点运行一个指定Pod副本,适用于节点守护进程的部署
适用场景:
- 日志采集:如Fluentd、Logstash等,每个节点采集日志
- 监控代理:如Prometheus Node Exporter、Sysdig Agent等,实时上报节点指标
- 网络插件:如Flannel、Calico等,保障集群网络互通。
- 存储守护进程:如Ceph OSD、Glusterd,管理分布式存储。
如何限制DaemonSet仅在特定节点运行?
- nodeSelector;基于节点选择目标节点
- affinify:定义节点亲和性规则,支持复杂的调度逻辑。
- tolerations:允许 Pod 调度到含特定污点的节点(如 node-role.kubernetes.io/master)
DaemonSet更新策略与Deployment的差异?
DaemonSet更新策略:
- 滚动更新:逐步节点替换旧Pod,支持控制最大不可用Pod数量
- 删除重建:支持删除旧Pod并创建新Pod
差异性: - 节点级更新:DaemonSet按节点顺序更新,而Deployment按副本数更新
- 目标范围:DaemonSet关注节点覆盖,Deployment关注副本数扩缩。
如何通过DaemonSet在每个节点运行日志收集组件(如Fluentd)?
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
spec:
selector:
matchLabels:
app: fluentd
template:
metadata:
labels:
app: fluentd
spec:
tolerations: # 允许调度到含污点的主节点
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: fluentd:1.16
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
hostPath:
path: /var/log
Job的作用是什么?如何定义一次性任务?
作用:用于管理一次性任务(如数据处理、批处理作业),确保任务成功完成指定次数后终止。
apiVersion: batch/v1
kind: Job
metadata:
name: batch-job
spec:
completions: 5 # 需完成的总任务数
parallelism: 2 # 并行执行的任务数
template:
spec:
containers:
- name: worker
image: batch-worker:1.0
restartPolicy: OnFailure
Job的restartPolicy与Pod的重启策略有何关联?
Job的restartPolicy:可选OnFailure或Never。
Pod的重启策略:由Job模版中的spce.template.spec.restartPolicy定义,必须与Job的RestartPolicy一致。
如何设置Job的并行度(parallelism与completions)?
parallelism:指定同时运行的 Pod 数量(默认 1)。
completions:指定需成功完成的 Pod 总数(默认 1)。
spec:
completions: 10 # 需完成 10 个任务
parallelism: 3 # 每次并行运行 3 个 Pod
CronJob的调度语法规则(与Crontab的差异)?
Cron 表达式:
Kubernetes 格式:分钟 小时 日 月 周(5 字段)。
Crontab 差异:不支持秒级调度,且月份和周字段的别名(如 MON)可能不兼容。
示例:
0 */6 * * *:每 6 小时执行一次。
如何避免CronJob任务的重叠执行(concurrencyPolicy)?
通过concurrencyPolicy控制并发行为:在这里插入代码片
Allow(默认):允许重叠执行
Forbid:禁止新任务执行,直到当前任务完成
Replace:取消当前任务,启动新任务。
如何清理CronJob执行后遗留的Job资源?
successfulJobsHistoryLimit:保留的成功 Job 数量(默认 3)。
failedJobsHistoryLimit:保留的失败 Job 数量(默认 1)。
spec:
successfulJobsHistoryLimit: 1
failedJobsHistoryLimit: 1
总结
- 通过 StatefulSet 固定 Pod 名称及 DNS 记录,结合 Headless Service 提供稳定域名,规避 IP 变化影响。应用层需适配 DNS 通信,避免依赖 IP。持久化存储确保数据一致性,滚动更新维护集群健康,保障有状态服务重启后网络与数据稳定。
- DaemonSet 适用于节点级守护进程,通过标签选择器和滚动更新保障稳定性13;Job 和 CronJob 管理一次性及定时任务,需合理配置并行度、重启策略和历史清理规则。