k8s对象 pod

PodKubernetes 应用程序的基本执行单元,即它是 Kubernetes 对象模型中创建或部署的最小和最简单的单元。

容器设计模式

云原生应用运行的环境都是复杂的分布式环境,目前 K8s 社区推出的容器设计模式主要分为三大类:

  • 单容器管理模式

  • 单节点多容器模式

  • 多节点多容器模式

  • 运行单个容器的 Pod —— 支持多容器的微服务实例

    • 每个 Pod 一个容器的模型是最常见的使用情况,在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
  • 运行多个协同工作的容器的 Pod —— 基于多容器微服务模型的分布式应用模型

    基于多容器微服务模型的分布式应用模型

    • Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序,Pod 将这些容器和存储资源打包为一个可管理的实体。
  • 分布式系统工具包:容器组合的模式 ——有状态服务水平扩展

    • 即将多个服务同时封装到同一个 Pod 中,对外提供服务,而不再需要用户手动安装其他服务或者工具,真正做到即时即用的便捷效果。
1
2
3
4
5
6
7
8
9
10
11
12
# 通过定义清单文件创建Pod
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
    - name: myapp-container
      image: busybox
      command: ["sh", "-c", "echo Hello Kubernetes! && sleep 3600"]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 通过定义清单文件创建Pod
apiVersion: v1
kind: Pod
  metadata:
  name: pod-demo
  namespace: default
  labels:
    app: myapp
spec:
  containers:
    - name: myapp-1
      image: hub.escapelife.site/library/nginx-test:v1
    - name: busybox-1
      image: busybox:latest
      command:
        - "/bin/sh"
        - "-c"
        - "sleep 3600"

pod 控制器

我们很少会直接在 kubernetes 中创建单个 Pod。因为 Pod 的生命周期是短暂的,用后即焚的实体。当 Pod 被创建后,都会被 Kubernetes 调度到集群的 Node 上。直到 Pod 的进程终止、被删掉、因为缺少资源而被驱逐、或者 Node 故障之前这个 Pod 都会一直保持在那个 Node 上。

我们需要知道 Pod 本身是不会自愈修复的。如果 Pod 运行的 Node 故障或者是调度器本身故障,这个 Pod 就会被删除。同样的,如果 Pod 所在 Node 因为缺少资源或者 Pod 处于维护状态,那么 Pod 也就会被自动驱逐掉。

Kubernetes 使用更高级的称为 Controller 的抽象层,来管理 Pod 实例。虽然可以直接使用 Pod,但是在 Kubernetes 中通常是使用 Controller 来管理 Pod 的。Controller 可以创建和管理多个 Pod,提供副本管理、滚动升级和集群级别的自愈能力。

需要注意的是,重启 Pod 中的容器跟重启 Pod 不是一回事。Pod 只提供容器的运行环境并保持容器的运行状态,重启容器不会造成 Pod 重启。

Kubernetes 使用了一个更高级的称为 控制器 的抽象,由它处理相对可丢弃的 Pod 实例的管理工作。因此,虽然可以直接使用 Pod,但在 Kubernetes 中,更为常见的是使用控制器管理 Pod。

  • Deployment
  • StatefulSet
  • DaemonSet

pod 结构

Pod 代表着集群中运行的进程:共享网络、共享存储

Pod 中其实可以同时运行一个或者多个容器,这些容器能够共享网络存储以及 CPU/内存等资源。

首先,我们需要知道的是,每个 Pod 都有一个特殊的被称为 “根容器”Pause 容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,通过 Pause 容器使工作在对应 Pod 的容器之间可以共享网络共享存储

image-20211016195805541

pod 共享

why use pause

使用 Pause 容器作为 Pod 根容器,以它的状态代表整个容器组的状态;其次,Pod 里的多个业务容器共享 Pause 容器的 IP 地址,共享 Pause 容器挂接的 Volume 资源。

  • 共享存储资源

