1. Ingress-nginx

1.1 ingress-nginx是什么?

它是 Kubernetes 的官方入口网关,用 NGINX 实现七层(HTTP/HTTPS)流量管理,自动将域名和路径路由到集群内不同服务。


核心功能

  1. 统一入口
    • 通过单个IP+端口(80/443)暴露所有HTTP服务,替代多个NodePort/LoadBalancer
  2. 智能路由
    • 根据 域名Host)和 路径Path)转发请求到后端Service。
  3. 自动化
    • 监听K8s API,动态更新NGINX配置,无需手动重启。

解决了什么问题?

  • 痛点:直接用Service的NodePortLoadBalancer时:
    • ❌ 无法基于域名路由
    • ❌ 需维护多个IP/端口
    • ❌ 手动管理TLS证书
  • 方案:Ingress-NGINX 通过声明式配置(YAML)一键搞定。

1.2 为什么引入Ingress?

我们说k8s 的服务(service)时,说暴露了service的三种方式ClusterIP、NodePort与LoadBalance,这几种方式都是在service的维度提供的,service的作用体现在两个方面,对集群内部,它不断跟踪pod的变化,更新endpoint中对应pod的对象,提供了ip不断变化的pod的服务发现机制,对集群外部,他类似负载均衡器,可以在集群内外部对pod进行访问。但是,单独用service暴露服务的方式,在实际生产环境中不太合适:

  • ClusterIP的方式只能在集群内部访问。

  • NodePort方式的话,测试环境使用还行,当有几十上百的服务在集群中运行时,NodePort的端口管理是灾难。

  • LoadBalance方式受限于云平台,且通常在云平台部署ELB还需要额外的费用。

所幸k8s还提供了一种集群维度暴露服务的方式,也就是ingress。ingress可以简单理解为service的service,他通过独立的ingress对象来制定请求转发的规则,把请求路由到一个或多个service中。这样就把服务与请求规则解耦了,可以从业务维度统一考虑业务的暴露,而不用为每个service单独考虑。

service通过iptables、ipvs实现。有缺陷:每一组业务都要开启nodePort,这样nodePort越来越多越来越难管理

解决方案:多加一层管理庞大的service

  • 本来nodePort是映射到Service的,现在在往上抽一层,映射到上层,由上层再分发到service,此方案Ingress实现了
  • 而Ingress是K8S中的资源,接口,可以由不同的控制器实现
  • Ingress-nginx是其中的一种实现,是对nginx的二次开发,来满足Ingress的规范ingress-nginx官方讲解

1.3 基于Helm部署ingress-nginx

官方地址: https://github.com/kubernetes/ingress-nginx

确保自己的harbor仓库有这两个镜像,可以在国内的渡渡鸟镜像网站里下载

  • 控制器镜像(controller):Ingress-Nginx 的核心组件,负责监听 Kubernetes API 并根据 Ingress 规则配置负载均衡器。它处理所有进入集群的 HTTP/HTTPS 流量,并将请求路由到对应的 Service。
  • kube-webhook-certgen 镜像(可选):用于自动生成和管理 Ingress-Nginx 的 admission webhook 所需的 TLS 证书。如果启用了 webhook 验证功能(默认启用),则需要此镜像。

在这里插入图片描述

[root@master 7.6]# helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
[root@master 7.6]# helm pull ingress-nginx/ingress-nginx
[root@master 7.6]# ls
ingress-nginx-4.12.3.tgz
[root@master 7.6]# tar -xf ingress-nginx-4.12.3.tgz 
[root@master 7.6]# ls
ingress-nginx             ingress-nginx-4.12.3.tgz

# 修改values.yaml文件
1- 修改global.image.registry=harbor:443
2- 修改image的拉取地方为harbor仓库里的镜像,tag也是
3- 修改 hostNetwork 的值为 true ,共享宿主机网络
4- dnsPolicy的值改为: clusterFirstWithHostNet
5- kind类型更改为:DaemonSet,启冗余作用
6- 关闭所有镜像的 digest
7- ingressClassResource.default=true

