摘要:你是否已经熟练使用 Docker,却在微服务架构带来的大规模容器管理面前感到力不从心?本文是一篇为开发者和初级运维工程师量身打造的 Kubernetes (K8s) 深度指南。我们将从 K8s 的核心设计哲学出发,系统讲解 Pod、Deployment、StatefulSet 等核心抽象,手把手带你搭建单节点及三节点集群,通过一个完整的 WordPress + MySQL 实战项目掌握 YAML 工程化,并最终探讨如何将 K8s 集成到 CI/CD 流水线中。读完本文,你将拥有从 0 到 1 在 K8s 上部署、管理和自动化应用的完整知识体系。

引言:告别刀耕火种,迎接云原生时代的“操作系统”

在过去的几年里,Docker 以前所未有的方式改变了软件的打包和分发。它像一个标准的“集装箱”,将我们的应用及其所有依赖完美封装,实现了“一次构建,处处运行”。

但故事并未就此结束。当我们从简单的单体应用迈向复杂的微服务架构时,我们手中的“集装箱”从几个变成了几十、几百甚至上千个。随之而来的,是“管理的混乱”:

  • 部署之苦:如何高效地在数十台服务器上部署和更新数百个容器?
  • 故障之痛:半夜服务宕机,难道要人工登录服务器,一个个地重启容器吗?
  • 伸缩之难:流量洪峰来临,如何快速地将服务实例从 10 个扩展到 200 个?
  • 网络之谜:容器 IP 动态变化,服务之间该如何发现彼此并可靠通信?

这些问题,已远超 Docker 引擎的能力范畴。我们需要一个更高维度的“大脑”来统一指挥和调度。Kubernetes (K8s) 正是为此而生。它不仅仅是一个容器编排工具,更被誉为云原生时代的分布式操作系统,为我们管理分布式应用提供了坚实的基础。


第一章:K8s 核心解密:不是魔法,而是精妙的顶层设计

1.1. K8s 是什么?
  • 生动的比喻:你可以将 K8s 想象成一个交响乐团的指挥家。容器是乐手,服务器是座位,而 K8s 就是那位指挥家,确保每个乐手(容器)在正确的时间、正确的位置,以正确的状态演奏。
  • 官方定义:Kubernetes 是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。
  • 核心理念:声明式 API 与控制循环
    这是 K8s 自动化的基石。你不需要告诉 K8s “如何做”(比如“先启动容器A,再启动B”),你只需要通过 YAML 文件告诉它**“你想要什么最终状态”(比如“我想要2个Nginx副本和一个MySQL副本”)。K8s 内部的控制循环 (Control Loop)** 会永不停歇地工作,时刻对比“期望状态”与“当前实际状态”,并采取一切必要措施使两者保持一致。
1.2. 核心架构:大脑与身体的分工

一个 K8s 集群由两种类型的节点组成:控制平面(Master)和工作节点(Worker)。

在这里插入图片描述

  • 控制平面 (Master Node) - 大脑

    • API Server: 集群的唯一入口,所有组件都通过它进行通信,负责处理所有请求和验证。
    • etcd: 一个高可用的键值数据库,存储了整个集群的所有状态信息(可以理解为 K8s 的记忆中心)。
    • Scheduler: 调度器。当有新的 Pod 需要创建时,Scheduler 会根据资源、亲和性等策略,决定把它分配到哪个 Worker Node 上。
    • Controller Manager: 控制器管理器。运行着各种控制器(如 Deployment 控制器、StatefulSet 控制器),它们是执行控制循环,确保集群状态与期望一致的核心。
  • 工作节点 (Worker Node) - 身体

    • Kubelet: Master 在每个 Worker 上的代理人,负责接收指令并管理该节点上的 Pod 和容器。
    • Kube-proxy: 网络管家,负责管理节点上的网络规则,实现 Service 的负载均衡等。
    • 容器运行时 (Container Runtime): 真正运行容器的引擎,最常见的就是 Docker。

第二章:万物皆对象:深入理解 K8s 的抽象层

在 K8s 中,一切皆可被描述为 API 对象。理解这些对象的含义是掌握 K8s 的关键。

2.1. 原子单元:Pod