可以为一个 Pod 指定多个共享的 Volume 资源。Pod 中的所有容器都可以访问共享的 volume 资源。Volume 也可以用来持久化 Pod 中的存储资源,以防容器重启后文件丢失。

  • 共享网络资源

    每个 Pod 都会被分配一个唯一的 IP 地址。Pod 中的所有容器共享网络空间,包括 IP 地址和端口。Pod 内部的容器可以使用 localhost 互相通信。Pod 中的容器与外界通信时,必须分配共享网络资源,例如使用宿主机的端口映射。

    • 同一个 Pod 内多个容器之前通过回环网络(lo - 127.0.0.1)进行通信
    • Pod 之间的通讯,则是通过 Overlay Network 网络进行通信
    • PodService 之间的通讯,则是各节点的 iptableslvs 规则
  • 不同情况下网络通信方式

    • 同一个 Pod 内部通讯:
      • 同一个 Pod 共享同一个网络命名空间,共享同一个 Linux 协议栈。
    • 不同 Pod 之间通讯:
      • Pod1 和 Pod2 在同一台 Node 主机,由 docker0 网桥直接转发请求到 Pod2 上面,不经过 Flannel 的转发。
      • Pod1 和 Pod2 不在同一台 Node 主机,Pod 的地址是与 docker0 在同一个网段的,但 docker0 网络与宿主机网卡是两个完全不同的 IP 网段,并且不同的 Node 之间的通讯只能通过宿主机的物理网卡进行。将 Pod 的 IP 地址和所在 Node 的 IP 地址关联起来,通过这个关联让 Pod 可以互相访问。
    • Pod 至 Service 的网络
      • 目前基于性能考虑,全部为 iptables 或 lvs 维护和转发。
    • Pod 到外网
      • Pod 想外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主机网卡完成路由选择之后,iptables 或 lvs 执行 Masquerade,把源 IP 地址更改为宿主机的网卡的 IP 地址,然后向外网服务器发送请求。
    • 外网访问 Pod
      • 通过 Service 服务来向外部提供 Pod 服务。

Fannel

FlannelCoreOS 团队针对 Kubernetes 设计的一个网络规划服务,简单来说,它的功能就是让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。而且它还能在这些 IP 地址之间建立一个覆盖的网络(Overlay Network),通过这个覆盖网络,将数据包原封不动地传递给目标容器内。

Overlay Network 网络进行通信

Overlay Network 网络进行通信

数据包原封格式

Flannel利用ETCD:

  • 存储管理 Flannel 可分配的 IP 地址段资源
  • 监控 ETCD 中每一个 Pod 的实际 IP 地址,并在内存中建立维护 Pod 节点的路由表

ETCD之于Flannel提供说明

veth 设备的特点

一个设备收到协议栈的数据发送请求后,会将数据发送到另一个设备上去

  • veth 和其它的网络设备都一样,一端连接的是内核协议栈
  • veth 设备是成对出现的,另一端两个设备彼此相连
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 物理网卡eth0配置的IP为192.168.1.11
# 而veth0和veth1的IP分别是192.168.2.11和192.168.2.10

+----------------------------------------------------------------+
|                                                                |
|       +------------------------------------------------+       |
|       |             Network Protocol Stack             |       |
|       +------------------------------------------------+       |
|              ↑               ↑               ↑                 |
|..............|...............|...............|.................|
|              ↓               ↓               ↓                 |
|        +----------+    +-----------+   +-----------+           |
|        |   eth0   |    |   veth0   |   |   veth1   |           |
|        +----------+    +-----------+   +-----------+           |
|192.168.1.11  ↑               ↑               ↑                 |
|              |               +---------------+                 |
|              |         192.168.2.11     192.168.2.10           |
+--------------|-------------------------------------------------+
               ↓
         Physical Network

不同类型的pod

  • ReplicationController

ReplicationController 用来确保容器应用的副本数量始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的 Pod 来代替,而如果异常多出现的容器会自动回收。

  • ReplicaSet

在新版本(相对而言的较优方式)的 Kubernetes 中建议使用 ReplicaSet 来取代 ReplicationController 来管理 Pod。虽然 ReplicaSetReplicationController 并没有本质上的不同,只是名字不一样而已,唯一的区别就是 ReplicaSet 支持集合式的 selector,可供标签筛选。

