HiHuo
首页
博客
手册
工具
关于
首页
博客
手册
工具
关于
  • DevOps与CI/CD

    • DevOps & CI/CD实践手册
    • 第1章:CI/CD流程设计
    • 第2章:Jenkins与GitLab CI
    • 第3章:Docker容器化
    • 第4章:Kubernetes编排
    • 第5章:GitOps与自动化部署

第4章:Kubernetes编排

Kubernetes核心概念

1. Kubernetes架构

┌────────────────────────────────────────────────────┐
│                 Control Plane                      │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐          │
│  │API Server│ │Scheduler │ │Controller│          │
│  └──────────┘ └──────────┘ │ Manager  │          │
│                             └──────────┘          │
│  ┌──────────┐                                     │
│  │  etcd    │ (集群状态存储)                      │
│  └──────────┘                                     │
└────────────────────────────────────────────────────┘
               ↓  ↓  ↓
┌──────────────────────────────────────────────────┐
│                  Worker Nodes                     │
│  ┌────────────────────────────────────────────┐  │
│  │  Node 1                                    │  │
│  │  ┌────────┐ ┌───────┐ ┌───────────────┐  │  │
│  │  │kubelet │ │kube-  │ │  Pods         │  │  │
│  │  │        │ │proxy  │ │ ┌───┐  ┌───┐ │  │  │
│  │  └────────┘ └───────┘ │ │Pod│  │Pod│ │  │  │
│  │                        │ └───┘  └───┘ │  │  │
│  │                        └───────────────┘  │  │
│  └────────────────────────────────────────────┘  │
│  ┌────────────────────────────────────────────┐  │
│  │  Node 2                                    │  │
│  │  (同上)                                     │  │
│  └────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────┘

2. 核心资源

Pod:

最小部署单元,包含一个或多个容器

┌─────────────────────┐
│       Pod           │
│  ┌──────────────┐  │
│  │  Container 1 │  │
│  └──────────────┘  │
│  ┌──────────────┐  │
│  │  Container 2 │  │
│  └──────────────┘  │
│  共享:             │
│  - 网络命名空间     │
│  - IPC命名空间      │
│  - Volume           │
└─────────────────────┘

Deployment:

管理Pod副本,支持滚动更新

Deployment
   ↓
ReplicaSet (v1)
   ↓
Pod Pod Pod

Service:

为Pod提供稳定的网络端点

Service (ClusterIP: 10.0.0.100)
   ↓
Selector: app=myapp
   ↓
┌────┐ ┌────┐ ┌────┐
│Pod │ │Pod │ │Pod │
└────┘ └────┘ └────┘

3. 安装Kubernetes

方式1:Minikube(本地开发):

# 安装Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube

# 启动集群
minikube start --cpus=4 --memory=8192 --driver=docker

# 验证
kubectl get nodes

方式2:k3s(轻量级生产):

# 安装k3s
curl -sfL https://get.k3s.io | sh -

# 配置kubeconfig
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown $USER ~/.kube/config

# 验证
kubectl get nodes

方式3:kubeadm(标准生产):

# 1. 安装Docker、kubeadm、kubelet、kubectl
# (详见官方文档)

# 2. 初始化Master节点
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

# 3. 配置kubeconfig
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 4. 安装网络插件(Calico)
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml

# 5. 加入Worker节点
sudo kubeadm join <master-ip>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

资源编排

1. Pod定义

基础Pod:

# pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: myapp:v1.0.0
    ports:
    - containerPort: 8080
    env:
    - name: DATABASE_URL
      value: postgres://db:5432/myapp
    resources:
      limits:
        cpu: "1"
        memory: "512Mi"
      requests:
        cpu: "0.5"
        memory: "256Mi"

多容器Pod(Sidecar):

# multi-container-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: myapp-with-sidecar
spec:
  containers:
  # 主应用容器
  - name: app
    image: myapp:v1.0.0
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app

  # Sidecar容器(日志收集)
  - name: log-collector
    image: fluentd:latest
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/app
      readOnly: true

  volumes:
  - name: shared-logs
    emptyDir: {}

2. Deployment

完整的Deployment:

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
  labels:
    app: myapp
spec:
  replicas: 3
  revisionHistoryLimit: 10  # 保留10个历史版本
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1         # 最多额外创建1个Pod
      maxUnavailable: 0   # 最多0个Pod不可用
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
        version: v1.0.0
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - myapp
              topologyKey: kubernetes.io/hostname
      containers:
      - name: myapp
        image: harbor.example.com/myproject/myapp:v1.0.0
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: myapp-secret
              key: database-url
        - name: REDIS_URL
          valueFrom:
            configMapKeyRef:
              name: myapp-config
              key: redis-url
        resources:
          limits:
            cpu: "1"
            memory: "1Gi"
          requests:
            cpu: "500m"
            memory: "512Mi"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          timeoutSeconds: 3
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 3
        volumeMounts:
        - name: config
          mountPath: /etc/config
          readOnly: true
      volumes:
      - name: config
        configMap:
          name: myapp-config
      imagePullSecrets:
      - name: harbor-secret

