3.1 Pod
为什么需要 Pod
在上一章中我们提到,Pod 用于解决应用间的紧密交互问题,他只是一个逻辑概念。我们可以将 Pod 和虚拟机做下类比,每个虚拟机里可以运行多个进程,每个 Pod 里也可以运行多个容器,容器的本质就是进程。多个容器之间可以通过 localhost 进行访问,容器间也可以共享数据卷。这一切是如何做到的呢?其实在 Pod 里最先启动的容器并不是我们的应用容器,而是有一个辅助容器叫做 infra(k8s.gcr.io/pause),infra 是 Pod 中最先启动的容器,它负责为 Pod 创建网络和共享存储,而我们的应用容器只是连接了 infra 容器创建的网络和数据卷,这样就达到了共享网络空间和数据卷的目的。
- 共享网络空间
- 共享 Volumes
- 每个 Pod 一个 IP 地址
ConfigMap
有些配置我们并不会打包到容器里,因为它们变动比较频繁,我们通常在容器启动的时候,将它们挂载到容器里。Kubernetes 为了应对这种需求就有了 ConfigMap 这种资源;有些配置文件里有敏感信息,需要对这些信息进行加密,为了应对这种需求就有了 Secret 这种资源。
创建 ConfigMap 的步骤如下:
- 编写 ConfigMap 配置
- 通过 kubectl 客户端提交给 Kubernetes 集群
- Kubernetes API Server 收到请求后将 配置存储到 etcd 中
- 容器启动时,kubelet 发请求给 API Server,将 ConfigMap 挂在到容器里
创建 nginx 配置
kubectl create configmap nginx-conf --from-file=nginx/hello.conf
在部署我们的 Flask 应用之前,我先部署一个 Nginx 服务。因为这个 Flask 应用是用 uwsgi 启动的,为了应对大流量访问,通常需要在前面部署一个 Nginx 代理服务。
kubectl create -f pods/hello.yaml
kubectl get pods
可以看到我们的 hello pod 已经启动了,但是如果 Nginx 占用大量的内存或CPU,会影响到这台物理机上启动的其他容器,所有我们要对这个 Nginx 容器做资源限制。
kubectl replace --force -f pods/hello-resources-limit.yaml
kubectl edit pods
我们给 Nginx 服务加了资源限制,但是当这个服务出现问题时,我们怎么检测到这个故障,并给他自动恢复呢?这时候就需要对这个服务进行监控了。
kubectl replace --force -f pods/hello-healthy.yaml
kubectl edit pods
我们可以通过 kubectl describe 看到 pod 的具体状态。
kubectl describe pod hello
Pod的状态Status:
- Pending:Pod 的配置已经被 API Server 存储到 etcd 中,但是此Pod因为某种原因不能被创建
- Running:Pod 已经被调度成功并且绑定到了某个节点上,容器创建成功并开始运行
- Succeeded:Pod 都正常运行完毕并已退出,这种状态一般在一次性任务中比较常见
- Faild:Pod 里至少有一个容器运行不正常(非0状态退出),需要查找Pod失败原因
- Unknown:Pod 的状态不能持续的被 kubelet 汇报给 API Server,可能是主节点也 kubelet通信问题
细分状态 Conditions:
- PodScheduled Pod 是否已经被调度,即给他分配了物理节点
- ContainersReady 容器是否已经处于 Ready 状态
- Ready Pod 是否应 Running 并且能够对外提供服务
- Initialized 是否完成了容器初始化操作
- Unschedulable 可能资源不足导致调度失败
我们对 Nginx 容器做资源限制,并且进行了监控检查,我们的 Nginx 服务就配置完成了,那我们改如何让他代理我们的 Flask 应用容器呢?答案就是讲 Nginx 容器和 Flask 应用容器运行在同一个Pod 中,两个容器通过 socket 文件进行交互。
部署 Flask 应用
kubectl replace --force -f pods/hello-flask-app.yaml
kubectl get pods hello
访问测试
kubectl port-forward hello 10080:80
curl http://127.0.0.1:10080
查看容器日志
kubectl logs -c nginx hello
kubectl logs -c hello hello
登录容器
kubectl exec -ti hello -c hello bash
至此,我们运行了一个 Flask 应用,并在前面给他加个一个 Nginx 代理。但你有没有想过,当我们部署的这个 pod 挂了或者突然访问量加大了,会出现什么问题?如果 pod 挂了,那么服务就不能正常访问了,那怎么解决这个问题?多起几个pod,某一个挂了,其他仍有可以提供访问;如果访问量加大,同样也可以启动多个 pod 进行分流。
那我们应该如何启动多个 pod 呢? 答案就是 ReplicaSet。