虽然 ReplicaSet 可以独立使用,但一般还是建议使用 Deployment 来自动管理 ReplicaSet 创建的 Pod,这样就无需担心跟其他机制的不兼容问题。比如 ReplicaSet 自身并不支持滚动更新(rolling-update),但是使用 Deployment 来部署就原生支持。

  • Deployment

DeploymentPodReplicaSet 提供了一个声明式定义方法,用来替代以前使用 ReplicationController 来方便且便捷的管理应用。主要的应用场景,包括:滚动升级和回滚应用扩容和缩容暂停和继续

  • HPA

HPA 仅仅适用于 DeploymentReplicaSet,在 V1 版本中仅支持根据 PodCPU 利用率扩缩容,在新版本中,支持根据内存和用户自定义的 metric 动态扩缩容。

  • StatefulSet

StatefulSet 是为了解决有状态服务的问题,相对于 DeploymentReplicaSet 而已。其主要的使用场景,包括:稳定的持久化存储、稳定的网络标识、有序部署、有序收缩。

  • DaemonSet

DaemonSet 确保全部或者一些 Node 上面运行一个 Pod 副本。当有 Node 加入集群的时候,也会为它们新加一个 Pod。当有 Node 从集群中移除的时候,这些 Pod 也会被回收。删除 DaemonSet 将会删除它所创建的所有 Pod

使用 DaemonSet 的典型场景就是,在每个节点运行日志收集、运行监控系统、运行集群存储等服务,只要新加进来的节点都需要运行该服务。

  • Job

Job 负责批处理任务,仅执行一次的任务,它保证批处理任务的一个或者多个 Pod 成功结束,才会返回成功。

  • Cron Job

Cron Job 管理是基于时间的 Job,即在给定时间点只运行一次,且周期行的在给定时间点运行特定任务。

pod 生命周期

Kubernetes 中的基本组件 kube-controller-manager 就是用来控制 Pod 的状态和生命周期的

Kubernetes的资源清单

在 Pod 重新启动时, init container 将会重新运行,常见的 Pod 重启场景如下 。

  • init container的镜像被更新时, init container将会重新运行,导致 Pod重启。 仅更新应用容器的镜像只会使得应用容器被重启。
  • Pod 的 pause 容器更新时, Pod 将会重启。
  • 若 Pod 中的所有应用容器都终止了,并且 RestartPolicy=Always, 则 Pod会重启 。

Pause 容器

让一个 Pod 里的多个容器之间最高效的共享某些资源和数据。

因为容器之间原本是被 Linux Namespace 和 cgroups 隔开的,所以现在实际要解决的是怎么去打破这个隔离,然后共享某些事情和某些信息。这就是 Pod 的设计要解决的核心问题所在。

由于有了这样一个 Infra container 之后,其他所有容器都会通过 Join Namespace 的方式加入到 Infra container 的 Network Namespace 中。

所以说一个 Pod 里面的所有容器,它们看到的网络视图是完全一样的。即:它们看到的网络设备、IP 地址、Mac 地址等等,跟网络相关的信息,其实全是一份,这一份都来自于 Pod 第一次创建的这个 Infra container。这就是 Pod 解决网络共享的一个解法。

在 Pod 里面,一定有一个 IP 地址,是这个 Pod 的 Network Namespace 对应的地址,也是这个 Infra container 的 IP 地址。所以大家看到的都是一份,而其他所有网络资源,都是一个 Pod 一份,并且被 Pod 中的所有容器共享。这就是 Pod 的网络实现方式。

由于需要有一个相当于说中间的容器存在,所以整个 Pod 里面,必然是 Infra container 第一个启动。并且整个 Pod 的生命周期是等同于 Infra container 的生命周期的,与容器 A 和 B 是无关的。这也是为什么在 Kubernetes 里面,它是允许去单独更新 Pod 里的某一个镜像的,即:做这个操作,整个 Pod 不会重建,也不会重启,这是非常重要的一个设计。

主要作用

