文章目录
概述
管好微服务,成为云原生时代的新难题。
从建好微服务到管好微服务,差的虽是一个字,连接起两边的却需要大量的微服务落地经验。因为软件架构的核心挑战是解决业务快速增长带来的系统复杂性问题,而微服务将应用进行解耦的过程中,服务和服务之间的调用和依赖关系也变得愈加复杂,关系越复杂、小的技术问题越可能被放大,造成大的线上故障。而容器和 Kubernetes 为代表技术的云原生时代,则加重了其中的复杂程度。网关是整个服务API请求的入口,可以统一对所有请求进行处理。
作用:可以实现用户的验证登录、解决跨域、日志拦截、权限控制、限流、熔断、负载均衡、黑名单与白名单机制等。对于微服务网关本文进行了对应的评估,以供参考。
微服务网关基本概念
不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:
- 客户端会多次请求不同的微服务,增加了客户端的复杂性
- 存在跨域请求,在一定场景下处理相对复杂
- 认证复杂,每个服务都需要独立认证
- 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施
某些微服务可能使用了防火墙、浏览器不友好的协议,直接访问会有一定困难
以上这些问题可以借助网关解决。
网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:
优点如下:
- 安全 :只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护。
- 易于监控:可以在网关收集监控数据并将其推送到外部系统进行分析。
- 易于认证:可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。减少了客户端与各个微服务之间的交互次数
- 易于统一授权。
总结:微服务网关就是一个系统,通过暴露该微服务网关系统,方便我们进行相关的鉴权,安全控制,日志统一处理,易于监控的相关功能。
微服务网关技术
实现微服务网关的技术有很多:
Nginx Nginx (tengine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务
Spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,性能比Zuul好。
APIsix APIsix是一个云原生、高性能、可扩展的微服务 API 开源网关,基于OpenResty(Nginx+Lua)和etcd来实现,对比传统的API网关,具有动态路由和热插件加载的特点(访问任何域名、URL会匹配到http_access_phase这个lua函数,这个函数将会基于C语言实现的基数前缀树匹配域名、URI等,每次路由发生变化,lua会去重建这颗基数树)
Zuul Zuul 是 Netflix 出品的一个基于 JVM 路由和服务端的负载均衡器。
Kong Kong基于Nginx来实现Api Gateway基本的负载均衡、反向代理等功能。
应用场景对比
Nginx | Spring-cloud-gateway | APIsix | Zuul | Kong | |
---|---|---|---|---|---|
应用场景 | HTTP服务器 静态服务器 方向代理 负载均衡 动静分离 | IO密集的任务 大请求或者大文件 队列的流式数据 超大量的连接 | 负载均衡 限速限流 身份验证 服务治理 动态路由 服务发现 反向代理 | 身份验证 动态路由 压力测试 静态响应处理 | 负载均衡 反向代理 监控 限流 认证 |
我们调研的APIsix这个微服务网关技术,无供应商锁定(云原生),APISIX可以从裸机运行到Kubernetes。同时支持OpenResty和Tengine,不用担心基础技术的锁定。(支持ARM64)
第一章 APISIX简介
1、什么是APISIX
官方地址:https://apisix.apache.org/
APISIX 是一个云原生、高性能、可扩展的微服务 API 开源网关,基于OpenResty(Nginx+Lua)和etcd来实现,对比传统的API网关,具有动态路由和热插件加载的特点。系统本身自带前端,可以手动配置路由、负载均衡、限速限流、熔断、金丝雀发布、身份验证、可监控等插件,操作方便。可以使用Apache APISIX来处理传统的南北流量,以及服务之间的东西流量。它也可以用作k8s入口控制器。
2、架构组成
第一部分叫做数据面,它是真正去处理来自客户端请求的一个组件,去处理用户的真实流量,包括像身份验证、证书卸载、日志分析和可观测性等功能。数据面本身并不会存储任何数据,所以它是一个无状态结构。
第二部分叫做控制面。APISIX 在控制面上并没有使用传统的类似于像 MySQL 去做配置存储,而是选择使用 etcd。
好处:
- 与产品架构的云原生技术体系更统一
- 更贴合 API 网关存放的数据类型
- 能更好地体现高可用特性
拥有低于毫秒级别的变化通知
使用 etcd 后,对于数据面而言只需监听 etcd 的变化即可。如果轮询数据库的话,可能需要 5-10 秒才能获取到最新的配置;但如果监听 etcd 的配置变更,就可以将时间控制在毫秒级别之内,达到实时生效的效果。
所以使用 etcd 而不是关系型数据库,不仅让 APISIX 在底层上更加贴合云原生,也让它在系统高可用的体现上带来了更多优势。
3、组件功能
你可以把 Apache APISIX 当做流量入口,来处理所有的业务数据,包括动态路由、动态上游、动态证书、 A/B 测试、金丝雀发布(灰度发布)、蓝绿部署、限流限速、抵御恶意攻击、监控报警、服务可观测性、服务治理等。
4、组件特点
全平台
云原生: 平台无关,没有供应商锁定,无论裸机还是 Kubernetes,APISIX 都可以运行。
运行环境: OpenResty 和 Tengine 都支持。
支持 ARM64: 不用担心底层技术的锁定。
多协议
TCP/UDP 代理: 动态 TCP/UDP 代理。
Dubbo 代理: 动态代理 HTTP 请求到 Dubbo 后端。
动态 MQTT 代理: 支持用 client_id 对 MQTT 进行负载均衡,同时支持 MQTT 3.1.* 和 5.0 两个协议标准。
gRPC 代理:通过 APISIX 代理 gRPC 连接,并使用 APISIX 的大部分特性管理你的 gRPC 服务。
gRPC 协议转换:支持协议的转换,这样客户端可以通过 HTTP/JSON 来访问你的 gRPC API。
Websocket 代理
Proxy Protocol
Dubbo 代理:基于 Tengine,可以实现 Dubbo 请求的代理。
HTTP(S) 反向代理
SSL:动态加载 SSL 证书。
全平台
云原生: 平台无关,没有供应商锁定,无论裸机还是 Kubernetes,APISIX 都可以运行。
运行环境: OpenResty 和 Tengine 都支持。
支持 ARM64: 不用担心底层技术的锁定。
多协议
TCP/UDP 代理: 动态 TCP/UDP 代理。
Dubbo 代理: 动态代理 HTTP 请求到 Dubbo 后端。
动态 MQTT 代理: 支持用 client_id 对 MQTT 进行负载均衡,同时支持 MQTT 3.1.* 和 5.0 两个协议标准。
gRPC 代理:通过 APISIX 代理 gRPC 连接,并使用 APISIX 的大部分特性管理你的 gRPC 服务。
gRPC 协议转换:支持协议的转换,这样客户端可以通过 HTTP/JSON 来访问你的 gRPC API。
Websocket 代理
Proxy Protocol
Dubbo 代理:基于 Tengine,可以实现 Dubbo 请求的代理。
HTTP(S) 反向代理
SSL:动态加载 SSL 证书。
全动态能力
热更新和热插件: 无需重启服务,就可以持续更新配置和插件。
代理请求重写: 支持重写请求上游的host、uri、schema、enable_websocket、headers信息。
输出内容重写: 支持自定义修改返回内容的 status code、body、headers。
Serverless: 在 APISIX 的每一个阶段,你都可以添加并调用自己编写的函数。
动态负载均衡:动态支持有权重的 round-robin 负载平衡。
支持一致性 hash 的负载均衡:动态支持一致性 hash 的负载均衡。
健康检查:启用上游节点的健康检查,将在负载均衡期间自动过滤不健康的节点,以确保系统稳定性。
熔断器: 智能跟踪不健康上游服务。
代理镜像: 提供镜像客户端请求的能力。
流量拆分: 允许用户逐步控制各个上游之间的流量百分比。
精细化路由
支持全路径匹配和前缀匹配
支持使用 Nginx 所有内置变量做为路由的条件,所以你可以使用 cookie, args 等做为路由的条件,来实现灰度发布、A/B 测试等功能
支持各类操作符做为路由的判断条件,比如 {“arg_age”, “>”, 24}
支持自定义路由匹配函数
IPv6:支持使用 IPv6 格式匹配路由
支持路由的自动过期(TTL)
支持路由的优先级
支持批量 Http 请求
支持通过GraphQL属性过滤路由
安全防护
多种身份认证方式: key-auth, JWT, basic-auth, wolf-rbac。
IP 黑白名单
Referer 白名单
IdP 支持: 支持外部的身份认证服务,比如 Auth0,Okta,Authing 等,用户可以借此来对接 Oauth2.0 等认证方式。
限制速率
限制请求数
限制并发
防御 ReDoS(正则表达式拒绝服务):内置策略,无需配置即可抵御 ReDoS。
CORS:为你的 API 启用 CORS。
URI 拦截器:根据 URI 拦截用户请求。
请求验证器。
运维友好
OpenTracing 可观测性: 支持 Apache Skywalking 和 Zipkin。
对接外部服务发现:除了内置的 etcd 外,还支持 Consul 和 Nacos,以及 Eureka。
监控和指标: Prometheus
集群:APISIX 节点是无状态的,创建配置中心集群请参考 etcd Clustering Guide。
高可用:支持配置同一个集群内的多个 etcd 地址。
控制台: 操作 APISIX 集群。
版本控制:支持操作的多次回滚。
CLI: 使用命令行来启动、关闭和重启 APISIX。
单机模式: 支持从本地配置文件中加载路由规则,在 kubernetes(k8s) 等环境下更友好。
全局规则:允许对所有请求执行插件,比如黑白名单、限流限速等。
高性能:在单核上 QPS 可以达到 18k,同时延迟只有 0.2 毫秒。
故障注入
REST Admin API: 使用 REST Admin API 来控制 Apache APISIX,默认只允许 127.0.0.1访问,你可以修改 conf/config.yaml 中的 allow_admin 字段,指定允许调用 Admin API 的 IP 列表。同时需要注意的是,Admin API 使用 key auth 来校验调用者身份,在部署前需要修改 conf/config.yaml 中的 admin_key 字段,来保证安全。
外部日志记录器:将访问日志导出到外部日志管理工具。(HTTP Logger,TCP Logger,Kafka Logger,UDP Logger)
Helm charts
高度可扩展
自定义插件: 允许挂载常见阶段,例如init, rewrite,access,balancer,header filter,body filter 和 log 阶段。
插件可以用 Java/Go 编写
自定义负载均衡算法:可以在 balancer 阶段使用自定义负载均衡算法。
自定义路由: 支持用户自己实现路由算法。
使用场景:
APISIX的功能有很多,包括动态路由、url重写、动态上游、IP黑白名单、A/B测试、灰度发布、限速限流、监控报警、健康检查等等,本文只介绍几个比较常用的功能,其他功能具体可以查看APISIX的官方文档说明。
- 服务热启动功能
使用过Nginx的同学都会遇到过这种情况,在修改nginx.conf后需要重启nginx服务修改才会生效,重启时间虽然短暂,但难免会有一段服务不可用时间。当然,可以通过其他方式进行规避服务不可用。APISIX的服务热启动通过在路由、Service、Upstreams等插件中动态的修改配置即可,并不需要再重启APISIX服务来使修改生效。 - 热插件功能
不再需要在nginx.conf文件中编写复杂的规则代码来实现需求,通过使用自带的路由、Upstreams等插件,在前端页面中添加所需要的规则即可实现。下文应用会详细介绍。目前通过插件可以实现uri重写、根据请求信息中的内容实现路由跳转等等。也可以根据自己的需求开发符合自己需求的插件。 - 动态负载均衡
通过Upstreams插件,可以实现基于权重的roundrobin和chash负载均衡。 - 数据集群
APISIX支持etcd集群,通过etcd集群增强了系统的可用性,大大减小了故障损失。 - 监控
APISIX外接第三方prometheus监控系统,提供符合prometheus数据格式的监控指标数据。Prometheus 是由 SoundCloud 开源监控告警解决方案,已经比较成熟完善。
5、启动步骤
apisix 启动时调用:
apisix init , 运行LUA脚本,执行apisix init,生成nginx配置文件,初始化 nginx 配置,通过读取 conf/config.yaml 生成 nginx config 文件。供 openresty(nginx)使用。
apisix init_etcd,初始化 etcd 配置,用于与 etcd 同步数据。
apisix start;实际执行了 openresty -p /usr/local/apisix -g ‘daemon off;’ 启动 openresty 。
第二章 安装部署
2.1裸金属
部署ETCD
wget https://github.com/etcd-io/etcd/releases/download/v3.4.13/etcd-v3.4.13-linux-amd64.tar.gz
tar -xvf etcd-v3.4.13-linux-amd64.tar.gz && \
cd etcd-v3.4.13-linux-amd64 && \
sudo cp -a etcd etcdctl /usr/bin/
# add OpenResty source
sudo yum install yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
# install OpenResty and some compilation tools
sudo yum install -y openresty curl git gcc openresty-openssl-devel unzip
# install LuaRocks
curl https://raw.githubusercontent.com/apache/apisix/master/utils/linux-install-luarocks.sh -sL | bash -
# start etcd server
nohup etcd &
# 防火墙关闭
systemctl stop firewalld.service
systemctl disable firewalld.service
setenforce 0
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
部署APIsix
$ mkdir apisix-2.3
$ wget https://archive.apache.org/dist/apisix/2.3/apache-apisix-2.3-src.tgz
$ tar zxvf apache-apisix-2.3-src.tgz -C apisix-2.3
安装依赖包
$ make deps
检查版本
$ ./bin/apisix version
启动服务
$ ./bin/apisix start
部署Dashboard
https://github.com/apache/apisix-dashboard
https://github.com/apache/apisix-dashboard/blob/master/docs/en/latest/deploy.md
web依赖安装
node安装
https://nodejs.org/en/download/
yarn 安装
https://yarnpkg.com/getting-started/install
克隆工程
git clone -b v2.4 https://github.com/apache/apisix-dashboard.git
编译
cd apisix-dashboard
make build
启动服务
cd output
./manager-api
nohup ./manager-api &
通过浏览器进行访问
http://ip:9080
2.2 Docker部署
克隆项目
#将 Apache APISIX 的 Docker 镜像下载到本地
git clone https://github.com/apache/apisix-docker.git
# 将当前的目录切换到 apisix-docker/example 路径下
cd apisix-docker/example
# 运行 docker-compose 命令,安装 Apache APISIX
docker-compose -p docker-apisix up -d
Apache APISIX 已支持 ARM64 架构。如果您正在使用 ARM64,请在最后一步执行 docker-compose -p docker-apisix -f docker-compose-arm64.yml up -d。
http://ip:9080
2.3 K8S部署
Etcd.yaml
apiVersion: v1
data:
jwt-token.pem: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS2dJQkFBS0NBZ0VBN1d6LzVNb3AzVHF0QWNMeFVMU2p5Mm9SbmhJSXBvTndBV2pLb2Uxb08reDFlKzMzCjc1dG1BTU91SmhxS0c3TGhIdFVxWENiQXZlYWRyZ09QTnJ4MGVLS0J2Ni9sY0FBbUh2Y2FVdyt3d2lYNFFxWXgKSWE0NTVGODkyL3pBT2YwUm5UMVVjUXJQbDR3SDZWWndvY3QrNzhZL3lDaWRQcGpoWTNra0IveWszUmlxUVFMMwpqR3NHMXZLYURNUEl3bFgxc0xkRUdzTjhjN1pvd0x5SWtCc1BiSWlYSHdPeWE3Mkp2cVRZc2dydWw5Ri8yRFl1ClBWZEhaMzREdTBpd1NVNCt1N1lQS0lFYUp6RmdSd3c2czJXYlZBQXVEN1h6LzU2anMvTm5uZEFNWHlYT1RReGsKTnQwZlZVS2R5SWNPdGJGK2w0blFnNG1RVXBDS3MvdGhHYzFzY1hMWHpqWVJaclo3NjFkVFRYSm15UWRWbWhOYgpaemZ2SzJEZ3ppYkZBcStPQ29PaWE2TlByYUhTZEFsejlWcS92MFB4T0RlbXZDR2Q1clg2VHF4eUdqcGtGcWxOCmdNbVpWR2pHdVBEWXN5TVpjUDZOWEVoUFFhWmRWNzY5Q1kyY0xlSWVsWk1LNC9TUDNOL0RiU3E2cEdZaDhOV1kKV3pyV2k0UWtyUVI0UnBlOGhGL1FRbmo5RnpVTUxlR05zUG91L0JnTGJCbDIyN2E3NmdlUEsrMmp2VW5UMXlCVApLbzJmWFlnYTgxVEhpYzhOR2VCSDlrU1VQMThXVUVTcGI2cXVJTVQ5dHAzTmx6SDdYc3E4TnNqQlEwMVJqb2VCCm9Tc1hYcDZteWhJdU90QjZINkFLbTJwTitCU0lrRW9XL0RUYlJwTllkdE5FSjRpT3BWZFNYaFE1d1dzQ0F3RUEKQVFLQ0FnRUE0R3VHV2NGSjN3WkdZQUxmVExUaW1qU3hZR09WYjZlUHFKVmY2NzFYS0VVeks2aGRFa3dtRjVUZgpPTDhmU2wxRDgzdjBaVlJ3SFZBdVBUeTZFemdCTThJUHVKdlAySlViYzJ1SW8zaVNVSUhKYjE1ZDFJTTF6NHJECkV2eU95b0ZPTS8yem9vSmdoTlBrNm9jOVFZSHpnenMyTU1GTEdNOHpSRzVPUTRwb1gyQ2dGWUZ6Y25QNzdCTTIKejlnRUhNVlp6ZWI4NWZ0ZjJKUlQ0ZEtUbHZzdEVoN3VFVy9TSjRycDk1MGtBdTdZWmdLdHdEWStjTmJkOUpJbApmdEtQWjBzaGV4YjByd21SS2ZpL0U0a1l0MWZVZ1lzRi91MnpMQ3pNZWgwYUZRNkJrekpPRllBZi9jZjNoUVRKCjFiRHJrNHlwcHgycVRac3JJdy9qTzRyaVZweFk0ZlVjOW5MeVJPeG1CaC9uTHlFNFVEQWhZSGMwZjZhUWxYSVYKcGtpZ3d4ZENrditRNm9uaUZLUFU0RDF3VlhQOVVxZ2ltaFJ5V2tPcmxXUGZWa09laWIwek03Z3NvVXBtRGJ4TAoyOXAweHB6WVBPQ3REbXVXTEZxZWZmSUFFM0g5UFowWHVRUlJPQTV3cHlBdUVqK1U1cjJPMGQ5T0ZLQVA0akpXCmM3aHEwK29pZHhHNmZMK3VJZ0d1T1hPZW9uYU5jNFQ2NVZPbG9EQWkrdkZycUlXVktSbm9qMjFLdytyYzg0aHoKK2tPTktnbHVjZ2JjbUgrb1AvanU3dklTdW8raXpRUFViZnZ2alhwRThxc1l0eW1UY1J2UW5pd2I2c3h0ekNBVgpuZVE5ZElZMGYzT2JvQitucHBQMUFIZWszZlJLN1hZZ2c5eTJ4eE1IdFpyRitvUXNpaGtDZ2dFQkFPNHNzVnVLCmhLcWNJcmdkZUc2OEg0TGNtT09GWHRyZlRMNTVzTS83STI5UWhjMmczc3pYYXZoM1BndEo1ekxJeDMwdWdKdWYKN1h6Snh2Tjl2RGs1SUlVTXc3SnRJYXZKNGVQWks2L0lHZUVkOXhWTUF2NTIrVE5rOFJSbW5oeW5ua0FPNlkxcwpGM21GTURmblVxbFhzODRCVlM1N1Y3Z3RZMXV2TWpOMHRSdmdjNkxFeStpd1NQYTRnUXM2aFY4R3dMSVk3ekQvCmJHWU93bVgxNjhwbVBhbXFxOXIyUU1ubnNiWFhJb3R5aVZ1YzFwY3B5aFdqOHI1MWw4RFR6eVpEVUZWcTlXcC8KOFdkYXZ3OURwS0srckIxcEM5dFJadXF2ZjNQTkJ2UjdXdnZNS3FXTCtGZi9LdXhTMk9yenRCSXBSeVJJQTNwNgowTnBDbVVNenJObDRBRGNDZ2dFQkFQOHg5Y255dlVXbHl4b01xKzVLaTVpS3ppVzBBb1loWlZVajFLN3BRNktPCkwxeEs1UHg0WS9aTmNlNGs0c3F4azBkZmpCT3J1eFdYSk1oMGhYSHhPVzhBUDBSYU1waWc5YVh4MWkwVXp6anIKbEZLZWtoNzNrQWpFcHBYN0FGcVRHOHF2NUJ2azArRWI1cGhPNFM4ZFlSQngxdzdSKzYvVisxS3JuYm1LOTE1RQoxbVBWTWtzQ2dlNnFwUGs4aHhWeHVhcStrOWR3eVVVSXhQR2w1NW5BU0hyN1JYaldYa3pkallIZk8vZHFxSGwwCkc3MWx2QmN5dUMwOERsMW5LVE5KQlAvY0pEeGVNVlVha25NM00yN2FNeitPSmRnTUE2YVV1V3pYS3NIWHdBeHkKeWM0ZWJwZEdKcVkrRGRhNGNLckV6VTQ4T2hTM1l6cGxZcXlyemtqeXBtMENnZ0VCQU5PSFUvbEdHNjlldmlNZwo0VjRQckRqUDdPVmRCVEtFVWFkMWNvZzB0bkxkWkFpTlVITkMrdGt6SmlKbWYzU0dCMDV4WjMxUDIxOFI0YVZOClRVYlJLc1dmNFlwdERCT0RXQ0RCTnVDR2FoMmFQR0Jvd3R2M0ZEb0Y4MnEzL01MY1Ixc0RJNEFidVBtUFJaVFEKMklSWHhQUTRFTXdZZFg2NHFONjd5VzBUd09uQ1BWRVpVVFFXcEthaWxORkJKMFNQUGNLdkRIaEswWjRPaTY1OAphKzYxUVJ5WDNNdTZHeTUyblVrdmlabXBucjZEbTc1ak9meGdRRzNSQ0hjVVpveklDZWZpOTVXZmplbktHWmZYCjdyY3Zlck1nSVl5bVRpNHVzWlpLU0Z3SDFuVjlEWDg3d2ROOVowUytDN01Yd0J6RkZrN3R1bEVrRkt0VHJNU1gKZDNNbzlaOENnZ0VCQUptaFhCVHRtMkI0aFNMemlmWDB6c0ZRbnZZM3ZtVTlhYUd0NW5ZK1c4ZGF6Y3hFRWtLagp2NW9oMlhyQ25mM2tsWU9jVTlucndyOG10TEF3NWIxSXVZakhuMDdvOWhqSW5kbi9FeThrbmZQb2J1eW1KZFdhCnVBMXZSZEo0dnlmSDlDMDdZcG9nVWlYdEJBK2hQUk4rSGxjbUVaQU1mZmJIWFh2UmNTeW9LbStJQllFb2NoU1MKTitLVXZLaUc5ZFBGR1Q5ZlorV0ZNc1hxbDVYYWlPa1l4d215aDRwTms0dTJ2Vi80SWtPNjVCM3A5bUU1QTlqNwpZY0ZwckVReXZLenhRcDg5eWxyRllmR1lBNTUxRnZPZlRNYndMbnc0RDJLVG1tV1p5MVhUS3Z6VGhnWWViL21GCjgvS1UzUVB0R1hiVTc3d3ZxYythNzVQU1FXc3VLd3ZqZUtrQ2dnRUFWMHlBbG9YQ2hicnQrYml3MTVsek50dmwKUktWbFlyeXNoWlJ4VTNoRU9yTllPY042WkwxazZLWnUySVhWckJBVjlQNlVPbmdaK1VxUVpibHluSGVZcTZteApDWU1HSjVaNVZkYzJEYXVVaUNkczRybkd5U0pKWGFpUC82WVlxbEJvWkMvdnlHK3dBTy9ybThtdFlrR1hhdEc5CkRqMkJqd2l5Z0ROQUlKZ2l0OHZYTWM0RFlvK3Z5WkJUZVRNb21RNkFITDJiNUc2NE81ZWxHU08yZzd3SnJ6QysKdjhCZUIyTCs3U0x0amNVTEsydktoWFNnVE9EZTUwWWU4UVFBVTRYM1lIQStPc3pGa1pLWVNGaEtnV3hzNDdzUApIRGU1ZS92NjFNRDFnbkdaVjBrS1hIRHhwVWExNkpTKzlya3Z2UEF6aVQwNzltUnJ4YTliUnhmd2lZS3FQUT09Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
kind: Secret
metadata:
labels:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
name: etcd-jwt-token
namespace: apisix
type: Opaque
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
generation: 1
labels:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
name: etcd
namespace: apisix
spec:
podManagementPolicy: Parallel
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
serviceName: etcd-headless
template:
metadata:
annotations:
checksum/token-secret: 60156acd10c1cc700c72beb227921dd1c20bf596700362f42d7ab98b32f67a44
prometheus.io/port: "2379"
prometheus.io/scrape: "true"
labels:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchLabels:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
namespaces:
- apisix
topologyKey: kubernetes.io/hostname
weight: 1
containers:
- env:
- name: BITNAMI_DEBUG
value: "false"
- name: MY_POD_IP
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.podIP
- name: MY_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: MY_POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
- name: ETCDCTL_API
value: "3"
- name: ETCD_ON_K8S
value: "yes"
- name: ETCD_START_FROM_SNAPSHOT
value: "no"
- name: ETCD_DISASTER_RECOVERY
value: "no"
- name: ETCD_NAME
value: $(MY_POD_NAME)
- name: ETCD_DATA_DIR
value: /bitnami/etcd/data
- name: ETCD_LOG_LEVEL
value: info
- name: ALLOW_NONE_AUTHENTICATION
value: "yes"
- name: ETCD_AUTH_TOKEN
value: jwt,priv-key=/opt/bitnami/etcd/certs/token/jwt-token.pem,sign-method=RS256,ttl=10m
- name: ETCD_ADVERTISE_CLIENT_URLS
value: http://$(MY_POD_NAME).etcd-headless.$(MY_POD_NAMESPACE).svc.cluster.local:2379,http://etcd.$(MY_POD_NAMESPACE).svc.cluster.local:2379
- name: ETCD_LISTEN_CLIENT_URLS
value: http://0.0.0.0:2379
- name: ETCD_INITIAL_ADVERTISE_PEER_URLS
value: http://$(MY_POD_NAME).etcd-headless.$(MY_POD_NAMESPACE).svc.cluster.local:2380
- name: ETCD_LISTEN_PEER_URLS
value: http://0.0.0.0:2380
- name: ETCD_INITIAL_CLUSTER_TOKEN
value: etcd-cluster-k8s
- name: ETCD_INITIAL_CLUSTER_STATE
value: new
- name: ETCD_INITIAL_CLUSTER
value: etcd-0=http://etcd-0.etcd-headless.$(MY_POD_NAMESPACE).svc.cluster.local:2380,etcd-1=http://etcd-1.etcd-headless.$(MY_POD_NAMESPACE).svc.cluster.local:2380,etcd-2=http://etcd-2.etcd-headless.$(MY_POD_NAMESPACE).svc.cluster.local:2380
- name: ETCD_CLUSTER_DOMAIN
value: etcd-headless.$(MY_POD_NAMESPACE).svc.cluster.local
image: artifactory.dep.devops.cmit.cloud:20101/panji_middleware_docker/etcd:3.5.4
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
exec:
command:
- /opt/bitnami/scripts/etcd/prestop.sh
livenessProbe:
failureThreshold: 5
initialDelaySeconds: 60
periodSeconds: 30
successThreshold: 1
tcpSocket:
port: 2379
timeoutSeconds: 5
name: etcd
ports:
- containerPort: 2379
name: client
protocol: TCP
- containerPort: 2380
name: peer
protocol: TCP
resources: {}
securityContext:
runAsNonRoot: true
runAsUser: 1001
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /bitnami/etcd
name: data
- mountPath: /opt/bitnami/etcd/certs/token/
name: etcd-jwt-token
readOnly: true
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext:
fsGroup: 1001
serviceAccount: default
serviceAccountName: default
terminationGracePeriodSeconds: 30
volumes:
- name: etcd-jwt-token
secret:
defaultMode: 256
secretName: etcd-jwt-token
updateStrategy:
type: RollingUpdate
volumeClaimTemplates:
- apiVersion: v1
kind: PersistentVolumeClaim
metadata:
creationTimestamp: null
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
storageClassName: nfs-controller-plane
volumeMode: Filesystem
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/instance: etcd
helm.sh/chart: etcd-3.4.13
name: etcd
namespace: apisix
spec:
ports:
- name: client
port: 2379
protocol: TCP
targetPort: client
- name: peer
port: 2380
protocol: TCP
targetPort: peer
selector:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
sessionAffinity: None
type: ClusterIP
---
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
labels:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
name: etcd-headless
namespace: apisix
spec:
clusterIP: None
ports:
- name: client
port: 2379
protocol: TCP
targetPort: client
- name: peer
port: 2380
protocol: TCP
targetPort: peer
publishNotReadyAddresses: true
selector:
app.kubernetes.io/instance: etcd
app.kubernetes.io/name: etcd
sessionAffinity: None
type: ClusterIP
Apisix.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
labels:
name: apisix-pvc
namespace: apisix
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: nfs-controller-plane
apiVersion: v1
data:
config.yaml: |-
apisix:
# node_listen: 9080 # APISIX listening port
node_listen: # This style support multiple ports
- 9080
# - port: 9081
# enable_http2: true # If not set, the default value is `false`.
# - ip: 127.0.0.2 # Specific IP, If not set, the default value is `0.0.0.0`.
# port: 9082
# enable_http2: true
enable_admin: true
enable_admin_cors: true # Admin API support CORS response headers.
enable_dev_mode: false # Sets nginx worker_processes to 1 if set to true
enable_reuseport: true # Enable nginx SO_REUSEPORT switch if set to true.
show_upstream_status_in_response_header: true # when true all upstream status write to `X-APISIX-Upstream-Status` otherwise only 5xx code
enable_ipv6: true
config_center: etcd # etcd: use etcd to store the config value
# yaml: fetch the config value from local yaml file `/your_path/conf/apisix.yaml`
#proxy_protocol: # Proxy Protocol configuration
#listen_http_port: 9181 # The port with proxy protocol for http, it differs from node_listen and port_admin.
# This port can only receive http request with proxy protocol, but node_listen & port_admin
# can only receive http request. If you enable proxy protocol, you must use this port to
# receive http request with proxy protocol
#listen_https_port: 9182 # The port with proxy protocol for https
#enable_tcp_pp: true # Enable the proxy protocol for tcp proxy, it works for stream_proxy.tcp option
#enable_tcp_pp_to_upstream: true # Enables the proxy protocol to the upstream server
enable_server_tokens: true # Whether the APISIX version number should be shown in Server header.
# It's enabled by default.
# configurations to load third party code and/or override the builtin one.
extra_lua_path: "" # extend lua_package_path to load third party code
extra_lua_cpath: "" # extend lua_package_cpath to load third party code
#lua_module_hook: "my_project.my_hook" # the hook module which will be used to inject third party code into APISIX
proxy_cache: # Proxy Caching configuration
cache_ttl: 10s # The default caching time in disk if the upstream does not specify the cache time
zones: # The parameters of a cache
- name: disk_cache_one # The name of the cache, administrator can specify
# which cache to use by name in the admin api (disk|memory)
memory_size: 50m # The size of shared memory, it's used to store the cache index for
# disk strategy, store cache content for memory strategy (disk|memory)
disk_size: 1G # The size of disk, it's used to store the cache data (disk)
disk_path: /tmp/disk_cache_one # The path to store the cache data (disk)
cache_levels: 1:2 # The hierarchy levels of a cache (disk)
#- name: disk_cache_two
# memory_size: 50m
# disk_size: 1G
# disk_path: "/tmp/disk_cache_two"
# cache_levels: "1:2"
- name: memory_cache
memory_size: 50m
allow_admin: # http://nginx.org/en/docs/http/ngx_http_access_module.html#allow
- 127.0.0.1/32 # If we don't set any IP list, then any IP access is allowed by default.
#- "::/64"
admin_listen: # use a separate port
ip: 127.0.0.1 # Specific IP, if not set, the default value is `0.0.0.0`.
port: 9180
#port_admin: 9180 # Not recommend: This parameter should be set via the `admin_listen`.
#https_admin: true # enable HTTPS when use a separate port for Admin API.
# Admin API will use conf/apisix_admin_api.crt and conf/apisix_admin_api.key as certificate.
admin_api_mtls: # Depends on `port_admin` and `https_admin`.
admin_ssl_cert: "" # Path of your self-signed server side cert.
admin_ssl_cert_key: "" # Path of your self-signed server side key.
admin_ssl_ca_cert: "" # Path of your self-signed ca cert.The CA is used to sign all admin api callers' certificates.
# Default token when use API to call for Admin API.
# *NOTE*: Highly recommended to modify this value to protect APISIX's Admin API.
# Disabling this configuration item means that the Admin API does not
# require any authentication.
admin_key:
-
name: admin
key: 84b625edd1c95f136f87adc8f1f03433
role: admin # admin: manage all configuration data
# viewer: only can view configuration data
-
name: viewer
key: 4054f7cf07e344346cd3f287985e76a2
role: viewer
delete_uri_tail_slash: false # delete the '/' at the end of the URI
# The URI normalization in servlet is a little different from the RFC's.
# See https://github.com/jakartaee/servlet/blob/master/spec/src/main/asciidoc/servlet-spec-body.adoc#352-uri-path-canonicalization,
# which is used under Tomcat.
# Turn this option on if you want to be compatible with servlet when matching URI path.
normalize_uri_like_servlet: false
router:
http: radixtree_uri # radixtree_uri: match route by uri(base on radixtree)
# radixtree_host_uri: match route by host + uri(base on radixtree)
# radixtree_uri_with_parameter: like radixtree_uri but match uri with parameters,
# see https://github.com/api7/lua-resty-radixtree/#parameters-in-path for
# more details.
ssl: radixtree_sni # radixtree_sni: match route by SNI(base on radixtree)
#stream_proxy: # TCP/UDP proxy
# only: true # use stream proxy only, don't enable HTTP stuff
# tcp: # TCP proxy port list
# - addr: 9100
# tls: true
# - addr: "127.0.0.1:9101"
# udp: # UDP proxy port list
# - 9200
# - "127.0.0.1:9201"
#dns_resolver: # If not set, read from `/etc/resolv.conf`
# - 1.1.1.1
# - 8.8.8.8
dns_resolver_valid: 30 # if given, override the TTL of the valid records. The unit is second.
resolver_timeout: 5 # resolver timeout
enable_resolv_search_opt: true # enable search option in resolv.conf
ssl:
enable: true
listen: # APISIX listening port in https.
- 9443
# - port: 9444
# enable_http2: true # If not set, the default value is `false`.
# - ip: 127.0.0.3 # Specific IP, If not set, the default value is `0.0.0.0`.
# port: 9445
# enable_http2: true
enable_http2: true # Not recommend: This parameter should be set via the `listen`.
# listen_port: 9443 # Not recommend: This parameter should be set via the `listen`.
#ssl_trusted_certificate: /path/to/ca-cert # Specifies a file path with trusted CA certificates in the PEM format
# used to verify the certificate when APISIX needs to do SSL/TLS handshaking
# with external services (e.g. etcd)
ssl_protocols: TLSv1.2 TLSv1.3
ssl_ciphers: ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl_session_tickets: false # disable ssl_session_tickets by default for 'ssl_session_tickets' would make Perfect Forward Secrecy useless.
# ref: https://github.com/mozilla/server-side-tls/issues/135
key_encrypt_salt: edd1c9f0985e76a2 # If not set, will save origin ssl key into etcd.
# If set this, must be a string of length 16. And it will encrypt ssl key with AES-128-CBC
# !!! So do not change it after saving your ssl, it can't decrypt the ssl keys have be saved if you change !!
#fallback_sni: "my.default.domain" # If set this, when the client doesn't send SNI during handshake, the fallback SNI will be used instead
enable_control: true
#control:
# ip: 127.0.0.1
# port: 9090
disable_sync_configuration_during_start: false # safe exit. Remove this once the feature is stable
nginx_config: # config for render the template to generate nginx.conf
#user: root # specifies the execution user of the worker process.
# the "user" directive makes sense only if the master process runs with super-user privileges.
# if you're not root user,the default is current user.
error_log: logs/error.log
error_log_level: warn # warn,error
worker_processes: 2 # if you want use multiple cores in container, you can inject the number of cpu as environment variable "APISIX_WORKER_PROCESSES"
enable_cpu_affinity: true # enable cpu affinity, this is just work well only on physical machine
worker_rlimit_nofile: 20480 # the number of files a worker process can open, should be larger than worker_connections
worker_shutdown_timeout: 240s # timeout for a graceful shutdown of worker processes
max_pending_timers: 16384 # increase it if you see "too many pending timers" error
max_running_timers: 4096 # increase it if you see "lua_max_running_timers are not enough" error
event:
worker_connections: 10620
#envs: # allow to get a list of environment variables
# - TEST_ENV
stream:
enable_access_log: false # enable access log or not, default false
access_log: logs/access_stream.log
access_log_format: "$remote_addr [$time_local] $protocol $status $bytes_sent $bytes_received $session_time"
# create your custom log format by visiting http://nginx.org/en/docs/varindex.html
access_log_format_escape: default # allows setting json or default characters escaping in variables
lua_shared_dict:
etcd-cluster-health-check-stream: 10m
lrucache-lock-stream: 10m
plugin-limit-conn-stream: 10m
# As user can add arbitrary configurations in the snippet,
# it is user's responsibility to check the configurations
# don't conflict with APISIX.
main_configuration_snippet: |
# Add custom Nginx main configuration to nginx.conf.
# The configuration should be well indented!
http_configuration_snippet: |
# Add custom Nginx http configuration to nginx.conf.
# The configuration should be well indented!
http_server_configuration_snippet: |
# Add custom Nginx http server configuration to nginx.conf.
# The configuration should be well indented!
http_server_location_configuration_snippet: |
# Add custom Nginx http server location configuration to nginx.conf.
# The configuration should be well indented!
http_admin_configuration_snippet: |
# Add custom Nginx admin server configuration to nginx.conf.
# The configuration should be well indented!
http_end_configuration_snippet: |
# Add custom Nginx http end configuration to nginx.conf.
# The configuration should be well indented!
stream_configuration_snippet: |
# Add custom Nginx stream configuration to nginx.conf.
# The configuration should be well indented!
http:
enable_access_log: true # enable access log or not, default true
access_log: logs/access.log
access_log_format: "apikey:[$http_apikey] - $remote_addr - $remote_user [$time_local] $http_host \"$request\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\""
access_log_format_escape: default # allows setting json or default characters escaping in variables
keepalive_timeout: 75s # timeout during which a keep-alive client connection will stay open on the server side.
client_header_timeout: 60s # timeout for reading client request header, then 408 (Request Time-out) error is returned to the client
client_body_timeout: 60s # timeout for reading client request body, then 408 (Request Time-out) error is returned to the client
client_max_body_size: 0 # The maximum allowed size of the client request body.
# If exceeded, the 413 (Request Entity Too Large) error is returned to the client.
# Note that unlike Nginx, we don't limit the body size by default.
send_timeout: 10s # timeout for transmitting a response to the client.then the connection is closed
underscores_in_headers: "on" # default enables the use of underscores in client request header fields
real_ip_header: X-Real-IP # http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
real_ip_recursive: "off" # http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
real_ip_from: # http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
- 127.0.0.1
- "unix:"
#custom_lua_shared_dict: # add custom shared cache to nginx.conf
# ipc_shared_dict: 100m # custom shared cache, format: `cache-key: cache-size`
# Enables or disables passing of the server name through TLS Server Name Indication extension (SNI, RFC 6066)
# when establishing a connection with the proxied HTTPS server.
proxy_ssl_server_name: true
upstream:
keepalive: 320 # Sets the maximum number of idle keepalive connections to upstream servers that are preserved in the cache of each worker process.
# When this number is exceeded, the least recently used connections are closed.
keepalive_requests: 1000 # Sets the maximum number of requests that can be served through one keepalive connection.
# After the maximum number of requests is made, the connection is closed.
keepalive_timeout: 60s # Sets a timeout during which an idle keepalive connection to an upstream server will stay open.
charset: utf-8 # Adds the specified charset to the "Content-Type" response header field, see
# http://nginx.org/en/docs/http/ngx_http_charset_module.html#charset
variables_hash_max_size: 2048 # Sets the maximum size of the variables hash table.
lua_shared_dict:
internal-status: 10m
plugin-limit-req: 10m
plugin-limit-count: 10m
prometheus-metrics: 10m
plugin-limit-conn: 10m
upstream-healthcheck: 10m
worker-events: 10m
lrucache-lock: 10m
balancer-ewma: 10m
balancer-ewma-locks: 10m
balancer-ewma-last-touched-at: 10m
plugin-limit-count-redis-cluster-slot-lock: 1m
tracing_buffer: 10m
plugin-api-breaker: 10m
etcd-cluster-health-check: 10m
discovery: 1m
jwks: 1m
introspection: 10m
access-tokens: 1m
ext-plugin: 1m
kubernetes: 1m
tars: 1m
etcd:
host: # it's possible to define multiple etcd hosts addresses of the same etcd cluster.
#- "http://127.0.0.1:2379" # multiple etcd address, if your etcd cluster enables TLS, please use https scheme,
- "http://etcd-0.etcd-headless.apisix.svc.cluster.local:2379" # multiple etcd address
- "http://etcd-1.etcd-headless.apisix.svc.cluster.local:2379"
- "http://etcd-2.etcd-headless.apisix.svc.cluster.local:2379"
# e.g. https://127.0.0.1:2379.
prefix: /apisix # apisix configurations prefix
timeout: 30 # 30 seconds
#resync_delay: 5 # when sync failed and a rest is needed, resync after the configured seconds plus 50% random jitter
#health_check_timeout: 10 # etcd retry the unhealthy nodes after the configured seconds
health_check_retry: 2 # etcd retry time that only affects the health check, default 2
#user: root # root username for etcd
#password: 5tHkHhYkjr6cQY # root password for etcd
tls:
# To enable etcd client certificate you need to build APISIX-Base, see
# https://apisix.apache.org/docs/apisix/FAQ#how-do-i-build-the-apisix-base-environment?
#cert: /path/to/cert # path of certificate used by the etcd client
#key: /path/to/key # path of key used by the etcd client
verify: true # whether to verify the etcd endpoint certificate when setup a TLS connection to etcd,
# the default value is true, e.g. the certificate will be verified strictly.
#sni: # the SNI for etcd TLS requests. If missed, the host part of the URL will be used.
# HashiCorp Vault storage backend for sensitive data retrieval. The config shows an example of what APISIX expects if you
# wish to integrate Vault for secret (sensetive string, public private keys etc.) retrieval. APISIX communicates with Vault
# server HTTP APIs. By default, APISIX doesn't need this configuration.
# vault:
# host: "http://0.0.0.0:8200" # The host address where the vault server is running.
# timeout: 10 # request timeout 30 seconds
# token: root # Authentication token to access Vault HTTP APIs
# prefix: kv/apisix # APISIX supports vault kv engine v1, where sensitive data are being stored
# and retrieved through vault HTTP APIs. enabling a prefix allows you to better enforcement of
# policies, generate limited scoped tokens and tightly control the data that can be accessed
# from APISIX.
#discovery: # service discovery center
# dns:
# servers:
# - "127.0.0.1:8600" # use the real address of your dns server
# eureka:
# host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster.
# - "http://127.0.0.1:8761"
# prefix: /eureka/
# fetch_interval: 30 # default 30s
# weight: 100 # default weight for node
# timeout:
# connect: 2000 # default 2000ms
# send: 2000 # default 2000ms
# read: 5000 # default 5000ms
graphql:
max_size: 1048576 # the maximum size limitation of graphql in bytes, default 1MiB
#ext-plugin:
#cmd: ["ls", "-l"]
plugins: # plugin list (sorted by priority)
- real-ip # priority: 23000
- client-control # priority: 22000
- proxy-control # priority: 21990
- zipkin # priority: 12011
#- skywalking # priority: 12010
#- opentelemetry # priority: 12009
- ext-plugin-pre-req # priority: 12000
- request-id # priority: 11010
- fault-injection # priority: 11000
- mocking # priority: 10900
- serverless-pre-function # priority: 10000
#- batch-requests # priority: 4010
- cors # priority: 4000
- ip-restriction # priority: 3000
- ua-restriction # priority: 2999
- referer-restriction # priority: 2990
- csrf # priority: 2980
- uri-blocker # priority: 2900
- request-validation # priority: 2800
- openid-connect # priority: 2599
- authz-casbin # priority: 2560
- authz-casdoor # priority: 2559
- wolf-rbac # priority: 2555
- ldap-auth # priority: 2540
- hmac-auth # priority: 2530
- basic-auth # priority: 2520
- jwt-auth # priority: 2510
- key-auth # priority: 2500
- consumer-restriction # priority: 2400
- forward-auth # priority: 2002
- opa # priority: 2001
- authz-keycloak # priority: 2000
- pj-auth # priority: 1999
#- error-log-logger # priority: 1091
- proxy-mirror # priority: 1010
- proxy-cache # priority: 1009
- proxy-rewrite # priority: 1008
- api-breaker # priority: 1005
- limit-conn # priority: 1003
- limit-count # priority: 1002
- limit-req # priority: 1001
- node-status # priority: 1000
- gzip # priority: 995
- server-info # priority: 990
- traffic-split # priority: 966
- redirect # priority: 900
- response-rewrite # priority: 899
- kafka-proxy # priority: 508
#- dubbo-proxy # priority: 507
- grpc-transcode # priority: 506
- grpc-web # priority: 505
- public-api # priority: 501
- prometheus # priority: 500
- datadog # priority: 495
- echo # priority: 412
- loggly # priority: 411
- http-logger # priority: 410
- splunk-hec-logging # priority: 409
- skywalking-logger # priority: 408
- google-cloud-logging # priority: 407
- sls-logger # priority: 406
- tcp-logger # priority: 405
- kafka-logger # priority: 403
- rocketmq-logger # priority: 402
- syslog # priority: 401
- udp-logger # priority: 400
- file-logger # priority: 399
- clickhouse-logger # priority: 398
- log-rotate # priority: 100
# <- recommend to use priority (0, 100) for your custom plugins
- example-plugin # priority: 0
- aws-lambda # priority: -1899
- azure-functions # priority: -1900
- openwhisk # priority: -1901
- serverless-post-function # priority: -2000
- ext-plugin-post-req # priority: -3000
- ext-plugin-post-resp # priority: -4000
stream_plugins: # sorted by priority
- ip-restriction # priority: 3000
- limit-conn # priority: 1003
- mqtt-proxy # priority: 1000
- syslog # priority: 401
# <- recommend to use priority (0, 100) for your custom plugins
#wasm:
#plugins:
#- name: wasm_log
#priority: 7999
#file: t/wasm/log/main.go.wasm
#xrpc:
#protocols:
#- name: pingpong
plugin_attr:
log-rotate:
interval: 3600 # rotate interval (unit: second)
max_kept: 12 # max number of log files will be kept
enable_compression: false # enable log file compression(gzip) or not, default false
skywalking:
service_name: APISIX
service_instance_name: APISIX Instance Name
endpoint_addr: http://127.0.0.1:12800
opentelemetry:
trace_id_source: x-request-id
resource:
service.name: APISIX
collector:
address: 127.0.0.1:4318
request_timeout: 3
request_headers:
Authorization: token
batch_span_processor:
drop_on_queue_full: false
max_queue_size: 1024
batch_timeout: 2
inactive_timeout: 1
max_export_batch_size: 16
prometheus:
export_uri: /apisix/prometheus/metrics
metric_prefix: apisix_
enable_export_server: true
export_addr:
ip: 0.0.0.0
port: 9091
server-info:
report_ttl: 60 # live time for server info in etcd (unit: second)
dubbo-proxy:
upstream_multiplex_count: 32
request-id:
snowflake:
enable: false
snowflake_epoc: 1609459200000 # the starting timestamp is expressed in milliseconds
data_machine_bits: 12 # data machine bit, maximum 31, because Lua cannot do bit operations greater than 31
sequence_bits: 10 # each machine generates a maximum of (1 << sequence_bits) serial numbers per millisecond
data_machine_ttl: 30 # live time for data_machine in etcd (unit: second)
data_machine_interval: 10 # lease renewal interval in etcd (unit: second)
proxy-mirror:
timeout: # proxy timeout in mirrored sub-request
connect: 60s
read: 60s
send: 60s
# redirect:
# https_port: 8443 # the default port for use by HTTP redirects to HTTPS
kind: ConfigMap
metadata:
labels:
clus_id: "1"
name: apisix-cm
namespace: apisix
apiVersion: v1
data:
pj-auth.lua: |-
--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements. See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You under the Apache License, Version 2.0
-- (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local core = require("apisix.core")
local ck = require("resty.cookie")
local http = require("resty.http")
local json = require("apisix.core.json")
local posix = require'posix'
local sub_str = string.sub
local schema = {
type = "object",
properties = {
address = {
type = "string",
default = "portal-auth.paas-portal.svc.cluster.local:8080",
},
}
}
-- 常量 自身插件名
local plugin_name = "pj-auth-plugin"
local _M = {
version = 0.1,
priority = 1999, -- TODO: add a type field, may be a good idea
name = plugin_name,
schema = schema,
}
local create_consume_cache
do
local consumer_ids = {}
function create_consume_cache(consumers)
core.table.clear(consumer_ids)
for _, consumer in ipairs(consumers.nodes) do
core.log.info("consumer node: ", core.json.delay_encode(consumer))
consumer_ids[consumer.auth_conf.appid] = consumer
end
return consumer_ids
end
end -- do
local function fetch_jwt_token(ctx)
-- 从请求中获得token
local token = core.request.header(ctx, "authorization")
if token then
local prefix = sub_str(token, 1, 7)
if prefix == 'Bearer ' or prefix == 'bearer ' then
return sub_str(token, 8)
end
return token
end
token = ctx.var.arg_jwt
if token then
return token
end
local cookie, err = ck:new()
if not cookie then
return nil, err
end
local val, err = cookie:get("jwt")
return val, err
end
local function new_headers()
-- 子请求的头
local t = {}
local lt = {}
local _mt = {
__index = function(t, k)
return rawget(lt, string.lower(k))
end,
__newindex = function(t, k, v)
rawset(t, k, v)
rawset(lt, string.lower(k), v)
end,
}
return setmetatable(t, _mt)
end
local function http_req(method, uri, body, myheaders, timeout)
-- 子请求构造,timeout单位ms
if myheaders == nil then myheaders = new_headers() end
local httpc = http.new()
if timeout then
httpc:set_timeouts(timeout, timeout, timeout)
end
local params = {method = method, headers = myheaders, body = body, keepalive = false, ssl_verify = false}
local res, err = httpc:request_uri(uri, params)
if err then
return nil, err
end
return res
end
local function http_post(uri, body, myheaders, timeout)
-- post请求方法
return http_req("POST", uri, body, myheaders, timeout)
end
function _M.check_schema(conf)
local ok, err = core.schema.check(schema, conf)
if not ok then
return false, err
end
return true
end
local function check_url_acl(server, action, req_uri, req_token)
-- 验证acl
-- 入参: acl服务接口地址,用户名,req的method,uri
local retry_max = 3
local errmsg
local res
local err
local access_check_url = server .. "/api/v1/auth-api"
local headers = new_headers()
headers["Content-Type"] = "application/json; charset=utf-8"
local ts_req1, ts_req2 = posix.clock_gettime()
local args = { uri = req_uri, method = action, token = req_token}
local timeout = 1000 * 10
for i = 1, retry_max do
res, err = http_post("http://" .. access_check_url, core.json.encode(args), headers, timeout)
if err then
break
else
if res.status < 500 then
break
else
core.log.error("request [curl -v ", url, "] failed! status:", res.status)
if i < retry_max then
ngx.sleep(0.1)
end
end
end
end
if err then
-- 访问acl-server异常
return {res_body = nil, status = 500, err = "request to acl-server failed, err:" .. tostring(err)}
end
if res.status ~= 200 and res.status ~= 403 then
-- 非200和403的未知http码
return {res_body = nil, status = 500, err = 'request to acl-server failed, status:' .. tostring(res.status)}
end
local ts_req3, ts_req4 = posix.clock_gettime()
if ts_req3-ts_req1 >= 1 then
core.log.error("over_1_s")
elseif ts_req4/1000000-ts_req2/1000000 >= 200 then
core.log.error("over_200_ms")
end
local body, err = json.decode(res.body)
if err then
errmsg = 'check permission failed! parse response json failed!'
return {res_body = nil, status = res.status, err = errmsg}
else
core.log.error("rsp_bdy:", core.json.delay_encode(res.body))
return {res_body = body, status = res.status}
end
end
function _M.rewrite(conf, ctx)
local uri = ctx.var.uri
local action = ctx.var.request_method
-- 如果是游览器为了跨域而发的OPTIONS,直接返回OK
if 'OPTIONS' == action then
return 200
end
local jwt_token, err = fetch_jwt_token(ctx)
if not jwt_token then
return 401, {message = "Missing JWT token in request"}
end
local res = check_url_acl(conf.address, action, uri, jwt_token)
if res.status ~= 200 then
return 401, {message = "no permission. code:10001"}
end
local code = res.res_body.code
if code ~= 200 then
if code == 30001 then
return 403, {message = "no permission. code:30001"}
elseif code == 30002 then
return 401, {message = "no permission. code:30002"}
elseif code == 30003 then
return 401, {message = "no permission. code:30002"}
elseif code == 40001 then
return 403, {message = "no permission. code:30002"}
elseif code == 40002 then
return 403, {message = "no permission. code:30002"}
elseif code == 40003 then
return 403, {message = "no permission. code:30002"}
elseif code == 40004 then
return 403, {message = "no permission. code:30002"}
else
return 403, {message = "no permission. code:10001"}
end
end
if res.res_body.data.auth ~= true then
return 403, {message = "no permission. code:30002"}
end
core.request.set_header(ctx, "username", res.res_body.data.userName)
core.request.set_header(ctx, "tenantcode", res.res_body.data.tenantCode)
end
return _M
kind: ConfigMap
metadata:
labels:
clus_id: "1"
name: apisix-pj-auth-cm
namespace: apisix
apiVersion: v1
kind: Service
metadata:
labels:
app: apisix
name: apisix
namespace: apisix
spec:
ports:
- name: http-apisix
port: 34088
protocol: TCP
targetPort: 9080
- name: http-apisix-prometheus
port: 34080
protocol: TCP
targetPort: 9091
selector:
app: apisix
sessionAffinity: None
type: ClusterIP
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: apisix
name: apisix
namespace: apisix
spec:
progressDeadlineSeconds: 600
replicas: 4
revisionHistoryLimit: 10
selector: # 匹配Pod标签的选择器,必须匹配到spec.template.metadata.labels的pod标签
matchLabels:
app: apisix
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
template: #spec.template里的内容就是声明Pod对象时要定义的各种属性所以叫PodTemplate
metadata:
creationTimestamp: null
labels:
app: apisix
spec: # pod里的容器属性配置
containers:
- image: artifactory.dep.devops.cmit.cloud:20101/panji_middleware/apisix:2.13.3
imagePullPolicy: Always
readinessProbe:
failureThreshold: 6
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 9080
timeoutSeconds: 1
lifecycle:
preStop:
exec:
command:
- /bin/sh
- '-c'
- sleep 30
name: apisix
ports:
- containerPort: 9080
protocol: TCP
- containerPort: 9091
protocol: TCP
resources:
requests:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "3Gi"
limits:
cpu: "2"
memory: "2Gi"
ephemeral-storage: "4Gi"
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/localtime
name: timezone
- mountPath: /usr/local/apisix/logs/
name: paas-pvc-log
subPath: apisixlog
- mountPath: /usr/local/apisix/conf/config.yaml
name: apisix-conf-path
subPath: config.yaml
- mountPath: /usr/local/apisix/apisix/plugins/pj-auth.lua
name: apisix-conf-pj-auth-path
subPath: pj-auth.lua
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
dnsPolicy: ClusterFirst
terminationGracePeriodSeconds: 30
volumes:
- name: paas-pvc-log
persistentVolumeClaim:
claimName: apisix-pvc
- configMap:
defaultMode: 420
items:
- key: config.yaml
path: config.yaml
name: apisix-cm
name: apisix-conf-path
- configMap:
defaultMode: 420
items:
- key: pj-auth.lua
path: pj-auth.lua
name: apisix-pj-auth-cm
name: apisix-conf-pj-auth-path
- hostPath:
path: /etc/localtime
type: ""
name: timezone
Apisix-dashboard.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
labels:
name: apisix-dashboard-role
namespace: apisix
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- list
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
name: apisix-dashboard-sa
namespace: apisix
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
name: apisix-dashboard-rolebinding
namespace: apisix
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: apisix-dashboard-role
subjects:
- kind: ServiceAccount
name: apisix-dashboard-sa
namespace: apisix
apiVersion: v1
data:
conf.yaml: |-
conf:
listen:
# host: 127.0.0.1 # the address on which the `Manager API` should listen.
# The default value is 0.0.0.0, if want to specify, please enable it.
# This value accepts IPv4, IPv6, and hostname.
port: 9000 # The port on which the `Manager API` should listen.
# ssl:
# host: 127.0.0.1 # the address on which the `Manager API` should listen for HTTPS.
# The default value is 0.0.0.0, if want to specify, please enable it.
# port: 9001 # The port on which the `Manager API` should listen for HTTPS.
# cert: "/tmp/cert/example.crt" # Path of your SSL cert.
# key: "/tmp/cert/example.key" # Path of your SSL key.
allow_list: # If we don't set any IP list, then any IP access is allowed by default.
- 0.0.0.0/0 # The rules are checked in sequence until the first match is found.
- ::1 # In this example, access is allowed only for IPv4 network 127.0.0.1, and for IPv6 network ::1.
# It also support CIDR like 192.168.1.0/24 and 2001:0db8::/32
etcd:
endpoints: # supports defining multiple etcd host addresses for an etcd cluster
- http://etcd-0.etcd-headless.apisix.svc.cluster.local:2379
- http://etcd-1.etcd-headless.apisix.svc.cluster.local:2379
- http://etcd-2.etcd-headless.apisix.svc.cluster.local:2379
# yamllint disable rule:comments-indentation
# etcd basic auth info
# username: "root" # ignore etcd username if not enable etcd auth
# password: "123456" # ignore etcd password if not enable etcd auth
mtls:
key_file: "" # Path of your self-signed client side key
cert_file: "" # Path of your self-signed client side cert
ca_file: "" # Path of your self-signed ca cert, the CA is used to sign callers' certificates
# prefix: /apisix # apisix config's prefix in etcd, /apisix by default
log:
error_log:
level: warn # supports levels, lower to higher: debug, info, warn, error, panic, fatal
file_path:
logs/error.log # supports relative path, absolute path, standard output
# such as: logs/error.log, /tmp/logs/error.log, /dev/stdout, /dev/stderr
# such as absolute path on Windows: winfile:///C:\error.log
access_log:
file_path:
logs/access.log # supports relative path, absolute path, standard output
# such as: logs/access.log, /tmp/logs/access.log, /dev/stdout, /dev/stderr
# such as absolute path on Windows: winfile:///C:\access.log
# log example: 2020-12-09T16:38:09.039+0800 INFO filter/logging.go:46 /apisix/admin/routes/r1 {"status": 401, "host": "127.0.0.1:9000", "query": "asdfsafd=adf&a=a", "requestId": "3d50ecb8-758c-46d1-af5b-cd9d1c820156", "latency": 0, "remoteIP": "127.0.0.1", "method": "PUT", "errs": []}
max_cpu: 0 # supports tweaking with the number of OS threads are going to be used for parallelism. Default value: 0 [will use max number of available cpu cores considering hyperthreading (if any)]. If the value is negative, is will not touch the existing parallelism profile.
# security:
# access_control_allow_origin: "http://httpbin.org"
# access_control_allow_credentials: true # support using custom cors configration
# access_control_allow_headers: "Authorization"
# access_control-allow_methods: "*"
# x_frame_options: "deny"
# content_security_policy: ""default-src 'self'; script-src 'self' 'unsafe-eval'; style-src 'self' 'unsafe-inline'""
authentication:
secret:
secret # secret for jwt token generation.
# NOTE: Highly recommended to modify this value to protect `manager api`.
# if it's default value, when `manager api` start, it will generate a random string to replace it.
expire_time: 3600 # jwt token expire time, in second
users: # yamllint enable rule:comments-indentation
- username: admin # username and password for login `manager api`
password: af7aaf061243bf1f3bb8679a2492dfe2
- username: user
password: 9c313a7d7a48e29f5bc0423d28be264c
plugins: # plugin list (sorted in alphabetical order)
- api-breaker
- authz-keycloak
- basic-auth
- batch-requests
- consumer-restriction
- cors
# - dubbo-proxy
- echo
# - error-log-logger
# - example-plugin
- fault-injection
- grpc-transcode
- hmac-auth
- http-logger
- ip-restriction
- jwt-auth
- kafka-logger
- key-auth
- limit-conn
- limit-count
- limit-req
- log-rotate
- node-status
- openid-connect
- prometheus
- proxy-cache
- proxy-mirror
- proxy-rewrite
- redirect
- referer-restriction
- request-id
- request-validation
- response-rewrite
- serverless-post-function
- serverless-pre-function
# - skywalking
- sls-logger
- syslog
- tcp-logger
- udp-logger
- uri-blocker
- wolf-rbac
- zipkin
- server-info
- traffic-split
kind: ConfigMap
metadata:
labels:
name: apisix-dashboard-cm
namespace: apisix
apiVersion: v1
data:
schema.json: |-
{"main":{"proto":{"properties":{"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"update_time":{"type":"integer"},"content":{"minLength":1,"type":"string","maxLength":1048576},"desc":{"type":"string","maxLength":256},"create_time":{"type":"integer"}},"type":"object","required":["content"]},"plugins":{"type":"array","items":{"properties":{"name":{"type":"string","minLength":1},"stream":{"type":"boolean"}},"type":"object","required":["name"]}},"route":{"allOf":[{"oneOf":[{"required":["uri"]},{"required":["uris"]}]},{"oneOf":[{"not":{"anyOf":[{"required":["host"]},{"required":["hosts"]}]}},{"required":["host"]},{"required":["hosts"]}]},{"oneOf":[{"not":{"anyOf":[{"required":["remote_addr"]},{"required":["remote_addrs"]}]}},{"required":["remote_addr"]},{"required":["remote_addrs"]}]}],"properties":{"status":{"description":"route status, 1 to enable, 0 to disable","default":1,"type":"integer","enum":[1,0]},"uris":{"minItems":1,"items":{"description":"HTTP uri","type":"string"},"type":"array","uniqueItems":true},"enable_websocket":{"description":"enable websocket for request","type":"boolean"},"methods":{"uniqueItems":true,"items":{"description":"HTTP method","type":"string","enum":["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS","CONNECT","TRACE"]},"type":"array"},"hosts":{"minItems":1,"items":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"type":"array","uniqueItems":true},"priority":{"type":"integer","default":0},"filter_func":{"minLength":10,"type":"string","pattern":"^function"},"script":{"minLength":10,"type":"string","maxLength":102400},"script_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"update_time":{"type":"integer"},"name":{"minLength":1,"type":"string","maxLength":100},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"service_protocol":{"enum":["grpc","http"]},"plugins":{"type":"object"},"remote_addrs":{"minItems":1,"items":{"description":"client IP","type":"string","anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"type":"array","uniqueItems":true},"service_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"desc":{"type":"string","maxLength":256},"uri":{"minLength":1,"type":"string","maxLength":4096},"upstream":{"properties":{"retries":{"type":"integer","minimum":0},"retry_timeout":{"type":"number","minimum":0},"keepalive_pool":{"type":"object","properties":{"idle_timeout":{"minimum":0,"type":"number","default":60},"requests":{"minimum":1,"type":"integer","default":1000},"size":{"minimum":1,"type":"integer","default":320}}},"type":{"description":"algorithms of load balancing","type":"string"},"update_time":{"type":"integer"},"name":{"minLength":1,"type":"string","maxLength":100},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"discovery_type":{"description":"discovery type","type":"string"},"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"discovery_args":{"type":"object","properties":{"namespace_id":{"description":"namespace id","type":"string"},"group_name":{"description":"group name","type":"string"}}},"checks":{"anyOf":[{"required":["active"]},{"required":["active","passive"]}],"properties":{"active":{"type":"object","properties":{"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"req_headers":{"minItems":1,"items":{"type":"string","uniqueItems":true},"type":"array"},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"port":{"maximum":65535,"type":"integer","minimum":1},"healthy":{"type":"object","properties":{"interval":{"default":1,"type":"integer","minimum":1},"http_statuses":{"default":[200,302],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"successes":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":1},"http_statuses":{"default":[429,404,500,501,502,503,504,505],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"timeouts":{"default":3,"maximum":254,"type":"integer","minimum":1},"interval":{"default":1,"type":"integer","minimum":1},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"concurrency":{"type":"integer","default":10},"http_path":{"type":"string","default":"\/"},"https_verify_certificate":{"type":"boolean","default":true},"timeout":{"type":"number","default":1}}},"passive":{"properties":{"healthy":{"type":"object","properties":{"successes":{"default":5,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":0},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":0},"timeouts":{"default":7,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[429,500,503],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}}},"type":"object","default":{"healthy":{"successes":0,"http_statuses":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308]},"type":"http","unhealthy":{"http_failures":0,"tcp_failures":0,"timeouts":0,"http_statuses":[429,500,503]}}}},"type":"object"},"service_name":{"minLength":1,"type":"string","maxLength":256},"desc":{"type":"string","maxLength":256},"key":{"description":"the key of chash for dynamic load balancing","type":"string"},"upstream_host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"pass_host":{"description":"mod of host passing","default":"pass","type":"string","enum":["pass","node","rewrite"]},"timeout":{"properties":{"connect":{"type":"number","exclusiveMinimum":0},"send":{"type":"number","exclusiveMinimum":0},"read":{"type":"number","exclusiveMinimum":0}},"type":"object","required":["connect","send","read"]},"hash_on":{"default":"vars","type":"string","enum":["vars","header","cookie","consumer","vars_combinations"]},"nodes":{"anyOf":[{"type":"object","patternProperties":{".*":{"description":"weight of node","type":"integer","minimum":0}}},{"type":"array","items":{"properties":{"weight":{"description":"weight of node","type":"integer","minimum":0},"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"priority":{"description":"priority of node","type":"integer","default":0},"metadata":{"description":"metadata of node","type":"object"},"port":{"description":"port of node","type":"integer","minimum":1}},"type":"object","required":["host","port","weight"]}}]},"scheme":{"description":"The scheme of the upstream. For L7 proxy, it can be one of grpc\/grpcs\/http\/https. For L4 proxy, it can be one of tcp\/tls\/udp.","default":"http","enum":["grpc","grpcs","http","https","tcp","tls","udp"]},"tls":{"properties":{"client_cert":{"minLength":128,"type":"string","maxLength":65536},"client_key":{"minLength":128,"type":"string","maxLength":65536}},"type":"object","required":["client_cert","client_key"]},"create_time":{"type":"integer"}},"type":"object","oneOf":[{"required":["type","nodes"]},{"required":["type","service_name","discovery_type"]}]},"plugin_config_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"create_time":{"type":"integer"},"remote_addr":{"description":"client IP","type":"string","anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"upstream_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"vars":{"type":"array"},"timeout":{"properties":{"connect":{"type":"number","exclusiveMinimum":0},"send":{"type":"number","exclusiveMinimum":0},"read":{"type":"number","exclusiveMinimum":0}},"type":"object","required":["connect","send","read"]}},"not":{"anyOf":[{"required":["script","plugins"]},{"required":["script","plugin_config_id"]}]},"type":"object","anyOf":[{"required":["plugins","uri"]},{"required":["upstream","uri"]},{"required":["upstream_id","uri"]},{"required":["service_id","uri"]},{"required":["plugins","uris"]},{"required":["upstream","uris"]},{"required":["upstream_id","uris"]},{"required":["service_id","uris"]},{"required":["script","uri"]},{"required":["script","uris"]}]},"upstream":{"properties":{"retries":{"type":"integer","minimum":0},"retry_timeout":{"type":"number","minimum":0},"keepalive_pool":{"type":"object","properties":{"idle_timeout":{"minimum":0,"type":"number","default":60},"requests":{"minimum":1,"type":"integer","default":1000},"size":{"minimum":1,"type":"integer","default":320}}},"type":{"description":"algorithms of load balancing","type":"string"},"update_time":{"type":"integer"},"name":{"minLength":1,"type":"string","maxLength":100},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"discovery_type":{"description":"discovery type","type":"string"},"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"discovery_args":{"type":"object","properties":{"namespace_id":{"description":"namespace id","type":"string"},"group_name":{"description":"group name","type":"string"}}},"checks":{"anyOf":[{"required":["active"]},{"required":["active","passive"]}],"properties":{"active":{"type":"object","properties":{"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"req_headers":{"minItems":1,"items":{"type":"string","uniqueItems":true},"type":"array"},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"port":{"maximum":65535,"type":"integer","minimum":1},"healthy":{"type":"object","properties":{"interval":{"default":1,"type":"integer","minimum":1},"http_statuses":{"default":[200,302],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"successes":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":1},"http_statuses":{"default":[429,404,500,501,502,503,504,505],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"timeouts":{"default":3,"maximum":254,"type":"integer","minimum":1},"interval":{"default":1,"type":"integer","minimum":1},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"concurrency":{"type":"integer","default":10},"http_path":{"type":"string","default":"\/"},"https_verify_certificate":{"type":"boolean","default":true},"timeout":{"type":"number","default":1}}},"passive":{"properties":{"healthy":{"type":"object","properties":{"successes":{"default":5,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":0},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":0},"timeouts":{"default":7,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[429,500,503],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}}},"type":"object","default":{"healthy":{"successes":0,"http_statuses":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308]},"type":"http","unhealthy":{"http_failures":0,"tcp_failures":0,"timeouts":0,"http_statuses":[429,500,503]}}}},"type":"object"},"service_name":{"minLength":1,"type":"string","maxLength":256},"desc":{"type":"string","maxLength":256},"key":{"description":"the key of chash for dynamic load balancing","type":"string"},"upstream_host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"pass_host":{"description":"mod of host passing","default":"pass","type":"string","enum":["pass","node","rewrite"]},"timeout":{"properties":{"connect":{"type":"number","exclusiveMinimum":0},"send":{"type":"number","exclusiveMinimum":0},"read":{"type":"number","exclusiveMinimum":0}},"type":"object","required":["connect","send","read"]},"hash_on":{"default":"vars","type":"string","enum":["vars","header","cookie","consumer","vars_combinations"]},"nodes":{"anyOf":[{"type":"object","patternProperties":{".*":{"description":"weight of node","type":"integer","minimum":0}}},{"type":"array","items":{"properties":{"weight":{"description":"weight of node","type":"integer","minimum":0},"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"priority":{"description":"priority of node","type":"integer","default":0},"metadata":{"description":"metadata of node","type":"object"},"port":{"description":"port of node","type":"integer","minimum":1}},"type":"object","required":["host","port","weight"]}}]},"scheme":{"description":"The scheme of the upstream. For L7 proxy, it can be one of grpc\/grpcs\/http\/https. For L4 proxy, it can be one of tcp\/tls\/udp.","default":"http","enum":["grpc","grpcs","http","https","tcp","tls","udp"]},"tls":{"properties":{"client_cert":{"minLength":128,"type":"string","maxLength":65536},"client_key":{"minLength":128,"type":"string","maxLength":65536}},"type":"object","required":["client_cert","client_key"]},"create_time":{"type":"integer"}},"type":"object","oneOf":[{"required":["type","nodes"]},{"required":["type","service_name","discovery_type"]}]},"global_rule":{"properties":{"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"update_time":{"type":"integer"},"plugins":{"type":"object"},"create_time":{"type":"integer"}},"type":"object","required":["plugins"]},"stream_route":{"type":"object","properties":{"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"plugins":{"type":"object"},"remote_addr":{"description":"client IP","type":"string","anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"desc":{"type":"string","maxLength":256},"update_time":{"type":"integer"},"server_addr":{"description":"server IP","type":"string","anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"upstream_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"upstream":{"properties":{"retries":{"type":"integer","minimum":0},"retry_timeout":{"type":"number","minimum":0},"keepalive_pool":{"type":"object","properties":{"idle_timeout":{"minimum":0,"type":"number","default":60},"requests":{"minimum":1,"type":"integer","default":1000},"size":{"minimum":1,"type":"integer","default":320}}},"type":{"description":"algorithms of load balancing","type":"string"},"update_time":{"type":"integer"},"name":{"minLength":1,"type":"string","maxLength":100},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"discovery_type":{"description":"discovery type","type":"string"},"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"discovery_args":{"type":"object","properties":{"namespace_id":{"description":"namespace id","type":"string"},"group_name":{"description":"group name","type":"string"}}},"checks":{"anyOf":[{"required":["active"]},{"required":["active","passive"]}],"properties":{"active":{"type":"object","properties":{"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"req_headers":{"minItems":1,"items":{"type":"string","uniqueItems":true},"type":"array"},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"port":{"maximum":65535,"type":"integer","minimum":1},"healthy":{"type":"object","properties":{"interval":{"default":1,"type":"integer","minimum":1},"http_statuses":{"default":[200,302],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"successes":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":1},"http_statuses":{"default":[429,404,500,501,502,503,504,505],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"timeouts":{"default":3,"maximum":254,"type":"integer","minimum":1},"interval":{"default":1,"type":"integer","minimum":1},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"concurrency":{"type":"integer","default":10},"http_path":{"type":"string","default":"\/"},"https_verify_certificate":{"type":"boolean","default":true},"timeout":{"type":"number","default":1}}},"passive":{"properties":{"healthy":{"type":"object","properties":{"successes":{"default":5,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":0},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":0},"timeouts":{"default":7,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[429,500,503],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}}},"type":"object","default":{"healthy":{"successes":0,"http_statuses":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308]},"type":"http","unhealthy":{"http_failures":0,"tcp_failures":0,"timeouts":0,"http_statuses":[429,500,503]}}}},"type":"object"},"service_name":{"minLength":1,"type":"string","maxLength":256},"desc":{"type":"string","maxLength":256},"key":{"description":"the key of chash for dynamic load balancing","type":"string"},"upstream_host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"pass_host":{"description":"mod of host passing","default":"pass","type":"string","enum":["pass","node","rewrite"]},"timeout":{"properties":{"connect":{"type":"number","exclusiveMinimum":0},"send":{"type":"number","exclusiveMinimum":0},"read":{"type":"number","exclusiveMinimum":0}},"type":"object","required":["connect","send","read"]},"hash_on":{"default":"vars","type":"string","enum":["vars","header","cookie","consumer","vars_combinations"]},"nodes":{"anyOf":[{"type":"object","patternProperties":{".*":{"description":"weight of node","type":"integer","minimum":0}}},{"type":"array","items":{"properties":{"weight":{"description":"weight of node","type":"integer","minimum":0},"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"priority":{"description":"priority of node","type":"integer","default":0},"metadata":{"description":"metadata of node","type":"object"},"port":{"description":"port of node","type":"integer","minimum":1}},"type":"object","required":["host","port","weight"]}}]},"scheme":{"description":"The scheme of the upstream. For L7 proxy, it can be one of grpc\/grpcs\/http\/https. For L4 proxy, it can be one of tcp\/tls\/udp.","default":"http","enum":["grpc","grpcs","http","https","tcp","tls","udp"]},"tls":{"properties":{"client_cert":{"minLength":128,"type":"string","maxLength":65536},"client_key":{"minLength":128,"type":"string","maxLength":65536}},"type":"object","required":["client_cert","client_key"]},"create_time":{"type":"integer"}},"type":"object","oneOf":[{"required":["type","nodes"]},{"required":["type","service_name","discovery_type"]}]},"server_port":{"description":"server port","type":"integer"},"sni":{"description":"server name indication","type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"create_time":{"type":"integer"}}},"upstream_hash_vars_schema":{"type":"string","pattern":"^((uri|server_name|server_addr|request_uri|remote_port|remote_addr|query_string|host|hostname)|arg_[0-9a-zA-z_-]+)$"},"service":{"type":"object","properties":{"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"enable_websocket":{"description":"enable websocket for request","type":"boolean"},"plugins":{"type":"object"},"script":{"minLength":10,"type":"string","maxLength":102400},"hosts":{"minItems":1,"items":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"type":"array","uniqueItems":true},"update_time":{"type":"integer"},"name":{"minLength":1,"type":"string","maxLength":100},"desc":{"type":"string","maxLength":256},"upstream":{"properties":{"retries":{"type":"integer","minimum":0},"retry_timeout":{"type":"number","minimum":0},"keepalive_pool":{"type":"object","properties":{"idle_timeout":{"minimum":0,"type":"number","default":60},"requests":{"minimum":1,"type":"integer","default":1000},"size":{"minimum":1,"type":"integer","default":320}}},"type":{"description":"algorithms of load balancing","type":"string"},"update_time":{"type":"integer"},"name":{"minLength":1,"type":"string","maxLength":100},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"discovery_type":{"description":"discovery type","type":"string"},"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"discovery_args":{"type":"object","properties":{"namespace_id":{"description":"namespace id","type":"string"},"group_name":{"description":"group name","type":"string"}}},"checks":{"anyOf":[{"required":["active"]},{"required":["active","passive"]}],"properties":{"active":{"type":"object","properties":{"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"req_headers":{"minItems":1,"items":{"type":"string","uniqueItems":true},"type":"array"},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"port":{"maximum":65535,"type":"integer","minimum":1},"healthy":{"type":"object","properties":{"interval":{"default":1,"type":"integer","minimum":1},"http_statuses":{"default":[200,302],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"successes":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":1},"http_statuses":{"default":[429,404,500,501,502,503,504,505],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"timeouts":{"default":3,"maximum":254,"type":"integer","minimum":1},"interval":{"default":1,"type":"integer","minimum":1},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"concurrency":{"type":"integer","default":10},"http_path":{"type":"string","default":"\/"},"https_verify_certificate":{"type":"boolean","default":true},"timeout":{"type":"number","default":1}}},"passive":{"properties":{"healthy":{"type":"object","properties":{"successes":{"default":5,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":0},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":0},"timeouts":{"default":7,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[429,500,503],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}}},"type":"object","default":{"healthy":{"successes":0,"http_statuses":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308]},"type":"http","unhealthy":{"http_failures":0,"tcp_failures":0,"timeouts":0,"http_statuses":[429,500,503]}}}},"type":"object"},"service_name":{"minLength":1,"type":"string","maxLength":256},"desc":{"type":"string","maxLength":256},"key":{"description":"the key of chash for dynamic load balancing","type":"string"},"upstream_host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"pass_host":{"description":"mod of host passing","default":"pass","type":"string","enum":["pass","node","rewrite"]},"timeout":{"properties":{"connect":{"type":"number","exclusiveMinimum":0},"send":{"type":"number","exclusiveMinimum":0},"read":{"type":"number","exclusiveMinimum":0}},"type":"object","required":["connect","send","read"]},"hash_on":{"default":"vars","type":"string","enum":["vars","header","cookie","consumer","vars_combinations"]},"nodes":{"anyOf":[{"type":"object","patternProperties":{".*":{"description":"weight of node","type":"integer","minimum":0}}},{"type":"array","items":{"properties":{"weight":{"description":"weight of node","type":"integer","minimum":0},"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"priority":{"description":"priority of node","type":"integer","default":0},"metadata":{"description":"metadata of node","type":"object"},"port":{"description":"port of node","type":"integer","minimum":1}},"type":"object","required":["host","port","weight"]}}]},"scheme":{"description":"The scheme of the upstream. For L7 proxy, it can be one of grpc\/grpcs\/http\/https. For L4 proxy, it can be one of tcp\/tls\/udp.","default":"http","enum":["grpc","grpcs","http","https","tcp","tls","udp"]},"tls":{"properties":{"client_cert":{"minLength":128,"type":"string","maxLength":65536},"client_key":{"minLength":128,"type":"string","maxLength":65536}},"type":"object","required":["client_cert","client_key"]},"create_time":{"type":"integer"}},"type":"object","oneOf":[{"required":["type","nodes"]},{"required":["type","service_name","discovery_type"]}]},"upstream_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"create_time":{"type":"integer"}}},"upstream_hash_header_schema":{"type":"string","pattern":"^[a-zA-Z0-9-_]+$"},"plugin_config":{"properties":{"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"update_time":{"type":"integer"},"plugins":{"type":"object"},"create_time":{"type":"integer"},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"desc":{"type":"string","maxLength":256}},"type":"object","required":["id","plugins"]},"ssl":{"properties":{"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"validity_end":{"type":"integer"},"status":{"description":"ssl status, 1 to enable, 0 to disable","default":1,"type":"integer","enum":[1,0]},"keys":{"type":"array","items":{"minLength":128,"type":"string","maxLength":65536}},"validity_start":{"type":"integer"},"client":{"properties":{"depth":{"default":1,"type":"integer","minimum":0},"ca":{"minLength":128,"type":"string","maxLength":65536}},"type":"object","required":["ca"]},"cert":{"minLength":128,"type":"string","maxLength":65536},"exptime":{"type":"integer","minimum":1588262400},"update_time":{"type":"integer"},"sni":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"key":{"minLength":128,"type":"string","maxLength":65536},"snis":{"minItems":1,"items":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"type":"array"},"certs":{"type":"array","items":{"minLength":128,"type":"string","maxLength":65536}},"create_time":{"type":"integer"}},"type":"object","oneOf":[{"required":["sni","key","cert"]},{"required":["snis","key","cert"]}]},"consumer":{"properties":{"update_time":{"type":"integer"},"username":{"pattern":"^[a-zA-Z0-9_]+$","minLength":1,"type":"string","maxLength":100},"plugins":{"type":"object"},"desc":{"type":"string","maxLength":256},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"create_time":{"type":"integer"}},"type":"object","required":["username"]}},"stream_plugins":{"ip-restriction":{"version":0.1,"priority":3000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"whitelist":{"minItems":1,"items":{"anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"type":"array"},"blacklist":{"minItems":1,"items":{"anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"type":"array"},"message":{"default":"Your IP address is not allowed","minLength":1,"type":"string","maxLength":1024},"disable":{"type":"boolean"}},"type":"object","oneOf":[{"required":["whitelist"]},{"required":["blacklist"]}]}},"limit-conn":{"version":0.1,"priority":1003,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"key_type":{"default":"var","type":"string","enum":["var","var_combination"]},"disable":{"type":"boolean"},"burst":{"type":"integer","minimum":0},"default_conn_delay":{"type":"number","exclusiveMinimum":0},"only_use_default_delay":{"type":"boolean","default":false},"conn":{"type":"integer","exclusiveMinimum":0},"key":{"type":"string"}},"type":"object","required":["conn","burst","default_conn_delay","key"]}},"mqtt-proxy":{"version":0.1,"priority":1000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"protocol_level":{"type":"integer"},"upstream":{"description":"Deprecated. We should configure upstream outside of the plugin","properties":{"ip":{"type":"string"},"host":{"type":"string"},"port":{"type":"number"}},"type":"object","oneOf":[{"required":["host","port"]},{"required":["ip","port"]}]},"disable":{"type":"boolean"},"protocol_name":{"type":"string"}},"type":"object","required":["protocol_name","protocol_level"]}}},"plugins":{"api-breaker":{"version":0.1,"priority":1005,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"healthy":{"properties":{"successes":{"default":3,"type":"integer","minimum":1},"http_statuses":{"default":[200],"minItems":1,"items":{"maximum":499,"type":"integer","minimum":200},"type":"array","uniqueItems":true}},"type":"object","default":{"successes":3,"http_statuses":[200]}},"disable":{"type":"boolean"},"break_response_code":{"maximum":599,"type":"integer","minimum":200},"max_breaker_sec":{"default":300,"type":"integer","minimum":3},"unhealthy":{"properties":{"failures":{"default":3,"type":"integer","minimum":1},"http_statuses":{"default":[500],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":500},"type":"array","uniqueItems":true}},"type":"object","default":{"failures":3,"http_statuses":[500]}}},"type":"object","required":["break_response_code"]}},"http-logger":{"version":0.1,"priority":410,"metadata_schema":{"type":"object","properties":{"log_format":{"type":"object","default":{"client_ip":"$remote_addr","host":"$host","@timestamp":"$time_iso8601"}}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"include_resp_body":{"type":"boolean","default":false},"include_resp_body_expr":{"minItems":1,"items":{"type":"array"},"type":"array"},"concat_method":{"default":"json","type":"string","enum":["json","new_line"]},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"disable":{"type":"boolean"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"uri":{"type":"string","pattern":"^[^\\\/]+:\\\/\\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?"},"include_req_body":{"type":"boolean","default":false},"name":{"type":"string","default":"http logger"},"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"ssl_verify":{"type":"boolean","default":false},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"auth_header":{"type":"string","default":""},"timeout":{"default":3,"type":"integer","minimum":1}},"type":"object","required":["uri"]}},"tcp-logger":{"version":0.1,"priority":405,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"tls":{"type":"boolean","default":false},"host":{"type":"string"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"tls_options":{"type":"string"},"port":{"type":"integer","minimum":0},"disable":{"type":"boolean"},"name":{"type":"string","default":"tcp logger"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"timeout":{"default":1000,"type":"integer","minimum":1},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"include_req_body":{"type":"boolean","default":false}},"type":"object","required":["host","port"]}},"kafka-logger":{"version":0.1,"priority":403,"metadata_schema":{"type":"object","properties":{"log_format":{"type":"object","default":{"client_ip":"$remote_addr","host":"$host","@timestamp":"$time_iso8601"}}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"include_resp_body":{"type":"boolean","default":false},"include_resp_body_expr":{"minItems":1,"items":{"type":"array"},"type":"array"},"disable":{"type":"boolean"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"meta_format":{"default":"default","type":"string","enum":["default","origin"]},"name":{"type":"string","default":"kafka logger"},"kafka_topic":{"type":"string"},"producer_type":{"default":"async","type":"string","enum":["async","sync"]},"required_acks":{"default":1,"type":"integer","enum":[0,1,-1]},"cluster_name":{"default":1,"type":"integer","minimum":1},"key":{"type":"string"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"include_req_body_expr":{"minItems":1,"items":{"type":"array"},"type":"array"},"broker_list":{"patternProperties":{".*":{"description":"the port of kafka broker","maximum":65535,"type":"integer","minimum":1}},"type":"object","minProperties":1},"include_req_body":{"type":"boolean","default":false},"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"timeout":{"default":3,"type":"integer","minimum":1}},"type":"object","required":["broker_list","kafka_topic"]}},"grpc-transcode":{"version":0.1,"priority":506,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"method":{"description":"the method name in the grpc service.","type":"string"},"disable":{"type":"boolean"},"service":{"description":"the grpc service name","type":"string"},"pb_option":{"minItems":1,"items":{"type":"string","anyOf":[{"description":"enum as result","type":"string","enum":["int64_as_number","int64_as_string","int64_as_hexstring"]},{"description":"int64 as result","type":"string","enum":["enum_as_name","enum_as_value"]},{"description":"default values option","type":"string","enum":["auto_default_values","no_default_values","use_default_values","use_default_metatable"]},{"description":"hooks option","type":"string","enum":["enable_hooks","disable_hooks"]}]},"type":"array"},"proto_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"deadline":{"description":"deadline for grpc, millisecond","type":"number","default":0}},"required":["proto_id","service","method"],"additionalProperties":true,"type":"object"}},"limit-req":{"version":0.1,"priority":1001,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"rejected_code":{"default":503,"maximum":599,"type":"integer","minimum":200},"rejected_msg":{"type":"string","minLength":1},"nodelay":{"type":"boolean","default":false},"allow_degradation":{"type":"boolean","default":false},"key":{"type":"string"},"disable":{"type":"boolean"},"rate":{"type":"number","exclusiveMinimum":0},"burst":{"type":"number","minimum":0},"key_type":{"default":"var","type":"string","enum":["var","var_combination"]}},"type":"object","required":["rate","burst","key"]}},"limit-conn":{"version":0.1,"priority":1003,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"rejected_code":{"default":503,"maximum":599,"type":"integer","minimum":200},"rejected_msg":{"type":"string","minLength":1},"default_conn_delay":{"type":"number","exclusiveMinimum":0},"only_use_default_delay":{"type":"boolean","default":false},"key":{"type":"string"},"disable":{"type":"boolean"},"allow_degradation":{"type":"boolean","default":false},"conn":{"type":"integer","exclusiveMinimum":0},"burst":{"type":"integer","minimum":0},"key_type":{"default":"var","type":"string","enum":["var","var_combination"]}},"type":"object","required":["conn","burst","default_conn_delay","key"]}},"authz-keycloak":{"version":0.1,"priority":2000,"schema":{"allOf":[{"anyOf":[{"required":["discovery"]},{"required":["token_endpoint"]}]},{"anyOf":[{"required":["client_id"]},{"required":["audience"]}]},{"anyOf":[{"properties":{"lazy_load_paths":{"enum":[false]}}},{"anyOf":[{"required":["discovery"]},{"required":["resource_registration_endpoint"]}],"properties":{"lazy_load_paths":{"enum":[true]}}}]}],"properties":{"disable":{"type":"boolean"},"keepalive_pool":{"default":5,"type":"integer","minimum":1},"token_endpoint":{"minLength":1,"type":"string","maxLength":4096},"resource_registration_endpoint":{"minLength":1,"type":"string","maxLength":4096},"audience":{"description":"Deprecated, use `client_id` instead.","minLength":1,"type":"string","maxLength":100},"keepalive":{"type":"boolean","default":true},"client_secret":{"minLength":1,"type":"string","maxLength":100},"grant_type":{"minLength":1,"default":"urn:ietf:params:oauth:grant-type:uma-ticket","maxLength":100,"type":"string","enum":["urn:ietf:params:oauth:grant-type:uma-ticket"]},"ssl_verify":{"type":"boolean","default":true},"policy_enforcement_mode":{"default":"ENFORCING","type":"string","enum":["ENFORCING","PERMISSIVE"]},"lazy_load_paths":{"type":"boolean","default":false},"http_method_as_scope":{"type":"boolean","default":false},"cache_ttl_seconds":{"default":86400,"type":"integer","minimum":1},"access_denied_redirect_uri":{"minLength":1,"type":"string","maxLength":2048},"client_id":{"minLength":1,"type":"string","maxLength":100},"access_token_expires_leeway":{"default":0,"type":"integer","minimum":0},"discovery":{"minLength":1,"type":"string","maxLength":4096},"refresh_token_expires_leeway":{"default":0,"type":"integer","minimum":0},"refresh_token_expires_in":{"default":3600,"type":"integer","minimum":1},"access_token_expires_in":{"default":300,"type":"integer","minimum":1},"keepalive_timeout":{"default":60000,"type":"integer","minimum":1000},"permissions":{"uniqueItems":true,"items":{"minLength":1,"type":"string","maxLength":100},"type":"array","default":{}},"timeout":{"default":3000,"type":"integer","minimum":1000}},"type":"object","$comment":"this is a mark for our injected plugin schema"}},"udp-logger":{"version":0.1,"priority":400,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"host":{"type":"string"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"port":{"type":"integer","minimum":0},"disable":{"type":"boolean"},"name":{"type":"string","default":"udp logger"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"include_req_body":{"type":"boolean","default":false},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"timeout":{"default":3,"type":"integer","minimum":1}},"type":"object","required":["host","port"]}},"key-auth":{"consumer_schema":{"properties":{"key":{"type":"string"}},"type":"object","required":["key"]},"version":0.1,"priority":2500,"type":"auth","schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"header":{"type":"string","default":"apikey"},"disable":{"type":"boolean"},"query":{"type":"string","default":"apikey"}},"type":"object"}},"hmac-auth":{"consumer_schema":{"title":"work with consumer object","properties":{"keep_headers":{"title":"whether to keep the http request header","type":"boolean","default":false},"encode_uri_params":{"title":"Whether to escape the uri parameter","type":"boolean","default":true},"validate_request_body":{"title":"A boolean value telling the plugin to enable body validation","type":"boolean","default":false},"max_req_body":{"title":"Max request body size","type":"integer","default":524288},"access_key":{"minLength":1,"type":"string","maxLength":256},"secret_key":{"minLength":1,"type":"string","maxLength":256},"algorithm":{"default":"hmac-sha256","type":"string","enum":["hmac-sha1","hmac-sha256","hmac-sha512"]},"clock_skew":{"type":"integer","default":0},"signed_headers":{"type":"array","items":{"minLength":1,"type":"string","maxLength":50}}},"type":"object","required":["access_key","secret_key"]},"version":0.1,"priority":2530,"type":"auth","schema":{"title":"work with route or service object","properties":{"disable":{"type":"boolean"}},"type":"object","$comment":"this is a mark for our injected plugin schema"}},"gzip":{"version":0.1,"priority":995,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"min_length":{"default":20,"type":"integer","minimum":1},"types":{"anyOf":[{"minItems":1,"items":{"type":"string","minLength":1},"type":"array"},{"enum":["*"]}],"default":["text\/html"]},"vary":{"type":"boolean"},"buffers":{"properties":{"size":{"default":4096,"type":"integer","minimum":1},"number":{"default":32,"type":"integer","minimum":1}},"type":"object","default":{"size":4096,"number":32}},"disable":{"type":"boolean"},"comp_level":{"default":1,"maximum":9,"type":"integer","minimum":1},"http_version":{"default":1.1,"enum":[1.1,1]}},"type":"object"}},"pj-auth":{"version":0.1,"priority":1999,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"address":{"type":"string","default":"portal-server.paas-portal.svc.cluster.local:8080"}},"type":"object"}},"grpc-web":{"version":0.1,"priority":505,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"}},"type":"object"}},"basic-auth":{"consumer_schema":{"title":"work with consumer object","properties":{"username":{"type":"string"},"password":{"type":"string"}},"type":"object","required":["username","password"]},"version":0.1,"priority":2520,"type":"auth","schema":{"title":"work with route or service object","properties":{"hide_credentials":{"type":"boolean","default":false},"disable":{"type":"boolean"}},"type":"object","$comment":"this is a mark for our injected plugin schema"}},"authz-casbin":{"version":0.1,"priority":2560,"metadata_schema":{"properties":{"model":{"type":"string"},"policy":{"type":"string"}},"type":"object","required":["model","policy"]},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"model":{"type":"string"},"policy":{"type":"string"},"username":{"type":"string"},"disable":{"type":"boolean"},"model_path":{"type":"string"},"policy_path":{"type":"string"}},"type":"object","oneOf":[{"required":["model_path","policy_path","username"]},{"required":["model","policy","username"]}]}},"zipkin":{"version":0.1,"priority":12011,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"endpoint":{"type":"string"},"server_addr":{"description":"default is $server_addr, you can specify your external ip address","type":"string","pattern":"^[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$"},"disable":{"type":"boolean"},"service_name":{"description":"service name for zipkin reporter","type":"string","default":"APISIX"},"span_version":{"default":2,"enum":[1,2]},"sample_ratio":{"maximum":1,"type":"number","minimum":1e-05}},"type":"object","required":["endpoint","sample_ratio"]}},"clickhouse-logger":{"version":0.1,"priority":398,"metadata_schema":{"type":"object","properties":{"log_format":{"type":"object","default":{"client_ip":"$remote_addr","host":"$host","@timestamp":"$time_iso8601"}}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"endpoint_addr":{"type":"string","pattern":"^[^\\\/]+:\\\/\\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"disable":{"type":"boolean"},"user":{"type":"string","default":""},"database":{"type":"string","default":""},"logtable":{"type":"string","default":""},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"name":{"type":"string","default":"clickhouse-logger"},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"ssl_verify":{"type":"boolean","default":true},"password":{"type":"string","default":""},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"timeout":{"default":3,"type":"integer","minimum":1}},"type":"object","required":["endpoint_addr","user","password","database","logtable"]}},"referer-restriction":{"version":0.1,"priority":2990,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"bypass_missing":{"type":"boolean","default":false},"disable":{"type":"boolean"},"whitelist":{"minItems":1,"items":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"type":"array"},"blacklist":{"minItems":1,"items":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"type":"array"},"message":{"default":"Your referer host is not allowed","minLength":1,"type":"string","maxLength":1024}},"type":"object","oneOf":[{"required":["whitelist"]},{"required":["blacklist"]}]}},"proxy-rewrite":{"version":0.1,"priority":1008,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"uri":{"description":"new uri for upstream","minLength":1,"maxLength":4096,"type":"string","pattern":"^\\\/.*"},"method":{"description":"proxy route method","type":"string","enum":["HEAD","POST","PUT","DELETE","MKCOL","COPY","MOVE","OPTIONS","PROPFIND","LOCK","UNLOCK","PATCH","TRACE","GET"]},"regex_uri":{"description":"new uri that substitute from client uri for upstream, lower priority than uri property","maxItems":2,"minItems":2,"items":{"description":"regex uri","type":"string"},"type":"array"},"headers":{"description":"new headers for request","type":"object","minProperties":1},"scheme":{"description":"new scheme for upstream","type":"string","enum":["http","https"]},"disable":{"type":"boolean"},"host":{"description":"new host for upstream","type":"string","pattern":"^[0-9a-zA-Z-.]+(:\\d{1,5})?$"}},"type":"object","minProperties":1}},"limit-count":{"version":0.4,"priority":1002,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"count":{"type":"integer","exclusiveMinimum":0},"rejected_msg":{"type":"string","minLength":1},"allow_degradation":{"type":"boolean","default":false},"key":{"type":"string","default":"remote_addr"},"policy":{"default":"local","type":"string","enum":["local","redis","redis-cluster"]},"disable":{"type":"boolean"},"time_window":{"type":"integer","exclusiveMinimum":0},"show_limit_quota_header":{"type":"boolean","default":true},"rejected_code":{"default":503,"maximum":599,"type":"integer","minimum":200},"group":{"type":"string"},"key_type":{"default":"var","type":"string","enum":["var","var_combination","constant"]}},"if":{"properties":{"policy":{"enum":["redis"]}}},"required":["count","time_window"],"else":{"if":{"properties":{"policy":{"enum":["redis-cluster"]}}},"then":{"required":["redis_cluster_nodes","redis_cluster_name"],"properties":{"redis_cluster_nodes":{"minItems":2,"items":{"minLength":2,"type":"string","maxLength":100},"type":"array"},"redis_password":{"type":"string","minLength":0},"redis_cluster_name":{"type":"string"},"redis_timeout":{"default":1000,"type":"integer","minimum":1}}}},"type":"object","then":{"required":["redis_host"],"properties":{"redis_host":{"type":"string","minLength":2},"redis_port":{"default":6379,"type":"integer","minimum":1},"redis_password":{"type":"string","minLength":0},"redis_database":{"default":0,"type":"integer","minimum":0},"redis_timeout":{"default":1000,"type":"integer","minimum":1}}}}},"node-status":{"version":0.1,"priority":1000,"scope":"global","schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"}},"type":"object"}},"cors":{"version":0.1,"priority":4000,"metadata_schema":{"type":"object","properties":{"allow_origins":{"type":"object","additionalProperties":{"type":"string","pattern":"^(\\*|\\*\\*|null|\\w+:\/\/[^,]+(,\\w+:\/\/[^,]+)*)$"}}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"allow_credential":{"description":"allow client append credential. according to CORS specification,if you set this option to 'true', you can not use '*' for other options.","type":"boolean","default":false},"max_age":{"description":"maximum number of seconds the results can be cached.-1 means no cached, the max value is depend on browser,more details plz check MDN. default: 5.","type":"integer","default":5},"allow_methods":{"description":"you can use '*' to allow all methods when no credentials,'**' to allow forcefully(it will bring some security risks, be carefully),multiple method use ',' to split. default: *.","type":"string","default":"*"},"allow_origins_by_regex":{"description":"you can use regex to allow specific origins when no credentials,for example use [.*\\.test.com] to allow a.test.com and b.test.com","minItems":1,"items":{"minLength":1,"type":"string","maxLength":4096},"type":"array","uniqueItems":true},"allow_origins":{"description":"you can use '*' to allow all origins when no credentials,'**' to allow forcefully(it will bring some security risks, be carefully),multiple origin use ',' to split. default: *.","default":"*","type":"string","pattern":"^(\\*|\\*\\*|null|\\w+:\/\/[^,]+(,\\w+:\/\/[^,]+)*)$"},"expose_headers":{"description":"you can use '*' to expose all header when no credentials,'**' to allow forcefully(it will bring some security risks, be carefully),multiple header use ',' to split. default: *.","type":"string","default":"*"},"allow_origins_by_metadata":{"description":"set allowed origins by referencing origins in plugin metadata","minItems":1,"items":{"minLength":1,"type":"string","maxLength":4096},"type":"array","uniqueItems":true},"allow_headers":{"description":"you can use '*' to allow all header when no credentials,'**' to allow forcefully(it will bring some security risks, be carefully),multiple header use ',' to split. default: *.","type":"string","default":"*"}},"type":"object"}},"redirect":{"version":0.1,"priority":900,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"ret_code":{"default":302,"type":"integer","minimum":200},"regex_uri":{"description":"params for generating new uri that substitute from client uri, first param is regular expression, the second one is uri template","maxItems":2,"minItems":2,"items":{"description":"regex uri","type":"string"},"type":"array"},"http_to_https":{"type":"boolean"},"encode_uri":{"type":"boolean","default":false},"append_query_string":{"type":"boolean","default":false},"disable":{"type":"boolean"},"uri":{"minLength":2,"type":"string","pattern":"(\\\\\\$[0-9a-zA-Z_]+)|\\$\\{([0-9a-zA-Z_]+)\\}|\\$([0-9a-zA-Z_]+)|(\\$|[^$\\\\]+)"}},"type":"object","oneOf":[{"required":["uri"]},{"required":["regex_uri"]},{"required":["http_to_https"]}]}},"ext-plugin-pre-req":{"version":0.1,"priority":12000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"allow_degradation":{"type":"boolean","default":false},"conf":{"minItems":1,"items":{"properties":{"name":{"minLength":1,"type":"string","maxLength":128},"value":{"type":"string"}},"type":"object","required":["name","value"]},"type":"array"},"disable":{"type":"boolean"}},"type":"object"}},"proxy-mirror":{"version":0.1,"priority":1010,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"sample_ratio":{"default":1,"maximum":1,"type":"number","minimum":1e-05},"host":{"type":"string","pattern":"^http(s)?:\\\/\\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?$"},"path":{"type":"string","pattern":"^\/[^?&]+$"}},"type":"object","required":["host"]}},"sls-logger":{"version":0.1,"priority":406,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"host":{"type":"string"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"disable":{"type":"boolean"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"project":{"type":"string"},"logstore":{"type":"string"},"access_key_id":{"type":"string"},"access_key_secret":{"type":"string"},"name":{"type":"string","default":"sls-logger"},"timeout":{"default":5000,"type":"integer","minimum":1},"port":{"type":"integer"},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"include_req_body":{"type":"boolean","default":false}},"type":"object","required":["host","port","project","logstore","access_key_id","access_key_secret"]}},"aws-lambda":{"version":0.1,"priority":-1899,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"authorization":{"type":"object","properties":{"iam":{"properties":{"service":{"description":"the service that is receiving the request","type":"string","default":"execute-api"},"accesskey":{"type":"string","description":"access key id from from aws iam console"},"aws_region":{"description":"the aws region that is receiving the request","type":"string","default":"us-east-1"},"secretkey":{"type":"string","description":"secret access key from from aws iam console"}},"type":"object","required":["accesskey","secretkey"]},"apikey":{"type":"string"}}},"keepalive":{"type":"boolean","default":true},"keepalive_timeout":{"default":60000,"type":"integer","minimum":1000},"disable":{"type":"boolean"},"ssl_verify":{"type":"boolean","default":true},"keepalive_pool":{"default":5,"type":"integer","minimum":1},"function_uri":{"type":"string"},"timeout":{"default":3000,"type":"integer","minimum":100}},"type":"object","required":["function_uri"]}},"log-rotate":{"version":0.1,"priority":100,"scope":"global","schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"}},"type":"object"}},"ext-plugin-post-req":{"version":0.1,"priority":-3000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"allow_degradation":{"type":"boolean","default":false},"conf":{"minItems":1,"items":{"properties":{"name":{"minLength":1,"type":"string","maxLength":128},"value":{"type":"string"}},"type":"object","required":["name","value"]},"type":"array"},"disable":{"type":"boolean"}},"type":"object"}},"real-ip":{"version":0.1,"priority":23000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"source":{"type":"string","minLength":1},"trusted_addresses":{"minItems":1,"items":{"anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"type":"array"},"disable":{"type":"boolean"}},"type":"object","required":["source"]}},"splunk-hec-logging":{"version":0.1,"priority":409,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"endpoint":{"properties":{"uri":{"type":"string","pattern":"^[^\\\/]+:\\\/\\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?"},"timeout":{"default":10,"type":"integer","minimum":1},"token":{"type":"string"},"channel":{"type":"string"}},"type":"object","required":["uri","token"]},"disable":{"type":"boolean"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"name":{"type":"string","default":"splunk-hec-logging"},"ssl_verify":{"type":"boolean","default":true},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"}},"type":"object","required":["endpoint"]}},"response-rewrite":{"version":0.1,"priority":899,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"body":{"description":"new body for response","type":"string"},"body_base64":{"description":"whether new body for response need base64 decode before return","type":"boolean","default":false},"disable":{"type":"boolean"},"headers":{"description":"new headers for response","type":"object","minProperties":1},"status_code":{"description":"new status code for response","maximum":598,"type":"integer","minimum":200},"vars":{"type":"array"}},"type":"object","minProperties":1}},"traffic-split":{"version":0.1,"priority":966,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"rules":{"type":"array","items":{"type":"object","properties":{"weighted_upstreams":{"maxItems":20,"default":[{"weight":1}],"minItems":1,"items":{"type":"object","properties":{"weight":{"description":"used to split traffic between differentupstreams for plugin configuration","minimum":0,"type":"integer","default":1},"upstream_id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"upstream":{"properties":{"retries":{"type":"integer","minimum":0},"retry_timeout":{"type":"number","minimum":0},"keepalive_pool":{"type":"object","properties":{"idle_timeout":{"minimum":0,"type":"number","default":60},"requests":{"minimum":1,"type":"integer","default":1000},"size":{"minimum":1,"type":"integer","default":320}}},"type":{"description":"algorithms of load balancing","type":"string"},"update_time":{"type":"integer"},"name":{"minLength":1,"type":"string","maxLength":100},"labels":{"description":"key\/value pairs to specify attributes","type":"object","patternProperties":{".*":{"description":"value of label","minLength":1,"maxLength":64,"type":"string","pattern":"^\\S+$"}}},"discovery_type":{"description":"discovery type","type":"string"},"id":{"anyOf":[{"pattern":"^[a-zA-Z0-9-_.]+$","minLength":1,"type":"string","maxLength":64},{"type":"integer","minimum":1}]},"discovery_args":{"type":"object","properties":{"namespace_id":{"description":"namespace id","type":"string"},"group_name":{"description":"group name","type":"string"}}},"checks":{"anyOf":[{"required":["active"]},{"required":["active","passive"]}],"properties":{"active":{"type":"object","properties":{"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"req_headers":{"minItems":1,"items":{"type":"string","uniqueItems":true},"type":"array"},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"port":{"maximum":65535,"type":"integer","minimum":1},"healthy":{"type":"object","properties":{"interval":{"default":1,"type":"integer","minimum":1},"http_statuses":{"default":[200,302],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"successes":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":1},"http_statuses":{"default":[429,404,500,501,502,503,504,505],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"timeouts":{"default":3,"maximum":254,"type":"integer","minimum":1},"interval":{"default":1,"type":"integer","minimum":1},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":1}}},"concurrency":{"type":"integer","default":10},"http_path":{"type":"string","default":"\/"},"https_verify_certificate":{"type":"boolean","default":true},"timeout":{"type":"number","default":1}}},"passive":{"properties":{"healthy":{"type":"object","properties":{"successes":{"default":5,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}},"type":{"default":"http","type":"string","enum":["http","https","tcp"]},"unhealthy":{"type":"object","properties":{"http_failures":{"default":5,"maximum":254,"type":"integer","minimum":0},"tcp_failures":{"default":2,"maximum":254,"type":"integer","minimum":0},"timeouts":{"default":7,"maximum":254,"type":"integer","minimum":0},"http_statuses":{"default":[429,500,503],"minItems":1,"items":{"maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true}}}},"type":"object","default":{"healthy":{"successes":0,"http_statuses":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308]},"type":"http","unhealthy":{"http_failures":0,"tcp_failures":0,"timeouts":0,"http_statuses":[429,500,503]}}}},"type":"object"},"service_name":{"minLength":1,"type":"string","maxLength":256},"desc":{"type":"string","maxLength":256},"key":{"description":"the key of chash for dynamic load balancing","type":"string"},"upstream_host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"pass_host":{"description":"mod of host passing","default":"pass","type":"string","enum":["pass","node","rewrite"]},"timeout":{"properties":{"connect":{"type":"number","exclusiveMinimum":0},"send":{"type":"number","exclusiveMinimum":0},"read":{"type":"number","exclusiveMinimum":0}},"type":"object","required":["connect","send","read"]},"hash_on":{"default":"vars","type":"string","enum":["vars","header","cookie","consumer","vars_combinations"]},"nodes":{"anyOf":[{"type":"object","patternProperties":{".*":{"description":"weight of node","type":"integer","minimum":0}}},{"type":"array","items":{"properties":{"weight":{"description":"weight of node","type":"integer","minimum":0},"host":{"type":"string","pattern":"^\\*?[0-9a-zA-Z-._]+$"},"priority":{"description":"priority of node","type":"integer","default":0},"metadata":{"description":"metadata of node","type":"object"},"port":{"description":"port of node","type":"integer","minimum":1}},"type":"object","required":["host","port","weight"]}}]},"scheme":{"description":"The scheme of the upstream. For L7 proxy, it can be one of grpc\/grpcs\/http\/https. For L4 proxy, it can be one of tcp\/tls\/udp.","default":"http","enum":["grpc","grpcs","http","https","tcp","tls","udp"]},"tls":{"properties":{"client_cert":{"minLength":128,"type":"string","maxLength":65536},"client_key":{"minLength":128,"type":"string","maxLength":65536}},"type":"object","required":["client_cert","client_key"]},"create_time":{"type":"integer"}},"type":"object","oneOf":[{"required":["type","nodes"]},{"required":["type","service_name","discovery_type"]}]}}},"type":"array"},"match":{"type":"array","items":{"type":"object","properties":{"vars":{"type":"array"}}}}}}}},"type":"object"}},"prometheus":{"version":0.2,"priority":500,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"prefer_name":{"type":"boolean","default":false}},"type":"object"}},"skywalking-logger":{"version":0.1,"priority":408,"metadata_schema":{"type":"object","properties":{"log_format":{"type":"object","default":{"client_ip":"$remote_addr","host":"$host","@timestamp":"$time_iso8601"}}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"service_name":{"type":"string","default":"APISIX"},"endpoint_addr":{"type":"string","pattern":"^[^\\\/]+:\\\/\\\/([\\da-zA-Z.-]+|\\[[\\da-fA-F:]+\\])(:\\d+)?"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"disable":{"type":"boolean"},"service_instance_name":{"type":"string","default":"APISIX Instance Name"},"name":{"type":"string","default":"skywalking logger"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"timeout":{"default":3,"type":"integer","minimum":1},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"include_req_body":{"type":"boolean","default":false}},"type":"object","required":["endpoint_addr"]}},"ldap-auth":{"consumer_schema":{"title":"work with consumer object","properties":{"user_dn":{"type":"string"}},"type":"object","required":["user_dn"]},"version":0.1,"priority":2540,"type":"auth","schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"uid":{"type":"string"},"disable":{"type":"boolean"},"base_dn":{"type":"string"},"ldap_uri":{"type":"string"},"use_tls":{"type":"boolean"}},"required":["base_dn","ldap_uri"],"title":"work with route or service object","type":"object"}},"jwt-auth":{"consumer_schema":{"dependencies":{"algorithm":{"oneOf":[{"properties":{"algorithm":{"default":"HS256","enum":["HS256","HS512"]}}},{"required":["public_key","private_key"],"properties":{"public_key":{"type":"string"},"private_key":{"type":"string"},"algorithm":{"enum":["RS256"]}}},{"required":["vault"],"properties":{"vault":{"type":"object","properties":{}},"algorithm":{"enum":["RS256"]}}}]}},"properties":{"vault":{"type":"object","properties":{}},"algorithm":{"default":"HS256","type":"string","enum":["HS256","HS512","RS256"]},"secret":{"type":"string"},"exp":{"default":86400,"type":"integer","minimum":1},"base64_secret":{"type":"boolean","default":false},"key":{"type":"string"}},"type":"object","required":["key"]},"version":0.1,"priority":2510,"type":"auth","schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"cookie":{"type":"string","default":"jwt"},"header":{"type":"string","default":"authorization"},"disable":{"type":"boolean"},"query":{"type":"string","default":"jwt"}},"type":"object"}},"public-api":{"version":0.1,"priority":501,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"uri":{"type":"string"},"disable":{"type":"boolean"}},"type":"object"}},"ua-restriction":{"version":0.1,"priority":2999,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"bypass_missing":{"type":"boolean","default":false},"disable":{"type":"boolean"},"allowlist":{"minItems":1,"items":{"type":"string","minLength":1},"type":"array"},"denylist":{"minItems":1,"items":{"type":"string","minLength":1},"type":"array"},"message":{"default":"Not allowed","minLength":1,"type":"string","maxLength":1024}},"type":"object"}},"file-logger":{"version":0.1,"priority":399,"metadata_schema":{"type":"object","properties":{"log_format":{"type":"object","default":{"client_ip":"$remote_addr","host":"$host","@timestamp":"$time_iso8601"}}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"path":{"type":"string"}},"type":"object","required":["path"]}},"server-info":{"scope":"global","priority":990,"version":0.1,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"}},"type":"object"}},"rocketmq-logger":{"version":0.1,"priority":402,"metadata_schema":{"type":"object","properties":{"log_format":{"type":"object","default":{"client_ip":"$remote_addr","host":"$host","@timestamp":"$time_iso8601"}}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"include_resp_body":{"type":"boolean","default":false},"include_resp_body_expr":{"minItems":1,"items":{"type":"array"},"type":"array"},"disable":{"type":"boolean"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"nameserver_list":{"minItems":1,"items":{"type":"string"},"type":"array"},"topic":{"type":"string"},"meta_format":{"default":"default","type":"string","enum":["default","origin"]},"name":{"type":"string","default":"rocketmq logger"},"use_tls":{"type":"boolean","default":false},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"include_req_body_expr":{"minItems":1,"items":{"type":"array"},"type":"array"},"key":{"type":"string"},"access_key":{"type":"string","default":""},"secret_key":{"type":"string","default":""},"tag":{"type":"string"},"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"timeout":{"default":3,"type":"integer","minimum":1},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"include_req_body":{"type":"boolean","default":false}},"type":"object","required":["nameserver_list","topic"]}},"ip-restriction":{"version":0.1,"priority":3000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"whitelist":{"minItems":1,"items":{"anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"type":"array"},"blacklist":{"minItems":1,"items":{"anyOf":[{"title":"IPv4","type":"string","format":"ipv4"},{"title":"IPv4\/CIDR","type":"string","pattern":"^([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([12]?[0-9]|3[0-2])$"},{"title":"IPv6","type":"string","format":"ipv6"},{"title":"IPv6\/CIDR","type":"string","pattern":"^([a-fA-F0-9]{0,4}:){1,8}(:[a-fA-F0-9]{0,4}){0,8}([a-fA-F0-9]{0,4})?\/[0-9]{1,3}$"}]},"type":"array"},"message":{"default":"Your IP address is not allowed","minLength":1,"type":"string","maxLength":1024},"disable":{"type":"boolean"}},"type":"object","oneOf":[{"required":["whitelist"]},{"required":["blacklist"]}]}},"mocking":{"version":0.1,"priority":10900,"schema":{"anyOf":[{"required":["response_example"]},{"required":["response_schema"]}],"properties":{"response_status":{"minimum":100,"type":"integer","default":200},"content_type":{"type":"string","default":"application\/json;charset=utf8"},"response_example":{"type":"string"},"delay":{"type":"integer","default":0},"with_mock_header":{"type":"boolean","default":true},"disable":{"type":"boolean"},"response_schema":{"type":"object"}},"type":"object","$comment":"this is a mark for our injected plugin schema"}},"example-plugin":{"version":0.1,"priority":0,"metadata_schema":{"properties":{"skey":{"type":"string"},"ikey":{"type":"number","minimum":0}},"type":"object","required":["ikey","skey"]},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"s":{"type":"string"},"t":{"type":"array","minItems":1},"disable":{"type":"boolean"},"i":{"type":"number","minimum":0},"ip":{"type":"string"},"port":{"type":"integer"}},"type":"object","required":["i"]}},"proxy-cache":{"version":0.2,"priority":1009,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"cache_control":{"type":"boolean","default":false},"cache_bypass":{"minItems":1,"items":{"type":"string","pattern":"(^[^\\$].+$|^\\$[0-9a-zA-Z_]+$)"},"type":"array"},"no_cache":{"minItems":1,"items":{"type":"string","pattern":"(^[^\\$].+$|^\\$[0-9a-zA-Z_]+$)"},"type":"array"},"cache_zone":{"default":"disk_cache_one","minLength":1,"type":"string","maxLength":100},"cache_strategy":{"default":"disk","type":"string","enum":["disk","memory"]},"cache_ttl":{"default":300,"type":"integer","minimum":1},"cache_http_status":{"default":[200,301,404],"minItems":1,"items":{"description":"http response status","maximum":599,"type":"integer","minimum":200},"type":"array","uniqueItems":true},"disable":{"type":"boolean"},"cache_method":{"default":["GET","HEAD"],"minItems":1,"items":{"description":"supported http method","type":"string","enum":["GET","POST","HEAD"]},"type":"array","uniqueItems":true},"cache_key":{"minItems":1,"items":{"description":"a key for caching","type":"string","pattern":"(^[^\\$].+$|^\\$[0-9a-zA-Z_]+$)"},"type":"array","default":["$host","$request_uri"]},"hide_cache_headers":{"type":"boolean","default":false}},"type":"object"}},"openid-connect":{"version":0.1,"priority":2599,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"introspection_endpoint":{"type":"string"},"introspection_endpoint_auth_method":{"type":"string","default":"client_secret_basic"},"bearer_only":{"type":"boolean","default":false},"realm":{"type":"string","default":"apisix"},"logout_path":{"type":"string","default":"\/logout"},"redirect_uri":{"type":"string","description":"use ngx.var.request_uri if not configured"},"post_logout_redirect_uri":{"type":"string","description":"the URI will be redirect when request logout_path"},"token_signing_alg_values_expected":{"type":"string"},"set_access_token_header":{"description":"Whether the access token should be added as a header to the request for downstream","type":"boolean","default":true},"access_token_in_authorization_header":{"description":"Whether the access token should be added in the Authorization header as opposed to the X-Access-Token header.","type":"boolean","default":false},"set_id_token_header":{"description":"Whether the ID token should be added in the X-ID-Token header to the request for downstream.","type":"boolean","default":true},"client_id":{"type":"string"},"discovery":{"type":"string"},"disable":{"type":"boolean"},"set_userinfo_header":{"description":"Whether the user info token should be added in the X-Userinfo header to the request for downstream.","type":"boolean","default":true},"scope":{"type":"string","default":"openid"},"ssl_verify":{"type":"boolean","default":false},"client_secret":{"type":"string"},"public_key":{"type":"string"},"timeout":{"description":"timeout in seconds","default":3,"type":"integer","minimum":1}},"type":"object","required":["client_id","client_secret","discovery"]}},"request-validation":{"version":0.1,"priority":2800,"type":"validation","schema":{"anyOf":[{"required":["header_schema"]},{"required":["body_schema"]}],"properties":{"header_schema":{"type":"object"},"body_schema":{"type":"object"},"rejected_msg":{"minLength":1,"type":"string","maxLength":256},"disable":{"type":"boolean"},"rejected_code":{"default":400,"maximum":599,"type":"integer","minimum":200}},"type":"object","$comment":"this is a mark for our injected plugin schema"}},"request-id":{"version":0.1,"priority":11010,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"include_in_response":{"type":"boolean","default":true},"disable":{"type":"boolean"},"algorithm":{"default":"uuid","type":"string","enum":["uuid","snowflake"]},"header_name":{"type":"string","default":"X-Request-Id"}},"type":"object"}},"serverless-post-function":{"version":0.1,"priority":-2000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"phase":{"default":"access","type":"string","enum":["rewrite","access","header_filter","body_filter","log","before_proxy"]},"functions":{"minItems":1,"items":{"type":"string"},"type":"array"},"disable":{"type":"boolean"}},"type":"object","required":["functions"]}},"openwhisk":{"version":0.1,"priority":-1901,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"keepalive_timeout":{"default":60000,"type":"integer","minimum":1000},"keepalive_pool":{"default":5,"type":"integer","minimum":1},"disable":{"type":"boolean"},"keepalive":{"type":"boolean","default":true},"api_host":{"type":"string"},"service_token":{"type":"string"},"namespace":{"pattern":"\\A([\\w]|[\\w][\\w@ .-]*[\\[email protected]]+)\\z","type":"string","maxLength":256},"package":{"pattern":"\\A([\\w]|[\\w][\\w@ .-]*[\\[email protected]]+)\\z","type":"string","maxLength":256},"ssl_verify":{"type":"boolean","default":true},"action":{"pattern":"\\A([\\w]|[\\w][\\w@ .-]*[\\[email protected]]+)\\z","type":"string","maxLength":256},"result":{"type":"boolean","default":true},"timeout":{"description":"timeout in milliseconds","default":3000,"minimum":1,"maximum":60000,"type":"integer"}},"type":"object","required":["api_host","service_token","namespace","action"]}},"uri-blocker":{"version":0.1,"priority":2900,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"rejected_code":{"default":403,"type":"integer","minimum":200},"rejected_msg":{"type":"string","minLength":1},"block_rules":{"uniqueItems":true,"items":{"minLength":1,"type":"string","maxLength":4096},"type":"array"},"case_insensitive":{"type":"boolean","default":false},"disable":{"type":"boolean"}},"type":"object","required":["block_rules"]}},"forward-auth":{"version":0.1,"priority":2002,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"upstream_headers":{"description":"authorization response header that will be sent to the upstream","items":{"type":"string"},"type":"array","default":{}},"client_headers":{"description":"authorization response header that will be sent tothe client when authorizing failed","items":{"type":"string"},"type":"array","default":{}},"keepalive_pool":{"default":5,"type":"integer","minimum":1},"uri":{"type":"string"},"keepalive":{"type":"boolean","default":true},"disable":{"type":"boolean"},"ssl_verify":{"type":"boolean","default":true},"keepalive_timeout":{"default":60000,"type":"integer","minimum":1000},"request_headers":{"description":"client request header that will be sent to the authorization service","items":{"type":"string"},"type":"array","default":{}},"timeout":{"description":"timeout in milliseconds","default":3000,"minimum":1,"maximum":60000,"type":"integer"}},"type":"object","required":["uri"]}},"client-control":{"version":0.1,"priority":22000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"max_body_size":{"type":"integer","minimum":0},"disable":{"type":"boolean"}},"type":"object"}},"azure-functions":{"version":0.1,"priority":-1900,"metadata_schema":{"type":"object","properties":{"master_clientid":{"type":"string","default":""},"master_apikey":{"type":"string","default":""}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"authorization":{"type":"object","properties":{"clientid":{"type":"string"},"apikey":{"type":"string"}}},"keepalive":{"type":"boolean","default":true},"keepalive_timeout":{"default":60000,"type":"integer","minimum":1000},"disable":{"type":"boolean"},"ssl_verify":{"type":"boolean","default":true},"keepalive_pool":{"default":5,"type":"integer","minimum":1},"function_uri":{"type":"string"},"timeout":{"default":3000,"type":"integer","minimum":100}},"type":"object","required":["function_uri"]}},"loggly":{"version":0.1,"priority":411,"metadata_schema":{"type":"object","properties":{"host":{"type":"string","default":"logs-01.loggly.com"},"log_format":{"type":"object"},"port":{"type":"integer","default":514},"protocol":{"default":"syslog","type":"string","enum":["syslog","http","https"]},"timeout":{"default":5000,"type":"integer","minimum":1}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"include_resp_body":{"type":"boolean","default":false},"include_resp_body_expr":{"minItems":1,"items":{"type":"array"},"type":"array"},"disable":{"type":"boolean"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"customer_token":{"type":"string"},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"severity":{"description":"base severity log level","default":"INFO","type":"string","enum":["DEBUG","debug","NOTICE","notice","ALERT","alert","CRIT","crit","ERR","err","EMEGR","emegr","WARNING","warning","INFO","info"]},"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"name":{"type":"string","default":"loggly"},"include_req_body":{"type":"boolean","default":false},"ssl_verify":{"type":"boolean","default":true},"tags":{"minItems":1,"items":{"type":"string","pattern":"^(?!tag=)[ -~]*"},"type":"array","default":["apisix"]},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"severity_map":{"description":"upstream response code vs syslog severity mapping","additionalProperties":false,"type":"object","patternProperties":{"^[1-5][0-9]{2}$":{"description":"keys are HTTP status code, values are severity","type":"string","enum":["DEBUG","debug","NOTICE","notice","ALERT","alert","CRIT","crit","ERR","err","EMEGR","emegr","WARNING","warning","INFO","info"]}}}},"type":"object","required":["customer_token"]}},"fault-injection":{"version":0.1,"priority":11000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"abort":{"properties":{"http_status":{"type":"integer","minimum":200},"percentage":{"maximum":100,"type":"integer","minimum":0},"body":{"type":"string","minLength":0},"vars":{"maxItems":20,"type":"array","items":{"type":"array"}}},"type":"object","required":["http_status"]},"disable":{"type":"boolean"},"delay":{"properties":{"percentage":{"maximum":100,"type":"integer","minimum":0},"duration":{"type":"number","minimum":0},"vars":{"maxItems":20,"type":"array","items":{"type":"array"}}},"type":"object","required":["duration"]}},"type":"object","minProperties":1}},"wolf-rbac":{"version":0.1,"priority":2555,"type":"auth","schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"appid":{"type":"string","default":"unset"},"server":{"type":"string","default":"http:\/\/127.0.0.1:12180"},"header_prefix":{"type":"string","default":"X-"}},"type":"object"}},"proxy-control":{"version":0.1,"priority":21990,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"request_buffering":{"type":"boolean","default":true},"disable":{"type":"boolean"}},"type":"object"}},"consumer-restriction":{"version":0.1,"priority":2400,"schema":{"anyOf":[{"required":["blacklist"]},{"required":["whitelist"]},{"required":["allowed_by_methods"]}],"properties":{"rejected_code":{"default":403,"type":"integer","minimum":200},"allowed_by_methods":{"type":"array","items":{"type":"object","properties":{"user":{"type":"string"},"methods":{"minItems":1,"items":{"description":"HTTP method","type":"string","enum":["GET","POST","PUT","DELETE","PATCH","HEAD","OPTIONS","CONNECT","TRACE"]},"type":"array"}}}},"disable":{"type":"boolean"},"whitelist":{"minItems":1,"items":{"type":"string"},"type":"array"},"blacklist":{"minItems":1,"items":{"type":"string"},"type":"array"},"type":{"default":"consumer_name","type":"string","enum":["consumer_name","service_id","route_id"]},"rejected_msg":{"type":"string"}},"type":"object","$comment":"this is a mark for our injected plugin schema"}},"syslog":{"version":0.1,"priority":401,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"sock_type":{"default":"tcp","type":"string","enum":["tcp","udp"]},"disable":{"type":"boolean"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"name":{"type":"string","default":"sys logger"},"tls":{"type":"boolean","default":false},"host":{"type":"string"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"},"timeout":{"default":3,"type":"integer","minimum":1},"flush_limit":{"default":4096,"type":"integer","minimum":1},"port":{"type":"integer"},"retry_interval":{"type":"integer","minimum":0},"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"drop_limit":{"type":"integer","default":1048576},"pool_size":{"default":5,"type":"integer","minimum":5},"max_retry_times":{"type":"integer","minimum":1},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"include_req_body":{"type":"boolean","default":false}},"type":"object","required":["host","port"]}},"datadog":{"version":0.1,"priority":495,"metadata_schema":{"type":"object","properties":{"constant_tags":{"items":{"type":"string"},"type":"array","default":["source:apisix"]},"namespace":{"type":"string","default":"apisix"},"host":{"type":"string","default":"127.0.0.1"},"port":{"default":8125,"type":"integer","minimum":0}}},"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"prefer_name":{"type":"boolean","default":true},"name":{"type":"string","default":"datadog"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"disable":{"type":"boolean"},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"}},"type":"object"}},"echo":{"version":0.1,"priority":412,"schema":{"anyOf":[{"required":["before_body"]},{"required":["body"]},{"required":["after_body"]}],"properties":{"body":{"description":"body to replace upstream response.","type":"string"},"disable":{"type":"boolean"},"headers":{"description":"new headers for response","type":"object","minProperties":1},"before_body":{"description":"body before the filter phase.","type":"string"},"after_body":{"description":"body after the modification of filter phase.","type":"string"}},"$comment":"this is a mark for our injected plugin schema","type":"object","minProperties":1}},"serverless-pre-function":{"version":0.1,"priority":10000,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"phase":{"default":"access","type":"string","enum":["rewrite","access","header_filter","body_filter","log","before_proxy"]},"functions":{"minItems":1,"items":{"type":"string"},"type":"array"},"disable":{"type":"boolean"}},"type":"object","required":["functions"]}},"google-cloud-logging":{"version":0.1,"priority":407,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"batch_max_size":{"minimum":1,"default":1000,"type":"integer"},"disable":{"type":"boolean"},"inactive_timeout":{"minimum":1,"default":5,"type":"integer"},"auth_file":{"type":"string"},"name":{"type":"string","default":"google-cloud-logging"},"auth_config":{"properties":{"private_key":{"type":"string"},"project_id":{"type":"string"},"token_uri":{"type":"string","default":"https:\/\/oauth2.googleapis.com\/token"},"scopes":{"default":["https:\/\/www.googleapis.com\/auth\/logging.read","https:\/\/www.googleapis.com\/auth\/logging.write","https:\/\/www.googleapis.com\/auth\/logging.admin","https:\/\/www.googleapis.com\/auth\/cloud-platform"],"minItems":1,"items":{"description":"Google OAuth2 Authorization Scopes","type":"string"},"type":"array","uniqueItems":true},"entries_uri":{"type":"string","default":"https:\/\/logging.googleapis.com\/v2\/entries:write"}},"type":"object","required":["private_key","project_id","token_uri"]},"resource":{"default":{"type":"global"},"properties":{"type":{"type":"string"},"labels":{"type":"object"}},"type":"object","required":["type"]},"retry_delay":{"minimum":0,"default":1,"type":"integer"},"ssl_verify":{"type":"boolean","default":true},"max_retry_count":{"minimum":0,"default":0,"type":"integer"},"log_id":{"type":"string","default":"apisix.apache.org%2Flogs"},"buffer_duration":{"minimum":1,"default":60,"type":"integer"}},"type":"object","oneOf":[{"required":["auth_config"]},{"required":["auth_file"]}]}},"csrf":{"version":0.1,"priority":2980,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"disable":{"type":"boolean"},"name":{"description":"the csrf token name","type":"string","default":"apisix-csrf-token"},"expires":{"description":"expires time(s) for csrf token","type":"integer","default":7200},"key":{"description":"use to generate csrf token","type":"string"}},"type":"object","required":["key"]}},"opa":{"version":0.1,"priority":2001,"schema":{"$comment":"this is a mark for our injected plugin schema","properties":{"keepalive_timeout":{"default":60000,"type":"integer","minimum":1000},"keepalive_pool":{"default":5,"type":"integer","minimum":1},"disable":{"type":"boolean"},"host":{"type":"string"},"policy":{"type":"string"},"with_service":{"type":"boolean","default":false},"with_route":{"type":"boolean","default":false},"ssl_verify":{"type":"boolean","default":true},"with_consumer":{"type":"boolean","default":false},"keepalive":{"type":"boolean","default":true},"timeout":{"description":"timeout in milliseconds","default":3000,"minimum":1,"maximum":60000,"type":"integer"}},"type":"object","required":["host","policy"]}}}}
kind: ConfigMap
metadata:
labels:
name: apisix-dashboard-schema-cm
namespace: apisix
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: apisix-dashboard
namespace: apisix
spec:
replicas: 1
selector:
matchLabels:
app: apisix-dashboard
template:
metadata:
labels:
app: apisix-dashboard
spec:
containers:
- image: artifactory.dep.devops.cmit.cloud:20101/panji_middleware/apisix-dashboard:2.13
ports:
- name: http
containerPort: 9000
protocol: TCP
imagePullPolicy: Always
name: apisix-dashboard
resources:
limits:
cpu: 1
memory: 2Gi
ephemeral-storage: "2Gi"
requests:
cpu: 0.5
memory: 1Gi
ephemeral-storage: "1Gi"
livenessProbe:
httpGet:
path: /ping
port: http
scheme: HTTP
timeoutSeconds: 1
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /ping
port: http
scheme: HTTP
timeoutSeconds: 1
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
volumeMounts:
- mountPath: /etc/localtime
name: timezone
- mountPath: /usr/local/apisix-dashboard/conf/conf.yaml
name: apisix-conf-path
subPath: path/to/conf.yaml
- mountPath: /usr/local/apisix-dashboard/conf/schema.json
name: apisix-schema
subPath: path/to/schema.json
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 30
serviceAccount: apisix-dashboard-sa
serviceAccountName: apisix-dashboard-sa
volumes:
- configMap:
items:
- key: conf.yaml
path: path/to/conf.yaml
name: apisix-dashboard-cm
name: apisix-conf-path
- configMap:
items:
- key: schema.json
path: path/to/schema.json
name: apisix-dashboard-schema-cm
name: apisix-schema
- hostPath:
path: /etc/localtime
name: timezone
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
---
apiVersion: v1
kind: Service
metadata:
labels:
app: apisix-dashboard
name: apisix-dashboard
namespace: apisix
spec:
ports:
- name: http-dashboard
port: 27114
protocol: TCP
targetPort: 9000
selector:
app: apisix-dashboard
sessionAffinity: None
type: ClusterIP
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
name: apisix-dashboard
namespace: apisix
spec:
replicas: 1
selector:
matchLabels:
app: apisix-dashboard
template:
metadata:
labels:
app: apisix-dashboard
spec:
containers:
- image: artifactory.dep.devops.cmit.cloud:20101/panji_middleware/apisix-dashboard:2.13
ports:
- name: http
containerPort: 9000
protocol: TCP
imagePullPolicy: Always
name: apisix-dashboard
resources:
limits:
cpu: 1
memory: 2Gi
ephemeral-storage: "2Gi"
requests:
cpu: 0.5
memory: 1Gi
ephemeral-storage: "1Gi"
livenessProbe:
httpGet:
path: /ping
port: http
scheme: HTTP
timeoutSeconds: 1
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /ping
port: http
scheme: HTTP
timeoutSeconds: 1
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
volumeMounts:
- mountPath: /etc/localtime
name: timezone
- mountPath: /usr/local/apisix/dashboard/conf/conf.yaml
name: apisix-conf-path
subPath: path/to/conf.yaml
- mountPath: /usr/local/apisix/dashboard/conf/schema.json
name: apisix-schema
subPath: path/to/schema.json
dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 30
serviceAccount: apisix-dashboard-sa
serviceAccountName: apisix-dashboard-sa
volumes:
- configMap:
items:
- key: conf.yaml
path: path/to/conf.yaml
name: apisix-dashboard-cm
name: apisix-conf-path
- configMap:
items:
- key: schema.json
path: path/to/schema.json
name: apisix-dashboard-schema-cm
name: apisix-schema
- hostPath:
path: /etc/localtime
name: timezone
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
---
apiVersion: v1
kind: Service
metadata:
labels:
app: apisix-dashboard
name: apisix-dashboard
namespace: apisix
spec:
ports:
- name: http-dashboard
port: 27114
protocol: TCP
targetPort: 9000
selector:
app: apisix-dashboard
sessionAffinity: None
type: ClusterIP
标签:string,default,object,minimum,干货,API,integer,type,APISIX
From: https://blog.csdn.net/qq_40477248/article/details/143903981