3.1 Pod

为什么需要 Pod

在上一章中我们提到,Pod 用于解决应用间的紧密交互问题,他只是一个逻辑概念。我们可以将 Pod 和虚拟机做下类比,每个虚拟机里可以运行多个进程,每个 Pod 里也可以运行多个容器,容器的本质就是进程。多个容器之间可以通过 localhost 进行访问,容器间也可以共享数据卷。这一切是如何做到的呢?其实在 Pod 里最先启动的容器并不是我们的应用容器,而是有一个辅助容器叫做 infra(k8s.gcr.io/pause),infra 是 Pod 中最先启动的容器,它负责为 Pod 创建网络和共享存储,而我们的应用容器只是连接了 infra 容器创建的网络和数据卷,这样就达到了共享网络空间和数据卷的目的。

Pod

  • 共享网络空间
  • 共享 Volumes
  • 每个 Pod 一个 IP 地址

ConfigMap

有些配置我们并不会打包到容器里,因为它们变动比较频繁,我们通常在容器启动的时候,将它们挂载到容器里。Kubernetes 为了应对这种需求就有了 ConfigMap 这种资源;有些配置文件里有敏感信息,需要对这些信息进行加密,为了应对这种需求就有了 Secret 这种资源。

创建 ConfigMap 的步骤如下:

  • 编写 ConfigMap 配置
  • 通过 kubectl 客户端提交给 Kubernetes 集群
  • Kubernetes API Server 收到请求后将 配置存储到 etcd 中
  • 容器启动时,kubelet 发请求给 API Server,将 ConfigMap 挂在到容器里

创建 nginx 配置

ConfigMap

  1. kubectl create configmap nginx-conf --from-file=nginx/hello.conf

在部署我们的 Flask 应用之前,我先部署一个 Nginx 服务。因为这个 Flask 应用是用 uwsgi 启动的,为了应对大流量访问,通常需要在前面部署一个 Nginx 代理服务。

  1. kubectl create -f pods/hello.yaml
  2. kubectl get pods

可以看到我们的 hello pod 已经启动了,但是如果 Nginx 占用大量的内存或CPU,会影响到这台物理机上启动的其他容器,所有我们要对这个 Nginx 容器做资源限制。

  1. kubectl replace --force -f pods/hello-resources-limit.yaml
  2. kubectl edit pods

我们给 Nginx 服务加了资源限制,但是当这个服务出现问题时,我们怎么检测到这个故障,并给他自动恢复呢?这时候就需要对这个服务进行监控了。

  1. kubectl replace --force -f pods/hello-healthy.yaml
  2. kubectl edit pods

我们可以通过 kubectl describe 看到 pod 的具体状态。

  1. 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 应用

  1. kubectl replace --force -f pods/hello-flask-app.yaml
  2. kubectl get pods hello

访问测试

  1. kubectl port-forward hello 10080:80
  2. curl http://127.0.0.1:10080

查看容器日志

  1. kubectl logs -c nginx hello
  2. kubectl logs -c hello hello

登录容器

  1. kubectl exec -ti hello -c hello bash

至此,我们运行了一个 Flask 应用,并在前面给他加个一个 Nginx 代理。但你有没有想过,当我们部署的这个 pod 挂了或者突然访问量加大了,会出现什么问题?如果 pod 挂了,那么服务就不能正常访问了,那怎么解决这个问题?多起几个pod,某一个挂了,其他仍有可以提供访问;如果访问量加大,同样也可以启动多个 pod 进行分流。

那我们应该如何启动多个 pod 呢? 答案就是 ReplicaSet。