# 创建一个名称空间为ingress
[root@master 7.6]# kubectl create ns ingress
# 部署ingress-nginx
[root@master 7.6]# helm install ingress-nginx -f ingress-nginx/values.yaml -n ingress ingress-nginx/
# 查看pod状态,为running就部署成功!
[root@master 7.6]# kubectl get pods -n ingress -o wide 
NAME                             READY   STATUS    RESTARTS   AGE     IP              NODE     NOMINATED NODE   READINESS GATES
ingress-nginx-controller-8lsvd   1/1     Running   0          3m37s   192.168.10.12   node02   <none>           <none>
ingress-nginx-controller-hhzmz   1/1     Running   0          3m37s   192.168.10.13   node03   <none>           <none>
ingress-nginx-controller-lqxlj   1/1     Running   0          3m37s   192.168.10.11   node01   <none>       

1.4 Ingress HTTP 代理访问

[root@master 7.6]# vim 1.ingress_http.yaml 
---
kind: Deployment
apiVersion: apps/v1
metadata: 
  name: ingress-http-www1
spec: 
  replicas: 2
  selector: 
    matchLabels: 
      hostname: www1
  template: 
    metadata: 
      labels: 
        hostname: www1
    spec: 
      containers: 
      - name: web
        image: myos:httpd
        ports: 
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata: 
  name: ingress-http-www1
spec: 
  ports: 
  - port: 80
    targetPort: 80
  selector: 
    hostname: www1
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata: 
  name: ingress-http-www1
spec: 
  ingressClassName: nginx # 关联到ingress-nginx控制器
  rules:                  # ingress规则定义
  - host: www1.zkbr.com   # 定义域名
    http:                 # 使用的协议
      paths:              # 定义访问的路径
      - path: /           # 访问的url路径
        pathType: Prefix  # 路径的类型(Exact、Prefix)
        backend:          # 定义后端服务
          service:        # 声明svc
            name: ingress-http-www1 # svc的名称
            port:         # 声明端口号
              number: 80  # 访问服务的端口号
[root@master 7.6]# kubectl apply -f 1.ingress_http.yaml 
[root@master 7.6]# kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
ingress-http-www1-c8bd7b98-6pptq   1/1     Running   0          5s
ingress-http-www1-c8bd7b98-r9zg4   1/1     Running   0          6s
[root@master 7.6]# kubectl get svc
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
ingress-http-www1   ClusterIP   10.245.44.237   <none>        80/TCP    15s
kubernetes          ClusterIP   10.245.0.1      <none>        443/TCP   67d
[root@master 7.6]# kubectl get ingress
NAME                CLASS   HOSTS           ADDRESS   PORTS   AGE
ingress-http-www1   nginx   www1.zkbr.com             80      19s

测试环境要配置host域名解析

在这里插入图片描述

在这里插入图片描述

访问域名,ingress会根据定义的规则来调用后端的svc响应

# hostNetwork 模式的访问链路
用户 → DNS 解析 → 宿主机 IP:80/443(直接绑定 ingress-nginx-controller Pod) → Nginx 匹配 Ingress 规则 → 转发到后端 Service → 后端 Pod → 响应返回给用户

在这里插入图片描述

1.4.1 基于ingress-nginx创建多虚拟主机的访问

[root@master 7.6]# vim 2.ingress_http.yaml 
---
kind: Deployment
apiVersion: apps/v1
metadata: 
  name: ingress-http-www2
spec: 
  replicas: 2
  selector: 
    matchLabels: 
      hostname: www2
  template: 
    metadata: 
      labels: 
        hostname: www2
    spec: 
      containers: 
      - name: web
        image: myos:httpd
        ports: 
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata: 
  name: ingress-http-www2
spec: 
  ports: 
  - port: 80
    targetPort: 80
  selector: 
    hostname: www2
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata: 
  name: ingress-http-www2
spec: 
  ingressClassName: nginx
  rules: 
  - host: www2.zkbr.com # 也可以创建多个host来实现多虚拟主机(推荐)
    http: 
      paths: 
      - path: /
        pathType: Prefix
        backend: 
          service: 
            name: ingress-http-www2
            port: 
              number: 80
