Pod 中可以有一个容器,也可以有多个容器
Pod 是最终对外提供服务的
2. Pod 的创建
2.1 通过命令的方式创建
命令:kubectl run ,完整的命令为:
其中,常用的命令选项有:
--image
:必须,pod 的镜像--env
:可选,表示传入容器的环境变量--port
:可选,表示使用的port端口--dry-run
:client: 仅仅打印输出,但并不实际创建 pod,检查 yaml 文件的格式是否正确
server: 实际创建
--overrides
:可选, 表示覆盖的 pod 的json文件,例如:--overrides='{ "apiVersion": "v1", "spec": { ... } }'
--image-pull-policy
: 可选,镜像下载策略:Always: 不管本地有没有镜像,都要去下载
IfNotPresent: 如果本地有,则优先使用本地镜像,如果没有镜像,就去下载
Never:从不去下载镜像
--command
:可选,表示执行的命令--labels
:可选,添加 标签
示例:
2.2 以 yaml 文件的方式创建
可以通过 dry-run 和 -o yaml 生成一个简单的模板,例如:
yaml 缩进是两个空格
以驼峰格式命名,并且 key 的首字母小写,value 的首字母大写
apiVersion 不同的资源使用不通的 apiVersion,可以使用此命令查看所有的 apiVersion:
kubectl api-version
如果不知道 yaml 中的属性,可以使用此命令查看:
kubectl explain pod
如果查看 pod 下的具体某个属性下的具体属性,可以使用:
kubectl explain pod.spec.containers
示例:
Notes:
一般,如果要设置命令,就填写在配置文件的
command
字段下,如果要设置命令的参数,就填写在配置文件的args
3. Pod 的常用命令
kubectl get pods -o wide
kubectl exec nginx -- shell 命令
注意: 如果 pod 中有多个容器,想默认 exec 进入到 第一个容器,称为主容器,后面的称为 sidecar
如果想进入指定容器,可以使用 -c 选项
kubectl exec -it nginx -- /bin/bash
进入指定的容器:
kubectl cp 本机文件名 Pod名:Pod目录
-> 从本机拷贝到容器kubectl cp Pod名:Pod文件目录 本机目录
4. Pod 的删除
kubectl delete pod nginx
-> 直接删除某个podkubectl delete -f nginx.yaml
-> 从创建的 yaml 文件 直接删除所有指定的资源
优雅的删除Pod:
kubectl 删除 pod 其实是发送一个 SIGTERM 信号给容器,让容器关闭进程
k8s 里默认设置了 30s 的时间等待容器 关闭进程,也就是等待 30s 后,在删除容器,如果容器中的进程 30s 内没有关闭,则会强制关闭
如果在 30s 内,容器已经关闭进程,则会直接删除容器,可以通过容器的 lifecycle 来控制容器的关闭
操作:
5. Pod 的生命周期
Pod 的生命周期,有两个 hook,分别是:
postStart:
表示当容器启动起来后,就运行的一些操作
postStart 这个进程,和主进程是同时进行的,也就是异步的。
preStop:
表示当容器关闭之前,运行的一些操作
如果 preStop 没有完成,Pod 是不会被删除的
使用方法:
在 yaml文件中添加 lifecycle
属性位置: pod.spec.containers.lifecycle
postStart 和 preStop 下又有三种方法,分别是
exec:执行命令
httpGet:使用发送http消息来访问某个地址
tcpSocket:使用发送tcp消息来访问某个地址
示例:
6. Pod 的端口暴露
例如:
说明:
targetPort : 这个是容器中监听的端口,也就是 9376
hostPort : 这个是将容器的端口映射到物理机的端口,也就是将容器的 9376 映射到物理机的 80 端口(与服务中的 port 相同)
7. Pod 的重启策略
在yaml文件中的 pod.spec.restartPolicy 字段,有三种情况:
Always : Pod 里的进程执行完了,不管正常或者异常,都回重新执行
OnFailure : pod 里的进程执行完了,如果异常退出,则会重新执行,如果正确退出,则不会重启
Never : 完全不会重启
8. init 初始化容器
初始化容器的步骤:
一个容器 A 依赖其他容器,可以为 A 设置多个依赖容器 A1,A2,A3
A1, A2, A3 要按照顺序启动,A1没有启动启动起来的话,A2, A3是不会启动的,直到所有的容器全部启动完毕,主容器 A 才会启动。
这里可以把 A1,A2,A3 设置为初始化容器
注意:
初始化容器失败,则会一直重启,后续的初始化容器不会执行,Pod 不会创建。 只有所有的初始化容器执行完毕,才会创建普通容器,Pod 才会创建。
使用方法:
pod.spec.initContainers 属性,来定义初始化容器
注意:容器中可以修改本机的内核属性的,但是必须设置
示例:
初始化容器的规则
它们总是运行到完成。
每个都必须在下一个启动之前成功完成。
如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的 restartPolicy 为 Never,它不会重新启动。
Init 容器支持应用容器的全部字段和特性,但不支持 Readiness Probe,因为它们必须在 Pod 就绪之前运行完成。
如果为一个 Pod 指定了多个 Init 容器,那些容器会按顺序一次运行一个。 每个 Init 容器必须运行成功,下一个才能够运行。
因为 Init 容器可能会被重启、重试或者重新执行,所以 Init 容器的代码应该是幂等的。 特别地,被写到 EmptyDirs 中文件的代码,应该对输出文件可能已经存在做好准备。
在 Pod 上使用 activeDeadlineSeconds,在容器上使用 livenessProbe,这样能够避免 Init 容器一直失败。 这就为 Init 容器活跃设置了一个期限。
activeDeadlineSeconds 标志失败 Pod 的重试最大时间,超过这个时间不会继续重试
在 Pod 中的每个 app 和 Init 容器的名称必须唯一;与任何其它容器共享同一个名称,会在验证时抛出错误。
对 Init 容器 spec 的修改,被限制在容器 image 字段中。 更改 Init 容器的 image 字段,等价于重启该 Pod。
9. 静态 Pod
静态 Pod 介绍:
静态 Pod 是直接由特定节点上的 kubelet 进程来管理,不通过主控节点上的 API 服务器。
静态 Pod 不关联任何 replication controller,它由 kubelet 进程自己来监控,当 Pod 崩溃时重启该 Pod 。
对于静态 Pod 没有健康检查。静态 Pod 始终绑定在某一个 kubelet,并且始终运行在同一个节点上。
方法:
在 node 节点上,找到 kubelet 的配置选项, –pod-manifest-path 选项,该选项指定的是 静态 Pod 的 yaml 文件存放的地址,步骤:
systemctl status kubelet
-> 查看 kubelet 的配置文件地址修改配置文件,在 Environment 中添加
--pod-manifest-path=静态pod目录
systemctl daemon-reload
systemctl restart kubelet
在指定的目录下创建 Pod 的 yaml 文件,则 kubelet 会自动创建该 Pod ,可以在 master 上查看,但是不由 master 管理,
10. Pod 的调度
当创建一个 Pod 时,scheduler 会根据自己的算法来决定 Pod 在那个节点上运行。
调度的三个对象有:
带调度的 Pod 列表
也就是新创建的所有的 Pod 列表
可用的 node 列表
也就是可以将 Pod 创建在哪些 node 节点的列表
调度算法
主机过滤(label 过滤)
主机打分
调度过程
主机过滤算法,是去除掉一些不符合要求的节点,然后剩下的节点都符合主机过滤算法的要求。
10.1
kubectl label nodes node名称 标签名=标签值
-> 给某个 node 添加标签kubectl label node --all 标签名=标签值
-> 为所有 node 添加标签kubectl label nodes node名称 标签名=标签值 --overwrite
10.2
方法:
在 node节点上可以定义一些 label,例如在 node1 指定 disktype 为 ssd 的标签
示例:
10.3
节点亲和通过 pod.spec 的 affinity 字段指定,有三种分别是
nodeAffinity
podAffinity
podAntiAffinity
注意:
- 两种类型(node 亲和性与 Pod 亲和性)的相同点在于后半部分: IgnoredDuringExecution。
- 也就是说,如果某一个 Pod 所在的 Node 的 label 发生了变化,导致一些已经运行在该 Node 上的 Pod 不符合运行条件,那么这些 Pod 也不会受到影响。
10.3.1
指定 node 的亲和性,也就是对 node 进行匹配和计算,有两个node 亲和性策略:
requiredDuringSchedulingIgnoredDuringExecution
: 硬策略指定了将 Pod 调度到一个节点上必须满足的规则
preferredDuringSchedulingIgnoredDuringExecution
: 软策略指定调度器将尝试执行但不能保证的偏好
affinity.nodeAffinity 下路径以及说明:
requiredDuringSchedulingIgnoredDuringExecution
: 硬策略nodeSelectorTerms
: 必填,node选择的具体策略,列表matchExpressions
: 通过标签进行匹配matchFields
: 通过 node 其他 filed 匹配
preferredDuringSchedulingIgnoredDuringExecution
: 软策略weight
: 设置该条件的权重,1-100preference
:matchExpressions
: 通过标签进行匹配matchFields
: 通过node 其他 filed 匹配
matchExpressions
和 matchFields
下的属性有:
key
: label 或 field 的 key 名称,必填operator
: 匹配的方法,有一下几种情况:In:label 的值在某个列表中
NotIn:label 的值不在某个列表中
Gt:label 的值大于某个值
Lt:label 的值小于某个值
Exists:某个 label 存在
DoesNotExist:某个 label 不存在
values
: 列表,通过上面 operator 方法,匹配下面的值
示例:
创建一个 deployment ,并且有在 node 亲和性 nodeAffinity 上有硬策略和软策略
在 node-1 上 有标签 disktype=ssd
硬策略是:kubernetes.io/hostname 必须是 node-1 和 node-2
软策略是: 优先选择 disktype=ssd 标签的 node
创建 deployment,查看结果, 可以看到优先在 node-1 上创建
10.3.2 podAffinity 和 podAntiAffinity (Pod 亲和性)
Pod 和 Pod 之间的亲和,例如将应用的前端和后端部署在一起,从而减少访问延迟。
用法与 nodeAffinity 相同
10.4
如果把某个节点设置了cordon(警戒线),则这个节点会被为不可调度,在创建新的 Pod 的时候,是不会在调度到这个 node 节点上的。
使用方法:
将某个节点设置为 cordon:
kubectl cordon k8s-node-1
将某个节点,取消 cordon:
kubectl uncordon k8s-node-1
设置完后,该节点就会变成不可调度状态,如下所示
将某个 node 节点设置了警戒线后,在调度 Pod 的时候,就会不在该节点上。但
10.5
如果 node 需要升级或者排错,这时候就需要将该 node 上的所有 Pod 安全的驱逐到其他 node 上,这就是 drain 的作用,用于节点的维护。
如果一个节点被设置为 drain,则此节点不再被调度 Pod ,且此节点上已经运行的 Pod 会被驱逐(evicted)到其他节点
方法:
将节点设为 drain
kubectl drain $NODENAME --ignore-daemonsets
可以看到该节点上的 pod 都为 evicted
10.6 调度: node 的污点 taint 及 Pod 的容忍性 tolerations
kubectl taint node keyName=valueName:NoSchedule
一般 key=value:NoSchedule 后加上 NoSchedule 表示该节点有污点不可调度
Pod 的容忍性 tolerations ,表示 Pod 可以容忍调度在有指定污点(taint)的 node 节点上
在 Pod 的 yaml 文件中,添加 tolerations 的属性,位置为:pod.spec.tolerations
tolerations 下的定义方法,类似 matchExpressions 的定义方法,也是通过,key、operator、value、effect
kubectl taint node <nodeName> keyNmae-
评论