一、几个问题
1、为什么要pod,而不是直接使用容器?
一个应用程序正常来说不止一个进程,当这些进程需要进程间通信、共享某些资源或者要组成进程组时,他们必须运行在同一台机器上。
如果我们仅使用容器来运行这些进程,那么这些进程都需要在一个容器中运行,也就是单个容器多个进程,这其实是不合理的,我们倾向于一个容器一个进程,因为多个进程在一个容器里运行会给维护、管理带来巨大的工作量。
在一个容器一个进程,又需要多个进程的情况下,将多个容器绑在一起作为一个单元进行管理,就是pod背后的根本原理
2、同一个pod中容器之间的部分隔离
容器之间是完全隔离的,但我们实际想隔离的是容器组,而不是容器,并让每个容器组内的容器共享一些资源,而不是全部资源,这就是部分隔离
k8s通过配置docker时一个pod内的所有容器共享同一Linux命名空间、网络命名空间、进程间通信命名空间,这样这些容器就可以像同时运行在一台主机上运行,所以pod是一个逻辑主机的概念。
容器是共享ip和端口号的,每个pod有独立的端口空间,只要一个pod里容器间的端口号不冲突,则对外永远都不会冲突,内部容器间可以通过localhost访问其他容器
3、pod间的平坦网络
k8s集群内的所有pod都有自己的ip地址,pod间的互相访问都是通过这个ip地址通信的,像极了一台主机,所以pod是一个逻辑主机的概念。
4、通过pod合理管理容器
虽然一个pod可以管理多个容器,但是我们还是倾向于一个pod里只运行一个容器,原因有两点:1.两个不需要共享资源的容器在同一个pod中运行时,k8s不会对容器调度,而是对pod调度,这个pod永远都只会在某一个工作节点上运行,降低了基础设施的使用率;2.扩缩容时,每个容器的要求并不一致,而扩缩容的基本单位也是pod,无法独立的扩缩容容器。
所以想让一个pod运行多个容器时,应该考虑这些容器是否需要在同一台主机运行(有主辅进程就需要一起运行),扩缩容要求是否一致
二、使用yaml或json描述文件来一个pod
1、pod定义yaml里的主要部分:
apiVerison: v1 //k8s API的版本
kind: Pod //yaml文件描述的类型
metadata: //包括名称、命名空间、标签、其他信息等
spec: //包含pod内容的实际说明,例如容器、卷等
status: //创建新pod时不需要提供,包含运行中pod的当前信息,例如pod所处的条件、每个容器的描述和状态、内部ip等
2、查看运行中pod的描述
kubectl get po xxx -n xxx -o yaml/json
3、如果不知道yaml中的参数怎么填
kubectl explain pods
kubectl explain pods.spec
4、创建
kubectl create -f xxx.yaml
三、使用标签组织pod
1、介绍标签
在pod非常多时,管理很混乱,可以使用标签对pod进行分组,将pod在不同维度上组织起来,形成子集。应用:一个pod的多个副本,一个应用的多个版本同时运行。
标签就是一个键值对,将pod规定到属于哪个维度(key)的哪个组(value)
2、创建pod时打标签
metadata:
labels:
creation_method: manual
env: pod
查看:
kubectl get po --show-labels
kubectl get po -L creation_method, env
修改标签:
kubectl label po xxx creation_method=manual --overwrite
查看某个标签下的所有pod
kubectl get po -l creation_method=manual //creation_method=manual的pod
kubectl get po -l creation_method //拥有creation_method标签的pod
kubectl get po -l '! creation_method' //没有creation_method标签的pod
kubectl get po -l creation_method!=manual //creation_method不是manual的pod
kubectl get po -l creation_method in (manual,aaa) //creation_method是manual或aaa的pod
kubectl get po -l creation_method notin (manual,aaa) //creation_method不是manual或aaa的pod
四、使用标签和选择器约束pod的调度
我们无法指定pod调度到哪个节点上,因为pod的调度归master节点的scheduler管, 但是我们可以描述一些要求,k8s根据我们的要求调度pod到符合要求的节点上。
假设现在我需要将某个pod调度到gpu的节点上
1、使用标签分类工作节点
kubectl label node xxx gpu=true
kubectl get nodes -l gpu=true
2、使用选择器
在pod的描述文件里添加:
spec:
nodeSelector:
gpu: "true"
注意:如果没有任何节点被打上此标签,这个pod将不可被调度。
五、命名空间
标签将对象组织成组,但是这些对象之间可以是重叠的,比如一个pod既可以有A标签,也可以有B标签,当我们想将对象分割成完全独立且不重叠的组时,就需要使用namespace
1、创建一个namespace
两种方法:
(1)YAML
apiVerison: v1
kind: Namespace //yaml文件描述的类型
metadata:
name: custom-namespace
kubectl create -f xxx.yaml
(2)命令行
kubectl create namespace custom-namespace
2、命名空间只是为资源名称提供了一个作用域,还可以限制单个用户可以访问的资源,它实际上不对正在运行的对象提供任何隔离,也就是说,不同的正在运行的pod之间,没有什么大的区别
其实命名空间的主要作用就是为了不同的用户/团队共用一个k8s集群
3、pod的描述文件里指定namespace:(json例子)
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"namespace": "custom-namespace"
}
六、删除pod
1、按名称删除
kubectl delete po pod-example
2、按标签删除
kubectl delete po -l app=yanshi
3、删除ns,自动删除ns下所有实例
kubectl delete ns xxxnamespace
4、保留ns删除pod
kubectl delete po --all -ns xxxnamespace