从概念、部署到优化,Kubernetes Ingress 网关的落地实践

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 随着容器和 Kubernetes 技术的兴起,集群入口流量管理方式逐渐通用化、标准化。Kubernetes 通过 Ingress 资源用来管理外部 HTTP/HTTPS 流量进入集群内部的方式。目前,Ingress 的实现者 - Provider 的发展呈现百花齐放的状态,用户可以根据自身业务场景进行产品选型。为了帮助用户从建好 Ingress 网关到用好 Ingress 网关,本文将分享 Kubernetes 集群内,Ingress 网关从概念到部署的落地实践以及 MSE 云原生网关如何更好地实现 Kubernetes Ingress。

Kubernetes Ingress 简介

通常情况下,K8s 集群内的网络环境与外部是隔离的,也就是说 K8s 集群外部的客户端无法直接访问到集群内部的服务,这属于不同网络域如何连接的问题。解决跨网络域访问的常规做法是为目标集群引入一个入口点,所有外部请求目标集群的流量必须访问这个入口点,然后由入口点将外部请求转发至目标节点。

同样,K8s 社区也是通过增设入口点的方案来解决集群内部服务如何对外暴露的问题。K8s 一贯的作风是通过定义标准来解决同一类问题,在解决集群对外流量管理的问题也不例外。K8s 对集群入口点进行了进一步的统一抽象,提出了3种解决方案:NodePort、LoadBalancer 和 Ingress。下图是这三种方案的对比:

1650856415636-2cdaba11-88a9-4c95-a55d-b993de9f806f.png

通过对比,可以看到 Ingress 是更适合业务使用的一种方式,可以基于其做更复杂的二次路由分发,这也是目前用户主流的选择。

Kubernetes Ingress 现状

虽然 K8s 对集群入口流量管理方式进行标准化的统一抽象,但仅仅覆盖了基本的 HTTP/HTTPS 流量转发功能,无法满足云原生分布式应用大规模复杂的流量治理问题。比如,标准的 Ingress 不支持流量分流、跨域、重写、重定向等较为常见的流量策略。针对这种问题,存在两种比较主流的解决方案。一种是在 Ingress 的 Annotation 中定义 Key-Value 的方式来拓展;另一种是利用 K8s CRD 来定义新的入口流量规则。如下图所示:

1650870864982-ac6eec8c-7100-471c-8d26-5eb6089a3491.png

Kubernetes Ingress 最佳实践

本节将从以下5个方面展开 K8s Ingress 最佳实践。

  • 流量隔离:部署多套 IngressProvider,缩小爆炸半径
  • 灰度发布:如何利 用IngressAnnotation 来进行灰度发布
  • 业务域拆分:如何按照业务域进行 API 设计
  • 零信任:什么是零信任,为什么需要零信任,怎么做
  • 性能调优:一些实用的性能调优方法

流量隔离

在实际业务场景中,集群中后端服务需要对外部用户或者内部其他集群提供服务。通常来说,我们将外部访问内部的流量称为南北向流量, 将内部服务之间的流量称为东西向流量。为了节省机器成本和运维压力,有些用户会选择将南北向流量和东西向流量共用一个Ingress Provider。这种做法会带来新的问题,无法针对外部流量或者内部流量做精细化的流量治理,同时扩大了故障影响面。最佳的做法是针对外网、内网的场景分别独立部署Ingress Provider,并且根据实际请求规模控制副本数以及硬件资源,在缩小爆炸半径的同时尽可能提供资源利用率。

1650880271119-b80004fd-e651-443b-b261-cb6cb77c0d26.png

灰度发布

在业务持续迭代发展过程中,业务的应用服务面临着版本频繁升级的问题。最原始最简单的方式,是停掉线上服务的旧版本,然后部署、启动服务的新版本。这种直接将服务的新版本提供给所有用户的方式会带来两个比较严重的问题。首先,在停掉服务旧版本与启动新版本这段时间内,该应用服务是不可用,流量请求的成功率跌零。其次,如果新版本中存在严重的程序BUG,那么新版本回滚到旧版本的操作又会导致服务出现短暂的不可用,不仅影响用户体验,而且也会对业务整体系统产生诸多不稳定因素。

那么,如何既能满足业务快速迭代的诉求,又能保证升级过程中业务应用对外的高可用?

1650881695816-4dd76efa-28a4-4754-97cf-fa9860ba7975.png

