Kubernetes 完全指南:从零基础到生产实践

Kubernetes 完全指南:从零基础到生产实践

本文定位:一篇适合新手入门、中手查漏补缺、老手温故知新的 K8s 百科全书。全文约 15000 字,建议收藏后分章节阅读。


📚 目录

  1. 为什么需要 Kubernetes?
  2. 核心概念与架构
  3. 安装与配置
  4. kubectl 完全命令手册
  5. 第一个应用部署(实操)
  6. 核心资源对象详解
  7. 进阶调度与弹性伸缩
  8. 存储管理 PV/PVC
  9. 网络模型与 Ingress
  10. 配置管理 ConfigMap/Secret
  11. Helm 包管理
  12. CI/CD 与 GitOps
  13. 监控与日志
  14. 常见故障排查
  15. 生产环境最佳实践

1. 为什么需要 Kubernetes?

1.1 从单体到微服务的演进

微服务架构

网关

用户服务

订单服务

商品服务

用户DB

订单DB

商品DB

单体架构

Web应用

数据库

文件存储

痛点

  • 微服务数量爆炸(几十上百个服务)
  • 部署频繁(一天多次发布)
  • 环境不一致(开发/测试/生产差异大)
  • 资源利用率低(服务器闲置浪费)

1.2 Kubernetes 能做什么?

能力说明类比
自动装箱根据资源需求自动调度容器到合适节点智能物流分拣
自我修复容器挂了自动重启,节点宕机自动迁移自愈能力
水平扩展根据 CPU/内存自动增减 Pod 数量弹性伸缩
服务发现自动为 Pod 分配 DNS 和 IP,负载均衡内置服务注册中心
滚动更新零停机发布,异常自动回滚金丝雀发布
存储编排自动挂载云存储、NFS、本地盘自动挂载硬盘

1.3 K8s 不是什么?

  • 不是 PaaS(平台即服务)—— 它不限制你用什么语言/框架
  • 不是 传统的 CI/CD 工具 —— 它只管部署,不负责构建
  • 不是 容器运行时 —— 它依赖 Docker/containerd 来运行容器
  • 不是 配置管理工具 —— 它用声明式 YAML,不用 Ansible/Puppet 那种命令式脚本

2. 核心概念与架构

2.1 整体架构图

工作节点 (Worker Node)

控制平面 (Control Plane)

Pods

kube-apiserver

etcd
(分布式存储)

kube-scheduler

kube-controller-manager

cloud-controller-manager

kubelet

kube-proxy

容器运行时
(containerd)

Pod A
(容器1, 容器2)

Pod B

kubectl
(用户)

2.2 组件详解

组件位置作用关键点
kube-apiserver控制平面集群唯一入口,REST API 服务所有操作都经过它,是集群的"前台"
etcd控制平面分布式键值存储,保存所有集群数据必须备份,损坏则集群无法恢复
kube-scheduler控制平面为新 Pod 选择最优节点考虑资源、亲和性、污点等
kube-controller-manager控制平面运行所有控制器(Deployment、Node 等)确保实际状态与期望状态一致
cloud-controller-manager控制平面与云厂商交互(负载均衡、存储卷)云上集群才有
kubelet工作节点管理 Pod 生命周期与 API Server 通信,汇报节点状态
kube-proxy工作节点维护网络规则,实现 Service 负载均衡支持 iptables/IPVS 模式
容器运行时工作节点实际运行容器containerd、CRI-O、Docker

2.3 核心资源对象层级

Cluster 集群

Namespace 命名空间

管理

管理

管理

管理

管理

Pod

Container 1

Container 2

Service

Ingress

PersistentVolume

PersistentVolumeClaim

ConfigMap

Secret

Deployment

StatefulSet

DaemonSet

Job

CronJob

2.4 核心资源对象速查表

资源类型缩写作用有状态?
Podpo最小部署单元,一个或多个容器
Deploymentdeploy无状态应用,滚动更新/回滚
StatefulSetsts有状态应用(数据库),稳定标识
DaemonSetds每个节点跑一个 Pod(监控、日志)
Jobjob一次性任务
CronJobcj定时任务
Servicesvc稳定访问入口,负载均衡
Ingressing七层路由(域名/路径转发)
ConfigMapcm非敏感配置项
Secretsecret敏感信息(密码/证书)
PersistentVolumepv集群级存储资源
PersistentVolumeClaimpvc存储资源申请
Namespacens资源隔离
ServiceAccountsaPod 身份认证

3. 安装与配置

3.1 本地开发环境

方式适用场景资源消耗难度
Minikube单节点本地学习⭐⭐
Kind多节点本地测试⭐⭐⭐
K3s轻量级生产/边缘极低⭐⭐
Docker DesktopMac/Windows 内置
Play with K8s在线免费体验
3.1.1 Minikube 安装(推荐新手)
# Windows (使用 Chocolatey)
choco install minikube

