kubernetes核心技术-Controller

什么是Controller

集群的智能管家

Controller是Kubernetes的核心控制回路,通过持续监控集群状态并驱动实际状态向期望状态收敛。它解决了分布式系统中的状态维护难题,确保应用在节点故障、资源波动等情况下保持稳定运行。

典型案例:当Node节点意外宕机时,ReplicaSet Controller会立即检测到Pod缺失,并在健康节点上重新创建Pod,整个过程通常在10-30秒内完成。

Kubernetes Controller 类型对比

Controller类型核心用途Pod标识部署顺序存储卷伸缩特性典型应用场景
Deployment管理无状态应用随机名称无序无状态或共享存储平滑伸缩Web服务、API微服务
StatefulSet管理有状态应用固定名称(web-0,1,2)有序专属持久卷(PV)需手动逐实例伸缩数据库(MySQL/MongoDB)、消息队列
DaemonSet节点级守护进程随机名称无序通常不需要跟随节点自动伸缩日志收集(Fluentd)、节点监控
Job单次任务随机名称无序临时存储不可伸缩数据处理、批量计算
CronJob定时任务随机名称无序临时存储按计划执行定期备份、报表生成

无状态应用 vs 有状态应用对比

特性无状态应用有状态应用
实例关系各实例完全独立实例间有主从、分片等依赖关系
数据存储不保存本地状态(状态存外部DB/缓存)需持久化存储本地状态(数据库文件/消息队列数据)
请求处理请求可被任意实例处理特定请求需路由到特定实例(如分片查询)
伸缩特性秒级快速伸缩需谨慎操作(如主从切换/数据迁移)
故障恢复新实例自动接管工作需恢复特定数据/状态
网络标识无需固定网络地址需稳定网络标识(如集群节点发现)
部署方式Deployment + ServiceStatefulSet + Headless Service
存储需求临时存储或共享存储持久化专属存储(PV/PVC)
配置管理ConfigMap/环境变量注入需实例级差异化配置
升级策略滚动更新(一次性替换所有实例)需按序更新(如先备后主)
典型代表Nginx、Node.js应用、无状态微服务MySQL集群、Redis集群、Zookeeper集群
扩缩容速度<5秒分钟级(需数据同步/验证)
服务发现通过Service负载均衡通过Headless Service获取所有节点DNS
数据一致性不涉及需保证(如使用RAFT共识算法)
K8s资源对象Deployment + Service + HPAStatefulSet + Headless Service + PVC

关键对比说明:

Controller选择决策树

有状态应用特殊需求

  • 唯一网络标识稳定性
1
2
3
# StatefulSet Pod固定命名规则
web-0.web.default.svc.cluster.local
web-1.web.default.svc.cluster.local
  • 存储拓扑
1
2
3
4
5
6
7
8
9
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: "ssd"
resources:
requests:
storage: 100Gi

混合架构案例

电商平台架构

组件类型Controller说明
商品搜索无状态Deployment3副本自动伸缩
订单服务无状态Deployment基于CPU的HPA
Redis缓存有状态StatefulSet主从架构+持久化
日志收集节点级DaemonSet每个节点部署Fluentd
每日销售报表定时任务CronJob每天02:00运行

Controller与Pod的协同关系

特性独立PodController管理的Pod
生命周期随节点销毁永久丢失自动重建保障持续运行
扩缩容需手动操作支持声明式伸缩(如kubectl scale)
更新策略无滚动更新能力支持蓝绿/金丝雀等高级策略
自愈能力依赖外部监控内置健康检查与自动恢复

Controller和Pod是通过label标签建立关系的

Deployment控制器核心应用场景

  1. 无状态应用管理(如Web服务)

    • 滚动更新:分批次替换Pod实现零停机升级
    • 版本回滚:一键回退到历史稳定版本
    • 副本维持:确保指定数量的Pod始终运行
  2. 发布策略实施

    1
    2
    3
    4
    5
    strategy:
    type: RollingUpdate
    rollingUpdate:
    maxSurge: 25% # 最大激增Pod数
    maxUnavailable: 20% # 最大不可用比例

    某金融APP采用此配置,将版本更新耗时从1小时缩短至8分钟,错误率下降90%。

