Ingress
1. 简介
外部网络访问K8s集群上Service的统一网关入口。 由Ingress所定义的规则来控制流量路由。 暴露Service的类型有两种:
方式 | 优点 | 缺点 |
---|---|---|
NodePort | 简单直接、暴露端口即可 | 占用节点端口,依赖节点等 |
LoadBalancer | 占用节点端口,高可用(节点故障服务IP可漂移) | 需要单独配置LB插件(metaLB), 非公有云的LB网段需与节点相同 一个Service对一个LB等等 |
2. Ingress原理
说明:
- Ingress支持7层网络代理,也就是Ingress除了http还支持域名和https对外暴露服务
- Ingress负责反代规则(哪个域名对应哪个service)
- 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:31822 和 https://120.26.130.121:31366/, 都会直接访问到ingress-nginx-controller上面去:
4. Ingress实操
4.1 域名访问
使用两个服务:hello-server和nginx-demo, 访问hello.rocket.com代理hello-server服务,访问demo.rocket.com代理nginx-demo,整个网络设计如下: 编写两个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:
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会发现
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错误: