返回首页返回书籍《Docker 从入门到实践》
目录

目录 · CONTENTS

  1. 01前言
  2. 02修订记录
  3. 03如何贡献
  4. 04第一章 Docker 简介
  5. 051.1 快速上手
  6. 061.2 什么是 Docker
  7. 071.3 为什么要用 Docker
  8. 08本章小结
  9. 09第二章 基本概念
  10. 102.1 镜像
  11. 112.2 容器
  12. 122.3 仓库
  13. 13本章小结
  14. 14第三章 安装 Docker
  15. 153.1 Ubuntu
  16. 163.2 Debian
  17. 173.3 Fedora
  18. 183.4 CentOS
  19. 193.5 Raspberry Pi
  20. 203.6 Linux 离线安装
  21. 213.7 macOS
  22. 223.8 Windows 10/11
  23. 233.9 镜像加速器
  24. 243.10 开启实验特性
  25. 25本章小结
  26. 26第四章 使用镜像
  27. 274.1 获取镜像
  28. 284.2 列出镜像
  29. 294.3 删除本地镜像
  30. 304.4 利用 commit 理解镜像构成
  31. 314.5 使用 Dockerfile 定制镜像
  32. 324.6 其他制作镜像的方式
  33. 334.7 实现原理
  34. 34本章小结
  35. 35第五章 操作容器
  36. 365.1 启动
  37. 375.2 守护态运行
  38. 385.3 终止
  39. 395.4 进入容器
  40. 405.5 导出和导入
  41. 415.6 删除
  42. 42本章小结
  43. 43第六章 访问仓库
  44. 446.1 Docker Hub
  45. 456.2 私有仓库
  46. 466.3 私有仓库高级配置
  47. 476.4 Nexus 3
  48. 48本章小结
  49. 49第七章 Dockerfile 指令详解
  50. 507.1 RUN 执行命令
  51. 517.2 COPY 复制文件
  52. 527.3 ADD 更高级的复制文件
  53. 537.4 CMD 容器启动命令
  54. 547.5 ENTRYPOINT 入口点
  55. 557.6 ENV 设置环境变量
  56. 567.7 ARG 构建参数
  57. 577.8 VOLUME 定义匿名卷
  58. 587.9 EXPOSE 暴露端口
  59. 597.10 WORKDIR 指定工作目录
  60. 607.11 USER 指定当前用户
  61. 617.12 HEALTHCHECK 健康检查
  62. 627.13 ONBUILD 为他人作嫁衣裳
  63. 637.14 LABEL 为镜像添加元数据
  64. 647.15 SHELL 指令
  65. 657.16 参考文档
  66. 667.17 多阶段构建
  67. 677.18 实战多阶段构建 Laravel 镜像
  68. 68本章小结
  69. 69第八章 数据管理
  70. 708.1 数据卷
  71. 718.2 挂载主机目录
  72. 728.3 tmpfs 挂载
  73. 73本章小结
  74. 74第九章 网络配置
  75. 759.1 配置 DNS
  76. 769.2 网络类型
  77. 779.3 自定义网络
  78. 789.4 容器互联
  79. 799.5 外部访问容器
  80. 809.6 网络隔离
  81. 819.7 容器网络高级特性
  82. 82本章小结
  83. 83第十章 Docker Buildx
  84. 8410.1 BuildKit
  85. 8510.2 使用 buildx 构建镜像
  86. 8610.3 使用 buildx 构建多种系统架构支持的 Docker 镜像
  87. 87本章小结
  88. 88第十一章 Docker Compose
  89. 8911.1 简介
  90. 9011.2 安装与卸载
  91. 9111.3 使用
  92. 9211.4 命令说明
  93. 9311.5 Compose 模板文件
  94. 9411.6 实战 Django
  95. 9511.7 实战 Rails
  96. 9611.8 实战 WordPress
  97. 9711.9 实战 LNMP
  98. 98本章小结
  99. 99第十二章 底层实现
  100. 10012.1 基本架构
  101. 10112.2 命名空间
  102. 10212.3 控制组
  103. 10312.4 联合文件系统
  104. 10412.5 容器格式
  105. 10512.6 网络
  106. 106本章小结
  107. 107第十三章 容器编排基础
  108. 10813.1 简介
  109. 10913.2 基本概念
  110. 11013.3 架构设计
  111. 11113.4 高级特性
  112. 11213.5 实战练习
  113. 113本章小结
  114. 114第十四章 部署 Kubernetes
  115. 11514.1 使用 kubeadm 部署 Kubernetes
  116. 11614.2 使用 kubeadm 部署 Kubernetes:使用 Docker
  117. 11714.3 在 Docker Desktop 使用
  118. 11814.4 Kind - Kubernetes IN Docker
  119. 11914.5 K3s - 轻量级 Kubernetes
  120. 12014.6 一步步部署 Kubernetes 集群
  121. 12114.7 可视化管理界面
  122. 12214.8 Kubernetes 命令行 kubectl
  123. 123本章小结
  124. 124第十五章 Etcd 项目
  125. 12515.1 简介
  126. 12615.2 安装
  127. 12715.3 集群
  128. 12815.4 使用 etcdctl
  129. 129本章小结
  130. 130第十六章 容器与云计算
  131. 13116.1 简介
  132. 13216.2 腾讯云
  133. 13316.3 阿里云
  134. 13416.4 亚马逊云
  135. 13516.5 多云部署策略
  136. 136本章小结
  137. 137第十七章 容器其他生态
  138. 13817.1 Fedora CoreOS 简介
  139. 13917.2 Fedora CoreOS 安装
  140. 14017.3 Podman - 下一代 Linux 容器工具
  141. 14117.4 Buildah - 容器镜像构建工具
  142. 14217.5 Skopeo - 容器镜像管理工具
  143. 14317.6 containerd - 核心容器运行时
  144. 14417.7 安全容器运行时
  145. 14517.8 WebAssembly 与容器
  146. 146本章小结
  147. 147第十八章 安全
  148. 14818.1 内核命名空间
  149. 14918.2 控制组
  150. 15018.3 服务端防护
  151. 15118.4 内核能力机制
  152. 15218.5 其他安全特性
  153. 15318.6 容器镜像安全扫描与供应链安全
  154. 154本章小结
  155. 155第十九章 容器监控与日志
  156. 15619.1 Prometheus
  157. 15719.2 ELK 套件
  158. 15819.3 容器性能优化与故障诊断
  159. 159本章小结
  160. 160第二十章 实战案例 - 操作系统
  161. 16120.1 Busybox
  162. 16220.2 Alpine
  163. 16320.3 Debian Ubuntu
  164. 16420.4 CentOS Fedora
  165. 165本章小结
  166. 166第二十一章 实战案例 - DevOps
  167. 16721.1 DevOps 完整工作流
  168. 16821.2 GitHub Actions
  169. 16921.3 Drone
  170. 17021.4 Drone Demo
  171. 17121.5 在 IDE 中使用 Docker
  172. 17221.6 VS Code
  173. 17321.7 实战案例:Go/Rust/数据库/微服务
  174. 174本章小结
  175. 175附录
  176. 176附录一:常见问题与错误速查
  177. 177常见错误处理
  178. 178附录二:热门镜像介绍
  179. 179Ubuntu
  180. 180CentOS
  181. 181Nginx
  182. 182PHP
  183. 183Node.js
  184. 184MySQL
  185. 185WordPress
  186. 186MongoDB
  187. 187Redis
  188. 188Minio
  189. 189附录三:Docker 命令查询
  190. 190客户端命令 - docker
  191. 191服务端命令 - dockerd
  192. 192附录四:Dockerfile 最佳实践
  193. 193附录五:如何调试 Docker
  194. 194附录六:资源链接
  195. 195附录七:术语表
  196. 196附录八:Docker 学习路线图与知识体系
