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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342