Kubernetes学习笔记01:Pod和控制器

发表于 2024-01-08 21:34 1456 字 8 min read

Spring AI学习笔记(四)工具调用和MCPSpring AI学习笔记(三)RAG从文档入库到回答Spring AI学习笔记(二)ChatClient从怎么调到怎么封装Spring AI学习笔记(一)它到底解决什么问题java新版本-java25学习笔记(四)用JFR和GC日志做一次体检java新版本-java25学习笔记(三)虚拟线程要和资源边界一起看java新版本-java25学习笔记(二)运行时基线先统一java新版本-java25学习笔记(一)LTS版本对比和学习路线主流AI Agent能力对比与工程选型我用Kiro做了个自己的工具站盘一盘虚拟线程我用Trae做了个AstrBot的AI角色扮演插件Python初学笔记(六)常用标准库先学这几个Python初学笔记(五)读写文件和处理异常Python初学笔记(四)函数让代码开始有结构Python初学笔记(三)条件、循环和推导式Python初学笔记(二)变量和基础类型比想象中重要Python初学笔记(一)先把环境和运行方式弄明白主流AI大模型能力对比Java 21和Spring Boot 3升级笔记(五)日志指标与可观测性Java 21和Spring Boot 3升级笔记(四)数据访问层适配Java 21和Spring Boot 3升级笔记(三)虚拟线程使用边界Java 21和Spring Boot 3升级笔记(二)Jakarta迁移要点Java 21和Spring Boot 3升级笔记(一)工程基线整理How Can We Tolerate Magic Values! Major Overhaul of JPA Specification!处理生僻字乱码:JPA框架对于Oracle的NVarchar2,NChar,NClob类型支持Redis Stream能不能当轻量消息队列用RocketMQ 5学习笔记:普通消息之外要看什么事件流不是换个消息队列这么简单Kubernetes学习笔记04:发布、排障和观测Kubernetes学习笔记03:配置、密钥和存储Kubernetes学习笔记02:Deployment、Service和IngressKubernetes学习笔记01:Pod和控制器mysql索引原理02--存储引擎索引的实现mysql索引原理01--索引的数据结构
This post is not yet available in English. Showing the original.
  学 Kubernetes 的第一步,我觉得不是先背一堆命令,也不是马上搭集群,而是先把几个核心对象之间的关系想清楚。   很多人刚开始接触 k8s,会把它理解成“一个高级 Docker 管理器”。这个理解不算错,但太浅了。Docker 更关心一个容器怎么构建、怎么运行;Kubernetes 更关心一组应用应该以什么状态持续运行。...

前言

  学 Kubernetes 的第一步,我觉得不是先背一堆命令,也不是马上搭集群,而是先把几个核心对象之间的关系想清楚。

  很多人刚开始接触 k8s,会把它理解成“一个高级 Docker 管理器”。这个理解不算错,但太浅了。Docker 更关心一个容器怎么构建、怎么运行;Kubernetes 更关心一组应用应该以什么状态持续运行。

  所以这篇先不讲太多组件细节,只从 Pod、ReplicaSet、Deployment 这些最常见的对象开始,把 k8s 的基本思路梳理一下。

Pod 是最小调度单元

  在 k8s 里,最小调度单元不是容器,而是 Pod。

一个 Pod 里可以有一个或多个容器。大多数业务服务只有一个主容器,但 Pod 这个抽象允许把关系非常紧密的容器放在一起运行,比如主应用容器加一个日志采集 sidecar。

Pod 里的容器共享网络命名空间,所以同一个 Pod 内的容器可以通过 localhost 互相访问。它们也可以共享 volume,用来交换文件或配置。

但这不代表应该把一堆服务都塞进一个 Pod。Pod 不是小型虚拟机。只有生命周期、部署节奏、资源边界都高度一致的容器,才适合放在同一个 Pod 里。

不要直接管理裸 Pod

  学习时可以写一个 Pod YAML 来理解字段,但真实项目里一般不会直接管理裸 Pod。

原因很简单:Pod 会死。

