K8S学习笔录 - Pod的概念和作用

2,993 阅读8分钟

阅读原文

在K8S集群中,集群直接管理的不是容器,而是Pod

Pod是K8S集群中最小的管理、创建、计划单元

什么是Pod

一个Pod中会含有一个或多个需要共同工作、共享资源的容器,组成一个对外提供服务的单一实例,并且容器之间共享网络和存储。

Pod的英文翻译是“豆荚”,是一个组,里面的“豆子”在组中共享组内的空间、资源,所以名字起得还是很形象的。

pod-overview.png

Pause容器

每个Pod中都有一个Pause容器。

Pause是基础设施容器,它为整个Pod中其他业务容器提供了各种命名空间资源

  • PID命名空间 - Pod中的不同应用程序可以看到其他应用程序的进程ID。

  • 网络命名空间 - Pod中的多个容器能够访问同一个IP和端口范围。

  • IPC命名空间 - Pod中的多个容器能够使用SystemV IPC或POSIX消息队列进行通信。

  • UTS命名空间 - Pod中的多个容器共享一个主机名、Volumes。

具体可以到 www.ianlewis.org/en/almighty… 进行更多了解。

网络

每个Pod拥有一个独立的IP地址,Pod中的每个容器共享Pod的网络。

所以Pod内的容器可以使用localhost相互通信。

Pod中容器如果对外提供服务,则该服务的地址为Pod的地址:映射到Pod上的端口。

存储

在Pod中,可以指定一组Volumes为共享存储,所有的容器都可以访问它,并通过它共享数据。

另外Volumes还可以用于Pod中数据的持久化,以防其中某个容器重启而丢失数据。

为什么用Pod

为什么K8S不便直接管理容器,而是选择通过Pod来管理容器?

  • 更方便的管理由一组容器组成的服务。整个服务的状态是由Pause容器来标记,由于它与业务无关,所以不容易异常,且可以代表整个Pod的状态。

  • 解决耦合业务容器之间的通信问题。Pod可以提供共享的物理存储和网络资源

为什么不使用一个容器,里面运行多个服务呢?

首先这违背了一个容器一个服务的原则。如果把多个服务部署在一个容器中,虽然部署过程简单了很多,但是会遇到一些问题

  • 容器还在运行,服务却出现了异常,集群无法及时感知

  • 某个服务出现了需要升级,却需要重启整个容器,导致其他服务受影响(服务隔离)

  • 日志收集相对混乱

Pod生命周期

Pod有一个PodStatus对象,其中定义了一个phase字段,该字段代表着当前Pod所处的运行阶段。该字段有以下值

  • 挂起(Pending) 此时Pod已被 Kubernetes 系统接受,但有一个或者多个容器镜像尚未创建。等待时间包括调度 Pod 的时间和通过网络下载镜像的时间等

  • 运行中(Running) 该Pod已经绑定到了一个节点上,Pod中所有的容器都已被创建。至少有一个容器正在运行,或者正处于启动或重启状态

  • 成功(Succeeded) Pod中的所有容器都被成功终止,并且不会再重启

  • 失败(Failed) Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,Pod中的某个容器出现了异常(这也是为什么不建议一个容器里运行多个服务)

  • 未知(Unknown) 因为某些原因无法取得Pod的状态,通常是因为与Pod所在主机通信失败

Pod的用法

Pod不具备自愈能力,一旦Pod所在的节点资源不够、或出现了一些其他异常,这个Pod便会被驱逐

所以一般情况下不会单独创建一个Pod,因为Pod的生命周期是短暂的,一旦Pod除了异常便可能会被抛弃销毁掉

一般情况下会有一个Controller来对Pod进行管理,而Controller会提供一个Pod Template来创建相应的Pod

Pod Template

从官网搞来一个Pod模板。使用这个可以创建一个包含一个busybox容器的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']

简单列一下Pod的相关配置,也可以点击Pod查看godoc.org上k8s对配置文件结构的定义

type Pod struct {
    metav1.TypeMeta `json:",inline"`
    metav1.ObjectMeta `json:"metadata,omitempty"`

    // Pod的明确定义
    Spec PodSpec `json:"spec,omitempty"`

    // Pod的状态,这个不是配置项,只读,有系统维护
    Status PodStatus `json:"status,omitempty"`
}

