Skip to content

预计时间

1 周

定位

这一节只要求理解概念 + 跑通 demo,不要求成为 K8s 专家。K8s 学习曲线陡峭,初学搞清楚 Pod / Deployment / Service / Ingress 就够了。

学习目标

  • 理解 Pod、Deployment、Service、Ingress
  • 能用 kubectl 操作集群
  • 能把 Docker Compose 项目迁移到 K8s

一、K8s 解决什么问题?

text
Docker Compose 的局限:
  - 单机 — 一台服务器挂了全挂
  - 手动扩容 — 要改 compose 文件加 replicas
  - 滚动更新 — 手动操作
  - 服务发现 — 靠 DNS 名,跨机器就不行

K8s 的答案:
  你告诉它"我要 3 个 backend、2 个 frontend、1 个 PostgreSQL"
  K8s 自动调度到多台机器、自动重启挂了容器、自动滚动更新

二、核心概念

2.1 Pod — 最小调度单元

yaml
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: backend-pod
  labels:
    app: backend
spec:
  containers:
    - name: backend
      image: my-backend:latest
      ports:
        - containerPort: 3001
      env:
        - name: DATABASE_URL
          value: "postgresql://user:pass@postgres:5432/db"
text
Pod 是什么?
  - K8s 不直接管理容器,管理 Pod
  - 1 个 Pod 通常有 1 个 Container(也有 sidecar 模式放 2 个)
  - Pod 里的容器共享网络和存储
  - Pod 是临时的,IP 会变,随时可能被销毁重建

一般不直接创建 Pod

Pod 是"底层",直接创建 Pod 挂了不会自动重启。实际使用 Deployment 管理 Pod。

2.2 Deployment — 管理 Pod

yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-deployment
spec:
  replicas: 3                    # 3 个副本
  selector:
    matchLabels:
      app: backend
  template:                      # Pod 模板
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: my-backend:v1.0
          ports:
            - containerPort: 3001
          resources:
            requests:
              memory: "256Mi"
              cpu: "250m"
            limits:
              memory: "512Mi"
              cpu: "500m"
          livenessProbe:         # 健康检查
            httpGet:
              path: /health
              port: 3001
            initialDelaySeconds: 10
            periodSeconds: 5
text
Deployment 做什么?
  - 保持 Pod 副本数(挂了自动补上)
  - 滚动更新(一个一个替换 Pod,服务不中断)
  - 回滚(kubectl rollout undo)

2.3 Service — 稳定的访问入口

yaml
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  selector:
    app: backend          # 选择哪些 Pod
  ports:
    - port: 80            # Service 的端口
      targetPort: 3001    # Pod 的端口
  type: ClusterIP         # 默认,集群内部访问
text
问题:Pod IP 会变 → 前端怎么知道连哪个 IP?
解决:Service 提供固定的 ClusterIP + DNS 名

集群内访问:
  http://backend-service  → Service → 自动负载均衡到 3 个 Pod

Service 类型:
  ClusterIP  — 仅集群内部访问(默认)
  NodePort   — 宿主机端口暴露(不推荐生产用)
  LoadBalancer — 云厂商 LB(生产用)

2.4 Ingress — 外部流量入口

yaml
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
spec:
  rules:
    - host: api.myapp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: backend-service
                port:
                  number: 80
    - host: myapp.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80
text
Ingress = K8s 版的 Nginx 反向代理

  myapp.com     → frontend-service
  api.myapp.com → backend-service

需要安装 Ingress Controller(如 nginx-ingress)才能工作。

三、ConfigMap & Secret

yaml
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  NODE_ENV: "production"
  LOG_LEVEL: "info"
---
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
type: Opaque
stringData:
  DATABASE_URL: "postgresql://user:password@postgres:5432/db"
  JWT_SECRET: "your-secret-key"
yaml
# 在 Deployment 中使用
spec:
  containers:
    - name: backend
      envFrom:
        - configMapRef:
            name: app-config
        - secretRef:
            name: app-secret

四、常用命令

bash
# 查看
kubectl get pods                    # 所有 Pod
kubectl get deployments             # 所有 Deployment
kubectl get services                # 所有 Service
kubectl get ingress                 # 所有 Ingress
kubectl describe pod <pod-name>     # Pod 详情

# 日志
kubectl logs <pod-name>             # 查看日志
kubectl logs -f <pod-name>          # 实时日志

# 操作
kubectl apply -f deployment.yaml    # 创建/更新资源
kubectl delete -f deployment.yaml   # 删除资源
kubectl rollout restart deployment/backend  # 重启
kubectl rollout undo deployment/backend     # 回滚

# 调试
kubectl exec -it <pod-name> -- /bin/sh  # 进容器
kubectl port-forward <pod-name> 3001:3001 # 端口转发到本地

五、Docker Compose → K8s 迁移对照

Docker ComposeKubernetes
ServiceDeployment + Service
ports: "3000:3000"Service port + targetPort
depends_oninitContainers 或 healthcheck + readinessProbe
volumes: - pgdata:/dataPersistentVolume + PersistentVolumeClaim
environmentConfigMap / Secret
networks默认 Pod 间互通 + NetworkPolicy 隔离

六、本地开发

不用买云服务器,本地就能跑 K8s:

bash
# 选项 1: Docker Desktop 内置 K8s
# Settings → Kubernetes → Enable Kubernetes

# 选项 2: minikube
brew install minikube
minikube start

# 选项 3: kind (Kubernetes in Docker)
brew install kind
kind create cluster

实践

  1. 装一个 minikube 或 kind
  2. 把 Docker Compose 项目转成 Deployment + Service YAML
  3. kubectl apply -f . 部署
  4. kubectl port-forward 访问
  5. 故意删一个 Pod → 观察自动恢复