kubernetes 中的 pause 容器主要为每个业务容器提供以下功能:

  • 在 pod 中担任 Linux 命名空间共享的基础;
  • 启用 pid 命名空间,开启 init 进程。

了解 Init 容器

我们知道 Pod 可以包含多个容器,应用运行在这些容器里面,同时 Pod 也可以有一个或多个先于应用容器启动的 Init 容器

对比应用容器

  • Init 容器支持应用容器的全部字段和特性,包括资源限制、数据卷和安全设置,
  • 不支持 Readiness Probe,因为它们必须在 Pod 就绪之前运行完成。

  • Init 容器总是运行到完成为止。
  • 多个 Init 容器,这些容器会按顺序逐个运行。

Pod 内设置的 Init 容器运行失败了,那么 Kubernetes 就会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的重启策略 restartPolicy 的值为 Never,它不会重新启动。如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时,Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。

资源限制

在 init container 的定义中也可以设置资源限制、 Volume 的使用和安全策略,等等 。 但资源限制的设置与应用容器略有不同 。

  • 如果多个 init container 都定义了资源请求 /资源限制,则取最大的值作为所有 init container 的资源请求值/资源限制值 。

  • Pod的有效(effective)资源诮求值/资源限制值取以下二者中的较大值:

    max(所有应用容器的资源请求值/资源限制值之和, init container 的有效资源请求值/资源限制值 )。

  • 调度算法将基千 Pod 的有效资源请求值 /资源限制值进行计算,也就是说 init container 可以为 初始化操作预留系统资源,即使后续应用容器无须使用这些资源。

  • Pod 的有效 QoS 等级适用于 init container 和应用容器 。

  • 资 源配额和限制将根据 Pod 的有效资源诮求值/资源限制值计算生效 。

  • Pod 级别的 cgroup 将基千 Pod 的有效 资源请求/限制 ,与 调度机制一致。

init container不能设置 readinessProbe探针,因为必须在它们成功运行后才能继续 运行在 Pod 中定义的普通容器

因为 Init 容器具有与应用容器分离的单独镜像,其启动相关代码具有如下优势:

  • Init 容器可以包含一些安装过程中应用容器中不存在的实用工具或个性化代码。例如,没有必要仅为了在安装过程中使用类似 sed、 awk、 python 或 dig 这样的工具而去 FROM 一个镜像来生成一个新的镜像。
  • Init 容器可以安全地运行这些工具,避免这些工具导致应用镜像的安全性降低。应用镜像的创建者和部署者可以各自独立工作,而没有必要联合构建一个单独的应用镜像。
  • Init 容器能以不同于 Pod 内应用容器的文件系统视图运行。因此,Init 容器可具有访问 Secrets 的权限,而应用容器不能够访问。
  • 由于 Init 容器必须在应用容器启动之前运行完成,因此 Init 容器提供了一种机制来阻塞或延迟应用容器的启动,直到满足了一组先决条件。一旦前置条件满足,Pod 内的所有的应用容器会并行启动。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 启动Pod
$ kubectl apply -f myapp.yaml
pod/myapp-pod created

# 检查Pod状态
$ kubectl get -f myapp.yaml
NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

# 如需更详细的信息
$ kubectl describe -f myapp.yaml

# 如需查看Pod内Init容器的日志
$ kubectl logs myapp-pod -c init-myservice
$ kubectl logs myapp-pod -c init-mydb

# 创建mydb和myservice
$ kubectl create -f services.yaml
service "myservice" created
service "mydb" created

# 查看Pod状态
$ kubectl get -f myapp.yaml
NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

状态和策略

状态值

Pod 的 status 定义在 PodStatus 对象中,其中有一个 phase 字段。Pod 的运行阶段(phase)中其生命周期中的简单宏观概述。该阶段并不是对容器或 Pod 的综合汇总,也不是为了做为综合状态机。下面是 phase 可能的值:

状态值 描述
Pending API Server 已经创建该 Pod,但还有一个或多个容器的镜像没有创建成功,如下载镜像等状态
Running Pod 内所有容器均已创建,且至少有一个容器处于运行状态、正在启动或正在重启状态
Succeeded Pod 内所有容器均已成功执行退出,且不会再重启
Failed Pod 内所有容器均已退出,但至少有一个容器退出为失败状态
Unknown 由于某种原因无法获取该 Pod 的状态,可能由于网络通信不畅导致

重启策略

Pod 重启策略 RestartPolicy 应用于 Pod 内的所有容器,并且仅在 Pod 所处的 Node 上由 kubelet 进行判断和重启操作。当某个容器异常退出或者健康检查失败时,kubelet 将根据 RestartPolicy 的设置来进行相应的操作。Pod 的重启策略包括 Always、OnFailure 和 Never 三种,默认值为 Always。

kubelet 重启失效容器的时间间隔以 sync-frequency 乘以 2n 来计算,例如 1、2、4 等,最长延时 5min,并且在成功重启后的 10min 后重置该时间。

重启策略 描述
Always 当容器失效时,由 kubelet 自动重启该容器
OnFailure 当容器终止运行切退出代码不为 0 时,由 kubelet 自动重启该容器
Never 不论容器运行状态如何,kubelet 都不会重启该容器

image-20220417195113675

kubelet 会定期执行这两类探针来诊断容器的健康状况。

( l ) LivenessProbe 探针:用千判断容器是否存活 ( Running 状态 ),如果 LivenessProbe 探针探测到容器不健康 ,则 kubelet 将“杀掉”该容器,并根据容器的重启策略做相 应的 处理 。 如果一个容器不包含 LivenessProbe 探针,那么 kubelet 认为该容器的 LivenessProbe 探针返回的值永远是 Success。

(2) ReadinessProbe 探针:用于判断容器服务是否可用 ( Ready 状态 ),达到 Ready 状 态的 Pod 才可以接收请求。对于被 Service 管理的 Pod, Service 与 Pod Endpoint 的关联关 系也将基于 Pod 是否 Ready 进行设置 。 如果在运行过程中 Ready 状态变为 False, 则系统

自动将其从 Service 的后端 Endpoint 列表中隔离出去,后续再把恢复到 Ready 状态的 Pod 加回后端 Endpoint 列表 。 这样就能保证客户端在访问 Service 时不会被转发到服务不可用 的 Pod 实例上 。需 要注意的是, ReadinessProbe 也是定期触发执行的,存在于 Pod 的整个 生命周期中 。

(3) StartupProbe 探针:某些 应用会遇到启动比较慢的情况,例如应用程序启动时需 要与远程服务器建立网络连接,或者遇到网络访问较慢等情况时,会造成容器启动缓慢, 此时 ReadinessProbe 就不适用了,因为这属千“有且仅有一次”的超长延时,可以通过 StartupProbe 探针解决该问题 。

pod 配置

pod控制器

  • ReplicationController
  • ReplicaSet
  • Deployment
  • DaemonSet
  • StateFulSet
  • Job
  • CronJob
  • Horizontal Pod Autoscaling

Pod 模板

.spec.template

书写配置文件的时候,.spec.template 是一个 pod 模板,它的模式与 pod 完全相同,只是它是嵌套的,没有 apiVersion 或 kind 属性。

设置标签

  • 优先级高 => .metadata.labels
  • 优先级低 => .spec.template.metadata.labels
  • 没有指定 .metadata.labels 则默认为 .spec.template.metadata.labels

控制器本身是可以设置标签的,用于做分类或者控制选择时使用。

Pod 选择器

  • .spec.selector
  • .spec.template.metadata.labels

没有指定 .spec.selector 则默认为 .spec.template.metadata.labels 其中 .spec.selector 字段是一个标签选择器,所创建出来的标签用于选择则出匹配的 Pod。如果指定了 .spec.template.metadata.labels 字段,则必须和 .spec.selector 字段相同,否则在创建的时候将会被 API 拒绝。

多个副本

  • .spec.replicas

可以通过设置 .spec.replicas 来指定应该同时运行多少个 Pod。在任何时候,处于运行状态的 Pod 个数都可能高于或者低于设定值。例如副本个数刚刚被增加或减少时,或者一个 pod 处于优雅终止过程中而其替代副本已经提前开始创建时。如果没有指定 .spec.replicas,那么它默认是 1 个。

