Kubernetes(K8S)学习笔记(3):基本对象Pod

注:该笔记整理自Kubernetes官方文档中的内容,笔记中使用的观点与资源均来源于官方文档以及我个人的理解,如果涵盖其它来源的观点,会额外标明引用。

1、什么是Pod

1.1、Pod的概念

Pod是Kubernetes可以创建与管理的最小的可部署单元。它其中可以包含多个容器,可以视为一个容器的集合,Pod之中的容器高度耦合,这些容器被并置(colocated)且一同被调度,他们共享一个pod中的资源(存储、网络、规约等)。一个形象的例子:在非云环境中,在同一个物理主机或虚拟机中的运行的应用类似于在一个Pod(或称之为逻辑主机,官方文档中把Pod描述为“特定于应用的逻辑主机”)中运行的云应用。

Pod中的内容总是共享上下文的,共享的上下文包括一组Linux名字空间、控制组(cgroup)以及其他的一些可能的隔离(容器隔离技术)。Kubernetes中的Pod主要存在两种用法:

  • 一个Pod对应一个容器(最常见的Kubernetes用例)

  • 运行多个协同工作的容器(1.2与1.3节中介绍)

1.2、Init容器

在1.1中,我们说的容器主要是“应用容器”,但是Pod中除了应用容器,还包括Init容器。在应用容器启动前,Pod中也可以有一个或多个Init容器优先于应用容器启动,例如:初始化数据库任务等。Init容器与普通容器基本一致,但存在两点不同:

  • Init容器总是运行到完成(如果Init容器运行失败,kubelet会不断重新启动该容器直到成功为止,如果restartPolicy被指定为“Never”,则如果Init容器运行失败,整个Pod的status会被设置为失败)

  • 每个Init容器都必须在下一个启动之前被完成。(为Pod指定多个Init容器时,这些容器会按顺序依次执行,并当所有的Init容器执行完成后,Kubernetes才会为应用容器进行初始化,并正常运行)

1.3、边车容器(Sidecar Containers)

上文说的Init容器是普通的Init容器,边车容器在Kubernetes中使用Init容器进行实现,但是被视为Init容器的特例,它同样是与主应用程序在同一个Pod中的辅助容器,它可以为主应用程序提供额外的功能,例如:日志、记录、安全性、数据同步等。

与普通的Init容器不同,边车容器会在Pod启动后一直保持运行状态。在Pod终止时,kubelet会推迟边车容器的终止时间,直到主应用容器终止,边车容器会按照它们在规约(.spec.initContainers)中出现顺序的相反顺序被关闭。

1.4、临时容器

当一个Pod创建完成后,不可以向其中加入新的容器。为什么这么设计呢?因为Pod通常是可替换的,如果需要这种操作,直接使用Deployment将Pod删除再新建就可以了。但是这种方式对于Debug等需要获取Pod状态的操作来说很不友好,所以设计了临时容器用来处理用户的请求。临时容器永远不会被重新启动,因此不适用于应用的构建(即资源与执行没有保证)。

2、Pod的使用

以下展示了一个Pod的使用示例,首先,使用一个Yaml文档对Pod进行描述。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

再kubectl中,可以通过以下指令来创建该pod(使用声明式对象配置):

kubectl apply -f https://k8s.io/examples/pods/simple-pod.yaml

通常而言,我们很少手动创建Pod,大部分情况下是通过Development对象以及Job这类工作负载资源来创建。

一个Pod通常对应一个服务应用的实例,但是如果实例想获取更多资源,可以横向扩展,即使用更多Pod运行更多实例,这些多的实例称之为副本。一组Pod副本通常有一个工作负载资源以及它的控制器来管理。

一个Pod为其容器天生的提供两种资源:网络与存储。它的名称必须为合法的DNS子域。

在操作系统方面,Pod需求的操作系统必须与主机的操作系统一致,你需要为Pod设置 .spec.os.name 字段,该字段目前只支持linux与windows两个值。值得注意的是,这个字段并不会影响到Pod的调度,你需要为Node节点正确设置 kubernetes.io/os标签,并使用Pod的nodeSelector字段对其进行匹配

我们可以使用工作负载资源控制器来管理和控制多个Pod,资源的控制器能处理副本的管理与上线,并能在Pod失效时提供自愈能力。Deployment、StatefulSet、DaemonSet都是工作负载资源。

工作负载资源的控制器通常是通过Pod模板来帮助你创建并管理Pod。Pod模板是工作负载对象的规范,它属于工作负载资源对象的清单文件中的一部分,以下为一个Job资源的清单文件的示例:

apiVersion: batch/v1
kind: Job
metadata:
  name: hello
spec:
  template:
    # 这里是 Pod 模板
    spec:
      containers:
      - name: hello
        image: busybox:1.28
        command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
      restartPolicy: OnFailure
    # 以上为 Pod 模板

一个Pod中的不同容器可以共享一组储存卷,同时,它们的数据还可以通过永久卷保存下来。在联网方面,Pod拥有一个唯一的IP地址,但Pod中的容器共享网络IP与端口,Pod中的容器可以通过localhost实现相互通信。

尽管大多数的Pod由控制平面管理(例如Deployment),但是静态Pod由kubelet管理,并且不需要控制平面看到它,通常而言,kubelet会自动为静态Pod在控制平面中创建一个镜像,以让控制平面看到他,但是无法控制它。

3、QoS类

服务质量(Quality of Service,QoS),根据QoS类,Kubernetes发现节点资源不足时,应当驱逐哪个节点。QoS 类有 GuaranteedBurstableBestEffort,在Kubenetes对Pod进行驱逐时,首先驱逐Guaranteed,然后Burstable,最后时BestEffort。值得注意的是,只有超出请求资源数的Pod才会成为驱逐对象。

Guaranteed:Pod具有最严格的资源限制,并最不可能被驱逐。低优先级Pod存在时,以及Guaranteed Pod没有超出资源限制时,这些Pod将保证不会被杀死。该类型的Pod可以通过该条件判断:Pod中每一个容器的资源请求的request都必须等于资源闲置的limit

Burstable:该类型的Pod提供了更灵活的资源,它有一些基于下限的request保障,但是不会超出limit,如果未指定limit,则limit默认设置为节点容量。判断该类型的Pod时,首先,必须不符合Guatanteed的判断条件,其次,必须有至少一个容器存在request或limit。

BestEffort:它的所有容器都没有limit或request,它可以自由的使用没有被Guaranteed以及Burstable使用的资源。

注意,这些行为可能导致一些不一样的情况:

1、多有超过limit的容器都会被kubelet杀死并重启,这不会影响到Pod中的其他容器。

2、如果一个容器超出了自身的request,它会作为候选驱逐对象,如果驱逐发生,Pod中的所有容器都将被终止。

3、Pod的request等于所有容器的request,Pod的limit等于所有容器的limit

4、抢占过程不考虑QoS类

你可能感兴趣的:(分布式与并行计算,kubernetes,云计算)