Pod API 原理解析
- 理解系统进程组
- 成组调度失败案例
- Pod实现原理
什么是Pod
Pod是 K8S 中最小的 API 对象。
换一个更专业的说法:Pod是 K8S 的原子调度单位。
是 K8S 能够描述和编排各种复杂应用的基石
为什么需要 Pod
# pstree -g
systemd(1)-+-accounts-daemon(1984)-+-{gdbus}(1984)
| `-{gmain}(1984)
|-acpid(2044)
...
|-rsyslogd(1632)-+-{in:imklog}(1632)
| |-{in:imuxsock) S 1(1632)
| `-{rs:main Q:Reg}(1632)
Pod 的实现原理
1、Pod 只是一个逻辑概念
关于 Pod 最重要的一个事实是:它只是一个逻辑概念
K8S 真正处理的,还是宿主机上 Linux 容器的 Namespace 和 Cgroups,
并不存在一个所谓的 Pod 的边界或者隔离环境。
2、Pod 是如何被"创建"出来的
Pod 其实是一组共享了某些资源的容器。
Pod 里的所有容器,共享的是同一个 Network Namespace,并且可以声明共享同一个 Volume。
pod属性分类
kind
指定了这个 API 对象的类型(Type),
是一个 Pod,根据实际情况,此处资源类型可以是Deployment、Job、Ingress、Service等。
metadata
包含Pod的一些meta信息,比如名称、namespace、标签等信息。
spec
specification of the resource content
指定该资源的内容,包括一些container,storage,
volume以及其他Kubernetes需要的参数,
以及诸如是否在容器失败时重新启动容器的属性。
可在特定Kubernetes API找到完整的Kubernetes Pod的属性。
容器可选的设置属性:
除了上述的基本属性外,还能够指定复杂的属性,
包括容器启动运行的命令、使用的参数、工作目录以及每次实例化是否拉取新的副本。
还可以指定更深入的信息,例如容器的退出日志的位置。
容器可选的设置属性包括:
name、image、command、args、workingDir、ports、env、resource、
volumeMounts、livenessProbe、readinessProbe、livecycle、terminationMessagePath、
imagePullPolicy、securityContext、stdin、stdinOnce、tty
跟"机器"相关的配置
运行节点选择
不指定由调度器分配node
指定可以用nodeSelector 或者nodeName指定
单个节点的时候 一般用nodeName
多节点的话 用nodeSelector ----node有统一的标签
nodeSelector举例
查version
[root@master ~]# kubectl explain DaemonSet
###################################################################################
[root@master ~]# kubectl explain DaemonSet
KIND: DaemonSet
VERSION: apps/v1
DESCRIPTION:
DaemonSet represents the configuration of a daemon set.
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
spec <Object>
The desired behavior of this daemon set. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
status <Object>
The current status of this daemon set. This data may be out of date by some
window of time. Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
查node标签
[root@master ~]# kubectl describe node node2
###################################################################################
[root@master ~]# kubectl describe node node2
Name: node2
Roles: <none>
Labels: beta.kubernetes.io/arch=amd64
beta.kubernetes.io/os=linux
kubernetes.io/arch=amd64
kubernetes.io/hostname=node2
kubernetes.io/os=linux
Annotations: flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"ca:49:fc:a1:73:a9"}
flannel.alpha.coreos.com/backend-type: vxlan
flannel.alpha.coreos.com/kube-subnet-manager: true
flannel.alpha.coreos.com/public-ip: 192.168.81.32
kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
node.alpha.kubernetes.io/ttl: 0
volumes.kubernetes.io/controller-managed-attach-detach: true
CreationTimestamp: Tue, 06 Sep 2022 23:15:33 +0800
Taints: <none>
Unschedulable: false
Conditions:
Type Status LastHeartbeatTime LastTransitionTime Reason Message
---- ------ ----------------- ------------------ ------ -------
NetworkUnavailable False Thu, 22 Sep 2022 17:49:15 +0800 Thu, 22 Sep 2022 17:49:15 +0800 FlannelIsUp Flannel is running on this node
MemoryPressure False Thu, 22 Sep 2022 18:29:09 +0800 Tue, 06 Sep 2022 23:15:33 +0800 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Thu, 22 Sep 2022 18:29:09 +0800 Tue, 06 Sep 2022 23:15:33 +0800 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Thu, 22 Sep 2022 18:29:09 +0800 Tue, 06 Sep 2022 23:15:33 +0800 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Thu, 22 Sep 2022 18:29:09 +0800 Tue, 06 Sep 2022 23:16:24 +0800 KubeletReady kubelet is posting ready status
Addresses:
之前
[root@master kubernetes]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx01
spec:
containers:
- name: nginx01
image: daocloud.io/library/nginx:1.7.9
[root@master kubernetes]# kubectl apply -f nginx.yaml
[root@master kubernetes]# kubectl get pod
[root@master kubernetes]# kubectl get pod -o wide
之后
[root@master kubernetes]# kubectl delete -f nginx.yaml
pod "nginx01" deleted
[root@master kubernetes]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx01
spec:
nodeSelector:
kubernetes.io/hostname: node2
containers:
- name: nginx01
image: daocloud.io/library/nginx:1.7.9
[root@master kubernetes]# kubectl apply -f nginx.yaml
pod/nginx01 created
[root@master kubernetes]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx01 0/1 ContainerCreating 0 25s <none> node2 <none> <none>
NodeName举例
[root@master kubernetes]# vim nginx.yaml
[root@master kubernetes]# kubectl apply -f nginx.yaml
pod/nginx01 created
[root@master kubernetes]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx01 1/1 Running 0 9s 10.244.1.7 node1 <none> <none>
[root@master kubernetes]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx01
spec:
nodeName: node1
containers:
- name: nginx01
image: daocloud.io/library/nginx:1.7.9
HostAliases
类似域名解析
定义 Pod 的 hosts 文件(比如 /etc/hosts)里的内容,用法:
apiVersion: v1
kind: Pod
...
spec:
hostAliases:
- ip: "10.1.2.3"
hostnames:
- "foo.remote"
- "bar.remote"
...
举例
[root@master kubernetes]# kubectl apply -f nginx.yaml
pod/nginx01 created
[root@master kubernetes]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx01
spec:
hostAliases:
- ip: "192.168.31.31"
hostnames:
- "www.xlx.com"
- "www.test.com"
containers:
- name: nginx01
image: daocloud.io/library/nginx:1.7.9
[root@master kubernetes]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx01 1/1 Running 0 31s 10.244.1.8 node1 <none> <none>
[root@master kubernetes]# kubectl exec -it nginx01 /bin/bash
root@nginx01:/# cat /etc/hosts
# Kubernetes-managed hosts file.
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
fe00::0 ip6-mcastprefix
fe00::1 ip6-allnodes
fe00::2 ip6-allrouters
10.244.1.8 nginx01
# Entries added by HostAliases.
192.168.31.31 www.xlx.com www.test.com
shareProcessNamespace
共享名称空间---【进程的名称空间】
表示这个 Pod 里的容器要共享 PID Namespace
[root@master kubernetes]# vim nginx.yaml
[root@master kubernetes]# kubectl apply -f nginx.yaml
pod/nginx01 created
[root@master kubernetes]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx01 2/2 Running 0 9s
[root@master kubernetes]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx01
spec:
containers:
- name: nginx01
image: daocloud.io/library/nginx:1.7.9
- name: busybox
image: daocloud.io/library/busybox
stdin: true
tty: true
[root@master kubernetes]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx01 2/2 Running 0 9s
2/2
后面2表示有一个pod有2个容器 前面2表示 2个都是运行的
[root@master kubernetes]# kubectl exec -it nginx01 /bin/bash
Defaulting container name to nginx01.
Use 'kubectl describe pod/nginx01 -n default' to see all of the containers in this pod.
默认进来是第一个容器
指定进入哪个容器 -c
[root@master kubernetes]# kubectl exec -it nginx01 -c busybox /bin/sh
/ #
[root@master kubernetes]# kubectl exec -it nginx01 -c busybox /bin/sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 sh
18 root 0:00 /bin/sh
24 root 0:00 ps
[root@master kubernetes]# cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx01
spec:
shareProcessNamespace: true
containers:
- name: nginx01
image: daocloud.io/library/nginx:1.7.9
- name: busybox
image: daocloud.io/library/busybox
stdin: true
tty: true
[root@master kubernetes]# kubectl apply -f nginx.yaml
pod/nginx01 created
[root@master kubernetes]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx01 2/2 Running 0 40s
[root@master kubernetes]# kubectl exec -it nginx01 -c busybox /bin/sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 /pause
7 root 0:00 nginx: master process nginx -g daemon off;
13 101 0:00 nginx: worker process
14 root 0:00 sh
20 root 0:00 /bin/sh
26 root 0:00 ps
stdin :-i
tty: -t
常用容器属性
Pod 里最重要的字段"Containers":
"Containers"和"Init Containers"这两个字段都属于 Pod 对容器的定义,
内容也完全相同,只是 Init Containers 的生命周期,会先于所有的 Containers,
并且严格按照定义的顺序执行。
K8S 对 Container 的定义,和 Docker 相比并没有什么太大区别。
Docker中Image(镜像)、Command(启动命令)、workingDir(容器的工作目录)、
Ports(容器要开发的端口),以及 volumeMounts(容器要挂载的 Volume)
都是构成 K8S 中 Container 的主要字段。
其他的容器属性
imagePullPolicy 字段
定义镜像的拉取策略。
之所以是一个 Container 级别的属性,是因为容器镜像本来就是 Container 定义中的一部分。
默认值: Always
表示每次创建 Pod 都重新拉取一次镜像。
当容器的镜像是类似于 nginx 或者 nginx:latest 这样的名字时,
ImagePullPolicy 也会被认为 Always。
值:Never 或者 IfNotPresent
表示 Pod 永远不会主动拉取这个镜像,或者只在宿主机上不存在这个镜像时才拉取。
eg:
spec:
containers:
- name: kubernetes-dashboard
image: kubernetesui/dashboard:v2.0.0-rc5
imagePullPolicy: IfNotPresent
pod状态【生命周期】
Pending:
此状态表示Pod 的 YAML 文件已经提交给了 Kubernetes,API 对象已经被创建并保存在 Etcd 当中。
但这个 Pod 里有些容器因为某种原因而不能被顺利创建。比如,调度不成功。
Running:
此状态表示Pod 已经调度成功,跟一个具体的节点绑定。它包含的容器都已经创建成功,
并且至少有一个正在运行中。
Succeeded:
此状态表示 Pod 里的所有容器都正常运行完毕,并且已经退出了。这种情况在运行一次性任务时最为常见。
Failed:
此状态表示 Pod 里至少有一个容器以不正常的状态(非 0 的返回码)退出。
这个状态的出现,意味着你得想办法 Debug 这个容器的应用,比如查看 Pod 的 Events 和日志。
Unknown:
这是一个异常状态,表示 Pod 的状态不能持续地被 kubelet 汇报给 kube-apiserver
这很有可能是主从节点(Master 和 Kubelet)间的通信出现了问题。
Pod 对象的 Status 字段,还可以再细分出一组 Conditions:
这些细分状态的值包括:PodScheduled、Ready、Initialized,以及 Unschedulable
它们主要用于描述造成当前 Status 的具体原因是什么。