kubernetes(k8s)-Ingress集群外部访问集群内部服务
【代码】k8s-Ingress。
Ingress
一、作用
Ingress 是管理从集群外部访问集群内部服务的 HTTP 和 HTTPS 路由规则的 API 对象。
你可以把它想象成集群的智能路由网关或入口管理员。在 Ingress 出现之前,我们通常使用 LoadBalancer 或 NodePort 类型的 Service 来暴露服务,但这两种方式都有其局限性,而 Ingress 就是为了解决这些问题而生的。
Ingress 的核心作用:
1、提供外部可访问的 URL
-
为内部服务提供一个统一的外部访问地址,如
https://api.example.com。
2、基于域名或路径的路由
- 基于主机名(域名):将
user-service.example.com的流量路由到用户服务,将order-service.example.com的流量路由到订单服务。 - 基于路径:将
example.com/user的流量路由到用户服务,将example.com/order的流量路由到订单服务。
3、负载均衡
-
在多个 Pod 副本之间分配流量。
4、终止 SSL/TLS
-
在 Ingress 层面处理 HTTPS 加密和解密,减轻后端服务的负担。你只需要在 Ingress 上配置证书,后端服务仍然可以使用 HTTP。
5、虚拟主机托管
-
在单个 IP 地址上通过不同的域名提供多个服务。
与 LoadBalancer 和 NodePort 的对比
| 特性 | NodePort | LoadBalancer | Ingress |
|---|---|---|---|
| 工作原理 | 在每个节点上开放一个端口 | 云厂商创建外部负载均衡器 | 一个 Ingress Controller 根据 Ingress 规则路由 HTTP/HTTPS 流量 |
| 暴露层级 | L4 (传输层) | L4 (传输层) | L7 (应用层) |
| 路由能力 | 无,流量直接转发到 Service | 无,流量直接转发到 Service | 有,基于域名和路径 |
| SSL 终止 | 需要在 Pod 内处理 | 需要在 Pod 内处理 | 可在 Ingress 层面统一处理 |
| 成本 | 低 | 高(云负载均衡器通常收费) | 低(自建)或 中等(使用云厂商的 Ingress Controller) |
| 适用场景 | 测试、开发、简单应用 | 需要直接 TCP/UDP 负载均衡的生产环境 | 暴露 HTTP/HTTPS 服务的标准生产环境方案 |
二、Ingress 的核心组件
要理解 Ingress,必须区分两个概念:
Ingress Controller(控制器)
- 是什么:一个具体的、正在运行的 Pod,它负责读取和处理 Ingress 规则,并充当反向代理和负载均衡器(类似于 Nginx、Traefik、HAProxy)。
- 作用:它是实际干活的组件。你必须先部署一个 Ingress Controller,Ingress 资源才能生效。
- 常见实现:
- Nginx Ingress Controller
- Traefik Proxy
- HAProxy Ingress
- 云厂商提供的:如 AWS ALB Ingress Controller, GCE Ingress 等。
Ingress Resource(资源)
- 是什么:一个 Kubernetes API 资源对象(一个 YAML 文件),它定义了具体的路由规则。
- 作用:它告诉 Ingress Controller 应该如何路由流量。你通过
kubectl apply -f ingress.yaml来创建它。
关系:你部署 Controller,然后创建 Resource 规则。Controller 会持续监听这些 Resource 的变化,并动态更新自己的配置。
三、案例演示
我们以最流行的 Nginx Ingress Controller 为例,演示一个完整的场景。
场景描述
我们有两个后端服务:
user-service:处理用户信息,我们希望通过my-app.com/user来访问。order-service:处理订单信息,我们希望通过my-app.com/order来访问。
同时,我们希望通过 HTTPS 访问。
步骤 1:部署 Ingress Controller
首先,你需要安装 Ingress Controller。这里我们使用官方的 Nginx Ingress Controller。
# 使用官方 Manifest 部署(适用于实验环境)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
注意:在生产环境中,请参考官方文档进行更详细的配置。
部署成功后,你可以查看 Ingress Controller 的 Pod 和 Service(通常是 LoadBalancer 类型):
kubectl get pods -n ingress-nginx
kubectl get svc -n ingress-nginx
步骤 2:部署后端服务
创建两个简单的 Deployments 和 Services。
user-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 2
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: nginx:alpine # 用一个简单镜像模拟
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- protocol: TCP
port: 80
targetPort: 80
order-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 2
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: nginx:alpine
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order-service
ports:
- protocol: TCP
port: 80
targetPort: 80
应用它们:
kubectl apply -f user-service.yaml
kubectl apply -f order-service.yaml
步骤 3:创建 Ingress 资源规则
现在,创建最重要的 Ingress 资源,定义路由规则。
ingress-rule.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
# 注解非常重要,用于指定特定控制器的行为
kubernetes.io/ingress.class: "nginx" # 指定使用 nginx ingress controller
nginx.ingress.kubernetes.io/rewrite-target: / # 重要:重写路径,后面会解释
spec:
tls: # TLS 配置部分,用于 HTTPS
- hosts:
- my-app.com
secretName: my-app-tls-secret # 指向一个包含 TLS 证书的 Secret
rules:
- host: my-app.com # 配置的域名
http:
paths:
- path: /user
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
- path: /order
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
应用这个 Ingress 规则:
kubectl apply -f ingress-rule.yaml
关于路径重写 (rewrite-target)
这是一个非常关键的注解。在我们的例子中:
- 用户访问
my-app.com/user/profile - Ingress Controller 收到请求后,需要将流量发送到
user-service服务。 - 但是,
user-service服务本身可能监听在/profile路径上。 - 如果不做重写,Ingress 会把
/user/profile这个完整的路径传递给后端服务,而后端服务可能没有/user/profile这个路由。 nginx.ingress.kubernetes.io/rewrite-target: /的作用是:将匹配到的路径(如/user)去掉,然后将剩余的路径(如/profile)传递给后端服务。- 所以,后端服务收到的请求路径就是
/profile。
步骤 4:测试
由于我们通常没有真实的域名和证书,可以通过修改本地 hosts 文件(C:\Windows\System32\drivers\etc\hosts 或 /etc/hosts)来进行测试。
1、获取 Ingress Controller 的外部 IP
kubectl get svc -n ingress-nginx
找到 ingress-nginx-controller 服务,并复制其 EXTERNAL-IP。如果是 localhost 或 minikube ip,则使用那个地址。假设 IP 是 192.168.49.2。
2、修改 hosts 文件,添加一行
192.168.49.2 my-app.com
# 当用户或应用程序尝试访问my-app.com时,系统会直接将其解析为192.168.49.2,而不是去查询DNS服务器。
3、进行访问
-
访问
http://my-app.com/user(会看到 Nginx 默认页面,这证明请求被成功路由到了user-service的 Pod)。 -
访问
http://my-app.com/order(请求被成功路由到了order-service)。
步骤 5:配置 HTTPS
要配置 HTTPS,你需要一个 TLS 证书。在测试环境中,可以创建一个自签名的证书。
1、生成自签名证书和私钥
# 生成证书和私钥
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout tls.key \
-out tls.crt \
-subj "/CN=my-app.com/O=my-app"
# 验证证书内容
openssl x509 -in tls.crt -text -noout
# 验证私钥
openssl rsa -in tls.key -check
2、在 Kubernetes 中创建 TLS Secret
kubectl create secret tls my-app-tls-secret \
--key tls.key \
--cert tls.crt
这个 Secret 的名字 my-app-tls-secret 必须与 Ingress YAML 中 tls.secretName 字段一致。
3、再次测试
现在你可以通过 https://my-app.com/user 来访问你的服务了。(浏览器会提示不安全,因为证书是自签名的,但连接已经是加密的)。
总结
Ingress 是 Kubernetes 中暴露 HTTP/HTTPS 服务的事实标准。它通过分离 Controller(实现) 和 Resource(规则),提供了一个灵活、强大且成本效益高的集群入口管理方案。核心优势在于其七层路由能力和集中的 SSL/TLS 管理。
使用Secret管理HTTPS证书
openssl req -x509 -nodes-days 365 \
-newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=test.com"
kubectl -n default create secret tls nginx-test-tls --key=tls.key --cert=tls.crt
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: nginx-https-test
namespace: default
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: https-test.com
http:
paths:
- backend:
serviceName: nginx-svc
servicePort: 80
tls:
- secretName: nginx-test-tls
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐

所有评论(0)