Skip to content

Ingress

1. 简介

外部网络访问K8s集群上Service的统一网关入口。 由Ingress所定义的规则来控制流量路由。
Alt text 暴露Service的类型有两种:

方式优点缺点
NodePort简单直接、暴露端口即可占用节点端口,依赖节点等
LoadBalancer占用节点端口,高可用(节点故障服务IP可漂移)需要单独配置LB插件(metaLB),
非公有云的LB网段需与节点相同
一个Service对一个LB等等

2. Ingress原理

Alt text 说明:

  1. Ingress支持7层网络代理,也就是Ingress除了http还支持域名和https对外暴露服务
  2. Ingress负责反代规则(哪个域名对应哪个service)
  3. Ingress controller负责读取Ingress规则将请求转发至合适的Pod,并可动态感知Ingress规则变化

3. 安装Ingress Controller

Ingress是在K8s中内置的,而Ingress控制器有很多不同厂家的实现,可以使用官网维护的Nginx Ingress,下载ingress-nginx:

sh
[root@node101 ~]# wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.1/deploy/static/provider/cloud/deploy.yaml -O ingress-nginx.yml
--2025-08-17 23:04:05--  https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.13.1/deploy/static/provider/cloud/deploy.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.109.133, 185.199.108.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16384 (16K) [text/plain]
Saving to: ‘ingress-nginx.yml’

ingress-nginx.yml                                 100%[=============================================================================================================>]  16.00K  24.9KB/s    in 0.6s    

2025-08-17 23:04:07 (24.9 KB/s) - ‘ingress-nginx.yml’ saved [16384/16384]

[root@node101 ~]# ls
alpine-pod.yaml  calico.yaml.bak  k8s-dashboard.yaml  kubernetes-dashboard.yaml  nginx-deployment.yaml
calico.yaml      hello-test.yml   ingress-nginx.yml                kubeadm.yaml        multi-pod.yml              update-kube-cert

修改镜像地址:

sh
[root@node101 ~]# vim ingress-nginx.yml
## 修改446行、549行、605行的镜像地址,并去掉后面sha校验
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/ingress-nginx/controller:v1.13.1
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/registry.k8s.io/ingress-nginx/kube-webhook-certgen:v1.6.1
## 修改392行控制器类型 kind: Deployment改为DaemonSet,因为ingress控制器每个节点至多只需要部署一个就可以了
kind: DaemonSet
## 修改410行strategy
updateStrategy: 
## 修改366行Service类型
type: NodePort

执行Ingress控制器的部署:

sh
[root@node101 ~]# kubectl apply -f ingress-nginx.yml 
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created

执行结果:

sh
[root@node101 ~]# kubectl get pod -A
NAMESPACE              NAME                                                    READY   STATUS              RESTARTS      AGE
ingress-nginx          ingress-nginx-admission-create-qg9ll                    0/1     Completed           0             7s
ingress-nginx          ingress-nginx-admission-patch-btblx                     0/1     Completed           0             7s
ingress-nginx          ingress-nginx-controller-69cb95db94-kp72r               0/1     ContainerCreating   0             7s
## 随后真正运行的是一个Pod
[root@node101 ~]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
ingress-nginx-controller-69cb95db94-kp72r   1/1     Running   0          90s
## 查看服务情况
[root@node101 ~]# kubectl get svc -n ingress-nginx 
NAME                                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller             NodePort    10.107.45.123    <none>        80:31822/TCP,443:31366/TCP   2d17h
ingress-nginx-controller-admission   ClusterIP   10.109.244.186   <none>        443/TCP                      2d17h

分别访问http://120.26.130.121:31822https://120.26.130.121:31366/, 都会直接访问到ingress-nginx-controller上面去:
alt text

4. Ingress实操

4.1 域名访问

使用两个服务:hello-server和nginx-demo, 访问hello.rocket.com代理hello-server服务,访问demo.rocket.com代理nginx-demo,整个网络设计如下: alt text 编写两个Service和Deployment的配置如下:

yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-nginx
  labels:
    app: hello-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello-nginx
  template:
    metadata:
      name: hello-nginx
      labels:
        app: hello-nginx
    spec:
      containers:
        - name: hello-nginx
          image: docker.io/library/nginx:1.21.5
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-demo
  labels:
    app: nginx-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx-demo
  template:
    metadata:
      name: nginx-demo
      labels:
        app: nginx-demo
    spec:
      containers:
        - name: nginx-demo
          image: docker.io/library/nginx:1.21.5
          imagePullPolicy: IfNotPresent
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: hello-nginx
  name: hello-nginx
