草庐IT

KubeSphere 网关的设计与实现(解读)

KubeSphere 云原生 2023-04-10 原文

作者:泓舟子,KubeSphere 后端研发工程师,云原生爱好者,现专注于云原生微服务方向。

KubeSphere 中为什么需要网关?

如果需要将 K8s 集群内的服务暴露到外部访问有那些方式呢?可以通过将 Service 设置成 NodePort 方式暴露出去或者通过 Ingress 方式。另外使用 Ingress 方式可以实现将请求分发到一个或多个 Service,可以同一个 IP 地址下暴露多个服务等优势。

但是对于 Ingress 方式而言,在 K8s 中只是内置了 Ingress CRD(可以创建 Ingress 资源),没有内置 Ingress Controller,必须部署了 Ingress Controller 才能为 Ingress 资源提供外部访问集群内部服务的能力。而 KubeSphere 中的网关就是 Ingress Controller 。

网关的设计

KubeSphere v3.2 对网关进行了重构,在保留了原有网关功能的基础上增加了以下几点新功能:

  1. 启用集群和项目级别的网关:可以根据业务上的需求灵活选择不同粒度的网关。
  2. 增减网关副本数:灵活调整副本数达到更高的可用性。
  3. 灵活配置 Ingress Controller 配置选项。
  4. 可指定网关应用负载安装的位置:可选择将网关应用负载安装的位置指定某固定命名空间或分别让其位于各自项目命名空间下。结合 KubeSphere 中的权限管理,若让资源位于各个项目命名空间下,拥有该项目权限的用户也能查看到网关资源。
  5. 网关日志:集中查询网关日志,将分布在各个副本的网关日志集中起来查询。
  6. 网关监控指标:监控网关中的一些指标,包括请求总量/成功率/延迟 等指标。

网关的实现

目前 K8s 支持和维护 AWSGCENginx Ingress 控制器,KubeSphere 使用 Ingress Nginx Controller 作为默认的网关实现,没有做任何代码修改。

各个功能点的实现思路

  • 集群和项目级别的网关:这个通过传入参数覆盖默认的 Helm Chart Values 来实现并在代码逻辑里控制,如果启用了集群网关就不能启用项目网关了;若启用了项目网关又启用了集群网关,那么通过两个网关入口都可以访问,只是这样会有两个 Ingress Controller 同时 Watch 相同的 Ingress 对象。

  • 增减网关副本数&配置 Ingress Controller 配置选项:这个通过传入参数覆盖默认的 Helm Chart Values 来实现,实现过程用到的 Helm Operator 将在后面重点介绍。

  • 可指定网关应用负载安装的位置:可选择将网关应用负载安装的位置指定某固定命名空间或分别让其位于各自项目命名空间下。这个在代码逻辑中控制,并做成了配置项,默认将所有资源安装在 kubesphere-controls-system 下。

  • 网关日志:使用到了 KubeSphere 中日志组件,日志组件会采集日志数据然后存储在 Elasticsearch 中,网关在查询日志过程就根据参数在 Elasticsearch 中查询日志。

  • 网关监控指标:使用到了 KubeSphere 中监控组件,KubeSphere 内部配置了 Prometheus 相关的参数采集 Ingress 相关指标,查询监控信息过程就根据监控组件中的 API 查询相关数据。

下面重点介绍设计实现过程抽象出的 CRD 和如何巧妙地用 Helm Operator 集成。

抽象出 Gateway CRD 做适配

在设计上抽象了一个 Gateway CRD 来适配不同的 Ingress Controller,Gateway CRD 中包含设置 Ingress Controller 所需的公共属性。KubeSphere API 和 UI 只与 Gateway CRD 交互。

# Gateway sample
apiVersion: gateway.kubesphere.io/v1alpha1
kind: Gateway
metadata:
  name: kubesphere-router-proj1
  namespace: kubesphere-controls-system # all Gateway workload will be created in the kubesphere-controls-system namespace by default. However, it's configurable in kubesphere-config when calling KubeSphere API. 
