《深入剖析kubernetes》学习笔记(2)——Pod

13. Pod基础

  • Pod基本概念
    • Pod只是一个逻辑概念,是一组共享了某些资源的容器
    • Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume
    • Pod 的实现需要使用一个中间容器,叫做infra容器;在一个 Pod 中,Infra 容器永远都是第一个被创建的容器,而其他用户定义的容器,则通过 Join Network Namespace 的方式,与 Infra 容器关联在一起
  • 如何理解容器的“单进程模型”?
    • 容器中PID=1的进程就是应用本身,其他进程均是该进程的子进程
    • 并不是说容器中只能运行一个进程,而是容器无法管理多个进程
  • 对于同一个Pod里的容器A与容器B而言:
    • 它们可以直接使用 localhost 进行通信;
    • 它们看到的网络设备跟 Infra 容器看到的完全一样;
    • 一个 Pod 只有一个 IP,也就是这个 Pod 的 Network Namespace 对应的 IP ;
    • 其他的所有网络资源,都是一个 Pod 一份,并且被该 Pod 中的所有容器共享;
    • Pod 的生命周期只跟 Infra 容器一致,而与容器 A 和 B 无关。
  • 如何理解Pod的本质?
    • Pod,实际上是在扮演传统基础设施里“虚拟机”的角色;而容器,则是这个虚拟机里运行的用户程序。
  • sidecar模式,在Pod中启动一个辅助容器,完成一些独立于主进程(主容器)的工作,例如
    • WAR 包与 Web 服务器
    • 容器的日志收集
  • Pod中的Init container:
    • 在Pod的yaml中,在spec.initContainers字段下定义
    • spec.initContainers中定义的容器比spec.containers下的容器优先,并按顺序逐一启动
    • 直到sepc.initcontainers容器都启动并退出,用户容器才会启动
  • 为什么需要Pod?

14 深入Pod(1)

  • 凡是调度、网络、存储,以及安全相关的属性,基本上是 Pod 级别的,常见字段:

    • spec.nodeSelector:指定Pod运行在什么样的节点上
    • spec.nodeName:该字段由调度器负责设置,一旦被赋值则认为该Pod已经完成调度
    • spec.hostAliases:定义Pod中Host文件(/etc/hosts)的内容
  • 凡是跟容器的 Linux Namespace 相关的属性,也一定是 Pod 级别的

    • Pod的设计就是令其中的容器尽可能多地共享linux namespace,仅保留必要地隔离和限制,从而让Pod尽可能像是一个虚拟机
    • spec.shareProcessNamespace:true意味着该Pod下的容器共享PID Namespace
  • 凡是Pod中的容器要共享宿主机的 Namespace,也一定是 Pod 级别的定义

    • spec.hostNetwork: true 共享宿主机网络
    • spec.hostIPC: true 直接与宿主机进行IPC通信【补充进程间通信知识】
    • spec.hostPID: true 共享宿主机PID namespace,可以看到宿主机上所有进程
  • 两个关于容器的常用属性:

    • ImagePullPolicy,取值有Always, Never, IfNotPresent
    • Lifecycle,定义容器生命周期钩子,用于在容器状态变化时触发某些操作
  • Pod对象的生命周期,pod.status.phase定义了pod当前状态Status,可能状态有:

    • pending,pod的api对象已经被创建并保存在etcd中,但有些容器没能顺利创建
    • running, pod已经调度成功
    • succeeded,pod中所有容器正常运行结束,已经退出
    • failed,pod中有容器以不正常状态退出
  • Pod的细分状态Conditions,常见的有

    • PodScheduled, Unschedulable, Ready, Initialized

