一个 Pod
是 Kubernetes
最基本的构建单元,也是最小、最简单的构建单元。Pod 也是扩缩容的基本单位,Kubernetes
的扩容和缩容都是直接对 Pod
进行操作的,直接增加 Pod
或是减少 Pod
。
一个 Pod
包含一个应用容器(有的时候有多个)、存储资源、唯一的网络 IP
、以及其它容器运行所必须的资源。
Pod
在 Kubernetes
集群中主要有两种使用方式:
运行一个单独的容器:这是最常用的方式;在这种情况下,可以认为一个 Pod
封装了一个单独的容器,Kubernetes
是对 pod
进行管理,而不是直接对容器进行管理。
运行耦合度高的多个容器:Pod
也可能包含多个容器,这些容器之间关联紧密需要共享资源。将多个容器添加到单个 Pod
的主要原因是应用可能由一个主进程和一个或多个辅助进程组成。在实践中,把一个进程放到一个容器中运行是最好的。
如图:
Node
与 Pod
Pod
是运行在 Node
上的。一个 Node
是 Kubernetes
上的工作节点,它可能是虚拟出来的节点或者是物理节点,这取决于集群的部署方式。
每个 Node
节点都被 Master
节点所管理,一个 Node
节点可以运行多个 Pod
,在集群中,Kubernetes Master
节点通过 Node
节点自动管理 Pods
。
每个 Nodes
运行至少需要两个组件:
Kubelet
:负责 Master
和 Node
之间的通信,用于管理节点上的 Pod
。Docker
:负责从仓库拉取容器镜像,运行应用等。如图:
Pod
Pod
和其他 Kubernetes
资源通过向 Kubernetes REST API
提供 JSON
或 YAML
描述文件来创建
编写YAML
有4个重要组成部分:
apiVersion
:YAML
描述文件所使用的Kubernetes API
版本kind
:Kubernetes
对象/资源类型metadata
:Pod
元数据(名称、命名空间、标签、注解等)spec
:Pod
规格/内容(容器列表、存储卷等)查看pods
有哪些属性
kubectl explain pods
编写 nginx.yaml
文件
此文件定义了一个名为
nginx
的Pod
,默认监听在 80 端口
apiVersion: v1
kind: Pod
metadata:
name: nginx-manual
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/nginx:1.9.1
name: nginx
ports:
- containerPort: 80
protocol: TCP
执行创建 pod
kubectl create -f nginx.yaml
在 Pod
列表查看新创建的 Pod
kubectl get pods
Pod
在整个生命周期中存在各种状态,常见的状态如下图:
另外 Pod
的重启策略(RestartPolicy
)有 3 种,分别为:
Always
:默认策略,当容器失效时,kubelet
会自动重启该容器
OnFailure
:当容器终止运行且退出码不为 0 时,kubelet
会自动重启该容器
Never
:不论容器运行状态如何,kubelet
都不重启该容器
# pod 上只有一个容器
kubectl logs nginx
# pod 上有多个容器,需要指定参数 -c 容器名 进行查询
kubectl logs nginx -c nginx
pod
端口是否可用# 执行端口转发,将本地 8080 端口转发到 nginx 80端口
kubectl port-forward nginx 8080:80
# 另起一个窗口,访问
curl http://localhost:8080
Pod
kubectl delete pod nginx
使用标签选择器删除pod
kubectl delete pod -l creation_method=manual
通过删除整个命名空间的方式来删除pod
kubectl delete ns test1-namespace
label
可以通过标签来组织 Pod
和所有其他 Kubernetes
资源对象。
通过标签划分组,这样就可以对属于某个组的所有 Pod
进行操作,而不需要单独为某个 Pod
执行操作。
标签是可以附加在 Kubernetes
资源对象的任意键值对,通过标签选择器可以选择具有该确切标签的资源。
标签的 key
是唯一的,一个资源可以拥有多个标签。
创建资源时可以将标签附加在资源上,也可以在现有的资源上添加标签或修改标签值。
yaml
文件apiVersion: v1
kind: Pod
metadata:
name: nginx-manual-v2
# 标签
labels:
creation_method: manual
rel: beta
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/nginx:1.9.1
name: nginx
ports:
- containerPort: 80
protocol: TCP
创建pod
kubectl create -f nginx-manual-with-labels.yaml
查看 pod
标签
kubectl get pod --show-labels
查看某个具体的标签 -L
kubectl get pod -L creation_method,rel
修改标签
# 向 nginx-manual 这个 pod 添加一个标签
$ kubectl label pod nginx-manual creation_method=manual
pod/nginx-manual labeled
# 将 nginx-manual-v2 这个 pod 上 rel=beat 修改为 rel=stable
# 需要添加 --overwrite 选项
$ kubectl label pod nginx-manual-v2 rel=stable --overwrite
pod/nginx-manual-v2 labeled
标签通常与标签选择器结合在一起使用,标签选择器可以选择标记有特定标签的 Pod
子集,并对这些 Pod
执行操作。
标签选择器对于标签的使用一般有如下 3 种方式:
想要筛选出所有手动创建的 Pod
kubectl get pod -l creation_method=manual
列出含有 rel
标签的所有pod
kubectl get pod -l rel
列出不含 rel
标签的所有 pod
kubectl get pod -l '!rel'
其他的使用方式
# 列出含有 creation_method 标签,但是其值不能为 manual 的 Pod
$ kubectl get pod -l 'creation_method!=manual'
# 列出含有 rel 标签,且其值为 beta 或是 stable 的 Pod
$ kubectl get pod -l 'rel in (beta,stable)'
# 列出含有 rel 标签,且其值不为 beta 和 stable 的 Pod
$ kubectl get pod -l 'rel notin (beta,stable)'
# 列出含有标签 creation_method=manual 和 rel=stable 的 Pod
$ kubectl get pod -l creation_method=manual,rel=stable
pod
调度Pod
通常都是随机调度到工作节点上。
如果想要将 Pod
调度到 GPU
的工作节点上,可以对相应的节点打上标签,然后在编写 yaml
文件时使用 nodeSelector
指定对应的节点标签。
查看环境中节点情况
kubectl get nodes
选择一个几点打上标签
kubectl label node kube-node-1 gpu=true
查看是否打上标签
kubectl get nodes -l gpu=true
新建名为 nginx-gpu
的pod
apiVersion: v1
kind: Pod
metadata:
name: nginx-gpu
spec:
# 标签选择器
nodeSelector:
gpu: "true"
containers:
- image: registry.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/nginx:1.9.1
name: nginx
ports:
- containerPort: 80
protocol: TCP
$ kubectl create -f nginx-gpu.yaml
pod/nginx-gpu created
namespace
由于标签和
Pod
是多对多的关系,使用标签可以将众多的Pod
进行分组,这些组中的Pod
有交叉重复的可能
使用 命名空间 就可以将对象分隔成完全独立且不重叠的组。
Kubernetes
的命名空间为对象名称提供了一个作用域。
对象名称只需要在一个命名空间内保持唯一,不同的命名空间可以包含同名的对象。
查看集群中所有的命名空间
kubectl get namespaces
查看 kube-system
命名空间下的 Pod
这里的
pod
都是和Kubernetes
系统相关的。
$kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5c98db65d4-zssrt 1/1 Running 0 64m
etcd-kube-master 1/1 Running 7 272d
kube-apiserver-kube-master 1/1 Running 7 272d
kube-controller-manager-kube-master 1/1 Running 7 64m
kube-proxy-2ddnw 1/1 Running 0 64m
kube-proxy-fjnhx 1/1 Running 0 64m
kube-proxy-wldhn 1/1 Running 0 64m
kube-scheduler-kube-master 1/1 Running 7 272d
kubernetes-dashboard-5ff478f859-d5b2g 1/1 Running 0 64m
apiVersion: v1
kind: Namespace
metadata:
name: test1-namespace
kubectl create -f test1-namespace.yaml
或者直接使用命令
kubectl create namespace test2-namespace
Pod
yaml
文件的 metadata
字段中添加 namespace: test1-namespace
属性Pod
时在命令中使用参数 -n
指定命名空间比如创建 pod
时候指定
$ kubectl create -f nginx-manual.yaml -n test1-namespace
pod/nginx-manual created
Node
挂掉了,Pod
如何处理?使用副本集 ReplicaSet
或部署 Deployment
来创建并管理 Pod
。
这样部署可以自动运行、保持健康、工作节点挂掉之后 Pod
会自动迁移到新的节点,所以几乎不会手动创建 Pod
副本集 ReplicaSet
是一种 Kubernetes
资源对象,它可以保证 Pod
始终处于运行状态。
如果 Pod
因任何原因消失,ReplicaSet
会注意到缺少了 Pod
并创建新的 Pod
进行替代。
ReplicaSet
主要用于创建和管理一个Pod
的多个副本(replicas
),核心标准是确保Pod
的数量始终与其标签选择器匹配,它会持续监控正在运行的Pod
列表,并保证带有对应标签的Pod
数量与期望相符,如果运行的Pod
太少会根据Pod
模板创建新的副本;如果运行的Pod
太多就会删除多余的副本。
ReplicaSet
由 3 个部分组成:
label selector
): 确定 ReplicaSet
作用域中有哪些 Pod
replica count
): 指定应运行的 Pod
数量Pod
模板(pod template
): 用于创建新的 Pod
副本上述的 3 个部分都可以随时修改,只有副本个数的变更会影响到现有的 Pod,更改标签选择器和 Pod 模板对现有的 Pod 没有影响。
如果更改标签选择器会使现有的 Pod
脱离 ReplicaSet
的范围,ReplicaSet
会停止关注它们;如果更改模板,只会对新创建的 Pod
应用新的模板,并不会影响现在存在的 Pod
。
使用 ReplicaSet
有以下 3 大好处:
Pod
持续运行,如果现有 Pod
数量不符合预期将会自动调整 Pod
的数量;ReplicaSet
控制的所有 Pod
会被创建新的替代副本;Pod
的水平伸缩。注意, 这里的标签选择器可以匹配如下的标签:
Pod
Pod
Pod
创建一个 ReplicaSet
nginx-replicaset.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: registry.cn-hangzhou.aliyuncs.com/chenshi-kubernetes/nginx:1.9.1
执行创建
kubectl create -f nginx-replicaset.yaml
查看创建的 pod
和 replicaSet
$ kubectl get pods
$ kubectl get rs
查看详细描述
kubectl describe rs
删除定义的ReplicaSet
删除
ReplicaSet
同时,会删除对应匹配的所有Pod
kubectl delete rs nginx
DaemonSet
)ReplicaSet
用于在 Kubernetes
集群上运行部署特定数量的 Pod
,如果你希望在集群的每个 Node
上都运行某个 Pod
,这个时候就需要使用到 DaemonSet
了,当有节点加入集群时,会为它们新增一个 Pod
。
当有节点从集群移除时,这些 Pod
也会被回收。删除 DaemonSet
将会删除它创建的所有 Pod。
DaemonSet
的使用情况分为两种:
Pod
Pod
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: mysql-ds
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
$ docker pull mysql:5.7
$ kubectl create -f mysql-ds.yaml
Pod
是否分布到了每个节点上$ kubectl get nodes
$ kubectl get pods -o wide
只需要在模板中的nodeSelector
属性中指明即可。
$ kubectl label node kube-node-1 disk1=ssd1
node/kube-node-1 labeled
yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: tomcat-ssd
spec:
selector:
matchLabels:
app: tomcat
template:
metadata:
labels:
app: tomcat
spec:
nodeSelector:
disk1: ssd1
containers:
- name: tomcat
image: kubeguide/tomcat-app:v1
$ kubectl create -f tomcat-ssd.yaml
daemonset.apps/tomcat-ssd created
DaemonSet
创建的 Pod
是否还存在?$ kubectl label node kube-node-1 disk1=hdd --overwrite
node/kube-node-1 labeled
pod
kubectl get pod
pod
已经终止了。
Job
)
ReplicaSet
和DaemonSet
监控管理的Pod
会持续不断的运行任务,这样的任务是没有完成态的,如果其中的进程退出了Pod
会重新启动。
如果想要执行一个可完成的任务,当进程终止后 Pod 不再重新启动,那么就需要使用任务 (Job)。
当节点发生故障的时候,该节点上由 Job
管理的 Pod
会按照 ReplicaSet
的 Pod
的方式,重新安排到其它节点;如果进程异常退出,可以将 Job
配置为重新启动容器。
模拟一个任务,有一个构建在 busybox
上的容器,该容器会调用 sleep
命令休息两分钟,然后就正常退出。
yaml
apiVersion: batch/v1
kind: Job
metadata:
name: batch-job
spec:
template:
metadata:
labels:
app: batch-job
spec:
# 当容器中的进程运行结束时,kubernetes会如何做
restartPolicy: OnFailure
containers:
- name: main
image: luksa/batch-job
$ kubectl create -f sleep.yaml
job.batch/batch-job created
Job
和 Pod
$ kubectl get jobs
$ kubectl get po
如果想让一项任务按顺序一次执行 10 次,可以使用 completions
属性
spec:
completions: 10
template: ...
如果想要一项任务总共运行 10 次,每次可以并行执行 3个 Pod
,可以使用 parallelism
属性
spec:
completions: 10
parallelism: 3
template: ...