我认为需要解决以下几个核心问题:

  1. 如何减小升级的影响面?
  2. 新版本出现Bug时如何快速回滚到稳定版本?
  3. 如何解决标准Ingress不支持流量分流的缺陷?

针对前两个问题,业界共识比较通用的做法是采用灰度发布,俗称金丝雀发布。金丝雀发布的思想则是将少量的请求引流到新版本上,因此部署新版本服务只需极小数的机器。验证新版本符合预期后,逐步调整流量,使得流量慢慢从老版本迁移至新版本,期间可以根据当前流量在新老版本上的分布,对新版本服务进行扩容,同时对老版本服务进行缩容,使得底层资源得到最大化利用。

在Ingress现状小节里,我们提到了目前比较流行的两种扩展Ingress的方案,其中通过为Annotation新增Key-Value的方式可以解决第三个问题。我们可以在Annotation中定义灰度发布需要的策略配置,比如配置灰度流量的Header、Cookie以及对应值的匹配方式 (精确匹配或者正则匹配)。之后由Ingress Provider识别新定义的Annotation并解析为自身的路由规则,也就是关键在于用户选择的Ingress Provider要支持丰富的路由方式。

灰度发布——按照Header灰度

在进行小流量验证服务新版本是否符合预期的环节中,我们可以有选择的将线上具有一部分特征的流量认为是小流量。请求内容中Header、Cookie都可以认为是请求特征,因此针对同一个API,我们可以按照Header或者Cookie对线上流量进行切分。如果真实流量中Header无差别,我们可以基于线上环境手动制造一些带有灰度Header的流量进行验证。此外,我们也可以按照客户端的重要性来分批进行新版本验证,比如对于普通用户的访问请求优先访问新版本,待验证完毕后,再逐步引流VIP用户。一般这些用户信息、客户端信息都会存在Cookie中。

以Nginx-Ingress为例,通过Annotation支持Ingress的流量分流,按照Header灰度的示意图如下:

1650888122357-03ef69d4-dd46-465b-bd22-e5ab8b714b72.png

灰度发布——按照权重灰度

按照Header灰度的方式可以对特定的请求或者用户提供服务新版本,但是无法很好评估访问新版本的请求规模,因此在为新版本分配机器时可能无法做到资源最大化利用。而按照权重进行灰度的方式可以精确控制流量比例,在机器资源分配上游刃有余。通过前期小流量验证后,后期通过调整流量权重,逐步完成版本升级,这种方式操作简单,易于管理。然而线上流量会无差别地导向新版本,可能会影响重要用户的体验。按照权重灰度的示意图如下:

1650888707034-71f1a4ba-b89f-49fa-8b81-d2451533fced.png

业务域拆分

随着云原生应用规模不断扩大,开发者开始对原来的单体架构进行细粒度的拆分,将单体应用中的服务模块拆分成一个个独立部署运行的微服务,并且这些微服务的生命周期由对应的业务团队独自负责,有效的解决了单体架构中存在的敏捷性不足、灵活性不强的问题。但任何架构都不是银弹,在解决旧问题同时势必会引入一些新的问题。单体应用通过一个四层SLB即可完成对外暴露服务,而分布式应用依赖Ingress提供七层流量分发能力,这时如何更好的设计路由规则尤为重要。

通常我们会根据业务域或者功能域进行服务拆分,那么我们在通过Ingress对外暴露服务时同样可以遵循该原则。为微服务设计对外API时可以在原有的Path上添加具有代表性意义的业务前缀,在请求完成路由匹配之后和转发请求到后端服务之前时,由Ingress Provider通过重写Path完成业务前缀消除的工作,工作流程图如下:

1650941272227-144386a6-0a2c-4ea9-98fc-37dc6f035126.png

该API设计原则易于管理对外暴露的服务集合,基于业务前缀做更细粒度的认证鉴权,同时方便对各个业务域服务进行统一的可观测建设。

零信任

安全问题始终是业务应用的头号公敌,伴随着业务发展的整个生命周期。此外,外部互联网的环境越来越复杂,内部业务架构日益庞大,部署结构涉及公有云、私有云以及混合云多种形态,安全问题愈演愈烈。零信任作为安全领域的一种新型设计模型应用而生,认为应用网络内外的所有用户、服务都不可信,在发起请求、处理请求之前都要经过身份认证,所有授权操作遵循最小权限原则。简单来说就是trust no-one, verify everything.