Pod 是 K8s 中可以创建和管理的最小、最基本的部署单元。它不是容器,而是一个或多个紧密耦合的容器的集合。同一个 Pod 内的容器共享同一个网络命名空间(IP地址和端口)和存储卷,非常适合于那些需要紧密协作的进程。

2.2. Pod 之上的管理者:工作负载抽象 (Workload Controllers)

我们很少直接创建 Pod,而是通过更高层次的控制器来管理它们。

2.2.1. 无状态应用守护神:Deployment
  • 核心职责: 管理一组完全相同、可随意替换的 Pod 副本。它提供了强大的滚动更新回滚能力,确保应用在升级过程中服务不中断。
  • 适用场景: Web 服务器 (Nginx, Tomcat)、API 网关、微服务的无状态业务逻辑部分。这是 K8s 中最常用的控制器
2.2.2. 有状态应用专家:StatefulSet
  • 核心特性: 专门为有状态应用设计。它能保证管理的 Pod 拥有稳定的、唯一的网络标识(如 db-0, db-1)和独立的、持久化的存储。Pod 的创建、更新、删除都是有序的。
  • 适用场景: 数据库 (MySQL, PostgreSQL)、消息队列 (Kafka)、分布式存储 (Zookeeper)。
2.2.3. 集群守护进程:DaemonSet
  • 核心职责: 确保在集群中的每一个(或指定的)Node 上都运行一个且仅一个 Pod 副本。当有新节点加入集群时,它会自动在该节点上部署一个 Pod。
  • 适用场景: 日志收集代理 (Fluentd)、监控代理 (Prometheus Node Exporter)、网络插件。
2.2.4. 任务执行者:Job & CronJob
  • 核心职责: Job 负责执行一次性的批处理任务,它会确保 Pod 成功运行完成后才终止。CronJob 则像 Linux 的 crontab 一样,可以按预定的时间计划周期性地创建 Job。
  • 适用场景: 数据备份、数据迁移、定时报表生成等。
2.3. 服务的发现与暴露
  • Service: 解决了 Pod IP 动态变化的问题。它为一组功能相同的 Pod 提供了一个单一、稳定的虚拟 IP 地址(ClusterIP)和 DNS 名称,并在这些 Pod 之间自动进行负载均衡。NodePortLoadBalancer 类型的 Service 还可以将服务暴露到集群外部。
  • Ingress: 如果说 Service 是4层(TCP/UDP)的负载均衡,那么 Ingress 就是7层(HTTP/HTTPS)的。它作为集群流量的“HTTP 路由网关”,可以根据域名和 URL 路径将外部请求转发到集群内部不同的 Service 上,非常适合管理多个 Web 应用。
2.4. 配置与存储
  • ConfigMap & Secret: 允许你将应用的配置信息(如数据库地址)和敏感信息(如密码、API Key)从容器镜像中解耦。这使得配置更灵活、应用更安全。
  • Volume, PersistentVolume (PV) & PersistentVolumeClaim (PVC): K8s 的持久化存储解决方案。PVC 是应用向 K8s 发出的“存储申请”,PV 是集群中已存在的“存储资源”。这种设计将应用对存储的需求与底层具体的存储实现(如 NFS、Ceph、云硬盘)解耦。

第三章:动手为王:从 0 搭建你的 K8s 实验环境

3.1. 本地单节点集群:极速上手 (Docker Desktop)

对于开发者来说,最快的方式是使用 Docker Desktop 内置的 K8s 功能。

  1. 安装 Docker Desktop: 前往 Docker 官网下载并安装。
  2. 启用 Kubernetes: 打开 Docker Desktop 的 Settings -> Kubernetes,勾选 Enable Kubernetes,然后点击 Apply & Restart
  3. 验证集群: 等待左下角 K8s 图标变绿后,打开终端,运行 kubectl get nodes。如果能看到一个名为 docker-desktop 的节点且状态为 Ready,恭喜你,本地 K8s 环境已就绪!
3.2. 构建一个“真正”的三节点集群 (使用 kubeadm)