3. ConfigMap和Secret

ConfigMap(配置):

# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
  namespace: production
data:
  redis-url: redis://redis:6379/0
  log-level: info
  config.yaml: |
    server:
      port: 8080
      timeout: 30s
    database:
      max_connections: 100

Secret(密钥):

# secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: myapp-secret
  namespace: production
type: Opaque
data:
  database-url: cG9zdGdyZXM6Ly91c2VyOnBhc3N3b3JkQGRiOjU0MzIvbXlhcHAK  # base64编码
  api-key: eW91ci1hcGkta2V5Cg==
# 创建Secret
kubectl create secret generic myapp-secret \
  --from-literal=database-url='postgres://user:password@db:5432/myapp' \
  --from-literal=api-key='your-api-key' \
  -n production

4. PersistentVolume和PVC

PersistentVolume(PV):

# pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: standard
  hostPath:
    path: /data/mysql

PersistentVolumeClaim(PVC):

# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pvc
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi
  storageClassName: standard

使用PVC:

# mysql-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
      - name: mysql
        image: mysql:8.0
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysql-secret
              key: root-password
        volumeMounts:
        - name: mysql-data
          mountPath: /var/lib/mysql
      volumes:
      - name: mysql-data
        persistentVolumeClaim:
          claimName: mysql-pvc

服务发现与负载均衡

1. Service类型

ClusterIP(集群内部访问):

# service-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  namespace: production
spec:
  type: ClusterIP
  selector:
    app: myapp
  ports:
  - name: http
    port: 80
    targetPort: 8080
    protocol: TCP

# 访问:curl http://myapp-service.production.svc.cluster.local

NodePort(节点端口访问):

# service-nodeport.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-nodeport
spec:
  type: NodePort
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080  # 节点端口(30000-32767)

# 访问:curl http://<node-ip>:30080

LoadBalancer(云负载均衡器):

# service-loadbalancer.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-lb
spec:
  type: LoadBalancer
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8080

# 云提供商自动创建负载均衡器
# 访问:curl http://<external-ip>

2. Ingress

安装Nginx Ingress Controller:

# 安装Nginx Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.0/deploy/static/provider/cloud/deploy.yaml

# 验证
kubectl get pods -n ingress-nginx

Ingress规则:

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

多域名Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
spec:
  ingressClassName: nginx
  rules:
  # www.example.com → frontend
  - host: www.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80

  # api.example.com → backend
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: backend-service
            port:
              number: 8080

自动扩缩容

1. Horizontal Pod Autoscaler (HPA)

基于CPU的HPA:

# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70  # CPU使用率超过70%时扩容
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80  # 内存使用率超过80%时扩容
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
      - type: Percent
        value: 50  # 每次扩容50%
        periodSeconds: 60
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
      - type: Pods
        value: 1  # 每次缩容1个Pod
        periodSeconds: 120

基于自定义指标的HPA:

# custom-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-custom-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 20
  metrics:
  # 基于QPS(每秒请求数)
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "1000"  # 每个Pod处理1000 QPS

2. Vertical Pod Autoscaler (VPA)

# vpa.yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: myapp-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  updatePolicy:
    updateMode: "Auto"  # 自动调整资源限制
  resourcePolicy:
    containerPolicies:
    - containerName: myapp
      minAllowed:
        cpu: "100m"
        memory: "128Mi"
      maxAllowed:
        cpu: "2"
        memory: "2Gi"

3. Cluster Autoscaler

# cluster-autoscaler.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-autoscaler
  namespace: kube-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cluster-autoscaler
  template:
    metadata:
      labels:
        app: cluster-autoscaler
    spec:
      serviceAccountName: cluster-autoscaler
      containers:
      - name: cluster-autoscaler
        image: k8s.gcr.io/autoscaling/cluster-autoscaler:v1.27.0
        command:
        - ./cluster-autoscaler
        - --cloud-provider=aws
        - --namespace=kube-system
        - --nodes=2:10:k8s-worker-asg  # 最小2个,最大10个节点
        - --skip-nodes-with-local-storage=false

Helm包管理

1. 安装Helm

# 安装Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# 验证
helm version

2. 使用Helm Charts

添加仓库:

# 添加官方仓库
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami

# 更新仓库
helm repo update