补充

概念

image-20211205113232391

image-20211205113111520

image-20211205113319583

为什么pod是必须的

container之间需要相互依赖,必须同一机器共享某些信息,解决超亲密关系统一调度

各自为政的话

  • 启动先后顺序,效率慢,互相等造成死锁

image-20211205113129445

如何决定pod有多少container

image-20211205113449553

容器设计模式

image-20211205120009967

可以使用init cointainer引入需要的资源

image-20211205121137066

这是一个通过组合两个不同角色的容器,并且按照这样一些像 Init Container 这样一种编排方式,统一的去打包这样一个应用,把它用 Pod 来去做的非常典型的一个例子。像这样的一个概念,在 Kubernetes 里面就是一个非常经典的容器设计模式,叫做Sidecar

image-20211205121254865

其实在 Pod 里面,可以定义一些专门的容器,来执行主业务容器所需要的一些辅助工作,比如我们前面举的例子,其实就干了一个事儿,这个 Init Container,它就是一个 Sidecar,它只负责把镜像里的 WAR 包拷贝到共享目录里面,以便被 Tomcat 能够用起来。

其它有哪些操作呢?比如说:

  • 原本需要在容器里面执行 SSH 需要干的一些事情,可以写脚本、一些前置的条件,其实都可以通过像 Init Container 或者另外像 Sidecar 的方式去解决;

  • 当然还有一个典型例子就是我的日志收集,日志收集本身是一个进程,是一个小容器,那么就可以把它打包进 Pod 里面去做这个收集工作;

  • 还有一个非常重要的东西就是 Debug 应用,实际上现在 Debug 整个应用都可以在应用 Pod 里面再次定义一个额外的小的 Container,它可以去 exec 应用 pod 的 namespace;

  • 查看其他容器的工作状态,这也是它可以做的事情。不再需要去 SSH 登陆到容器里去看,只要把监控组件装到额外的小容器里面就可以了,然后把它作为一个 Sidecar 启动起来,跟主业务容器进行协作,所以同样业务监控也都可以通过 Sidecar 方式来去做。

这种做法一个非常明显的优势就是在于其实将辅助功能从我的业务容器解耦了,所以我就能够独立发布 Sidecar 容器,并且更重要的是这个能力是可以重用的,即同样的一个监控 Sidecar 或者日志 Sidecar,可以被全公司的人共用的。这就是设计模式的一个威力。

sidecar 应用场景

  • Sidecar:应用与日志收集

    业务容器将日志写在一个 Volume 里面,而由于 Volume 在 Pod 里面是被共享的,所以日志容器 —— 即 Sidecar 容器一定可以通过共享该 Volume,直接把日志文件读出来,然后存到远程存储里面,或者转发到另外一个例子。现在业界常用的 Fluentd 日志进程或日志组件,基本上都是这样的工作方式。

    image-20211205122152039

  • 代理容器 Proxy

    假如现在有个 Pod 需要访问一个外部系统,或者一些外部服务,但是这些外部系统是一个集群,那么这个时候如何通过一个统一的、简单的方式,用一个 IP 地址,就把这些集群都访问到?有一种方法就是:修改代码。因为代码里记录了这些集群的地址;另外还有一种解耦的方法,即通过 Sidecar 代理容器。

    简单说,单独写一个这么小的 Proxy,用来处理对接外部的服务集群,它对外暴露出来只有一个 IP 地址就可以了。所以接下来,业务容器主要访问 Proxy,然后由 Proxy 去连接这些服务集群,这里的关键在于 Pod 里面多个容器是通过 localhost 直接通信的,因为它们同属于一个 network Namespace,网络视图都一样,所以它们俩通信 localhost,并没有性能损耗。

    image-20211205122329732

  • 适配器容器 Adapter

    现在业务暴露出来的 API,比如说有个 API 的一个格式是 A,但是现在有一个外部系统要去访问我的业务容器,它只知道的一种格式是 API B ,所以要做一个工作,就是把业务容器怎么想办法改掉,要去改业务代码。但实际上,你可以通过一个 Adapter 帮你来做这层转换。

    image-20211205122856115