节点故障、镜像拉取失败、探针失败、资源被驱逐,都可能导致 Pod 被删除或重新创建。如果只是手写一个裸 Pod,它没有更高层的控制器负责维持副本数量。

Kubernetes 真正重要的地方在于控制循环。你声明“我希望系统里有 3 个可用副本”,控制器就持续观察当前状态。如果只剩 2 个,它会再拉起 1 个。如果多了,它会删掉多余的。

这个思路和手工运维不一样。手工运维更像是执行动作,k8s 更像是持续对齐目标状态。

ReplicaSet 负责副本数量

  ReplicaSet 的职责很直接:保证某类 Pod 的副本数量符合预期。

比如希望有 3 个 nginx Pod:

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-rs
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25

这里最关键的是 selectortemplate.metadata.labels 要对得上。ReplicaSet 通过 label 找到自己管理的 Pod。如果 selector 写错,控制器就可能找不到 Pod,或者误管了不该管的 Pod。

不过项目里也很少直接写 ReplicaSet。因为它只解决副本数量,不负责发布策略。

Deployment 是最常用入口

  实际写业务服务时,最常见的是 Deployment。

Deployment 会在底层创建 ReplicaSet,再由 ReplicaSet 创建 Pod。它比 ReplicaSet 多了一层发布管理能力,可以做滚动更新、回滚、版本记录。

一个典型 Deployment 大概是这样:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service
          image: registry.example.com/order-service:2024-01-08
          ports:
            - containerPort: 8080

这段 YAML 看起来只是启动了 3 个服务实例,但背后其实包含了几个重要约定:

1.应用用镜像交付。 2.副本数量由控制器维持。 3.Pod 通过 label 被识别。 4.发布时通过更新模板触发滚动升级。

理解了这些,再看各种平台上的“部署应用”按钮,其实大多都是在生成类似的对象。

Label 是对象之间的胶水

  k8s 里很多对象不是靠固定名称强绑定,而是靠 label 和 selector 关联。

Deployment 用 selector 找 Pod,Service 用 selector 找后端 Pod,监控和日志系统也经常用 label 做筛选。

所以 label 不能随便写。至少要有一些稳定字段,比如:

labels:
  app: order-service
  tier: backend
  part-of: mall

我比较不建议把经常变化的信息放进核心 selector,比如版本号、构建号、临时环境标识。版本可以作为补充 label,但不要让 Service 这类长期对象依赖它,否则发布时容易出现流量切换异常。

label 设计得越稳定,后面接入 Service、Ingress、监控、日志和灰度发布时越省事。

声明式不是只写 YAML

  k8s 经常被说成声明式系统,但声明式不等于“把命令改成 YAML”。

真正的区别是:你描述期望状态,控制器负责把实际状态推进过去。

比如你把 Deployment 的 replicas 从 3 改成 5,k8s 会创建两个新 Pod。你把镜像 tag 改了,k8s 会触发滚动更新。你删掉一个 Pod,控制器会发现副本不足并重新创建。

这也意味着我们排查问题时,不能只看最后一个命令是否执行成功,而要看对象状态有没有收敛:

kubectl get deployment order-service
kubectl describe deployment order-service
kubectl get pods -l app=order-service

如果期望状态和实际状态不一致,就要顺着事件、Pod 状态、镜像拉取、调度结果继续查。

小结

  Kubernetes 入门时,先把 Pod 和控制器关系弄清楚,比记命令更重要。

  Pod 是应用运行的最小调度单元,但业务服务通常不直接管理 Pod,而是通过 Deployment 声明副本数量和发布策略。ReplicaSet 在中间保证副本数量,label 和 selector 负责把这些对象关联起来。

  如果能先接受“声明期望状态,控制器持续对齐”这个思路,后面再学 Service、Ingress、配置、存储和排障,就不会觉得 Kubernetes 只是很多 YAML 堆在一起。

If you enjoyed this, leave a comment~

© 2019 - 2026 VincentHo @VincentHo
Powered by theme astro-koharu · Inspired by Shoka