Kubernetes Pod 控制器 RC&RS

发布于:2025-06-28 ⋅ 阅读:(20) ⋅ 点赞:(0)

前言

在传统架构中,我们总是面临一个问题:我们的应用部署在哪台机器上?如果应用不可访问了,就需要登录到对应的机器上去排查。

使用 kubernetes 后,这个问题彻底不存在了。我们用容器封装应用,用 Pod 部署容器,至于 Pod 被调度到哪台机器,完全交给 kubernetes 就好了,我们不需要关心。排查问题时,直接找出故障 Pod,查看日志即可。

一般来说,我们部署应用,会有以下两点需求:

  • 应用最好能方便部署多个实例,分摊压力
  • 应用最好能自我修复,崩溃后尝试恢复

基于以上两点考量,在生产环境,一般不会直接部署 Pod,而是基于 Pod 控制器来部署。

Replication Controller

Replication Controller,简称 RC,也叫 副本控制器。顾名思义,它被用来控制 Pod 的副本数量始终满足期望值。

通过 RC,我们可以一键部署 N 个相同的 Pod,RC 会确保这一组 Pod 始终是可用的。如果存在的 Pod 大于期望值,RC 会销毁额外的的 Pod;如果存在的 Pod 小于期望值,RC 会自动部署新的 Pod,以达到期望值。

考虑到 Pod 的可用性,哪怕你只需要一个 Pod,也应该通过 RC 来部署,因为它会在 Pod 意外崩溃时,自动部署新的 Pod 来替换旧的。

如下所示,rc.yaml描述了一个具备2个副本的 RC。spec.template是 Pod 模板定义,当 Pod 数量小于期望值时,RC 会基于这个模板来创建新的 Pod。

这个 Pod 部署了一个基于 go 编写的 web 服务,通过 8080 端口对外提供服务。

apiVersion: v1
kind: ReplicationController
metadata:
  name: go-server-rc
spec:
  replicas: 2
  selector:
    app: go-server
  template:
    metadata:
      name: go-server
      labels:
        app: go-server
    spec:
      containers:
      - name: go-server
        image: docker.io/library/go-server:1.0
        ports:
        - containerPort: 8080
        env:
        - name: MY_ENV_USER
          value: user-v1

执行kubectl apply -f rc.yaml就会创建 RC 对象。

kubectl get rc查看 RC,DESIRED 是期望的 Pod 数,CURRENT 是当前Pod数,READY 是准备就绪的 Pod 数。

kubectl get pods查看 RC 创建的 Pod。

因为 RC 会保证 Pod 数量始终满足期望值,所以即使执行kubectl delete pod删除 Pod,当 RC 发现 Pod 数量小于期望值时,立马就会创建新的 Pod 补上。

RC 和 Pod 是通过spec.selector选择器来匹配的,换言之,RC 会保证经过spec.selector选择器筛选后的 Pod 数量始终满足期望值。示例中的配置是app: go-server,如果我们把其中一个 Pod 对应的 labels 删除,该 Pod 将不再被 RC 管理,RC 经过选择器后筛选完发现只有一个 Pod,又会再创建一个新的 Pod,结果是会有三个 Pod。

ReplicaSet

ReplicaSet 算是 ReplicationController 的一个升级版,相较于 RC 的主要升级点有:

  • 支持集合选择器:RC 只支持等值匹配,RS 支持集合选择器,允许通过 in notin exists 操作符来匹配 Pod,更加灵活
  • 与 Deployment 集成:ReplicaSet 通常与 Deployment 一起使用,提供更高级的功能,如滚动更新和回滚等。虽然 ReplicaSet 可以单独使用,但在实际应用中,通常通过 Deployment 来管理

如下是 ReplicaSet 简单示例,与 RC 的主要区别是spec.selector.matchLabels部分是基于标签的等值匹配,spec.selector.matchExpressions部分是基于集合的选择器。

在这个例子中,ReplicaSet 会保证标签 env 包含 prod、且 release 不包含 canary、且存在 online 标签的 Pod 数量始终满足两个。

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: go-server-rs
spec:
  replicas: 2
  selector:
    matchLabels:
      app: go-server
    matchExpressions:
      - { key: env, operator: In, values: [ prod ] }
      - { key: release, operator: NotIn, values: [ canary ] }
      - { key: online, operator: Exists }
  template:
    metadata:
      name: go-server
      labels:
        app: go-server
        env: prod
        release: stable
        online: "yes"
    spec:
      containers:
        - name: go-server
          image: docker.io/library/go-server:1.0
          ports:
            - containerPort: 8080
          env:
            - name: MY_ENV_USER
              value: user-v1

执行kubectl apply -f rs.yaml部署 ReplicaSet,顺利启动 2 个 Pod。

因为示例中的 ReplicaSet 选择器要求 Pod 必须具备 online 标签,我们尝试删除掉其中一个 Pod 的 online 标签,会发现 ReplicaSet 立马就会启动新的 Pod 补齐。

尾巴

为了保证可用性,几乎不会直接部署 Pod,因为它不具备崩溃恢复的能力。最佳实践是通过 Pod 控制器来部署 Pod。ReplicationController 会保证满足要求的 Pod 数量始终满足期望值,ReplicaSet 是一个升级版,支持了更灵活的集合选择器模式。

在生产中,ReplicationController 不再推荐使用,后续会被废弃。ReplicaSet 也很少单独使用,推荐使用更高级的 Deployment 来间接部署 ReplicaSet。


网站公告

今日签到

点亮在社区的每一天
去签到