# 搜索Chart
helm search repo mysql

安装应用:

# 安装MySQL
helm install my-mysql bitnami/mysql \
  --set auth.rootPassword=secretpassword \
  --set primary.persistence.size=10Gi \
  --namespace database \
  --create-namespace

# 查看状态
helm status my-mysql -n database

# 查看值
helm get values my-mysql -n database

# 升级
helm upgrade my-mysql bitnami/mysql \
  --set auth.rootPassword=newsecret \
  -n database

# 回滚
helm rollback my-mysql 1 -n database

# 卸载
helm uninstall my-mysql -n database

3. 创建Helm Chart

Chart结构:

myapp/
├── Chart.yaml          # Chart元数据
├── values.yaml         # 默认配置值
├── templates/          # 模板文件
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── _helpers.tpl   # 辅助模板
│   └── NOTES.txt      # 安装后说明
└── charts/            # 依赖Chart

Chart.yaml:

apiVersion: v2
name: myapp
description: A Helm chart for myapp
type: application
version: 1.0.0
appVersion: "1.0.0"
maintainers:
- name: Your Name
  email: your@email.com

values.yaml:

replicaCount: 3

image:
  repository: myapp
  pullPolicy: IfNotPresent
  tag: "v1.0.0"

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  className: nginx
  hosts:
    - host: myapp.example.com
      paths:
        - path: /
          pathType: Prefix

resources:
  limits:
    cpu: 1000m
    memory: 1Gi
  requests:
    cpu: 500m
    memory: 512Mi

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70

templates/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "myapp.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "myapp.selectorLabels" . | nindent 8 }}
    spec:
      containers:
      - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        resources:
          {{- toYaml .Values.resources | nindent 12 }}

安装自定义Chart:

# 本地Chart
helm install myapp ./myapp -n production

# 自定义值
helm install myapp ./myapp \
  --set replicaCount=5 \
  --set image.tag=v2.0.0 \
  -n production

# 使用values文件
helm install myapp ./myapp -f values-prod.yaml -n production

监控与日志

1. Prometheus监控

安装Prometheus Operator:

# 使用Helm安装kube-prometheus-stack
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install kube-prometheus prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace

ServiceMonitor(监控应用):

# servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: myapp-metrics
  namespace: production
  labels:
    release: kube-prometheus
spec:
  selector:
    matchLabels:
      app: myapp
  endpoints:
  - port: metrics
    interval: 30s
    path: /metrics

应用暴露Prometheus指标:

# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
  labels:
    app: myapp
spec:
  selector:
    app: myapp
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: metrics
    port: 9090
    targetPort: 9090  # Prometheus指标端口

PrometheusRule(告警规则):

# prometheusrule.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: myapp-alerts
  namespace: monitoring
spec:
  groups:
  - name: myapp
    interval: 30s
    rules:
    - alert: HighErrorRate
      expr: rate(http_requests_total{status=~"5.."}[5m]) > 0.05
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "High error rate on {{ $labels.pod }}"
        description: "Error rate is {{ $value }} requests/sec"

    - alert: PodCrashLooping
      expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Pod {{ $labels.pod }} is crash looping"

2. Grafana可视化

访问Grafana:

# 获取admin密码
kubectl get secret kube-prometheus-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decode

# 端口转发
kubectl port-forward -n monitoring svc/kube-prometheus-grafana 3000:80

# 访问:http://localhost:3000
# 用户名:admin
# 密码:(上面获取的密码)

导入Dashboard:

Grafana → Dashboards → Import

推荐Dashboard ID:
- 315:Kubernetes Cluster Monitoring
- 6417:Kubernetes Cluster
- 7249:Kubernetes Deployment

3. EFK日志栈

安装Elasticsearch:

helm repo add elastic https://helm.elastic.co
helm install elasticsearch elastic/elasticsearch -n logging --create-namespace

安装Fluentd:

# fluentd-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: logging
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      serviceAccountName: fluentd
      containers:
      - name: fluentd
        image: fluent/fluentd-kubernetes-daemonset:v1-debian-elasticsearch
        env:
        - name: FLUENT_ELASTICSEARCH_HOST
          value: "elasticsearch-master.logging.svc.cluster.local"
        - name: FLUENT_ELASTICSEARCH_PORT
          value: "9200"
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

安装Kibana:

helm install kibana elastic/kibana -n logging

# 访问Kibana
kubectl port-forward -n logging svc/kibana-kibana 5601:5601
# http://localhost:5601

面试问答

Pod和容器有什么区别?

答案:

容器(Container):
- 单个应用进程
- Docker镜像的运行实例

Pod:
- Kubernetes最小部署单元
- 包含一个或多个容器
- 共享网络和存储