# macOS
brew install minikube

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

# 启动集群
minikube start --driver=docker --cpus=2 --memory=4096

# 验证
kubectl get nodes
3.1.2 Kind 安装(需先安装 Docker)
# Windows
choco install kind

# macOS
brew install kind

# Linux
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

# 创建 3 节点集群
kind create cluster --name my-cluster --config - <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
EOF

# 验证
kubectl cluster-info --context kind-my-cluster

3.2 生产环境安装

方式适用场景复杂度
kubeadm自建集群(裸金属/虚拟机)⭐⭐⭐⭐
云厂商托管阿里云 ACK、腾讯云 TKE、AWS EKS
Rancher多集群管理⭐⭐⭐
3.2.1 kubeadm 快速搭建(生产级)
# 1. 所有节点安装 kubeadm/kubelet/kubectl
apt-get update && apt-get install -y kubeadm kubelet kubectl

# 2. 初始化控制平面(仅主节点)
kubeadm init --pod-network-cidr=10.244.0.0/16

# 3. 配置 kubectl(主节点)
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://raw.githubusercontent.com/projectcalico/calico/v3.27/manifests/calico.yaml

# 5. 加入工作节点(在工作节点执行)
kubeadm join <控制平面IP>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

# 6. 验证集群
kubectl get nodes

3.3 kubectl 配置

# 查看当前配置
kubectl config view

# 切换上下文
kubectl config use-context docker-desktop

# 查看所有上下文
kubectl config get-contexts

# 设置默认命名空间
kubectl config set-context --current --namespace=my-ns

# 配置自动补全(bash)
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" >> ~/.bashrc

# 配置自动补全(zsh)
source <(kubectl completion zsh)
echo "source <(kubectl completion zsh)" >> ~/.zshrc

4. kubectl 完全命令手册

4.1 命令结构

kubectl [command] [TYPE] [NAME] [flags]
部分说明示例
command操作类型get, create, apply, delete, describe, logs
TYPE资源类型pod, deployment, service
NAME资源名称my-pod
flags额外参数-n namespace, -o yaml

4.2 基础命令(每日必用)

# ========== 查看资源 ==========
kubectl get nodes                     # 查看节点
kubectl get pods                      # 查看所有 Pod
kubectl get pods -n kube-system       # 查看指定命名空间
kubectl get pods -o wide              # 显示更多信息(IP、节点)
kubectl get pods -o yaml              # 输出 YAML 格式
kubectl get pods -o json              # 输出 JSON 格式
kubectl get pods -w                   # 持续监听变化 (watch)
kubectl get all                       # 查看所有资源

# ========== 详细查看 ==========
kubectl describe pod my-pod           # 查看 Pod 详情(事件、状态)
kubectl describe node node-1          # 查看节点资源使用

# ========== 创建/更新 ==========
kubectl apply -f deployment.yaml      # 创建或更新资源
kubectl create deployment nginx --image=nginx --replicas=3  # 命令式创建
kubectl run nginx --image=nginx       # 快速创建 Pod
kubectl expose deployment nginx --port=80 --type=NodePort   # 暴露 Service

# ========== 删除 ==========
kubectl delete pod my-pod             # 删除 Pod(会自动重建)
kubectl delete deployment nginx       # 删除 Deployment
kubectl delete -f deployment.yaml     # 删除文件中所有资源
kubectl delete pod --all              # 删除所有 Pod

# ========== 日志查看 ==========
kubectl logs my-pod                   # 查看 Pod 日志
kubectl logs my-pod -c container-1    # 查看特定容器日志
kubectl logs -f my-pod                # 实时跟踪日志
kubectl logs --tail=100 my-pod        # 查看最后 100 行
kubectl logs --since=1h my-pod        # 查看最近 1 小时日志

# ========== 进入容器 ==========
kubectl exec -it my-pod -- /bin/bash  # 进入 Pod 终端
kubectl exec my-pod -- ls /app        # 在容器中执行命令

# ========== 端口转发 ==========
kubectl port-forward pod/my-pod 8080:80  # 将 Pod 80 端口转发到本地 8080
kubectl port-forward service/my-svc 8080:80  # 将 Service 端口转发到本地

# ========== 其他 ==========
kubectl explain pod                  # 查看资源字段说明
kubectl api-resources                # 查看所有支持的资源类型
kubectl version                      # 查看版本信息

4.3 高级命令

# ========== 滚动更新 ==========
# 更新镜像(触发滚动更新)
kubectl set image deployment/nginx nginx=nginx:1.20

# 查看滚动更新状态
kubectl rollout status deployment/nginx

# 查看历史版本
kubectl rollout history deployment/nginx

# 回滚到上一版本
kubectl rollout undo deployment/nginx

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

