前提:在集群部署好Nginx Ingress

Redirect

redirect主要用于域名重定向,比如访问a.com被重定向到b.com。
如下我们配置访问ng.coolops.com重定向到www.baidu.com

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. nginx.ingress.kubernetes.io/permanent-redirect: "https://www.baidu.com"
  8. spec:
  9. rules:
  10. - host: ng.coolops.cn
  11. http:
  12. paths:
  13. - path:
  14. backend:
  15. serviceName: ng-svc
  16. servicePort: 80

然后浏览器访问ng.coolops.cn就会被重定向到https://www.baidu.com

  1. PS E:\DEV\Go\src\code.rookieops.com\coolops> curl.exe -I http://ng.coolops.cn:30369
  2. HTTP/1.1 301 Moved Permanently
  3. Server: nginx/1.17.10
  4. Date: Tue, 12 May 2020 09:06:29 GMT
  5. Content-Type: text/html
  6. Content-Length: 170
  7. Connection: keep-alive
  8. Location: https://www.baidu.com

Rewrite

rewrite主要用于地址重写,比如访问a.com/foo重写到a.com,访问a.com/foo/bbb重写到a.com/bbb。
比如下面例子:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. nginx.ingress.kubernetes.io/rewrite-target: "/$1"
  8. spec:
  9. rules:
  10. - host: ng.coolops.cn
  11. http:
  12. paths:
  13. - path: /foo/?(.*)
  14. backend:
  15. serviceName: ng-svc
  16. servicePort: 80

image.png

匹配请求头

匹配请求头,主要用于根据请求头信息将用户请求转发到不同的应用,比如根据不同的客户端转发请求。
如下:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. nginx.ingress.kubernetes.io/server-snippet: |
  8. set $agentflag 0;
  9. if ($http_user_agent ~* "(iPhone)" ){
  10. set $agentflag 1;
  11. }
  12. if ( $agentflag = 1 ) {
  13. return 301 http://iphone.coolops.cn:30369;
  14. }
  15. spec:
  16. rules:
  17. - host: ng.coolops.cn
  18. http:
  19. paths:
  20. - path:
  21. backend:
  22. serviceName: ng-svc
  23. servicePort: 80

然后再创建一个iphone.coolops.cn的ingress,我这里只是测试就随便定义了,如下:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. spec:
  8. rules:
  9. - host: iphone.coolops.cn
  10. http:
  11. paths:
  12. - path:
  13. backend:
  14. serviceName: ng-svc
  15. servicePort: 80

我现在以iPad访问,我们发现起没有被301重定向。
image.png

当我们使用iPhone访问的时候,可以发现起被301重定向了
image.png

认证访问

有些访问是需要认证访问的,比如dubbo-admin,我们在访问的时候会先叫你输入用户名和密码。ingress nginx也可以实现这种。
(1)、创建密码,我这里用http的命令工具来生成

  1. [root@k8s-master ingress-nginx]# htpasswd -c auth joker
  2. New password:
  3. Re-type new password:
  4. Adding password for user joker
  5. [root@k8s-master ingress-nginx]# cat auth
  6. joker:$apr1$R.G4krs/$hh0mX8xe4A3lYKMjvlVs1/

(2)、创建secret

  1. [root@k8s-master ingress-nginx]# kubectl create secret generic basic-auth --from-file=auth
  2. secret/basic-auth created

(3)、配置Ingress

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. nginx.ingress.kubernetes.io/auth-type: basic
  8. nginx.ingress.kubernetes.io/auth-secret: basic-auth
  9. spec:
  10. rules:
  11. - host: iphone.coolops.cn
  12. http:
  13. paths:
  14. - path:
  15. backend:
  16. serviceName: ng-svc
  17. servicePort: 80

image.png

黑白名单

在配置NG的时候可以用allow和deny来配置黑白名单,在ingress nginx上也可以设置黑白名单。
(1)、白名单
添加白名单的方式可以直接写annotation,也可以配置在ConfigMap中。
写在annotation中:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. nginx.ingress.kubernetes.io/whitelist-source-range: 10.1.10.2
  8. spec:
  9. rules:
  10. - host: iphone.coolops.cn
  11. http:
  12. paths:
  13. - path:
  14. backend:
  15. serviceName: ng-svc
  16. servicePort: 80

也可以写固定IP,也可以写网段。