[root@master 7.6]# kubectl apply -f 2.ingress_http.yaml 
[root@master 7.6]# kubectl get pods
NAME                                 READY   STATUS    RESTARTS   AGE
ingress-http-www1-c8bd7b98-6pptq     1/1     Running   0          30m
ingress-http-www1-c8bd7b98-r9zg4     1/1     Running   0          30m
ingress-http-www2-786b6bcd67-h2gnx   1/1     Running   0          10s
ingress-http-www2-786b6bcd67-jxmpj   1/1     Running   0          10s
[root@master 7.6]# kubectl get svc
NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
ingress-http-www1   ClusterIP   10.245.44.237   <none>        80/TCP    34m
ingress-http-www2   ClusterIP   10.245.60.88    <none>        80/TCP    3m50s
kubernetes          ClusterIP   10.245.0.1      <none>        443/TCP   67d
[root@master 7.6]# kubectl get ingress
NAME                CLASS   HOSTS           ADDRESS   PORTS   AGE
ingress-http-www1   nginx   www1.zkbr.com             80      34m
ingress-http-www2   nginx   www2.zkbr.com             80      3m54s

添加解析记录

在这里插入图片描述

访问www2.zkbr.com/info.php

在这里插入图片描述

1.5 Ingress HTTPS 代理访问

# 生成测试环境中的私钥和证书,生产环境中肯定是要去购买
[root@master 7.7]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
Generating a RSA private key
..............+++++
...................................+++++
writing new private key to 'tls.key'
-----
[root@master 7.7]# ls
tls.crt  tls.key
# 创建tls类型的secret,并指定私钥和证书
[root@master 7.7]# kubectl create secret tls ingress-nginx-tls --key tls.key --cert tls.crt 

# 编写资源清单文件
[root@master 7.7]# vim 1.ingress-nginx-https.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-http-ssl
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ingress-http-ssl
  template:
    metadata:
      labels:
        app: ingress-http-ssl
    spec:
      containers:
      - image: myos:httpd
        name: myos
---
apiVersion: v1
kind: Service
metadata: 
  name: ingress-http-ssl
spec: 
  ports: 
  - port: 80
    targetPort: 80
  selector: 
    app: ingress-http-ssl
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata: 
  name: ingress-http-ssl
  annotations: 
    nginx.ingress.kubernetes.io/ssl-redirect: "true" # 强制 HTTPS 重定向,将所有 HTTP 请求(端口 80)重定向到 HTTPS(端口 443)
spec: 
  ingressClassName: nginx
  tls: 
  - hosts: 
    - ssl.zkbr.com
    secretName: ingress-nginx-tls
  rules: 
  - host: ssl.zkbr.com
    http: 
      paths: 
      - path: /
        pathType: Prefix
        backend: 
          service: 
            name: ingress-http-ssl
            port: 
              number: 80
[root@master 7.7]# kubectl apply -f 1.ingress-nginx-https.yaml
[root@master 7.7]# kubectl get pods 
NAME                                 READY   STATUS    RESTARTS      AGE
ingress-http-ssl-678cf7dcf6-29p2b    1/1     Running   0             6m6s
ingress-http-ssl-678cf7dcf6-wc87h    1/1     Running   0             6m6s
ingress-http-www1-c8bd7b98-6pptq     1/1     Running   1 (12h ago)   24h
ingress-http-www1-c8bd7b98-r9zg4     1/1     Running   1 (12h ago)   24h
ingress-http-www2-786b6bcd67-h2gnx   1/1     Running   1 (12h ago)   24h
ingress-http-www2-786b6bcd67-jxmpj   1/1     Running   1 (12h ago)   24h
[root@master 7.7]# kubectl get svc,ingress
NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/ingress-http-ssl    ClusterIP   10.245.100.178   <none>        80/TCP    6m29s
service/ingress-http-www1   ClusterIP   10.245.44.237    <none>        80/TCP    24h
service/ingress-http-www2   ClusterIP   10.245.60.88     <none>        80/TCP    24h
service/kubernetes          ClusterIP   10.245.0.1       <none>        443/TCP   68d

NAME                                          CLASS   HOSTS           ADDRESS   PORTS     AGE
ingress.networking.k8s.io/ingress-http-ssl    nginx   ssl.zkbr.com              80, 443   6m29s
ingress.networking.k8s.io/ingress-http-www1   nginx   www1.zkbr.com             80        24h
ingress.networking.k8s.io/ingress-http-www2   nginx   www2.zkbr.com             80        24h