下图是关于外部用户->Ingress Provider->后端服务整个端到端落地零信任思想的架构图:

1650942822546-19a4664b-a890-47f7-8d0c-9c0fd29c2dbb.png

  • 外部用户与Ingress Provider。外部用户通过向权威证书机构验证Ingress Provider提供的证书完成身份认证;Ingress Provider通过外部用户提供JWT凭证完成认证鉴权。
  • Ingress Provider与后端服务。Ingress Provider通过向内部私有证书机构验证后端服务提供的证书完成身份认证,后端服务通过向内部私有证书验证Ingress Provider提供的证书完成身份认证,同时后端服务可以基于调用方身份向授权服务进行鉴权操作。

性能调优

所有的外部访问流量都需要先经过Ingress Provider,因此主要性能瓶颈体现在Ingress Provider,在高并发、高性能上有了更高的要求。抛开各个Ingress Provider之间的性能差异,我们可以通过调整内核参数来进一步释放性能。经过阿里巴巴多年在集群接入层的实践经验,我们可以适当调整以下内核参数:


  1. 调大TCP连接队列的容量:net.core.somaxconn
  2. 调大可用端口范围:net.ipv4.ip_local_port_range
  3. 复用TCP连接:net.ipv4.tcp_tw_reuse

另一个优化角度是从硬件着手,充分释放底层硬件算力来进一步提高应用层的性能。当下HTTPS已经成为公网请求的主要使用方式,全部使用HTTPS后由于其要做TLS握手,相比HTTP势必性能上会有很大损耗。目前随着CPU性能的大幅提升,利用CPU的SIMD机制可以很好的加速TLS的性能。该优化方案依赖机器硬件的支持以及Ingresss Provider内部实现的支持。

目前,依托Istio-Envoy架构的MSE云原生网关结合阿里云第七代ECS率先完成了TLS硬件加速,在不增加用户资源成本的同时大幅度提升HTTPS的性能。

1642598010888-9e2f1400-f54f-4665-aa20-e8de85e60b59.png

Ingress Provider新选择——MSE 云原生网关

随着云原生技术持续演进,云原生应用微服务化不断深入,Nginx Ingress在面对复杂路由规则配置、支持多种应用层协议(Dubbo和QUIC等)、服务访问的安全性以及流量的可观测性等问题上略显疲惫。另外,Nignx Ingress在处理配置更新问题上是通过Reload方式来生效配置,在面对大规模长连接的情况下是会出现闪断情况,频繁变更配置可能会造成业务流量有损。

为了解决用户对大规模流量治理的强烈诉求,MSE云原生网关应运而生,这是阿里云推出的兼容标准Ingress规范的下一代网关,具备低成本、安全、高集成和高可用的产品优势。将传统的WAF网关、流量网关和微服务网关合并,在降低50%资源成本的同时为用户提供了精细化的流量治理能力,支持ACK容器服务、Nacos、Eureka、固定地址、FaaS等多种服务发现方式,支持多种认证登录方式快速构建安全防线,提供全方面、多视角的监控体系,如指标监控、日志分析以及链路追踪,并且支持解析单、多K8s集群模式下的标准Ingress资源,帮助用户在云原生应用场景下以声明式进行统一流量治理,此外我们引入了WASM插件市场满足用户定制化的需求。

1650957451074-75048b37-7fe3-44c6-a1e6-046a4b73c164.png

Nginx Ingress VS MSE 云原生网关

以下是Nginx Ingress与MSE云原生网关的对比总结:

1650957597957-c45c26e7-6569-4f44-a437-b9f4c6d513f8.png

平滑迁移

MSE云原生网关由阿里云托管,免运维,降成本,功能丰富,且与阿里云周边产品深度集成,下图是从Nginx Ingress如何无缝迁移至MSE云原生网关,其他Ingress Provider也可以参考该方法。

1650957762335-6112070b-781f-41d1-bdb7-121f440fe6e8.png

动手实践

接下来,我们会基于阿里云容器服务 ACK 进行 Ingress Provider——MSE云原生网关相关的实践操作,您可以了解到如何通过 MSE Ingress Controller 来管理集群入口流量。

操作文档地址:https://help.aliyun.com/document_detail/426544.html

前提条件

安装MSE Ingress Controller

我们可以在阿里云容器服务的应用市场中找到ack-mse-ingress-controller,并且按照组件下方的操作文档完成安装。

1651042349667-b3528071-55ea-47f9-9afb-a2dd01e897ff.png