# 暂停/恢复更新(用于金丝雀发布)
kubectl rollout pause deployment/nginx
kubectl rollout resume deployment/nginx

# ========== 扩缩容 ==========
kubectl scale deployment/nginx --replicas=5   # 手动扩缩
kubectl autoscale deployment/nginx --min=2 --max=10 --cpu-percent=80  # 自动伸缩

# ========== 标签操作 ==========
kubectl label pods my-pod app=web              # 添加标签
kubectl label pods my-pod app-                 # 删除标签
kubectl get pods -l app=web                    # 通过标签筛选

# ========== 命名空间 ==========
kubectl create namespace my-ns                 # 创建命名空间
kubectl get ns                                 # 查看所有命名空间
kubectl config set-context --current --namespace=my-ns  # 切换默认命名空间

# ========== 故障排查 ==========
# 查看节点资源使用
kubectl top nodes
kubectl top pods

# 查看事件
kubectl get events --sort-by='.lastTimestamp'
kubectl get events -n kube-system

# 查看 Pod 启动失败原因
kubectl describe pod my-pod | grep -A 10 "Events"

# 查看 API Server 日志
kubectl logs -n kube-system kube-apiserver-<node>

# 查看 Pod 的资源使用
kubectl exec my-pod -- top
kubectl exec my-pod -- cat /proc/meminfo

4.4 常用别名配置(提高效率)

# 添加到 ~/.bashrc 或 ~/.zshrc
alias k='kubectl'
alias kgp='kubectl get pods'
alias kgd='kubectl get deployment'
alias kgs='kubectl get service'
alias kgn='kubectl get nodes'
alias kdp='kubectl describe pod'
alias kdd='kubectl describe deployment'
alias kl='kubectl logs'
alias kex='kubectl exec -it'
alias kaf='kubectl apply -f'
alias kdf='kubectl delete -f'

# 快速查看 Pod 状态 + IP
alias kgpw='kubectl get pods -o wide'

# 查看所有命名空间的 Pod
alias kgpa='kubectl get pods --all-namespaces'

5. 第一个应用部署(实操)

5.1 完整流程

编写代码

构建镜像

推送到仓库

编写 YAML

部署到 K8s

暴露服务

访问测试

5.2 步骤详解

步骤 1:准备一个简单的应用

创建一个 app.py(Flask 示例):

from flask import Flask
import os
import socket

app = Flask(__name__)

@app.route('/')
def hello():
    return {
        'message': 'Hello Kubernetes!',
        'hostname': socket.gethostname(),
        'version': 'v1'
    }

@app.route('/health')
def health():
    return {'status': 'ok'}

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
步骤 2:编写 Dockerfile
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
COPY app.py .
EXPOSE 5000
CMD ["python", "app.py"]
步骤 3:构建并推送镜像
# 构建镜像
docker build -t myapp:v1 .

# 推送到 Docker Hub(或阿里云 ACR)
docker tag myapp:v1 yourusername/myapp:v1
docker push yourusername/myapp:v1
步骤 4:编写 Kubernetes 部署文件

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: yourusername/myapp:v1
        ports:
        - containerPort: 5000
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
        env:
        - name: ENVIRONMENT
          value: "production"
        livenessProbe:
          httpGet:
            path: /health
            port: 5000
          initialDelaySeconds: 5
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health
            port: 5000
          initialDelaySeconds: 3
          periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 5000
  type: NodePort
步骤 5:部署到 Kubernetes
# 1. 应用配置
kubectl apply -f deployment.yaml

# 2. 查看部署状态
kubectl get pods -w              # 等待所有 Pod 变为 Running
kubectl get deployment myapp
kubectl get svc myapp-service

# 3. 查看 Service 分配的 NodePort
kubectl get svc myapp-service
# 输出: myapp-service   NodePort   10.96.xxx.xxx   <none>   80:31234/TCP

# 4. 访问测试
curl http://localhost:31234       # 本地访问
# 或通过节点 IP 访问
curl http://<NodeIP>:31234

# 5. 查看日志
kubectl logs -f deployment/myapp
步骤 6:滚动更新
# 构建新版本镜像
docker build -t myapp:v2 .
docker push yourusername/myapp:v2

# 更新 Deployment
kubectl set image deployment/myapp myapp=yourusername/myapp:v2

# 观察滚动更新过程
kubectl rollout status deployment/myapp

# 如果出问题,立即回滚
kubectl rollout undo deployment/myapp

5.3 完整的 Ingress 配置(使用域名访问)

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: api.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service
            port:
              number: 80
# 安装 Ingress Controller(如果未安装)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml

# 应用 Ingress 规则
kubectl apply -f ingress.yaml

# 查看 Ingress
kubectl get ingress

# 配置本地 hosts 文件访问
echo "127.0.0.1 api.myapp.com" >> /etc/hosts
curl http://api.myapp.com

