首先当然是 Pod,我相信 Pod 是在接触 Kubernetes 时听到较多的一个词语,Pod 到底是什么?和容器之间有怎样的关系?本文将继续通过对 .NET Core 服务的部署来了解更多关于 Pod 的知识。
Pod 从表现上来看更像一台虚拟机,容器则是运行在这台虚拟机中的一个个程序进程,如下图( Infra 容器是 Pod 实现中使用的一个中间容器 ):
在现实的容器调度中,会存在容器间的强依赖情况,也就是多个容器需要运行在同一台机器上,这时如果从容器层面来调度,当机器资源只能满足部分容器被编排时,这时候就傻逼了,要么容器运行不正常,要么通过其他手段使容器重新被正确编排。所以面对这样的场景,以容器为单位来编排就可能存在问题,所以在 Kubernetes 中提出了 Pod 的概念,Pod 是一组容器的集合,以 Pod 为单位( 如 CPU、内存等资源定义 )来编排就显得更为合理。当然在实际情况下,一个 Pod 下一个容器还是比较常见的使用方式。
下面依然使用之前制作的 .NET Core API 服务的镜像 ( beckjin/k8sdemo:1.0.0 ) 在 Kubernetes 中创建 Pod 来演示。
Pod 启动后默认是无法直接访问的,有以下几种方式可以设置支持外部访问,这里暂介绍前两种方式,其他的涉及 Kubernetes 中更多的模块内容,后面会逐步涉及。
在配置文件 spec 字段下添加 hostNetwork: true ,这种情况下主机上监听的端口与容器暴露的端口一样。
spec:
hostNetwork: true
containers:
...
在配置文件 ports 字段下添加 hostPort: 自定义端口 。
ports:
- containerPort: 80
hostPort: 8888
以上两种方式任选一种进行测试即可( 以下截图是基于 hostNetwork 方式 ),修改后重启 Pod kubectl apply --force -f k8sdemo-pod.yaml ,然后通过 kubectl get pods,svc -o wide 查看 Pod 所在的主机IP。
nodeSelector 字段可根据指定的 lable 过滤符合条件的节点,如下给 k8s-node2 这个节点添加了 lable : tag=main
kubectl label nodes k8s-node2 tag=main
配置文件如下调整后,重启 Pod 就会移到 k8s-node2 节点上运行。
spec:
containers:
...
nodeSelector:
tag: main
如果需要给运行在 Pod 增加一些域名的解析(例如宿主机的主机名),但又不想动 DNS 模块,则可以通过 hostAliases 字段来配置。
spec:
containers:
...
hostAliases:
- ip: "10.10.22.22"
hostnames:
- "www.test.com"
lifecycle 字段可设置在容器状态发生变化时触发一些动作。使用方式如下:
spec:
containers:
- name: k8sdemo
...
lifecycle:
postStart:
exec:
command: ["echo start"]
preStop:
exec:
command: ["echo stop"]
livenessProbe 字段可设置健康检查需要执行的命令或 HTTP/TCP 请求。以下设置通过发起 HTTP 请求方式,根据 /healthz 接口返回状态来判断服务是否正常,目前肯定是失败,因为接口本身就 404。
spec:
containers:
- name: k8sdemo
...
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 15
periodSeconds: 5
timeoutSeconds: 1
但由于 Pod 默认自带恢复机制,也就是 spec.restartPolicy 字段的默认中是 Always ,所以当健康检查失败就会触发自动恢复机制,这个字段值还支持 OnFailure (异常时才自动重启) 和 Never (永不重启),实际使用中,需要根据场景设置合理的恢复策略。
但需要注意 Pod 的恢复永远都发生在当前节点,并不会移到其他节点,这也就意味着如果该 Pod 所在的机器宕机了,这个 Pod 就彻底挂了。至于如何处理这个问题,在后面 Deployment 控制器部分将会介绍。