1Kubernetes 实战

Kubernetes 概述

容器编排的基石

容器编排集群

🎯 AI 时代的学习建议:不要只读理论。理解这一章的设计动机(为什么需要这个概念?)和边界条件(什么情况下会失效?)。当 AI 生成的代码涉及这些概念时,你能判断它是否用对了场景。AI 能帮你总结内容,但无法替代你亲手阅读、思考、建立直觉的过程。

第1章:Kubernetes简介(Introduction to Kubernetes)

一、导读

1.1 本章学习目标

第1章是整本《Kubernetes实战》的开篇之作,它将带你走进 Kubernetes 的世界,理解这个现代云计算领域最重要的技术之一。在深入具体的技术细节之前,你需要先建立对 Kubernetes 的全局认知:它从何而来、解决了什么问题、核心设计理念是什么、集群由哪些组件构成。这种全局视角对于后续章节深入学习每个子系统至关重要——在了解每个零件之前,你需要先知道整台机器的蓝图。

本章的核心学习目标包括:

  • 理解 Kubernetes 的起源和演进:从 Google Borg 到 Kubernetes,再到 CNCF 生态,了解 K8s 的设计哲学从何而来。
  • 掌握集群架构的核心组件:Control Plane(API Server、etcd、Scheduler、Controller Manager)和 Worker 节点(kubelet、kube-proxy、Container Runtime)各自承担什么职责?
  • 理解声明式 API 模型:Kubernetes 如何通过"期望状态"和"实际状态"的调谐循环来管理集群?
  • 认识核心抽象对象:Pod、Service、Deployment、Namespace 等核心资源之间的关系是什么?
  • 了解 K8s 的设计哲学:自动化、可扩展、声明式、自愈等核心原则如何影响系统设计?
  • 搭建本地开发环境:使用 Minikube 或 Kind 搭建本地 K8s 集群,完成第一次 kubectl 操作。

1.2 为什么第一章如此重要

很多初学者急于学习 Pod、Deployment 等具体资源的操作,觉得第一章"太概念化"或"太泛"。这种想法是极其危险的。Kubernetes 是一个复杂的分布式系统,拥有数百个 API 资源和数千个配置选项。没有全局观,后续学习就容易陷入"只见树木,不见森林"的困境——你会机械地复制 YAML 配置,却不理解背后的设计意图。

Kubernetes 的设计深受 Google 内部系统 Borg 和 Omega 的影响。理解这段历史,你就能理解为什么 K8s 采用声明式 API、为什么控制器模式如此核心、为什么 etcd 是集群的"唯一真相来源"。这些设计决策不是偶然的,而是 Google 十多年大规模集群运营经验的结晶。

更重要的是,Kubernetes 的核心抽象之间存在精密的层级关系。Pod 是调度的最小单元,Deployment 管理 Pod 的副本和更新,Service 为 Pod 提供稳定的网络入口——不理解这些关系,你就无法设计出健壮的应用架构。第一章正是帮助你建立这种关系图谱的起点。

1.3 核心问题引导

在阅读本章时,请带着以下问题思考:

Kubernetes 和 Docker 的关系是什么?K8s 只是"Docker 的升级版"吗?

为什么 Kubernetes 选择声明式 API 而不是命令式 API?声明式有什么优势?

etcd 为什么如此重要?如果 etcd 数据丢失会发生什么?

Pod 和容器的区别是什么?为什么不直接调度容器,而要引入 Pod 这个抽象?

Controller Manager 中的各个控制器是如何协同工作的?

当你执行 kubectl apply -f deployment.yaml 时,K8s 内部发生了什么?


二、核心概念详解

2.1 Kubernetes 的起源与演进

2.1.1 Google Borg 时代

Kubernetes 的故事要从 2003 年说起。那一年,Google 内部启动了一个名为 Borg 的项目——一个大规模集群管理系统,用于运行 Google 搜索、Gmail、YouTube 等核心服务。Borg 在 Google 内部运行了十多年,管理着数以百万计的容器,积累了大量宝贵的经验和教训。

Borg 的核心设计理念包括:

  • 声明式管理:用户提交作业的期望规格(desired specification),Borg 负责确保实际状态与期望一致
  • 自动化运维:自动故障恢复、自动扩缩容、自动滚动更新
  • 高利用率:通过混合部署批处理作业和在线服务,最大化集群资源利用率
  • 可扩展性:通过分层架构支持超大规模集群