Deployment YAML关键字段解析

快速生成模板进行修改

这条命令不会在 Kubernetes 集群中真正创建任何资源,而是生成一个 基于默认配置的 Deployment YAML 文件,并将其保存到本地磁盘上的 nginx-deployment.yaml 文件中。

1
2
kubectl create deployment nginx-web --image=nginx --dry-run -o yaml > nginx-deployment.yaml
#结果:W0624 14:01:42.976616 32550 helpers.go:598] --dry-run is deprecated and can be replaced with --dry-run=client.

命令详解

部分含义
kubectlKubernetes 的命令行工具,用于与集群交互。
create deployment创建一个 Deployment 资源对象。Deployment 是 Kubernetes 中最常用的控制器之一,用于管理无状态应用的副本数量、滚动更新等。
nginx-web指定要创建的 Deployment 名称为 nginx-web
--image=nginx设置容器使用的镜像为 nginx(默认是 nginx:latest)。
--dry-run表示“只模拟执行”,不真正提交到集群中运行。仅输出将要创建的资源定义。
-o yaml输出格式为 YAML 格式。
> nginx-deployment.yaml将命令输出重定向写入到文件 nginx-deployment.yaml 中。

推荐扩展用法

  1. 添加资源限制(resources)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 指定使用的 API 版本为 apps/v1,这是 Kubernetes 中用于部署无状态应用的标准 API。
apiVersion: apps/v1

# 定义资源类型为 Deployment,表示这是一个用于管理 Pod 副本集的控制器。
kind: Deployment

# metadata 描述该 Deployment 的元数据信息。
metadata:
# 给这个 Deployment 起一个名字:nginx-web。
name: nginx-web

# spec 是 Deployment 的具体配置内容。
spec:
# 设置副本数量为 3,即始终保证有 3 个运行中的 Pod。
replicas: 3
# selector 用于选择哪些 Pod 属于这个 Deployment 管理的范围。
selector:
matchLabels:
# 匹配标签 app=nginx 的 Pod。
app: nginx

# template 是创建 Pod 的模板定义,Deployment 根据此模板来生成 Pod。
template:
# metadata 描述 Pod 的元数据。
metadata:
labels:
# 所有由这个 Deployment 创建的 Pod 都带有标签 app=nginx。
app: nginx

# spec 是 Pod 的具体规格定义。
spec:
# containers 定义容器列表,这里只有一个容器。
containers:
- name: nginx
# 使用的镜像名称和版本:nginx:1.23.1。
image: nginx:1.23.1
# 容器监听的端口,这里是 80。
ports:
- containerPort: 80

# 资源限制设置(limits):对容器能使用的最大 CPU 和内存进行限制。
resources:
limits:
# 最多使用 0.5 个 CPU(即 500m CPU)。
cpu: "0.5"
# 最多使用 512Mi 内存。
memory: "512Mi"
  1. 添加健康检查探针(liveness/readiness probe)
1
2
3
4
5
6
7
8
9
10
11
12
13
livenessProbe:  # 定义存活探针(liveness probe),用于判断容器是否健康并决定是否重启容器。
httpGet: # 使用 HTTP GET 请求方式进行健康检查。
path: / # 指定要访问的路径,默认是根路径 "/"。
port: 80 # 指定服务监听的端口号,这里设置为 80 端口。
initialDelaySeconds: 30 # 容器启动后等待 30 秒才开始执行第一次健康检查。
periodSeconds: 10 # 每隔 10 秒执行一次健康检查。

readinessProbe: # 定义就绪探针(readiness probe),用于判断容器是否准备好接收流量。
httpGet: # 同样使用 HTTP GET 请求方式进行健康检查。
path: / # 指定要访问的路径,默认是根路径 "/"。
port: 80 # 指定服务监听的端口号,这里设置为 80 端口。
initialDelaySeconds: 5 # 容器启动后等待 5 秒才开始执行第一次就绪检查。
periodSeconds: 5 # 每隔 5 秒执行一次就绪检查。
  1. 设置滚动更新策略
