正在加载,请稍候…

Kubernetes 入门教程:Pod、Deployment、Service 与你的第一个集群

面向初学者的 Kubernetes 全面教程:涵盖架构、Pod、Deployment、Service、ConfigMap、Secret、Ingress,以及如何

Kubernetes 入门教程:Pod、Deployment、Service 与你的第一个集群

为什么 Kubernetes 值得学习

Kubernetes(K8s)是云的操作系统。它很复杂,这一点无需掩饰。但如果你以任何规模运行容器化应用——哪怕只是几个微服务——它都能解决手动处理起来非常痛苦的实际问题。

K8s 解决的问题:如何重启崩溃的容器?如何无停机地推出更新?流量高峰时如何扩容?如何将流量路由到正确的容器?K8s 对所有这些都有成熟的方案,背后是 Google 多年的生产经验。

Kubernetes 入门教程:Pod、Deployment、Service 与你的第一个集群 插图

核心架构

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

Kubernetes 入门教程:Pod、Deployment、Service 与你的第一个集群 插图

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

Kubernetes 入门教程:Pod、Deployment、Service 与你的第一个集群 插图

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 格式。