跳转至

Kubernetes权威指南:从Docker到Kubernetes实践全接触(第4版)-龚正等

  •  Kubernetes权威指南:从Docker到Kubernetes实践全接触(第4版)|200
  • 书名: Kubernetes权威指南:从Docker到Kubernetes实践全接触(第4版)
  • 作者: 龚正等
  • 简介: Kubernetes是由谷歌开源的Docker容器集群管理系统,为容器化的应用提供了资源调度、部署运行、服务发现、扩容及缩容等一整套功能。本书从架构师、开发人员和运维人员的角度,阐述了Kubernetes的基本概念、实践指南、核心原理、开发指导、运维指南、新特性演进等内容,图文并茂、内容丰富、由浅入深、讲解全面;并围绕在生产环境中可能出现的问题,给出了大量的典型案例,比如安全配置方案、网络方案、共享存储方案、高可用方案及TroubleShooting技巧等,有很强的实战指导意义。本书内容随着Kubernetes的版本更新不断完善,目前涵盖了Kubernetes从1.0到1.14版本的主要特性,努力为Kubernetes用户提供全方位的Kubernetes技术指南。本书源码已上传至GitHub的kubeguide/K8sDefinitiveGuide-V4-Sourcecode目录,可自行下载本书源码进行练习。无论是对于软件工程师、测试工程师、运维工程师、软件架构师、技术经理,还是对于资深IT人士,本书都极具参考价值。
  • 出版时间 2019-05-01 00:00:00
  • ISBN: 9787121362354
  • 分类: 计算机-理论知识
  • 出版社: 电子工业出版社

高亮划线

封面

版权信息

作者介绍

推荐序

自序

第1章 Kubernetes入门

1.2 为什么要用Kubernetes

1.3 从一个简单的例子开始

  • 📌 spec.template.metadata. labels指定了该Pod的标签,需要特别注意的是:这里的labels必须匹配之前的spec.selector,否则此RC每创建一个无法匹配Label的Pod,就会不停地尝试创建新的Pod,陷入恶性循环中。 ^8-3155-3282

    • ⏱ 2023-02-15 13:51:54
  • 📌 根据Service的唯一名称,容器可以从环境变量中获取Service对应的Cluster IP地址和端口,从而发起TCP/IP连接请求。 ^8-6479-6547

    • ⏱ 2023-02-15 13:57:02
  • 📌 type=NodePort和nodePort=30001的两个属性表明此Service开启了NodePort方式的外网访问模式。在Kubernetes集群之外,比如在本机的浏览器里,可以通过30001这个端口访问myweb(对应到8080的虚端口上) ^8-8211-8336

    • ⏱ 2023-02-15 14:00:45

