高性能APISIX微服务网关替换K8S传统Ingress-nginx-controller

高性能APISIX微服务网关替换K8S传统Ingress-nginx-controller

Deng YongJie's blog 686 2022-10-02

Apche APISIX网关

功能:

提供完善可观测性,流量日志记录到clickhouse(废弃es)上。
统一ingress和业务系统的流量网关,降低流量损耗。
统一鉴权模型,接入业务系统鉴权逻辑。
流量防护,启动熔断限流等多种防护措施。
流量重放,为后期自动测试提供数据重复供。

验证步骤:

rancher上部署apisix网关,建立demo路由,简单测试路由转发功能
切换rancher上的ingress-nginx,对外暴露80,443端口。dashbaord上创建的路由能正常转发到测试服务上。
部署apisix-ingress-controller,修改rancher的ingress域名,controller自动监听并自动在APISIX创建路由规则。
记录访问日志,存储在clickhouse上。
测试熔断,限流。

需知问题:

helm部署的模板以nodeport暴露服务,修改调整成demoset暴露,还要修改模板加入443端口,否则不会暴露443端口。此外还要加入ssl参数,否则nginx不会监听443
ingress上需要添加注解 kubernetes.io/ingress.class=apisix ,否则流量不会进入apix。特别注意不能提前设置这个注解,否则原有的ingress会失效,且只能通过yaml进行修改。

待解决问题:

兼容appid设置,需要保证一个默认的appid。
兼容trace-id,能够在网关上生产trace-id。
参考文档 https://apisix.apache.org/docs/apisix/getting-started/

建议架构搭配:

单个k8s集群的apisix对应单个独立的etcd集群,不跟k8s集群使用的etcd共用

一、APISIX网关部署

官方文档:https://apisix.apache.org/zh/docs/apisix/installation-guide/

https://apisix.apache.org/zh/docs/apisix/FAQ/

helm地址:https://github.com/apache/apisix-helm-chart/tree/master/charts/apisix

apisix和apisix-dashboard、apisix-ingress-controller 三个服务,如需替换ingress,则要把apisix服务开启hostnetwork模式

注意节点80 443端口不能被占用,默认配置了反亲和,每台节点只存在一个pod

注意事项:dashboard不能部署多个pod。否则登录成功,又跳转出重新登录界面,或者刷新一下,又跳回重新登录

注意,apisix-controller默认监听k8s ingress的apiversion为:networking.io/v1。所以最佳搭配是1.19-1.22以下

image-20221124180644059

下载官方helm包到本地

helm repo add apisix https://charts.apiseven.com
helm repo update

helm search repo apisix
helm pull apisix/apisix --version 0.11.2
wget http://github.com/apache/apisix-helm-chart/releases/download/apisix-0.11.2/apisix-0.11.2.tgz

0. apisix里面有nginx服务,启动的时候默认会监听9100端口,如果集群部署了prometheus监控,node-export会占用了9100端口。所以需要把apisix的9100端口改成其它端口,否则会一直报错起不来

image-20221116113615931

使用官方提供的helm部署,helm包下载到本地,然后需要修改values值

开启的参数解释:https://github.com/apache/apisix-helm-chart/tree/master/charts/apisix

1.etcd需要添加存储类,否则会使用了官方默认的local类,无法自动创建pvc和pv

创建ceph-rbd存储类
kubectl create -n ingress-apisix csi-storeclass.yaml

还需要创建命名空间的服务账户,关联集群角色
kubectl create -n ingress-apisix -f csi-provisioner-psp.yaml
kubectl create -n ingress-apisix -f csi-provisioner-rbac.yaml

vim charts/etcd/templates/statefulset.yaml
image-20221116115341683

2. 把apisix默认监听的9080 9443端口改成80 443

vim templates/configmap.yaml

添加一行443的,变量定义

image-20221116114846067

3. 然后改成80 443端口

vim values.yaml

4. 把Deployment改成Daemonset,注释replica。并打开hostnetwork

vim values.yaml

5. 修改dashboard账户密码和添加nodeport端口

vim charts/apisix-dashboard/values.yaml

6.注释掉apisix-ingress-controller控制器的健康检测,否则会出现nc 9100端口失败的报错

vim charts/apisix-ingress-controller/templates/deployment.yaml

7. dashboard、apisix、controller三个服务,都可以打开serviceMoitor监控端口,方便后续接入监控

8. apisix服务,需要加上server-info的插件,否则dashboard显示不出apisix服务的信息

vim values.yaml

9. 该步骤非常重要!需要在config文件添加ssl,否则无法通过https访问!!!

vim templates/configmap.yaml

vim values.yaml

10. 关闭ingress-controller的hostport,因为hostnetwork是在apisix网关服务暴露的。否则无法启动多个pod,因为配置了节点反亲和性,每台节点只存在一个pod

vim charts/apisix-ingress-controller/templates/deployment.yaml

11. 重点注意!非常重要的步骤,否则rancher创建ingress会一直处于黄色状态(Initializing)

需要修改apisix-ingress-controller的配置文件,把ingress_status_address参数加上worker的ip地址

这个黄色状态就是由于没有修改配置文件参数,没有添加worker节点ip地址。controller控制器的status没有信息更新,所以就长期初始化!

相关错误的案例:https://github.com/rancher/rancher/issues/20267

解决方法:

