目录

 文件结构

1-基础环境搭建(都要做)

1.1-个人环境信息

1.2-配置环境

2-基础 Pod 操作(仅master)

2.1-创建最小 BusyBox Pod

创建最小 BusyBox Pod

 部署并验证

2.2-Pod 滚动更新与镜像拉取策略

创建带版本标签的 Pod-v1

部署并测试镜像拉取策略

创建pod-2(可以不删除,用于后续做实验)

问题处理(跳过)

3-Deployment 与 Service

3.1 部署 Nginx Deployment(3副本)

创建 Deployment

部署并验证

3.2-创建 ClusterIP Service(内部访问)

创建 ClusterIP Service

测试 ClusterIP

3.3-创建 NodePort Service(外部访问)

创建 NodePort Service

测试 NodePort

4-ConfigMap / Secret / Volume

4.1-ConfigMap 注入环境变量

创建 ConfigMap

使用 ConfigMap

4.2-Secret 注入敏感信息

创建 Secret

使用 Secret

4.3-Volume 持久化

emptyDir(临时存储)

hostPath(宿主机路径)

5-Ingress 与负载均衡

5.1-安装 NGINX Ingress Controller

安装 Ingress Controller

5.2-部署两个应用并配置 Ingress

部署 App1(蓝色)

部署 App2(绿色)

创建 Ingress 规则

测试 Ingress

5.3-配置 TLS 证书

生成自签名证书

更新 Ingress 添加 TLS

6-多容器 Pod 与探针

6.1-Sidecar 模式(日志收集)

创建带 Sidecar 的 Pod

6.2-健康检查探针

Liveness Probe(存活探针)

Readiness Probe(就绪探针)

Startup Probe(启动探针)

7-自动扩缩容与资源管理

7.1-资源请求与限制

7.2-安装 Metrics Server

7.3-Horizontal Pod Autoscaler (HPA)

部署测试应用

创建 HPA

负载测试

8-网络策略与安全

8.1-创建测试环境

8.2-配置网络策略

策略1: 拒绝所有入站流量

策略2:仅允许 backend 访问 database

策略3:限制 Pod 级别访问

9-CI/CD & Helm

9.1-安装 Helm

9.2-创建自定义 Helm Chart

9.3-部署和管理

9.4-Kubectl Rollout 管理

总结与清理


 文件结构

k8s-practice/
├── 01-basic-pods
│   ├── busybox-pod.yaml
│   ├── nginx-pod-v1.yaml
│   └── nginx-pod-v2.yaml
├── 02-deployments-service
│   ├── nginx-deployment.yaml
│   ├── nginx-service-clusterip.yaml
│   └── nginx-service-nodeport.yaml
├── 03-configmaps-secrets-volume
│   ├── configmap.yaml
│   ├── pod-emptydir.yaml
│   ├── pod-hostpath.yaml
│   ├── pod-with-configmap.yaml
│   ├── pod-with-secret.yaml
│   └── secret.yaml
├── 04-ingress
│   ├── app1
│   │   └── app1-deployment.yaml
│   ├── app2
│   │   └── app2-deployment.yaml
│   ├── ingress-rules.yaml
│   ├── ingress-tls.yaml
│   ├── tls.crt
│   └── tls.key
├── 05-pods-probes
│   ├── deployment-readiness.yaml
│   ├── pod-liveness.yaml
│   ├── pod-sidecar.yaml
│   └── pod-startup.yaml
├── 06-AS-resource-management
│   ├── deployment-resources.yaml
│   ├── hpa.yaml
│   └── php-apache.yaml
├── 07-ENV-test
│   ├── allow-backend-to-db.yaml
│   ├── backend-policy.yaml
│   └── deny-all-ingress.yaml
└── 08-helm
    ├── custom-values.yaml
    └── myapp
        ├── charts
        ├── Chart.yaml
        ├── templates
        │   ├── deployment.yaml
        │   ├── _helpers.tpl
        │   ├── hpa.yaml
        │   ├── httproute.yaml
        │   ├── ingress.yaml
        │   ├── NOTES.txt
        │   ├── serviceaccount.yaml
        │   ├── service.yaml
        │   └── tests
        │       └── test-connection.yaml
        └── values.yaml

mkdir -p k8s-practice/{01-basic-pods,02-deployments-service,03-configmaps-secrets-volume,04-ingress/{app1,app2},05-pods-probes,06-AS-resource-management,07-ENV-test,08-helm/myapp}

1-基础环境搭建(都要做)

1.1-个人环境信息

  • Master: 192.168.132.100

  • Node: 192.168.132.101

  • Pod CIDR: 10.244.0.0/16

  • Service CIDR: 10.96.0.0/12

  • K8s Version: 1.34.1

修改containerd的镜像仓库为官方镜像仓库

# registry.k8s.io(Kubernetes 官方镜像仓库)
mkdir -p /etc/containerd/certs.d/registry.k8s.io
tee /etc/containerd/certs.d/registry.k8s.io/hosts.toml >/dev/null <<'EOM'
server = "https://registry.k8s.io"
EOM

# docker.io(Docker Hub 官方域名建议使用 registry-1.docker.io)
mkdir -p /etc/containerd/certs.d/docker.io
tee /etc/containerd/certs.d/docker.io/hosts.toml >/dev/null <<'EOM'
server = "https://registry-1.docker.io"
EOM

# quay.io(若使用)
mkdir -p /etc/containerd/certs.d/quay.io
tee /etc/containerd/certs.d/quay.io/hosts.toml >/dev/null <<'EOM'
server = "https://quay.io"
EOM

# 确认 containerd 使用官方 pause(前文已设置为 registry.k8s.io/pause:3.10)
sed -ri 's#^\s*sandbox_image = ".*"#  sandbox_image = "registry.k8s.io/pause:3.10"#' /etc/containerd/config.toml

systemctl restart containerd

生成默认/etc/containerd/config.toml文件用于修改