第 109 / 196 节

第 109 节 · SECTION 109

13.2 基本概念

13.2 基本概念

如图 13-2 所示,Kubernetes 由控制平面与工作节点构成。

Kubernetes 基本概念示意图

图 13-2:Kubernetes 基本概念示意图

  • 节点 (Node):一个节点是一个运行 Kubernetes 中的主机。
  • 容器组 (Pod):Kubernetes 中最小的可部署和调度单元;一个 Pod 包含一个或多个紧密协作的容器,共享网络身份,并可共享一个或多个卷 (volume)。
  • 容器组生命周期 (pod-states):包含所有容器状态集合,包括容器组状态类型,容器组生命周期,事件,重启策略。
  • 服务 (services):一个 Kubernetes 服务是容器组逻辑的高级抽象,同时也对外提供访问容器组的策略。
  • 卷 (volumes):一个卷就是一个目录,容器对其有访问权限。
  • 标签 (labels):标签是用来连接一组对象的,比如容器组。标签可以被用来组织和选择子对象。
  • 接口权限 (accessing_the_api):端口,IP 地址和代理的防火墙规则。
  • web 界面 (ux):用户可以通过 Headlamp 等仍在维护的 web 界面观察和操作 Kubernetes;历史 Dashboard 已停止维护。
  • 命令行操作 (cli):kubectl 命令。

