【Kubernetes】Kubelet 和 Pod

Posted by 西维蜀黍 on 2021-06-28, Last Modified on 2023-03-23

Kubernetes

kubernetes 是一个分布式的集群管理系统,在每个节点(node)上都要运行一个 worker 对容器进行生命周期的管理,这个 worker 程序就是 kubelet

简单地说,kubelet 的主要功能就是定时从某个地方获取节点上 Pod / Container 的期望状态(运行什么容器、运行的副本数量、网络或者存储如何配置等等),并调用对应的容器平台接口达到这个状态。

集群状态下,kubelet 会从 master 上读取信息,但其实 kubelet 还可以从其他地方获取节点的 pod 信息。目前 kubelet 支持三种数据源:

kubelet 主要功能

pod 管理

Pod 是 Kubernetes 中可部署的最小、最基本对象。一个 Pod 代表集群中正在运行的单个进程实例。

Pod 包含一个或多个容器,例如 Docker 容器。当 Pod 运行多个容器时,这些容器将作为一个实体进行管理并共用 Pod 的资源。通常,在单个 Pod 中运行多个容器是一种高级使用场景。

Pod 还包含其容器的共享网络和存储资源:

  • 网络:系统会自动为 Pod 分配独一无二的 IP 地址。各 Pod 容器共用同一网络命名空间,包括 IP 地址和网络端口。Pod 中的各容器在 Pod 内通过 localhost 彼此通信。
  • 存储:Pod 可以指定一组可在各容器之间共用的共享存储卷。

您可以将 Pod 视为一个自成一体的独立“逻辑主机”,其中包含该 Pod 所服务于的应用的系统需求。

之所以费功夫提供这一层封装,主要是因为容器推荐的用法是里面只运行一个进程,而一般情况下某个应用都由多个组件构成的。

pod 中所有的容器最大的特性也是最大的好处就是共享了很多资源,比如网络空间。pod 下所有容器共享网络和端口空间,也就是它们之间可以通过 localhost 访问和通信,对外的通信方式也是一样的,省去了很多容器通信的麻烦。

除了网络之外,定义在 pod 里的 volume 也可以 mount 到多个容器里,以实现共享的目的。

最后,定义在 pod 的资源限制(比如 CPU 和 Memory) 也是所有容器共享的。

为什么需要 K8s pod?

容器集与集群之间的关系决定了 Kubernetes 不会直接运行容器,而是运行容器集以确保其中的每个容器都共享相同的资源和本地网络。通过以这种方式对容器进行分组,可以让它们如同共享相同的物理硬件一样彼此通信,但同时仍保持一定程度的隔离。

正是有了这种将容器分组为容器集的方式,一项广为人知的 Kubernetes 功能才得以实现,那就是"复制"功能。将容器分组为容器集后,Kubernetes 可以根据需要使用复制控制器来横向扩展应用。实际上,这意味着如果单个容器集过载,Kubernetes 可自动复制该容器集并将其部署到集群中。除了在高负荷期间确保各项功能状况良好外,Kubernetes 容器集还经常被连续复制,以便为系统提供抗故障能力

Pod 怎样管理多个容器

Pod 被设计成支持形成内聚服务单元的多个协作过程(形式为容器)。 Pod 中的容器被自动安排到集群中的同一物理机或虚拟机上,并可以一起进行调度。 容器之间可以共享资源和依赖、彼此通信、协调何时以及何种方式终止自身。

Pod 联网

每个 Pod 都在每个地址族中获得一个唯一的 IP 地址。 Pod 中的每个容器共享网络名字空间,包括 IP 地址和网络端口。 Pod 内的容器可以使用 localhost 互相通信。 当 Pod 中的容器与 Pod 之外的实体通信时,它们必须协调如何使用共享的网络资源(例如端口)。

在同一个 Pod 内,所有容器共享一个 IP 地址和端口空间,并且可以通过 localhost 发现对方。 他们也能通过如 SystemV 信号量或 POSIX 共享内存这类标准的进程间通信方式互相通信。 不同 Pod 中的容器的 IP 地址互不相同,如果没有特殊配置,就无法通过 OS 级 IPC 进行通信。 如果某容器希望与运行于其他 Pod 中的容器通信,可以通过 IP 联网的方式实现。

容器健康检查

创建了容器之后,kubelet 还要查看容器是否正常运行,如果容器运行出错,就要根据设置的重启策略进行处理。检查容器是否健康主要有两种方式:在容器中执行命令和通过 HTTP 访问预定义的 endpoint。

先来说说执行命令的方式,简单来说就是在容器中执行某个 shell 命令,根据它的 exit code 来判断容器是否正常工作:

livenessProbe:
      exec:
        command:
        - cat
        - /tmp/health
      initialDelaySeconds: 15
      timeoutSeconds: 1

另外一种就是 HTTP 的方式,通过向某个 url 路径发送 HTTP GET 请求,根据 response code 判断容器是否正常工作:

livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
        httpHeaders:
          - name: X-Custom-Header
            value: Awesome
      initialDelaySeconds: 15
      timeoutSeconds: 1

可以看到,你也可以自定义发送的 HTTP 请求的头部。

不管用什么方式,如果检测到容器不健康,kubelet 会删除该容器,并根据容器的重启策略进行处理(比如重启,或者什么都不做)。

Reference