共计 10644 个字符,预计需要花费 27 分钟才能阅读完成。
作者
冉昕,腾讯云服务网格 TCM 产品经理,现负责云原生流量接入网关与利用通信可观测性等产品个性策动与设计工作。
刘旭,腾讯云高级工程师,专一容器云原生畛域,有多年大规模 Kubernetes 集群治理及微服务治理教训,现负责腾讯云服务网格 TCM 数据面产品架构设计和研发工作。
引言
利用的入口流量治理始终是开发运维关注的焦点之一,随业务部署的计算资源、网络环境、利用架构的倒退变更,接入层流量治理计划的倒退可大抵分为传统架构、云原生容器化两个阶段。为满足利用交付的效率和诉求,各阶段都涌现了不同的接入层解决方案,从最后的简略负载平衡,到起初的 HAProxy、Nginx 等反向代理,再到现在的容器化环境下的各类 Kubernetes Ingress Controller。每个倒退阶段有哪些特点?面临什么挑战?都有什么解决方案?
阶段 | 利用部署资源粒度 | 利用架构 | 利用拜访寻址 |
---|---|---|---|
传统架构 | 物理 / 虚拟机(资源利用率低) | 单体或简略拆分模块 | 基于较固定的 IP 地址治理 |
云原生容器化 | 容器(资源利用率高) | 服务化 | 容器 IP 动态变化,通过动静服务注册更新 |
传统架构阶段,业务为单体利用,三层架构;部署于物理机 / 虚拟机;网络环境基于 IP 地址治理,绝对固定,根本不会变动;业务更新迭代的速度较慢,接入层的次要需要是具备 4 层和 7 层的负载平衡能力,用传统负载均衡器反对即可。随着利用架构演进(利用做了肯定模块拆分)和迭代效率的晋升,呈现了一些更简单的接入层诉求:按流量内容特色路由、灰度公布、限流、鉴权等,个别通过在负载均衡器后减少一层网络代理(e.g. Nginx)反对,网络代理 Nginx 具备更多的 7 层流量解决的能力,可通过 OpenResty 社区的 Lua 扩大上述内容路由、灰度公布、鉴权限流等高级性能。
云原生容器化阶段的现实状态是业务开发者只需专一实现业务逻辑,无需关怀资源调度和运维治理,可真正做到按需应用,按量计费。虚拟机 / 物理机资源粒度毛糙,利用效率较低,需提前布局计算、存储、网络资源,与现实状态有较大差距。云原生阶段,容器资源的粒度更细,利用率高,启动 / 销毁速度达到秒级,可灵便弹性伸缩(Kubernetes 已成为容器编排调度的业界规范,以下容器环境均代指 Kubernetes 集群);网络管理环境也产生了变更,呈现 Service 的概念,一个微服务往往是由一组弹性伸缩、动静调度的容器(Pod)承载,Pod 的 IP 地址动态变化,这一组 Pod 个别以 Service 对外提供拜访,流量治理是以 Service 为单位。服务化拆分业务模块构建利用更容易,加上容器环境良好的弹性伸缩能力,DevOps 理念得以很好的施行,微服务的迭代步调放慢,常常须要滚动更新。此时的入口流量治理面临如下新挑战:
- 须要与 Kubernetes 集成,反对转发流量到指定 Pod。
- 更新迭代速度放慢,对服务新版本灰度公布的诉求更加强烈。
- 呈现集群概念,集群之间的服务发现是隔离的,接入层需反对跨集群的服务发现(即接入层可抉择 backend 为多个集群的 Pod);这区别于传统物理机 / 虚拟机阶段,没有集群隔离,只需保障网络联通性,即可配置接入层后端为任意对应服务的 IP 地址。
- 传统阶段到云原生阶段的迁徙过程中,呈现 VM、容器环境混布的状况。
基于上述挑战,呈现了以下容器环境的接入层流量治理解决方案:
- Kubernetes 官网定义的 Ingress API:老牌网络代理(e.g. Nginx,HAProxy)或云厂商的负载平衡产品(e.g. AWS Elastic Load Balancer,腾讯云 CLB)都实现了各自的 Ingress Controller,作为单个集群的入口流量治理解决方案。灰度公布、鉴权限流等能力,视 Ingress Controller 的能力,可通过 Annotation 扩大,局部 Ingress Controller 还设计了本人的流量治理模型和语法。
- Service Mesh Ingress:服务网格的服务发现和治理界线大于集群纬度,以 Istio Ingress Gateway 为例,基于 Istio 跨集群的服务发现能力,backend 能够来自不同集群的服务,同时还反对注册在网格内运行在虚拟机上的服务。Istio 也设计了本人的治理模型和语法,申明式反对配置统一的南北 + 东西向流量治理。
- 沿用原有 VM 上部署的网络代理,转发流量至 VM 服务或 Kubernetes 集群的服务。
上面本文将从云原生容器化环境入口流量治理应用场景切入,带您理解云原生接入层流量治理的各类解决方案及优劣比照。
云原生接入层流量治理场景与解决方案
场景一:根底流量治理
入口流量治理的首个应用场景是须要将服务裸露给内部,供客户端调用。常见的形式是将服务按 URL 裸露,例如一个电商网站,须要将 /login 的申请路由到登陆服务,将 /product 的申请路由到商品服务等,该场景要求接入层具备基于流量内容路由的能力。
计划:Load Balancer + NodePort
在容器化的晚期阶段,利用同时部署在虚拟机和 Kubernetes 集群上,很多用户会应用原有负载平衡(e.g. Nginx, 腾讯云 CLB)将申请别离转发到虚拟机和容器,同时受限于容器网络计划,原有负载平衡不能间接拜访 Pod IP,因而须要通过 NodePort 裸露集群内的服务。
然而该计划存在以下问题:
- NodePort 端口数量无限(默认 30000-32767)
- 随着集群规模的扩充,Nginx 配置文件越来越简单,不易治理
- 用户将利用公布到 Kubernetes 集群后,须要再独自批改 Nginx 配置,体验不够云原生
计划:Kubernetes Ingress
Kubernetes 提供了 Ingress API [1] 用于裸露集群内的 HTTP 服务,Ingress 反对基于 Host 和 Path 将申请路由到不同 Service。为了让 Ingress 工作,集群必须有一个正在运行的 Ingress 控制器(e.g. Nginx Ingress Controller)。原生 Ingress 语法提供简略的基于 Host,Path 路由,以及配置 TLS 的能力。
1. 基于 Host 路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: public-services
namespace: default
spec:
rules:
- host: service1.tencent.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /
- host: service2.tencent.com
http:
paths:
- backend:
serviceName: service2
servicePort: 80
path: /
2. 基于 Path 路由
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: public-services
namespace: default
spec:
rules:
- host: services.tencent.com
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /service1
- backend:
serviceName: service2
servicePort: 80
path: /service2
3. TLS 配置
Ingress 也提供了 TLS 反对,能够将集群内的 HTTP 服务对外裸露为 HTTPS,咱们须要先将 SSL 证书以 Secret 的模式保留在集群中,再应用 Ingress 援用刚刚创立的 Secret。
apiVersion: v1
kind: Secret
metadata:
name: public-services-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: services-with-tls
namespace: default
spec:
tls:
- hosts:
- services.tencent.com
secretName: public-services-tls
rules:
http:
paths:
- backend:
serviceName: service1
servicePort: 80
path: /service1
- backend:
serviceName: service2
servicePort: 80
path: /service2
Kubernetes Ingress 小结:对于简略的 HTTP 流量的路由,应用 Ingress 配置非常容易,这也是以后 Ingress 受欢迎的起因(据 CNCF 2020 云原生调查报告 [2],50% 的用户正在或行将应用第三方代理做利用流量转发,其中 Nginx 和 Envoy [3] 是最受欢迎的 Ingress provider)。
然而另一方面原生 Ingress 的性能非常无限,不能满足很多简单场景的需要。许多第三方的 Ingress Controller [4] 通过 annotation 或新的配置模型和语法扩大了原生 Ingress 的性能,但依然受限于集群间服务发现隔离的问题,只能作为单集群入口流量治理计划。
场景二:灰度公布
服务可裸露给内部拜访后,还须要思考如何做版本公布,做平滑、无风险地迭代。常见的两种做法是按权重或流量内容切局部流量至新版本验证稳定性,无问题后逐步过渡至新版本,即咱们熟知的灰度公布、AB test。
Kubernetes Ingress API 原生并没有灰度公布的性能,Nginx ingress controller 通过 annotation 的形式扩大了原生 Ingress API 的性能,实现了灰度公布,但这种形式并不能很好地撑持管制利用流量的公布策略,相比之下,Istio CRD 配置更灵便易用,上面介绍如何应用 Istio VirtualService 配置灰度公布路由规定。
1. 基于权重
Istio 可通过 Virtual Service 配置基于权重的灰度公布,以下是配置来自 {namespace}/{gateway} 的入口流量 95% 路由到 {service} 的 current 版本,5% 路由到 canary 版本的示例:
apiVersion: ...
kind: VirtualService
metadata:
name: canary-weight
spec:
hosts:
- '*'
gateways:
- {namespace}/{gateway}
http:
- route:
- destination:
host: {service}
subset: current
weight: 95
- destination:
host: {service}
subset: canary
weight: 5
2. 基于申请内容
VirtualService 也反对配置基于内容的灰度公布路由规定,以下是配置来自 {namespace}/{gateway} 的入口流量 header cookie “version=stable” 时路由到 {service} 的 current 版本,”version=canary” 时路由到 {service} 的 canary 版本的示例:
apiVersion: ...
kind: VirtualService
metadata:
name: canary-content
spec:
hosts:
- '*'
gateways:
- {namespace}/{gateway}
http:
- match:
- headers:
cookie:
exact: version=stable
route:
- destination:
host: {service}
subset: current
- match:
- headers:
cookie:
exact: version=canary
route:
- destination:
host: {service}
subset: canary
场景三:利用流量鉴权与限流
鉴权与限流,是保障南北流量的安全性与健壮性的两个重要能力。
接入层是拜访后端服务的对立入口,保障接入层的平安是接入层流量治理的一个重要场景,个别在入口处须要配置认证与受权规定,传统架构下认证受权性能个别通过代码逻辑实现,Istio 自 1.5 之后提供了 AuthorizationPolicy 和 RequestAuthentication CRD [5],可灵便配置入口层的认证和受权规定。
1. 申请身份认证(JWT)
入口处认证申请携带的 Json Web Token,放通携带非法令牌的申请,回绝携带非法令牌的申请。
以下是应用 Istio RequestAuthentication 配置 Ingress Gateway 放通携带非法 JWT 申请的配置示例:
apiVersion: ..
kind: RequestAuthentication
metadata:
name: jwt-example
namespace: istio-system
spec:
selector:
matchLabels:
istio: ingressgateway
jwtRules:
- issuer: {issuer that issued the JWT}
jwksUri: {URL of the provider’s public key set to validate signature of the JWT}
2. 受权
在入口处配置受权策略,依据流量内容特色,容许 / 回绝流量拜访,例如在入口处配置 IP 黑 / 白名单;或有内部鉴权服务,心愿入口组件可对接内部鉴权服务,依照其返回的鉴权后果放通 / 回绝流量。
以下是应用 Istio AuthorizationPolicy 为 Ingress Gateway 配置 IP block 白名单的示例:
apiVersion: ...
kind: AuthorizationPolicy
metadata:
name: white-list
namespace: istio-system
spec:
selector:
matchLabels:
app: istio-ingressgateway
action: ALLOW
rules:
- from:
- source:
ipBlocks: {single IP or CIDR}
Istio 1.9 加强了对 AuthorizationPolicy 对于对接内部鉴权零碎的反对,可配置 Ingress Gateway 依照内部鉴权零碎返回的后果放通或回绝流量。
apiVersion: ...
kind: AuthorizationPolicy
metadata:
name: ext-authz
namespace: istio-system
spec:
selector:
matchLabels:
app: istio-ingressgateway
action: CUSTOM
provider:
name: "my-ext-authz-service"
rules: ...
3. 限流
业务规模较大,后端服务提供给泛滥租户应用时,须要在入口处管制申请的速率,例如限度每个 User ID 每分钟只能申请“/product”接口 100 次。
为了应用 Istio Ingress Gateway 的限流性能,首先须要装置 Ratelimit service,能够自行实现或间接应用社区的 ratelimit [6],而后应用 Envoyfilter 配置限流规定,具体配置办法可参考官网文档[7]。
场景四:多集群异构场景入口流量治理
随着业务规模的减少,或对容灾、数据合规性、业务之间隔离要求的晋升,业务会思考与施行部署多个 Kubernetes 集群,甚至会呈现容器化环境与非容器化环境异构混布的状况,给入口流量治理又带来了一系列新的挑战。
多 Kubernetes 集群个别是基于容灾和业务隔离两方面的思考:
(1)容灾。Kubernetes 集群有地区属性,依据利用交付提供服务的拜访时效和容灾诉求,同一利用可能散布在多个不同的天文区域。多(私有)云、混合云(IDC + 私有云)架构的容灾,也需部署多个集群。跨地区多集群容灾与就近接入可通过 DNS 解析提供,但 DNS 有缓存,故障转移理论失效工夫可能较长,并且无奈视服务衰弱水平切局部流量到备份地区,只能全副切换。
Istio 基于以下能力:1. 多集群服务发现能力;2. 地区感知、故障感知、容灾流量容量布局,可实现:1. 当所有集群的服务都衰弱时,依照申请起源地就近路由至对应服务;2. 某个集群的服务呈现局部故障时,视服务的衰弱水平转移肯定比例的流量到其余集群的备份服务。
(2)业务隔离。据 CNCF 2020 云原生调查报告显示 [2],用多个集群做利用隔离是仅次于用 namespace 隔离的应用形式,使用率从 2019 年的 47% 回升到了 2020 年的 50%。多个业务仍共用一个流量入口时,接入层需具备多集群服务发现的能力,将流量按指定策略路由至指定集群的服务。
计划:Service Mesh Ingress
Kubernetes Ingress Controller 遇到的一个挑战是,Kubernetes 集群隔离了集群间的服务发现,Ingress Controller 只能作为集群级别的流量入口。而 Service Mesh 技术借助于管制面服务发现的能力,可发现或注册多个集群的服务甚至异构服务,买通集群间的服务发现壁垒,不受利用部署平台限度,人造提供统一的接入流量转发治理能力。
Istio 作为最受欢迎的 Service Mesh 开源我的项目,它的接入层 Istio Ingress Gateway 同样提供了对 Ingress API 的反对,然而不倡议应用 Ingress 去配置 Ingress Gateway,这大大减弱了 Istio 的能力。Istio 对流量治理模型提供了更高水平的形象,能够间接应用 Istio API 实现更灵便的流量治理能力,实现灰度公布,跨集群路由,地区感知等高级个性。
Istio Ingress Gateway 基于 Envoy [3] 实现,Envoy 最后由 Lyft 创立,是一款为云原生场景设计的高性能服务代理软件,后由 Lyft 募捐到了 CNCF 社区,并已从 CNCF 毕业。
1. 多 Kubernetes 集群服务治理
Istiod 能够通过网格内所有集群的 API Server 来获取 endpoints 信息,聚合多个集群的信息后,将最终生成的配置推送到 Ingress Gateway,Ingress Gateway 能够将申请按需转发至网格内所有 Pod。
2. 地区感知负载平衡
在服务网格中,一个 Pod 的地理信息包含以下 3 个局部 [8]:
- Region(地区):通常代表一个较大的天文区域(e.g 北京 上海),在 Kubernetes 中,节点的地区由标签
topology.kubernetes.io/region
决定 - Zone(可用区):一个地区通常蕴含多个可用区(e.g. 北京一区 北京二区),在 Kubernetes 中,节点的可用区由标签
topology.kubernetes.io/zone
决定 - Sub-zone:容许对可用区做进一步划分实现更细粒度的管制,例如能够依照 rack(机架)划分,在 Kubernetes 中不存在 sub-zone 的概念,Istio 应用节点的
topology.istio.io/subzone
标签来定义 sub-zone
如果应用云厂商托管的 Kubernetes 服务,节点的 Region 和 Zone 标签已由云厂商配置,例如在 TKE 集群中,上海二区的节点会有以下标签:
topology.kubernetes.io/region: sh
topology.kubernetes.io/zone: "200002"
网格内的集群可能散布在不同地区不同可用区,大多数状况下,咱们心愿尽量减少跨地区 / 跨可用区的申请调用,因为这会减少申请时延。因而接入层需具备感知 endpoints 地理信息的能力,并反对依据地理信息配置负载平衡及故障转移策略。
(1)地区故障转移
在开启地区负载平衡的状况下,Istio 会告知 Ingress Gateway 将申请就近转发。当所有实例都失常时,申请将放弃在同一地点,当实例异样时,流量会散发到下一优先地区的实例。
例如,位于 bj.bj-01 的 Ingress Gateway 转发申请的优先级如下:
优先级 | 地理位置 | |
---|---|---|
1 | bj.bj-01 | Region Zone 齐全匹配 |
2 | bj.bj-02 | Region 匹配 Zone 不匹配 |
3 | sh.sh-01/sh-02 | Region Zone 都不匹配 |
(2)地区加权负载平衡
地区加权负载平衡能够将用户定义的肯定百分比的流量散发到某些地区,例如咱们能够应用如下配置散发流量:
global:
localityLbSetting:
enabled: true
distribute:
- from: bj/bj-01/*
to:
"bj/bj-01/*": 70
"bj/bj-02/*": 20
"sh/sh-01/*": 10
3. 异构服务入口流量治理
除了多集群,用户在云原生革新的过程中,经常会面临局部服务曾经做了容器化革新,运行在 Kubernetes 集群,局部不便革新的服务仍在虚拟机的状况,甚至会有局部应用的是云厂商 serverless 云函数服务(e.g. AWS lambda)。接入层需具备异构服务注册 / 发现的能力,以治理异构部署服务的南北向流量。
能够通过 Istio 提供的 WorkloadGroup 和 WorkloadEntry 将虚拟机上的服务注册到网格内,同一个服务能够同时运行在 Kubernetes 集群和虚拟机上。
Istio Ingress Gateway 小结:Istio Ingress Gateway 在入口灰度公布、平安、多集群异构流量治理等场景提供了多集群服务发现、地区感知、流量容量布局,以及更弱小灵便的流量治理 API 的反对,但与此同时,用户也不得不面对 Istio 的复杂性。须要投入资源和人力老本运维 Istiod 和 Istio Ingress Gateway,集成 metric,trace,log 等可观测性及证书治理周边零碎老本较高,还须要正确配置各种 CRD(Gateway VirtualService DestinationRule 等)。
接入层解决方案性能比照
以下是腾讯云容器环境下常见的接入层解决方案性能比照。
多集群灰度公布 / 跨集群容灾 Demo
上面将应用腾讯云服务网格 TCM 控制台演示 Service Mesh Ingress 做多 Kubernetes 集群环境下的灰度公布和容灾。
- 创立服务网格,增加两个部署服务的服务发现集群(根底监控指标主动对接到云监控,可在控制台查看,可视状况开启云原生监控,满足自定义监控诉求),勾选启用 Ingress Gateway
- 应用 Destination Rule 定义 frontend 服务的版本(frontend 服务在两个集群均有同样的部署)
- 应用 Gateway 配置 ingress gateway 监听规定,开启 443 端口 https 拜访,应用腾讯云 SSL 平台服务器证书
- 应用 VirtualService 配置路由规定,50% 流量路由至 v1 版本,50% 路由至 v2 版本
- 有拜访申请后,查看工作负载(frontend,frontend-canary)监控,两个版本均有流量,比例大抵 1:1
- 灰度完结,更改权重,100% 的流量均路由至 v2 版本,再次查看工作负载的监控数据,发现所有流量都已申请至 frontend-canary
- 上面咱们通过调整其中一个集群的 frontend 服务工作负载 Pod 数量为 0 来模仿其中一个集群 frontend 服务故障状况,发现其中一个集群 frontend 服务故障后,仍能够失常拜访该服务,查看另一集群的 frontend 服务的工作负载监控,会发现入带宽减少了一倍,表明其中一个集群的服务故障后,流量容灾切到了另一集群。
- 如有扩大东西向流量治理的须要,能够给业务注入 envoy sidecar,即可应用同一套 Istio API 实现南北东西向流量一致性治理,开箱即用网络拓扑、调用追踪等可观测性功能。
腾讯云服务网格 TCM,是腾讯云齐全兼容 Istio 的 Service Mesh 产品,目前已实现了管制面组件托管,应用 TCM Ingress Gateway 只须要部署一组数据面 envoy pod 在业务集群,即可开箱即用上述 Istio Ingress Gateway 的所有入口流量治理能力。同时,TCM 集成了腾讯云监控、证书周边产品,提供开箱即用的可观测能力和证书配置性能。
结语
本文由业务部署倒退的两个阶段引入,介绍了:
- 云原生容器化环境下接入层流量治理的典型场景。
- 入口流量治理的解决方案及优劣比照。
- 以腾讯云服务网格 TCM 为例,演示 Service Mesh Ingress 多集群环境下灰度公布及服务跨集群容灾的能力。
次要论断有:
- 对于简略的 HTTP 流量的路由,应用 Kubernetes 原生 Ingress 配置非常容易,一些 Ingress Controller(e.g. Nginx, Traefik)也通过 annotation 或 CRD 扩大了原生 Ingress 的性能,但仍是集群级别的流量入口。
- Service Mesh 级别的接入层,借助管制面服务发现的能力,可作为多集群 / 异构环境下的对立流量入口,可具备跨集群路由,地区感知等高级个性;后续也可平滑扩大统一语法治理东西向流量。
本文是云原生接入层流量治理系列文章的第一篇,后续咱们将会推出一系列文章具体介绍入口流量治理、平安、可观测性、多集群异构入口流量治理等场景下的最佳实际。
Reference
[1] https://kubernetes.io/docs/co…
[2] https://www.cncf.io/wp-conten…
[3] https://www.envoyproxy.io/doc…
[4] https://kubernetes.io/docs/co…
[5] https://istio.io/latest/docs/…
[6] https://github.com/envoyproxy…
[7] https://istio.io/latest/docs/…
[8] https://istio.io/latest/docs/…
【腾讯云原生】云说新品、云研新术、云游新活、云赏资讯,扫码关注同名公众号,及时获取更多干货!!