6. 核心资源对象详解

6.1 Pod 详解

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  namespace: default
  labels:
    app: nginx
    env: prod
  annotations:
    description: "这是一个 Nginx 示例 Pod"
spec:
  # 容器定义
  containers:
  - name: nginx
    image: nginx:1.25
    imagePullPolicy: IfNotPresent  # Always, Never, IfNotPresent
    ports:
    - containerPort: 80
      protocol: TCP
    env:
    - name: ENV
      value: "production"
    - name: SECRET_USERNAME
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: username
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    volumeMounts:
    - name: nginx-storage
      mountPath: /usr/share/nginx/html
    livenessProbe:
      httpGet:
        path: /health
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 5
      failureThreshold: 3
    readinessProbe:
      httpGet:
        path: /ready
        port: 80
      initialDelaySeconds: 2
      periodSeconds: 3
    startupProbe:
      httpGet:
        path: /startup
        port: 80
      initialDelaySeconds: 0
      periodSeconds: 10
      failureThreshold: 30
  # 多容器(Sidecar 模式)
  - name: sidecar
    image: alpine:latest
    command: ["/bin/sh", "-c"]
    args: ["tail -f /dev/null"]

  # 存储卷
  volumes:
  - name: nginx-storage
    persistentVolumeClaim:
      claimName: nginx-pvc

  # 调度策略
  nodeSelector:
    disktype: ssd

  # 容忍度
  tolerations:
  - key: "key"
    operator: "Equal"
    value: "value"
    effect: "NoSchedule"

  # 重启策略
  restartPolicy: Always  # Always, OnFailure, Never

  # 服务账号
  serviceAccountName: default

6.2 Deployment 详解

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
  namespace: default
  labels:
    app: myapp
spec:
  replicas: 3
  revisionHistoryLimit: 10        # 保留的历史版本数
  strategy:
    type: RollingUpdate          # RollingUpdate | Recreate
    rollingUpdate:
      maxSurge: 1                # 最多可以超出的 Pod 数
      maxUnavailable: 0          # 最多不可用的 Pod 数(0 表示无停机)
  selector:
    matchLabels:
      app: myapp
  template:                      # Pod 模板(同 Pod 定义)
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:v1
        ports:
        - containerPort: 8080

6.3 Service 详解

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  type: ClusterIP               # ClusterIP | NodePort | LoadBalancer | ExternalName
  selector:
    app: myapp
  ports:
  - name: http
    port: 80                    # Service 端口
    targetPort: 8080            # Pod 端口
    nodePort: 30080             # NodePort 类型时指定(不指定则随机)
    protocol: TCP
  sessionAffinity: None         # ClientIP(保持会话粘性)
  # sessionAffinityConfig:
  #   clientIP:
  #     timeoutSeconds: 10800

Service 类型对比

类型访问范围使用场景
ClusterIP仅集群内部Pod 间通信
NodePort通过节点 IP:端口外部访问测试
LoadBalancer通过云厂商负载均衡器生产环境外部访问
ExternalName指向外部 DNS访问集群外服务

6.4 StatefulSet(有状态应用)

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: mysql
  replicas: 3
  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: password
        volumeMounts:
        - name: data
          mountPath: /var/lib/mysql
  volumeClaimTemplates:          # 每个 Pod 独立 PVC
  - metadata:
      name: data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi
---
# StatefulSet 对应的 Headless Service
apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  clusterIP: None                # Headless Service
  selector:
    app: mysql
  ports:
  - port: 3306

StatefulSet 特点

  • Pod 有稳定的网络标识:mysql-0, mysql-1, mysql-2
  • 每个 Pod 有自己的持久化存储
  • 按顺序创建/删除(从 0 到 N-1)

6.5 DaemonSet(每个节点一个 Pod)

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: filebeat
spec:
  selector:
    matchLabels:
      app: filebeat
  template:
    metadata:
      labels:
        app: filebeat
    spec:
      containers:
      - name: filebeat
        image: elastic/filebeat:8.11
        volumeMounts:
        - name: varlog
          mountPath: /var/log
        - name: varlibdockercontainers
          mountPath: /var/lib/docker/containers
          readOnly: true
      tolerations:                # 允许调度到 Master 节点
      - key: node-role.kubernetes.io/control-plane
        operator: Exists
        effect: NoSchedule
      volumes:
      - name: varlog
        hostPath:
          path: /var/log
      - name: varlibdockercontainers
        hostPath:
          path: /var/lib/docker/containers

7. 进阶调度与弹性伸缩

7.1 调度策略

# 节点亲和性 (Node Affinity)
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:  # 硬性要求
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/arch
            operator: In
            values:
            - amd64
      preferredDuringSchedulingIgnoredDuringExecution:  # 软性偏好
      - weight: 100
        preference:
          matchExpressions:
          - key: node-type
            operator: In
            values:
            - high-cpu

