Pod并不是容器,而是Kubernetes项目中最小的编排单位,将这个设计落到API对象上,容器Contariner就成了Pod属性中的一个普通的字段,那么那些属性是Pod对象中存在的,那些属性是属于Container的呢?

我们将Pod看做是传统环境中的机器,将容器看做是运行在这个机器中的用户程序,那么和整体机器相关的配置都是Pod级别的,比如网络,调度,存储,安全这些

Kubernetes将Pod描述为一个机器的整体,而不是里面运行的程序,比如,配置一个机器的网卡就是Pod中的网卡,配置这个机器的运行地址,就是Pod的调度

那么,我们说下Pod中几个重要字段的用法和含义

NodeSelecter:是一个供用户将Pod和Node绑定的字段

apiVersion: v1

kind: Pod

spec:

nodeSelector:

disktype: ssd

有了nodeSelecter,就意味着这个Pod只能在Label为 disktype:ssd

不然会调度失败

NodeName

这个字段被赋值,意味着kubernetes项目将这个pod调度起来了,这个字段也是交给K8S去负责设置的,当然可以手动设置来骗过调度器

HostAliases,定义了Pod的hosts文件中的内容

apiVersion: v1

kind: Pod

spec:

hostAliases:

– ip: “10.1.2.3”

hostnames:

– “foo.remote”

– “bar.remote”

在这个Pod的YAML文件中设置了一组IP和hostaname的数据,这样启动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中,如果设置Host内容,还是靠Yaml中的文件,不然重建Pod后,Kubelet会覆盖host文件中的内容

凡是和容器的Linux Namesapce相关的属性,都是Pod级别的,Pod的设计,就是可以在一个Pod中,共享更多的Linux Namespace,仅仅保留必要的隔离和限制能力,这样Pod模拟出的效果,和虚拟机中程序的关系很相似了

那么,我们看下例子

假设我们在Pod的YAML文件中,定义了shareProcessNamespace=true

就是指定共享了PID Namespace

apiVersion: v1

kind: Pod

metadata:

name: nginx

spec:

shareProcessNamespace: true

containers:

– name: nginx

image: nginx

– name: shell

image: busybox

stdin: true

tty: true

在这个YAML文件中,还有两个容器,一个是nginx容器,一个是tty和stdin的shell容器

tty和stdin是一顿好搭档,设置开启了这两,就相当于设置了docker run中的it -i是stdin -t是tty,用来接收用户的标准输入,返回操作程序的标准输出

这样,Pod被创建了之后,就可以使用shell容器的tty跟这个容器交互了

kubectl create -f nginx.yaml

然后就可以使用kubectl attach命令,连接到shell容器的tty上

kubectl attach -it nginx -c shell

这样,我们能看到这个shell容器中所有的进程,执行ps指令

$ kubectl attach -it nginx -c shell

/ # ps ax

PID   USER     TIME  COMMAND

1 root      0:00 /pause

8 root      0:00 nginx: master process nginx -g daemon off;

14 101       0:00 nginx: worker process

15 root      0:00 sh

21 root      0:00 ps ax

这样,我们就可以看到shell容器本身的 ps ax指令之外,还有着nginx容器的进程,以及Infra容器的/pause进程,这样就一个Pod共享了整个Pid Namespace

类似的,凡是Pod中容器要共享宿主机的Namespace的,一定是Pod级别的定义

apiVersion: v1

kind: Pod

metadata:

name: nginx

spec:

hostNetwork: true

hostIPC: true

hostPID: true

containers:

– name: nginx

image: nginx

– name: shell

image: busybox

stdin: true

tty: true

这个Pod中,定义共享了宿主机的Network IPC PID

Namespace,这就是Pod中所有的容器,会直接使用宿主机的网络,直接和宿主机进行IPC通信,看到宿主机运行的进程

Pod最重要的字段属于Containers,这个是定义的容器详情,对于之前说的Init Containers,也是一个Container,只不过其生命周期,会先于所有的Containers,严格按照定义的顺序执行

Kubernetes中对Container的定义,其实和Docker类似,也有着Image镜像,Command 启动命令,workingDir 容器的工作目录, Ports 容器要开发的端口 volumeMouts 容器挂载的Volume

都是构成Kubernetes项目中Container的主要字段

除此之外,还有一些特殊的定义参数

1.ImagePullPolicy字段,定义了镜像拉取的策略,

默认值是Always,每次创建Pod都拉取一次镜像,当每次创建Pod都拉取一次镜像,当容器的镜像类似nginx或者nginx:lastest的时候,ImagePullPolicy都被认为Always

值被定义为Never或者IfNotPresent,意味Pod永远不会主动拉取这个镜像,只有不存在的时候才重新拉取

2.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/message”]

preStop:

exec:

command: [“/usr/sbin/nginx”,”-s”,”quit”]

在这个yaml中,我们定义了两个lifecycle

分别是postStart和preStop

意味着是

在容器启动后,立刻执行一个指定的操作,但是这个操作虽然是在Docker容器启动后执行的,但是并不严格保证顺序,如果postStart执行超时或者错误的时候,Kubernetes会在Pod的Events中报出这个容器失败的错误信息,让Pod也处于失败的状态

preStop发生的实际,则是在容器被杀死之前,在这个Hook执行的过程,会阻塞当前的杀死进程,直到Hook的操作完成后,才能让容器被杀死,和postStart不一样

在这个例子中,我们在容器成功启动后,在/usr/share/message中写入了一句欢迎信息,然后在删除之前,我们调用了nginx的退出指令,实现了容器的优雅退出

最后,我们说一下Pod Api对象的生命周期,Pod的生命周期的变化,主要在Pod API对象的Status部分,除了Metedata和spec之外的第三个重要的字段

(1) Pending Pod的YAML文件已经提交了Kubernetes,API对象已经被创建并被保存在Etcd之中了,但是这个Pod中某些容器因为某些原因不能顺利被创建,导致的这个状态

(2) Running,这个状态下,Pod已经调度成功,跟一个具体的节点绑定了,包含的容器都已经创建成功

(3)Succesded,这个状态意味着,Pod中所有容器都运行完毕,并且退出了,这是运行一次性任务最常见的状态

(4)Failed Pod中至少有一个容器以不正常的状态退出,这个状态出现,意味着得想办法查看这个日志的错误信息

(5)Unknown,这是意味着Pod的状态不能持续的报给kube-apiserver,说明可能是和主节点的通信出现了问题

除此外,还有着更细分的概念,包含PodScheduled Ready Initialized 以及 Unschedulable

用于描述当前的Status的具体原因是什么

Pod当时的Status是Pending,对应的Condition是Unschedulable,意味着调度出现了问题

其中,Ready比较需要注意,Ready说明,是在启动完成后,可以对外提供服务了

和Running是有一定的区别的

本次,我们介绍了Pod Api对象,介绍了Pod的核心用法,分析了Pod和Container在字段上的异同

,Pod API对象,是整个Kubernetes体系中最为核心的一个概念,在之后的时候,我们遇到一个Pod的Yaml,可以不用查阅文档,将其信手拈来

是否有一些Pod的状态是Running,但是已经停止服务的例子?

1.程序本身有Bug,导致的服务不能提供

2.程序因为内存问题,僵死了,但是进程还是在的

3.Dockerfile写的不规范,应用程序不是主进程出现了问题

4.程序内死循环

发表评论

邮箱地址不会被公开。 必填项已用*标注