
为什么 Kubernetes 值得学习
Kubernetes(K8s)是云的操作系统。它很复杂,这一点无需掩饰。但如果你以任何规模运行容器化应用——哪怕只是几个微服务——它都能解决手动处理起来非常痛苦的实际问题。
K8s 解决的问题:如何重启崩溃的容器?如何无停机地推出更新?流量高峰时如何扩容?如何将流量路由到正确的容器?K8s 对所有这些都有成熟的方案,背后是 Google 多年的生产经验。

核心架构
Kubernetes 集群
├── 控制平面(原 "master")
│ ├── API Server — 所有通信都经过这里
│ ├── etcd — 集群状态存储(分布式键值存储)
│ ├── Scheduler — 决定哪个节点运行哪个 Pod
│ └── Controller Manager — 确保期望状态与实际状态一致
│
└── 工作节点(1 到数千个)
├── kubelet — 在每个节点上运行的代理,与 API Server 通信
├── kube-proxy — 网络代理,管理 Service 路由
└── 容器运行时 — containerd/CRI-O(运行你的容器)
基本循环:你向 API Server 告知你的期望状态("我想要这个容器的 3 个副本")。控制器比较期望状态与实际状态,并进行更改以达到期望状态。
Pod:最小单元
Pod 是一个或多个共享网络和存储的容器:
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-app
labels:
app: my-app
environment: production
spec:
containers:
- name: app
image: my-app:1.0.0
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi" # 最低保证
cpu: "100m" # 100 毫核 = 0.1 CPU
limits:
memory: "256Mi" # 最大允许
cpu: "500m"
env:
- name: NODE_ENV
value: "production"
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
# 应用并检查
kubectl apply -f pod.yaml
kubectl get pods
kubectl describe pod my-app
kubectl logs my-app
kubectl exec -it my-app -- /bin/sh
不要在生产环境中直接运行 Pod——它们不会自动重启。请使用 Deployment。
Deployment:托管 Pod 生命周期
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3 # 运行 3 个 Pod
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 更新期间创建 1 个额外 Pod
maxUnavailable: 0 # 绝不低于 3 个运行中的 Pod
template:
metadata:
labels:
app: my-app # 必须与 selector 匹配
spec:
containers:
- name: app
image: my-app:1.0.0
ports:
- containerPort: 3000
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
# 常见的 Deployment 操作
kubectl apply -f deployment.yaml
# 手动扩缩
kubectl scale deployment my-app --replicas=5
# 滚动更新
kubectl set image deployment/my-app app=my-app:2.0.0
# 查看更新进度
kubectl rollout status deployment/my-app
# 如果出问题则回滚
kubectl rollout undo deployment/my-app
# 查看更新历史
kubectl rollout history deployment/my-app
kubectl rollout undo deployment/my-app --to-revision=2

Service:稳定的网络
Pod 是短暂的——它们会死亡并被替换为新的 IP。Service 提供稳定的端点:
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app # 路由到具有此标签的 Pod
ports:
- port: 80 # Service 端口
targetPort: 3000 # 容器端口
type: ClusterIP # 仅内部(默认)
---
# 用于云环境的外部访问:
apiVersion: v1
kind: Service
metadata:
name: my-app-loadbalancer
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 3000
type: LoadBalancer # 云提供商配置负载均衡器
Service 类型:
ClusterIP:集群内部(默认)NodePort:在每个节点的端口上暴露(30000-32767)LoadBalancer:创建云负载均衡器(AWS ELB、GCP LB 等)ExternalName:外部服务的 DNS 别名
Ingress:HTTP 路由
用于将 HTTP 流量路由到多个 Service:
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-prod # 自动 TLS
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls-cert
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-service
port:
number: 80
- host: admin.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: admin-service
port:
number: 80
ConfigMap 和 Secret
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
# 键值对
LOG_LEVEL: "info"
API_BASE_URL: "https://api.example.com"
# 多行值(配置文件)
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://localhost:3000;
}
}
---
# secret.yaml(base64 编码的值)
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
url: cG9zdGdyZXNxbDovL3VzZXI6cGFzc0Bob3N0L2Ri # base64 编码
password: c3VwZXJzZWNyZXQ=
# 从命令行创建 Secret(避免手动 base64 编码)
kubectl create secret generic db-credentials --from-literal=url="postgresql://user:pass@host/db" --from-literal=password="supersecret"
# 或从文件创建
kubectl create secret generic tls-cert --from-file=tls.crt=./cert.pem --from-file=tls.key=./key.pem
# 在 Deployment 中使用 ConfigMap 和 Secret
spec:
containers:
- name: app
envFrom:
- configMapRef:
name: app-config # 所有键都成为环境变量
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
volumeMounts:
- name: config-volume
mountPath: /etc/nginx
volumes:
- name: config-volume
configMap:
name: app-config
items:
- key: nginx.conf
path: nginx.conf

Namespace:环境隔离
# 创建用于环境隔离的 Namespace
kubectl create namespace staging
kubectl create namespace production
# 部署到特定 Namespace
kubectl apply -f deployment.yaml -n production
# 查看 Namespace 中的资源
kubectl get all -n production
# 设置 kubectl 的默认 Namespace
kubectl config set-context --current --namespace=production
# 每个 Namespace 的资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
pods: "50"
services: "20"
健康检查
spec:
containers:
- name: app
# Liveness:容器是否存活?失败则重启。
livenessProbe:
httpGet:
path: /health/live
port: 3000
initialDelaySeconds: 30 # 首次检查前等待 30 秒
periodSeconds: 10 # 每 10 秒检查一次
timeoutSeconds: 5 # 5 秒无响应则失败
failureThreshold: 3 # 连续 3 次失败后重启
# Readiness:容器是否准备好接收流量?
# 失败则从 Service 端点中移除(不重启)
readinessProbe:
httpGet:
path: /health/ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1 # 1 次成功即标记为就绪
# Startup:启动缓慢的容器——启动期间覆盖 liveness
startupProbe:
httpGet:
path: /health/live
port: 3000
failureThreshold: 30 # 允许最多 5 分钟启动(30 * 10 秒)
periodSeconds: 10
HorizontalPodAutoscaler
# autoscaler.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70 # CPU 使用率超过 70% 时扩容
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
必备 kubectl 命令
# 集群信息
kubectl cluster-info
kubectl get nodes
kubectl top nodes # CPU/内存使用情况
# 资源
kubectl get pods -A # 所有 Namespace
kubectl get pods -o wide # 显示节点分配
kubectl describe pod <name> # 详细信息 + 事件
kubectl logs <pod> -f # 跟踪日志
kubectl logs <pod> --previous # 崩溃容器的日志
# 调试
kubectl exec -it <pod> -- bash # 进入容器 Shell
kubectl port-forward <pod> 8080:3000 # 本地端口转发
kubectl cp <pod>:/path/to/file ./local-file # 复制文件
# 应用 / 删除
kubectl apply -f . # 应用目录中的所有 YAML
kubectl delete -f deployment.yaml
kubectl delete pod <name> --force # 强制删除卡住的 Pod
# 上下文切换
kubectl config get-contexts
kubectl config use-context production-cluster
# 试运行(测试而不应用)
kubectl apply -f deployment.yaml --dry-run=client
Kubernetes 的学习曲线很陡峭,但一旦你理解了其思维模型,这些抽象设计得非常精良。控制循环(期望状态 → 实际状态)是一切的基础,一旦你内化了它,每种资源类型的行为就变得可预测。
→ 使用 Docker Run Converter 将 Docker run 命令转换为 Docker Compose 格式。