1.6 Deployment
为了更好地解决 Pod 的编排问题,引入了Deployment。可看作 RC 的一次升级,两者的相似度超过 90%。
Deployment 相对于 RC 的一个最大升级是我们可以随时知道当前 Pod “部署”的进度。实际上由于一个 Pod 的创建、调度、绑定节点及在目标 Node 上启动对应的容器这完整过程需要一定的时间,所以我们期待系统启动N个 Pod 副本的目标状态,实际上是一个连续变化的“部署过程”导致的最终状态。
Deployment 的典型使用场景有以下几个。
- 创建 Deployment 对象来生成对应的 Replica Set 井完成 Pod 副本的创建过程
- 检查 Deployment 的状态来看部署动作是否完成( Pod 副本的数量是否达到预期的值)
- 更新 Deployment 以创建新的 Pod (比如镜像升级)
- 如果当前 Deployment 不稳定,则回滚到一个早先的 Deployment 版本
- 暂停 Deployment 以便于一次性修改多个 PodTemplateSpec 的配置项,之后再恢复Deployment ,进行新的发布。
- 扩展 Deployment 以应对高负载。
- 查看 Deployment 的状态,以此作为发布是否成功的指标。
- 清理不再需要的旧版本 ReplicaSets
1.7 Horizontal Pod Autoscaler
Horizontal Pod Autoscaling (Pod 横向自动扩容,简称HPA )。
HPA可以有以下两种方式作为 Pod 负载的度量指标。
- CPUUtilizationPercentage
- 应用程序自定义的度量指标,比如服务在每秒内的相应的请求数 CTPS或QPS )。
如果某一时刻 CPUUtilizationPercentag 的值超过 80% ,则意味着当前的 Pod 副本数很可能不足以支撑接下来更多的请求,需要进行动态扩容,而当请求高峰时段过去后, Pod的CPU 利用率又会降下来,此时对应的 Pod 副本数应该自动减少到一个合理的水平。
下面展示一个YAML:
apiVersion : autoscaling/vl
kind: HorizontalPodAutoscaler
metadata :
name : php-apache
namespace: default
spec:
maxReplicas : 10
minReplicas : 1
scaleTargetRef:
kind : Deplo nent
name : php-apache
targetCPUUtilizationPercentage : 90
上面的HPA控制的目标对象 php-apache的Deployment里的 Pod副本,当这些 Pod 副本 CPUUtilizationPercentage的值超过90%会触发自动动态扩容行为,扩容或缩容时必须满足的一个约束条件是Pod 的副本数介于1与10之间。
1.8 StatefulSet
StatefulSet从本质上来说,可以看作 Deployment/RC的一个特殊变种,它有如下一些特性:
- StatefulSet 里的每个 Pod 都有稳定、唯一的网络标识,可以用来发现集群内的其他成员。
- 假设StatefulSet 名字叫kafka, 那么第1个 Pod kafka-0 ,第2个叫 kafk-1,以此类推。
- StatefulSet 控制的 Pod副本的启停顺序是受控的,操作第n个Pod 时,前 n-1 Pod已经是运行且准备好的状态。
- StatefulSet 里的Pod采用稳定的持久化存储卷,通过 PV/PVC 来实现,删除 Pod 时默认 不会删除与StatefulSet相关的存储卷(为了保证数据的安全)
StatefulSet在Headless Service 的基础上又为StatefulSet 控制的每个 Pod 实例创建了 DNS 域名,这个域名的格式为:
$(podname).$(headless service name)
比如一个三节点的Kafka StatefulSet 集群,对应的 Headless Service 的名字为 kafka,StatefulSet 的名字为 kafka,则 StatefulSet 里面的 Pod DNS 名称分别为 kafka-0.kafka,kafka-1.kafka kafka-3 .kafka ,这些 DNS 名称可以直接在集群的配置文件中固定下来。
1.9 Service(服务)
概述:
Service 也是 Kubemetes 里的最核心的资源对象之 Kubernetes 里的每个 Service 其实就是我们经常提起的微服务架构中的一个“微服务”.
Pod , RC Service 的关系:
通过分析、识别并建模系统中的所有服务为微服务一Kubernetes Service 最终我们的系统由多个提供不同业务能力而又彼此独立的微服务单元所组成,服务之间通过 TCP/IP 进行通信,从而形成了我们强大而又灵活的弹性网格,拥有了强大的分布式能力、弹性扩展能力、容错能力.
Service不是共用一个负载均衡器的 地址,而是每个 Service 分配了 一个全局唯一的虚拟 IP 地址,这个虚拟IP被称为 Cluster 。这样一来,每个服务就变成了具备唯一 地址的“通信节点”,服务调用就变成了最基础 TCP 网络通信问题.
Kubernetes 的服务发现机制
如何通过 Service 的名字找到对应的 Cluster IP?
最早时 Kubemetes 采用了 Linux 环境变量的方式解决这个问题,即每个 Service 生成 些对应的 Linux 环境变量 CENV ),并在每个 Pod 的容器在启动时,自动注入这些环境变量,以下是tomcat-service 产生的环境变量条目:
TOMCAT SERVICE SERVICE HOST=69.169.41.218
TOMCAT SERVICE SERVICE PORT SERVICE PORT=8080
TOMCAT SERVICE SERVICE PORT SHUTDOWN PORT=BOOS
TOMCAT SERVICE SERVICE PORT=8080
TOMCAT SERVICE PORT 8005 TCP PORT=BOOS
TOMCAT SERVICE PORT=tcp://169.169.41.218:8080
TOMCAT SERVICE PORT 8080 TCP ADDR=l69.169.41.218
TOMCAT_SERVICE_PORT_8080_TCP=tcp://169.169.41.218:8080
TOMCAT SERVICE PORT 8080 TCP PROTO=tcp
TOMCAT SERVICE PORT 8080 TCP PORT=8080
TOMCAT_SERVICE_PORT_8005 TCP=tcp://169.169.41 18:8005
TOMCAT SERVICE PORT 8005 TCP ADDR=169.169.41.218
TOMCAT SERVICE PORT 8005 TCP PROTO=tcp
上述环境变量中,比较重要的是前3条环境变量,我们可以看到,每个 Service 的 IP地址及端口都是有标准的命名规范的,遵循这个命名规范,就可以通过代码访问系统环境变量的方式得到所需的信息,实现服务调用。
外部系统访问 Service 的问题
为了更加深入地理解和掌握 Kubemetes ,我们需要弄明白 Kubemetes 里的"三种IP"这个关键问题,这三种IP分别如下。
- Node IP: Node 节点的 IP 地址
Node IP Kubemetes 集群中每个节点的物理网卡的 IP 地址. - Pod IP: Pod IP 地址
Pod IP 是每个 Pod IP 地址,它是 Docker Engine 根据 docker0网桥的IP地址段进行分配的,通常是一个虚拟的二层网络,前面我们说过, Kubemetes 要求位于不同 Node 上的Pod 能够彼此直接通信,所以 Kubemetes 里一 Pod 里的容器访问另外一 Pod 里的容器,就是通过 Pod 在的虚拟二层网络进行通信的,而真实的 TCP/IP 则是通过Node 在的物理网卡流出的. - Cluster IP: Service 的IP地址
- Cluster IP仅仅作用 Kubemetes Service 这个对象,并由 Kubemetes 管理和分配 IP地址(来源于 Cluster 地址池);
- Cluster 无法被 Ping 因为没有一个“实体网络对象”来响应;
- Cluster 只能结合 Service Port 组成 个具体的通信端口,单独的Cluster 具备TCP/IP的基础,并且它们属于 Kubemetes 集群这样一个封闭的空间, 集群之外的节点如果要访问这个通信端口 ,则需要做一些额外的工作;
- 在Kubemetes 集群之内, Node 网、 Pod IP 网与 Cluster 网之间的通 采用的是Kubemetes 自己设计的一种编程方式的特殊的路由规则,与我们所熟知的 路由有很大的不同。
以tomcat-service 为例,我们在 Service 的定义里做如下扩展即可:
apiVersion : vl
kind: Service
metadata :
name : tomcat-service
spec:
type: Node Port
ports:
- port: 8080
nodePort: 31002
selector:
tier: frontend
只要我们把 Service type=NodePort改为type=LoadBalancer ,此时 Kubemetes 会自动创建一个对应的 Load balancer 实例并返回它的 IP 地址供外部客户端使用。其他公有云提供商只要实现了支持此特性的驱动,则也可以达到上述目的。此外,裸机上的类似机制( Bare Metal Service Load Balancers )也正在被开发.