# Pod 亲和性 (Pod Affinity) - 让 Pod 靠近
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app: cache
        topologyKey: kubernetes.io/hostname

# Pod 反亲和性 (Pod Anti-Affinity) - 让 Pod 分散
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: web
          topologyKey: kubernetes.io/hostname

7.2 污点与容忍度

# 给节点添加污点
kubectl taint nodes node1 key=value:NoSchedule
kubectl taint nodes node1 key=value:NoExecute
kubectl taint nodes node1 key=value:PreferNoSchedule

# 查看节点污点
kubectl describe node node1 | grep Taints

# 删除污点
kubectl taint nodes node1 key:NoSchedule-

# Pod 容忍度配置
tolerations:
- key: "key"
  operator: "Equal"
  value: "value"
  effect: "NoSchedule"
- key: "node.kubernetes.io/not-ready"
  operator: "Exists"
  effect: "NoExecute"
  tolerationSeconds: 300

7.3 水平 Pod 自动伸缩(HPA)

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: 50
  - type: Resource
    resource:
      name: memory
      target:
        type: AverageValue
        averageValue: 200Mi
  - type: Pods                # 自定义指标(需安装 Prometheus)
    pods:
      metric:
        name: requests_per_second
      target:
        type: AverageValue
        averageValue: 1000
# 查看 HPA 状态
kubectl get hpa
kubectl describe hpa myapp-hpa

# 手动触发扩容(测试)
kubectl run -it --rm load-generator --image=busybox -- /bin/sh -c "while true; do wget -q -O- http://myapp-service; done"

7.4 垂直 Pod 自动伸缩(VPA)

apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
  name: myapp-vpa
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: myapp
  updatePolicy:
    updateMode: Auto          # Off | Initial | Recreate | Auto
  resourcePolicy:
    containerPolicies:
    - containerName: myapp
      minAllowed:
        cpu: 100m
        memory: 50Mi
      maxAllowed:
        cpu: 2
        memory: 2Gi

8. 存储管理 PV/PVC

8.1 存储架构

集群

PVC
(存储申请)

PV
(存储资源)

Pod

NFS

Ceph

云存储
(EBS/OSS)

本地盘

8.2 静态存储(预先创建 PV)

# 1. 创建 PV
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
  - ReadWriteMany
  nfs:
    server: 192.168.1.100
    path: /data/nfs
  persistentVolumeReclaimPolicy: Retain  # Retain | Delete | Recycle

---
# 2. 创建 PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nfs-pvc
spec:
  accessModes:
  - ReadWriteMany
  resources:
    requests:
      storage: 5Gi

---
# 3. Pod 使用 PVC
apiVersion: v1
kind: Pod
metadata:
  name: app-with-storage
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: storage
      mountPath: /usr/share/nginx/html
  volumes:
  - name: storage
    persistentVolumeClaim:
      claimName: nfs-pvc

8.3 动态存储(StorageClass)

# 1. 定义 StorageClass
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-storage
provisioner: kubernetes.io/aws-ebs  # 云厂商驱动
parameters:
  type: gp3
  fsType: ext4
reclaimPolicy: Delete
allowVolumeExpansion: true

---
# 2. 声明 PVC 自动创建 PV
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: dynamic-pvc
spec:
  storageClassName: fast-storage
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

8.4 存储访问模式

访问模式缩写说明
ReadWriteOnceRWO仅单个节点可读写
ReadOnlyManyROX多个节点只读
ReadWriteManyRWX多个节点读写(如 NFS)
ReadWriteOncePodRWOP仅单个 Pod 可读写(K8s 1.27+)

9. 网络模型与 Ingress

9.1 Kubernetes 网络模型

Kubernetes 网络要求满足四个基本条件:

  1. 所有 Pod 可以在不使用 NAT 的情况下相互通信
  2. 所有节点可以在不使用 NAT 的情况下与所有 Pod 通信
  3. Pod 看到的自己的 IP 与其他 Pod 看到的 IP 相同
  4. 每个 Pod 有独立的 IP 地址

节点2

节点1

直接通信

Pod A
10.244.1.2

Pod B
10.244.1.3

Pod C
10.244.2.2

Pod D
10.244.2.3

Service
10.96.0.1

Ingress
外部域名

9.2 常用 CNI 插件对比

CNI 插件性能特性适用场景
Calico网络策略丰富,支持 eBPF生产环境首选
Flannel简单易用,功能基础学习/小规模
Cilium极高eBPF 驱动,安全能力强高性能/安全敏感
Weave加密通信,易部署跨云/混合云
AntreaVMware 支持,集成 NSX虚拟化环境

9.3 NetworkPolicy(网络策略)

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8
    ports:
    - protocol: TCP
      port: 3306