通过CRD的方式创建MSE云原生网关

MseIngressConfig是由MSE Ingress Controller提供的CRD资源,MSE Ingress Controller使用MseIngressConfig来管理MSE 云原生网关实例的生命周期。一个MseIngressConfig对应一个Mse 云原生网关实例,如果您需要使用多个Mse 云原生网关实例,需要创建多个MseIngressConfig配置。为了简单展示,我们以一个最小化配置的方式来创建网关。

apiVersion: mse.alibabacloud.com/v1alpha1
kind: MseIngressConfig
metadata:
  name: test
spec:
  name: mse-ingress
  common:
    network:
      vSwitches:
        - "vsw-bp1d5hjttmsazp0ueor5b"

配置K8s标准的IngressClass来关联MseIngressConfig,关联完毕后云原生网关就会开始监听集群中与该IngressClass有关的Ingress资源。

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  annotations:
    ingressclass.kubernetes.io/is-default-class: 'true'
  name: mse
spec:
  controller: mse.alibabacloud.com/ingress
  parameters:
    apiGroup: mse.alibabacloud.com
    kind: MseIngressConfig
    name: test

我们可以通过查看MseIngressConfig的status来查看当前状态。MseIngressConfig会按照Pending > Running > Listening的状态依次变化。各状态说明如下:

  • Pending:表示云原生网关正在创建中,需等待3min左右。
  • Running:表示云原生网关创建成功,并处于运行状态。
  • Listening:表示云原生处于运行状态,并监听集群中Ingress资源。
  • Failed:表示云原生网关处于非法状态,可以查看Status字段中Message来进一步明确原因。

灰度发布实践

假设集群有一个后端服务httpbin,我们希望在版本升级时可以按照header进行灰度验证,如图所示:

1651043289224-f42b3dfa-24c0-43eb-af4f-61957a377518.png

首先部署httpbin v1和v2版本,通过apply以下资源到ACK集群中:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-httpbin-v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-httpbin-v1
  template:
    metadata:
      labels:
        app: go-httpbin-v1
        version: v1
    spec:
      containers:
        - image: specialyang/go-httpbin:v3
          args:
            - "--port=8090"
            - "--version=v1"
          imagePullPolicy: Always
          name: go-httpbin
          ports:
            - containerPort: 8090
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-httpbin-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: go-httpbin-v2
  template:
    metadata:
      labels:
        app: go-httpbin-v2
        version: v2
    spec:
      containers:
        - image: specialyang/go-httpbin:v3
          args:
            - "--port=8090"
            - "--version=v2"
          imagePullPolicy: Always
          name: go-httpbin
          ports:
            - containerPort: 8090
---
apiVersion: v1
kind: Service
metadata:
  name: go-httpbin-v1
spec:
  ports:
    - port: 80
      targetPort: 8090
      protocol: TCP
  selector:
    app: go-httpbin-v1
---
apiVersion: v1
kind: Service
metadata:
  name: go-httpbin-v2
spec:
  ports:
    - port: 80
      targetPort: 8090
      protocol: TCP
  selector:
    app: go-httpbin-v2  

发布稳定版本v1的Ingress资源:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpbin
spec:
  ingressClassName: mse
  rules:
  - host: test.com
    http:
      paths:
      - path: /version
        pathType: Exact
        backend:
          service:
            name: go-httpbin-v1
            port: 
              number: 80

发布灰度版本v2的Ingress资源:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    "nginx.ingress.kubernetes.io/canary": "true"
    "nginx.ingress.kubernetes.io/canary-by-header": "stage"
    "nginx.ingress.kubernetes.io/canary-by-header-value": "gray"
  name: httpbin-canary-header
spec:
  ingressClassName: mse
  rules:
  - host: test.com
    http:
      paths:
      - path: /version
        pathType: Exact
        backend:
          service:
            name: go-httpbin-v2
            port: 
              number: 80

测试验证

# 测试稳定版本
curl -H "host: test.com" <your ingress ip>/version
# 测试结果
version: v1
# 测试灰度版本
curl -H "host: test.com" -H "stage: gray" <your ingress ip>/version
# 测试结果
version: v2

以上就是我们利用Ingress Annotation的方式扩展标准Ingress支持灰度发布的高阶流量治理能力。



写在最后