配置到ConfigMap中:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. labels:
  5. helm.sh/chart: ingress-nginx-2.1.0
  6. app.kubernetes.io/name: ingress-nginx
  7. app.kubernetes.io/instance: ingress-nginx
  8. app.kubernetes.io/version: 0.32.0
  9. app.kubernetes.io/managed-by: Helm
  10. app.kubernetes.io/component: controller
  11. name: ingress-nginx-controller
  12. namespace: ingress-nginx
  13. data:
  14. whitelist-source-range: 10.1.10.0/24

然后重新apply一下就OK

(2)、黑名单
黑名单就只能通过ConfigMap来配置了,配置如下:

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. labels:
  5. helm.sh/chart: ingress-nginx-2.1.0
  6. app.kubernetes.io/name: ingress-nginx
  7. app.kubernetes.io/instance: ingress-nginx
  8. app.kubernetes.io/version: 0.32.0
  9. app.kubernetes.io/managed-by: Helm
  10. app.kubernetes.io/component: controller
  11. name: ingress-nginx-controller
  12. namespace: ingress-nginx
  13. data:
  14. whitelist-source-range: 10.1.10.0/24
  15. block-cidrs: 10.1.10.100

速率限制

可以限制速率来降低后端压力,比如如下配置:

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. nginx.ingress.kubernetes.io/limit-rate: "100K"
  8. nginx.ingress.kubernetes.io/limit-whitelist: "10.1.10.100"
  9. nginx.ingress.kubernetes.io/limit-rps: "1"
  10. nginx.ingress.kubernetes.io/limit-rpm: "30"
  11. spec:
  12. rules:
  13. - host: iphone.coolops.cn
  14. http:
  15. paths:
  16. - path:
  17. backend:
  18. serviceName: ng-svc
  19. servicePort: 80

其中:

  • nginx.ingress.kubernetes.io/limit-rate:限制客户端每秒传输的字节数
  • nginx.ingress.kubernetes.io/limit-whitelist:白名单中的IP不限速
  • nginx.ingress.kubernetes.io/limit-rps:单个IP每秒的连接数
  • nginx.ingress.kubernetes.io/limit-rpm:单个IP每分钟的连接数

更多请点这里

灰度发布

Nginx Annotations 支持以下 4 种 Canary 规则:

  • nginx.ingress.kubernetes.io/canary-by-header:基于 Request Header 的流量切分,适用于灰度发布以及 A/B 测试。当 Request Header 设置为 always时,请求将会被一直发送到 Canary 版本;当 Request Header 设置为 never时,请求不会被发送到 Canary 入口;对于任何其他 Header 值,将忽略 Header,并通过优先级将请求与其他金丝雀规则进行优先级的比较。
  • nginx.ingress.kubernetes.io/canary-by-header-value:要匹配的 Request Header 的值,用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务。当 Request Header 设置为此值时,它将被路由到 Canary 入口。该规则允许用户自定义 Request Header 的值,必须与上一个 annotation (即:canary-by-header)一起使用。
  • nginx.ingress.kubernetes.io/canary-weight:基于服务权重的流量切分,适用于蓝绿部署,权重范围 0 - 100 按百分比将请求路由到 Canary Ingress 中指定的服务。权重为 0 意味着该金丝雀规则不会向 Canary 入口的服务发送任何请求。权重为 100 意味着所有请求都将被发送到 Canary 入口。
  • nginx.ingress.kubernetes.io/canary-by-cookie:基于 Cookie 的流量切分,适用于灰度发布与 A/B 测试。用于通知 Ingress 将请求路由到 Canary Ingress 中指定的服务的cookie。当 cookie 值设置为 always时,它将被路由到 Canary 入口;当 cookie 值设置为 never时,请求不会被发送到 Canary 入口;对于任何其他值,将忽略 cookie 并将请求与其他金丝雀规则进行优先级的比较。

定义两个版本的代码。
代码v1

  1. package main
  2. import (
  3. "github.com/gin-gonic/gin"
  4. "net/http"
  5. )
  6. func main(){
  7. g:=gin.Default()
  8. g.GET("/", func(c *gin.Context) {
  9. c.JSON(http.StatusOK,gin.H{
  10. "version": "v1",
  11. "data": "hello world",
  12. })
  13. })
  14. _ = g.Run("8080")
  15. }

代码v2

  1. package main
  2. import (
  3. "github.com/gin-gonic/gin"
  4. "net/http"
  5. )
  6. func main(){
  7. g:=gin.Default()
  8. g.GET("/", func(c *gin.Context) {
  9. c.JSON(http.StatusOK,gin.H{
  10. "version": "v2",
  11. "data": "hello world,SB",
  12. })
  13. })
  14. _ = g.Run("8080")
  15. }