1.4 Kubernetes的基本概念和术语

  • 📌 更加优雅的做法是,先采用方法1实现这个新特性,经过几个版本的迭代,等新特性变得稳定成熟了以后,可以在后续版本中采用方法2升级到正式版。为此,Kubernetes为每个资源对象都增加了类似数据库表里备注字段的通用属性Annotations,以实现方法1的升级。 ^9-1989-2118

    • ⏱ 2023-02-15 14:15:20
  • 📌 Kubernetes集群中的其他机器被称为Node ^9-4641-4666

    • ⏱ 2023-02-15 14:17:36
  • 📌 Kubernetes要求底层网络支持集群内任意两个Pod之间的TCP/IP直接通信,这通常采用虚拟二层网络技术来实现,例如Flannel、Open vSwitch等,因此我们需要牢记一点:在Kubernetes里,一个Pod里的容器与另外主机上的Pod容器能够直接通信。 ^9-11580-11715

    • ⏱ 2023-02-15 14:29:25
  • 📌 Pod的IP加上这里的容器端口(containerPort),组成了一个新的概念——Endpoint,它代表此Pod里的一个服务进程的对外通信地址 ^9-13308-13381

    • ⏱ 2023-02-15 14:32:03
  • 📌 Pod Volume ^9-13524-13534

    • ⏱ 2023-02-15 14:40:15
  • 📌 这里顺便提一下Kubernetes的Event概念。Event是一个事件的记录,记录了事件的最早产生时间、最后重现时间、重复次数、发起者、类型,以及导致此事件的原因等众多信息。Event通常会被关联到某个具体的资源对象上,是排查故障的重要参考信息,之前我们看到Node的描述信息包括了Event,而Pod同样有Event记录,当我们发现某个Pod迟迟无法创建时,可以用kubectl describe pod xxxx来查看它的描述信息,以定位问题的成因 ^9-13642-13869

    • ⏱ 2023-02-15 14:40:26
  • 📌 对于绝大多数容器来说,一个CPU的资源配额相当大,所以在Kubernetes里通常以千分之一的CPU配额为最小单位,用m来表示。通常一个容器的CPU配额被定义为100~300m,即占用0.1~0.3个CPU。由于CPU配额是一个绝对值,所以无论在拥有一个Core的机器上,还是在拥有48个Core的机器上,100m这个配额所代表的CPU的使用量都是一样的。与CPU配额类似,Memory配额也是一个绝对值,它的单位是内存字节数 ^9-14625-14838

    • ⏱ 2023-02-15 14:41:46
  • 📌 Label(标签)是Kubernetes系统中另外一个核心概念。一个Label是一个key=value的键值对,其中key与value由用户自己指定。Label可以被附加到各种资源对象上,例如Node、Pod、Service、RC等,一个资源对象可以定义任意数量的Label,同一个Label也可以被添加到任意数量的资源对象上。Label通常在资源对象定义时确定,也可以在对象创建后动态添加或者删除。 ^9-15996-16196

    • ⏱ 2023-02-15 14:50:14
  • 📌 当前有两种Label Selector表达式:基于等式的(Equality-based)和基于集合的(Set-based),前者采用等式类表达式匹配标签,下面是一些具体的例子。 ^9-17127-17215

    • ⏱ 2023-02-15 15:42:02
  • 📌 运行在每个Node上的kube-proxy进程其实就是一个智能的软件负载均衡器,负责把对Service的请求转发到后端的某个Pod实例上,并在内部实现服务的负载均衡与会话保持机制 ^9-35984-36073

    • ⏱ 2023-02-15 16:54:09
  • 📌 而Service一旦被创建,Kubernetes就会自动为它分配一个可用的Cluster IP,而且在Service的整个生命周期内,它的Cluster IP不会发生改变。于是,服务发现这个棘手的问题在Kubernetes的架构里也得以轻松解决:只要用Service的Name与Service的Cluster IP地址做一个DNS域名映射即可完美解决问题 ^9-36313-36490

    • ⏱ 2023-02-15 16:57:23
  • 📌 目前,Kubernetes上的大部分应用都已经采用了DNS这种新兴的服务发现机制,后面会讲解如何部署DNS系统 ^9-40956-41011

    • ⏱ 2023-02-15 16:47:58
  • 📌 PV可以被理解成Kubernetes集群中的某个网络存储对应的一块存储,它与Volume类似,但有以下区别。 ^9-51731-51785

    • ⏱ 2023-02-15 17:09:29
  • 📌 accessModes属性 ^9-52653-52666

    • ⏱ 2023-02-15 17:10:13
  • 📌 接下来,Kubernetes提供了一种内建机制,将存储在etcd中的ConfigMap通过Volume映射的方式变成目标Pod内的配置文件,不管目标Pod被调度到哪台服务器上,都会完成自动映射。进一步地,如果ConfigMap中的key-value数据被修改,则映射到Pod中的“配置文件”也会随之自动更新。 ^9-57581-57735

    • ⏱ 2023-02-16 15:48:00
  • 📌 配置中心 ^9-57797-57801

    • ⏱ 2023-02-16 15:48:16

第2章 Kubernetes安装配置指南

2.2 使用kubeadm工具快速安装Kubernetes集群

2.3 以二进制文件方式安装Kubernetes集群

2.4 Kubernetes集群的安全设置

2.5 Kubernetes集群的网络配置

2.6 内网中的Kubernetes相关配置

2.7 Kubernetes的版本升级

2.8 Kubernetes核心服务配置详解

2.9 CRI(容器运行时接口)详解

2.10 kubectl命令行工具用法详解

第3章 深入掌握Pod

3.1 Pod定义详解