测试环境添加域名解析记录

在这里插入图片描述

在这里插入图片描述

1.6 Ingress basicAuth 代理

[root@master 7.7]# dnf -y install httpd-tools
[root@master 7.7]# htpasswd -c auth hehe
# 添加用户
[root@master 7.7]# htpasswd auth lili
[root@master 7.7]# cat auth 
hehe:$apr1$.qikKmFZ$9sbloDIxooQ20Phrd0.pu/
lili:$apr1$H8rRr66e$6dDOrWsGERrQhcrDXpgt80
[root@master 7.7]#  kubectl create secret generic ingress-basic-auth --from-file=auth
[root@master 7.7]# vim 2.ingress-nginx-auth.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-http-auth
spec:
  replicas: 2
  selector:
    matchLabels:
      app: ingress-http-auth
  template:
    metadata:
      labels:
        app: ingress-http-auth
    spec:
      containers:
      - image: myos:httpd
        name: myos
        ports: 
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata: 
  name: ingress-http-auth
spec: 
  ports: 
  - port: 80
    targetPort: 80
  selector: 
    app: ingress-http-auth
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-http-auth
  annotations:  # 添加释文
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: ingress-basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Admin Area'
spec:
  ingressClassName: nginx
  rules:
  - host: auth.zkbr.com
    http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: ingress-http-auth
            port:
              number: 80
  tls:
  - hosts:
    - auth.zkbr.com
    secretName: ingress-nginx-tls
[root@master 7.7]# kubectl apply -f 2.ingress-nginx-auth.yaml 
[root@master 7.7]# kubectl get ingress
NAME                CLASS   HOSTS           ADDRESS   PORTS     AGE
ingress-http-auth   nginx   auth.zkbr.com             80, 443   6m59s
ingress-http-ssl    nginx   ssl.zkbr.com              80, 443   44h
ingress-http-www1   nginx   www1.zkbr.com             80        2d20h
ingress-http-www2   nginx   www2.zkbr.com             80        2d20h

测试环境添加解析记录

在这里插入图片描述

在这里插入图片描述

1.7 Ingress-nginx 域名重定向

Redirect(重定向):

  • 作用:重定向是指服务器向客户端发出一个新的URL,让客户端进行新的请求。客户端会收到一个HTTP3xx状态码,然后根据其中的重定向地址进行新的请求。这意味着客户端会知道发生了重定向,客户端的地址栏也会变成重定向的地址,它会发起新的请求
  • 示例:比如你有一个网站的旧地址是http://example.com,但是你希望所有的请求都转发到https://example.com,这时你就可以使用重定向将所有的HTTP请求重定向到HTTPS
[root@master 7.9]# vim 1.ingress-redirect.yaml 
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata: 
  name: ingress-redirect
  annotations: 
    # 设置301永久重定向
    nginx.ingress.kubernetes.io/permanent-redirect: https://www.jd.com
spec:
  ingressClassName: nginx
  rules:
  - host: redirect.zkbr.com    
    http:  # 因为我们要把整个域名重定向到京东,所以下面就不用定义访问路径了

测试效果

[root@master 7.9]# echo "192.168.10.13 redirect.zkbr.com" >> /etc/hosts
[root@master 7.9]# curl -I redirect.zkbr.com 
HTTP/1.1 301 Moved Permanently
Date: Wed, 09 Jul 2025 10:35:54 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: https://www.jd.com  # 被301重定向到了jd

在这里插入图片描述
在这里插入图片描述

1.8 Ingress-nginx 地址重写

Rewrite (重写)

  • 作用:重写是指修改请求的路径,但是客户端不会察觉到这个变化,它仅在服务器内部发生。在Kubernetes 中,可以通过Ingress 的注解来配置重写规则
  • 示例:比如你有一个服务部署在/v1路径下,但是你希望用户访问时不需要输入/v1,那么你可以使用重写将请求从根路径/重写到/v1