然后制作镜像,这里我们正好可以练习下多阶段构建…
Dockerfile如下:

  1. FROM golang AS build-env
  2. ADD . /go/src/app
  3. WORKDIR /go/src/app
  4. RUN go get -u -v github.com/gin-gonic/gin
  5. RUN govendor sync
  6. RUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server-v1
  7. FROM alpine
  8. RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  9. COPY --from=build-env /go/src/app/app-server-v1 /usr/local/bin/app-server-v1
  10. EXPOSE 8080
  11. CMD [ "/usr/local/bin/app-server-v1" ]

构建镜像

  1. docker build -t registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v1 .

上传镜像

  1. docker push registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v1

v2版本相同操作

v1版本的deploy和svc

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: app-server-v1
  5. spec:
  6. selector:
  7. matchLabels:
  8. app: app-server-v1
  9. replicas: 2
  10. template:
  11. metadata:
  12. labels:
  13. app: app-server-v1
  14. spec:
  15. containers:
  16. - name: app-server-v1
  17. image: registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v1
  18. imagePullPolicy: IfNotPresent
  19. ports:
  20. - name: http
  21. containerPort: 8080
  22. ---
  23. apiVersion: v1
  24. kind: Service
  25. metadata:
  26. name: app-server-v1-svc
  27. spec:
  28. selector:
  29. app: app-server-v1
  30. ports:
  31. - name: http
  32. port: 8080

v2版本deploy和svc

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: app-server-v2
  5. spec:
  6. selector:
  7. matchLabels:
  8. app: app-server-v2
  9. replicas: 2
  10. template:
  11. metadata:
  12. labels:
  13. app: app-server-v2
  14. spec:
  15. containers:
  16. - name: app-server-v2
  17. image: registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v2
  18. imagePullPolicy: IfNotPresent
  19. ports:
  20. - name: http
  21. containerPort: 8080
  22. ---
  23. apiVersion: v1
  24. kind: Service
  25. metadata:
  26. name: app-server-v2-svc
  27. spec:
  28. selector:
  29. app: app-server-v2
  30. ports:
  31. - name: http
  32. port: 8080

运行两个版本进行测试:

  1. [root@k8s-master ingress-nginx]# curl 10.103.133.234:8080
  2. {"data":"hello world","version":"v1"}
  3. [root@k8s-master ingress-nginx]# curl 10.101.125.220:8080
  4. {"data":"hello SB","version":"v2"}

然后创建ingress。
(1)、正常版本(v1版本)

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. spec:
  8. rules:
  9. - host: ng.coolops.cn
  10. http:
  11. paths:
  12. - path:
  13. backend:
  14. serviceName: app-server-v1
  15. servicePort: 8080

部署后访问
image.png
(2)、v2版本

  1. apiVersion: networking.k8s.io/v1beta1
  2. kind: Ingress
  3. metadata:
  4. name: ingress-nginx
  5. annotations:
  6. kubernetes.io/ingress.class: "nginx"
  7. nginx.ingress.kubernetes.io/canary: "true"
  8. nginx.ingress.kubernetes.io/canary-weight: "10"
  9. spec:
  10. rules:
  11. - host: ng.coolops.cn
  12. http:
  13. paths:
  14. - path:
  15. backend:
  16. serviceName: app-server-v2-svc
  17. servicePort: 8080

说明:

  • nginx.ingress.kubernetes.io/canary: true 表示开启canary
  • nginx.ingress.kubernetes.io/canary-weight: 10 表示权重为10,也就是v1:v2大致为9:1

然后部署后进行测试:

  1. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  2. {"data":"hello world","version":"v1"}
  3. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  4. {"data":"hello world","version":"v1"}
  5. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  6. {"data":"hello world","version":"v1"}
  7. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  8. {"data":"hello world","version":"v1"}
  9. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  10. {"data":"hello world","version":"v1"}
  11. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  12. {"data":"hello world","version":"v1"}
  13. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  14. {"data":"hello world","version":"v1"}
  15. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  16. {"data":"hello world","version":"v1"}
  17. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  18. {"data":"hello world","version":"v1"}
  19. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  20. {"data":"hello world","version":"v1"}
  21. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  22. {"data":"hello world","version":"v1"}
  23. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  24. {"data":"hello world","version":"v1"}
  25. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  26. {"data":"hello world","version":"v1"}
  27. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  28. {"data":"hello world","version":"v1"}
  29. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  30. {"data":"hello SB","version":"v2"}
  31. [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369
  32. {"data":"hello SB","version":"v2"}

可以看到上述的这些操作基本都用到annotation,更多的可以点击官方文档