在实际使用场景中,两个 K8s 集群之间经常有互相访问的需求,或者 K8s 集群有访问集群外部某些服务的需求,常规的解决方案是手动维护固定的 Services 和 Endpoints,或者直接在业务配置中写死 IP。但这些方案都没有对外部服务的探活功能,无法实现高可用。如果引入外部高可用负载均衡,又会增加复杂度,且很多公司不具备引入外部负载均衡的条件,所以这个方案不是最优解。
众所周知,kube-proxy 的主要功能是维护集群内的 Services 和 Endpoints,并在对应主机上创建对应的 IPVS 规则,因此 Pod 之间可以通过 ClusterIP 相互访问。
受 kube-proxy 启发,新的想法诞生了:编写一个 Controller,维护一个 CRD 来自动创建需要访问的外部服务所对应的 Service 和 Endpoint,并对创建的 Endpoint 中的外部服务数据(IP:Port 列表)进行探活,探活失败则移除对应的外部服务数据。
于是 endpoints-operator[1] 项目隆重登场!
endpoints-operator 介绍
endpoints-operator 是一个云原生、高可靠性、高性能、面向 K8s 内部服务访问外部服务的具备探活功能的 4 层 LB。
特性
更加贴近云原生
声明式 API:探活的定义方式与 Kubelet 保持一致,还是熟悉的语法、熟悉的味道
高可靠性:原生 Service、Endpoint 资源,拒绝重复造轮子
高性能、高稳定:原生 IPVS 高性能 4 层负载均衡
核心优势
完全使用 K8s 原生的 Service、Endpoint 资源,无自定义 IPVS 策略,依托 K8s 的 Service 能力,高可靠。
通过 controller 管理一个 CRD 资源 ClusterEndpoint(缩写 cep)即可,无需手动管理 Service 和 Endpoint 两个资源
完全兼容已有的自定义 Service、Endpoint 资源,可无缝切换至 endpoints-operator 管理。
原生的 IPVS 4 层负载,未引入 Nginx、HAProxy 等 LB,降低了复杂度,满足高性能和高稳定性的需求
使用场景
主要使用在集群内部的 Pod 需要访问外部服务的场景,比如数据库、中间件等,通过 endpoints-operator 的探活能力,可及时将有问题的后端服务剔除,避免受单个宕机副本影响,并可查看 status 获取后端服务健康状态和探活失败的服务。
使用介绍
安装
$ git clone https://github.com/sealyun/endpoints-operator.git
$ cd endpoints-operator
$ checkout v0.1.0
$ helm install -n kube-system endpoints-operator config/charts/endpoints-operator
创建一个健康的 ClusterEndpoint 数据
apiVersion: sealyun.com/v1beta1
kind: ClusterEndpoint
metadata:
name: wordpress
namespace: default
spec:
hosts:
- 172.18.191.215
periodSeconds: 10
ports:
- failureThreshold: 3
name: https
port: 38082
protocol: TCP
successThreshold: 1
targetPort: 80
tcpSocket:
enable: true
timeoutSeconds: 1
- httpGet:
path: /
scheme: http
name: http
port: 38081
protocol: TCP
targetPort: 80
经过 Controller 处理后发现
apiVersion: sealyun.com/v1beta1
kind: ClusterEndpoint
metadata:
creationTimestamp: "2022-01-18T13:44:08Z"
generation: 1
name: wordpress
namespace: default
resourceVersion: "610358"
uid: 41303de7-9706-487a-8204-79a3a358730f
spec:
hosts:
- 172.18.191.215
periodSeconds: 10
ports:
- failureThreshold: 3
name: https
port: 38082
protocol: TCP
successThreshold: 1
targetPort: 80
tcpSocket:
enable: true
timeoutSeconds: 1
- httpGet:
path: /
scheme: http
name: http
port: 38081
protocol: TCP
targetPort: 80
status:
conditions:
- lastHeartbeatTime: "2022-01-18T13:44:08Z"
lastTransitionTime: "2022-01-18T13:44:08Z"
message: cluster endpoints has been initialized
reason: Initialized
status: "True"
type: Initialized
- lastHeartbeatTime: "2022-01-18T13:44:08Z"
lastTransitionTime: "2022-01-18T13:44:08Z"
message: sync service successfully
reason: SyncServiceReady
status: "True"
type: SyncServiceReady
- lastHeartbeatTime: "2022-01-18T13:44:08Z"
lastTransitionTime: "2022-01-18T13:44:08Z"
message: sync endpoint successfully
reason: SyncEndpointReady
status: "True"
type: SyncEndpointReady
- lastHeartbeatTime: "2022-01-18T13:44:08Z"
lastTransitionTime: "2022-01-18T13:44:08Z"
message: ClusterEndpoint is available now
reason: Ready
status: "True"
type: Ready
phase: Healthy
验证 Service 和 Endpoint 数据
$ kubectl get cep wordpress
NAME AGE STATUS
wordpress 108m Healthy
$ kubectl get svc wordpress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress ClusterIP 10.104.2.110 <none> 38082/TCP,38081/TCP 108m
$ kubectl get ep wordpress
NAME ENDPOINTS AGE
wordpress 172.18.191.215:80,172.18.191.215:80 108m
ClusterEndpoint 数据 status 变更
将其中一个端口立即关掉则 cep 的状态已经变为 UnHealthy
$ kubectl get cep wordpress
NAME AGE STATUS
wordpress 115m UnHealthy
$ kubectl get svc wordpress
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress ClusterIP 10.104.2.110 <none> 38083/TCP,38081/TCP 115m
$ kubectl get ep wordpress
NAME ENDPOINTS AGE
wordpress 172.18.191.215:80 115m
总结
endpoint-operator 从开发的角度更优雅地解决了集群内访问外部服务的问题,实现方式更加云原生,对产品无任何侵入。后续将会支持更多的探活协议,比如 UDP/gRPC 等。还会支持监控以及 Webhook 校验等功能。
有兴趣欢迎到 GitHub 贡献代码 : https://github.com/sealyun/endpoints-operator
引用链接
[1]
endpoints-operator: https://github.com/sealyun/endpoints-operator
你可能还喜欢
点击下方图片即可阅读
云原生是一种信仰 🤘
关注公众号
后台回复◉k8s◉获取史上最方便快捷的 Kubernetes 高可用部署工具,只需一条命令,连 ssh 都不需要!
点击 "阅读原文" 获取更好的阅读体验!
发现朋友圈变“安静”了吗?