网关的K8s化不是一蹴而就的。在最早期,流利说的流量较小、业务形态较为简单。业务网关层采用的是最简单的单点Nginx部署架构;后端服务采用Docker,部署在不同的ECS上,并将相应的IP + Port通过upstream的方式配置在Nginx的虚拟服务器里 —— 客户端的请求全部打向单节点的Nginx,Nginx通过7层代理,将请求转发到对应的后端服务。当有路由变更需求或者流量切换时,基础架构的同事通过登陆Nginx服务器,修改配置文件的方式来解决,如下图所示。
至此,研发可以完全自助地对各自应用进行发版与路由变更,而基础架构的同事可以专注于架构优化、链路可视化、监控告警、自动化工具开发等工作。
后来在针对业务网关层Kong维护的过程中,又发现了以下几个痛点:
虽然上述有些问题可以通过云上Auto Scaling Group产品本身的一些特性,并对接云上API开发自动化平台来解决,但是不同云厂家的Auto Scaling Group的产品特性是不一样的,暴露出的API也不一样,无论从云上界面的使用还是对接云上API制作自动化工具,成本都是比较高的。“架构大演进”后,随着我们对K8s的逐渐熟悉,发现可以利用K8s Deployment、HPA解决业务网关层Kong的运维痛点,使网关层的维护更轻量、更安全可控。在网关层K8s化的过程中,主要需要确认以下三个问题:
经过七天不间断的压测,从链路延迟的P95和P99结果可以得出,在各项条件对齐的情况下,K8s化后的Kong对整链路的延迟并没有影响。
Kong in ASG 7 days P99 & P95(2021-09-18 14:30~2021-09-25 14:30) | |
---|---|
host | nginx-test.llstest.com |
7 days P99 | 0.005s |
7 days P95 | 0.004s |
Kong in K8s 7 days P99 & P95(2021-09-28 10:15~2021-10-04 10:15) | |
---|---|
host | nginx-test.llstest.com |
7 days P99 | 0.005s |
7 days P95 | 0.004s |
Kong Pod的优雅停止是指在删除Pod的过程中,比如手动删除Pod以实现重启、Kong Deployment的滚动更新、HPA扩缩容、云上K8s集群自动扩缩容的过程中,是否会中断已有的服务(尤其是长连接服务)。
4.2.1. Pod终止生命周期简介
1. Pod被设置为Terminating状态,并将其从对应Service的Endpoints列表中移除
2. 执行preStop hook
3. SIGTERM信号发送给Pod
4. Kubernetes等待宽限期
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: busybox
terminationGracePeriodSeconds: 60
Usage: kong quit [OPTIONS]
Gracefully quit a running Kong node (Nginx and other
configured services) in given prefix directory.
This command sends a SIGQUIT signal to Nginx, meaning all
requests will finish processing before shutting down.
If the timeout delay is reached, the node will be forcefully
stopped (SIGTERM).
Options:
-p,--prefix (optional string) prefix Kong is running at
-t,--timeout (default 10) timeout before forced shutdown
-w,--wait (default 0) wait time before initiating the shutdown
$ kong quit -p ${PREFIX_DIR} -t ${TIMEOUT}
apiVersion: apps/v1
kind: Deployment
metadata:
name: kong-proxy
labels:
kong :
kong-proxy :
namespace: kong-proxy
spec:
replicas: 2
selector:
matchLabels:
kong :
kong-proxy :
template:
metadata:
annotations:
"true" :
labels:
name: kong-proxy
kong :
:
containers:
name: kong-proxy
our.registry.com/fake-repo-here/cutom-kong-docker:version :
imagePullPolicy: Always
["start_command"] :
["some", "args", "at", "here"] :
ports:
name: http-proxy
80 :
# start of readiness probe & liveness probe
readinessProbe:
exec:
["kong_health_check.sh"] :
initialDelaySeconds: 8
livenessProbe:
exec:
command: ["kong_liveness_check.sh"]
periodSeconds: 10
# end of readiness probe & liveness probe
/you_guess :
resources:
requests:
memory: "1Gi"
cpu: "1"
limits:
memory: "2Gi"
cpu: "2"
# Graceful shutdown settings - Timeout in Kong container level
lifecycle:
preStop:
exec:
command: ["kong", "quit", "-p", "/kong/prefix/path", "-t", "2700"]
# Graceful shutdown settings - Timeout in Kong container level
nodeSelector:
kong :
tolerations:
key: app
operator: Equal
value: kong
NoSchedule :
# Graceful shutdown settings - Timeout in pod level
terminationGracePeriodSeconds: 3600
# 把kong-proxy pod加入到和Kong in ASG相同的虚拟服务器组里
apiVersion: v1
kind: Service
metadata:
annotations:
# 指定已有的loadbalancer id
lb-loadbalancer-id-that-currently-used :
# 设置目标虚拟服务器组ID,及将流量转发到组里服务器的服务端口号
rsp-virtual-server-port:80 :
# 设置打向Pod上的流量权重
"10" :
# 设置不要覆盖已有的监听配置
# service.beta.kubernetes.io/alicloud-loadbalancer-force-override-listeners: 'false'
labels:
app: kong-proxy
name: kong-proxy
name: kong-proxy
namespace: kong-proxy
spec:
ports:
name: http-proxy
port: 80
protocol: TCP
targetPort: 80
selector:
app: kong
kong-proxy :
type: LoadBalancer
通过该方式将Kong Pod接入到已有SLB中提供服务,其架构如下所示。此时Kong in Asg和Kong in K8s两个架构可以在环境中双跑,架构的切换和发现问题时架构快速回滚的方案,就简化成了在SLB上切换目标服务器的权重。
当前流利说已经完成业务网关Kong的K8s化。通过CronHPA,我们可以实现每日在业务高峰来临前提前扩容Kong Pod的实例;当K8s的计算资源不够时,能够通过云上的Cluster Auto Scaler自动扩展集群节点;Kong本身的配置或版本更新也更轻量化,结合已有的GitOps流程和CD系统,基础架构的同学只需要更新Dockerfile和相关的配置文件,然后git push即可触发自动构建镜像、自动业务不中断地滚动更新网关;通过Deployment控制器中提供的参数控制,可以灵活地定制Kong Pod滚动更新或回滚的策略。和原先相比,能够更轻松、更安全可靠地对网关层进行维护。
在将网关层K8s化的同时,流利说后端业务K8s也已经逐渐接入Istio;利用K8s LoadBalancer type Service和云上LB带来的优势,在未来我们计划将网关层的Kong平滑地替换成Istio Gateway,以提升整体链路的可观测性。