一、负载均衡器
负载均衡器有两类,区别在于 四层网络 和 七层网络 的支持,传输层在第四层,这层协议有 TCP/UDP/TCP SSL 等,而七层有 HTTP/HTTPS。
1. 基于 LVS 的 HTTPS 负载均衡
基于 LVS 的 HTTPS 负载均衡 是 典型的四层代理架构。客户端发出请求,经过LVS直接转发到服务器,然后服务器返回结果,从请求的发出到结果的响应,中间仅仅产生一次完整的TCP连接。
2. 基于 Nginx 的 HTTPS 负载均衡
基于 Nginx 的 HTTPS 负载均衡是一种基于七层网络代理架构的实现。客户端发出 https 请求,请求到达nginx服务器,nginx 重新生成一个新的 http 请求发到真实的服务器,服务器计算结果后发往 nginx,nginx再将结果以 https 的方式返回给客户端。从请求的发出到结果的响应,中间产生了两次请求。
二、Ingress简介
1. Ingress 介绍
Ingress 是从 Kubernetes 集群外部访问集群内部服务的入口,同时为集群内的 Service 提供七层负载均衡能力。它提供了 HTTP 和 HTTPS 路由功能,使外部流量能够访问集群内部的服务。通过定义 Ingress 资源,可以控制哪些外部请求能够访问集群中的哪些服务,以及如何路由这些请求。
具体架构图如下:
我们做网站时,使用 Nginx 做 Web 服务器,会使用一个子域名绑定一个网站,a.xxx.com
绑定 A 网站,b.xxx.com
绑定 B 网站,这样在一个域名的不同子域名可以访问不同的站点,对于现在的大多数互联网网站,依然会使用这种方法划分。
在微服务架构中,多个模块部署在不同的服务器上,则但是我们希望都通过 xxx.com
这个域名直接访问,就好像所有模块都在一起,让用户感觉只有一个网站。则可能会使用目录路径对模块进行划分,例如如果我们要实现 xxx.com/a
访问 A 模块,xxx.com/b
访问 B 模块,但对用户来说,一直在访问 xxx.com
这个域名。
这种需求,我们可以使用 nginx 进行反向代理,而在 Kubernetes 中,这种需求也是一模一样的。
首先,我们可以为 A、B、C 等应用,创建多个 Service,每个 Service 访问一个应用,然后使用 Ingress 配置路由规则,决定 URL 可以访问哪个 Service。
Ingress 公开了从集群外部到集群内服务的 HTTP 和 HTTPS 路由,Ingress 资源上定义的规则控制了路由。
Ingress 可以让集群中的多个 Service 能够从集群外访问,Ingress 还提供负载均衡、SSL/TLS 和基于名称的虚拟服务器等,Ingress 可以配置边缘路由器或其他前端工具来帮助处理网络流量,但是一般都是通自己的负载均衡器来实现。
Ingress 有两部分,一部分是 LoadBalancer ,提供统一入口,代理请求;另一部分是 Ingress 控制器,复制定义路由规则等。
如果不使用公有云平台的 LoadBalancer ,那么就自己搭建一个服务器,这台服务器加入到 Kubernetes 集群中,做流量入口,这台服务器网络接口必须够大,抗得住流量。
2. Ingress 与 Service
在前面,我们已经学习到了 Service,通过 Service 我们可以暴露一个端口到外网中,通过这个端口可以访问应用。
其中,有两种方法可以暴露 Service,可以让其被集群外部访问:
- 使用
Service.Type=LoadBalancer
- 使用
Service.Type=NodePort
Service 的访问方式是 IP,每次要将服务公开给外界时,都必须创建一个新的 LoadBalancer 并向云服务商获取一个公网 IP 地址。或者使用 NodePort
,但是只能在一台服务器上被访问,而且 Service 只能为一种 Pod 服务,暴露一个或多个端口,那么 N 个服务,就需要创建 N 个 Service。Service 虽然能够公开端口到外部网络中,但是无法将这些服务合并到一个 example.com/{服务}
中访问,Service 需要通过不同的端口访问。
如果你有一个 example.com
域名,你部署了多个 Web 服务,其中有两个子模块分别为课程(course)、考试(exam) 两个微服务,这些模块构成了一个培训网站。此时我们希望访问 example.com/api/course
能够访问课程学习模块,访问 example.com/api/exam
能够访问考试模块。显然,Service 是无法做到的。
使用 Ingress ,可以轻松设置路由规则,而且无需创建一堆 LoadBalancers/Nodes 公开每个服务,并且 Ingress 本身具有很多功能。
Ingress 也需要 Service 。
三、 安装 Ingress 控制器
Ingress 控制器有多种实现,其中 Kubernetes 官方有一个名为 Ingress-nginx 的实现,其它实现还有 Kong Ingress、Traefik、HAProxy Ingress 等。这里演示 使用 Helm 安装 Ingress-nginx 。
官方文档:https://kubernetes.github.io/ingress-nginx/deploy/#using-helm
1. 下载 Ingress-nginx 安装包
需要首先安装helm管理工具:https://georgechan95.github.io/blog/d8e3c7b3.html
ingress-nginx 的仓库在国外,国内下载需要vpn支持,参考:https://georgechan95.github.io/blog/7f174b3e.html
# 添加 ingress-nginx仓库
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
# 下载 ingress-nginx 安装包
helm pull ingress-nginx/ingress-nginx --version=4.8.3
2. 导入 Ingress-nginx 镜像
这些镜像是 ingress-nginx 启动时所需的镜像,由于国内的网络无法从国外下载镜像,因此需要提前把这些镜像下载好,导入到服务器中。
关于如何使用 Docker 拉取谷歌镜像,参考这篇博客:https://georgechan95.github.io/blog/b01d5c62.html
# 下载 ingress-nginx 需要的镜像
# 所有节点都需要导入这些镜像
docker pull registry.k8s.io/ingress-nginx/controller:v1.9.4
docker pull registry.k8s.io/defaultbackend-amd64:1.5
docker pull registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20231011-8b53cabe0
docker pull registry.k8s.io/ingress-nginx/opentelemetry:v20230721-3e2062ee5
3. 安装 Ingress-nginx
3.1 解压 Ingress-nginx 压缩包
# 安装包解压
$ tar -zxvf ingress-nginx-4.8.3.tgz
# 进入 ingress-nginx 解压后的目录
$ cd ingress-nginx
# 当前所在目录
$ pwd
/opt/k8s/10/ingress-nginx
# 查看 ingress-nginx 目录结构
$ tree .
.
├── CHANGELOG.md
├── Chart.yaml
├── .....
├── README.md.gotmpl
├── changelog
│ ├── Changelog-4.5.2.md
│ ├── .....
│ └── Changelog-4.8.3.md
├── changelog.md.gotmpl
├── ci
│ ├── controller-admission-tls-cert-manager-values.yaml
........
│ └── deployment-webhook-values.yaml
├── templates
│ ├── NOTES.txt
│ ├── admission-webhooks
│ │ ├── cert-manager.yaml
│ │ ├── job-patch
│ │ │ ├── clusterrole.yaml
│ │ │ ├── ......
│ │ │ └── serviceaccount.yaml
│ │ └── validating-webhook.yaml
│ ├── clusterrole.yaml
│ ├── .....
│ └── default-backend-serviceaccount.yaml
└── values.yaml
3.2 编辑 values.yaml
# 修改 values.yaml 文件
$ vim values.yaml
# 修改1:
# 修改如下内容:
controller
hostNetwork: true # 使用主机网路
dnsPolicy: ClusterFirstWithHostNet # Pod 的网络命名空间与主机共享,Pod 使用主机的网络栈
kind: DaemonSet # 每个节点部署一个 ingress-nginx-controller
ingressClassResource:
default: true # 使用默认的Inginx类,默认是 nginx
# 修改2:
#注释 digest 相关内容
controller
image:
#digest: sha256:xxxxx
#digestChroot: sha256:xxxxx
admissionWebhooks:
patch:
image:
#digest: sha256:xxxxx
将解压后的 ingress-nginx 目录内 values.yaml 文件中的 digest: sha256xxxx 所在的所有的行注释掉,避免因为下载镜像的指纹与文件要求不一致,无法运行
3.3 关于 dnsPolicy
ClusterFirstWithHostNet:
- 当 Pod 的
hostNetwork
设置为 true 时,使用该 DNS 策略。 - 这意味着 Pod 的网络命名空间与主机共享,Pod 使用主机的网络栈。
- 在此配置下,Pod 将首先尝试通过主机上的 DNS 解析 DNS 请求。如果主机上没有找到,则会将请求发送到 kube-dns 服务,由 kube-dns 服务进行处理。
- 这种策略适用于需要与主机网络共享的特殊情况,但它不会为 Pod 提供专用的 DNS 解析功能。
ClusterFirst:
- 这是 Kubernetes 中默认的 DNS 策略。
- 当 Pod 的
hostNetwork
设置为 false 或未设置时,使用该策略。 - 在此策略下,Pod 首先尝试通过 kube-dns 服务解析 DNS 请求。如果 kube-dns 无法解析,则会向上级 DNS 服务器继续发起请求。
- 这种策略适用于大多数情况,其中 Pod 需要使用 Kubernetes 集群的 DNS 服务解析其他 Pod 或服务的主机名。
3.4 安装 ingress-nginx
# 使用 Helm 安装 ingress-nginx
$ helm install ingress-nginx --namespace ingress-nginx --create-namespace .
# 查看 ingress-nginx release
$ helm list -n ingress-nginx
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
ingress-nginx ingress-nginx 1 2025-06-26 18:35:32.209570796 +0800 CST deployed ingress-nginx-4.8.3 1.9.4
# 查看 IngressClass
$ kubectl get ingressclass
NAME CONTROLLER PARAMETERS AGE
nginx k8s.io/ingress-nginx <none> 153m
# 查看 Service
$ kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.105.7.64 <pending> 80:32570/TCP,443:31991/TCP 117m
ingress-nginx-controller-admission ClusterIP 10.102.42.201 <none> 443/TCP 117m
# 查看 Pod
$ kubectl get pod -n ingress-nginx -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-controller-pf6sb 1/1 Running 0 117m 192.168.6.141 k8s-node02 <none> <none>
ingress-nginx-controller-qmb7h 1/1 Running 0 117m 192.168.6.140 k8s-node01 <none> <none>
# 查看 DaemonSet
$ kubectl get daemonset -n ingress-nginx -o wide
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
ingress-nginx-controller 2 2 2 2 2 kubernetes.io/os=linux 118m controller registry.k8s.io/ingress-nginx/controller:v1.9.4 app.kubernetes.io/component=controller,app.kubernetes.io/instance=ingress-nginx,app.kubernetes.io/name=ingress-nginx
4. 测试 Ingress-nginx
4.1 创建 Service 和 Deployment
httpproxy-dep-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: nginx:1.29.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: default
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
selector:
app: nginx
执行资源清单
$ kubectl apply -f httpproxy-dep-svc.yaml
查看资源
$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 59d <none>
nginx-svc ClusterIP 10.111.16.251 <none> 80/TCP 8s app=nginx
$ kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deploy 2/2 2 2 16s my-nginx nginx:1.29.0 app=nginx
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-6fc4ff86dc-n76xc 1/1 Running 0 22s 172.16.58.249 k8s-node02 <none> <none>
nginx-deploy-6fc4ff86dc-nlmw5 1/1 Running 0 22s 172.16.85.206 k8s-node01 <none> <none>
4.2 创建 Ingress
ingress.yaml
apiVersion: networking.k8s.io/v1 # 指定 API 版本
kind: Ingress # 指定资源类型为 Ingress,表示这是一个用于管理 HTTP/HTTPS 流量的 Kubernetes 资源
metadata:
name: ingress-httpproxy
namespace: default
spec:
ingressClassName: nginx # 指定此 Ingress 资源由名称为 nginx 的 IngressClass 处理,定义在 values.yaml 中 controller.ingressClassResource.name
rules: # 定义了流量路由的规则,即如何根据域名(host)和路径(path)将请求转发到后端服务。
- host: www.test-http-proxy.com # 指定此规则适用于请求的 HTTP 主机头(Host Header)为 www.test-http-proxy.com 的流量。客户端必须通过该域名访问, 如果省略 host,Ingress 会匹配所有域名(即通配规则)。
http: # 定义了 HTTP 协议的路由规则
paths: # 用于指定路径匹配规则
- path: / # 指定匹配的 URL 路径为 /,即根路径,这是最常见的路径,表示匹配所有以 / 开头的请求
pathType: Prefix # 定义路径匹配的类型为 Prefix,表示匹配以指定路径(/) 开头的所有请求
backend: # 定义请求的转发目标,即后端服务
service:
name: nginx-svc # 指定后端服务的名称为 nginx-svc.(必须存在于同一命名空间,或通过 <namespace>/<service-name> 跨命名空间引用)
port:
number: 80 # 指定目标 Service 的端口为 80
执行资源清单
$ curl http://www.test-http-proxy.com
查看资源
$ kubectl get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-httpproxy nginx www.test-http-proxy.com 80 18
4.3 修改主机 host 文件
修改host文件,将其中一台集群节点的IP,映射域名:www.test-http-proxy.com
4.4 浏览器访问域名
打开浏览器,访问 http://www.test-http-proxy.com:32570/ ,其中 32570 端口是在创建 ingress-nginx 时自动分配的物理端口,可以通过命令查看:
$ kubectl get service -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.105.7.64 <pending> 80:32570/TCP,443:31991/TCP 117m
ingress-nginx-controller-admission ClusterIP 10.102.42.201 <none> 443/TCP 117m
至此可以了解到通过使用 Ingress-Nginx 让外部流量能够访问集群内部的服务。
四、Ingress Nginx 使用
ingress的api版本历经过多次变化他们的配置项也不太一样分别是:
- extensions/v1beta1:1.16版本之前使用
- networking.k8s.io/v1beta1:1.19版本之前使用
- networking.k8s.io/v1:1.19版本之后使用
1. Ingress-nginx HTTP 代理
资源清单:ingress-nginx-http-proxy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: nginx:1.29.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80 # 指定容器监听的端口
protocol: TCP # 指定端口使用的协议,TCP 表示端口处理 TCP 流量,适合 nginx 的 HTTP 服务
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: default
spec:
ports:
- port: 80 # Service 对外暴露的端口号
targetPort: 80 # Service 将流量转发到的目标 Pod 的端口号
protocol: TCP
selector:
app: nginx # Service 将流量路由到带有标签 app=nginx 的 Pod
apiVersion: networking.k8s.io/v1 # 指定 API 版本
kind: Ingress # 指定资源类型为 Ingress,表示这是一个用于管理 HTTP/HTTPS 流量的 Kubernetes 资源
metadata:
name: ingress-httpproxy
namespace: default
spec:
ingressClassName: nginx # 指定此 Ingress 资源由名称为 nginx 的 IngressClass 处理,定义在 values.yaml 中 controller.ingressClassResource.name
rules: # 定义了流量路由的规则,即如何根据域名(host)和路径(path)将请求转发到后端服务。
- host: www.test-http-proxy.com # 指定此规则适用于请求的 HTTP 主机头(Host Header)为 www.test-http-proxy.com 的流量。客户端必须通过该域名访问, 如果省略 host,Ingress 会匹配所有域名(即通配规则)。
http: # 定义了 HTTP 协议的路由规则
paths: # 用于指定路径匹配规则
- path: / # 指定匹配的 URL 路径为 /,即根路径,这是最常见的路径,表示匹配所有以 / 开头的请求
pathType: Prefix # 定义路径匹配的类型为 Prefix,表示匹配以指定路径(/) 开头的所有请求
backend: # 定义请求的转发目标,即后端服务
service:
name: nginx-svc # 指定后端服务的名称为 nginx-svc.(必须存在于同一命名空间,或通过 <namespace>/<service-name> 跨命名空间引用)
port:
number: 80 # 指定目标 Service 的端口为 80
执行资源清单
$ kubectl apply -f ingress-nginx-http-proxy.yaml
deployment.apps/nginx-deploy created
service/nginx-svc created
ingress.networking.k8s.io/ingress-httpproxy created
查看部署资源
$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 59d <none>
nginx-svc ClusterIP 10.111.16.251 <none> 80/TCP 8s app=nginx
$ kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deploy 2/2 2 2 16s my-nginx nginx:1.29.0 app=nginx
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-6fc4ff86dc-n76xc 1/1 Running 0 22s 172.16.58.249 k8s-node02 <none> <none>
nginx-deploy-6fc4ff86dc-nlmw5 1/1 Running 0 22s 172.16.85.206 k8s-node01 <none> <none>
$ kubectl get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-httpproxy nginx www.test-http-proxy.com 80 18
修改主机 Host 文件
IP 可以是集群内部署了 Ingress-Controler 的任意一台服务器 IP
192.168.6.139 www.test-http-proxy.com
测试访问 HTTP
$ curl http://www.test-http-proxy.com:32570
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
2. Ingress-nginx HTTPS 代理
2.1 生成证书和私钥
# 1. 创建证书扩展文件
$ vim http.ext
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = www.https-proxy.com
IP.1 = 127.0.0.1
# 2. 创建证书
# 生成证书步骤1 : 生成 CSR(证书签名请求) 和 私钥文件 tls.key
openssl req -new -newkey rsa:2048 -sha256 -nodes -out tls.csr -keyout tls.key -subj "/C=CN/ST=Beijing/L=Beijing/O=Super Inc./OU=Web Security/CN=www.https-proxy.com"
# 生成证书步骤2 : 生成证书tls.crt,并指定证书扩展文件
openssl x509 -req -days 365 -in tls.csr -signkey tls.key -out tls.crt -extfile http.ext -extensions v3_req
# 查看生成的证书文件
$ ls
http.ext tls.crt tls.csr tls.key
# 3. 将证书和私钥存储到 Secret
$ kubectl create secret tls ingress-nginx-tls --key tls.key --cert tls.crt
查看证书 Secret
# 查看 Secret $ kubectl get secret ingress-nginx-tls -n default NAME TYPE DATA AGE ingress-nginx-tls kubernetes.io/tls 2 22s # 查看 Secret 详情 $ kubectl describe secret ingress-nginx-tls -n default Name: ingress-nginx-tls Namespace: default Labels: <none> Annotations: <none> Type: kubernetes.io/tls Data ==== tls.crt: 1436 bytes tls.key: 1708 bytes # 查看 Secret 数据 $ kubectl get secret ingress-nginx-tls -n default -o yaml apiVersion: v1 data: tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQrRENDQXVDZ0F3SUJBZ0lVWk9iZ3V4cUR5bTlVWk1XUDROMEdnR3pTZkw4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd2V6RUxNQWtHQTFVRUJoTUNRMDR4RURBT0JnTlZCQWdNQjBKbGFXcHBibWN4RURBT0JnTlZCQWNNQjBKbAphV3BwYm1jeEV6QVJCZ05WQkFvTUNsTjFjR1Z5SUVsdVl5NHhGVEFUQmdOVkJBc01ERmRsWWlCVFpXTjFjbWwwCmVURWNNQm9HQTFVRUF3d1RkM2QzTG1oMGRIQnpMWEJ5YjNoNUxtTnZiVEFlRncweU5UQTJNamN3TXpBeE1qWmEKRncweU5qQTJNamN3TXpBeE1qWmFNSHN4Q3pBSkJnTlZCQVlUQWtOT01SQXdEZ1lEVlFRSURBZENaV2xxYVc1bgpNUkF3RGdZRFZRUUhEQWRDWldscWFXNW5NUk13RVFZRFZRUUtEQXBUZFhCbGNpQkpibU11TVJVd0V3WURWUVFMCkRBeFhaV0lnVTJWamRYSnBkSGt4SERBYUJnTlZCQU1NRTNkM2R5NW9kSFJ3Y3kxd2NtOTRlUzVqYjIwd2dnRWkKTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDUVJkTE1TZGpNdHQ2NzVPclVhbmNRNTN5eQpTZitEYVZ2Q2xPdjlGNDRkbG1GSFlrVVZXRW9VQkNIRzdCM1pBb0pRWGFpaEJRbUl5UTNJV0o2ODhsWVpEOU1XClgzU212MGp3Q1A0SVcxaTYyVHBwb0JVRHhlNlI3SHhBQXJXeG9pMzV6Q1lFVVRoZzY3OExhWDRma04xR0pYY3AKaERqZ1FFZ3NqTmVwdGNGRVBLaUxicTNhNVlkRWdpTmpVTnh3dWpKY1RFYllkMXgwUFh5V1lYVDNDV29Fd3JUZQozcU0zWUxTdThjRXdIT21VUW13Rzhvc1p4c2lLeXZjN2MwK3JWWUpqeXR1MFJDRVRjY3Njb2hhSWpqT25xaTN0ClVhd0tKbG9Fa3M5Y2dCb05BSzFodXRDRk9UbzJMY3VZSjA1akhSdy84VXI4RG4rc0w4cGFFSWNqZ2VqOUFnTUIKQUFHamREQnlNQWtHQTFVZEV3UUNNQUF3Q3dZRFZSMFBCQVFEQWdYZ01CTUdBMVVkSlFRTU1Bb0dDQ3NHQVFVRgpCd01CTUNRR0ExVWRFUVFkTUJ1Q0UzZDNkeTVvZEhSd2N5MXdjbTk0ZVM1amIyMkhCSDhBQUFFd0hRWURWUjBPCkJCWUVGTU9jdUNxSTVpL3kwazBtSDVWeFFNaEdhRTA0TUEwR0NTcUdTSWIzRFFFQkN3VUFBNElCQVFBeHZ5LzUKWGE1TjRxc3B4WS9rN0NPSTZoT2VBTitqaGF1SWVMeUkrb1UvczkzVnVLTkRrQ0ErakEyRHRWQmhtQ0xrVUdnbQo1enN5MkJHTndZZW4zV05mTXZZUmQ1ZFhjK3ZzUVNaV2VROWwwZ3FKaTdTeEQwaDJZa3BOUlJVcy84RXRSOUJFCmFKSmNkYTV1dlVwT2VFQ3JrWVhGRnIvK09yZW9Mdi9MV3dtK3VLRytLd204YUU1V3Z6czM0SUlqM1pOMlk1ZVQKVDh3dVhhOVJqbU1mRldaaDA4UHJUd3RXT1R1cW5TQUZ3Z2tpeTBab0RtNFd5amlUNmluZWpzTlpSa2ZCcW5ieQpwQVN0eGlmUWk4S2hRNVUzOEhkUVMzYnpNdnFiS2g3ZlZoamh4Si8wNVBQVHE0NGU3eG56dnlEazFUaC9vWnZ0CjJLdUZuVVkxLzlMayt1U1cKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2d0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktrd2dnU2xBZ0VBQW9JQkFRQ1FSZExNU2RqTXR0NjcKNU9yVWFuY1E1M3l5U2YrRGFWdkNsT3Y5RjQ0ZGxtRkhZa1VWV0VvVUJDSEc3QjNaQW9KUVhhaWhCUW1JeVEzSQpXSjY4OGxZWkQ5TVdYM1NtdjBqd0NQNElXMWk2MlRwcG9CVUR4ZTZSN0h4QUFyV3hvaTM1ekNZRVVUaGc2NzhMCmFYNGZrTjFHSlhjcGhEamdRRWdzak5lcHRjRkVQS2lMYnEzYTVZZEVnaU5qVU54d3VqSmNURWJZZDF4MFBYeVcKWVhUM0NXb0V3clRlM3FNM1lMU3U4Y0V3SE9tVVFtd0c4b3NaeHNpS3l2YzdjMCtyVllKanl0dTBSQ0VUY2NzYwpvaGFJampPbnFpM3RVYXdLSmxvRWtzOWNnQm9OQUsxaHV0Q0ZPVG8yTGN1WUowNWpIUncvOFVyOERuK3NMOHBhCkVJY2pnZWo5QWdNQkFBRUNnZ0VBQm1OOUpldzRPWS9OMWFxdSs3M2FMTDYweVhnQzVLTm4rNDl1S0NIZ3BSbEUKRUszcFFCSE40cUhiTldIcElYTmR2aExPVlR1eDlDTnVaT1V6RHZhNU9YaTNWaVNKelJvbjJwbnFBVE02L3VLQQpnUmhrWXl0NE9NWFhnUVhOc2hmQkt2QmFGNTRFSGR0RlNyWCt3OXJvU0MzL3RKcmFZajNKSkdYajVVRTdRQnI4CkxZemUvaXp0TVAyeENMSytwL3hJa1JpRVRaVmRubmtaM2FEY3JtcGlmOGRUcGZMbDVYUlRTNWtvbitXMmdybkUKdFd3L3lsWUVzcHo2c1BPRWV0bDNWK3VNYVlsOW9sTEZtQ1M1NUJxQjRid05zSHQyMDdzRmQ2SmdmRFdpZE9yUwpOSWdqRXMxOVphSU9VZitRN254VkQrNGNWaVFJbHhJc21CVGNONjRlOFFLQmdRRERSQmJzdWs3aHQ4MDRwR2wzCnN3M2Q5NndDZHZyOEVtdU41ZDdScEtudG5RdkQvaVJjTS9nNGZlU2czQ1lTbUpCSFNwUDFmZE0wODZBTXBIbzMKcmw2RGtZZ2diUGM4QndHZGp2NDJUdmFYUkQ1T2tnSjlPcDUreHZLMFpmZWJVeERlT3k2SmhNNFFJck5GZVF1dgpCZ0lJSUlSRTJzOTdlak1FclNPQ21CSlNjUUtCZ1FDOUpXOTYwVjIxdkk2L2lBUzZ5eitlSytJaVRxYjh3TUxwCjZjTWR0UEhTdy9URkJ0RVFpSGJvYTUwZER5YVh5TXR4dUpvamNLUXN5ZzdZWlFxQnpheEkwZEIvR0dqRzNlM1oKNjYwQXVXZ0pSN0VOYit3N2pDdjVGa0NWTEg1MEcxbXM2RjlBRXk0ajlOOStuSDlOTEtzbHZmcmNYbFIvY09HeQp6Q29adjdWdFRRS0JnUUNaYkJWckdSUERqQ3dsOWlDY0dVYXJBZC9YNis1V1FvN1paaVRGcWRDT1R4ZWdmajNKCmFGZis0d1BSVkVoaDBoZUN2RmsyeVE4N0NyVFZXaUpoUDVNcFl4NkhBN2JhSmxNaG5lbWxlRE9PTk9PVHptdEEKUTkrbWt1QzkxMlJPV1Z6bWo2K0lBNTM0MVpydjJpVFE5ekovZWpVUytLMlBRanQxMENnWGd5N2FNUUtCZ1FDMQpFdVdLV215djB2ZUZmSjJxaFhFOTV4enhZd0tSN2FlcmIxS1BXZTQzcThqajVnYTNJUzFVaTlFNVJJdlp1eXlvCmplVmlFQy9iZ1FSOVBSMjE3a1FFNG5nTGRENjZRek8wNzk0TFYzTzFqcUI5RUt6Q3hRcER4MzNFVVhndGh4RnUKYW5ibFRIZGJqTTE0MURFNm5JeXI4UmY3WjRMVkRpZkRsNWltVmRWRjhRS0JnUUNnTlB6enkrQUJtVHFLVytXbAoxb0lzUlJlQjdDd1pxUjNUZ0FBaXdKOEpRTFdoREdiQzdJQ0FLVlZkNGZjeUtXVlovRWIrK3RZdUc5ZUpWUkY4CldzU2J1Y0phcktBN1k4UDUydDVtWUp6ZkZjb0hLNXVSVFlOVElFM2w4YmhnSmxqaVJPTER1a2N6cEhVdkJLZkYKYVg4UjNtR3hhZFJ4U25TZUhiN2QvNUFaVlE9PQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg== kind: Secret metadata: creationTimestamp: "2025-06-27T03:10:37Z" name: ingress-nginx-tls namespace: default resourceVersion: "13338253" uid: fffb5d77-97c4-4237-8be9-a487d96dbf34 type: kubernetes.io/tls
2.2 创建资源清单
资源清单:ingress-nginx-https-proxy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx-https
template:
metadata:
labels:
app: nginx-https
spec:
containers:
- name: my-nginx
image: nginx:1.29.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80 # 指定容器监听的端口
protocol: TCP # 指定端口使用的协议,TCP 表示端口处理 TCP 流量,适合 nginx 的 HTTP 服务
apiVersion: v1
kind: Service
metadata:
name: nginx-https-svc
namespace: default
spec:
ports:
- port: 80 # Service 对外暴露的端口号
targetPort: 80 # Service 将流量转发到的目标 Pod 的端口号
protocol: TCP
selector:
app: nginx-https # Service 将流量路由到带有标签 app=nginx-https 的 Pod
apiVersion: networking.k8s.io/v1 # 指定 API 版本
kind: Ingress # 指定资源类型为 Ingress,表示这是一个用于管理 HTTP/HTTPS 流量的 Kubernetes 资源
metadata:
name: ingress-https-proxy
namespace: default
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true" # HTTP 重定向为HTTPS, true表示强制重定向
spec:
ingressClassName: nginx # 指定此 Ingress 资源由名称为 nginx 的 IngressClass 处理,定义在 values.yaml 中 controller.ingressClassResource.name
rules: # 定义了流量路由的规则,即如何根据域名(host)和路径(path)将请求转发到后端服务。
- host: www.https-proxy.com # 指定此规则适用于请求的 HTTP 主机头(Host Header)为 www.www.https-proxy.com 的流量。客户端必须通过该域名访问, 如果省略 host,Ingress 会匹配所有域名(即通配规则)。
http: # 定义了 HTTP 协议的路由规则
paths: # 用于指定路径匹配规则
- path: / # 指定匹配的 URL 路径为 /,即根路径,这是最常见的路径,表示匹配所有以 / 开头的请求
pathType: Prefix # 定义路径匹配的类型为 Prefix,表示匹配以指定路径(/) 开头的所有请求
backend: # 定义请求的转发目标,即后端服务
service:
name: nginx-https-svc # 指定后端服务的名称为 nginx-https-svc.(必须存在于同一命名空间,或通过 <namespace>/<service-name> 跨命名空间引用)
port:
number: 80 # 指定目标 Service 的端口为 80
tls:
- hosts:
- www.https-proxy.com # 指定域名
secretName: ingress-nginx-tls # 证书和私钥保存的 Secret
可以看到Ingress添加TLS配置也非常简单,只需要在 spec下添加一个 tls 字段即可:
- hosts:证书所授权的域名列表
- secretName:证书的 Secret 名字
- ingressClassName: ingress class 的名字,1.22+需要配置
执行资源清单
$ kubectl apply -f ingress-nginx-https-proxy.yaml
deployment.apps/nginx-deploy created
service/nginx-https-svc created
ingress.networking.k8s.io/ingress-https-proxy created
查看部署资源
$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 59d <none>
nginx-https-svc ClusterIP 10.99.219.148 <none> 80/TCP 96s app=nginx-https
$ kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deploy 2/2 2 2 8s my-nginx nginx:1.29.0 app=nginx-https
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-7d6bd7f587-47kqv 1/1 Running 0 21s 172.16.85.213 k8s-node01 <none> <none>
nginx-deploy-7d6bd7f587-92hhz 1/1 Running 0 21s 172.16.58.233 k8s-node02 <none> <none>
$ kubectl get ingress -o wide
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress-https-proxy nginx www.https-proxy.com 80, 443 2m57s
修改主机 Host 文件
IP 可以是集群内部署了 Ingress-Controler 的任意一台服务器 IP
192.168.6.139 www.https-proxy.com
测试访问 HTTPS访问
端口号通过命令:kubectl get svc -n ingress-nginx 查看 443 映射端口
# 用命令行测试 https 请求,其中 -k 表示忽略自签名证书警告
$ curl -k https://www.https-proxy.com:31991/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
需要将自签发的 tls.crt 证书导入到浏览器中,否则会有 “不安全” 的告警提示
如果在ingress中设置tls,即默认的http会被强制重定向到https,http即不可访问,如果需要http与https同时可以使用可以设置
- nginx.ingress.kubernetes.io/ssl-redirect: “false” :禁用强制重定向,这样可以同时使用http与https
3. Ingress-nginx BasicAuth 代理
有些网站可能需要通过密码来访问,对于这类网站可以使用 Nginx 的 basic-auth 设置密码访 问,具体方法如下,由于需要使用 htpasswd 工具,所以需要安装httpd。
# 安装 htpasswd 工具
$ dnf -y install httpd-tools
# 使用 htpasswd 命令创建一个新的基本认证密码文件 auth,并为用户 george 设置密码。
$ htpasswd -c auth george
New password:
Re-type new password:
Adding password for user george
# 创建一个 Kubernetes Secret 资源,类型为 generic,用于存储基本认证的密码文件 auth,以便在 Ingress 或 Nginx 中启用 HTTP 基本认证。
$ kubectl create secret generic ingress-basic-auth --from-file=auth
查看 Secret
$ kubectl get secret ingress-basic-auth -o yaml apiVersion: v1 data: auth: Z2VvcmdlOiRhcHIxJEpoZFB6aVNPJDVXcjhqTDYyQll5Nm5aa3ZHWlB3ejAK kind: Secret metadata: creationTimestamp: "2025-06-27T06:12:07Z" name: ingress-basic-auth namespace: default resourceVersion: "13361989" uid: 9550e4af-4a83-48d7-9b40-fc207303a192 type: Opaque
创建包含密码认证的Ingress:
- nginx.ingress.kubernetes.io/auth-type:认证类型,可以是 basic 和 digest
- nginx.ingress.kubernetes.io/auth-secret:密码文件的 Secret 名称
- nginx.ingress.kubernetes.io/auth-realm:需要密码认证的消息提醒
资源清单
ingress-nginx-basic-auth.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: nginx:1.29.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80 # 指定容器监听的端口
protocol: TCP # 指定端口使用的协议,TCP 表示端口处理 TCP 流量,适合 nginx 的 HTTP 服务
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: default
spec:
ports:
- port: 80 # Service 对外暴露的端口号
targetPort: 80 # Service 将流量转发到的目标 Pod 的端口号
protocol: TCP
selector:
app: nginx # Service 将流量路由到带有标签 app=nginx 的 Pod
apiVersion: networking.k8s.io/v1 # 指定 API 版本
kind: Ingress # 指定资源类型为 Ingress,表示这是一个用于管理 HTTP/HTTPS 流量的 Kubernetes 资源
metadata:
name: ingress-basic-auth
namespace: default
annotations:
nginx.ingress.kubernetes.io/auth-type: basic # 认证类型
nginx.ingress.kubernetes.io/auth-secret: ingress-basic-auth # 密码文件的 Secret 名称
nginx.ingress.kubernetes.io/auth-realm: '请输入用户名和密码:' # 需要密码认证的消息提醒
spec:
ingressClassName: nginx # 指定此 Ingress 资源由名称为 nginx 的 IngressClass 处理,定义在 values.yaml 中 controller.ingressClassResource.name
rules: # 定义了流量路由的规则,即如何根据域名(host)和路径(path)将请求转发到后端服务。
- host: auth.basic.com # 指定此规则适用于请求的 HTTP 主机头(Host Header)为 auth.basic.com 的流量。
http: # 定义了 HTTP 协议的路由规则
paths: # 用于指定路径匹配规则
- path: / # 指定匹配的 URL 路径为 /,即根路径,这是最常见的路径,表示匹配所有以 / 开头的请求
pathType: ImplementationSpecific # 表示路径匹配行为由 Ingress 控制器定义,对于 nginx Ingress 控制器,ImplementationSpecific 通常等同于 Prefix,即匹配以指定路径开头的请求。
backend: # 定义请求的转发目标,即后端服务
service:
name: nginx-svc # 指定后端服务的名称为 nginx-svc.(必须存在于同一命名空间,或通过 <namespace>/<service-name> 跨命名空间引用)
port:
number: 80 # 指定目标 Service 的端口为 80
执行资源清单
$ kubectl apply -f ingress-nginx-basic-auth.yaml
修改主机 Host 文件
IP 可以是集群内部署了 Ingress-Controler 的任意一台服务器 IP
192.168.6.139 auth.basic.com
浏览器访问测试
4. Ingress-nginx 域名重定向
在 Nginx 作为代理服务器时,Redirect 可用于域名的重定向,比如访问 old.com 被重定向到 new.com。Ingress 可以更简单的实现 Redirect 功能,接下来用 ingress-redirect.com 作为旧域名, www.baidu.com 作为新域名进行演示:
相关配置项:
- permanent-redirect:重定向到的域名
- permanent-redirect-code:重定向代码,不配置默认301(永久重定向,如有其他原因可自行配置)
资源清单:ingress-nginx-redirect.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: my-nginx
image: nginx:1.29.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80 # 指定容器监听的端口
protocol: TCP # 指定端口使用的协议,TCP 表示端口处理 TCP 流量,适合 nginx 的 HTTP 服务
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
namespace: default
spec:
ports:
- port: 80 # Service 对外暴露的端口号
targetPort: 80 # Service 将流量转发到的目标 Pod 的端口号
protocol: TCP
selector:
app: nginx # Service 将流量路由到带有标签 app=nginx-https 的 Pod
apiVersion: networking.k8s.io/v1 # 指定 API 版本
kind: Ingress # 指定资源类型为 Ingress,表示这是一个用于管理 HTTP/HTTPS 流量的 Kubernetes 资源
metadata:
name: ingress-redirect
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx" # 指定使用的Ingress控制器类名,与 ingressClassName 作用相同
nginx.ingress.kubernetes.io/permanent-redirect: https://www.baidu.com # 永久重定向网址
nginx.ingress.kubernetes.io/permanent-redirect-code: '301' # 永久重定向状态码
spec:
ingressClassName: nginx # 指定此 Ingress 资源由名称为 nginx 的 IngressClass 处理,定义在 values.yaml 中 controller.ingressClassResource.name
rules: # 定义了流量路由的规则,即如何根据域名(host)和路径(path)将请求转发到后端服务。
- host: ingress-redirect.com # 指定此规则适用于请求的 HTTP 主机头(Host Header)为 ingress-redirect.com 的流量。客户端必须通过该域名访问, 如果省略 host,Ingress 会匹配所有域名(即通配规则)。
执行资源清单
$ kubectl apply -f ingress-nginx-redirect.yaml
修改主机host文件,添加域名映射
IP 可以是集群内部署了 Ingress-Controler 的任意一台服务器 IP
192.168.6.139 ingress-redirect.com
浏览器访问测试
5. Ingress-nginx Rewrite
5.1 案例
5.1 rewrite 和 redirect
6. Ingress-nginx 错误代码重定向
7. Ingress-nginx 匹配请求头
8. Ingress-nginx 配置黑白名单
9. Ingress-nginx 速率限制
10. Ingress-nginx 灰度或者金丝雀发布
11. Ingress-nginx 代理后端 https 协议
12. Ingress-nginx 四层代理
13. Ingress-nginx 链路追踪
参考链接
https://zhangzhuo.ltd/articles/2022/03/20/1647773666928.html
https://www.cnblogs.com/tencent-cloud-native/p/13865502.html
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 george_95@126.com