3.2 Pod的基本用法

  • 📌 Kubernetes系统中对长时间运行容器的要求是:其主程序需要一直在前台执行 ^22-537-576

    • ⏱ 2023-02-16 16:03:30
  • 📌 Supervisor ^22-1001-1011

    • ⏱ 2023-02-16 16:03:54

3.3 静态Pod

3.4 Pod容器共享Volume

3.5 Pod的配置管理

  • 📌 通过环境变量获取ConfigMap中的内容 ^25-16731-16752

    • ⏱ 2023-02-16 16:47:31
  • 📌 通过Volume挂载的方式将ConfigMap中的内容挂载为容器内部的文件或目录。 ^25-16785-16826

    • ⏱ 2023-02-16 16:47:35
  • 📌 envFrom ^25-19630-19637

    • ⏱ 2023-02-16 17:05:14

3.6 在容器内获取Pod信息(Downward API)

3.7 Pod生命周期和重启策略

3.8 Pod健康检查和服务可用性检查

  • 📌 对于每种探测方式,都需要设置initialDelaySeconds和timeoutSeconds两个参数,它们的含义分别如下 ^28-3615-3677
    • ⏱ 2023-02-17 10:52:22

3.9 玩转Pod调度

  • 📌 我们不应该直接使用底层的ReplicaSet来控制Pod副本,而应该使用管理ReplicaSet的Deployment对象来控制副本,这是来自官方的建议 ^29-1651-1727

    • ⏱ 2023-02-17 10:56:13
  • 📌 NodeAffinity ^29-2429-2441

    • ⏱ 2023-02-17 10:57:42
  • 📌 在Kubernates 1.9之前,在RC等对象被删除后,它们所创建的Pod副本都不会被删除;在Kubernates 1.9以后,这些Pod副本会被一并删除。如果不希望这样做,则可以通过kubectl命令的--cascade=false参数来取消这一默认特性: ^29-3491-3621

    • ⏱ 2023-02-17 11:04:54
  • 📌 需要注意的是,如果我们指定了Pod的nodeSelector条件,且在集群中不存在包含相应标签的Node,则即使在集群中还有其他可供使用的Node,这个Pod也无法被成功调度。 ^29-8729-8817

    • ⏱ 2023-02-17 11:13:14
  • 📌 这种规则可以描述为:如果在具有标签X的Node上运行了一个或者多个符合条件Y的Pod,那么Pod应该(如果是互斥的情况,那么就变成拒绝)运行在这个Node上。 ^29-12542-12621

    • ⏱ 2023-02-17 11:54:01
  • 📌 Taint则正好相反,它让Node拒绝Pod的运行。 ^29-17905-17931

    • ⏱ 2023-02-17 11:59:55

3.10 Init Container(初始化容器)

  • 📌 init container与应用容器在本质上是一样的,但它们是仅运行一次就结束的任务,并且必须在成功执行完成后,系统才能继续执行下一个容器 ^30-878-948
    • ⏱ 2023-02-17 14:15:29

3.11 Pod的升级和回滚

3.12 Pod的扩缩容

3.13 使用StatefulSet搭建MongoDB集群

第4章 深入掌握Service

4.1 Service定义详解

4.2 Service的基本用法

  • 📌 这时可以通过创建一个无Label Selector的Service来实现: ^36-7579-7616
    • ⏱ 2023-02-17 14:55:55

4.3 Headless Service

4.4 从集群外部访问Pod或Service

4.5 DNS服务搭建和配置指南

4.6 Ingress:HTTP 7层路由机制

  • 📌 从Kubernetes 1.1版本开始新增Ingress资源对象,用于将不同URL的访问请求转发到后端不同的Service,以实现HTTP层的业务路由机制 ^40-602-679
    • ⏱ 2023-12-01 15:45:03

第5章 核心组件运行机制

5.2 Controller Manager原理解析

5.3 Scheduler原理解析

5.4 kubelet运行机制解析

5.5 kube-proxy运行机制解析

第6章 深入分析集群安全机制

6.1 API Server认证管理

6.2 API Server授权管理

6.3 Admission Control

6.4 Service Account

6.5 Secret私密凭据

6.6 Pod的安全策略配置

第7章 网络原理