9.4 Ingress 完整配置

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - api.myapp.com
    - www.myapp.com
    secretName: myapp-tls
  rules:
  - host: api.myapp.com
    http:
      paths:
      - path: /v1(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: myapp-v1-service
            port:
              number: 80
      - path: /v2(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: myapp-v2-service
            port:
              number: 80
  - host: www.myapp.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-service
            port:
              number: 80

10. 配置管理 ConfigMap/Secret

10.1 ConfigMap

# 方式 1:从字面量创建
kubectl create configmap app-config --from-literal=ENV=production --from-literal=LOG_LEVEL=info

# 方式 2:从文件创建
kubectl create configmap app-config --from-file=config.ini

# 方式 3:声明式定义
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  ENV: production
  LOG_LEVEL: info
  app.properties: |
    database.url=jdbc:mysql://mysql:3306/app
    cache.ttl=300

---
# Pod 中使用 ConfigMap
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: app
    image: myapp
    env:
    - name: ENV
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: ENV
    volumeMounts:
    - name: config
      mountPath: /etc/config
  volumes:
  - name: config
    configMap:
      name: app-config

10.2 Secret

# 创建 Secret(base64 编码)
kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password=P@ssw0rd

# 从文件创建
kubectl create secret tls my-tls --cert=cert.pem --key=key.pem

# 声明式定义(值需要 base64 编码)
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque  # Opaque | kubernetes.io/tls | kubernetes.io/dockerconfigjson
data:
  username: YWRtaW4=
  password: UEBzc3cwcmQ=

---
# Pod 中使用 Secret
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: app
    env:
    - name: DB_USER
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: username
    - name: DB_PASS
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password
  imagePullSecrets:
  - name: dockerhub-secret  # 从私有仓库拉取镜像

10.3 敏感信息加密(Sealed Secrets / Vault)

# 使用 kubeseal 加密 Secret
kubeseal --format yaml < secret.yaml > sealed-secret.yaml

# 部署后,Sealed Secrets Controller 会自动解密
kubectl apply -f sealed-secret.yaml

11. Helm 包管理

11.1 Helm 核心概念

Chart
(模板包)

Release
(运行实例)

values.yaml
(环境配置)

Templates
(K8s YAML 模板)

Repository
(仓库)

11.2 Helm 常用命令

# 安装 Helm
# macOS: brew install helm
# Windows: choco install helm

# 添加仓库
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 nginx
helm search hub nginx

# 安装 Chart
helm install my-nginx bitnami/nginx
helm install my-redis bitnami/redis --set auth.password=myPassword

# 查看已安装 Release
helm list
helm list -n my-ns

# 升级 Release
helm upgrade my-nginx bitnami/nginx --set service.type=LoadBalancer

# 回滚 Release
helm history my-nginx
helm rollback my-nginx 1

# 卸载 Release
helm uninstall my-nginx

# 创建自己的 Chart
helm create myapp-chart

# 验证 Chart
helm lint myapp-chart

# 渲染模板(调试)
helm template myapp-chart --set image.tag=v2

# 查看默认值
helm show values bitnami/nginx

11.3 Chart 目录结构

myapp-chart/
├── Chart.yaml              # Chart 元数据
├── values.yaml             # 默认配置
├── charts/                 # 依赖的子 Chart
├── templates/              # K8s YAML 模板
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── configmap.yaml
│   ├── _helpers.tpl        # 模板辅助函数
│   └── NOTES.txt           # 安装后提示信息
└── .helmignore             # 忽略文件

11.4 模板语法示例

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  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 }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: {{ .Values.service.port }}
        env:
        - name: ENVIRONMENT
          value: {{ .Values.environment | default "production" }}
        resources:
          {{- toYaml .Values.resources | nindent 10 }}
# values.yaml
replicaCount: 3

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

service:
  type: ClusterIP
  port: 8080

environment: production

resources:
  requests:
    memory: "64Mi"
    cpu: "100m"
  limits:
    memory: "128Mi"
    cpu: "200m"

12. CI/CD 与 GitOps

12.1 GitOps 工作流

开发提交代码
(git push)

CI 流水线
(构建镜像)

镜像仓库
(ACR/Docker Hub)

更新部署配置
(git push YAML)

Git 仓库
(YAML 文件)

ArgoCD
(持续同步)

Kubernetes 集群

12.2 GitHub Actions 示例

# .github/workflows/deploy.yml
name: Deploy to Kubernetes

on:
  push:
    branches: [main]
    paths:
      - 'src/**'
      - 'k8s/**'

env:
  REGISTRY: your-registry.aliyuncs.com
  IMAGE_NAME: myapp

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v2

    - name: Log in to Container Registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ secrets.REGISTRY_USERNAME }}
        password: ${{ secrets.REGISTRY_PASSWORD }}

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}

    - name: Update deployment image tag
      run: |
        sed -i "s|image:.*|image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}|" k8s/deployment.yaml

    - name: Deploy to Kubernetes
      uses: azure/setup-kubectl@v3
      with:
        version: 'latest'
    - name: Deploy to Kubernetes
      run: |
        kubectl apply -f k8s/ -n production
        kubectl rollout status deployment/myapp -n production