1
2
3
4
5
6
7
8
9
strategy:  # 定义 Deployment 的更新策略,控制滚动更新的行为。
type: RollingUpdate # 指定使用“滚动更新”策略。即逐步替换旧版本 Pod,确保服务不中断。
rollingUpdate: # 配置 RollingUpdate 类型的具体参数。
maxSurge: 25% # 表示在更新过程中,最多可以超出期望副本数的 25%。
# 举例:如果当前有 4 个 Pod,最多可以临时增加 1 个新 Pod(4 * 25% = 1),
# 用于保证扩容时系统资源充足、避免负载过高。
maxUnavailable: 25% # 表示在更新过程中,最多允许 25% 的 Pod 不可用(即停止旧 Pod)。
# 举例:如果有 4 个 Pod,最多允许 1 个 Pod 暂时不可用(4 * 25% = 1),
# 确保服务仍然有足够的副本提供访问能力。

Deployment控制器部署应用

创建部署配置文件

保存以下内容为nginx-deployment.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web
spec:
replicas: 3 # 核心:副本数控制
selector: # Pod选择器
matchLabels:
app: nginx
template: # Pod模板(控制器据此创建Pod)
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.23.1
ports:
- containerPort: 80
resources:
limits: # 资源约束
cpu: "0.5"
memory: "512Mi"

使用yaml部署应用

1
2
kubectl apply -f nginx-deployment.yaml
watch kubectl get pods # 实时观察Pod创建过程
  • kubectl apply:这是一个用于从文件或标准输入(stdin)中应用配置变更的命令。它会创建或更新资源。
  • -f nginx-deployment.yaml:指定要应用的 YAML 文件。在这个例子中,该文件名为 nginx-deployment.yaml,通常包含了 Deployment 或其他 Kubernetes 对象的定义。
  • watch:这是一个 Linux 命令行工具,它可以定期运行指定的命令,并全屏显示输出结果。默认情况下,每 2 秒执行一次命令。
  • kubectl get pods:这是用来列出当前命名空间下的所有 Pods 的命令。
1
kubectl get pods -l app=nginx

预期输出:

1
2
3
4
5
6
7
NAME        READY   UP-TO-DATE   AVAILABLE   AGE
nginx-web 3/3 3 3 1m

NAME READY STATUS RESTARTS AGE
nginx-web-5d96f5f8b7-2xk9t 1/1 Running 0 1m
nginx-web-5d96f5f8b7-8qjzv 1/1 Running 0 1m
nginx-web-5d96f5f8b7-vl6d4 1/1 Running 0 1m

对外暴露服务

1
2
3
4
5
6
7
kubectl expose deployment nginx-web \
--port=80 \
--type=NodePort \
--target-port=80 \
--name=nginx-service \
--dry-run=client \
-o yaml > nginx-service.yaml

命令解释

  • kubectl expose deployment nginx-web: 这一部分表示基于名为 nginx-web 的 Deployment 来创建一个新的服务。Kubernetes 会自动将服务关联到与指定 Deployment 相同的标签选择器上。
  • --port=80: 指定服务监听的端口为 80。这意味着外部流量可以通过这个端口访问服务。
  • --type=NodePort: 设置服务类型为 NodePort。这使得服务可以通过集群中每个节点的 IP 和静态端口(NodePort)从外部访问。Kubernetes 将在每个节点上预留一个端口(通常范围在 30000-32767之间)并将其转发到 --target-port 指定的服务端口。
  • --target-port=80: 表示请求将会被转发到后端 Pod 的 80 端口上。
  • --name=nginx-service: 给创建的服务命名为 nginx-service
  • --dry-run=client: 使用 dry-run 选项可以模拟执行这条命令的效果而不真正应用它。这对于验证命令的有效性和查看将要发生的更改非常有用。client 表示不会发送任何请求到服务器端。
  • -o yaml: 指定输出格式为 YAML。当与 --dry-run=client 结合使用时,命令会输出对象的 YAML 定义而不是实际创建资源。
  • > nginx-service.yaml: 最后,通过标准输出重定向符号 > 将上述命令的输出(即服务的 YAML 定义)保存到当前目录下的 nginx-service.yaml 文件中。

