Ingress Nginx与Nginx Ingress的区别

Ingress-nginx:它是由Kubernetes社区基于Nginx Web服务器开发的,并补充了一组用于实现额外功能的Lua插件,作为“官方”默认控制器支持当然最优。
Ingress-nginx:项目地址
ingress-nginx:文档

Nginx-ingress:是Nginx官方社区开发产品,Nginx ingress具有很高的稳定性,持续的向后兼容性,没有任何第三方模块,并且由于消除了Lua代码而保证了较高的速度。
Nginx-ingress:项目地址
Nginx-ingress:文档

常用示例

基本使用

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: study-ingress
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

pathType说明:
Ingress 中的每个路径都需要有对应的路径类型(Path Type)。未明确设置 pathType 的路径无法通过合法性检查。当前支持的路径类型有三种:

  • ImplementationSpecific:对于这种路径类型,匹配方法取决于 IngressClass。 具体实现可以将其作为单独的 pathType 处理或者与 Prefix 或 Exact 类型作相同处理。
  • Exact:精确匹配 URL 路径,且区分大小写。
  • Prefix:基于以 / 分隔的 URL 路径前缀匹配。匹配区分大小写,并且对路径中的元素逐个完成。 路径元素指的是由 / 分隔符分隔的路径中的标签列表。 如果每个 p 都是请求路径 p 的元素前缀,则请求与路径 p 匹配。

域名重定向Redirect

常用重定向的类别:

  • 301:nginx.ingress.kubernetes.io/permanent-redirect,永久性重定向:新网址完全继承旧网址,旧网址的SEO网络搜索引擎的排名等完全清零
  • 302:nginx.ingress.kubernetes.io/temporal-redirect: ,302临时性重定向:对旧网址没有影响,但新网址不会有排名
  • 307:nginx.ingress.kubernetes.io/permanent-redirect-code: '307',307 的定义实际上和 302 是一致的,唯一的区别在于,307 状态码不允许浏览器将原本为 POST 的请求重定向到 GET 请求上。

在 Nginx 作为代理服务器时,Redirect 可用于域名的重定向,比如访问 old.com 被重定向到new.com。Ingress 可以更简单的实现 Redirect 功能,接下来用 nginx.redirect.com 作为旧域名,baidu.com 作为新域名进行演示:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com
  name: nginx-redirect
  namespace: study-ingress
spec:
  rules:
  - host: nginx.redirect.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

使用域名、IP、域名及IP三种方式进行访问

域名

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: study-ingress
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

IP

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: study-ingress
spec:
  rules:
  - http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

域名及IP

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: study-ingress
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  - http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

前后端分离Rewrite

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
  name: backend-test
  namespace: study-ingress
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: backend-test
            port:
              number: 80
        path: /test(/|$)(.*)
        pathType: ImplementationSpecific

SSL访问

生产环境对外提供服务时,一般需要配置https协议,使用Ingress也可以非常方便的添加https的证书。
创建测试证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginx.test.com"

创建secret保存证书:

kubectl create secret tls ca-secret --cert=tls.crt --key=tls.key -n study-ingress

创建Ingress资源:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  creationTimestamp: null
  name: nginx-ingress
  namespace: study-ingress
spec:
  ingressClassName: nginx # for k8s >= 1.22+
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - hosts:		# 证书所授权的域名列表
      - nginx.test.com		# 证书锁授权的域名列表
    secretName: ca-secret		# 证书的secret名字

匹配请求头

在实际使用时,常会遇到来自于手机端的访问路由至手机端页面,电脑端的访问路由器至电脑端页面。可以通过请求头中的$http_user_agent来进行匹配分配。

创建手机端应用:

kubectl create deploy phone --image=nginx:phone -n study-ingress
kubectl expose deploy phone --port 80 -n study-ingress

创建手机端应用的ingress:

kubectl create ingress phone --rule=m.test.com/*=phone:80 -n study-ingress

创建PC端应用:

kubectl create deploy pc --image=nginx:pc -n study-ingress
kubectl expose deploy pc --port 80 -n study-ingress

创建电脑端的ingress,通过ingress.annotationsnginx.ingress.kubernetes.io/server-snippet配置。此配置专门用于一些复杂的Nginx配置。

  • nginx.ingress.kubernetes.io/server-snippet:在nginx.conf的“server”字段中添加自定义配置。
  • nginx.ingress.kubernetes.io/configuration-snippet:在nginx.conf的“location”字段中添加自定义配置。

此配置和Nginx的配置通用,匹配移动端的实例如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
  nginx.ingress.kubernetes.io/server-snippet: |
    set $agentflag 0;
        if ($http_user_agent ~* "(Android|iPhone|Windows Phone|UC|Kindle)" ){
            set $agentflag 1;
        }
        if ( $agentflag = 1 ) {
            return 301 http://m.test.com;
        }
  name: pc
  namespace: study-ingress
spec:
  rules:
  - host: test.com
    http:
      paths:
      - backend:
          service:
            name: laptop
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

此时,如果用手机端访问test.com,那么会跳转至m.test.com

基本认证

如果网络需要通过密码来进行验证访问,可以使用Nginx的basic-auth设置密码,配置密码时,需要使用htpasswd工具,此工具为httpd服务内置工具,所以需要安装httpd服务。

$ yum install httpd -y

# 生成某个用户的密码:
$ htpasswd -c auth test
New password:
Re-type new password:
Adding password for user test

$ cat auth
test:$apr1$okma2fa9$hdTJ.Kbmi4pY9T6a2MjeS1

基于生成的密码文件创建secret:

kubectl create secret generic basic-auth --from-file=auth -n study-ingress

创建包含密码认证的ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-realm: Please Input Your Username and Password		# 密码认证时的提示信息
    nginx.ingress.kubernetes.io/auth-secret: basic-auth		# 认证密码文件的secret名称
    nginx.ingress.kubernetes.io/auth-type: basic		# 认证类型:basic、digest
  name: ingress-with-auth
  namespace: study-ingress
spec:
rules:
  - host: auth.test.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: nginx
            port:
              number: 80

黑/白名单

配置黑名单

配置黑名单需要在Ingress Nginx的ConfigMap中进行配置,比如将1.1.1.1添加至黑名单

vim values.yaml
config:
  block-cidrs: 1.1.1.1		# 如有多个通过逗号分隔

更新ingress nginx

helm upgrade ingress-nginx -n ingress-nginx . 

配置白名单

通过添加metadata.annotationsnginx.ingress.kubernetes.io/whitelist-source-range来进行配置。

速率限制

通过添加注解来进行配置

  • nginx.ingress.kubernetes.io/limit-connections:限制连接个数
  • nginx.ingress.kubernetes.io/limit-rps:限制每个IP每秒的连接数
  • nginx.ingress.kubernetes.io/limit-rpm:限制每个IP每分钟的连接数
  • nginx.ingress.kubernetes.io/limit-rate:限制客户端每秒传输的字节数,单位是K,需要开启proxy-buffering
  • nginx.ingress.kubernetes.io/limit-whitelist:限制白名单的速率

灰度/金丝雀发布

关于发布方式的区别请参考:常见发布方式介绍

V1版本环境

kubectl create ns prod

kubectl create deploy canary-v1 --images=test:v1 -n prod

kubectl expose deploy canary-v1 --port 8080 -n prod

kubectl create ingress canary-v1 --rule=test.com/*=canary-v1:8080 -n prod

V2版本环境

kubectl create ns canary

kubectl create deploy canary-v2 --image=test:v2 -n canary

kubectl expose deploy canary-v2 --port 8080 -n canary

创建canary的ingress进行流量切入

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
  name: canary-v2
  namespace: canary
spec:
  ingressClassName: nginx # for k8s >=1.22+
rules:
  - host: canary.com
http:
  paths:
    - path: /
      pathType: ImplementationSpecific
      backend:
        service:
          name: canary-v2
          port:
            number: 8080

创建v2版本的Ingress时,需要添加两个注释:

  • nginx.ingress.kubernetes.io/canary: true:表示此为灰度环境
  • nginx.ingress.kubernetes.io/canary-weight: "10":表示切入10%的流量

此时v2版本占10%的流量,v1版本占90%的流量。

跨域

通过如下注解进行配置:

  • nginx.ingress.kubernetes.io/cors-allow-credentials::控制在跨域配置中是否允许传递凭据,默认值:true
  • nginx.ingress.kubernetes.io/cors-max-age:控制预检请求可以缓存多长时间。默认值:1728000。一般配置为'600'
  • nginx.ingress.kubernetes.io/cors-allow-origin:控制CORS的可接受来源,默认值:*
  • nginx.ingress.kubernetes.io/cors-expose-headers:控制哪些标头暴露给响应,默认值:empty。一般情况不配置。
  • nginx.ingress.kubernetes.io/cors-allow-headers:控制接受哪些标头,默认值:DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization。配置时需根据程序请求头信息将所有涉及到的请求头key进行填写。
  • nginx.ingress.kubernetes.io/cors-allow-methods:控制可接受的方法。默认:GET, PUT, POST, DELETE, PATCH, OPTIONS。根据需求填写需要的方法即可。
  • nginx.ingress.kubernetes.io/enable-cors:控制是否开启跨域配置。开启配置为:true

示例:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  namespace: study-ingress
  annotations:
    nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization,token,idcard"
    nginx.ingress.kubernetes.io/cors-allow-methods: "GET,POST,OPTIONS"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
    nginx.ingress.kubernetes.io/cors-max-age: "600"
    nginx.ingress.kubernetes.io/enable-cors: "true"
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: nginx
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific

星霜荏苒 居诸不息