第4章:Kubernetes核心概念:Pod、Service、Deployment、ConfigMap、Secret详解
好,咱们进入正题。Kubernetes 这东西,说白了就是一套容器编排系统。但很多新手一上来就被各种概念搞懵了。Pod、Service、Deployment……这些到底都是啥?
我刚开始接触 K8s 的时候,也觉得头大。后来在项目中踩了不少坑,才慢慢理清楚。今天我就用我的理解,把这些核心概念给你讲透。
4.1 Pod:最小的调度单元
Pod 是 K8s 里你能创建和管理的最小计算单元。你可以把它理解成一个“容器盒子”。
一个 Pod 里可以放一个或多个容器。 但实践中,我建议一个 Pod 只放一个主容器。除非你有特别强的耦合需求,比如 sidecar 模式。
核心要点: Pod 里的容器共享网络栈和存储卷。它们可以通过 localhost 互相通信。
我在项目中遇到过一个问题:两个容器放在同一个 Pod 里,结果其中一个日志爆了,把共享的 emptyDir 卷写满了,导致另一个容器也挂了。嗯,这就是共享存储带来的风险。
Pod 的典型 YAML
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
你看,定义很简单。但实际生产中,我们很少直接创建 Pod。为什么?因为 Pod 挂了就真的挂了,没人管它。这时候就需要 Deployment 出场了。
4.2 Deployment:声明式更新与扩缩容
Deployment 是管理 Pod 的“高级管家”。你告诉它“我要跑 3 个 nginx”,它就会帮你创建 3 个 Pod,并且持续保证这个数量。
Deployment 的核心能力:
- 滚动更新:逐步替换旧版本 Pod,保证服务不中断
- 回滚:更新出问题了?一键回到上一个版本
- 扩缩容:流量大了,把副本数从 3 调到 10
我的习惯: 每次更新 Deployment 时,我都会设置 revisionHistoryLimit 为 5。保留太多历史版本没意义,还占 etcd 空间。
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.21
ports:
- containerPort: 80
这里有个关键点:selector.matchLabels 必须和 template.metadata.labels 匹配。我曾经因为 label 写错了一个字母,结果 Deployment 创建的 Pod 全都不受管控……排查了半天。
4.3 Service:稳定的网络入口
Pod 是动态的,随时可能被销毁、重建。那客户端怎么访问?IP 地址一直在变啊。
Service 就是来解决这个问题的。它提供一个稳定的虚拟 IP(ClusterIP),背后代理一组 Pod。
Service 的类型:
| 类型 | 说明 | 使用场景 |
|---|---|---|
| ClusterIP | 集群内部可访问 | 内部服务调用 |
| NodePort | 通过节点 IP + 端口访问 | 开发测试环境 |
| LoadBalancer | 云厂商提供负载均衡器 | 生产环境对外暴露 |
注意: 别把 NodePort 用在生产环境。端口范围有限(30000-32767),而且暴露了节点 IP,不安全。
我个人习惯用 ClusterIP 配合 Ingress 对外暴露服务。这样更灵活,也更容易管理证书和路由规则。
4.4 ConfigMap 与 Secret:配置管理
应用配置不能写死在镜像里。否则换个环境就得重新打包,太蠢了。
ConfigMap 用来存非敏感配置,比如数据库地址、日志级别。Secret 用来存敏感信息,比如密码、API Key。
ConfigMap 示例
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
app.properties: |
db.host=mysql-service
db.port=3306
log.level=INFO
Secret 示例
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
password: bXlwYXNzd29yZA== # base64 编码后的值
重要提醒: Secret 的 base64 编码不是加密!它只是防眼瞎。真正安全要用外部密钥管理工具,比如 HashiCorp Vault 或云厂商的 KMS。
我曾经犯过一个错:把数据库密码直接写在 ConfigMap 里,结果同事不小心把 YAML 提交到了公开仓库……嗯,那晚我加班到凌晨三点改密码。
4.5 它们如何协同工作?
咱们把整个流程串起来看看:
- 你创建一个 Deployment,声明要跑 3 个 nginx Pod
- Deployment 通过 ReplicaSet 创建 3 个 Pod
- Pod 里挂载 ConfigMap 和 Secret,读取配置和密码
- 你创建一个 Service,选择器匹配 Pod 的 label
- 客户端通过 Service 的 ClusterIP 访问 nginx 服务
你看,这几个概念环环相扣。缺一个,整个系统就跑不起来。
避坑指南: 我曾经在更新 ConfigMap 后,发现 Pod 里的配置没变。为什么?因为 ConfigMap 更新后,Pod 不会自动重新加载。你需要手动重启 Pod,或者用一些工具(比如 Reloader)来自动触发滚动更新。
4.6 小结
今天咱们聊了 K8s 的五个核心概念:
- Pod:最小调度单元,一个盒子装一个或多个容器
- Deployment:管理 Pod 的生命周期,支持滚动更新和扩缩容
- Service:提供稳定的网络入口,屏蔽 Pod 的动态变化
- ConfigMap:存非敏感配置
- Secret:存敏感信息,但别依赖它的安全性
说实话,这些概念光看文档是不够的。你最好自己搭个集群,亲手创建几个 Pod、Deployment、Service,再改改 ConfigMap 看看效果。实践出真知嘛。
下一章咱们聊聊存储,PersistentVolume 和 PersistentVolumeClaim。到时候我会分享一个我在生产环境遇到的存储坑,保证让你印象深刻。