元数据

label

标签主要用来筛选资源和组合资源,可以使用类似于 SQL 查询 select,来根据 Label 查询相关的资源。

image-20211212170830168

Annotations

一般是系统或者工具用来存储资源的非标示性信息,可以用来扩展资源的 spec/status 的描述

image-20211212171548248

Ownereference

所谓所有者,一般就是指集合类的资源,比如说 Pod 集合,就有 replicaset、statefulset,这个将在后序的课程中讲到。

集合类资源的控制器会创建对应的归属资源。比如:replicaset 控制器在操作中会创建 Pod,被创建 Pod 的 Ownereference 就指向了创建 Pod 的 replicaset,Ownereference 使得用户可以方便地查找一个创建资源的对象,另外,还可以用来实现级联删除的效果。

容器里面获取pod信息(Downward API)

Pod 的 逻辑概念在容器之上, Kubemetes 在成功创建 Pod 之后,会为 Pod 和容器设置一些额外的信息,例如 Pod 级别的 Pod 名称、Pod IP、Node IP、Label、Annotation、 容器级别的资源限制等。

Downward API 可以通过以下两种方式将 Pod 和容器的元数据信息注人容器内部 。

  • 环境变量 : 将 Pod 或 Container 信息设置为容器内的环境变量 。
  • Volume 挂载 : 将 Pod 或 Container 信息以文件的形式挂载到容器内部 。

env 原数据

image-20220417141524777

image-20220417141558209

env resource

image-20220417141730368

image-20220417141742835

Volume metedata

image-20220417141939715

image-20220417142028070

Volume resource

image-20220417142142036

image-20220417142200370

静态pod

静态 Pod 直接由特定节点上的kubelet进程来管理,不通过 master 节点上的apiserver。无法与我们常用的控制器Deployment或者DaemonSet进行关联,它由kubelet进程自己来监控,当pod崩溃时重启该podkubelete也无法对他们进行健康检查。

静态 pod 始终绑定在某一个kubelet,并且始终运行在同一个节点上。

kubelet会自动为每一个静态 pod 在 Kubernetes 的 apiserver 上创建一个镜像 Pod(Mirror Pod),因此我们可以在 apiserver 中查询到该 pod,但是不能通过 apiserver 进行控制(例如不能删除)。

配置文件

比如我们在 node01 这个节点上用静态 pod 的方式来启动一个 nginx 的服务。我们登录到node01节点上面,可以通过下面命令找到kubelet对应的启动配置文件

1
$ systemctl status kubelet

配置文件路径为:

1
$ /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

打开这个文件我们可以看到其中有一条如下的环境变量配置: Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"

所以如果我们通过kubeadm的方式来安装的集群环境,对应的kubelet已经配置了我们的静态 Pod 文件的路径,那就是/etc/kubernetes/manifests,所以我们只需要在该目录下面创建一个标准的 Pod 的 JSON 或者 YAML 文件即可

通过 HTTP 创建静态 Pods

kubelet 周期地从–manifest-url=参数指定的地址下载文件,并且把它翻译成 JSON/YAML 格式的 pod 定义。此后的操作方式与–pod-manifest-path=相同,kubelet 会不时地重新下载该文件,当文件变化时对应地终止或启动静态 pod。

kubelet行为

kubelet 启动时,由--pod-manifest-path= or --manifest-url=参数指定的目录下定义的所有 pod 都会自动创建

运行中的kubelet周期扫描配置的目录(我们这个例子中就是/etc/kubernetes/manifests)下文件的变化,当这个目录中有文件出现或消失时创建或删除pods。

why

  • master 节点上面的几个重要组件都是用静态 Pod 的方式运行,万一不小心把这个 Pod 删掉了呢。使用静态Pod可以有效预防通过kubectl、或管理工具操作的误删除,可以利用它来部署一些核心组件应用,保障应用服务总是运行稳定数量和提供稳定服务。