这样,你就得到了一个描述 Kubernetes 服务的 YAML 文件,可以在后续步骤中手动编辑或直接使用 kubectl apply -f nginx-service.yaml 命令来创建服务。

nginx-service.yaml内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
name: nginx-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
type: NodePort
status:
loadBalancer: {}

部署服务

1
kubectl apply -f nginx-service.yaml

验证服务暴露

1
kubectl get svc nginx-service

预期输出:

1
2
NAME            TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
nginx-service NodePort 10.99.201.61 <none> 80:31533/TCP 26s

访问地址:http://<NodeIP>:31533(将NodeIP替换为集群节点任意实际IP)

升级回滚

滚动更新镜像版本

请深刻理解滚动这个词,生成一个新的版本的同时删除一个旧的版本,依此所有都替换成新的镜像版本。

1
kubectl set image deployment/nginx-web nginx=nginx:1.24.0

这条命令的作用是:

  • 更新名为 nginx-webDeployment 中的一个容器。
  • 容器名是 nginx(在 Pod 模板的 spec.containers.name 字段中定义)。
  • 将该容器使用的镜像从原来的版本(比如 nginx:latest 或其他)更新为指定版本:nginx:1.24.0
部分说明
kubectlKubernetes 的命令行客户端,用于与集群交互。
set image子命令,用于更新资源中容器的镜像。
deployment/nginx-web指定要操作的 Deployment 名称为 nginx-web
nginx=nginx:1.24.0表示将名为 nginx 的容器的镜像更新为 nginx:1.24.0 版本。
1
2
3
4
5
6
# kubectl get pods  示例 生成一个新的版本的同时删除一个旧的版本,依此所有都替换成新的镜像版本
NAME READY STATUS RESTARTS AGE
nginx-web-68c6c6948b-8ddfb 1/1 Running 0 39m
nginx-web-68c6c6948b-j2nld 1/1 Running 0 39m
nginx-web-68c6c6948b-pd9lt 1/1 Running 0 39m
nginx-web-ffcd78588-w7n5t 0/1 ContainerCreating 0 19s
1
2
3
4
5
6
7
8
9
10
11
12
13
# 监控更新过程
kubectl rollout status deployment/nginx-web

# 验证更新结果
kubectl describe pods -l app=nginx | grep Image

# 预期输出:
Image: nginx:1.24.0
Image ID: docker-pullable://nginx@sha256:f6daac2445b0ce70e64d77442ccf62839f3f1b4c24bf6746a857eff014e798c8
Image: nginx:1.24.0
Image ID: docker-pullable://nginx@sha256:f6daac2445b0ce70e64d77442ccf62839f3f1b4c24bf6746a857eff014e798c8
Image: nginx:1.24.0
Image ID: docker-pullable://nginx@sha256:f6daac2445b0ce70e64d77442ccf62839f3f1b4c24bf6746a857eff014e798c8

版本回滚操作

1
2
3
4
kubectl rollout history deployment/nginx-web  # 查看发布历史
kubectl rollout undo deployment/nginx-web # 回滚到上一版本
kubectl rollout undo deployment/nginx-web --to-revision=2 # 明确指定要回滚到第 2 个版本
kubectl describe pods -l app=nginx | grep Image # 验证回滚结果
  • kubectl rollout history:用于查看某个 Deployment 的滚动更新历史记录
  • deployment/nginx-web:指定要查看的是名为 nginx-web 的 Deployment。
  • kubectl rollout undo:用于将 Deployment 回滚到上一个版本或指定版本。
  • --to-revision=2:明确指定要回滚到第 2 个版本(revision 2)

微软Azure实践数据:通过标准化Deployment流程,其容器服务部署失败率降低62%,平均恢复时间(MTTR)从45分钟缩短至4分钟。

弹性伸缩

1. 手动伸缩

1
2
3
4
5
# 扩展至5个副本
kubectl scale deployment nginx-web --replicas=5

# 缩减至2个副本
kubectl scale deployment nginx-web --replicas=2
部分含义
kubectlKubernetes 的命令行工具,用于与集群交互。
scale子命令,表示要对资源进行伸缩操作(即修改副本数量)。
deployment表示要伸缩的资源类型是 Deployment 控制器。
nginx-web要伸缩的具体 Deployment 名称。
--replicas=5设置目标副本数为 5,即让 Kubernetes 将运行中的 Pod 数量调整为 5 个。

