熟悉Pod的相关的概念
1、总的概念
- Pod,不是容器,而是Kubernetes项目中的最小的编排单位。将这个设计落实到API对象上,容器就成了Pod属性里的一个普通的字段。
- Pod扮演的是传统部署环境里的“虚拟机”的角色,这样的设计,是为了使用户从传统环境向Kubernetes(容器环境)的迁移,更加平滑。而如果你能把Pod看成传统环境里的“机器”、把容器看作是运行这个“机器”里的“用户程序”,那么很多关于Pod对象的设计就非常容易理解了。
- 凡是调度、网络、存储、以及安全相关的属性。基本上是Pod级别的。
2、细分的概念(几个重要的字段和用法)
-
(1)NodeSelector:是一个供用户将Pod与Node 进行绑定的字段 用法如下所示:
-
apiVersion: v1 kind: Pod ... spec: nodeSelector: disktype: ssd
- 这样一个配置,意味着这个Pod 永远只能运行在携带了“disktype: ssd” 标签(Label)的节点上,否则,它将调度失败。
-
-
(2)NodeName:一旦Pod 的这个字段被赋值,Kubernetes 项目就会被认为这个Pod 已经经过了调度,调度的结果就是赋值的这个节点名字,所以,这个字段一般由调度器负责设置,但用户也可以设置它来“骗过”调度器,当然这个做法一般是在测试或者调试的时候才会用到。
-
(3)HostAliases:定义了Pod 的hosts文件(比如/etc/hosts)里的内容,用法如下:
-
apiVersion: v1 kind: Pod ... spec: hostAliases: - ip: "10.1.2.3" hostnames: - "foo.remote" - "bar.remote" ...
-
在这个Pod 的YAML文件中,我设置了一组IP和hostname 的数据,这样,这个Pod启动后,/etc/hosts/文件中的内容如下所示:
-
cat /etc/hosts # Kubernetes-managed hosts file. 127.0.0.1 localhost ... 10.244.135.10 hostaliases-pod 10.1.2.3 foo.remote 10.1.2.3 bar.remote #其中,最下面两行记录,就是我通过 HostAliases 字段为 Pod 设置的。需要指出的是,在Kubernetes 项目中,如果要设置 hosts 文件里的内容,一定要通过这种方法。否则,如果直接修改了 hosts 文件的话,在 Pod 被删除重建之后,kubelet 会自动覆盖掉被修改的内容。
-
-
-
除了上述跟“机器”相关的配置外,你可能也会发现,凡是跟容器的 (4)Linux Namespace 相关的属性,也一定是 Pod 级别的。这个原因也很容易理解:Pod 的设计,就是要让它里 面的容器尽可能多地共享 Linux Namespace,仅保留必要的隔离和限制能力。这样,Pod 模拟出的效果,就跟虚拟机里程序间的关系非常类似了。 举个例子,在下面这个 Pod 的 YAML 文件中,我定义了 shareProcessNamespace=true:
-
apiVersion: v1 kind: Pod metadata: name: nginx1 namespace: test spec: shareProcessNamespace: true containers: - name: nginx image: nginx - name: shell image: busybox stdin: true tty: true
-
这就意味着这个 Pod 里的容器要共享 PID Namespace。 而在这个 YAML 文件中,我还定义了两个容器:一个是 nginx 容器,一个是开启了 tty 和 stdin 的 shell 容器。 我在前面介绍容器基础时,曾经讲解过什么是 tty 和 stdin。而在 Pod 的 YAML 文件里声 明开启它们俩,其实等同于设置了 docker run 里的 -it(-i 即 stdin,-t 即 tty)参数。 如果你还是不太理解它们俩的作用的话,可以直接认为 tty 就是 Linux 给用户提供的一个常 驻小程序,用于接收用户的标准输入,返回操作系统的标准输出。当然,为了能够在 tty 中 输入信息,你还需要同时开启 stdin(标准输入流)。 于是,这个 Pod 被创建后,你就可以使用 shell 容器的 tty 跟这个容器进行交互了。我们 一起实践一下:
-
# 创建Pod kubectl create -f nginx.yaml # 进入 shell容器的tty上 kubectl attach -it nginx -c shell #相关显示如图
可以看到,在这个容器里,我们不仅可以看到它本身的 ps ax 指令,还可以看到 nginx 容 器的进程,以及 Infra 容器的 /pause 进程。这就意味着,整个 Pod 里的每个容器的进 程,对于所有容器来说都是可见的:它们共享了同一个 PID Namespace。
-
-
-
(5)ImagePullPoliy 字段,它定义了镜像拉取的策略,它是Container级别的熟悉,是因为容器镜像本来就是Container定义中的一部分。lmagePullPolicy 的默认是Always ,即每次创建Pod都是重新拉取一次镜像,另外,当容器的镜像是类似于Nginx 或者Nginx:latest 这样的名字时候,lmagePullPolicy 也会被认为Always。而如果它的值被定义为Never 或者IfNotPresent,则意味着Pod 永远不会主动拉取这个镜像,或者只在宿主机上不存在这个镜像时候才会拉取。
-
(6)Lifecycle字段 定义的是Container Lifecycle Hooks, 是在容器状态发生变化时候触发一系列的“钩子”,例如
apiVersion: v1 kind: Pod metadata: name: lifecycle-demo spec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share preStop: exec: command: ["/usr/sbin/nginx","-s","quit"]
- 这是一个来自Kubernetes官方文档的Pod的YAML文件,只是定义了一个Nginx容器,在Container部分,设置了一个postStart和preStop参数。
- 首先postStart 参数,在容器启动后,立刻执行一个指定的参数,在postStart 启动时候,ENTRYPOINT 有可能还没有结束。
- preStop 执行的时间,是容器被杀死之前,需要明确的是,preStop 操作的执行是同步的,会阻止当前的容器杀死流程,直到这个Hook 定义操作完成后,才允许容器被杀死。这跟postStart不同。
- 例子解释在这个例子中,我们在容器成功启动之后,在 /usr/share/message 里写入了一 句“欢迎信息”(即 postStart 定义的操作)。而在这个容器被删除之前,我们则先调用了 nginx 的退出指令(即 preStop 定义的操作),从而实现了容器的“优雅退出”。
- 这是一个来自Kubernetes官方文档的Pod的YAML文件,只是定义了一个Nginx容器,在Container部分,设置了一个postStart和preStop参数。
-
Pod对象的生命周期
-
总结,Pod生命周期的变化,主要体现在Pod API 对象的Status ,这是除了Metadata和Spec 之外的第三个重要字段。其中pod.status.phase ,就是Pod的当前状态。
-
Pending 这个状态表示,Pod 的YAML 文件已经提交给了Kubernetes,API对象已经被创建并且保存在Etcd 当中,但是,这个Pod里有些容器因为某些原因不能被顺利创建,比如,调度不成功
-
Running Man 这个状态下,表示Pod 已经调度成功。
-
Successed. 这个表示Pod的所有容器都正常运行完毕,并且已经退出了。这种情况在运行一次性任务最为常见。
-
Failed 这个状态下,Pod至少有一个容器以不正常的状态退出。 这种状态的出现,需要Debug这个容器的应用,比如查看Pod 的Events和日志。
-
Unknown 这个是异常状态,意味着Pod的状态不能持续的被kubelet 汇报给kube-apiserver 这很有可能呢是主从节点的通信出现了问题。
-
-