kubeadm 是官方推荐的用于快速搭建生产级 K8s 集群的工具。

  • 环境准备: 准备3台配置至少 2核CPU/2G内存 的 Linux 虚拟机(如 CentOS 7/8 或 Ubuntu 20.04),一台作为 Master,两台作为 Worker。确保它们网络互通,并已完成基础配置(如关闭防火墙、禁用 SELinux、关闭 swap)。

  • 安装步骤:

    1. 所有节点: 安装 Docker 和 K8s 组件。

      # (以CentOS为例)
      # 1. 安装Docker... (此处省略详细步骤,请参考Docker官方文档)
      
      # 2. 添加K8s YUM源
      cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
      [kubernetes]
      name=Kubernetes
      baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
      enabled=1
      gpgcheck=1
      repo_gpgcheck=1
      gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
      exclude=kubelet kubeadm kubectl
      EOF
      
      # 3. 安装kubelet, kubeadm, kubectl
      sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
      sudo systemctl enable --now kubelet
      
    2. Master 节点: 初始化控制平面。

      # --pod-network-cidr 是网络插件需要的地址段,这里以Calico为例
      # --image-repository 使用国内镜像源加速
      sudo kubeadm init \
        --image-repository registry.aliyuncs.com/google_containers \
        --pod-network-cidr=192.168.0.0/16
      
      # 初始化成功后,按提示保存 kubeadm join 命令!
      mkdir -p $HOME/.kube
      sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
      sudo chown $(id -u):$(id -g) $HOME/.kube/config
      
    3. Master 节点: 安装网络插件(CNI)。这一步至关重要,否则节点会一直处于 NotReady 状态!

      # 以Calico为例
      kubectl apply -f https://docs.project.calico.org/manifests/calico.yaml
      
    4. Worker 节点: 使用 Master 初始化时生成的 kubeadm join 命令加入集群。

      sudo kubeadm join <master-ip>:<master-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
      
  • 验证集群: 在 Master 节点上运行 kubectl get nodes -o wide,你应该能看到一个 master 和两个 worker 节点,状态都为 Ready


第四章:YAML 工程化:声明式 API 的艺术

在 K8s 中,我们通过编写 YAML 文件来定义所有 API 对象。

4.2. 案例实战:部署一个完整的 WordPress 应用

我们将部署一个包含 WordPress(无状态 Deployment)和 MySQL(有状态 StatefulSet)的经典 Web 应用。

1. mysql-secret.yaml (存储密码)

apiVersion: v1
kind: Secret
metadata:
  name: mysql-secret
type: Opaque
data:
  password: cGFzc3dvcmQ= # 'password' 的 Base64 编码

2. mysql-statefulset.yaml & mysql-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  selector: { app: mysql }
  clusterIP: None # Headless Service for StatefulSet
  ports:
  - port: 3306
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: mysql
spec:
  serviceName: "mysql"
  replicas: 1
  selector: { matchLabels: { app: mysql } }
  template:
    metadata: { labels: { app: mysql } }
    spec:
      containers:
      - name: mysql
        image: mysql:5.7
        env:
        - name: MYSQL_ROOT_PASSWORD
          valueFrom: { secretKeyRef: { name: mysql-secret, key: password } }
        ports:
        - containerPort: 3306
        volumeMounts:
        - name: mysql-persistent-storage
          mountPath: /var/lib/mysql
  volumeClaimTemplates:
  - metadata: { name: mysql-persistent-storage }
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources: { requests: { storage: "5Gi" } }

3. wordpress-deployment.yaml & wordpress-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: wordpress
spec:
  type: NodePort
  selector: { app: wordpress }
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: wordpress
spec:
  replicas: 1
  selector: { matchLabels: { app: wordpress } }
  template:
    metadata: { labels: { app: wordpress } }
    spec:
      containers:
      - name: wordpress
        image: wordpress:latest
        env:
        - name: WORDPRESS_DB_HOST
          value: "mysql" # 使用MySQL Service的DNS名称
        - name: WORDPRESS_DB_PASSWORD
          valueFrom: { secretKeyRef: { name: mysql-secret, key: password } }
        - name: WORDPRESS_DB_USER
          value: "root"
        ports:
        - containerPort: 80