12.3 ArgoCD 配置

# application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/yourname/myapp-k8s-config
    targetRevision: main
    path: overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true
# 安装 ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 获取初始密码
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

# 端口转发访问 UI
kubectl port-forward svc/argocd-server -n argocd 8443:443

# 创建应用
kubectl apply -f application.yaml

13. 监控与日志

13.1 监控架构(Prometheus + Grafana)

采集指标

存储

查询

告警

通知

通知

通知

系统指标

K8s 指标

容器指标

Kubernetes 集群

Prometheus

TSDB
(时序数据库)

Grafana
(可视化)

AlertManager
(告警管理)

邮件

钉钉/微信

Webhook

Node Exporter

kube-state-metrics

cAdvisor

13.2 安装 Prometheus Stack

# 添加仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# 安装 kube-prometheus-stack
helm install prometheus prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace \
  --set grafana.adminPassword=admin \
  --set prometheus.prometheusSpec.retention=15d

13.3 日志采集(EFK Stack)

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

13.4 常用监控命令

# 查看节点资源使用
kubectl top nodes
kubectl top nodes --sort-by=cpu
kubectl top nodes --sort-by=memory

# 查看 Pod 资源使用
kubectl top pods
kubectl top pods -n kube-system
kubectl top pods --sort-by=cpu

# 查看集群事件
kubectl get events --sort-by='.lastTimestamp' | tail -20
kubectl get events -n kube-system --field-selector type=Warning

# 使用 PromQL 查询(需要安装 Prometheus)
# 查询 CPU 使用率
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# 查询内存使用率
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100

14. 常见故障排查

14.1 Pod 状态速查表

状态含义常见原因排查方法
Pending调度中资源不足、节点选择器不匹配kubectl describe pod 查看事件
ContainerCreating创建中镜像拉取中、存储挂载中检查网络和存储配置
Running正常运行--
CrashLoopBackOff反复重启应用启动失败、健康检查失败kubectl logs 查看日志
ImagePullBackOff镜像拉取失败镜像不存在、认证失败、网络问题kubectl describe pod 查看错误
ErrImagePull镜像拉取错误同上同上
Failed失败应用退出kubectl logs 查看退出原因
Unknown未知节点失联kubectl get nodes 检查节点状态

14.2 常见问题排查流程图

Pending

资源不足

节点选择器不匹配

ImagePullBackOff

CrashLoopBackOff

应用启动失败

健康检查失败

内存超出

Pod 状态异常

是什么状态?

kubectl describe pod

事件显示?

增加节点或减少资源请求

修改节点标签或 Pod 调度策略

检查镜像名称是否正确

镜像是否存在?

构建并推送镜像

是否需要认证?

创建 imagePullSecret

检查网络/镜像源配置

kubectl logs

应用日志显示?

修复应用启动逻辑

调整探针参数

增加 memory limits

14.3 调试命令大全

# ========== Pod 调试 ==========
# 查看 Pod 详细信息
kubectl describe pod my-pod

# 查看 Pod 日志
kubectl logs my-pod
kubectl logs my-pod -c container-name
kubectl logs my-pod --previous    # 查看上一次崩溃的日志

# 进入 Pod 内部
kubectl exec -it my-pod -- /bin/sh
kubectl exec -it my-pod -- /bin/bash

# 在 Pod 中执行命令
kubectl exec my-pod -- curl -s http://localhost:8080/health

# 端口转发调试
kubectl port-forward pod/my-pod 8080:80

# ========== Service 调试 ==========
# 查看 Service 详情
kubectl describe svc my-service

# 检查 Service 是否关联到 Pod
kubectl get endpoints my-service

# 测试 Service 连通性
kubectl run test --image=busybox -it --rm -- wget -O- http://my-service

# ========== 网络调试 ==========
# 在集群内部执行 DNS 查询
kubectl run dns-test --image=busybox -it --rm -- nslookup kubernetes.default.svc.cluster.local

# 查看网络策略
kubectl get networkpolicies
kubectl describe networkpolicy my-policy

# ========== 存储调试 ==========
# 查看 PVC 状态
kubectl get pvc
kubectl describe pvc my-pvc

# 查看 PV 状态
kubectl get pv
kubectl describe pv my-pv

# ========== 节点调试 ==========
# 查看节点状态
kubectl get nodes
kubectl describe node node-1

# 查看节点上的 Pod
kubectl get pods --field-selector spec.nodeName=node-1

