2、Kubernetes核心实战:Pod创建与管理、Deployment部署与扩缩容、Service服务发现、ConfigMap与Secret配置管理

好,咱们直接进入正题。Kubernetes 这东西,说白了就是一个「管家」,帮你管着你的应用容器。这一章我们就把最核心的几个概念撸一遍:Pod、Deployment、Service,还有配置管理用的 ConfigMap 和 Secret。这些都是你每天都会打交道的玩意儿。

本章核心脉络: 从最小的调度单元 Pod 开始,到用 Deployment 管理 Pod 的「生老病死」,再到用 Service 把 Pod 的网络暴露出去,最后用 ConfigMap 和 Secret 把配置和敏感信息剥离出来。一条线串下来,你就知道一个应用在 K8s 里是怎么跑起来的。

Kubernetes 核心实战 Pod 最小调度单元 Deployment 声明式更新 & 扩缩容 Service 网络代理 & 服务发现 ConfigMap & Secret 配置 & 敏感信息管理 从 Pod 出发,层层递进,构建完整应用

2.1 Pod:K8s 里最小的「兵」

Pod 是啥?你可以把它想象成一个「容器盒子」。一个 Pod 里可以放一个容器,也可以放多个紧密耦合的容器。但记住,Pod 是 K8s 调度的最小单位,不是容器本身。

我个人习惯把 Pod 比作「豆荚」—— 里面包着几颗豆子(容器),共享同一个网络命名空间和存储卷。它们之间用 localhost 就能通信,方便得很。

创建一个 Pod 很简单,写个 YAML 文件就行:

apiVersion: v1
kind: Pod
metadata:
  name: my-nginx
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    ports:
    - containerPort: 80

然后 kubectl apply -f pod.yaml 就起来了。想看看状态?kubectl get pods。想进去看看?kubectl exec -it my-nginx -- /bin/bash

小技巧: 我刚开始用的时候,老是记不住 Pod 的完整 YAML 结构。后来发现 kubectl run my-pod --image=nginx --dry-run=client -o yaml 这个命令能直接帮你生成模板,省事多了。

不过,直接创建 Pod 有个问题 —— 它挂了就真挂了,没人管。所以生产环境我们很少直接搞 Pod,而是用 Deployment 来管它。

2.2 Deployment:让 Pod 永不掉线

Deployment 是什么?说白了,它是一个「Pod 管家」。你告诉它「我要跑 3 个 nginx 实例」,它就帮你盯着,哪个 Pod 挂了就立刻再拉一个起来。

我记得有一次线上服务半夜挂了,就是因为 Pod 被 OOM Kill 了,但 Deployment 自动重建了一个,用户几乎没感知。嗯,这就是声明式管理的魅力。

来个 Deployment 的例子:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80

这里 replicas: 3 就是告诉 K8s:我要 3 个副本。想扩缩容?简单:

kubectl scale deployment nginx-deployment --replicas=5

或者直接改 YAML 里的 replicas 再 apply 一次。我个人更推荐后者,因为 YAML 才是「真相来源」,命令行操作容易忘记。

注意: 扩缩容不是瞬间完成的。K8s 会先拉镜像、启动容器、等就绪检查通过,才会把新 Pod 纳入服务。我曾经遇到过镜像拉取超时导致扩容卡住的情况,所以建议提前把镜像拉到节点上,或者配置好镜像拉取策略。

Deployment 还有一个大招 —— 滚动更新。你改了镜像版本,apply 一下,它会逐个替换 Pod,不会一次性全干掉。这招在线上更新时特别有用。

2.3 Service:给 Pod 一个稳定的「门牌号」

Pod 是动态的,今天在这台机器上,明天可能就跑到另一台了。IP 地址也会变。那客户端怎么访问它?这就轮到 Service 出场了。

Service 相当于一个「反向代理 + 负载均衡」。它有一个固定的虚拟 IP(ClusterIP),你只要访问这个 IP,它就把流量转发到后端的 Pod 上。

你想想看,如果没有 Service,每次 Pod 重启你都得去查新 IP,那得多崩溃。

创建一个 Service:

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
  type: ClusterIP

这里 selector 就是告诉 Service:去找那些带有 app: nginx 标签的 Pod。然后 port: 80 是 Service 的端口,targetPort: 80 是 Pod 里容器的端口。

Service 的类型有几种:

类型 说明 适用场景
ClusterIP 集群内部可访问,外部不行 内部微服务调用
NodePort 在每个节点上开一个端口,外部可通过节点IP+端口访问 开发测试、简单暴露
LoadBalancer 云厂商提供负载均衡器,外部直接访问 生产环境对外暴露

避坑指南: 我曾经把 Service 的 selector 写错了标签,结果流量全打到了错误的 Pod 上。排查了半天才发现是标签不匹配。所以创建 Service 前,先用 kubectl get pods --show-labels 确认一下 Pod 的标签。

2.4 ConfigMap 与 Secret:配置与敏感信息分离

应用总得有些配置吧?比如数据库地址、日志级别。这些如果硬编码在镜像里,换个环境就得重新打包,太蠢了。ConfigMap 就是用来干这个的。

Secret 呢?跟 ConfigMap 差不多,但它是用来存敏感信息的,比如密码、API Key。数据会做 base64 编码,虽然不算绝对安全,但至少不会明文暴露在 YAML 里。

先看 ConfigMap:

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

然后在 Pod 里引用它:

spec:
  containers:
  - name: my-app
    image: my-app:latest
    envFrom:
    - configMapRef:
        name: app-config

这样配置就注入到环境变量里了。你也可以挂载成文件,看需求。

Secret 的用法几乎一样,只是 data 里的值需要 base64 编码:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:
  db.password: bXlwYXNzd29yZA==  # 这是 "mypassword" 的 base64

安全提醒: base64 不是加密,只是编码。任何能拿到 YAML 的人都能解码。真正生产环境,建议用外部密钥管理服务(比如 Vault、AWS Secrets Manager),或者用 Sealed Secrets 这类工具。我之前在一个项目里看到有人把生产数据库密码直接 base64 放在 Git 里,吓得我赶紧让他改了。

嗯,到这里,Kubernetes 的核心实战四件套就讲完了。Pod 是基础,Deployment 保证高可用,Service 搞定网络,ConfigMap 和 Secret 管好配置。把这几个玩转了,你就能在 K8s 上跑起一个像样的应用了。


专注资料整理