apisix ingress controller使用指南

1.ingress.class示例

通过ingress.class方式暴露服务

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apisix-dashboard
  annotations:
    kubernetes.io/ingress.class: apisix
spec:
  rules:
  - host: apisix-dashboard.example.com
    http:
      paths:
      - backend:
          serviceName: apisix-dashboard
          servicePort: 80
        path: /*
        pathType: Prefix

首先确定apifix-ingress-controller配置文件中ingress_class的值, 默认为apisix

注意如果要匹配跟下面的所有路径,需要将path配置为/*, 也可以配置pathType: Prefix会创建/ /* 两个路径 其它的用法完全符合ingress的默认配置,annotation可配置参数参考官方文档

2.crd基础示例

2.1.ApisixRoute基本用法

先在集群中部署httpbin服务

kubectl run httpbin --image kennethreitz/httpbin --port 80
kubectl expose pod httpbin --port 80

创建httpbin-route.yaml文件,内容如下:

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - httpbin.example.com
      paths:
      - /*
    backends:
       - serviceName: httpbin
         servicePort: 80

可以使用两种路径类型prefix、exact,默认为exact,如果prefix需要,只需附加一个,例如,/id/匹配前缀为 的所有路径/id/。

测试过程如下:

➜  ~ curl -H "Host: httpbin.example.com" http://internal/headers/ -v
*   Trying internal...
* TCP_NODELAY set
* Connected to internal (internal) port 80 (#0)
> GET / HTTP/1.1
> Host: httpbin.example.com
> User-Agent: curl/7.64.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 9593
< Connection: keep-alive
< Date: Tue, 16 Aug 2022 09:07:36 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Server: APISIX/2.15.0

2.2.ApisixTls基本用法

ApisixTls主要用来维护https证书

需要先创建tls secret

kubectl -n kube-system create secret tls traefik-ui-tls-cert --key=tls.key --cert=tls.crt

创建httpbin-tls.yaml文件,内容如下:

apiVersion: apisix.apache.org/v2
kind: ApisixTls
metadata:
  name: wildcard.example.com-ApisixTls
spec:
  hosts:
  - "*.example.com"
  secret:
    name: wildcard.example.com-tls-secret
    namespace: ingress-apisix

通过该方式创建的ssl证书,对apisix全局服务都有效,apisix会根据请求域名动态选择

2.3.ApisixUpstream基本用法

ApisixUpstream 需要配置成和Kubernetes Service相同的名字,通过添加负载均衡、健康检查、重试、超时参数等使 Kubernetes Service 更加丰富。

如果不使用ApisixUpstream,则loadbalancer的类型为roundrobin

apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  name: httpbin
spec:
  loadbalancer:
    type: ewma
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
spec:
  selector:
    app: httpbin
  ports:
  - name: http
    port: 80
    targetPort: 8080

其中loadbalancer支持如下四种类型

Round robin: 轮询,配置为type: roundrobin

Least loaded: 最小链接,配置为type: least_conn

Peak EWMA: 维护每个副本往返时间的移动平均值,按未完成请求的数量加权,并将流量分配到成本函数最小的副本。配置为type: ewma

chash: 一致性哈希 配置为type: chash

3.ApisixRoute使用进阶

3.1.ApisixRoute配置多个域名和路径

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: rule1
    match:
      hosts:
      - local.example.com
      - local01.example.com
      paths:
      - /*
      - /api
    backends:
       - serviceName: httpbin
         servicePort: 80

3.2.路径/api特殊配制,路径/无特殊配制

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /api*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: proxy-rewrite 
      enable: true
      config: 
        regex_uri: ["^/api(/|$)(.*)", "/$2"]
  - name: default-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000

apisix中会创建两个route,分别是httpserver-route 和 default-route

3.3.ApisixRoute添加插件

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpbin-route
spec:
  http:
    - name: httpbin
      match:
        hosts:
        - local.httpbin.org
        paths:
          - /*
      backends:
      - serviceName: foo
        servicePort: 80
      plugins:
        - name: gzip
          enable: true

3.4.HTTP强跳HTTPS

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: redirect
      enable: true
      config: 
        http_to_https: true

3.5.域名跳转

local.example.com跳转到local01.example.com

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: redirect
      enable: true
      config: 
        uri: "https://local01.example.com$request_uri"

3.6.rewrite路径跳转

3.6.1./api/header 转/header

方法一: 使用redirect插件,页面会发生302跳转

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: redirect
      enable: true
      config: 
        regex_uri: ["^/api(/|$)(.*)", "/$2"] 

方法二: 使用proxy-rewrite 插件,页面不会302跳转

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: proxy-rewrite 
      enable: true
      config: 
        regex_uri: ["^/api(/|$)(.*)", "/$2"] 

3.6.2./header转/api/header

使用proxy-rewrite 插件,页面不会302跳转

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: proxy-rewrite 
      enable: true
      config: 
        uri: /api/$uri

3.7.基于用户名和密码的认证**

basix-auth插件需要与 Consumer 一起使用才能实现该功能。 开启认证的apisixroute会自动匹配用户名

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth
spec:
  authParameter:
    basicAuth:
      value:
        username: admin
        password: admin
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    authentication:
      enable: true 
      type: basicAuth

测试:

curl -i -uadmin:admin https://local.example.com/

3.8.基于apikey的认证

key-auth插件需要与 Consumer 一起使用才能实现该功能。 开启认证的apisixroute会自动匹配key

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth
spec:
  authParameter:
    keyAuth:
      value:
        key: admin
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    authentication:
      enable: true 
      type: keyAuth

测试:

curl -H 'apikey:admin' https://local.example.com/ 

3.9.限制站点的用户名和密码

通过3.6.基于用户名和密码的认证和3.7.基于apikey的说法,有没有办法用户名和密码只针对一个站点生效, 创建两个consumer,分别是admin01和宫秀德,只允许admin可以进行认证。

apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth-admin
spec:
  authParameter:
    basicAuth:
      value:
        username: admin
        password: admin
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  name: httpserver-basicauth-admin01
spec:
  authParameter:
    basicAuth:
      value:
        username: admin01
        password: admin01
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: consumer-restriction
      enable: true
      config:
        whitelist: 
        - ingress_apisix_httpserver_basicauth_admin 
    authentication:
      enable: true 
      type: basicAuth

httpserver-basicauth-admin需要添加ingress-controller添加的默认前缀ingress_apisix,否则会报403,所以全名为ingress_apisix_httpserver_basicauth_admin

测试admin01访问

> curl -i -uadmin01:admin01 https://local.example.com/
HTTP/2 403
date: Tue, 30 Aug 2022 08:00:04 GMT
content-type: text/plain; charset=utf-8
server: APISIX/2.15.0

{"message":"The consumer_name is forbidden."}

测试admin访问

curl -i -uadmin:admin https://local.example.com/
HTTP/2 200
content-type: text/html; charset=utf-8
content-length: 615
date: Tue, 30 Aug 2022 07:55:55 GMT
last-modified: Wed, 25 May 2022 10:01:40 GMT
etag: "628dfe84-267"
accept-ranges: bytes
server: APISIX/2.15.0
.........

3.10.基于IP的白名单配置

ip-restriction插件实现该功能, 只允许10.10.50.207 10.0.0.0/16 访问站点

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: ip-restriction
      enable: true
      config:
        whitelist: 
        - 10.10.50.207
        - 10.0.0.0/16

白名单中地址测试正常打开页面

非白名单地址测试

> curl  https://local.example.com/
{"message":"Your IP address is not allowed"}

3.11.基于IP的黑名单限制

ip-restriction插件实现该功能, 不允许10.10.50.207 访问站点

apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  name: httpserver-route
spec:
  http:
  - name: httpserver-route
    match:
      hosts:
      - local.example.com
      paths:
      - /*
    backends:
    - serviceName: httpbin
      servicePort: 8000
    plugins:
    - name: ip-restriction
      enable: true
      config:
        blacklist: 
        - 10.10.50.207

测试

> curl  https://local.example.com/
{"message":"Your IP address is not allowed"}

3.12.添加自定义配置

4.灰度发布

4.1.准备环境

4.1.1.stable版本

# vim s1-stable.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-stable-service
  namespace: default
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http-port
  selector:
    app: myapp
    version: stable
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-stable
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      version: stable
  template:
    metadata:
      labels:
        app: myapp
        version: stable
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/public-registry-fzh/myapp:v1
        imagePullPolicy: IfNotPresent
        name: myapp-stable
        ports:
        - name: http-port
          containerPort: 80
        env:
        - name: APP_ENV
          value: stable

4.1.2.canary版本

# vim s2-canary.yaml
---
apiVersion: v1
kind: Service
metadata:
  name: myapp-canary-service
  namespace: canary
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http-port
  selector:
    app: myapp
    version: canary
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-canary
  namespace: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
      version: canary
  template:
    metadata:
      labels:
        app: myapp
        version: canary
    spec:
      containers:
      - image: registry.cn-hangzhou.aliyuncs.com/public-registry-fzh/myapp:v2
        imagePullPolicy: IfNotPresent
        name: myapp-canary
        ports:
        - name: http-port
          containerPort: 80
        env:
        - name: APP_ENV
          value: canary

4.2.基于weight分流

# vim s3-apisixroute-weight.yaml 
---
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute
  namespace: canary 
spec:
  http:
  - name: myapp-canary-rule
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
      weight: 10
    - serviceName: myapp-canary-service
      servicePort: 80
      weight: 1

创建服务和路由等

➜  kubectl apply -f ./
service/myapp-stable-service unchanged
deployment.apps/myapp-stable unchanged
service/myapp-canary-service unchanged
deployment.apps/myapp-canary unchanged
apisixroute.apisix.apache.org/myapp-canary-apisixroute unchanged
➜  kubectl get pods -n canary
NAME                           READY   STATUS    RESTARTS   AGE
myapp-canary-9ff4c55f9-ndjrs   1/1     Running   0          15s
myapp-stable-5fdf6bd75-sq8df   1/1     Running   0          75s
➜  kubectl get apisixroute -n canary
NAME                       HOSTS                   URIS   AGE
myapp-canary-apisixroute   [myapp.example.com]   [/]    97s

测试weight灰度

Stable和 Canary 的比例约为10:1

  ~ for i in `seq 30`;do curl https://myapp.example.com;done
myapp:v1
myapp:v1
.......
myapp:v2
myapp:v1
myapp:v1
myapp:v2
myapp:v1
myapp:v1
myapp:v1
.......
myapp:v1
myapp:v1
myapp:v2
myapp:v1
myapp:v1
myapp:v2

4.3.基于优先级分流

# vim s4-priority.yaml
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute2
  namespace: canary
spec:
  http:
  - name: myapp-stable-rule2
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule2
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

测试,流量会优先打入优先级高的pod

➜  ~ for i in `seq 30`;do curl https://myapp.example.com;done
myapp:v2
myapp:v2
........
myapp:v2
myapp:v2
myapp:v2
myapp:v2

4.4.基于header分流

# vim  canary-header.yaml 
---
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute3
  namespace: canary 
spec:
  http:
  - name: myapp-stable-rule3
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule3
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
      exprs:
      - subject:
          scope: Header
          name: canary
        op: RegexMatch
        value: ".*myapp.*"
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

测试

➜  ~ curl https://myapp.example.com
myapp:v1
➜  ~ curl https://myapp.example.com
myapp:v1
➜  ~ curl https://myapp.example.com
myapp:v1
➜  ~ curl https://myapp.example.com -X GET -H "canary: 124myapp"
myapp:v2
➜  ~ curl https://myapp.example.com -X GET -H "canary: myapp"
myapp:v2
➜  ~ curl https://myapp.example.com -X GET -H "canary: xiamyapp"
myapp:v2
➜  ~ curl https://myapp.example.com -X GET -H "stable: xiamyapp"
myapp:v1
➜  ~ curl https://myapp.example.com -X GET -H "stable: myapp"
myapp:v1

4.5.基于参数的分流

# cat vars.yaml 
---
apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute3
  namespace: canary 
spec:
  http:
  - name: myapp-stable-rule3
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule3
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
      exprs:
      - subject:
          scope: Query
          name: id
        op: In
        set:
        - "12"
        - "23"
        - "45"
        - "67"
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

测试

➜  ~ curl https://myapp.example.com
myapp:v1
➜  ~ curl https://myapp.example.com
myapp:v1
➜  ~ curl https://myapp.example.com
myapp:v1
➜  ~ curl https://myapp.example.com
myapp:v1
➜  ~ curl https://myapp.example.com/\?id\=12
myapp:v2
➜  ~ curl https://myapp.example.com/\?id\=23
myapp:v2
➜  ~ curl https://myapp.example.com/\?id\=45
myapp:v2
➜  ~ curl https://myapp.example.com/\?id\=67
myapp:v2
➜  ~ curl https://myapp.example.com/\?id\=89
myapp:v1
➜  ~ curl https://myapp.example.com/\?id\=143
myapp:v1

4.6.基于cookie分流

apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: myapp-canary-apisixroute
  namespace: default 
spec:
  http:
  - name: myapp-stable-rule3
    priority: 1
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
    backends:
    - serviceName: myapp-stable-service
      servicePort: 80
  - name: myapp-canary-rule3
    priority: 2
    match:
      hosts:
      - myapp.example.com
      paths:
      - /
      exprs:
      - subject:
          scope: Cookie
          name: canary_v5
        op: Equal
        value: "always"
    backends:
    - serviceName: myapp-canary-service
      servicePort: 80

测试携带cookie:

➜  ~ curl --cookie "canary_v5=always" "http://myapp.example.com"
myapp:v2

测试不携带cookie

➜  ~ curl  "http://myapp.example.com"
myapp:v1

你可能感兴趣的:(apisix ingress controller使用指南)