7.1 Kubernetes网络模型

  • 📌 IP是以Pod为单位进行分配的 ^54-654-669

    • ⏱ 2023-02-17 16:14:46
  • 📌 Pod都能够被看作一台独立的虚拟机或物理机。 ^54-1804-1826

    • ⏱ 2023-02-17 16:17:17
  • 📌 有很多开源组件可以帮助我们打通Docker容器和容器之间的网络,实现满足Kubernetes要求的网络模型。当然,每种方案都有适合的场景,我们要根据自己的实际需要进行选择。 ^54-2618-2704

    • ⏱ 2023-02-17 16:22:24

7.2 Docker网络基础

  • 📌 在Linux的网络命名空间中可以有自己独立的路由表及独立的iptables设置来提供包转发、NAT及IP包过滤等功能。 ^55-868-927

    • ⏱ 2023-02-17 16:24:39
  • 📌 物理设备(连接实际硬件的设备)通常只能关联到root这个命名空间中。虚拟的网络设备(虚拟的以太网接口或者虚拟网口对)则可以被创建并关联到一个给定的命名空间中,而且可以在这些命名空间之间移动 ^55-2108-2202

    • ⏱ 2023-02-17 16:29:10
  • 📌 Veth设备对的一个重要作用就是打通互相看不到的协议栈之间的壁垒,它就像一条管子,一端连着这个网络命名空间的协议栈,一端连着另一个网络命名空间的协议栈。所以如果想在两个命名空间之间通信,就必须有一个Veth设备对 ^55-2356-2462

    • ⏱ 2023-02-17 16:32:12
  • 📌 具体哪些设备能被转移到不同的命名空间呢?在设备里面有一个重要的属性:NETIF_F_ ETNS_LOCAL,如果这个属性为on,就不能被转移到其他命名空间中。Veth设备属于可以转移的设备,而很多其他设备如lo设备、vxlan设备、ppp设备、bridge设备等都是不可以转移的。将无法转移的设备移动到别的命名空间时,会得到无效参数的错误提示。 ^55-3373-3545

    • ⏱ 2023-02-17 16:33:59
  • 📌 在Docker的实现里面,它除了将Veth放入容器内,还将它的名字改成了eth0,简直以假乱真,你以为它是一个本地网卡吗 ^55-7543-7603

    • ⏱ 2023-02-17 16:40:29
  • 📌 一旦将Veth设备对的对端放入另一个命名空间,在本命名空间中就看不到它了。那么我们怎么知道这个Veth设备的对端在哪里呢,也就是说它到底连接到哪个命名空间呢?可以使用ethtool工具来查看(当网络命名空间特别多时,这可不是一件很容易的事情)。首先,在命名空间netns1中查询Veth设备对端接口在设备列表中的序列号: ^55-9169-9405

    • ⏱ 2023-12-01 21:41:52
  • 📌 Linux内核支持网口的桥接(目前只支持以太网接口)。但是与单纯的交换机不同,交换机只是一个二层设备,对于接收到的报文,要么转发,要么丢弃。运行着Linux内核的机器本身就是一台主机,有可能是网络报文的目的地,其收到的报文除了转发和丢弃,还可能被送到网络协议栈的上层(网络层),从而被自己(这台主机本身的协议栈)消化,所以我们既可以把网桥看作一个二层设备,也可以把它看作一个三层设备。 ^55-10613-10805

    • ⏱ 2023-12-01 21:51:49
  • 📌 如图7.3所示,网桥设备br0绑定了eth0和eth1。对于网络协议栈的上层来说,只看得到br0就行。因为桥接是在数据链路层实现的,上层不需要关心桥接的细节,所以协议栈上层需要发送的报文被送到br0,网桥设备的处理代码判断报文该被转发到eth0还是eth1,或者两者皆转发;反过来,从eth0或从eth1接收到的报文被提交给网桥的处理代码,在这里会判断报文应该被转发、丢弃还是被提交到协议栈上层。 ^55-11271-11469

    • ⏱ 2023-12-01 21:57:53
  • 📌 Netfilter负责在内核中执行各种挂接的规则,运行在内核模式中;而iptables是在用户模式下运行的进程,负责协助和维护内核中Netfilter的各种规则表。二者互相配合来实现整个Linux网络协议栈中灵活的数据包处理机制。 ^55-12706-12821

    • ⏱ 2023-12-01 22:02:44
  • 📌 当Linux协议栈的数据处理运行到挂接点时,它会依次调用挂接点上所有的挂钩函数,直到数据包的处理结果是明确地接受或者拒绝 ^55-13805-13865

    • ⏱ 2023-02-17 17:29:18
  • 📌 在通常情况下,如果主机与目的主机直接相连,那么主机可以直接发送IP报文到目的主机,这个过程比较简单。例如,通过点对点的链接或网络共享,如果主机与目的主机没有直接相连,那么主机会将IP报文发送给默认的路由器,然后由路由器来决定往哪里发送IP报文。 ^55-15148-15270

    • ⏱ 2023-12-01 22:04:36
  • 📌 当从网络侧接收到数据报文时,IP层首先会检查报文的IP地址是否与主机自身的地址相同。如果数据报文中的IP地址是主机自身的地址,那么报文将被发送到传输层相应的协议中。如果报文中的IP地址不是主机自身的地址,并且主机配置了路由功能,那么报文将被转发,否则,报文将被丢弃。 ^55-15348-15481

    • ⏱ 2023-12-01 22:06:47