13.2.1 节点

在 Kubernetes 中,节点是实际工作的点,节点可以是虚拟机或者物理机器,依赖于一个集群环境。每个节点都有一些必要的组件以运行容器组,并且它们都可以通过控制平面来管理。必要组件包括 kubelet、容器运行时(如 containerd 或 CRI-O)和 kube-proxy;Docker 不再是 Kubernetes 节点的默认基线运行时。

容器状态

容器状态用来描述节点的当前状态。现在,其中包含三个信息:

主机 IP

主机 IP 需要云平台来查询,Kubernetes 把它作为状态的一部分来保存。如果 Kubernetes 没有运行在云平台上,节点 ID 就是必需的。IP 地址可以变化,并且可以包含多种类型的 IP 地址,如公共 IP,私有 IP,动态 IP,ipv6 等等。

节点状态

注:Pending / Running / Succeeded / Failed / Unknown 是 Pod 的生命周期阶段(pod.status.phase),不是节点状态。节点本身没有 Terminated 状态。

节点的状态通过一组条件(Conditions)来描述。主要条件包括 Ready(kubelet 健康且可以接收 Pod)、MemoryPressure(内存不足)、DiskPressure(磁盘不足)和 PIDPressure(进程数过多)等。其中 Ready 条件最为关键:值为 True 表示节点健康可调度,False 表示节点异常,Unknown 表示节点控制器超过一定时间未收到心跳。被标记为 Unknown 较长时间的节点,其上的 Pod 会被驱逐重新调度到其他节点。

节点管理

节点并非 Kubernetes 创建,而是由云平台创建,或者就是物理机器、虚拟机。在 Kubernetes 中,节点仅仅是一条记录,节点创建之后,Kubernetes 会检查其是否可用。可以通过 kubectl 查看节点信息:

$ kubectl get nodes
NAME           STATUS   ROLES           AGE   VERSION
control-plane  Ready    control-plane   10d   v1.36.0
worker-1       Ready    <none>          10d   v1.36.0
worker-2       Ready    <none>          10d   v1.36.0

每个节点的详细信息以如下结构保存:

apiVersion: v1
kind: Node
metadata:
  name: worker-1
  labels:
    kubernetes.io/os: linux
status:
  capacity:
    cpu: "4"
    memory: 8Gi
  conditions:
    - type: Ready
      status: "True"

节点控制器

在 Kubernetes 控制平面中,节点控制器 (Node Controller) 负责管理节点的生命周期,主要包含:

  • 集群范围内节点状态同步
  • 单节点生命周期管理

节点控制器会持续监控节点的健康状态。当节点变为不可达时,控制器会等待一个超时期限,然后将该节点上的 Pod 标记为失败,并触发重新调度。可以使用 kubectl 来管理节点,例如标记节点为不可调度或排空节点上的工作负载:

## 标记节点为不可调度
$ kubectl cordon worker-1

## 排空节点上的 Pod
$ kubectl drain worker-1 --ignore-daemonsets

13.2.2 容器组