Borg 的经验催生了两个重要项目:Omega(Borg 的下一代,引入了共享状态和并行控制)和 Kubernetes(Borg 的开源版本,将 Google 的容器编排经验带给全世界)。

2.1.2 Kubernetes 的诞生

2014 年,Google 的 Joe Beda、Brendan Burns 和 Craig McLuckie 开始设计 Kubernetes。他们借鉴了 Borg 和 Omega 的设计,同时吸收了开源社区的反馈。2015 年,Kubernetes 正式开源,同年 Google 联合 Pivotal、Red Hat、IBM 等公司成立了 Cloud Native Computing Foundation(CNCF),将 Kubernetes 捐赠给 CNCF 管理。

Kubernetes 的名字来源于希腊语,意为"舵手"或"飞行员",缩写 K8s(K 和 s 之间的 8 个字母)已经成为社区的标准简称。

2.1.3 CNCF 生态的发展

CNCF 的成立标志着 Kubernetes 进入了一个全新的阶段。在 CNCF 的治理下,Kubernetes 生态蓬勃发展:

  • 2015-2016:Kubernetes 1.0-1.5,核心 API 逐步稳定,社区快速成长
  • 2017-2018:Kubernetes 1.6-1.12,RBAC、Custom Resources、Service Mesh 等特性成熟
  • 2019-2020:Kubernetes 1.13-1.20,Windows 容器支持、IPv6、GA 特性增多
  • 2021-至今:Kubernetes 1.21+,Gateway API、Sidecar Containers、更好的多集群支持

截至 2024 年,CNCF 已经拥有超过 150 个项目,包括 Prometheus、Envoy、containerd、Helm、Argo 等,形成了一个完整的云原生技术生态。

2.2 集群架构

Kubernetes 集群由两类节点组成:Control Plane(控制平面,也称 Master 节点)和 Worker 节点(工作节点)。这种分离设计使得控制逻辑和计算负载互不干扰。

2.2.1 Control Plane 组件

Control Plane 是 Kubernetes 的"大脑",负责维护集群的期望状态并驱动实际状态向期望状态收敛。

kube-apiserver

API Server 是所有集群操作的唯一入口。它提供 RESTful API,接收来自 kubectl、控制器、kubelet 等客户端的请求。API Server 的设计遵循以下原则:

  • 简单性:所有操作都是对资源的 CRUD(创建、读取、更新、删除)
  • 一致性:所有状态存储在 etcd 中,保证强一致性
  • 可扩展性:通过 Custom Resource Definition(CRD)支持自定义资源
bash
# 查看 API Server 支持的资源类型
kubectl api-resources

# 查看 API Server 版本
kubectl version --short

# 直接调用 API Server
kubectl get --raw /api/v1/namespaces
kubectl get --raw /apis/apps/v1/deployments

API Server 还负责认证(Authentication)、授权(Authorization)和准入控制(Admission Control)。每个请求都必须通过这三层检查才能被处理。

etcd

etcd 是一个高可用的分布式键值存储,用于保存 Kubernetes 集群的所有状态数据。它是集群的"唯一真相来源"(Single Source of Truth)。etcd 使用 Raft 共识算法保证数据一致性。

etcd 存储的数据包括:

  • 所有 Kubernetes 资源(Pod、Service、Deployment 等)的配置和状态
  • 集群的配置信息
  • Secret 数据(加密存储)
bash
# 查看 etcd 中的数据(需要 etcdctl 工具)
etcdctl get /registry/pods/default/my-pod --prefix

# etcd 的备份
etcdctl snapshot save /backup/etcd-snapshot.db

# etcd 的恢复
etcdctl snapshot restore /backup/etcd-snapshot.db --data-dir=/var/lib/etcd-restored

kube-scheduler

Scheduler 负责决定新创建的 Pod 应该运行在哪个 Worker 节点上。调度过程分为两个阶段:

过滤(Filtering/Predicates):排除不满足 Pod 需求的节点(如资源不足、节点选择器不匹配)

打分(Scoring/Priorities):对剩余节点评分,选择得分最高的节点

