类别 | 名称 |
资源对象 | Pod、ReplicaSet、ReplicationController、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaler |
配置对象 | Node、Namespace、Service、Secret、ConfigMap、Ingress、Label、CustomResourceDefinition、 ServiceAccount |
存储对象 | Volume、Persistent Volume |
策略对象 | SecurityContext、ResourceQuota、LimitRange |
Kubernetes提供了多种资源对象,可以根据自己应用的特性加以选择。现在我们只谈谈pod。
什么是pod
Pod是Kubernetes中可以创建的最小部署单元,由一个或者多个容器组成,它们共享容器存储、网络和容器运行配置项。
Pod中的容器共享IP地址和端口号(k8s中的容器是使用的container网络模式),它们之间可以通过localhost互相发现。也可以通过进程间通信。
通常,用户不需要手动直接创建Pod,而是应该使用controller(例如Deployment,StatefulSet,DaemonSet),即使是在创建单个Pod的情况下。Controller可以提供集群级别的自愈功能、复制和升级管理。
Pod中可以同时运行多个进程(作为容器运行)协同工作。同一个Pod中的容器会自动的分配到同一个node上。同一个Pod中的容器共享资源、网络环境和依赖,它们总是被同时调度。
在k8s中对运行容器的要求为:容器的主程序需要一直在前台运行,而不是后台运行。应用可以改造成前台运行的方式,例如Go语言的程序,直接运行二进制文件;java语言则运行主类。tomcat程序可以写个运行脚本。
Pod中可以共享两种资源:网络和存储
- 每个Pod都会被分配一个唯一的IP地址。Pod中的所有容器共享网络空间,包括IP地址和端口。Pod内部的容器可以使用localhost互相通信。
- 可以为一个Pod指定多个共享的Volume。Pod中的所有容器都可以访问共享的volume。Volume也可以用来持久化Pod中的存储资源,以防容器重启后文件丢失。
Pod中容器的运行方式
- 只运行一个单独的容器:是最常用的模式,可以把这样的Pod看成单独的一个容器去管理
- 运行多个强关联的容器:(sidecar模式),Pod 封装了一组紧耦合、共享资源、协同寻址的容器,将这组容器作为一个管理单元
为什么需要pod
- 为了方便管理:互相协作的进程共同形成一个完整的服务。以一个或多个容器的方式组合成一个整体,作为管理的基本单元,通过Pod可以方便部署、水平扩展,协同调度等。
- 为了资源共享和通信:通过共享网络和存储的方式来简化紧耦合容器之间的通信,从这个角度,可以将Pod简单理解为一个逻辑上的“虚拟机”。而不同的Pod之间的通信则通过Pod的IP和端口的方式。
- 调度器和控制器的可拔插性:将Pod的生存期从controller中剥离出来,从而减少相互影响。
pause容器
一个Pod至少会有两种容器, pause容器和应用容器
pause容器的最主要的作用:创建共享的网络名称空间,以便于其它容器以平等的关系加入此网络名称空间
pause进程是pod中所有容器的父进程(即第一个进程),每个Pod里运行着一个特殊的被称之为Pause的容器,其他容器则为业务容器,这些业务容器共享Pause容器的网络栈和Volume挂载卷,
pause容器主要为每个业务容器提供以下功能:
- 在pod中担任Linux命名空间共享的基础;
- 启用pid命名空间,开启init进程。
特点
- 镜像非常小,目前在700KB左右
- 永远处于Pause (暂停) 状态
Pod里的多个容器怎么去共享网络
假设现在有一个Pod,它包含两个容器(A和B),K8S是通过让他们加入(join)另一个第三方容器的network namespace实现的共享,而这个第三方容器就是pause容器。
没有pause容器,那么A和B要共享网络,要不就是A加入B的network namespace,要么就是B加入A的network namespace, 而无论是谁加入谁,只要network的owner退出了,该Pod里的所有其他容器网络都会立马异常,这显然是不合理的。反过来,由于pause里只有是挂起一个容器,里面没有任何复杂的逻辑,只要不主动杀掉Pod,pause都会一直存活,这样一来就能保证在Pod运行期间同一Pod里的容器网络的稳定。
由于所有的业务容器都要依赖于pause容器,因此在Pod启动时,它总是创建的第一个容器,可以说Pod的生命周期就是pause容器的生命周期。
init容器
init容器和pause容器有相同点,也有不同点
- 相同点在于:它们都有固定用途,是专用的特殊容器
- 不同点在于:init容器是用户级的容器,它是由用户来定义的,而pause容器是系统级容器,它不是由用户定义的。
Init容器与普通的容器非常像,除了如下两点:
- Init容器总是运行到成功完成为止。
- 每个Init容器都必须在下一个Init容器启动之前成功完成。
init容器,从名字上来看,也能看出是的用途就是运行一些初始化任务,来保证应用容器运行环境,这就决定了:
- init容器必须先于应用容器启动
- 仅当init容器完成后,才能运行应用容器
- 一个Pod允许有多个init容器,做不同的初始化任务
应用场景
假设我们有一个Web服务,该服务又依赖于另外一个数据库服务。但是在启动这个Web服务的时候,我们并不能保证依赖的这个数据库服务就已经启动起来了,所以可能会出现一段时间内Web服务连接数据库异常。
要解决这个问题的话我们就可以在Web服务的Pod中使用一个InitContainer,在这个初始化容器中去检查数据库是否已经准备好了,准备好了过后初始化容器就结束退出,然后我们的主容器Web服务被启动起来,这个时候去连接数据库就不会有问题了。
静态pod
静态Pod是由kubelet进行创建并管理,仅存在于特定Node上的Pod。它们不能通过API Server进行管理,无法与ReplicationController、Deployment或DaemonSet进行关联,并且kubelet也无法对其健康检查。
创建静态Pod的方式:
- 通过配置文件方式:需要设置kubelet的启动参数“–config”,指定kubelet需要监控的配置文件所在目录,kubelet会定期扫描该目录,并根据该目录的.yaml或.json文件进行创建操作。静态Pod无法通过API Server删除(若删除会变成pending状态),如需删除该Pod则将yaml或json文件从这个目录中删除。
#假设配置目录为/etc/kubernetes/conf/,配置kubelet启动参数为"--config=/etc/kubernetes/conf/",然后重启kubelet服务。
等待一会,查看本机中已经启动的容器,可以看到容器已经被kubelet创建出来了。
- HTTP方式:通过设置kubelet的启动参数“--manifest-url”,kubelet将会定期从该URL地址下载pod的定义文件,并以.yaml或.json文件的格式进行解析,然后创建pod。其实现方式与配置文件方式是一致的。