spec:
  controller:
  # controlpanel replicas. For ingress Controler that has controlpanel and workers. *Reserved field. Changing on UI isn't supported yet. 
  replicas: 1
  # annotations of the controlpanel deployment. *Reserved field. Changing on UI isn't supported yet. 
  annotations: {}

  # Watching scope,
  # enabled =true, watching for the project only. The user needs to specify the watching namespace.
  # enabled =false, Global gateway, watching for all namespaces.
  scope:
    enabled: false
    namespace: ""  # defaults to .Release.Namespace

  # gateway configurations. only key-value pair supported currently.
  config:
    max-bucket: 1m

  # worker workload deployment configuration
  deployment:
    annotations: 
    "servicemesh.kubesphere.io/enabled": "false"
    replicas: 1

  # 
  service:
    # Cloud LoadBalancer configurations for service
    annotations: 
      "service.beta.kubernetes.io/qingcloud-load-balancer-eip-ids": "test-ip-id"
    # Service Type, only LoadBalancer and NodePort are supported
    type: LoadBalancer

集成 Nginx Ingress Controller

KubeSphere 使用 Nginx Ingress Controller 作为默认的网关实现。为了简化部署步骤,我们集成了 Helm-operator-plugins 作为 Helm Operator

在 Helm Operator 中主要有以下关键点:

根据 watch.yaml 中配置的监听指定 CRD 下的 CR 来创建或更新 Chart 资源。其中可以根据 CR spec 中的值覆盖默认 Helm Chart 中的值,这是由 Helm Operator 中的机制决定的,详见官方说明

如下的含义是需要 Watch gateway.kubesphere.io/v1alpha1 的 Nginx CR,如果有变化就触发 Reconcile ,根据 chart 中配置的地址创建或更新对应的资源。

- group: gateway.kubesphere.io
  version: v1alpha1
  kind: Nginx
  chart: /var/helm-charts/ingress-nginx

在 KubeSphere 中的使用:

watchs.yaml 中就做了如下配置:

- group: gateway.kubesphere.io
  version: v1alpha1
  kind: Nginx
  chart: /var/helm-charts/ingress-nginx
- group: gateway.kubesphere.io
  version: v1alpha1
  kind: Gateway
  chart: /var/helm-charts/gateway

其中对 chart 而言:

整体而言:

Helm Operator Watch 了 Gateway 和 Nginx 2 个 CRD 的资源,当前端发起创建或更新网关时是对 Gateway CR 发起创建或更新操作:

  1. 发起请求创建或更新 Gateway CR ;
  2. 根据 watchs.yaml 配置的 Gateway, Helm Operator 监听到有 Gateway CR 资源变化,将创建或更新 Nginx CR ;
  3. 根据 watchs.yaml 配置的 Nginx,Helm Operator 监听到 Nginx CR 资源变化后就根据 Nginx CR 中的 spec 中的值来覆盖默认 Helm Chart 中的值来创建或更新 Nginx Ingress Contoller。

配置项的设计

为了方便更改网关的一些参数设计了如下配置项:

gateway:
  watchesPath: /var/helm-charts/watches.yaml
  repository: kubesphere/nginx-ingress-controller
  tag: v1.1.0
  namespace: kubesphere-controls-system
  • watchesPath:指定 Helm Operator Watch 的配置文件,如果需要禁用 Helm Operator 就可以删掉这个配置项。
  • repository:指定 nginx-ingress-controller 的仓库。
  • tag:指定 nginx-ingress-controller 的 tag。
  • namespace:指定网关应用负载安装的位置位于指定的命名空间下,若删掉这个配置项就会安装在各个项目命名空间下。

使用过程注意事项

  1. 如果启用了 servicemesh ,在原有的 Ingress 需要加上额外的注解 nginx.ingress.kubernetes.io/upstream-vhost: [service-name].[service-namespace].svc.cluster.local 流量拓扑/链路追踪可以正常工作,不然入口流量处会有异常。
  2. 修改网关相关属性,比如:副本数、Nginx 配置项等,不能直接在相关的 deploy/configmap 等应用负载里面修改,需要在网关设置中修改(修改的是 Gateway CR)。因为使用的是 Helm Operator 来管理控制网关相关资源的状态,所有值都会以 Gateway CR 中的配置为准,改了网关相关应用负载中的值最终都会被 Helm Operator 还原掉。

参考:

  1. https://kubernetes.io/docs/concepts/services-networking/ingress-controllers/
  2. https://github.com/kubesphere/community/blob/master/sig-microservice/concepts-and-designs/KubeSphere-gateway-operator-design.md
  3. https://github.com/kubesphere/kubesphere
  4. https://sdk.operatorframework.io/docs/building-operators/helm/

本文由博客一文多发平台 OpenWrite 发布!

有关KubeSphere 网关的设计与实现(解读)的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  7. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

  8. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. ruby - Arrays Sets 和 SortedSets 在 Ruby 中是如何实现的 - 2

    通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复

随机推荐