目录

  1. 使用原生 YAML 安装 APISIX 和 APISIX Ingress 控制器

    1. 先决条件
    2. ETCD 安装
    3. APISIX 安装
    4. HTTPBIN 服务
    5. 定义路由
    6. 安装 APISIX Ingress 控制器
  2. Ingress 控制器

    1. 模块

    2. CRD 设计

    3. 监视 CRD

      1. 时序图
      2. 转换结构
      3. 级联更新
      4. 差分规则
      5. 服务发现
      6. 注解实现
  3. 参考文档


1. 使用原生 YAML 安装 APISIX 和 APISIX Ingress 控制器

在本教程中,我们将使用原生 YAML 在 Kubernetes 中安装 APISIX 和 APISIX Ingress 控制器。

1.1. 先决条件

如果没有 Kubernetes 集群使用,建议使用 kind 创建本地 Kubernetes 集群。

在本教程中,我们的所有操作都将在命名空间 apisix 中执行。

1.2. ETCD 安装

在这里,我们将在 Kubernetes 集群内部部署不带认证的单节点 ETCD 集群。

在本例中,我们假设你拥有存储部署器。如果你正在使用 Kind,那么将自动创建本地路径部署器。如果没有存储部署器或不想使用持久化存储卷,那么可以使用 emptyDir 作为存储卷。

将这两个 YAML 文件应用到 Kubernetes,等待几秒,ETCD 安装就成功了。我们可以运行健康检查,进行确认:

请注意该 ETCD 安装非常简单,缺乏许多必要的生产特性,仅用于学习场景。如果想部署生产级 ETCD,请参阅 bitnami/etcd

1.3. APISIX 安装

为我们的 APISIX 创建配置文件。我们将部署 2.5 版本的 APISIX。

注意 APISIX Ingress 控制器需要与 APISIX 管理 API 进行通信,因此为进行测试,我们将 apisix.allow_admin 设置为 0.0.0.0/0

请确保 etcd.host 与我们最初创建的无头服务匹配。在我们的例子中,它是 http://etcd-headless.apisix.svc.cluster.local:2379

在该配置中,我们在 apisix.admin_key 部分的下方定义具有 admin 名称的访问密钥。该密钥是我们的 API 密钥,以后将用于控制 APISIX。该密钥是 APISIX 的默认密钥,在生产环境中,应该修改它。

将其保存为 config.yaml,然后运行 kubectl -n apisix create -f config.yaml,创建 ConfigMap。稍后,我们将该 ConfigMap 挂载到 APISIX Deployment 中。

现在,应该可以使用 APISIX 了。使用 kubectl get pods -n apisix -l app.kubernetes.io/name=apisix -o name 来列举 APISIX Pod 名称。这里我们假设 Pod 名称是 apisix-7644966c4d-cl4k6

我们检查一下:

如果你正在使用 Linux 或 macOS,那么在 Bash 中运行下面的命令:

如果 APISIX 正常工作,那么它应该输出:{"error_msg":"404 Route Not Found"}。因为我们尚未定义任何路由。

1.4. HTTPBIN 服务

在配置 APISIX 前,我们需要创建一个测试服务。在这里,我们使用 kennethreitz/httpbin。我们将该 httpbin 服务放在 demo 命名空间中。

在 httpbin 服务启动后,我们应该可以在 APISIX Pod 中通过服务访问它。

该命令输出请求的查询参数,比如:

如欲阅读更多,请参阅快速入门

1.5. 定义路由

现在,我们可以定义通过 APISIX 代理 HTTPBIN 服务流量的路由。

假设我们想路由 URI 拥有 /httpbin 前缀,并且请求包含 Host: httpbin.org 头的所有流量。

请注意管理端口是 9180

输出如下所示:

我们可以通过 GET /apisix/admin/routes 检查路由规则:

输出如下所示:

现在,我们测试路由规则:

输出如下所示:

1.6. 安装 APISIX Ingress 控制器

APISIX Ingress 控制器可以帮助你通过使用 Kubernetes 资源的方式,声明式地管理配置。这里我们将安装 1.6.0 版本。

当前,APISIX Ingress 控制器同时支持官方的 Ingress 资源和 APISIX 的自定义资源定义,包括 ApisixRoute 和 ApisixUpstream。

在安装 APISIX Ingress 控制器前,我们需要创建服务账号和相应的集群角色,以确保 APISIX Ingress 控制器有足够的权限访问所需的资源。

下面是来自 apisix-helm-chart 的示例配置:

然后,我们需要创建 ApisixRoute CRD:

请参阅 samples 获取细节。

为使 Ingress 控制器与 APISIX 一起正常工作,我们需要创建一个配置文件,其中包含 APISIX 管理 API URL 和 API 密钥,如下所示:

如果想学习所有配置项,查看 conf/config-default.yaml 获取细节。

因为 Ingress 控制器需要访问 APISIX 管理 API,所以我们需要为 APISIX 创建一个服务。

因为当前 APISIX Ingress 控制器不 100% 兼容 APISIX,所以我们需要删除之前创建的路由,以防某些数据结构不匹配。