在 Kubernetes 中,使用的最小调度单位是容器组 (Pod),它是创建、调度、管理的最小单位。一个 Pod 包含一个或多个紧密协作的容器,它们共享网络命名空间,并可共享一个或多个存储卷。

Pod 通常不会被直接创建,而是通过 Deployment 等控制器来管理。当节点发生故障时,控制器会在其他可用节点上重新创建 Pod。

容器组设计的初衷

容器组 (Pod) 的设计主要是为了解决应用间的紧密协作和资源共享问题。

资源共享和通信

容器组主要是为了数据共享和它们之间的通信。

在一个容器组中,容器都使用相同的网络地址和端口,可以通过本地网络来相互通信。每个容器组都有独立的 IP,可以通过网络来和其他物理主机或者容器通信。

容器组可以挂载一组存储卷(挂载点)。卷不只用于持久化,也可用于 emptyDir 临时交换、ConfigMap/Secret 投射、日志旁路收集等场景。真正需要跨 Pod 生命周期保留的数据,应使用 PersistentVolume / PersistentVolumeClaim 等持久化机制。

容器组管理

容器组是一个应用管理和部署的高层次抽象,同时也是一组容器的接口。容器组是部署、水平放缩的最小单位。

容器组的使用

容器组可以通过组合来构建复杂的应用,典型的使用模式包含:

  • 内容管理,文件和数据加载以及本地缓存管理等。
  • 日志和检查点备份,压缩,快照等。
  • 监听数据变化,跟踪日志,日志和监控代理,消息发布等。
  • 代理,网桥
  • 控制器,管理,配置以及更新

为什么不在一个容器里运行多个程序

  1. 透明化:为了使容器组中的容器保持一致的基础设施和服务,比如进程管理和资源监控。
  2. 解耦依赖:每个容器都可能独立地重新构建和发布。
  3. 方便使用:用户不必运行独立的程序管理,也不用担心每个应用程序的退出状态。
  4. 高效:考虑到基础设施有更多的职责,容器必须要轻量化。

容器组的生命状态

Pod phase 包括若干状态值:Pending、Running、Succeeded、Failed、Unknown。

状态 说明
Pending Pod 已被集群接受,但有一个或多个容器还没有运行起来(可能在拉取镜像)。
Running Pod 已被调度到节点,并且所有容器都已启动。至少有一个容器处于运行状态。
Succeeded Pod 中的所有容器都正常退出,且不会被重启。
Failed Pod 中的所有容器都已终止,且至少有一个容器以失败状态退出。
Unknown 集群无法获取 Pod 状态,常见原因是节点失联。

容器组生命周期与重启策略

Pod 的重启策略 (restartPolicy) 决定了容器退出后的行为:

重启策略 容器正常退出 容器异常退出
Always(默认) 重启容器 重启容器
OnFailure 不重启 重启容器
Never 不重启 不重启

当节点故障或不可达时,Pod 可能先表现为 Unknown,之后根据控制器、驱逐策略和垃圾回收机制转为 Failed 或被重新创建。如果这些 Pod 由 Deployment 等控制器管理,控制器会自动在其他节点上重新创建。

13.2.3 Deployment 与 ReplicaSet

Deployment 是管理无状态应用的推荐方式,它通过 ReplicaSet 来确保指定数量的 Pod 副本始终在运行。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:1.28
          ports:
            - containerPort: 80

Deployment 的核心能力包括:

  • 副本管理:确保始终有指定数量的 Pod 在运行
  • 滚动更新:逐步替换旧版本 Pod,实现零停机部署
  • 回滚:如果新版本出现问题,可以快速回滚到之前的版本

早期 Kubernetes 使用 Replication Controller (RC) 来管理副本,现已被 ReplicaSet/Deployment 取代。

13.2.4 StatefulSet

Deployment 适合无状态应用,而 StatefulSet 用于管理有状态应用(如数据库、消息队列)。与 Deployment 不同,StatefulSet 为每个 Pod 提供稳定的网络标识和持久化存储。

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.4
          volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 10Gi

