Kubernetes 中的 Pod:创建、实现原理、Job 调度及网络详解
Kubernetes 中的 Pod:创建、实现原理、Job 调度及网络详解
Pod 概述
Pod 是 Kubernetes 中最小的部署单元,由一个或多个容器组成。一个 Pod 中的容器共享网络命名空间,每个 Pod 包含一个或多个紧密相关的用户业务容器。Pod 是 Kubernetes 系统中可以创建和管理的最小单元,也是在 Kubernetes 上运行容器化应用的资源对象。其他资源对象都是用来支撑或者扩展 Pod 对象功能的,比如控制器对象是用来管控 Pod 对象的,Service 或者 Ingress 资源对象是用来暴露 Pod 引用对象的,PersistentVolume 资源对象是用来为 Pod 提供存储等等。
Pod 的创建
现在创建一个 nginx 的 Pod,创建一个文件: my-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-nginx
labels:
name: my-nginx
spec:
containers:
- name: my-nginx
image: nginx:latest
resources:
limits:
memory: "128Mi"
cpu: "500m"
ports:
- containerPort: 80
使用以下命令创建 Pod:
kubectl create -f my-nginx.yaml
输出结果:
pod/my-nginx created
查看 Pod 状态:
kubectl get po
输出结果:
NAME READY STATUS RESTARTS AGE
my-nginx 0/1 ContainerCreating 0 6s
描述 Pod 详细信息:
kubectl describe pod my-nginx
输出结果:
Name: my-nginx
Namespace: default
Priority: 0
Node: node1.k8s/10.211.55.11
Start Time: Thu, 18 Apr 2024 09:49:12 +0800
Labels: name=my-nginx
Annotations: <none>
Status: Running
IP: 10.244.1.12
IPs:
IP: 10.244.1.12
Containers:
my-nginx:
Container ID: docker://2c73c0faa3aa91a72849fdaa1aa09cbca1ce3c6ef2092e2542fc7558d3b524a3
Image: nginx
Image ID: docker-pullable://nginx@sha256:d2cb0992f098fb075674730da5e1c6cccdd4890516e448a1db96e0245c1b7fca
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Thu, 18 Apr 2024 09:49:23 +0800
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 128Mi
Requests:
cpu: 500m
memory: 128Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-kpmzn (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
kube-api-access-kpmzn:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 13s default-scheduler Successfully assigned default/my-nginx to node1.k8s
Normal Pulling 13s kubelet Pulling image "nginx"
Normal Pulled 2s kubelet Successfully pulled image "nginx" in 10.625690431s
Normal Created 2s kubelet Created container my-nginx
Normal Started 2s kubelet Started container my-nginx
从输出结果可以看到,Pod 已经成功分配到 node1.k8s 节点上。
Pod 的实现原理
- Pod 在 Kubernetes 中的结构
Kubernetes 不会直接处理容器,而是 Pod。Pod 由一个或多个 container 组成,每个 Pod 都有一个特殊的被称为“根容器”的 Pause 容器。Pause 容器对应的镜像属于 Kubernetes 平台的一部分,除了 Pause 容器,每个 Pod 还包含一个或多个紧密相关的用户业务容器。
- 实现原理
Pod 的共享上下文包括一组 Linux 名字空间、控制组(cgroup)和可能一些其他的隔离方面。即用来隔离 Docker 容器的技术。在 Pod 的上下文中,每个独立的应用可能会进一步实施隔离。就 Docker 概念的术语而言,Pod 类似于共享名字空间和文件系统卷的一组 Docker 容器。说明:除了 Docker 之外,Kubernetes 支持很多其他容器运行时。Docker 是最有名的运行时,使用 Docker 的术语来描述 Pod 会很有帮助。
- Pod 的结构图例
一个包含多个容器的 Pod 中包含一个用来拉取文件的程序和一个 Web 服务器,均使用持久卷作为容器间共享的存储。在这个小小的 Pod 之内,网络(网卡)和磁盘都是独立的。一个 Pod 内的容器可以实现互相通信和资源共享,也就是可以访问同一个目录。在 Pod 停掉之前,会先关闭里面的容器。
- Pod 的使用
通常你不需要直接创建 Pod,甚至单实例 Pod。相反,你会使用诸如 Deployment 或 Job 这类工作负载资源来创建 Pod。如果 Pod 需要跟踪状态,可以考虑 StatefulSet 资源。
- Kubernetes 集群中的 Pod 主要有两种用法
- a)运行单个容器的 Pod
“每个 Pod 一个容器”模型是最常见的 Kubernetes 用例。在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。
- b)运行多个协同工作的容器的 Pod
Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。这些位于同一位置的容器可能形成单个内聚的服务单元:一个容器将文件从共享卷提供给公众,而另一个单独的“边车”(sidecar)容器则刷新或更新这些文件。比如:这个 sidecar 是一个日志的收集容器, 要时时的收集日志,读取应用的日志并推送到 log-stash,elk 或 Prometheus 中去。Pod 将这些容器和存储资源打包为一个可管理的实体,通过这种方式形成一个协同工作的单元。
- 使用 Job 调度一系列的 Pod
目的:基于一个 nginx 容器完成 shell 命令,并且完成 5 次。
创建 hello-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: hello-job
spec:
completions: 5 # 完成5次
template:
spec:
containers:
- name: hello-job
image: nginx
command: ['sh', '-c', 'echo "Hello, Kubernetes" && sleep 1']
restartPolicy: OnFailure
创建 Job:
kubectl create -f hello-job.yaml
输出结果:
job.batch/hello-job created
获取 Job:
kubectl get job
输出结果:
NAME COMPLETIONS DURATION AGE
hello-job 0/5 39s 39s
监控 Pod:
kubectl get po -w
输出结果:
NAME READY STATUS RESTARTS AGE
hello-job--1-dfj2j 0/1 Completed 0 12s
hello-job--1-k2d2w 0/1 Completed 0 32s
hello-job--1-km7sn 0/1 Completed 0 21s
hello-job--1-n78fk 0/1 Completed 0 45s
hello-job--1-pgcvn 0/1 ContainerCreating 0 2s
hello-job--1-pgcvn 1/1 Running 0 8s
hello-job--1-pgcvn 0/1 Completed 0 9s
再次获取 Job:
kubectl get job
输出结果:
NAME COMPLETIONS DURATION AGE
hello-job 5/5 39s 39s
再次查看 Pod:
kubectl get po
输出结果:
hello-job--1-dfj2j 0/1 Completed 0 16m
hello-job--1-k2d2w 0/1 Completed 0 16m
hello-job--1-km7sn 0/1 Completed 0 16m
hello-job--1-n78fk 0/1 Completed 0 17m
hello-job--1-pgcvn 0/1 Completed 0 16m
查看日志:
kubectl logs hello-job--1-pgcvn
输出结果:
Hello, Kubernetes
删除 Job:
kubectl delete job hello-job
输出结果:
job.batch "hello-job" deleted
基于以上,可以看到,基于 Job 维护 Pod 的运行状态的一个简单示例。
- Pod 的网络
每个 Pod 都在每个地址族中获得一个唯一的 IP 地址。Pod 中的每个容器共享网络名字空间,包括 IP 地址和网络端口。Pod 内的容器可以使用 localhost 互相通信。当 Pod 中的容器与 Pod 之外的实体通信时,它们必须协调如何使用共享的网络资源(例如端口)。