# 标记节点不可调度(维护模式)
kubectl cordon node-1
# 恢复调度
kubectl uncordon node-1

# 驱逐节点上的 Pod
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data

# ========== 集群调试 ==========
# 查看集群信息
kubectl cluster-info
kubectl cluster-info dump

# 查看 API Server 日志
kubectl logs -n kube-system kube-apiserver-$(hostname)

# 查看所有命名空间的事件
kubectl get events --all-namespaces --sort-by='.lastTimestamp'

# 查看资源使用情况
kubectl top nodes
kubectl top pods

14.4 常见错误与解决方案

错误原因解决方案
ImagePullBackOff镜像拉取失败检查镜像名、标签、认证、网络
CrashLoopBackOff容器反复崩溃查看日志,检查启动命令、健康检查
Pending (no nodes available)资源不足增加节点或减少资源请求
FailedMount存储挂载失败检查 PV/PVC 状态,查看存储服务
Readiness probe failed就绪检查失败检查应用端口、路径,调整探针参数
Liveness probe failed存活检查失败同上,或应用性能问题
context deadline exceededAPI Server 超时检查网络连接,增加 kubelet 超时时间
port already allocated端口冲突修改 NodePort 或检查端口占用
No such file or directory挂载路径错误检查 volumeMounts 配置

15. 生产环境最佳实践

15.1 资源配额(ResourceQuota)

# 命名空间级别资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
  name: namespace-quota
spec:
  hard:
    limits.cpu: "20"
    limits.memory: 20Gi
    requests.cpu: "10"
    requests.memory: 10Gi
    persistentvolumeclaims: "10"
    pods: "50"
    services: "20"
    services.nodeports: "5"
    count/deployments.apps: "10"

15.2 限制范围(LimitRange)

apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
spec:
  limits:
  - default:
      cpu: 200m
      memory: 256Mi
    defaultRequest:
      cpu: 100m
      memory: 128Mi
    max:
      cpu: 2
      memory: 2Gi
    min:
      cpu: 50m
      memory: 64Mi
    type: Container

15.3 Pod 安全策略(PodSecurityContext)

apiVersion: v1
kind: Pod
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
        - ALL
      readOnlyRootFilesystem: true

15.4 PodDisruptionBudget(保证服务可用性)

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: myapp-pdb
spec:
  minAvailable: 2            # 最少可用 Pod 数
  # maxUnavailable: 1        # 最大不可用 Pod 数(与 minAvailable 二选一)
  selector:
    matchLabels:
      app: myapp

15.5 节点维护流程

# 1. 标记节点不可调度(阻止新 Pod 调度)
kubectl cordon node-1

# 2. 驱逐节点上的 Pod(DaemonSet 不会被驱逐)
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data

# 3. 维护节点(重启、升级等)

# 4. 恢复节点调度
kubectl uncordon node-1

15.6 生产环境检查清单

检查项说明
✅ 所有容器设置 resources.requests/limits避免资源竞争
✅ 配置 livenessProbe/readinessProbe确保服务健康
✅ 使用 PodDisruptionBudget保证维护期间服务可用
✅ 设置 revisionHistoryLimit控制历史版本数量
✅ 使用 私有镜像仓库 + imagePullSecret安全拉取镜像
✅ 敏感信息使用 Secret(非 ConfigMap)保护敏感数据
✅ 启用 RBAC 权限控制最小权限原则
✅ 配置 NetworkPolicy网络隔离
✅ 启用 PodSecurityPolicy/PodSecurityContext安全加固
✅ 定期备份 etcd灾难恢复
✅ 配置 日志收集监控告警可观测性
✅ 使用 Ingress 暴露服务(非 NodePort)统一入口管理
✅ 开启 自动伸缩(HPA)弹性应对流量
✅ 使用 Helm 管理应用版本控制和环境管理
✅ 实施 GitOps 流程声明式交付
✅ 节点 定期更新/打补丁安全合规
✅ 使用 readOnlyRootFilesystem提高安全性

📚 推荐学习资源

资源链接说明
官方文档https://kubernetes.io/docs/最权威的参考
Play with K8shttps://labs.play-with-k8s.com/在线免费实验环境
Killercodahttps://killercoda.com/交互式 K8s 教程
K8s 练习https://k8s-exercises.com/实战练习题
Kubernetes Patternshttps://kubernetespatterns.com/设计模式
Awesome K8shttps://github.com/ramitsurana/awesome-kubernetes资源合集

最后的话:Kubernetes 是一个庞大的生态系统,没有人能记住所有细节。重要的是理解核心概念和架构,掌握 kubectl 常用命令,学会查看文档和排查问题。实践是最好的学习方式——从本地 Minikube 开始,逐步过渡到生产集群,每一次踩坑都是成长。希望这份指南能成为你 K8s 学习路上的一个可靠参考。🚀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值