kubernete中的原子调度单位:pod

        在前面的文章中,我们介绍了容器技术,他的本质是操作系统上的一个进程,那么打包的容器镜像其实就是一个安装包,类似于windows操作系统中的exe文件,那容器所在的kubernete集群其实就是一个操作系统。

        容器和操作系统中进程一样,并不是独立的运行,而是和其他容器之间有着关联的关系。假如我们有3个进程,因为相互之间的关系需要部署在同一台宿主机上,这3个进程每个需要分配1G内存,但是有2个宿主机,A机器有3G内存,B机器有2.5G内存,如果不能统一调度,其中2个进程调度到B机器后,因为内存不足,第3个进程启动失败。而如果我们使用kubernete中的pod,pod会对3个容器统一管理和调度,这样就会直接选择A宿主机。

       调度在一个pod的中的容器,一般具有某些关联关系,比如共享Linux namespace,共享volume,通过localhost进行通信。像Tomcat和它所依赖的war包,就是这样的一个例子。在pod的,实现这个功能,依靠的是一个infra容器,这个容器使用的镜像是k8s.gcr.io/pause,只有不到200k,它的状态永远是pause,作用是启动后控制namespace,pod中的其他容器启动后就可以加入当前这个namespace中,这样pod中的容器共享一份namespace,就可以通过localhost进行通信了。如下图所示:

kubernete中的原子调度单位:pod

因此,infra容器是一个基础容器,它控制着namespace和整个pod的生命周期。

下面我们看一个yaml文件,Tomcat和war在同一个pod的不同容器中

apiVersion: v1
kind: Pod
metadata:
  name: javaweb-2
spec:
  initContainers:
  - image: zjj2006forever/spingboot-rabbitmq
    name: war
    command: ["cp", "/spingboot-rabbitmq.war", "/app"]
    volumeMounts:
    - mountPath: /app
      name: app-volume
  containers:
  - image: tomcat:jdk8-openjdk-slim
    name: tomcat
    command: ["sh","-c","/root/apache-tomcat-8.5.54-v2/bin/start.sh"]
    volumeMounts:
    - mountPath: /root/apache-tomcat-8.5.54-v2/webapps
      name: app-volume
    ports:
    - containerPort: 8080
      hostPort: 8001 
  volumes:
  - name: app-volume
    emptyDir: {}

上面的yaml文件中,定义了一个pod,这个pod中有2个容器,其中一个是运行标准Tomcat8镜像,一个是存放Tomcat下的war包,这儿使用的是我之前做的一个springboot-rabbitmq的镜像。同时我们也看到war包所在的容器类型是initContainer,这个镜像的特点是会比spec.containers中的容器先启动。而且,这2个容器都挂载了一个叫app-volume的volume,这个volume的路径是/app,war包容器启动时会把war包copy到/app目录下,这样Tomcat容器的/root/apache-tomcat-8.5.54-v2/webapps下就可以看到这个war包了。这就是kubernete容器编排的高明之处。如果没有pod,那就是两种处理方式,要不就是在Tomcat容器下启动一个war包容器,这种方式不方便升级war包;要不就是把war包放在宿主机上,挂载在容器种,但这种情况不适合分布式场景。

上面这个配置,叫做sidecar模式,也就是在pod中启动一个辅助容器来配合主容器进程的工作,上面的war容器就是一个sidecar。sidecar有很多场景可以应用,比如pod中可以启动一个sidecar来收集日志。

上一篇:Kubernetes存储系统介绍及机制实现


下一篇:GFS分布式文件系统