┌─────────────────────┐
│       Pod           │
│  ┌──────────────┐  │
│  │  容器1        │  │
│  │  (主应用)     │  │
│  └──────────────┘  │
│  ┌──────────────┐  │
│  │  容器2        │  │
│  │  (Sidecar)    │  │
│  └──────────────┘  │
│  共享:             │
│  - IP地址          │
│  - localhost通信   │
│  - Volume          │
└─────────────────────┘

使用场景:

单容器Pod:
- 独立应用

多容器Pod(Sidecar模式):
- 日志收集:App + Fluentd
- 服务网格:App + Envoy
- 配置热更新:App + ConfigReloader

Kubernetes的Service有哪些类型?

答案:

类型使用场景访问方式
ClusterIP集群内部通信ClusterIP
NodePort测试环境<NodeIP>:<NodePort>
LoadBalancer生产环境云负载均衡器IP
IngressHTTP/HTTPS流量域名

详细说明:

ClusterIP(默认):
service-name.namespace.svc.cluster.local

NodePort:
http://<任意节点IP>:30080

LoadBalancer:
http://<外部IP>

Ingress:
http://myapp.example.com

选择建议:

开发环境:ClusterIP + kubectl port-forward
测试环境:NodePort
生产环境:LoadBalancer或Ingress

如何实现Kubernetes的滚动更新和回滚?

答案:

滚动更新:

# 方式1:kubectl set image
kubectl set image deployment/myapp myapp=myapp:v2.0.0 -n production
kubectl rollout status deployment/myapp -n production

# 方式2:kubectl apply
# 修改deployment.yaml中的image
kubectl apply -f deployment.yaml

# 方式3:kubectl edit
kubectl edit deployment myapp -n production

滚动更新策略:

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1         # 最多额外创建1个Pod
      maxUnavailable: 0   # 更新时保持所有Pod可用

更新流程:

初始状态:v1.0.0 (3个Pod)
┌────┐ ┌────┐ ┌────┐
│ v1 │ │ v1 │ │ v1 │
└────┘ └────┘ └────┘

步骤1:创建1个v2 Pod
┌────┐ ┌────┐ ┌────┐ ┌────┐
│ v1 │ │ v1 │ │ v1 │ │ v2 │
└────┘ └────┘ └────┘ └────┘

步骤2:删除1个v1 Pod
┌────┐ ┌────┐ ┌────┐
│ v1 │ │ v1 │ │ v2 │
└────┘ └────┘ └────┘

...重复直到全部v2
┌────┐ ┌────┐ ┌────┐
│ v2 │ │ v2 │ │ v2 │
└────┘ └────┘ └────┘

回滚:

# 查看历史版本
kubectl rollout history deployment/myapp -n production

# 回滚到上一个版本
kubectl rollout undo deployment/myapp -n production

# 回滚到指定版本
kubectl rollout undo deployment/myapp --to-revision=2 -n production

# 暂停和恢复
kubectl rollout pause deployment/myapp -n production
kubectl rollout resume deployment/myapp -n production

如何实现Kubernetes的自动扩缩容?

答案:

1. HPA(水平扩缩容):

# 基于CPU/内存
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: myapp-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

2. VPA(垂直扩缩容):

# 自动调整资源requests/limits
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: myapp-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  updatePolicy:
    updateMode: "Auto"

3. Cluster Autoscaler(集群扩缩容):

自动增加/减少节点数量:
- Pod pending → 增加节点
- 节点空闲 → 减少节点

三者关系:

HPA:Pod副本数量(2 → 10)
VPA:Pod资源大小(512Mi → 1Gi)
CA:节点数量(3 → 5)

如何保证Kubernetes应用的高可用?

答案:

1. 多副本部署:

spec:
  replicas: 3  # 至少3个副本

2. Pod反亲和性:

# 确保Pod分散在不同节点
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - myapp
        topologyKey: kubernetes.io/hostname

3. PodDisruptionBudget:

# 确保最少可用Pod数量
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: myapp-pdb
spec:
  minAvailable: 2  # 至少2个Pod可用
  selector:
    matchLabels:
      app: myapp

4. 健康检查:

livenessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 30
  periodSeconds: 10

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 10
  periodSeconds: 5

5. 资源限制:

resources:
  limits:
    cpu: "1"
    memory: "1Gi"
  requests:
    cpu: "500m"
    memory: "512Mi"

6. 滚动更新策略:

strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1
    maxUnavailable: 0  # 保持所有Pod可用

参考资料

  • Kubernetes Documentation
  • Helm Documentation
  • Prometheus Operator
  • kube-prometheus-stack
Prev
第3章:Docker容器化
Next
第5章:GitOps与自动化部署