Nginx Ingress的一些奇巧淫技
12.2.1、Nginx Ingress 奇巧淫技
前提:在集群部署好Nginx Ingress
Redirect
redirect主要用于域名重定向,比如访问a.com被重定向到b.com。
如下我们配置访问ng.coolops.com重定向到www.baidu.com
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/permanent-redirect: "https://www.baidu.com"spec: rules: - host: ng.coolops.cn http: paths: - path: backend: serviceName: ng-svc servicePort: 80
然后浏览器访问ng.coolops.cn就会被重定向到https://www.baidu.com
PS E:\DEV\Go\src\code.rookieops.com\coolops> curl.exe -I http://ng.coolops.cn:30369HTTP/1.1 301 Moved PermanentlyServer: nginx/1.17.10Date: Tue, 12 May 2020 09:06:29 GMTContent-Type: text/htmlContent-Length: 170Connection: keep-aliveLocation: https://www.baidu.com
Rewrite
rewrite主要用于地址重写,比如访问a.com/foo重写到a.com,访问a.com/foo/bbb重写到a.com/bbb。
比如下面例子:
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/rewrite-target: "/$1"spec: rules: - host: ng.coolops.cn http: paths: - path: /foo/?(.*) backend: serviceName: ng-svc servicePort: 80
匹配请求头
匹配请求头,主要用于根据请求头信息将用户请求转发到不同的应用,比如根据不同的客户端转发请求。
如下:
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/server-snippet: | set $agentflag 0; if ($http_user_agent ~* "(iPhone)" ){ set $agentflag 1; } if ( $agentflag = 1 ) { return 301 http://iphone.coolops.cn:30369; }spec: rules: - host: ng.coolops.cn http: paths: - path: backend: serviceName: ng-svc servicePort: 80
然后再创建一个iphone.coolops.cn的ingress,我这里只是测试就随便定义了,如下:
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx"spec: rules: - host: iphone.coolops.cn http: paths: - path: backend: serviceName: ng-svc servicePort: 80
我现在以iPad访问,我们发现起没有被301重定向。
当我们使用iPhone访问的时候,可以发现起被301重定向了
认证访问
有些访问是需要认证访问的,比如dubbo-admin,我们在访问的时候会先叫你输入用户名和密码。ingress nginx也可以实现这种。
(1)、创建密码,我这里用http的命令工具来生成
[root@k8s-master ingress-nginx]# htpasswd -c auth jokerNew password: Re-type new password: Adding password for user joker[root@k8s-master ingress-nginx]# cat auth joker:$apr1$R.G4krs/$hh0mX8xe4A3lYKMjvlVs1/
(2)、创建secret
[root@k8s-master ingress-nginx]# kubectl create secret generic basic-auth --from-file=auth secret/basic-auth created
(3)、配置Ingress
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/auth-type: basic nginx.ingress.kubernetes.io/auth-secret: basic-authspec: rules: - host: iphone.coolops.cn http: paths: - path: backend: serviceName: ng-svc servicePort: 80
黑白名单
在配置NG的时候可以用allow和deny来配置黑白名单,在ingress nginx上也可以设置黑白名单。
(1)、白名单
添加白名单的方式可以直接写annotation,也可以配置在ConfigMap中。
写在annotation中:
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/whitelist-source-range: 10.1.10.2spec: rules: - host: iphone.coolops.cn http: paths: - path: backend: serviceName: ng-svc servicePort: 80
也可以写固定IP,也可以写网段。
配置到ConfigMap中:
apiVersion: v1kind: ConfigMapmetadata: labels: helm.sh/chart: ingress-nginx-2.1.0 app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/version: 0.32.0 app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: controller name: ingress-nginx-controller namespace: ingress-nginxdata: whitelist-source-range: 10.1.10.0/24
然后重新apply一下就OK
(2)、黑名单
黑名单就只能通过ConfigMap来配置了,配置如下:
apiVersion: v1kind: ConfigMapmetadata: labels: helm.sh/chart: ingress-nginx-2.1.0 app.kubernetes.io/name: ingress-nginx app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/version: 0.32.0 app.kubernetes.io/managed-by: Helm app.kubernetes.io/component: controller name: ingress-nginx-controller namespace: ingress-nginxdata: whitelist-source-range: 10.1.10.0/24 block-cidrs: 10.1.10.100
速率限制
可以限制速率来降低后端压力,比如如下配置:
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/limit-rate: 100K nginx.ingress.kubernetes.io/limit-whitelist: 10.1.10.100 nginx.ingress.kubernetes.io/limit-rps: 1 nginx.ingress.kubernetes.io/limit-rpm: 30spec: rules: - host: iphone.coolops.cn http: paths: - path: backend: serviceName: ng-svc 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
package mainimport ( "github.com/gin-gonic/gin" "net/http")func main(){ g:=gin.Default() g.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK,gin.H{ "version": "v1", "data": "hello world", }) }) _ = g.Run("8080")}
代码v2
package mainimport ( "github.com/gin-gonic/gin" "net/http")func main(){ g:=gin.Default() g.GET("/", func(c *gin.Context) { c.JSON(http.StatusOK,gin.H{ "version": "v2", "data": "hello world,SB", }) }) _ = g.Run("8080")}
然后制作镜像,这里我们正好可以练习下多阶段构建...
Dockerfile如下:
FROM golang AS build-envADD . /go/src/appWORKDIR /go/src/appRUN go get -u -v github.com/gin-gonic/ginRUN govendor syncRUN GOOS=linux GOARCH=386 go build -v -o /go/src/app/app-server-v1FROM alpineRUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeCOPY --from=build-env /go/src/app/app-server-v1 /usr/local/bin/app-server-v1EXPOSE 8080CMD [ "/usr/local/bin/app-server-v1" ]
构建镜像
docker build -t registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v1 .
上传镜像
docker push registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v1
v2版本相同操作
v1版本的deploy和svc
apiVersion: apps/v1 kind: Deploymentmetadata: name: app-server-v1spec: selector: matchLabels: app: app-server-v1 replicas: 2 template: metadata: labels: app: app-server-v1 spec: containers: - name: app-server-v1 image: registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v1 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080---apiVersion: v1kind: Servicemetadata: name: app-server-v1-svcspec: selector: app: app-server-v1 ports: - name: http port: 8080
v2版本deploy和svc
apiVersion: apps/v1 kind: Deploymentmetadata: name: app-server-v2spec: selector: matchLabels: app: app-server-v2 replicas: 2 template: metadata: labels: app: app-server-v2 spec: containers: - name: app-server-v2 image: registry.cn-hangzhou.aliyuncs.com/rookieops/go-test:v2 imagePullPolicy: IfNotPresent ports: - name: http containerPort: 8080---apiVersion: v1kind: Servicemetadata: name: app-server-v2-svcspec: selector: app: app-server-v2 ports: - name: http port: 8080
运行两个版本进行测试:
[root@k8s-master ingress-nginx]# curl 10.103.133.234:8080{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl 10.101.125.220:8080{"data":"hello SB","version":"v2"}
然后创建ingress。
(1)、正常版本(v1版本)
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx"spec: rules: - host: ng.coolops.cn http: paths: - path: backend: serviceName: app-server-v1 servicePort: 8080
部署后访问
(2)、v2版本
apiVersion: networking.k8s.io/v1beta1kind: Ingressmetadata: name: ingress-nginx annotations: kubernetes.io/ingress.class: "nginx" nginx.ingress.kubernetes.io/canary: "true" nginx.ingress.kubernetes.io/canary-weight: "10"spec: rules: - host: ng.coolops.cn http: paths: - path: backend: serviceName: app-server-v2-svc servicePort: 8080
说明:
- nginx.ingress.kubernetes.io/canary: true 表示开启canary
- nginx.ingress.kubernetes.io/canary-weight: 10 表示权重为10,也就是v1:v2大致为9:1
然后部署后进行测试:
[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"} [root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello world","version":"v1"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello SB","version":"v2"}[root@k8s-master ingress-nginx]# curl http://ng.coolops.cn:30369{"data":"hello SB","version":"v2"}
可以看到上述的这些操作基本都用到annotation,更多的可以点击官方文档。
完
©著作权归作者所有:来自51CTO博客作者mb5ff97f7b72697的原创作品,如需转载,请注明出处,否则将追究法律责任
更多相关文章
- 让DNS运行在容器中
- 控制器访问与参数解析类以及api天气接口实现输入城市查询天气
- mvc控制器的访问与参数解析和API接口获取数据
- PHP: 解析pathinfo(从url解析控制器和方法) 和 cUrl的简单应用
- jqueryDom操作与ajax请求
- mvc控制器类的访问-参数解析-谷歌翻译接口数据渲染到页面
- 面试官:说说你之前负责的系统,QPS 能达到多少?
- 阿里问题定位神器 Arthas 的骚操作,定位线上BUG,超给力!
- 扎心一问:前后端分离开发,RESTful 接口要怎样设计?