7.3 Docker的网络实现

  • 📌 在Kubernetes管理模式下通常只会使用bridge模式,所以本节只介绍在bridge模式下Docker是如何支持网络的。 ^56-726-789
    • ⏱ 2023-02-17 17:32:44

7.4 Kubernetes的网络实现

  • 📌 Pod的地址是与docker0在同一个网段的,我们知道docker0网段与宿主机网卡是两个完全不同的IP网段,并且不同Node之间的通信只能通过宿主机的物理网卡进行,因此要想实现不同Node上Pod容器之间的通信,就必须想办法通过主机的这个IP地址进行寻址和通信 ^57-2902-3033

    • ⏱ 2023-12-01 23:02:27
  • 📌 综上所述,要想支持不同Node上Pod之间的通信,就要满足两个条件:(1)在整个Kubernetes集群中对Pod的IP分配进行规划,不能有冲突;(2)找到一种办法,将Pod的IP和所在Node的IP关联起来,通过这个关联让Pod可以互相访问 ^57-3394-3573

    • ⏱ 2023-12-01 23:06:10

7.5 Pod和Service网络实战

  • 📌 在部署了一个Pod时,在同一个集群内,各主机都可以访问其他主机上的Pod IP,并不需要在主机上做端口映射 ^58-1556-1609

    • ⏱ 2023-02-17 17:57:20
  • 📌 这个IP段可以是任何段,只要不和docker0或者物理网络的子网冲突就可以 ^58-13763-13800

    • ⏱ 2023-02-17 18:09:14
  • 📌 选择任意其他网段的原因是这个网段将不会在物理网络和docker0网络上进行路由。 ^58-13801-13841

    • ⏱ 2023-02-17 18:09:39
  • 📌 这个kube-proxy服务给每一个新创建的服务都关联了一个随机的端口号,并且监听那个特定的端口,为服务创建相关的负载均衡对象 ^58-14771-14834

    • ⏱ 2023-02-17 18:12:17
  • 📌 现在我们知道,所有流量都被导入kube-proxy中了 ^58-15246-15273

    • ⏱ 2023-02-17 18:15:33

7.6 CNI网络模型

7.7 Kubernetes网络策略

7.8 开源的网络组件

第8章 共享存储原理

  • 📌 PV由管理员创建和配置,它与共享存储的具体实现直接相关,例如GlusterFS、iSCSI、RBD或GCE或AWS公有云提供的共享存储,通过插件式的机制完成与共享存储的对接,以供应用访问和使用 ^62-860-956

    • ⏱ 2023-02-22 11:23:03
  • 📌 PVC则是用户对存储资源的一个“申请” ^62-986-1005

    • ⏱ 2023-02-22 11:23:11
  • 📌 Kubernetes从1.4版本开始引入了一个新的资源对象StorageClass,用于标记存储资源的特性和性能。到1.6版本时,StorageClass和动态资源供应的机制得到了完善,实现了存储卷的按需创建,在共享存储的自动化管理进程中实现了重要的一步。 ^62-1173-1301

    • ⏱ 2023-02-22 11:23:59
  • 📌 (CSI) ^62-1571-1576

    • ⏱ 2023-02-22 11:26:09