yaml
# 调度策略配置示例
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
  - schedulerName: default-scheduler
    plugins:
      score:
        enabled:
          - name: NodeResourcesBalancedAllocation
            weight: 1
          - name: ImageLocality
            weight: 1

kube-controller-manager

Controller Manager 运行着多个控制器进程,每个控制器负责一种资源的调谐。控制器的核心逻辑是"观察-对比-行动"循环:

观察资源的当前状态

与期望状态对比

执行操作使当前状态向期望状态收敛

主要的控制器包括:

  • ReplicaSet Controller:维持指定数量的 Pod 副本
  • Deployment Controller:管理 ReplicaSet,实现滚动更新
  • Node Controller:监控节点状态
  • Job Controller:管理一次性任务
  • Endpoint Controller:维护 Service 和 Pod 的关联
  • ServiceAccount Controller:为新 Namespace 创建默认 ServiceAccount

2.2.2 Worker 节点组件

每个 Worker 节点运行着三个关键组件:

kubelet

kubelet 是节点上的"代理人",它接收来自 API Server 的 Pod 规格,确保容器按照规格运行。kubelet 的主要职责:

  • 管理 Pod 生命周期:创建、启动、停止、删除容器
  • 监控容器状态:通过 Liveness/Readiness Probe 检测容器健康
  • 报告节点状态:定期向 API Server 汇报节点资源使用情况
  • 管理 Volume:挂载和卸载存储卷
bash
# 查看 kubelet 状态
systemctl status kubelet

# 查看 kubelet 日志
journalctl -u kubelet -f

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

kube-proxy

kube-proxy 在每个节点上维护网络规则,实现 Service 的负载均衡。它有三种工作模式:

  • userspace 模式(已过时):通过用户空间代理转发流量
  • iptables 模式(默认):使用 iptables 规则实现负载均衡
  • IPVS 模式:使用 Linux IPVS(IP Virtual Server)实现更高效的负载均衡
bash
# 查看 iptables 规则(iptables 模式)
iptables -t nat -L KUBE-SERVICES -n

# 查看 IPVS 规则(IPVS 模式)
ipvsadm -Ln

Container Runtime

容器运行时负责实际创建和运行容器。Kubernetes 通过 Container Runtime Interface(CRI)与容器运行时交互。常见的运行时:

  • containerd:从 Docker 中剥离出的轻量级运行时,CNCF 毕业项目
  • CRI-O:专为 Kubernetes 设计的轻量级运行时
  • Docker:通过 dockershim 支持(K8s 1.24+ 已移除内置支持)

2.3 声明式 API 模型

Kubernetes 最核心的设计理念是声明式 API:你告诉系统"我想要什么状态",Kubernetes 负责将实际状态收敛到期望状态。这与传统的命令式 API("执行这个操作")形成鲜明对比。

2.3.1 声明式 vs 命令式

bash
# 命令式:告诉 K8s "做什么"
kubectl create deployment nginx --image=nginx
kubectl scale deployment nginx --replicas=3
kubectl set image deployment/nginx nginx=nginx:1.25

# 声明式:告诉 K8s "要什么"
kubectl apply -f deployment.yaml
# deployment.yaml 中定义了期望状态:3个副本、nginx:1.25 镜像
# K8s 自动完成从当前状态到期望状态的转换

声明式的优势:

  • 幂等性:多次 apply 同一个文件,结果一致
  • 版本控制:YAML 文件可以存储在 Git 中,实现 GitOps
  • 自动化:控制器自动处理故障恢复和状态收敛
  • 可审计:期望状态和实际状态的差异可以被检测和告警

2.3.2 调谐循环(Reconciliation Loop)

每个控制器都运行着一个调谐循环:

while true:
    current_state = get_current_state(resource)
    desired_state = get_desired_state(resource)
    
    if current_state != desired_state:
        take_action(desired_state)
    
    sleep(interval)

例如,Deployment 控制器发现当前只有 2 个 Pod 副本,但期望是 3 个,它就会创建 1 个新的 Pod。如果某个 Pod 异常退出,控制器会检测到并创建替代 Pod。这就是 Kubernetes 的"自愈"能力。

2.4 核心抽象对象

2.4.1 Pod