StatefulSet 的核心特性:

  • 稳定的网络标识:Pod 名称按顺序编号(mysql-0, mysql-1, mysql-2),配合 Headless Service 提供可预测的 DNS 名称
  • 有序部署与删除:Pod 按序号顺序创建,逆序删除
  • 持久化存储:通过 volumeClaimTemplates 为每个 Pod 自动创建独立的 PVC

13.2.5 DaemonSet

DaemonSet 确保在集群的每个节点(或指定节点)上运行一个 Pod 副本。典型用途包括日志收集、监控代理和网络插件。

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      containers:
        - name: fluentd
          image: fluent/fluentd:v1.17
          volumeMounts:
            - name: varlog
              mountPath: /var/log
      volumes:
        - name: varlog
          hostPath:
            path: /var/log

当新节点加入集群时,DaemonSet 会自动在该节点上创建 Pod;当节点被移除时,对应的 Pod 也会被回收。

13.2.6 Job 与 CronJob

Job 用于运行一次性任务,确保指定数量的 Pod 成功完成后自动退出。CronJob 则按照 cron 表达式周期性地创建 Job。

apiVersion: batch/v1
kind: Job
metadata:
  name: data-migration
spec:
  completions: 1
  template:
    spec:
      containers:
        - name: migrate
          image: myapp/migrate:latest
          command: ["python", "migrate.py"]
      restartPolicy: Never
  backoffLimit: 3
apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-backup
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
            - name: backup
              image: myapp/backup:latest
          restartPolicy: OnFailure

Job 的 backoffLimit 控制失败重试次数,completions 指定需要成功完成的 Pod 数量。CronJob 适用于定时备份、报表生成等场景。

13.2.7 服务

服务 (Service) 定义了一组 Pod 的逻辑集合和访问策略。由于 Pod 的 IP 地址是动态分配的,Service 提供了一个稳定的访问入口。

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

常见的 Service 类型:

类型 说明
ClusterIP 默认类型,仅集群内部可访问
NodePort 在每个节点上开放固定端口,集群外部可通过 节点IP:端口 访问
LoadBalancer 通过云平台的负载均衡器暴露服务

13.2.8 卷

卷 (Volume) 为 Pod 中的容器提供持久化存储。Kubernetes 支持多种卷类型:

卷类型 说明
emptyDir 临时存储,Pod 删除后数据丢失
hostPath 挂载节点上的文件或目录
PersistentVolumeClaim 使用持久卷声明,与底层存储解耦
configMap / secret 将配置或敏感数据挂载为文件

生产环境中,推荐使用 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC) 来管理存储,实现存储资源与使用者的解耦。

13.2.9 标签

标签 (Label) 是附加到 Kubernetes 对象上的键值对,用于组织和选择对象子集。标签是 Kubernetes 中实现松耦合的关键机制。

## 为 Pod 添加标签
$ kubectl label pod my-pod env=production

## 通过标签选择器查询
$ kubectl get pods -l env=production

Service、Deployment 等资源都通过标签选择器 (selector) 来关联目标 Pod。

13.2.10 API 访问控制

Kubernetes API 的访问通过三个阶段进行控制:

  1. 认证 (Authentication):验证请求者的身份(如证书、Token、OIDC)
  2. 授权 (Authorization):判断请求者是否有权限执行操作(通常使用 RBAC)
  3. 准入控制 (Admission Control):在请求被持久化之前对其进行校验或修改

13.2.11 Dashboard

Kubernetes Dashboard 是一个基于 Web 的用户界面,用于部署容器化应用、监控集群资源和排查问题。Dashboard 的部署方法详见部署 Dashboard 章节。

13.2.12 命令行工具 kubectl

kubectl 是 Kubernetes 的命令行工具,用于与集群进行交互。常用命令如下:

## 查看集群中的资源
$ kubectl get pods,deployments,services,nodes

## 创建资源
$ kubectl apply -f deployment.yaml

## 查看 Pod 日志
$ kubectl logs my-pod

## 进入 Pod 执行命令
$ kubectl exec -it my-pod -- /bin/sh

## 查看资源详情
$ kubectl describe pod my-pod

更多 kubectl 操作详见kubectl 命令行章节。