8.2 PV详解

  • 📌 PV可以设定其存储的类别,通过storageClassName参数指定一个StorageClass资源对象的名称。具有特定类别的PV只能与请求了该类别的PVC进行绑定。未设定类别的PV则只能与不请求任何类别的PVC进行绑定。 ^63-4707-4819
    • ⏱ 2023-02-22 11:36:38

8.3 PVC详解

  • 📌 PVC也可以不设置Class需求。如果storageClassName字段的值被设置为空(storageClassName=""),则表示该PVC不要求特定的Class,系统将只选择未设定Class的PV与之匹配和绑定。PVC也可以完全不设置storageClassName字段,此时将根据系统是否启用了名为DefaultStorageClass的admission controller进行相应的操作。 ^64-1871-2073

    • ⏱ 2023-11-30 19:12:05
  • 📌 注意,PVC和PV都受限于Namespace,PVC在选择PV时受到Namespace的限制,只有相同Namespace中的PV才可能与PVC绑定。Pod在引用PVC时同样受Namespace的限制,只有相同Namespace中的PVC才能挂载到Pod内。 ^64-2601-2729

    • ⏱ 2023-11-30 19:14:48
  • 📌 在启用动态供应模式的情况下,一旦用户删除了PVC,与之绑定的PV也将根据其默认的回收策略“Delete”被删除。如果需要保留PV(用户数据),则在动态绑定成功后,用户需要将系统自动生成PV的回收策略从“Delete”改成“Retain”。 ^64-2956-3075

    • ⏱ 2023-11-30 19:15:43

8.4 PV和PVC的生命周期

  • 📌 PVC可以声明Class为"",说明该PVC禁止使用动态模式。 ^65-1145-1176

    • ⏱ 2023-02-22 17:22:17
  • 📌 PV。PV一旦绑定到某个PVC上,就会被这个PVC独占,不能再与其他PVC进行绑定了 ^65-1428-1470

    • ⏱ 2023-11-30 19:17:41
  • 📌 。在这种情况下,当PVC申请的存储空间比PV的少时,整个PV的空间就都能够为PVC所用,可能会造成资源的浪费。如果资源供应使用的是动态模式,则系统在为PVC找到合适的StorageClass后,将自动创建一个PV并完成与PVC的绑定。 ^65-1470-1587

    • ⏱ 2023-11-30 19:18:24
  • 📌 当用户对存储资源使用完毕后,用户可以删除PVC,与该PVC绑定的PV将会被标记为“已释放”,但还不能立刻与其他PVC进行绑定。通过之前PVC写入的数据可能还被留在存储设备上,只有在清除之后该PV才能再次使用。 ^65-1919-2023

    • ⏱ 2023-11-30 19:19:43

8.5 StorageClass详解

8.6 动态存储管理实战:GlusterFS

8.7 CSI存储机制详解

第9章 Kubernetes开发指南

9.1 REST简述

9.2 Kubernetes API详解

9.3 使用Java程序访问Kubernetes API

9.4 Kubernetes API的扩展

第10章 Kubernetes集群管理

10.2 更新资源对象的Label

10.3 Namespace:集群环境共享与隔离

10.4 Kubernetes资源管理

10.5 资源紧缺时的Pod驱逐机制

10.6 Pod Disruption Budget(主动驱逐保护)

10.7 Kubernetes集群的高可用部署方案

10.8 Kubernetes集群监控

10.9 集群统一日志管理

10.10 Kubernetes的审计机制

10.11 使用Web UI(Dashboard)管理集群

10.12 Helm:Kubernetes应用包管理工具

第11章 Trouble Shooting指导

11.1 查看系统Event

11.2 查看容器日志

11.3 查看Kubernetes服务日志

11.4 常见问题

11.5 寻求帮助

第12章 Kubernetes开发中的新功能

12.1 对Windows容器的支持

12.2 对GPU的支持

12.3 Pod的垂直扩缩容

12.4 Kubernetes的演进路线和开发模式

专家评价

读书笔记

本书评论