部署与验证:将以上文件保存到同一目录,然后运行 kubectl apply -f .。等待所有 Pod 启动后,通过浏览器访问任意一个 Worker 节点的 IP 地址加上端口 30080(例如 http://<worker-ip>:30080),你将看到 WordPress 的安装界面!


第五章:运维与调试:成为 K8s 的“老司机”

5.1. kubectl 常用命令清单
  • 查看: get pods, get nodes, get svc, get deploy, get all -n <namespace>
  • 诊断: describe pod <pod-name>, logs <pod-name>, exec -it <pod-name> -- /bin/sh
  • 操作: apply -f, delete -f, scale deployment <name> --replicas=3, rollout status/history/undo deployment <name>
5.2. 本地调试神器:port-forward

port-forward 可以在你的本地机器和集群内的 Pod/Service 之间建立一个安全的隧道,非常适合本地调试。

场景:你想用本地的 Navicat/DataGrip 工具连接到集群内部的 MySQL 数据库。

# 将本地的 3306 端口转发到 mysql-0 Pod 的 3306 端口
kubectl port-forward pod/mysql-0 3306:3306

现在,你可以在本地的数据库客户端中,通过连接 localhost:3306 来直接访问集群中的 MySQL 了!

5.3. 定制化你的应用:Operator 模式初探

StatefulSet 解决了有状态应用的部署问题,但更复杂的运维任务(如主从切换、备份恢复、版本升级)怎么办?Operator 模式应运而生。

理念: Operator = CRD (自定义资源) + Controller (自定义控制器)。它将一个领域专家(如 DBA)的运维知识代码化。例如,你可以安装一个 PostgresOperator,然后像下面这样简单地定义一个高可用的 PostgreSQL 集群:

apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
  name: acid-minimal-cluster
spec:
  teamId: "acid"
  volume: { size: "1Gi" }
  numberOfInstances: 2
  users: { zalando: [superuser, createdb] }
  databases: { foo: zalando }

Operator 会自动为你完成所有复杂的配置。这是 K8s 生态的未来,让管理复杂应用变得像管理 Deployment 一样简单。


第六章:迈向自动化:将 K8s 集成到 CI/CD 流水线

6.1. CI/CD for K8s 流程概览
  1. 提交代码: 开发者将代码推送到 GitLab/GitHub。
  2. 触发流水线: Jenkins 或 GitLab CI 自动触发。
  3. 构建 & 推送: 流水线作业构建 Docker 镜像,并将其推送到镜像仓库(如 Harbor, Docker Hub)。
  4. 部署更新: 流水线作业更新 K8s Deployment YAML 文件中的镜像版本标签,然后执行 kubectl apply 来触发滚动更新。
6.2. 实战案例:使用 GitLab CI 自动化部署

在你的项目根目录下创建一个 .gitlab-ci.yml 文件:

stages:
  - build
  - deploy

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

build_image:
  stage: build
  image: docker:20.10.16
  services:
    - docker:20.10.16-dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG

deploy_to_k8s:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    # KUBECONFIG 通常作为 CI/CD 变量存储
    - echo "$KUBE_CONFIG_DATA" > kubeconfig.yaml
    - export KUBECONFIG=kubeconfig.yaml
    # 使用 sed 或 kustomize 等工具更新 Deployment 的镜像标签
    - sed -i "s|image:.*|image: $IMAGE_TAG|g" k8s-deployment.yaml
    - kubectl apply -f k8s-deployment.yaml
    - kubectl rollout status deployment/my-app-deployment

总结与展望:K8s 不是终点,而是云原生之旅的起点

今天,我们从 K8s 的核心设计哲学出发,系统地学习了它的架构、核心抽象,亲手搭建了实验环境,并通过实战项目掌握了 YAML 的编写和应用的部署。我们还探讨了日常运维和 CI/CD 集成的方向。

你已经掌握了 K8s 的核心骨架,但这仅仅是开始。云原生的世界广阔无垠,接下来你可以继续探索:

  • 网络: 深入理解 CNI 插件(Calico, Flannel)的工作原理。
  • 存储: 探索 CSI 插件和各种分布式存储方案(Ceph, Rook)。
  • 服务网格 (Service Mesh): 学习 Istio 或 Linkerd,实现更强大的流量管理、可观察性和安全性。
  • 监控与日志: 掌握 Prometheus + Grafana 进行监控,以及 EFK/PLG 栈进行日志管理。
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