containerd config default > /etc/containerd/config.toml
vim /etc/containerd/config.toml
  # 添加以下行
  [plugins."io.containerd.grpc.v1.cri".registry]
    config_path = "/etc/containerd/certs.d"

      [plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
        base_runtime_spec = ""
  
      [plugins."io.containerd.grpc.v1.cri".dns]
        servers = ["8.8.8.8", "1.1.1.1"]

1.2-配置环境

windows上(这里使用的是cv)

  • 在windows上ipconfig查询IP(192.168.132.1),和虚拟机网段相同(我的虚拟机网关为192.168.132.2)
  • 然后打开cv软件--->设置--->找到配置目录--->修改文件配置为如下(需要打开本地文件进行修改):
mixed-port: 7897
allow-lan: true
log-level: info
external-controller: 0.0.0.0:9097

    在 systemd 为 containerd 添加完整的 proxy/no_proxy

    内容如下(用你主机的真实 IP 替换):

    sudo mkdir -p /etc/systemd/system/containerd.service.d
    
    sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf > /dev/null <<'EOF'
    [Service]
    Environment="HTTP_PROXY=http://192.168.132.1:7897"
    Environment="HTTPS_PROXY=http://192.168.132.1:7897"
    Environment="NO_PROXY=127.0.0.1,localhost,10.96.0.1,10.96.0.0/12,.svc,.cluster.local,192.168.132.0/24,192.168.132.100,192.168.132.101"
    EOF
    

    同样为 kubelet(必须)添加 NO_PROXY(kubelet 也会调用 CNI)

    sudo mkdir -p /etc/systemd/system/kubelet.service.d
    
    sudo tee /etc/systemd/system/kubelet.service.d/http-proxy.conf > /dev/null <<'EOF'
    [Service]
    Environment="HTTP_PROXY=http://192.168.132.1:7897"
    Environment="HTTPS_PROXY=http://192.168.132.1:7897"
    Environment="NO_PROXY=127.0.0.1,localhost,10.96.0.1,10.96.0.0/12,.svc,.cluster.local,192.168.132.0/24,192.168.132.100,192.168.132.101"
    EOF
    

    验证crictl代理是否完成

    # 重新加载 systemd 并重启服务
    systemctl daemon-reexec
    systemctl daemon-reload
    systemctl restart containerd
    systemctl restart kubelet
    

    重启 / 重建 Calico daemonset 的 pods(让 calico-node 重新尝试)

    kubectl -n calico-system delete pod -l k8s-app=calico-node
    kubectl -n calico-system get pods
    
    # 期望输出:Connection to 192.168.132.1 7897 port [tcp/*] succeeded!
    nc -vz 192.168.132.1 7897
    
    # 如果返回 HTTP/1.1 200 OK 或 HTTP/2 200,就说明代理已成功。
    curl -x http://192.168.132.1:7897 https://www.google.com -I
    
    crictl pull docker.io/library/busybox:1.36
    

    2-基础 Pod 操作(仅master)

    2.1-创建最小 BusyBox Pod

    代码解析

    • apiVersion: v1: 使用核心 API 组
    • kind: Pod: 资源类型为 Pod
    • metadata: 元数据,包含名称和标签
    • spec.containers: 容器定义
    • command: 覆盖镜像默认命令
    • resources: 资源限制,防止资源耗尽

    创建最小 BusyBox Pod

    mkdir -p ~/k8s-practice/01-basic-pods && cd ~/k8s-practice/01-basic-pods
    cat > busybox-pod.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: busybox-test
      labels:
        app: busybox
    spec:
      containers:
      - name: busybox
        image: busybox:1.36
        command: ['sh', '-c', 'echo "Hello Kubernetes!" && sleep 3600']
        resources:
          requests:
            memory: "64Mi"
            cpu: "100m"
          limits:
            memory: "128Mi"
            cpu: "200m"
    EOF
    
    # 创建 Pod
    kubectl apply -f busybox-pod.yaml
    
    1. 如果 image 标签带有 :latest
      默认拉取策略是 Always,即每次都会尝试从远程仓库拉取镜像。

    2. 如果 image 标签不是 :latest(比如 busybox:1.36)
      默认拉取策略是 IfNotPresent,即本地有就用本地的,没有才去远程仓库拉取

    3. 确保node节点上有镜像而不是master上有镜像(master节点不运行业务)

     部署并验证

    # 查看 Pod 状态
    kubectl get pods
    kubectl get pods -w  # 实时监控pod创建
    kubectl get pods -o wide  # 查看详细信息(IP、节点等)
    
    # 查看 Pod 详细描述(常用,用于观察pod创建过程中产生的Events)
    kubectl describe pod busybox-test
    

    # 查看 Pod 日志(输出:Hello Kubernetes!)
    kubectl logs busybox-test
    
    # 进入 Pod 执行命令(测试pod)
    # kubectl exec -it busybox-test -- sh
    # 在容器内执行:ping -c 3 www.baidu.com
    kubectl exec busybox-test -- ping -c 3 www.baidu.com
    

    # 删除 Pod
    kubectl delete pod busybox-test
    
    # 强制删除 pod
    kubectl delete pod busybox-test --grace-period=0 --force
    
    # 另一种方式删除资源(删除文件构建产生的资源)
    kubectl  delete -f busybox-pod.yaml
    

    2.2-Pod 滚动更新与镜像拉取策略

    创建带版本标签的 Pod-v1

    mkdir -p ~/k8s-practice/01-basic-pods && cd ~/k8s-practice/01-basic-pods
    cat > nginx-pod-v1.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-app-1
      labels:
        app: nginx
        version: v1
    spec:
      containers:
      - name: nginx
        image: nginx:1.23-alpine
        imagePullPolicy: IfNotPresent  # 如果本地有则不拉取
        ports:
        - containerPort: 80
          name: http
    EOF
    
    # 部署 v1
    kubectl apply -f nginx-pod-v1.yaml
    

    部署并测试镜像拉取策略

    # 查看pod
    kubectl get pods
    kubectl describe pod nginx-app-1 | sed -n '/Events/,$p'
    
    # 通过标签查询pod
    kubectl get pods -l app=nginx
    

    # 查看当前镜像版本(输出:nginx:1.23-alpine)
    kubectl get pod nginx-app-1 -o jsonpath='{.spec.containers[0].image}'
    
    # 更新镜像(Pod 需要删除重建)
    kubectl delete pod nginx-app-1
    

    创建pod-2(可以不删除,用于后续做实验)

    cat > nginx-pod-v2.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: nginx-app-2
      labels:
        app: nginx
        version: v2
    spec:
      containers:
      - name: nginx
        image: nginx:1.24-alpine
        imagePullPolicy: Always  # 总是拉取最新镜像
        ports:
        - containerPort: 80
    EOF
    
    kubectl apply -f nginx-pod-v2.yaml
    kubectl get pods -w
    
    # 查看pod
    kubectl describe pod nginx-app-2 | sed -n '/Events/,$p'
    
    # 查看当前镜像版本(输出:nginx:1.24-alpine)
    kubectl get pod nginx-app-2 -o jsonpath='{.spec.containers[0].image}'
    

    镜像拉取策略说明

    • Always: 每次都从仓库拉取
    • IfNotPresent: 本地有则使用本地
    • Never: 只使用本地镜像

    问题处理(跳过)

    直接kubectl apply -f busybox-pod.yaml无法直接创建busybox-pod,下面是解决方法

    • 说明:你之前修改的 calico-cni-plugin ClusterRole 被 operator 管理并可能回写覆盖。为避免 operator 干预,我们创建一个额外的、独立的 ClusterRole + ClusterRoleBinding(名字不同),单独授权 projectcalico.org group 的 clusterinformations 给该 SA。这样即便 operator 回写原角色,你仍然有权限。
    # 为 calico-cni-plugin 旁路授权(不受 operator 回写影响)
    cat <<'EOF' | kubectl apply -f -
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: calico-cni-plugin-extra
    rules:
    - apiGroups: ["projectcalico.org"]
      resources:
      - clusterinformations
      verbs: ["get","list","watch"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: calico-cni-plugin-extra-binding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: calico-cni-plugin-extra
    subjects:
    - kind: ServiceAccount
      name: calico-cni-plugin
      namespace: calico-system
    EOF
    
    

    重启 calico-node 并验证

    # 删除 calico-node pods 让其重建(不涉及 operator 对 extra role):
    kubectl -n calico-system delete pod -l k8s-app=calico-node
    kubectl -n calico-system get pods -w   # 等它们都 Running
    

    再次用节点上的 kubeconfig 验证:

    KUBECONFIG=/etc/cni/net.d/calico-kubeconfig kubectl get clusterinformations default -o yaml
    

    最后重新启动/创建测试 Pod:

    kubectl delete pod busybox-test --ignore-not-found
    kubectl run busybox-test --image=busybox:1.36 -- sh -c "echo Hello && sleep 3600"
    kubectl get pods -o wide
    

    3-Deployment 与 Service

    3.1 部署 Nginx Deployment(3副本)

    创建 Deployment

    mkdir -p ~/k8s-practice/02-deployments-service && cd ~/k8s-practice/02-deployments-service
    cat > nginx-deployment.yaml <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 3  # 3个副本
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.24-alpine
            ports:
            - containerPort: 80
            resources:
              requests:
                memory: "128Mi"
                cpu: "100m"
              limits:
                memory: "256Mi"
                cpu: "200m"
            livenessProbe:
              httpGet:
                path: /
                port: 80
              initialDelaySeconds: 10
              periodSeconds: 5
            readinessProbe:
              httpGet:
                path: /
                port: 80
              initialDelaySeconds: 5
              periodSeconds: 3
    EOF
    
    # 创建 Deployment
    kubectl apply -f nginx-deployment.yaml
    

    部署并验证

    # 查看 Deployment
    kubectl get deployment
    kubectl get deployment nginx-deployment -o wide
    

    # 查看 ReplicaSet
    kubectl get rs
    
    # 查看 Pods(应该有3个)
    kubectl get pods -l app=nginx -o wide
    

    # 查看某个 Pod 详情
    kubectl describe pod nginx-deployment-5d8b9dbdd4-7r4h6
    
    # 测试自愈能力:删除一个 Pod
    kubectl delete pod nginx-deployment-5d8b9dbdd4-7r4h6
    kubectl get pods -l app=nginx  # 会自动创建新的 Pod
    

    ​# 删除deployments
    kubectl delete deployments nginx-deployment
    kubectl delete -f nginx-deployment.yaml
    

    3.2-创建 ClusterIP Service(内部访问)

    创建 ClusterIP Service

    
    cat > nginx-service-clusterip.yaml <<EOF
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      type: ClusterIP  # 默认类型,仅集群内访问
      selector:
        app: nginx  # 选择标签为 app=nginx 的 Pod
      ports:
      - protocol: TCP
        port: 80        # Service 端口
        targetPort: 80  # Pod 端口
    EOF
    
    # 创建 Service
    kubectl apply -f nginx-service-clusterip.yaml
    

    测试 ClusterIP

    # 查看 Service
    kubectl get svc nginx-service
    kubectl describe svc nginx-service
    
    # 查看 Endpoints(关联的 Pod IP)
    kubectl get endpoints nginx-service
    
    # 从集群内测试(创建临时 Pod)
    kubectl run test-client --rm -it --image=busybox:1.36 -- sh
    # 在容器内执行:
    wget -qO- http://nginx-service
    wget -qO- http://nginx-service.default.svc.cluster.local
    exit
    

    # 删除 nginx-service
    kubectl delete -f nginx-service-clusterip.yaml
    

    3.3-创建 NodePort Service(外部访问)

    创建 NodePort Service

    cat > nginx-service-nodeport.yaml <<EOF
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-nodeport
    spec:
      type: NodePort
      selector:
        app: nginx
      ports:
      - protocol: TCP
        port: 80
        targetPort: 80
        nodePort: 30080  # 指定 NodePort(范围:30000-32767)
    EOF
    
    # 创建 NodePort Service
    kubectl apply -f nginx-service-nodeport.yaml
    

    测试 NodePort

    # 查看 Service
    kubectl get svc nginx-nodeport
    kubectl get endpoints nginx-nodeport
    

    # 从宿主机访问(任意节点 IP)
    curl http://192.168.132.100:30080
    curl http://192.168.132.101:30080
    
    # 如果失败,检查防火墙
    sudo iptables -L -n | grep 30080
    
    # 删除资源
    kubectl delete -f nginx-service-nodeport.yaml
    

    Service 类型对比

    • ClusterIP: 仅集群内访问,默认类型

    • NodePort: 通过节点 IP:Port 访问,端口范围 30000-32767

    • LoadBalancer: 云环境下使用外部负载均衡器

    4-ConfigMap / Secret / Volume

    4.1-ConfigMap 注入环境变量

    创建 ConfigMap

    # 命令行创建 app-config
    kubectl create configmap app-config \
      --from-literal=APP_ENV=production \
      --from-literal=APP_DEBUG=false \
      --from-literal=DB_HOST=mysql.default.svc.cluster.local
    

    # YAML 文件创建 app-config-file
    cat > configmap.yaml <<EOF
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: app-config-file
    data:
      # 键值对形式
      app.env: "production"
      log.level: "info"
      # 文件内容形式
      nginx.conf: |
        server {
          listen 80;
          server_name localhost;
          location / {
            root /usr/share/nginx/html;
            index index.html;
          }
        }
    EOF
    
    kubectl apply -f configmap.yaml
    
    # 查看 ConfigMap
    kubectl get configmap
    kubectl describe configmap app-config-file
    kubectl get configmap app-config-file -o yaml
    

    使用 ConfigMap

    cat > pod-with-configmap.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: app-with-config
    spec:
      containers:
      - name: app
        image: busybox:1.36
        command: ['sh', '-c', 'echo "ENV: \$APP_ENV, DEBUG: \$APP_DEBUG, DB: \$DB_HOST" && sleep 3600']
        # 方式1:将 ConfigMap 所有键作为环境变量
        envFrom:
        - configMapRef:
            name: app-config
        # 方式2:选择特定键作为环境变量
        env:
        - name: LOG_LEVEL
          valueFrom:
            configMapKeyRef:
              name: app-config-file
              key: log.level
        # 方式3:挂载为文件
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
      volumes:
      - name: config-volume
        configMap:
          name: app-config-file
          items:
          - key: nginx.conf
            path: nginx.conf
    EOF
    
    kubectl apply -f pod-with-configmap.yaml
    
    # 验证
    kubectl logs app-with-config
    kubectl exec app-with-config -- cat /etc/config/nginx.conf
    

    4.2-Secret 注入敏感信息

    创建 Secret

    # 方法1:命令行创建 db-secret
    kubectl create secret generic db-secret \
      --from-literal=username=admin \
      --from-literal=password=MyP@ssw0rd123
    

    # 方法2:YAML 创建(需 base64 编码)
    echo -n 'admin' | base64      # YWRtaW4=
    echo -n 'MyP@ssw0rd123' | base64  # TXlQQHNzdzByZDEyMw==
    
    cat > secret.yaml <<EOF
    apiVersion: v1
    kind: Secret
    metadata:
      name: db-secret-yaml
    type: Opaque
    data:
      username: YWRtaW4=
      password: TXlQQHNzdzByZDEyMw==
    EOF
    
    kubectl apply -f secret.yaml
    
    # 查看 Secret(data 不会直接显示)
    kubectl get secret
    kubectl describe secret db-secret
    kubectl describe secret db-secret-yaml
    

    使用 Secret

    cat > pod-with-secret.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: app-with-secret
    spec:
      containers:
      - name: app
        image: busybox:1.36
        command: ['sh', '-c', 'echo "User: \$DB_USER, Pass: \$DB_PASS" && sleep 3600']
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: password
        # 挂载为文件
        volumeMounts:
        - name: secret-volume
          mountPath: /etc/secret
          readOnly: true
      volumes:
      - name: secret-volume
        secret:
          secretName: db-secret
    EOF
    
    kubectl apply -f pod-with-secret.yaml
    
    # 验证
    kubectl logs app-with-secret
    kubectl exec app-with-secret -- ls /etc/secret
    kubectl exec app-with-secret -- cat /etc/secret/username
    

    4.3-Volume 持久化

    emptyDir(临时存储)

    cat > pod-emptydir.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-emptydir
    spec:
      containers:
      - name: writer
        image: busybox:1.36
        command: ['sh', '-c', 'while true; do echo $(date) >> /data/log.txt; sleep 5; done']
        volumeMounts:
        - name: shared-data
          mountPath: /data
      - name: reader
        image: busybox:1.36
        command: ['sh', '-c', 'tail -f /data/log.txt']
        volumeMounts:
        - name: shared-data
          mountPath: /data
      volumes:
      - name: shared-data
        emptyDir: {}  # Pod 删除后数据丢失
    EOF
    
    kubectl apply -f pod-emptydir.yaml
    
    # 查看日志
    kubectl logs pod-emptydir -c writer
    kubectl logs pod-emptydir -c reader
    

    hostPath(宿主机路径)

    注意:这里的192.168.132.101的主机名为k8s-node1(在写yaml的时候要注意)

    # 在 node 节点上创建目录
    ssh root@192.168.132.101 "mkdir -p /data/k8s-host"
    
    cat > pod-hostpath.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-hostpath
    spec:
      nodeSelector:
        kubernetes.io/hostname: k8s-node1  # 指定运行在 node 节点
      containers:
      - name: nginx
        image: nginx:1.24-alpine
        volumeMounts:
        - name: host-data
          mountPath: /usr/share/nginx/html
      volumes:
      - name: host-data
        hostPath:
          path: /data/k8s-host
          type: DirectoryOrCreate
    EOF
    
    kubectl apply -f pod-hostpath.yaml
    
    # 在 node 节点创建测试文件
    ssh root@192.168.132.101 "echo '<h1>HostPath Test</h1>' > /data/k8s-host/index.html"
    
    # 验证
    kubectl exec pod-hostpath -- cat /usr/share/nginx/html/index.html
    

    # 删除资源
    kubectl delete -f pod-hostpath.yaml
    kubectl delete -f pod-emptydir.yaml
    kubectl delete -f pod-with-secret.yaml
    kubectl delete -f secret.yaml
    kubectl delete secret db-secret
    kubectl delete -f pod-with-configmap.yaml
    kubectl delete -f configmap.yaml
    kubectl delete configmap app-config
    

    5-Ingress 与负载均衡

    5.1-安装 NGINX Ingress Controller

    安装 Ingress Controller

    mkdir -p ~/k8s-practice/04-ingress/{app1,app2} && cd ~/k8s-practice/04-ingress/
    
    # 下载官方 YAML (由于官方yaml无法安装)
    # kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/baremetal/deploy.yaml
    
    kubectl apply -f https://fastly.jsdelivr.net/gh/kubernetes/ingress-nginx@controller-v1.8.1/deploy/static/provider/baremetal/deploy.yaml
    
    # 等待 Pod 就绪
    kubectl get pods -n ingress-nginx -w
    
    # 查看 Ingress Controller Service
    kubectl get svc -n ingress-nginx
    
    # 如果是 NodePort 类型,查看端口
    kubectl get svc ingress-nginx-controller -n ingress-nginx
    # 记录 HTTP 和 HTTPS 端口(例如:80:32419/TCP, 443:30232/TCP)
    

    5.2-部署两个应用并配置 Ingress

    部署 App1(蓝色)

    cd ~/k8s-practice/04-ingress/app1
    cat > app1-deployment.yaml <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: app1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: app1
      template:
        metadata:
          labels:
            app: app1
        spec:
          containers:
          - name: nginx
            image: nginx:1.24-alpine
            ports:
            - containerPort: 80
            volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
          volumes:
          - name: html
            configMap:
              name: app1-html
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: app1-service
    spec:
      selector:
        app: app1
      ports:
      - port: 80
        targetPort: 80
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: app1-html
    data:
      index.html: |
        <html>
        <body style="background-color: #3498db;">
          <h1>App1 - Blue Service</h1>
          <p>Path: /app1</p>
        </body>
        </html>
    EOF
    
    kubectl apply -f app1-deployment.yaml
    
    # 创建的资源查询
    kubectl get deployment app1
    kubectl get service app1-service
    kubectl get configmap app1-html
    

    部署 App2(绿色)

    cd ~/k8s-practice/04-ingress/app2
    cat > app2-deployment.yaml <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: app2
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: app2
      template:
        metadata:
          labels:
            app: app2
        spec:
          containers:
          - name: nginx
            image: nginx:1.24-alpine
            ports:
            - containerPort: 80
            volumeMounts:
            - name: html
              mountPath: /usr/share/nginx/html
          volumes:
          - name: html
            configMap:
              name: app2-html
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: app2-service
    spec:
      selector:
        app: app2
      ports:
      - port: 80
        targetPort: 80
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: app2-html
    data:
      index.html: |
        <html>
        <body style="background-color: #2ecc71;">
          <h1>App2 - Green Service</h1>
          <p>Path: /app2</p>
        </body>
        </html>
    EOF
    
    kubectl apply -f app2-deployment.yaml
    
    # 创建的资源查询
    kubectl get deployment app2
    kubectl get service app2-service
    kubectl get configmap app2-html
    

    创建 Ingress 规则

    cd ~/k8s-practice/04-ingress
    cat > ingress-rules.yaml <<EOF
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: multi-path-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      ingressClassName: nginx
      rules:
      - host: myapp.local  # 自定义域名
        http:
          paths:
          - path: /app1
            pathType: Prefix
            backend:
              service:
                name: app1-service
                port:
                  number: 80
          - path: /app2
            pathType: Prefix
            backend:
              service:
                name: app2-service
                port:
                  number: 80
    EOF
    
    kubectl apply -f ingress-rules.yaml
    
    # 查看 Ingress
    kubectl get ingress
    kubectl describe ingress multi-path-ingress
    

    测试 Ingress

    # 获取 Ingress Controller NodePort
    INGRESS_PORT=$(kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.ports[0].nodePort}')
    
    # 配置 hosts(在你的操作机器上)
    echo "192.168.132.100 myapp.local" | sudo tee -a /etc/hosts
    
    # 测试访问(在操作机器上)
    curl http://myapp.local:$INGRESS_PORT/app1
    curl http://myapp.local:$INGRESS_PORT/app2
    
    # 或在ubuntu中使用浏览器访问
    # http://myapp.local:32419/app1
    # http://myapp.local:32419/app2
    

    5.3-配置 TLS 证书

    生成自签名证书

    # 生成私钥和证书
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
      -keyout tls.key -out tls.crt \
      -subj "/CN=myapp.local/O=myapp"
    
    # 创建 Secret
    kubectl create secret tls myapp-tls --cert=tls.crt --key=tls.key
    
    # 查看 Secret
    kubectl get secret myapp-tls
    

    更新 Ingress 添加 TLS

    cat > ingress-tls.yaml <<EOF
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: multi-path-ingress
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - myapp.local
        secretName: myapp-tls
      rules:
      - host: myapp.local
        http:
          paths:
          - path: /app1
            pathType: Prefix
            backend:
              service:
                name: app1-service
                port:
                  number: 80
          - path: /app2
            pathType: Prefix
            backend:
              service:
                name: app2-service
                port:
                  number: 80
    EOF
    
    kubectl apply -f ingress-tls.yaml
    
    # 测试 HTTPS(忽略证书警告)
    INGRESS_HTTPS_PORT=$(kubectl get svc ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.ports[1].nodePort}')
    
    curl -k https://myapp.local:$INGRESS_HTTPS_PORT/app1
    

    # 清理资源
    kubectl delete -f ingress-tls.yaml
    kubectl delete secret myapp-tls
    kubectl delete -f app1/app1-deployment.yaml
    kubectl delete -f app2/app2-deployment.yaml
    

    6-多容器 Pod 与探针

    6.1-Sidecar 模式(日志收集)

    创建带 Sidecar 的 Pod

    mkdir -p ~/k8s-practice/05-pods-probes && cd ~/k8s-practice/05-pods-probes
    cat > pod-sidecar.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: app-with-sidecar
    spec:
      containers:
      # 主容器:生成日志
      - name: app
        image: busybox:1.36
        command: ['sh', '-c']
        args:
        - while true; do
            echo "$(date) - App log entry" >> /var/log/app.log;
            sleep 3;
          done
        volumeMounts:
        - name: log-volume
          mountPath: /var/log
      
      # Sidecar 容器:读取并处理日志
      - name: log-collector
        image: busybox:1.36
        command: ['sh', '-c']
        args:
        - tail -f /var/log/app.log | while read line; do
            echo "[COLLECTED] $line";
          done
        volumeMounts:
        - name: log-volume
          mountPath: /var/log
      
      volumes:
      - name: log-volume
        emptyDir: {}
    EOF
    
    kubectl apply -f pod-sidecar.yaml
    
    # 查看主容器日志
    kubectl logs app-with-sidecar -c app
    
    # 查看 Sidecar 日志
    kubectl logs app-with-sidecar -c log-collector -f
    

    6.2-健康检查探针

    Liveness Probe(存活探针)

    cat > pod-liveness.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-liveness-test
    spec:
      containers:
      - name: app
        image: busybox:1.36
        command: ['sh', '-c']
        args:
        - touch /tmp/healthy;
          sleep 30;
          rm -f /tmp/healthy;
          sleep 600
        livenessProbe:
          exec:
            command:
            - cat
            - /tmp/healthy
          initialDelaySeconds: 5  # 启动后5秒开始检查
          periodSeconds: 5        # 每5秒检查一次
          failureThreshold: 3     # 失败3次后重启
    EOF
    
    kubectl apply -f pod-liveness.yaml
    
    # 观察 Pod 状态(30秒后会重启)
    kubectl get pod pod-liveness-test -w
    
    # 查看事件
    kubectl describe pod pod-liveness-test
    

    Readiness Probe(就绪探针)

    cat > deployment-readiness.yaml <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: app-readiness
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: readiness-test
      template:
        metadata:
          labels:
            app: readiness-test
        spec:
          containers:
          - name: nginx
            image: nginx:1.24-alpine
            ports:
            - containerPort: 80
            readinessProbe:
              httpGet:
                path: /
                port: 80
              initialDelaySeconds: 5
              periodSeconds: 3
              successThreshold: 1  # 成功1次即标记为就绪
              failureThreshold: 2  # 失败2次标记为未就绪
            livenessProbe:
              httpGet:
                path: /
                port: 80
              initialDelaySeconds: 15
              periodSeconds: 10
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: readiness-service
    spec:
      selector:
        app: readiness-test
      ports:
      - port: 80
    EOF
    
    kubectl apply -f deployment-readiness.yaml
    
    # 查看 Pod 就绪状态
    kubectl get pods -l app=readiness-test
    
    # 查看 Service Endpoints(只包含就绪的 Pod)
    kubectl get endpoints readiness-service
    

    Startup Probe(启动探针)

    cat > pod-startup.yaml <<EOF
    apiVersion: v1
    kind: Pod
    metadata:
      name: slow-start-app
    spec:
      containers:
      - name: app
        image: busybox:1.36
        command: ['sh', '-c', 'sleep 45 && touch /tmp/ready && sleep 3600']
        startupProbe:
          exec:
            command:
            - cat
            - /tmp/ready
          initialDelaySeconds: 0
          periodSeconds: 10
          failureThreshold: 10  # 允许100秒启动时间
        livenessProbe:
          exec:
            command:
            - cat
            - /tmp/ready
          periodSeconds: 5
    EOF
    
    kubectl apply -f pod-startup.yaml
    kubectl get pod slow-start-app -w
    

    # 删除资源
    kubectl delete -f pod-startup.yaml
    kubectl delete -f deployment-readiness.yaml
    kubectl delete -f pod-liveness.yaml
    kubectl delete -f pod-sidecar.yaml
    

    7-自动扩缩容与资源管理

    7.1-资源请求与限制

    部署带资源限制的应用

    mkdir -p ~/k8s-practice/06-AS-resource-management && cd ~/k8s-practice/06-AS-resource-management
    cat > deployment-resources.yaml <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: resource-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: resource-demo
      template:
        metadata:
          labels:
            app: resource-demo
        spec:
          containers:
          - name: stress
            image: polinux/stress:1.0.4
            command: ['stress']
            args:
            - '--cpu'
            - '1'
            - '--vm'
            - '1'
            - '--vm-bytes'
            - '64M'
            resources:
              requests:
                memory: "64Mi"
                cpu: "100m"       # 0.1 核
              limits:
                memory: "128Mi"
                cpu: "200m"       # 0.2 核
    EOF
    
    kubectl apply -f deployment-resources.yaml
    
    # 查看资源使用(需要安装 metrics-server)
    # 下载命令如下:(下面小节也详细介绍如何下载)
    # kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
    
    kubectl top pods -l app=resource-demo
    kubectl top nodes
    

    7.2-安装 Metrics Server

    # 方法一:下载 Metrics Server
    wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml -O metrics-server.yaml
    
    # 修改配置(绕过 TLS 验证)
    cat >> metrics-server-patch.yaml <<EOF
    spec:
      template:
        spec:
          containers:
          - name: metrics-server
            args:
            - --kubelet-insecure-tls
            - --kubelet-preferred-address-types=InternalIP
    EOF
    
    # 编辑 metrics-server.yaml,在 Deployment 的 spec.template.spec.containers[0].args 下添加:
    # - --kubelet-insecure-tls
    # - --kubelet-preferred-address-types=InternalIP
    
    # 方法二:或直接替换
    kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
    
    kubectl edit deployment metrics-server -n kube-system
    # 添加上述参数
    
    # 等待就绪
    kubectl get pods -n kube-system -l k8s-app=metrics-server
    
    # 测试
    kubectl top nodes
    kubectl top pods -A
    

    7.3-Horizontal Pod Autoscaler (HPA)

    部署测试应用

    cat > php-apache.yaml <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: php-apache
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: php-apache
      template:
        metadata:
          labels:
            app: php-apache
        spec:
          containers:
          - name: php-apache
            image: registry.k8s.io/hpa-example
            ports:
            - containerPort: 80
            resources:
              requests:
                cpu: 100m
              limits:
                cpu: 200m
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: php-apache
    spec:
      selector:
        app: php-apache
      ports:
      - port: 80
    EOF
    
    kubectl apply -f php-apache.yaml
    

    创建 HPA

    # 方法1:命令行
    kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10
    
    # 方法2:YAML
    cat > hpa.yaml <<EOF
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: php-apache-hpa
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: php-apache
      minReplicas: 1
      maxReplicas: 3
      metrics:
      - type: Resource
        resource:
          name: cpu
          target:
            type: Utilization
            averageUtilization: 50
    EOF
    
    kubectl apply -f hpa.yaml
    
    # 查看 HPA
    kubectl get hpa
    kubectl describe hpa php-apache-hpa
    

    负载测试

    # 在新终端监控 HPA
    watch -n 1 kubectl get hpa
    
    # 生成负载
    kubectl run load-generator --image=busybox:1.36 --restart=Never -- /bin/sh -c "while true; do wget -q -O- http://php-apache; done"
    
    # 观察 Pod 自动扩展
    kubectl get pods -l app=php-apache -w
    
    # 停止负载
    kubectl delete pod load-generator
    
    # 观察 Pod 自动缩减(需要等待约5分钟)
    

    这里由于去官网拉取镜像导致部分pod创建时间过长导致不能很好的实现HPA,我的想法是将HPA的配置设置设置成本地拉取镜像,先将镜像拉取到本地后保证pod能够正常伸缩。

    # 删除资源
    kubectl delete -f hpa.yaml
    kubectl delete -f php-apache.yaml
    kubectl delete -f deployment-resources.yaml
    

    8-网络策略与安全

    检查当前 CNI

    kubectl get pods -A | grep -E 'calico|flannel|weave'
    

    8.1-创建测试环境

    创建三个命名空间

    mkdir ~/k8s-practice/07-ENV-test && cd ~/k8s-practice/07-ENV-test
    kubectl create namespace frontend
    kubectl create namespace backend
    kubectl create namespace database
    

    部署应用

    # Frontend
    kubectl run frontend --image=nginx:1.24-alpine -n frontend --port=80
    kubectl expose pod frontend --port=80 -n frontend
    
    # Backend
    kubectl run backend --image=nginx:1.24-alpine -n backend --port=80
    kubectl expose pod backend --port=80 -n backend
    
    # Database
    kubectl run database --image=nginx:1.24-alpine -n database --port=80
    kubectl expose pod database --port=80 -n database
    
    # 测试 Pod(用于测试连通性)
    kubectl run test-pod --image=busybox:1.36 -n frontend -- sleep 3600
    

    测试默认连通性

    # 从 frontend 访问其他服务(默认全通)
    kubectl exec -n frontend test-pod -- wget -qO- --timeout=2 backend.backend.svc.cluster.local
    
    kubectl exec -n frontend test-pod -- wget -qO- --timeout=2 database.database.svc.cluster.local
    

    8.2-配置网络策略

    策略1: 拒绝所有入站流量

    cat > deny-all-ingress.yaml <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: deny-all-ingress
      namespace: database
    spec:
      podSelector: {}  # 应用于所有 Pod
      policyTypes:
      - Ingress
    EOF
    
    kubectl apply -f deny-all-ingress.yaml
    
    # 测试(应该超时)
    kubectl exec -n frontend test-pod -- wget -qO- --timeout=2 database.database.svc.cluster.local
    

    策略2:仅允许 backend 访问 database

    cat > allow-backend-to-db.yaml <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-backend-to-db
      namespace: database
    spec:
      podSelector:
        matchLabels: {}  # 应用于 database 命名空间的所有 Pod
      policyTypes:
      - Ingress
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              name: backend
        ports:
        - protocol: TCP
          port: 80
    EOF
    
    # 给 backend 命名空间打标签
    kubectl label namespace backend name=backend
    
    kubectl apply -f allow-backend-to-db.yaml
    
    # 从 backend 创建测试 Pod
    kubectl run test-backend --image=busybox:1.36 -n backend -- sleep 3600
    
    # 测试(应该成功)
    kubectl exec -n backend test-backend -- wget -qO- --timeout=2 database.database.svc.cluster.local
    
    # 从 frontend 测试(应该失败)
    kubectl exec -n frontend test-pod -- wget -qO- --timeout=2 database.database.svc.cluster.local
    

    策略3:限制 Pod 级别访问

    cat > backend-policy.yaml <<EOF
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: backend-access
      namespace: backend
    spec:
      podSelector:
        matchLabels:
          run: backend
      policyTypes:
      - Ingress
      - Egress
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              name: frontend
        - podSelector:
            matchLabels:
              role: api-gateway
        ports:
        - protocol: TCP
          port: 80
      egress:
      - to:
        - namespaceSelector:
            matchLabels:
              name: database
        ports:
        - protocol: TCP
          port: 80
      # 允许 DNS 查询
      - to:
        - namespaceSelector:
            matchLabels:
              name: kube-system
        ports:
        - protocol: UDP
          port: 53
    EOF
    
    kubectl label namespace frontend name=frontend
    kubectl label namespace kube-system name=kube-system
    
    kubectl apply -f backend-policy.yaml
    
    # 删除资源
    kubectl delete -f backend-policy.yaml
    kubectl delete -f allow-backend-to-db.yaml
    delete -f deny-all-ingress.yaml
    kubectl delete pod test-pod -n frontend
    kubectl delete pod frontend -n frontend
    kubectl delete pod backend -n backend
    kubectl delete pod database -n database
    kubectl delete namespace frontend backend database
    

    9-CI/CD & Helm

    9.1-安装 Helm

    mkdir ~/k8s-practice/08-helm && cd ~/k8s-practice/08-helm
    
    # 下载 Helm
    curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
    
    # 验证安装
    helm version
    
    # 添加常用仓库
    helm repo add stable https://charts.helm.sh/stable
    helm repo add bitnami https://charts.bitnami.com/bitnami
    # 添加 bitnami 镜像源(阿里云)
    # helm repo add bitnami https://mirrors.aliyun.com/helm/bitnami/
    helm repo update
    
    # 搜索 Chart
    helm search repo nginx
    

    9.2-创建自定义 Helm Chart

    创建 Chart 结构

    helm create myapp
    
    # 查看生成的目录结构
    tree myapp
    # myapp/
    # ├── Chart.yaml          # Chart 元数据
    # ├── values.yaml         # 默认配置
    # ├── charts/             # 依赖 Chart
    # └── templates/          # K8s 资源模板
    #     ├── deployment.yaml
    #     ├── service.yaml
    #     ├── ingress.yaml
    #     └── ...
    

    编辑 Chart.yaml

    cat > myapp/Chart.yaml <<EOF
    apiVersion: v2
    name: myapp
    description: A simple web application
    type: application
    version: 1.0.0
    appVersion: "1.0"
    EOF
    

    编辑 values.yaml

    cat > myapp/values.yaml <<EOF
    replicaCount: 2
    
    image:
      repository: nginx
      tag: "1.24-alpine"
      pullPolicy: IfNotPresent
    
    service:
      type: ClusterIP
      port: 80
    
    ingress:
      enabled: true
      className: nginx
      hosts:
        - host: myapp.local
          paths:
            - path: /
              pathType: Prefix
    
    resources:
      limits:
        cpu: 200m
        memory: 256Mi
      requests:
        cpu: 100m
        memory: 128Mi
    
    autoscaling:
      enabled: true
      minReplicas: 2
      maxReplicas: 5
      targetCPUUtilizationPercentage: 70
    
    serviceAccount:
      create: true
      automount: true
      name: ""
    
    httpRoute:
      enabled: false
    EOF
    
    

    简化 templates/deployment.yaml

    cat > myapp/templates/deployment.yaml <<'EOF'
    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 }}"
            imagePullPolicy: {{ .Values.image.pullPolicy }}
            ports:
            - containerPort: 80
            resources:
              {{- toYaml .Values.resources | nindent 10 }}
    EOF
    

    验证 Chart

    # 语法检查
    helm lint myapp
    
    # 渲染模板(不安装)
    helm template myapp ./myapp
    
    # 调试安装
    helm install myapp ./myapp --dry-run --debug
    

    9.3-部署和管理

    安装 Chart

    # 安装到 default 命名空间
    helm install myapp-release-1 ./myapp
    
    # 安装到指定命名空间(需要先删除上面创建的)
    helm list -A
    helm uninstall myapp-release-1
    helm install myapp-release-2 ./myapp -n myapp-ns --create-namespace
    
    # 覆盖 values
    helm list -A
    helm uninstall -n myapp-ns myapp-release-2
    helm install myapp-release-3 ./myapp --set replicaCount=3
    
    # 使用自定义 values 文件
    cat > custom-values.yaml <<EOF
    replicaCount: 4
    image:
      tag: "1.25-alpine"
    EOF
    
    helm uninstall myapp-release-3
    helm install myapp-release-4 ./myapp -f custom-values.yaml
    
    # 查看部署
    helm list
    helm status myapp-release-4
    kubectl get all -l app.kubernetes.io/instance=myapp-release-4
    

    升级 Chart

    # 修改 values.yaml 或代码
    
    # 升级
    helm upgrade myapp-release-4 ./myapp
    
    # 升级并修改参数
    helm upgrade myapp-release-4 ./myapp --set replicaCount=5
    
    # 查看历史版本
    helm history myapp-release-4
    

    回滚

    # 回滚到上一个版本
    helm rollback myapp-release-4
    
    # 回滚到指定版本
    helm rollback myapp-release-4 1
    
    # 查看回滚后状态
    helm history myapp-release-4
    

    卸载

    # 卸载 Release
    helm uninstall myapp-release-4
    
    # 保留历史记录的删除
    helm uninstall myapp-release-4 --keep-history
    

    9.4-Kubectl Rollout 管理

    部署新版本

    # 更新镜像
    kubectl set image deployment/nginx-deployment nginx=nginx:1.25-alpine --record
    
    # 查看滚动更新状态
    kubectl rollout status deployment/nginx-deployment
    
    # 查看更新历史
    kubectl rollout history deployment/nginx-deployment
    
    # 查看特定版本详情
    kubectl rollout history deployment/nginx-deployment --revision=2
    

    暂停和恢复

    # 暂停滚动更新
    kubectl rollout pause deployment/nginx-deployment
    
    # 进行多次更新
    kubectl set image deployment/nginx-deployment nginx=nginx:1.26-alpine
    kubectl set resources deployment/nginx-deployment -c=nginx --limits=cpu=500m,memory=512Mi
    
    # 恢复滚动更新
    kubectl rollout resume deployment/nginx-deployment
    

    回滚

    # 回滚到上一个版本
    kubectl rollout undo deployment/nginx-deployment
    
    # 回滚到指定版本
    kubectl rollout undo deployment/nginx-deployment --to-revision=2
    
    # 验证回滚
    kubectl get deployment nginx-deployment -o jsonpath='{.spec.template.spec.containers[0].image}'
    

    总结与清理

    清理所有资源

    # 删除所有 Deployment
    kubectl delete deployment --all
    
    # 删除所有 Service
    kubectl delete service --all
    
    # 删除所有 Ingress
    kubectl delete ingress --all
    
    # 删除所有 ConfigMap
    kubectl delete configmap --all
    
    # 删除所有 Secret(系统 Secret 会保留)
    kubectl delete secret --all
    
    # 删除命名空间
    kubectl delete namespace frontend backend database
    
    # 卸载 Helm Release
    helm uninstall $(helm list -q)
    
    # 卸载 Ingress Controller
    kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/baremetal/deploy.yaml
    

    更多推荐