Pod 是 Kubernetes 的最小调度单元。一个 Pod 包含一个或多个容器,这些容器共享网络命名空间(相同的 IP 地址和端口空间)和存储卷。

为什么需要 Pod?为什么不直接调度容器?因为有些应用需要紧密耦合的容器组合:

  • Sidecar 模式:主容器 + 日志收集容器,共享日志目录
  • Ambassador 模式:主容器 + 代理容器,代理外部访问
  • Adapter 模式:主容器 + 标准化容器,统一监控接口
yaml
apiVersion: v1
kind: Pod
metadata:
  name: multi-container-pod
spec:
  containers:
    - name: app
      image: myapp:1.0
      ports:
        - containerPort: 8080
      volumeMounts:
        - name: shared-data
          mountPath: /data
    - name: sidecar
      image: fluentd:latest
      volumeMounts:
        - name: shared-data
          mountPath: /var/log
  volumes:
    - name: shared-data
      emptyDir: {}

2.4.2 Service

Service 为一组 Pod 提供稳定的网络入口(IP 地址和 DNS 名称)。Pod 的 IP 是动态的——Pod 重启后 IP 会变化,但 Service 的 IP 和 DNS 名称是稳定的。

yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - port: 80
      targetPort: 8080
  type: ClusterIP

Service 类型:

  • ClusterIP:集群内部访问(默认)
  • NodePort:通过节点端口暴露
  • LoadBalancer:通过云厂商负载均衡器暴露
  • ExternalName:映射到外部 DNS 名称

2.4.3 Deployment

Deployment 管理 Pod 的副本数、滚动更新和回滚。它是生产环境中管理无状态应用的标准方式。

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.25
          ports:
            - containerPort: 80

Deployment → ReplicaSet → Pod 的层级关系是 Kubernetes 的核心设计模式。Deployment 管理 ReplicaSet 的版本,ReplicaSet 管理 Pod 的副本数。

2.4.4 Namespace

Namespace 提供逻辑隔离,用于在多租户环境中区分不同的项目、团队或环境。

bash
kubectl create namespace development
kubectl create namespace production
kubectl get pods -n development
kubectl get pods --all-namespaces

2.5 Kubernetes 的设计哲学

2.5.1 自动化

Kubernetes 的设计目标是最大限度地减少人工干预。一旦定义了期望状态,系统会自动处理:

  • 故障恢复:Pod 异常退出时自动重建
  • 滚动更新:自动按比例替换旧版本 Pod
  • 扩缩容:根据 CPU/内存使用率自动调整副本数
  • 调度:自动选择最优节点运行 Pod

2.5.2 可扩展性

Kubernetes 通过以下机制实现可扩展性:

  • Custom Resource Definition(CRD):定义自定义资源
  • Operator 模式:通过控制器扩展 K8s 的能力
  • API 聚合:将自定义 API 集成到 API Server
  • 插件机制:网络插件(CNI)、存储插件(CSI)、设备插件

2.5.3 声明式

如前所述,声明式 API 是 Kubernetes 的核心理念。用户定义"期望状态",系统负责"实际状态"的收敛。这种模式简化了运维操作,使得系统可以自动化处理各种场景。

2.5.4 自愈

Kubernetes 的自愈能力体现在多个层面:

  • 容器级别:Liveness Probe 失败时重启容器
  • Pod 级别:Pod 异常退出时由控制器重建
  • 节点级别:节点不可用时将 Pod 迁移到其他节点
  • 服务级别:Service 自动移除不健康的 Pod

三、实战案例

3.1 搭建本地 Kubernetes 集群

使用 Minikube

bash
# 安装 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=4 --memory=4096

# 验证集群
kubectl cluster-info
kubectl get nodes
# NAME       STATUS   ROLES           AGE   VERSION
# minikube   Ready    control-plane   1m    v1.28.0

# 启用 Dashboard
minikube dashboard

使用 Kind(Kubernetes in Docker)

bash
# 安装 Kind
go install sigs.k8s.io/kind@latest

# 创建集群
kind create cluster --name my-cluster --config kind-config.yaml

# kind-config.yaml
# kind: Cluster
# apiVersion: kind.x-k8s.io/v1alpha4
# nodes:
#   - role: control-plane
#   - role: worker
#   - role: worker