15. 深入Pod(2)

  • 投射数据卷(Projected Volume),为容器提供预先定义好的数据,有四种

    1. Secret:存储在etcd中的加密数据,容器以volume挂载的方式访问到;一旦etcd中数据更新,volume里的内容也同步更新(由kubelet组件定时维护,可能会有延时)。

      spec:
        containers:
        	......
          volumeMounts:
          - name: mysql-cred
            mountPath: "/projected-volume"
            readOnly: true
        volumes:
        - name: mysql-cred
          projected:
            sources:
            - secret:
                name: user
            - secret:
                name: pass
      

      上述yaml则将secret衷地user和pass对象,投射到了容器的/project-volume目录下

    2. ConfigMap,存储的是不需要加密的配置信息,用法与Secret基本相同

    3. Downward API,让Pod 里的容器能够直接获取到这个 Pod API 对象本身的信息,例如

      ...
      spec:
        containers:
          - name: client-container
            .....
            volumeMounts:
              - name: podinfo
                mountPath: /etc/podinfo
                readOnly: false
        volumes:
          - name: podinfo
            projected:
              sources:
              - downwardAPI:
                  items:
                    - path: "labels"
                      fieldRef:
                        fieldPath: metadata.labels
      

      当前 Pod 的 Labels 字段的值,就会被 Kubernetes 自动挂载成为容器里的 /etc/podinfo/labels 文件

      Downward API只能提供容器启动前就可以确定的信息

      Secret、ConfigMap,以及 Downward API 定义的信息,一般也都可以通过环境变量的方式获取,但是通过环境变量获取不具备自动更新的能力,因此仍应尽量使用Projected Volume

    4. ServiceAccountToken, 是一个特殊的Secret对象,保存着Service Account的授权信息和文件,明确了对kubernetes API的操作权限。

      每一个Pod在创建时,kubernetes自动在sepc.volumes字段添加了一个默认的ServiceAccountToken,并给每个容器添加了队以ingVolumeMounts字段。(也可以设置不添加该字段)

      把 Kubernetes 客户端以容器的方式运行在集群里,然后使用 default Service Account 自动授权的方式,被称作“InClusterConfig”

  • 单 Pod 的 Deployment 与一个 Pod 最主要的区别

    • 单个pod——一旦一个 Pod 与一个节点(Node)绑定,除非这个绑定发生了变化(pod.spec.node 字段被修改),否则它永远都不会离开这个节点。这也就意味着,如果这个宿主机宕机了,这个 Pod 也不会主动迁移到其他节点上去
    • 单 Pod 的 Deployment —— Pod 重新创建后可能出现在其他的可用节点
  • 容器的探针(Probe)

    • 有三种执行探针的方法:
      • 执行Exec语句,看命令是否以状态0退出,例如cat /tmp/healthy
      • 执行TCP请求,看特定端口是否打开
      • 执行HTTP Get方法,看返回结果是否在200到400之间
    • 每种探针都有三种可能的结果:
      • Success,容器通过诊断
      • Failure,容器没有通过诊断
      • Unknown,诊断操作执行失败
    • kubelet可以执行或响应以下三种探针
      • livenessProbe,判断容器是否处在running状态,若失败,根据恢复机制判断是否重启
      • readinessProbe,判断容器是否ready,若失败,将从各Service中移除该Pod的IP地址
      • startupProbe,判断容器中应用是否已经启动,如果有该探针,则其他探针均失效,直到该探针的结果为success;若失败,根据恢复机制判断是否重启
  • Pod的恢复机制

    • 单个Pod的恢复,永远只发生在当前节点上
    • 定义在pod.spec.restartPolicy字段下,有如下取值方式:
      • Always(默认取值),表示任何情况下容器不在运行(running)状态,就自动重启容器;
      • OnFailure,只在容器异常时才自动重启容器
      • Never,永远不会重启容器
    • 恢复机制、Pod的状态、Pod中容器的状态三者关系原则:
      • 只要 Pod 的 restartPolicy 指定的策略允许重启异常的容器(比如:Always),那么这个 Pod 就会保持 Running 状态,并进行容器重启。否则,Pod 就会进入 Failed 状态 。
      • 对于包含多个容器的 Pod,只有它里面所有的容器都进入异常状态后,Pod 才会进入 Failed 状态。在此之前,Pod 都是 Running 状态。
  • 关于Pod和容器的状态、探针、恢复机制的内容比较细碎,具体可以参考官方文档

  • PodPreset对象

    • 作用于其spec.selector 所定义的Pod对象,为其追加内容
    • 会在Pod API对象创建之前追加在pod定义中,不会影响Pod控制器(例如deployment)的定义
    • 多个PodPreset对一个Pod进行修改时,kubernetes会自动合并各PodPreset的修改,并忽略其中的冲突字段
posted @ 2021-02-01 15:30  lwjj  阅读(201)  评论(0编辑  收藏  举报