https://github.com/apache/apisix-ingress-controller/blob/master/conf/config-default.yaml

配置解释:
ingress_publish_service: ""  # the controller will use the Endpoint of this Service to
                             # update the status information of the Ingress resource.
                             # The format is "namespace/svc-name" to solve the situation that
                             # the data plane and the controller are not deployed in the same namespace.
ingress_status_address: []   # when there is no available information on the Service
                             # used for publishing on the data plane,
                             # the static address provided here will be
                             # used to update the status information of Ingress.
                             # When ingress-publish-service is specified at the same time, ingress-status-address is preferred.
                             # For example, no available LB exists in the bare metal environment.

vim charts/apisix-ingress-controller/values.yaml

ingressStatusAddress: [10.7.0.110,10.7.0.111,10.7.0.112,10.7.0.113,10.7.0.114]

https://apisix.apache.org/zh/docs/ingress-controller/deployments/tke/#specify-the-ingress-version

这是对应k8s版本的ingress-apiversion,由于这里是k8s 1.20版本,默认是networking.k8s.io/v1。所以无需更改

vim charts/apisix-ingress-controller/templates/configmap.yaml

这里注意要空两格,默认是没有空格的,这是ingress-controller配置文件引用ingress_status_address的参数,填写worker节点ip的地方。如果格式不对,controller无法正常识别loadbanlancer地址。则会长期处于黄色状态(Initializing)

vim charts/apisix-ingress-controller/values.yaml

然后在rancher创建ingress测试

12. ssl证书需要上传到dashboard里面,rancher里面添加的ingress配置已经没用了。流量先经过apisix,再进行路由转发!

13.路由规则必须使用非https协议,上游pod都是基于http协议通讯,改成https会提示502 Bad Gateway! (除非pod内部做了https例外)

14. 通过yaml文件或rancher创建ingress,apisix-controller会监听api-server事件,等apisix-controller自动把配置更新到apisix。需要在ingress添加一行注释”kubernetes.io/ingress.class: apisix“才能被apisix-controller成功监听。(如果在apisix-dashboard添加域名路由,不通过api-server创建ingress,此时apisix-etcd毁灭性故障,会导致在dashboard添加的路由配置丢失)

下面参数是把etcd、controller关闭,如果已经部署运行状态,就不能改成false,否则会把正在运行的给删掉了

例如:–set ingress-controller.enabled=false

–set etcd.enabled=false

–set discovery.registry.nacos.host[0]={http://nacos.nacos:8848}

如需修改etcd连接地址:–set etcd.host={http:ip:port}

也可以修改nacos的配置文件:

https://apisix.apache.org/zh/docs/apisix/discovery/nacos/

vim values.yaml
discovery:
  nacos:
    host:
      - "http://${username}:${password}@${host1}:${port1}"
    prefix: "/nacos/v1/"
    fetch_interval: 30    # default 30 sec
    weight: 100           # default 100
    timeout:
      connect: 2000       # default 2000 ms
      send: 2000          # default 2000 ms
      read: 5000          # default 5000 ms

执行更新安装命令,如需关闭或不重复安装某个组件,则把上述参数改为false

#注意,需要在helm当前目录执行
helm upgrade --install apisix ./   --set gateway.type=NodePort  --set ingress-controller.enabled=true   --namespace ingress-apisix   --set ingress-controller.config.apisix.serviceNamespace=ingress-apisix

#如果不需要更新dashboard和controller,则把set参数去掉
helm upgrade --install apisix ./   --set gateway.type=NodePort --namespace ingress-apisix 

#进入dashboard,启动服务
cd charts/apisix-dashboard/
helm upgrade --install apisix-dashboard ./ --namespace ingress-apisix


#连接nacos的启动方式
helm upgrade --install apisix ./   --set gateway.type=NodePort --set discovery.registry.nacos.host={http://nacos-headless.nacos.svc.cluster.local:8848}  --namespace ingress-apisix   --set ingress-controller.config.apisix.serviceNamespace=ingress-apisix

二、对接外部etcd,apisix、apisix-dashboard都需要修改yaml文件

上面的步骤改好模板

apisix和dashboard都需要连接etcd,所以都需要开启tls认证并挂载secret和引用ca.pem证书

使用外部etcd,必看的配置文件:

https://github.com/apache/apisix-dashboard/blob/master/api/conf/conf.yaml#L44-L47

https://github.com/apache/apisix-helm-chart/tree/master/charts/apisix

1. 修改apisix的helm模板,关闭helm部署的etcd,配置ca.pem

先提前创建certs,名字需跟下面修改yaml文件时对应。把etcd相关的证书,复制到当前目录

kubectl -n ingress-apisix create secret generic etcd-certs \
--from-file=ca.pem \
--from-file=server-key.pem \
--from-file=server.pem 

vim values.yaml

sni注释掉,否则出现以下报错:

vim template/configmap.yaml

注意,有两个地方需要注释sni,搜索出来注释,因为下面的文件有判断语句

如果verify改成true,可能会出现下面连接etcd证书失败的问题:

把verify改成false关闭,就没有出现连接etcd证书失败的问题了:

apisix连接etcd出现证书问题的案例:

https://github.com/apache/apisix/issues/5155

https://github.com/apache/apisix/issues/5650


详细版联系我

后续需要接入skywalking分布式链路追踪、opentelemetry遥测数据管理工具等,组建完善的APM链路