# 验证
kubectl get nodes
# NAME                 STATUS   ROLES           AGE   VERSION
# my-cluster-control-plane  Ready    control-plane   1m    v1.28.0
# my-cluster-worker         Ready    <none>          1m    v1.28.0
# my-cluster-worker2        Ready    <none>          1m    v1.28.0

3.2 第一次部署应用

bash
# 创建 Deployment
kubectl create deployment hello --image=nginx:1.25 --replicas=3

# 查看 Deployment
kubectl get deployments
# NAME    READY   UP-TO-DATE   AVAILABLE   AGE
# hello   3/3     3            3           30s

# 查看 Pod
kubectl get pods -o wide
# NAME                     READY   STATUS    NODE
# hello-abc12-xyz1         1/1     Running   minikube
# hello-abc12-xyz2         1/1     Running   minikube
# hello-abc12-xyz3         1/1     Running   minikube

# 创建 Service
kubectl expose deployment hello --type=NodePort --port=80

# 访问应用
minikube service hello --url
# http://192.168.49.2:31234

# 扩缩容
kubectl scale deployment hello --replicas=5
kubectl get pods

# 滚动更新
kubectl set image deployment/hello hello=nginx:1.26
kubectl rollout status deployment/hello

# 回滚
kubectl rollout undo deployment/hello

3.3 使用 YAML 声明式部署

yaml
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
  labels:
    app: web-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-app
  template:
    metadata:
      labels:
        app: web-app
    spec:
      containers:
        - name: web
          image: nginx:1.25-alpine
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 200m
              memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
  name: web-app
spec:
  selector:
    app: web-app
  ports:
    - port: 80
      targetPort: 80
  type: LoadBalancer
bash
# 声明式部署
kubectl apply -f deployment.yaml

# 修改副本数后再次 apply
kubectl apply -f deployment.yaml

# 查看事件
kubectl describe deployment web-app
kubectl get events --sort-by='.lastTimestamp'

四、本章小结

第1章通过 Kubernetes 的起源、集群架构、声明式 API、核心抽象和设计哲学,为你建立了 Kubernetes 的全局视图。核心知识点包括:

Kubernetes 源自 Google Borg,继承了十多年大规模集群管理的经验,是云原生时代的操作系统。

集群由 Control Plane 和 Worker 节点组成:API Server 是统一入口,etcd 是状态存储,Scheduler 负责调度,Controller Manager 维护期望状态,kubelet 管理节点上的 Pod。

声明式 API 是核心理念:你定义"期望状态",Kubernetes 通过调谐循环自动将"实际状态"收敛到"期望状态"。

Pod 是最小调度单元,Service 提供稳定网络入口,Deployment 管理 Pod 副本和更新,Namespace 提供逻辑隔离。

设计哲学:自动化、可扩展、声明式、自愈——这些原则贯穿 Kubernetes 的每个设计决策。

后续章节将深入每个核心资源:第2章夯实容器基础,第3章实战应用部署,第4-5章深入 Pod 机制,第6章讲解控制器,第7章讨论配置管理,第8章探索持久化存储。


五、思考与练习

思考题

为什么 Kubernetes 选择 etcd 作为状态存储,而不是 MySQL 或 Redis?etcd 的 Raft 共识算法如何保证数据一致性?

声明式 API 和命令式 API 各有什么优缺点?在什么场景下你会选择命令式操作?

如果 API Server 宕机,已经运行的 Pod 会受到影响吗?为什么?

Pod 和容器的区别是什么?为什么 Kubernetes 不直接管理容器,而要引入 Pod 抽象?

Controller Manager 中的多个控制器如何避免冲突?例如,Deployment Controller 和 ReplicaSet Controller 如何协作?

练习题

使用 Minikube 或 Kind 搭建本地 K8s 集群,部署一个 Nginx 应用,并通过 Service 暴露服务。

手动删除一个 Pod,观察 ReplicaSet 的行为。解释发生了什么以及为什么。

使用 kubectl get pods -o yaml 查看 Pod 的完整 YAML,找出其中由系统自动生成的字段。

创建一个3副本的 Deployment,执行滚动更新(修改镜像版本),然后回滚到上一版本。使用 kubectl rollout history 查看更新历史。

1/8Kube
0%