3、Kubernetes核心概念:Pod、Deployment、Service、Ingress、ConfigMap、Secret

好,咱们进入正题。Kubernetes 的概念很多,但真正每天都要打交道的,其实就这几个。我刚开始接触 K8s 时,也被一堆名词搞晕过。后来发现,你只要把 Pod、Deployment、Service 这几个搞明白,日常运维基本就够用了。

今天咱们一个一个拆开讲。我会结合我踩过的坑,帮你把这些概念真正吃透。

3.1 Pod:最小的调度单元

Pod 是 K8s 里最小的部署单元。说白了,它就是一个或多个容器的组合。这些容器共享网络栈和存储卷。

为什么要有 Pod? 你想想看,有时候两个进程需要紧密协作,比如一个写日志、一个读日志。它们最好在同一个网络命名空间里,用 localhost 通信。Pod 就是干这个的。

核心要点:

  • 一个 Pod 通常只运行一个主容器
  • 多个容器共享同一个 IP 和端口空间
  • Pod 是临时性的,随时可能被销毁重建

我在项目中遇到过一个问题:有个同事把两个需要独立扩缩容的服务放在同一个 Pod 里。结果一个服务负载高了,整个 Pod 都得扩容,另一个服务也跟着遭殃。嗯,这里要注意——Pod 里的容器必须是一荣俱荣、一损俱损的关系

# 一个简单的 Pod 定义
apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
  labels:
    app: my-app
spec:
  containers:
  - name: my-container
    image: nginx:1.21
    ports:
    - containerPort: 80

3.2 Deployment:声明式更新

Deployment 是我个人最常用的资源。它管理着 Pod 的副本数、滚动更新策略、回滚操作。说白了,你告诉它「我要 3 个 Pod,镜像版本是 v2」,它就会帮你搞定一切。

Deployment 的核心能力:

  • 副本管理:保证指定数量的 Pod 一直在运行
  • 滚动更新:逐步替换旧版本 Pod,避免服务中断
  • 快速回滚:新版本出问题,一键回到上一个版本

我曾经有一次线上事故,就是因为没配 maxSurgemaxUnavailable。默认值是 25%,对于小集群来说,滚动更新时可能会瞬间创建太多 Pod,把节点资源打满。后来我养成了习惯——生产环境一定要显式配置这两个参数

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: my-app:v2
        ports:
        - containerPort: 8080

我的经验: 对于关键业务,建议把 maxUnavailable 设为 0,确保更新期间始终有完整的服务能力。代价是更新速度会慢一些,但安全第一。

3.3 Service:稳定的访问入口

Pod 是会漂移的。今天这个 Pod 在 node1,明天可能就在 node2 了。IP 也会变。那客户端怎么访问?Service 就是来解决这个问题的。

Service 提供了一组 Pod 的稳定访问入口。它通过标签选择器找到对应的 Pod,然后做负载均衡。

Service 的几种类型:

类型 使用场景 访问方式
ClusterIP 集群内部访问 虚拟 IP,仅集群内可达
NodePort 外部调试或测试 节点 IP + 固定端口
LoadBalancer 云环境对外暴露 云厂商负载均衡器

我个人建议:生产环境对外暴露服务,优先用 Ingress,而不是 NodePort。NodePort 虽然简单,但会暴露所有节点的端口,安全性和管理性都不好。

apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
spec:
  selector:
    app: my-app
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP

3.4 Ingress:七层路由

Service 工作在四层(TCP/UDP),它只能做简单的端口转发。但实际场景中,我们经常需要根据域名、路径来做路由。这时候就需要 Ingress 了。

Ingress 是七层的 HTTP/HTTPS 路由。它可以把不同域名的请求转发到不同的 Service 上。比如 api.example.com 转到 Service A,web.example.com 转到 Service B。

注意: Ingress 本身只是一个资源定义,真正干活的是 Ingress Controller(比如 Nginx Ingress Controller、Traefik)。你得先部署一个 Ingress Controller,Ingress 资源才会生效。

我曾经踩过一个坑:配了 Ingress 但一直不生效,排查了半天才发现忘了部署 Ingress Controller。嗯,这个顺序很重要——先有 Controller,再有 Ingress 资源

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-svc
            port:
              number: 80

3.5 ConfigMap 与 Secret:配置管理

这两个都是用来管理配置的。区别很简单:ConfigMap 存明文,Secret 存敏感信息

ConfigMap 的使用场景:

  • 应用配置文件(如 nginx.conf、application.yml)
  • 环境变量(如数据库地址、日志级别)
  • 命令行参数

Secret 的使用场景:

  • 数据库密码、API 密钥
  • TLS 证书
  • SSH 私钥

安全提醒: Secret 只是做了 Base64 编码,不是加密!任何有 etcd 访问权限的人都能解码看到明文。生产环境建议用外部密钥管理服务(如 HashiCorp Vault、AWS Secrets Manager)配合 external-secretssecrets-store-csi-driver

我见过有人把数据库密码直接写在 Deployment 的 YAML 里,然后提交到 Git 仓库。这简直是灾难。正确的做法是——用 Secret 引用,并且给 Secret 加上 RBAC 权限控制

# ConfigMap 示例
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  app.properties: |
    log.level=INFO
    db.host=mysql-service
    db.port=3306

---
# Secret 示例
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  username: YWRtaW4=  # base64 编码后的 "admin"
  password: cGFzc3dvcmQxMjM=  # base64 编码后的 "password123"
# 在 Pod 中引用 ConfigMap 和 Secret
apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
spec:
  containers:
  - name: my-container
    image: my-app:latest
    env:
    - name: DB_USERNAME
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: username
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: app-config

3.6 它们之间的关系

最后,我用一句话总结这几个概念的关系:

  • Pod 是你的应用实例
  • Deployment 管理 Pod 的生命周期
  • Service 给 Pod 提供稳定的访问入口
  • Ingress 在 Service 之上做七层路由
  • ConfigMap 和 Secret 给 Pod 提供配置信息

你想想看,一个典型的微服务部署流程就是:写好代码 → 打成镜像 → 用 Deployment 部署 → 用 Service 暴露 → 用 Ingress 做域名路由 → 配置放在 ConfigMap/Secret 里。这一套下来,一个完整的云原生应用就上线了。

我的建议: 刚开始学 K8s,别急着搞太复杂的东西。先把 Pod、Deployment、Service 这三个玩熟,能跑起来一个完整的应用,就算入门了。Ingress 和 ConfigMap/Secret 可以等有需要时再深入。

下一章,咱们聊聊 K8s 的存储体系——PV、PVC 和 StorageClass。这些在生产环境中几乎是必用的。