MSE - 云原生网关,旨在为用户提供更可靠的、成本更低、效率更高的,符合 K8s Ingress 标准的企业级网关产品,更多发布详情移步直播间观看:https://yqh.aliyun.com/live/detail/28477

MSE - 云原生网关提供后付费和包年包月两类付费模式,支持杭州、上海、北京、深圳 、张家口、香港、新加坡、美国(弗吉尼亚)、美国(硅谷)、德国(法兰克福)10个 region,并会逐步开放其他 region,云原生网关购买链接在这里

现在购买MSE云原生网关预付费全规格,立享7折优惠,新老同享。


也可钉钉搜索群号 34754806 可加入用户群交流、答疑。

1642599892533-9caa4835-ccb6-4144-8c20-ac88c345f815.png

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
6天前
|
Kubernetes 应用服务中间件 Docker
Kubernetes学习-集群搭建篇(二) 部署Node服务,启动JNI网络插件
Kubernetes学习-集群搭建篇(二) 部署Node服务,启动JNI网络插件
|
4天前
|
资源调度 Kubernetes 监控
Kubernetes 集群性能优化实践
【5月更文挑战第17天】在容器化和微服务架构日益普及的当下,Kubernetes 已成为众多企业的首选容器编排工具。然而,随着集群规模的增长和业务复杂度的提升,性能优化成为确保系统稳定性与高效运行的关键。本文将深入探讨 Kubernetes 集群性能优化的策略与实践,覆盖从节点资源配置到网络通信优化,再到高效的资源调度机制,旨在为运维人员提供系统的优化路径和具体的操作建议。
|
5天前
|
Kubernetes 前端开发 容器
k8s部署模板
k8s部署模板
|
5天前
|
Java 数据库连接 Spring
K8S+Docker理论与实践深度集成java面试jvm原理
K8S+Docker理论与实践深度集成java面试jvm原理
|
5天前
|
存储 Kubernetes 监控
使用Kubernetes进行容器编排:技术详解与实践
【5月更文挑战第16天】Kubernetes,简称K8s,是开源容器编排系统,用于自动化部署、扩展和管理容器化应用。核心概念包括节点、Pod(最小部署单元)、服务、标签和副本集。其特点有高可用性、可扩展性、自动化和可移植性。实践使用涉及安装配置集群、编写YAML部署清单、应用部署、监控管理和扩展更新。Kubernetes帮助提升应用的可用性、可扩展性和可移植性。
|
6天前
|
运维 Prometheus 监控
Kubernetes 集群监控与性能优化实践
【5月更文挑战第14天】 在微服务架构日益普及的当下,Kubernetes 已成为容器编排的事实标准。然而,随着集群规模的扩大和业务复杂度的增加,监控系统的性能及稳定性变得至关重要。本文将深入探讨 Kubernetes 集群监控的重要性,介绍常用监控工具,并分享一系列针对集群性能优化的实践策略,帮助运维工程师确保服务的高可用性和优越性能。
|
6天前
|
运维 Kubernetes Linux
Kubernetes详解(七)——Service对象部署和应用
Kubernetes详解(七)——Service对象部署和应用
12 3
|
2天前
|
运维 监控 Kubernetes
Kubernetes 集群的监控与日志管理最佳实践
【5月更文挑战第19天】 在现代微服务架构中,容器编排平台如Kubernetes已成为部署、管理和扩展应用程序的关键工具。随着其应用范围不断扩大,集群的稳定性和性能监控变得至关重要。本文将探讨针对Kubernetes集群的监控策略,并深入分析日志管理的实现方法。通过介绍先进的技术堆栈和实用工具,旨在为运维专家提供一套完整的解决方案,以确保集群运行的透明度和可靠性。
33 3
|
2天前
|
存储 运维 监控
Kubernetes 集群的监控与性能优化策略
【5月更文挑战第19天】 在微服务架构日益普及的背景下,容器编排工具如Kubernetes已成为部署、管理和扩展服务的关键平台。然而,随着集群规模的增长和服务的复杂化,有效的监控和性能优化成为确保系统稳定性和高效性的重要挑战。本文将探讨针对Kubernetes集群监控的最佳实践,并提出一系列性能优化策略,旨在帮助运维人员识别潜在的瓶颈,保障服务的持续可靠性及响应速度。
|
5天前
|
存储 Java Serverless
ACK One Argo 工作流集群:玩转容器对象存储
ACK One Argo 工作流集群:玩转容器对象存储
ACK One Argo 工作流集群:玩转容器对象存储