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,避免服务中断
- 快速回滚:新版本出问题,一键回到上一个版本
我曾经有一次线上事故,就是因为没配 maxSurge 和 maxUnavailable。默认值是 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-secrets 或 secrets-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。这些在生产环境中几乎是必用的。