[root@master 7.9]# vim 2.ingress-rewrite.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-rewrite
  annotations:
    # 启用URL重写功能
    nginx.ingress.kubernetes.io/rewrite-target: /info.$1
    # 启用正则表达式匹配
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: rewrite.zkbr.com
    http:
      paths:
      - path: /test.(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: ingress-http-www1  # 请求被该svc响应
            port:
              number: 80

测试环境添加域名解析

在这里插入图片描述
在这里插入图片描述

1.9 Ingress-nginx 自定义错误页

[root@master 7.10]# vim 1.ingress-error.yaml 
---
kind: Deployment
apiVersion: apps/v1
metadata: 
  name: ingress-error
spec: 
  replicas: 2
  selector: 
    matchLabels: 
      name: error
  template: 
    metadata: 
      labels: 
        name: error
    spec: 
      containers: 
      - name: test
        image: library/errorweb:v1.0  # 该镜像是我提前下载到我的harbor仓库中的,使用的是汪洋老师的镜像
        ports: 
        - containerPort: 80
--- 
kind: Service
apiVersion: v1
metadata: 
  name: ingress-error
spec: 
  selector: 
    name: error
  ports: 
  - port: 80
    targetPort: 80
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata: 
  name: ingress-error
  annotations: 
    # 指定需要自定义的错误码
    nginx.ingress.kubernetes.io/custom-http-errors: "404,500"
    # 将错误请求转发到后端的svc来响应
    nginx.ingress.kubernetes.io/default-backend: "ingress-error"
spec: 
  rules: 
  - host: error.zkbr.com
    http: 
      paths: 
        - path: /
          pathType: Prefix
          backend: 
            service: 
              name: ingress-http-www1 # 该svc,是之前定义的svc
              port: 
                number: 80
[root@master 7.10]# kubectl apppl -f 1.ingress-error.yaml
[root@master 7.10]# kubectl get ingress
NAME                CLASS   HOSTS               ADDRESS   PORTS     AGE
ingress-error       nginx   error.zkbr.com                80        15m
ingress-http-auth   nginx   auth.zkbr.com                 80, 443   28h
ingress-http-ssl    nginx   ssl.zkbr.com                  80, 443   3d
ingress-http-www1   nginx   www1.zkbr.com                 80        4d1h
ingress-http-www2   nginx   www2.zkbr.com                 80        4d
ingress-redirect    nginx   redirect.zkbr.com             80        27h
ingress-rewrite     nginx   rewrite.zkbr.com              80        26h

测试环境添加域名解析记录

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.10 Ingress-nginx snippet 自定义配置片段

Ingress-nginx 中,snippet 通常指的是通过注解(Annotations)向 Nginx 配置注入的自定义配置片段。下面从其作用、使用方式、优势与风险等方面详细介绍:

1.10.1 作用

Ingress-nginx 作为 Kubernetes 中常用的 Ingress 控制器,负责将外部流量路由到集群内的服务上。尽管它提供了丰富的默认配置和参数,但在一些复杂场景下,默认配置无法满足需求。这时,snippet 就派上用场了,它允许用户灵活地自定义 Nginx 的配置,从而实现更精细的流量控制、安全策略、性能优化等功能 。例如:

  • 自定义重定向:根据请求的来源、客户端类型等条件,设置特定的重定向规则。
  • 添加自定义 HTTP 头:在响应中添加自定义的 HTTP 头部信息,用于实现特定的业务逻辑或安全策略。
  • 配置缓存策略:对某些资源设置缓存规则,提高响应速度。

1.10.2 优势与风险

  • 优势:极大地增强了 Ingress-nginx 的灵活性和扩展性,能满足多样化的业务需求,而无需修改 Ingress-nginx 的代码或重新部署。
  • 风险:直接修改 Nginx 配置存在一定的安全风险,如果配置不当,可能会导致服务不可用、安全漏洞等问题。因此,默认情况下,Ingress-nginx 禁止通过注解注入配置片段,需要在 Ingress-nginx 的 ConfigMap 中设置 allow-snippet-annotations: "true" 来开启该功能,并且在使用时需要严格测试和审核配置内容 。

1.10.3开启注解注入配置片段的权限

allow-snippet-annotations参数设为 true 时,用户可以在 Ingress 资源的 annotations 中使用以下特殊注解,直接注入 Nginx 配置片段:

  • nginx.ingress.kubernetes.io/configuration-snippet:注入到 Nginx 服务器(server)块的配置中(适用于路由级别的自定义,如重定向、缓存策略等)。
  • nginx.ingress.kubernetes.io/server-snippet:注入到 Nginx 全局 http 块的配置中(适用于全局级别的自定义,如日志格式、全局变量等)。
  • nginx.ingress.kubernetes.io/location-snippet:注入到 Nginx location 块的配置中(适用于特定路径的细节配置)。
# 开启自定义配置片段功能
[root@master 8.10]# kubectl edit -n ingress cm ingress-nginx-controller 
data:
  allow-snippet-annotations: "true"
[root@master 8.10]# vim snippet.yaml 
apiVersion: apps/v1
kind: Deployment
metadata: 
  name: snippet
spec: 
  replicas: 1
  selector: 
    matchLabels: 
      app: snippet
  template: 
    metadata: 
      labels: 
        app: snippet
    spec: 
      containers: 
      - name: test
        image: myos:httpd
---
kind: Service
apiVersion: v1
metadata: 
  name: snippet
spec: 
  ports: 
  - name: 80-80
    port: 80
    targetPort: 80
    protocol: TCP
  selector: 
    app: snippet
  type: ClusterIP
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata: 
  name: snippet.zkbr.com
  annotations: 
    # 配置全局变量和地址重定向
    nginx.ingress.kubernetes.io/server-snippet: |
      set $agentflag 0;
      if ($http_user_agent ~* "(Firefox)") {
        set $agentflag 1;
      }
      if ($agentflag = 1){
        # 如果用户使用Firefox浏览器访问,那么会临时重定向到百度
        return 302 http://www.baidu.com;
        break;
      }
      if ($http_user_agent ~* "(chrome)") {
        set $agentflag 2;
      }
      if ($agentflag = 2){
        # 如果用户使用chrome浏览器访问,那么会临时重定向到京东
        return 302 http://www.jd.com;
        break;
      }
spec: 
  rules: 
  - host: snippet.zkbr.com
    http: 
      paths: 
      - path: /
        pathType: Prefix
        backend: 
          service: 
            name: snippet
            port: 
              number: 80
[root@master 8.10]# kubectl apply -f snippet.yaml

验证

# 添加解析记录
[root@master 8.10]# echo "192.168.10.12 snippet.zkbr.com" >> /etc/hosts
[root@master 8.10]# curl snippet.zkbr.com -H 'User-Agent: chrome' -I
HTTP/1.1 302 Moved Temporarily  # 使用的是302临时重定向
Date: Sun, 10 Aug 2025 09:35:43 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
Location: http://www.jd.com   # 被重定向到了京东

[root@master 8.10]# curl snippet.zkbr.com -H 'User-Agent: Firefox' -I
HTTP/1.1 302 Moved Temporarily  # 使用的是302临时重定向
Date: Sun, 10 Aug 2025 09:36:12 GMT
Content-Type: text/html
Content-Length: 138
Connection: keep-alive
Location: http://www.baidu.com # 被重定向到了百度

[root@master 8.10]# curl snippet.zkbr.com  -I
HTTP/1.1 200 OK    # 核心状态码:请求成功处理
Date: Sun, 10 Aug 2025 09:36:18 GMT     # 服务器处理时间
Content-Type: text/html; charset=UTF-8  # 响应体是 HTML 文本(UTF-8 编码)
Content-Length: 23         # 响应体大小为 23 字节
Connection: keep-alive     # 保持长连接
Last-Modified: Mon, 16 Jan 2023 04:21:54 GMT  # 资源最后修改时间
ETag: "17-5f259ec4c7c80"   # 资源唯一标识(用于缓存验证)
Accept-Ranges: bytes       # 服务器支持断点续传(按字节范围请求

1.11 Ingress-nginx 配置黑白名单

1.11.1 配置方案

  • Annotations:只对指定的ingress生效
  • ConfigMap:全局生效
  • 若是同时配置了Annotations和configmap,一般都是annotations 生效,configmap不生效,因为annotations优先级比configmap高

1.11.2 黑白名单概念

  • 白名单:仅允许指定 IP 地址(或 IP 段)访问后端服务,其他 IP 被拒绝。
  • 黑名单:拒绝指定 IP 地址(或 IP 段)访问,其他 IP 被允许。

1.11.3 配置方案建议

  • 黑名单建议使用ConfigMap去配置
  • 白名单建议使用Annotations去配置

1.11.4 Configmap 添加黑名单

[root@master 8.10]# kubectl edit -n ingress cm ingress-nginx-controller 
 data:
   allow-snippet-annotations: "true"
   # 添加黑名单
   block-cidrs: 192.168.10.12
   
# 用之前部署的ingress做实验
[root@master 8.10]# kubectl get ingress
NAME                CLASS   HOSTS               ADDRESS   PORTS     AGE
ingress-error       nginx   error.zkbr.com                80        30d
ingress-http-auth   nginx   auth.zkbr.com                 80, 443   32d
ingress-http-ssl    nginx   ssl.zkbr.com                  80, 443   33d
ingress-http-www1   nginx   www1.zkbr.com                 80        34d
ingress-http-www2   nginx   www2.zkbr.com                 80        34d
ingress-redirect    nginx   redirect.zkbr.com             80        32d
ingress-rewrite     nginx   rewrite.zkbr.com              80        31d
snippet.zkbr.com    nginx   snippet.zkbr.com              80        107m
[root@master 8.10]# echo "192.168.10.12 www1.zkbr.com" >> /etc/hosts
[root@master 8.10]# curl www1.zkbr.com
Welcome to The Apache.

# 用node01(192.168.10.11)访问,能访问
[root@node01 ~]#  echo "192.168.10.13 www1.zkbr.com" >> /etc/hosts
[root@node01 ~]# curl www1.zkbr.com
Welcome to The Apache.

# 用node03(192.168.10.13)访问,不能访问,权限被拒绝
[root@node03 ~]# echo "192.168.10.12 www1.zkbr.com" >> /etc/hosts
[root@node03 ~]# curl www1.zkbr.com
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

1.11.5 Annotations 添加白名单

[root@master 8.10]# vim white.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: white-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: white
  template:
    metadata:
      labels:
        app: white
    spec:
      containers:
      - image: myos:httpd
        name: myapp
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: white
  name: white-svc
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: white
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    # 配置白名单IP,这了就192.168.10.13一个IP
    nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.10.13
  name: white-zkbr-com
  labels:
    app: white
spec:
  rules:
  - host: white.zkbr.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: white-svc
            port:
              number: 80

[root@master 8.10]# kubectl apply -f white.yaml 
[root@master 8.10]# echo "192.168.10.12 white.zkbr.com" >> /etc/hosts
# 访问失败,因为我们配置了白名单,只能192.168.10.13能访问
[root@master 8.10]# curl white.zkbr.com
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

# 访问失败,因为我们配置了白名单,只能192.168.10.13能访问
[root@node01 ~]#  echo "192.168.10.12 white.zkbr.com" >> /etc/hosts
[root@node01 ~]#  curl white.zkbr.com
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

==========================================================
# 访问成功,因为node03的IP是192.168.10.13
# 同时我们也证明了一点,当configmap和Annotations同时配置的时候,configmap是不生效的,因为Annotations优先级高,即生效。
[root@node03 ~]#  echo "192.168.10.12 white.zkbr.com" >> /etc/hosts
[root@node03 ~]#  curl white.zkbr.com
Welcome to The Apache.

1.12 Ingress-nginx 金丝雀部署和灰度发布

在 Kubernetes(K8s)中,金丝雀部署(Canary Deployment)灰度发布(Gray Release) 是两种常用的渐进式发布策略,用于在生产环境中安全地验证新版本应用的稳定性。Ingress 作为 K8s 中管理外部流量入口的 API 对象,可通过 Ingress 控制器(如 Nginx Ingress、Traefik 等)的扩展能力实现这两种策略,核心是通过精细化的流量规则将部分流量导向新版本,逐步扩大范围直至全量切换。

1.12.1 核心概念

  • 金丝雀部署:通常基于流量比例(如 10%、30%、50%)将部分流量路由到新版本,验证无误后逐步提高比例,最终全量切换。
  • 灰度发布:更强调精准的用户 / 场景筛选(如按用户 ID、地域、浏览器类型等),仅让特定群体访问新版本,验证通过后分批扩大覆盖范围。

1.12.2 金丝雀部署示例:

这里我们是把业务web服务的apache改为nginx,企业中一般都是从v1版本升级到v2版本,思路是一样的。

[root@master 8.13]# vim 1.old_ingress.yaml 
---
# apache版本的Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-http
spec:
  replicas: 5
  selector:
    matchLabels:
      app: myapp-http
  template:
    metadata:
      labels:
        app: myapp-http
    spec:
      containers:
      - name: http
        image: myos:httpd
        ports:
        - containerPort: 80
---
# apache版本的Service
apiVersion: v1
kind: Service
metadata:
  name: myapp-http-svc
spec:
  selector:
    app: myapp-http
  ports:
  - port: 80
    targetPort: 80
---
# apache版本的ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: 
  name: myapp-http-ingress
spec: 
  rules: 
  - host: myapp-web.zkbr.com
    http: 
      paths: 
      - path: /
        pathType: Prefix
        backend: 
          service: 
            name: myapp-http-svc
            port: 
              number: 80
[root@master 8.13]# kubectl apply -f 1.old_ingress.yaml 
[root@master 8.13]# echo "192.168.10.12 myapp-web.zkbr.com" >> /etc/hosts
# 访问apache的ingress,不管怎么访问都是apache给的回应,因为我们还没部署nginx
[root@master 8.13]# curl myapp-web.zkbr.com
Welcome to The Apache.
[root@master 8.13]# curl myapp-web.zkbr.com
Welcome to The Apache.

=======================新版本Ingress====================
[root@master 8.13]# vim 2.new_ingress.yaml 
---
# nginx版本的Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-nginx
spec:
  replicas: 5
  selector:
    matchLabels:
      app: myapp-nginx
  template:
    metadata:
      labels:
        app: myapp-nginx
    spec:
      containers:
      - name: nginx
        image: myos:nginx
        ports:
        - containerPort: 80
---
# nginx版本的Service
apiVersion: v1
kind: Service
metadata:
  name: myapp-nginx-svc
spec:
  selector:
    app: myapp-nginx
  ports:
  - port: 80
    targetPort: 80
---
# 金丝雀Ingress(路由部分流量到nginx版本)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-canary-ingress
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"      # 声明为金丝雀Ingress
    nginx.ingress.kubernetes.io/canary-weight: "10" # 10%流量到nginx版本(0-100之间)
spec:
  rules:
  - host: myapp-web.zkbr.com  # 与apache的Ingress同域名,共享流量规则
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-nginx-svc  # 金丝雀流量到nginx版本
            port:
              number: 80
[root@master 8.13]# kubectl apply -f 2.new_ingress.yaml 
[root@master 8.13]# kubectl get ingress
NAME                   CLASS   HOSTS                ADDRESS   PORTS     AGE
myapp-canary-ingress   nginx   myapp-web.zkbr.com             80        18m
myapp-http-ingress     nginx   myapp-web.zkbr.com             80        25m

1.12.3 验证金丝雀部署:

# 我们使用脚本来验证
[root@master 8.13]# for i in {1..100};do curl myapp-web.zkbr.com >> sum;done
# 10% 的请求会被路由到nginx,90% 到apache;
[root@master 8.13]# cat sum | sort | uniq -c
     9 Nginx is running !
     91 Welcome to The Apache.
     
# 调整:若 nginx版本 稳定,可逐步将canary-weight从 10→30→50→100,最终删除主 Ingress 完成全量切换。
# 把canary-weight的值设置为50
[root@master 8.13]# kubectl edit ingress myapp-canary-ingress 

在这里插入图片描述

[root@master 8.13]# for i in {1..100};do curl myapp-web.zkbr.com >> sum;done^C
# 50% 的请求会被路由到nginx,50% 到apache
[root@master 8.13]# cat sum | sort | uniq -c
     57 Nginx is running !
     43 Welcome to The Apache.
Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