← Lesson 0014 讲了 Pod、Deployment、Service。这课解决:「外部怎么访问?」「配置怎么管?」「数据怎么存?」
Service 的 NodePort 只在开发环境用。生产用 Ingress——相当于 K8s 里的 Nginx 反向代理。
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
spec:
rules:
- host: example.com # 域名
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-svc # 指向 api Service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: web-svc # 指向 web Service
port:
number: 80
tls:
- hosts:
- example.com
secretName: example-tls # TLS 证书存在 Secret 里
Ingress 需要 Ingress Controller 才能工作(如 nginx-ingress、traefik)。云 K8s 通常自带。
# 从字面量创建
kubectl create configmap app-config \
--from-literal=LOG_LEVEL=debug \
--from-literal=API_URL=https://api.example.com
# 从文件创建
kubectl create configmap nginx-config --from-file=nginx.conf
# 在 Deployment 里使用
spec:
containers:
- name: app
image: my-app
envFrom:
- configMapRef:
name: app-config # 所有 key 变成环境变量
# 或挂载为文件
volumeMounts:
- name: nginx-conf
mountPath: /etc/nginx/conf.d
volumes:
- name: nginx-conf
configMap:
name: nginx-config
# 创建 Secret(数据要 base64 编码)
kubectl create secret generic db-secret \
--from-literal=DB_PASSWORD=s3cret!
# 或者从文件
echo -n "s3cret!" | kubectl create secret generic db-secret --from-file=password=/dev/stdin
# 使用方式和 ConfigMap 一样,只是数据在 etcd 里加密存储
spec:
containers:
- name: app
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
Pod 里的文件是临时的。数据库数据需要持久化→用 PersistentVolume (PV) + PersistentVolumeClaim (PVC)。
# pvc.yaml —— 申请存储(类似「我要 10GB 的 SSD」)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: db-pvc
spec:
accessModes:
- ReadWriteOnce # 单个 Pod 读写
resources:
requests:
storage: 10Gi
storageClassName: standard # 云厂商自动创建 PV
---
# Deployment 中使用 PVC
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts:
- name: db-data
mountPath: /var/lib/postgresql/data
volumes:
- name: db-data
persistentVolumeClaim:
claimName: db-pvc
spec:
containers:
- name: app
image: my-app
resources:
requests: # 调度保证(至少分配这么多)
memory: "128Mi"
cpu: "100m" # 100 millicores = 0.1 CPU
limits: # 硬上限(绝对不能超过)
memory: "256Mi" # 超过 → OOMKilled
cpu: "500m" # 超过 → throttled(被限速,不会被杀)
requests vs limits:requests 决定 Pod 调度到哪个 Node(Node 要有足够资源)。limits 是运行时天花板。
spec:
containers:
- name: app
image: my-app
livenessProbe: # 「还活着吗?」→ 失败就重启
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 10 # 启动等 10 秒再开始检查
periodSeconds: 15 # 每 15 秒检查一次
failureThreshold: 3 # 连续失败 3 次才重启
readinessProbe: # 「能接流量了吗?」→ 失败就摘除
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
startupProbe: # 启动完成了吗?(启动慢的应用专用)
httpGet:
path: /startup
port: 3000
failureThreshold: 30 # 最多等 30×10s=300s
periodSeconds: 10
| Probe | 作用 | 失败后果 |
|---|---|---|
livenessProbe | 容器是否还活着 | kubelet 杀掉容器重建 |
readinessProbe | 容器能否接请求 | 从 Service 摘除,不杀 |
startupProbe | 启动是否完成 | 启动期间 disable liveness+readiness |
Lesson 0016:K8s 生产实践 →——Helm、HPA、RBAC、监控集成。Plan A 最后一课。