type PodSpec struct {
    // 可以被容器挂载使用的卷列表
    Volumes []Volume `json:"volumes,omitempty"`

    // Pod的初始化容器容器列表,初始化容器将会在Pod启动之前按照顺序依次启动执行,任何初始化容器失败,都会看做Pod启动失败,然后根据Pod的restartPolicy进行相关处理
    // 初始化容器列表目前不能被修改
    InitContainers []Container `json:"initContainers,omitempty"`

    // 应用容器列表
    Containers []Container `json:"containers"`

    // 短暂容器配置
    EphemeralContainers []EphemeralContainer `json:"ephemeralContainers,omitempty"`

    // Pod中容器的重启策略
    // 值有Always、OnFailure和Never,默认为Always
    RestartPolicy RestartPolicy `json:"restartPolicy,omitempty"`

    // Pod被停止前的等待时间,必须为非负整数,0值则立刻停止,默认30秒
    // 在系统给Pod发送了SIGTERM信号后开始计时,TerminationGracePeriodSeconds秒后结束Pod
    // 实际上是给Pod一些缓冲时间来进行结束前的清理工作
    TerminationGracePeriodSeconds *int64 `json:"terminationGracePeriodSeconds,omitempty"`

    // Pod在存活了ActiveDeadlineSeconds秒之后将会被标记为failed,并杀死相关的容器
    // 值必须为一个正整数
    ActiveDeadlineSeconds *int64 `json:"activeDeadlineSeconds,omitempty"`

    // 为Pod设置DNS策略
    // 值可以为ClusterFirst(默认)、ClusterFirstWithHostNet, Default和None
    // 此处配置将会与DNSConfig一同合并到Pod的DNS配置里
    DNSPolicy DNSPolicy `json:"dnsPolicy,omitempty"`

    // 节点标签选择器。通过设置该值可以让Pod部署在满足指定标签要求的节点上。
    NodeSelector map[string]string `json:"nodeSelector,omitempty"`

    // 该Pod实用的ServiceAccount名
    ServiceAccountName string `json:"serviceAccountName,omitempty"`

    // 自动挂载ServiceAccount凭证
    AutomountServiceAccountToken *bool `json:"automountServiceAccountToken,omitempty"`

    // 要被调度到的节点名称,简单粗暴
    NodeName string `json:"nodeName,omitempty"`

    // 是否使用宿主机的网络命名空间 默认false
    HostNetwork bool `json:"hostNetwork,omitempty"`

    // 是否使用Host的PID命名空间 默认false
    HostPID bool `json:"hostPID,omitempty"`

    // 是否使用Host的IPC命名空间 默认false
    HostIPC bool `json:"hostIPC,omitempty"`

    // 在所有容器与Pod之间共享Process命名空间 默认false
    // 设置为true后,容器可以查看和发送新号给同一个Pod下其他容器的进程,而且容器中第一个进程的PID也不会是1
    // 不能与HostPID同时为true
    ShareProcessNamespace *bool `json:"shareProcessNamespace,omitempty"`

    // 控制pod-level安全属性和容器的通用配置,默认为空
    SecurityContext *PodSecurityContext `json:"securityContext,omitempty"`

    // 查看 https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod
    ImagePullSecrets []LocalObjectReference `json:"imagePullSecrets,omitempty"`

    // Pod主机名称,默认使用系统定义的值
    Hostname string `json:"hostname,omitempty"`

    // 如果定义了,Pod的完整hostname值将为<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>
    // 否则不会有域名部分
    Subdomain string `json:"subdomain,omitempty"`

    // Pod的亲和配置,通过该配置可以将节点调度到指定的环境中
    Affinity *Affinity `json:"affinity,omitempty"`

    // 调度器名称,默认使用默认调度器
    SchedulerName string `json:"schedulerName,omitempty"`

    // Pod的容忍配置,可以容忍节点的污点,通过该配置可以将节点调度到指定的环境中
    Tolerations []Toleration `json:"tolerations,omitempty"`

    // 为Pod增加额外的hosts配置
    HostAliases []HostAlias `json:"hostAliases,omitempty"`

    // 权重类型名称,可以通过配置此值来使用对应的PriorityClass
    // system-node-critical和system-cluster-critical是两个定义了最高级权重的特殊值
    // 如果此值未找到对应的权重类,则默认使用0
    PriorityClassName string `json:"priorityClassName,omitempty"`

    // 权重值,在Pod调度过程中会根据该值决定是否优先部署该Pod
    // 当使用PriorityAdmission控制器的时候,此值不允许用户赋值,将会从PriorityClassName对应的PriorityClass上获取
    Priority *int32 `json:"priority,omitempty"`


    // DNS配置,将会合并到生成的DNS配置中。配置将基于DNSPolicy。
    DNSConfig *PodDNSConfig `json:"dnsConfig,omitempty"`

    // Pod是否就绪的判断列表
    // Pod将在所有容器转改为就绪和所有这里定义的条件状态为True时就绪
    ReadinessGates []PodReadinessGate `json:"readinessGates,omitempty"`

    // 配置RuntimeClass的名称,默认为legacy
    // 更多信息查看https://git.k8s.io/enhancements/keps/sig-node/runtime-class.md
    RuntimeClassName *string `json:"runtimeClassName,omitempty"`

    // Pod创建后会将一些服务信息以环境变量的形式注入Pod
    // 可以通过 kubectl exec <pod-name> -- printenv 查看
    // 如果不需要服务环境变量,可以通过将此值设置为false禁用,默认为true
    EnableServiceLinks *bool `json:"enableServiceLinks,omitempty"`

    // 标记是否会抢占低优先级的Pod,
    // 值有PreemptLowerPriority(默认)和Never,分别代表会抢占低优先级Pod和不会抢占低优先级Pod
    PreemptionPolicy *PreemptionPolicy `json:"preemptionPolicy,omitempty"`

    // 配置Pod的开销情况 Kubernetes v1.16 alpha
    // 在设置了该值以后,调度Pod的时候除了要考虑容器请求的资源以外,还会考虑Pod的开销
    // 在驱逐其他Pod的时候,除了优先级、资源使用情况外,也会考虑Pod的开销情况
    // 详情查看https://kubernetes.io/docs/concepts/configuration/pod-overhead/
    Overhead ResourceList `json:"overhead,omitempty"`

    // Pod的拓扑约束配置
    // 详情查看https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
    TopologySpreadConstraints []TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
}