Kubernetes 中 Pod 定义与操作实践
一、为什么需要 Pod
1.1 有了docker之类的容器为什么还需要 Pod ?
- 我们使用容器的目的一般是为了达到进程隔离、简化应用部署环境的目的,所以一个容器内只运行一个进程。但是在我们实际的应用场景下,存在多个进程交互紧密、存在依赖关系的情况,但他们与其他的进程不存在任何的交互关系。这样我们把存在交互关系的容器放在同一个Pod下,让他们共享网络、磁盘等资源,容器也能够继续保持相对独立。这样,一个Pod相当于一个作战小组,小组内共享组内资源,小组成员角色不同,但各司其职。
- 将运行的进程与调度解耦。一个Pod内存在若干个容器,至少1个。同时,一个Pod页是一个完整的功能单元,例如一个博客应用可能包含一个Java进程、Redis进程、MySQL进程构成一个完整的服务。这3个服务所在的容器可以在同一个Pod中。后期如果用户量暴涨,直接复制Pod即可。
1.2 Pod 的本质
Pod是一个逻辑上的概念,在物理上它并不存在。Pod的边界跟Docker实现的原理类似,也是通过Linux操作系统上的namespace技术进行隔离,cgroup技术进行限制。Pod中的所有容器,共享同一个network namespace,并且可以声明共享同一个Volume。
Docker技术本身也可以达到类似的效果,为什么还需要Pod呢?例如我们可以通过下面的命令使得2个容器A和B共享网络:
$ docker run --net=B --volumes-from=B --name=A image-A ...
但是,需要注意,这样A和B这2个容器存在明显的依赖关系,他们是不对等的。
Pod的思路是实现一个中间容器(被称为infra容器),在一个Pod中,infra容器总是被第一个创建出来,其它的用户容器则是通过join network namespace的方式与infra容器关联在一起。
infra容器的镜像是用汇编语言编写的,永远处于暂停状态的容器,该容器占用的资源很少。镜像文件即便是被解压也只有100~200KB。而且处于暂停状态的容器也很少占用其它资源。
二、在 Yaml 文件中定义 Pod
在K8S的调度系统中,操作对象是API资源对象。Pod资源是最基本的API资源对象了。其他的资源对象都是对Pod资源对象的封装。
- apiVersion:每一种资源对象都有对应的版本。通过该字段决定;
- kind:确定API资源对象的类型;
- metadata:相当于创建资源对象时的请求头。其中的
name
字段可指定改资源对象实例的名称。同时也可labels
标签下添加key-value 对,用于后面资源调度时的筛选与定位。 - spec.containers:
pod
的具体规格就在该字段下进行定义。pod
下的每个容器相当于该定义下的一个元素。
apiVersion: v1
kind: Pod
metadata:
name: test-pod
labels:
env: dev
tier: back
spec:
initContainers:
- image: geektime/sample:v2
name: war
command: ["cp", "/resource.war", "/app"]
volumeMounts:
- mountPath: /app
name: app-volume
containers:
- image: busybox:latest # 镜像版本
name: busy #容器名称
imagePullPolicy: IfNotPresent # 镜像拉取策略
env: # 定义容器内的环境变量
- name: os
value: "ubuntu"
command:# 启动容器时执行的命令
- /bin/echo
args:# 启动容器时使用到的参数
- "$(os)"
Pod中定义的initContainer 会比 spec.containers 中定义的用户容器先启动。而且 initContainer 会按照定义的顺序逐个启动,等他们全部启动并退出后,用户容器才会启动。
三、使用命令工具 kubectl
操作 Pod
下面总结下对 Pod 这种API 资源进行操作常用的命令
kubectl apply -f pod-test.yaml
: 根据yaml 文件中的定义,创建Pod 资源;kubectl delete -f pod-test.yaml
: 删除该 Yaml 文件中定义的 Pod 资源;kubectl get pod test-pod
: 获取指定pod 名的pod 信息;kubectl cp x.txt test-pod:/tmp
: 将文件x.txt
复制到 test-pod 这个pod的/tmp
这个目录下;kubectl describe test-pod
: 输出 test-pod 这个pod的详细信息,一般我们在pod 运行异常的情况下使用该命令进行错误排查;kubectl logs test-pod
: 查看 test-pod 这个pod 的运行日志;kubectl exec -it test-pod -- sh
: 进入到 test-pod 这个 pod 中进行操作;
四、静态Pod
- Kubernetes 里还存在一种特殊的 Pod 叫做静态Pod。静态Pod 的创建与调度不受 Kubernetes 的控制,而是通过在节点的
/etc/kubernetes/manifests
目录下定义好相应的Yaml 文件,节点小管家 kubelet 会定期扫描该目录下的文件,并创建对应的资源对象; - Kubernetes 管理面的4个核心组件——apiServer, controller-manager, scheduler, etcd 就是通过静态Pod 的方式部署运行的。