大家好,我是秋意零。
本专栏上一篇中,我们介绍了 Pod 的核心思想以及 Pod 的工作原理。今天我们还是探讨 Pod ,聊一聊 Pod 的基本概念。简介
- 个人主页: 秋意零
- 个人介绍:在校期间参与众多云计算相关比赛,如: “省赛”、“国赛”,并斩获多项奖项荣誉证书
- 目前状况:24 届毕业生,拿到一家私有云(IAAS)公司 offer,暑假开始实习
- 账号:各个平台, 秋意零 账号创作者、 云社区 创建者
- 欢迎大家:欢迎大家一起学习云计算,走向年薪 30 万
【云原生|探索 Kubernetes 系列 1】容器的本质是进程
【云原生|探索 Kubernetes 系列 2】容器 Linux Cgroups 限制
【云原生|探索 Kubernetes 系列 3】深入理解容器进程的文件系统
【云原生|探索 Kubernetes 系列 4】现代云原生时代的引擎
【云原生|探索 Kubernetes 系列 5】简化 Kubernetes 的部署,深入解析其工作流程
【云原生|探索 Kubernetes 系列 6】从 0 到 1,轻松搭建完整的 Kubernetes 集群
【云原生|探索 Kubernetes 系列 7】探究 Pod 有什么用,为什么需要它
正文开始:
首先,我们来介绍一下 Pod 的生命周期,如图:
Pod 生命周期的变化,主要体现在 Pod API 对象的 Status 部分,这是它除了 Metadata 和 Spec 之外的第三个重要字段。pod.status.phase
字段就是 Pod 的当前状态,有如下几种可能的情况:
而其中,Ready 这个细分状态非常值得我们关注:它意味着 Pod 不仅已经正常启动(Running 状态),而且已经可以对外提供服务了。这两者之间(Running 和 Ready)是有区别的。
Pod 中包含了容器。那么,我们怎么在写 YAML 文件时,怎么区分 Pod 这个 API 对象中,那些是 Pod 属性里的字段,那些是 containers(容器)属性里的字段呢?
其实,我们可以形象的把虚拟机里面的属性,如:内存、磁盘、网络 等资源,对应到 Pod 中,这样 Pod 就是扮演的 “虚拟机” 的角色。但是,不要把我们本专栏文章中的第 4 篇,提到的 Kubernetes 比作 “操作系统” 的概率混淆。
所以,你把 Pod 看作是 “虚拟机”,把容器还是看做虚拟机里面的 “程序进程”,这样 Pod 的 API 对象里面的属性字段,那些是 Pod 属性里的,那些是 containers(容器)属性里的,就能一清二楚了。
结论:凡是和网络、存储、CPU、内存、调度这种虚拟机操作系统 “机器” 相关的,那么一般都是 Pod 级别的属性。
Kubernetes 中有个很重要概率 “标签”:
Key=Value
键值对组成,它是为了标识某个对象(即:Node、Pod、Service、Job 等)。如果我们为某两个对象打了同样的 “标签”,那么它们之前是可以通过“标签” 来与之关联和选择某个对象的依据。web: app
(YAML 文件中的格式)标签,那么它们之间就关联起来了,这样我们访问 Service 的 虚拟 IP 时,就相当于在访问这个 Pod。NodeSelector 是 Pod 去找对应 Node 计算节点与之绑定的字段,用法如下:
这里也可以自己为 Node 节点打标签,命令:
kubectl label
。
kubectl get node --show-labels=true
在 Pod 中,spec.nodeSelector
字段下写上 kubernetes.io/hostname: worker01
,那么这个 Pod 在运行之前进入调度队列时,就一定会在 worker01 节点运行,如果这个标签或者节点不存在,那么 Pod 就一直处于挂起状态并调度失败,否则则调度成功。
cat > web-qyl.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
labels:
run: web
name: web
spec:
nodeSelector:
kubernetes.io/hostname: worker01
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
EOF
-o wide
是详细输出)。kubectl apply -f web-qyl.yaml
kubectl get pod -o wide
NodeName 字段,手动将对象调度到 NodeName 所指定的节点名称上。
这个指其实是 kube-scheduler 组件负责设置赋值的。调度和创建过程:
这样就完成了整个调度和创建过程。
总结:所以,我们这里直接使用 NodeName 字段为其赋了值,那么 kube-scheduler 判断 NodeName 这个值是否为空时,发现有值,那么这个调度过程就是完成了的。
HostAliases 是定义了 Pod 的 /etc/hosts 文件中的内容,用法如下:
cat > hostaliases-qyl.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
labels:
run: hostaliases-qyl
name: hostliases-qyl
spec:
hostAliases:
- ip: "192.168.200.1"
hostnames:
- "vm1.com"
- "vm2.com"
- ip: "192.168.200.2"
hostnames:
- "vm.com"
containers:
- image: busybox
name: busybox
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "sleep 3600" ]
EOF
上诉中,我们在 spec.hostAliases
字段下,写了两组 ip
和 hostnames
的配置。我运行 Pod 后,查看 /etc/hosts 文件内容:
spec.hostAliases.ip.hostnames
设置的内容;kubectl apply -f hostaliases-qyl.yaml
kubectl get -f hostaliases-qyl.yaml -owide
kubectl exec -it pod/hostliases-qyl -- cat /etc/hosts
这里 spec.hostAliases
字段,也体现了跟 “虚拟机机器” 相关的配置外,也会发现,凡是跟容器的 Linux Namespace 相关的属性,也一定是 Pod 级别的。
这里,我们开启 shareProcessNamespace=true
,意味着 Pod 里的容器要共享 PID Namespace ,举个例子:
cat > nginx-shell.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
labels:
run: shell-qyl
name: shell-qyl
spec:
shareProcessNamespace: true
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
- image: busybox
name: busybox
imagePullPolicy: IfNotPresent
command: [ "/bin/sh", "-c", "sleep 3600" ]
EOF
kubectl apply -f nginx-shell.yaml
执行 ps
命令,查看进程:
nginx -g daemon off;
进程,和 busybox 容器 sleep 3600
进程,以及 Infra 容器的 /pause
进程;总结:凡是跟容器的 Linux Namespace 相关的属性,也一定是 Pod 级别的。
containers 可以算是 Pod 中最重要的字段了,本专栏。上一篇文章中(第 7 篇),我们提到了一个 containers 字段中的属性 initContainers ,这两个字段都是对 Pod 中容器的定义,定义的内容也完全相同,不同的是它们的启动顺序不同。initContainers 定义的容器,会在 containers 定义的容器之前运行,并严格按照定义的顺序执行。
containers 字段定义的内容就是为了创建容器的相关属性,比如:image(镜像)、ports(端口)、command(启动命令)、volumeMounts(挂载卷)、imagePullPolicy(镜像拉取策略)、name(容器名称)。
imagePullPolicy 的取值有:
Lifecycle,它定义的是 Container Lifecycle Hooks(生命周期挂钩)。顾名思义,Container Lifecycle Hooks 的作用,是在容器状态发生变化时(如:启动、停止之前)触发一系列 “钩子” 。
我们来看个例子:
我们在容器成功启动之后,在 /usr/share/message 里写入了一句 “Hello World”。而在这个容器被删除之前,我们则先调用了 nginx 的退出指令,从而实现了容器的 “优雅退出”。
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-qyl
spec:
containers:
- name: nginx-qyl
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", echo "Hello World" > /usr/share/message]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
今天介绍了,Pod 的基本概念。
重点说明了,Pod 的 API 对象属性字段,那些是属于 Pod 级别,那些是属于容器级别的。所以你应该了解了,能够区分大部分 Pod 的 API 对象属性字段的级别是什么。
之后介绍了,Pod 的一些常用字段的用法。