spec:
  selector:
    app: hello-nginx
  ports:
    - port: 8000
      protocol: TCP
      targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: nginx-demo
  name: nginx-demo
spec:
  selector:
    app: nginx-demo
  ports:
    - port: 8000
      protocol: TCP
      targetPort: 80

执行应用部署:

sh
[root@node101 ~]# kubectl apply -f hello-nginx.yml 
deployment.apps/hello-nginx created
deployment.apps/nginx-demo created
service/hello-nginx created
service/nginx-demo created
## 修改hello-nginx和nginx-demo中的首页,便于后续测试区分:
[root@node101 ~]# kubectl get pod 
NAME                           READY   STATUS    RESTARTS   AGE
hello-nginx-6fd94744c8-dft7z   1/1     Running   0          10m
hello-nginx-6fd94744c8-jrjs9   1/1     Running   0          10m
nginx-demo-b64497749-wrmbd     1/1     Running   0          10m
nginx-demo-b64497749-z8rmm     1/1     Running   0          10m
[root@node101 ~]# kubectl exec -it hello-nginx-6fd94744c8-dft7z -- /bin/bash
[root@node101 ~]# echo "<html><html><head><title>index</title></head><body><h2>hello-nginx</h2></body></html>" > /usr/share/nginx/html/index.html
[root@node101 ~]# kubectl exec -it hello-nginx-6fd94744c8-jrjs9 -- /bin/bash
[root@node101 ~]# echo "<html><html><head><title>index</title></head><body><h2>hello-nginx</h2></body></html>" > /usr/share/nginx/html/index.html
[root@node101 ~]# kubectl exec -it nginx-demo-b64497749-wrmbd -- /bin/bash
[root@node101 ~]# echo "<html><html><head><title>index</title></head><body><h2>nginx-demo</h2></body></html>" > /usr/share/nginx/html/index.html
[root@node101 ~]# kubectl exec -it nginx-demo-b64497749-z8rmm -- /bin/bash
[root@node101 ~]# echo "<html><html><head><title>index</title></head><body><h2>nginx-demo</h2></body></html>" > /usr/share/nginx/html/index.html

编写路由规则yml如下:

yml
apiVersion: networking.k8s.io/v1
kind: Ingress  # 转发规则类型
metadata:
  name: ingress-host-rule
spec:
  ingressClassName: nginx
  rules:
    - host: "hello.tuanzi.com"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: hello-nginx
                port:
                  number: 8000
    - host: "demo.tuanzi.com"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: nginx-demo
                port:
                  number: 8000

执行应用规则:

sh
[root@node101 ~]# kubectl apply -f ingress-rule.yml
ingress.networking.k8s.io/ingress-host-rule configured

修改本地windows的host文件,做域名映射:

ini
120.26.130.121 demo.tuanzi.com
120.26.130.121 hello.tuanzi.com

访问demo.tuanzi.com和hello.tuanzi.com会发现被路由正确指向了我们的service:
alt text

4.2 路径重写

参考ingress-nginx官网文档,使用annotations配置项:

yml
apiVersion: networking.k8s.io/v1
kind: Ingress  # 转发规则类型
metadata:
  name: ingress-host-rule
  ## 添加url重写
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  ingressClassName: nginx
  rules:
    - host: "hello.tuanzi.com"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: hello-nginx
                port:
                  number: 8000
    - host: "demo.tuanzi.com"
      http:
        paths:
          ## 表示api会被去掉,缩短url长度
          - path: /api(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: nginx-demo
                port:
                  number: 8000

应用路由规则:

sh
[root@node101 ~]# kubectl apply -f ingress-rule.yml 
ingress.networking.k8s.io/ingress-host-rule configured

访问demo.tuanzi.com:31822/api和demo.tuanzi.com:31822/aa会发现 alt text

4.3 流量限制

更改ingress-rule.yml文件:

yml
apiVersion: networking.k8s.io/v1
kind: Ingress  # 转发规则类型
metadata:
  name: ingress-host-rule
  ## 添加url重写
  annotations:
    nginx.ingress.kubernetes.io/limit-rps: "1"
spec:
  ingressClassName: nginx
  rules:
    - host: "demo.tuanzi.com"
      http:
        paths:
          - path: /
            pathType: Exact  # 使用精确模式
            backend:
              service:
                name: hello-nginx
                port:
                  number: 8000

配置文件中限制每秒请求为1秒一次,超过请求频率就会返回503错误:
alt text