Pod
-
自主式 Pod
即不被控制器管理的 Pod。因为不被控制器管理,所以这种 Pod 在停止后无法自动重启或者自动创建新的 Pod。
-
控制器管理的 Pod
网络共享,只要定义了一个 Pod,那么该 Pod 会自带一个 pause 容器,pause 容器专门用来共享网络。也就是说,该 Pod 里面的所有容器都基于 pause 容器进行网络通讯。容器之间可以直接使用 localhost:端口号
来进行通信,因此同一个 Pod 里面的容器的端口号不能相同。
数据卷共享,Pod 里除了网络共享之外,所有的容器也共享一个数据卷。
Pod 控制器
ReplicationController
ReplicationController(RC) 用来确保容器的副本数始终维持在用户定义的副本数,也就是说,如果有容器异常退出,会自动创建新的 Pod 来替代。同理,如果容器多于期望的副本数,也会自动回收。
在新版本的的 k8s 中建议使用 ReplicaSet 来代替 ReplicationController。
ReplicaSet
ReplicaSet(RS) 与 ReplicationController 没有本质不同,只是名称不一样。但是 ReplicaSet 还支持集合式的 selector。
集合式的 selector:Pod 在被创建的时候,可以打上标签来标记该 Pod,RS 支持同时管理多个同一标签的 Pod。
虽然 RS 可以独立使用,但一般还是建议使用 Deployment 来自动管理 RS,这样就无需担心跟其它机制的不兼容问题(比如 RS 不支持 rolling-update ,但 Deployment 支持)。
Deployment
因为 Deployment 不支持 Pod 的创建,所以需要结合 RS 来创建 Pod。
Deployment 为 RS 和 Pod 提供了一个声明式定义(declarative)方法,用来替代以前的 RC 来方便管理应用。典型的应用场景包括:
- 定义 Deployment 来创建 Pod 和 RS
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续 Deployment
滚动更新:
创建一个 Deployment ,Deployment 会创建一个 RS,让 RS 来创建 Pod,该 Pod 里运行的是 v1 版本的容器(假设运行了 2 个容器)。
现在进行版本更新,使用 Deployment 再创建一个 RS,同理让 RS 来创建 Pod,但是这次的 Pod 里面运行的是 v2 版本的容器。当 v2 版本的容器启动完成之后,再删除 v1 版本的容器。
需要注意是的, v2 版本的容器创建的时候,并不是一次创建两个。而是先创建一个 v2 版本的容器,该容器启动完成之后,删除一个 v1 版本的容器。然后再创建一个 v2 版本的容器,启动完成之后再删除一个 v1 版本的容器。即:创建一个 v2 删除一个 v1。
回滚:
如果更新完成之后,发现 v2 版本存在问题,可以进行回滚操作。
滚动更新成功之后,原本的 RS 并不会被删除,进行回滚的时候,会重新启动这个 RS,创建其中的容器,其原理和更新时一样,先创建一个 v1 版本的容器,再删除一个 v2 版本的容器。
HAP
HAP(Horizontal Pod Autoscaling)仅适用于 Deployment 和 ReplicaSet,在 v1 版本中仅支持根据 Pod 的 CPU 利用率扩缩容,在 vlalpha 版本中,支持根据内存和用户自定义的 metric 扩缩容。
StatefulSet
StatefulSet 是为了解决有状态服务的问题(对应 Deployment 和 ReplicaSets 是为无状态服务而设计),其应用场景包括:
- 稳定的持久化存储,即 Pod 重新调度后还是能访问到相同的持久化数据,基于 PVC 来实现
- 稳定的网络标志,即 Pod 冲i性能调度后其 PodName 和 HostName 不变,基于 Headless Service(即没有 Cluster IP 的 Service)来实现
- 有序部署,有序扩展,即 Pod 是有顺寻的,在部署或者扩展的时候要依据定义的顺序一次进行(即从 0 到 N-1,在下一个 Pod 运行之前所有的 Pod 必须都是 Running 和 Ready 状态),基于 init containers 来实现
- 有序收缩,有序删除(即从 N-1 到 0)
DaemonSet
DaemonSet 确保全部(或者一些)Node 上运行一个 Pod 的副本。当有 Node 加入集群时,也会为他们新增一个 Pod。当有 Node 从集群移除时,这些 Pod 也会被自动回收。删除 DaemonSet 将会删除它创建的所有 Pod。
DaemonSet 的一些典型用法:
- 运行集群存储 daemon,例如在每个 Node 上运行 glusterd、ceph。
- 在每个 Node 上运行日志收集 daemon,例如 fluentd、logstash。
- 在每个 Node 上运行监控 daemon,例如 Prometheus Node Exporter。
Job
Job 负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个 Pod 成功结束。
Cronjob 是基于时间管理的 Job,即:
- 在给定时间运行一次
- 周期性的在给定时间运行
服务发现
k8s 的 Pod 之间可以直接通过 IP 来互相通信。但是由于容器重启之后 IP 会变,所以使用 IP 直接通信的方式不常见。
这时可以使用 service(SVC) 来管理一组相同标签的 Pod。通过 serivce 对外开放的地址来访问到该 service 下的容器。
上图中的 php-fpm
使用 service-php-fpm
代理,squid
要访问到 php-fpm
只需要访问 service-php-fpm
提供的地址即可。
网络通讯方式
Kubernetes 的网络模型假定了所有 Pod 都在一个可以直接连通的扁平的网络空间中(即 Pod 间可以直接通过 IP 互相通信),这在 GCE(Google Compute Engine)里面是现成的网络模型,Kubernetes 假定这个网络己经存在。 而在私有云里搭建 Kubernetes 集群,就不能假定这个网络己经存在了。我们需要自己实现这个网络假设,将不同节点上的 Docker 容器之间的互相访问先打通,然后运行 Kubernetes。
-
同一个 Pod 内部通讯
同一个 Pod 共享同一个网络命名空间(pause容器),共享同一个 Linux 协议栈。
-
Pod1 至 Pod2(overlay network)
-
Pod1 与 Pod2 不在同一台主机
Pod 的地址是与 docker0 在同一个网段的,但 docker0 网段与宿主机网卡是两个完 全不同的 IP 网段,并且不同 Node 之间的通信只能通过宿主机的物理网卡进行。将 Pod 的 IP 所在 Node 的 IP 关联起来,通过这个关联让 Pod 可以互相访问。
-
Pod1 与 Pod2 在同一台机器
由 Docker0 网桥直接转发请求至 Pod2,不需要经过 Flannel。
-
-
Pod 至 Service 的网络
默认使用 iptables 维护和转发。新版本中采用的是 lvs。
-
Pod 到外网
Pod 向外网发送请求,査找路由表,转发数据包到宿主机的网卡,宿主网卡完成路由选择后,iptables 执行Masquerade,把源 IP 更改为宿主网卡的 IP,然后向外网服务器发送请求。
-
外网访问 Pod
直接访问 Pod 对应的 Service。
overlay network 实现方案 Flannel:
Flannel 是 CoreOS 团队针对 Kubernetes 设计的一个网络规划服务,简单来说,它的功能是 让集群中的不同节点主机创建的 Docker 容器都具有全集群唯一的虚拟 IP 地址。而且它还能在这些 IP 地址之间建立一个覆盖网络(Overlay Network),通过这个覆盖网络,将数据包原封不动地传递到目标容器内。
上图中共有两台主机,同一主机内容器间通信只需要经过容器自己的网桥(Docker0)转发数据即可。
如果要跨主机通信,那么就需要将数据包封装,右边是数据包封装的格式,其中封装了两层地址信息,第一层是源主机地址及目的主机地址,第二层是源容器地址及目的容器地址。
-- end --