完成这些配置后,我们现在部署 Ingress 控制器。

在该 Deployment 中,我们将上面创建的 ConfigMap 挂载为配置文件,并且告诉 Kubernetes 使用服务账号 apisix-ingress-controller

在 Ingress 控制器的状态转换为 Running 后,我们创建 APISIXRoute 资源,观察它的行为。

下面是 APISIXRoute 示例:

注意 apiVersion 字段应该匹配上面的 ConfigMap。serviceName 应该匹配暴露的服务名称,这里是 httpbin

在创建它前,我们确认带头 Host: local.http.demo 的请求返回 404:

将返回:

在与目标服务相同的命名空间中应用 APISIXRoute,本例是 demo。在应用它后,我们检查它是否生效:

应该返回:

这就是所有!享受你的 APISIX 和 APISIX Ingress 控制器之旅。


2. Ingress 控制器

用于 Kubernetes 的 Apache APISIX Ingress 控制器。

2.1. 模块

modules.png

2.1.1. Ingress-types
2.1.2. Types
2.1.3. Seven
2.1.4. Ingress-controller

2.2. CRD 设计

当前 apisix-ingress-controller CRD 包括 6 部分:ApisixRoute/ApisixUpstream/ApisixConsumer/ApisixTls/ApisixClusterConfig/ApisixPluginConfig。其设计遵循如下思想。

  1. 网关最重要的部分是路由部分,它用于定义网关流量的分发规则
  2. 为便于理解和配置,ApisixRoute 的设计结构与 Kubernetes Ingress 基本相似
  3. 在注解的设计中,以 Kubernetes Ingress 的结构为参考,但内部实现基于 Apache APISIX 的插件
  4. 在最简单的情况下,只需定义 ApisixRoute,Ingress 控制器将自动添加 ApisixUpstream
  5. ApisixUpstream 可以定义 Apache APISIX 上游上的一些细节,比如负载均衡/健康检查等

2.3. 监视 CRD

apisix-ingress-controller 负责与 Kubernetes API Server 进行交互,申请可访问资源权限(RBAC),监视变更,在 Ingress 控制器中实现对象转换,比较变更,然后同步到 Apache APISIX。

2.3.1. 时序图

flow.png

下面是介绍 ApisixRoute 和其它 CRD 在同步过程中的主要逻辑的流程图。

sync-logic-controller.png

2.3.2. 转换结构

apisix-ingress-controller 为 CRD 提供外部配置方法。它针对的是日常运维等操作人员,他们经常需要批量地处理大量路由,希望在同一配置文件中处理所有相关服务,同时具有方便易懂的管理能力。而 Apache APISIX 从网关的角度进行设计,所有路由相互独立。这导致两者在数据结构上有明显的差异。一个侧重于批量定义,而另一个是离散实现。

考虑到不同人群的使用习惯,CRD 的数据结构借鉴 Kubernetes Ingress 的数据结构,在形态上基本相同。

简单的对比如下,它们有不同的定义:

struct-compare.png

他们是多对多的关系。因此,apisix-ingress-controller 必须对 CRD 执行一些转换,以适配不同网关。

2.3.3. 级联更新

目前,我们定义多个 CRD,这些 CRD 负责它们各自的字段定义。ApisixRoute/ ApisixUpstream 对应 Apache APISIX 中的 route/ service/upstream 等对象。由于 APISIX 对象之间的强绑定关系,在批量修改和删除 CRD 等数据结构时,必须考虑对象之间的级联影响。

因此,在 apisix-ingress-controller 中,通过 channel 实现广播通知机制,即任何对象的定义必须被通知给与其相关的其它对象,并且触发相应的行为。

cascade-update.png

2.3.4. 差分规则

seven 模块在内部保存内存数据结构,目前它与 Apache APISIX 资源对象非常相似。当 Kubernetes 资源对象发生新变更时,seven 将比较内存对象,然后根据比较结果,进行增量更新。

当前的比较规则基于 route / service / upstream 资源对象的分组,分别进行比较,发现差异后,进行相应的广播通知。

diff-rules.png

2.3.5. 服务发现

apisix-ingress-controller 根据 ApisixUpstream 资源对象中定义的 namespacenameport,将处于 running 状态的 endpoints 节点信息注册到 Apache APISIX Upstream 中的节点。并且根据 Kubernetes,实时同步 Endpoint 状态。

基于服务发现,Apache APISIX Ingress 可以直接访问后端 Pod 节点。绕过 Kubernetes 服务,可实现定制化的负载均衡策略。

2.3.6. 注解实现

与 Kubernetes Nginx Ingress 的实现不同,apisix-ingress-controller 基于 Apache APISIX 的插件机制实现注解。

比如,通过 ApisixRoute 资源对象中的 k8s.apisix.apache.org/whitelist-source-range 注解配置黑/白名单设置。

这里的黑/白名单由 ip-restriction 插件实现。

未来将有更多注释实现,以方便定义一些常见配置,比如 CORS。

如果你有注解需求,欢迎到 issue 讨论,我们讨论如何进行实现。


3. 参考文档