2. 自动伸缩(HPA)

在 Kubernetes (k8s) 中,实现自动扩缩容(auto-scaling)通常涉及到 Horizontal Pod Autoscaler (HPA)。HPA 可以根据观察到的 CPU 利用率、内存使用量或其他自定义指标自动调整副本的数量。下面是配置 HPA 实现自动扩缩容的基本步骤:

1. 前提条件

  • Metrics Server: Kubernetes 集群需要部署 Metrics Server 来收集资源使用情况。
  • 资源请求和限制: 对于每个容器,你应当定义 CPU 和/或内存的请求和限制。

2. 配置步骤

确保你的集群中已经安装了 Metrics Server。可以通过以下命令检查是否运行:

1
2
3
4
# 检查安装与否
kubectl get apiservices | grep metrics
# 安装metrics-server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

3. 配置 Horizontal Pod Autoscaler

首先,你需要有一个部署(Deployment),它将作为自动扩缩的目标。

接下来,为你的部署配置 HPA。例如,基于 CPU 使用率设置最小 2 个副本,最大 10 个副本,目标 CPU 使用率为 60%:

1
kubectl autoscale deployment nginx-web --cpu-percent=60 --min=2 --max=10

或者通过 YAML 文件配置,保存为 nginx-hpa.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 指定使用的 API 版本为 autoscaling/v2,这是 Kubernetes 中用于配置自动伸缩的标准 API。
apiVersion: autoscaling/v2

# 定义资源类型为 HorizontalPodAutoscaler,表示这是一个水平 Pod 自动伸缩器。
kind: HorizontalPodAutoscaler

# metadata 描述该 HPA 对象本身的元数据信息。
metadata:
# 给这个 HorizontalPodAutoscaler 起一个名字:nginx-hpa。
name: nginx-hpa

# spec 是该 HPA 的具体配置和行为定义。
spec:
# scaleTargetRef 表示要自动伸缩的目标资源对象。
scaleTargetRef:
# 指定目标资源的 API 版本为 apps/v1,通常是 Deployment、ReplicaSet 等控制器。
apiVersion: apps/v1
# 指定目标资源的类型为 Deployment。
kind: Deployment
# 指定目标 Deployment 的名称是 nginx-web。
name: nginx-web

# 设置副本数量的最小值,即自动伸缩时最少保持 2 个 Pod。
minReplicas: 2

# 设置副本数量的最大值,即自动伸缩时最多扩展到 10 个 Pod。
maxReplicas: 10

# metrics 定义了触发自动伸缩的指标列表。
metrics:
- type: Resource # 表示使用的是资源类型的指标(如 CPU、内存等)。
resource:
# 指定监控的资源为 CPU。
name: cpu
target:
# 使用 Utilization 类型的目标,表示根据资源利用率来伸缩。
type: Utilization
# 设置平均 CPU 利用率的目标值为 60%,当超过这个值时会扩容,低于则可能缩容。
averageUtilization: 60

应用该yaml配置:

1
kubectl apply -f nginx-hpa.yaml

4. 验证命令:

1
2
3
4
5
6
7
kubectl get hpa
# 输出示例:
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
# nginx-hpa Deployment/nginx-web 1%/80% 3 10 3 2m

# 检查节点指标
kubectl top nodes

5. 定时伸缩(CronHPA)
适用于预知流量峰值的场景(如每日9:00-18:00扩展至10副本)

图:Nginx在Kubernetes中的典型部署架构

其他常用Controller类型

  1. StatefulSet:管理有状态应用(如数据库)
    • 稳定网络标识(PodName-0, PodName-1)
    • 有序部署/伸缩(如MySQL主从架构)
  2. DaemonSet:节点级部署(如日志收集器)
    • 每个Node运行一个Pod实例
    • 典型应用:Fluentd日志代理
  3. Job/CronJob:任务调度系统
    • 批处理作业(如每日报表生成)
    • 定时任务(Cron表达式控制)