K8s Ingress Controller 深度解析:原理、配置与流量管理实战
作为一名后端开发,你肯定遇到过这样的场景:辛辛苦苦用 K8s 部署了一堆服务,结果外部用户根本访问不到!这时候,Ingress Controller 就如同救星般出现,帮你打通 K8s 集群与外部世界的桥梁。今天,咱们就来深入聊聊 Ingress Controller,从原理到配置,再到实际应用,让你彻底掌握它。
什么是 Ingress?它和 Ingress Controller 有什么关系?
首先,我们要搞清楚 Ingress 和 Ingress Controller 之间的关系。Ingress 就像一张路由规则表,它定义了外部请求如何转发到 K8s 集群内部的服务。而 Ingress Controller 则是这张表的执行者,它负责监听 Ingress 规则的变化,并根据这些规则配置底层的负载均衡器,从而实现流量的转发。
你可以把 Ingress 比作交通规则,Ingress Controller 比作交警。交通规则定义了车辆行驶的路线,而交警则负责指挥交通,确保车辆按照规则行驶。
简单来说:
- Ingress: 定义流量如何进入集群的规则。
- Ingress Controller: 实现这些规则的具体组件。
没有 Ingress Controller,Ingress 规则就只是一堆 YAML 文件,没有任何实际作用。只有部署了 Ingress Controller,Ingress 规则才能生效,外部流量才能正确地路由到 K8s 集群内部的服务。
为什么要使用 Ingress Controller?
你可能会问,K8s 不是已经有 Service 了吗?为什么还需要 Ingress Controller 呢?
Service 主要用于集群内部的服务发现和负载均衡。如果你想让外部流量访问到你的服务,通常需要将 Service 的类型设置为 LoadBalancer 或 NodePort。但是,这两种方式都有一些缺点:
- LoadBalancer: 每创建一个
LoadBalancer类型的 Service,K8s 都会向云服务商申请一个负载均衡器。这会增加你的成本,而且负载均衡器的数量是有限制的。 - NodePort:
NodePort会在每个 Node 节点上开放一个端口,外部流量可以通过NodeIP:NodePort的方式访问到你的服务。但是,这种方式不够灵活,而且暴露了 Node 节点的 IP 地址,存在安全风险。
而 Ingress Controller 可以很好地解决这些问题。它只需要一个外部负载均衡器,就可以管理多个 Service 的外部访问。你可以通过配置 Ingress 规则,将不同的域名或路径映射到不同的 Service 上。这样,你就可以用一个负载均衡器,对外提供多个服务,大大节省了成本。
此外,Ingress Controller 还提供了更多的功能,例如:
- SSL termination: 在 Ingress Controller 上配置 SSL 证书,可以实现 HTTPS 加密,保护用户的数据安全。
- Name-based virtual hosting: 可以根据不同的域名,将流量路由到不同的 Service 上。
- Path-based routing: 可以根据不同的 URL 路径,将流量路由到不同的 Service 上。
- Load balancing: 可以对后端服务进行负载均衡,提高服务的可用性和性能。
常见的 Ingress Controller 实现
目前有很多 Ingress Controller 的实现,常见的有:
- NGINX Ingress Controller: 基于 Nginx,功能强大,配置灵活,社区活跃。
- Traefik: 云原生 Ingress Controller,易于配置,支持自动发现。
- HAProxy Ingress Controller: 基于 HAProxy,性能优异,稳定性高。
- Contour: 基于 Envoy,高性能,可扩展,适用于大型集群。
选择哪个 Ingress Controller,取决于你的具体需求和技术栈。如果你对 Nginx 比较熟悉,可以选择 NGINX Ingress Controller。如果你追求易用性,可以选择 Traefik。如果你需要高性能和可扩展性,可以选择 Contour。
在本文中,我们将以 NGINX Ingress Controller 为例,介绍 Ingress Controller 的配置和使用。
NGINX Ingress Controller 的安装与配置
1. 安装 NGINX Ingress Controller
你可以通过 Helm 或 YAML 文件安装 NGINX Ingress Controller。这里我们以 Helm 为例:
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update
helm install my-nginx-ingress ingress-nginx/ingress-nginx
这条命令会在你的 K8s 集群中安装 NGINX Ingress Controller。安装完成后,你可以通过以下命令查看 Ingress Controller 的状态:
kubectl get pods -n ingress-nginx
如果所有的 Pod 都处于 Running 状态,说明 Ingress Controller 已经成功安装。
2. 配置 Ingress 规则
接下来,我们需要创建一个 Ingress 规则,定义外部请求如何转发到 K8s 集群内部的服务。假设我们有两个 Service:web-app 和 api-server。我们希望将域名 example.com 上的流量,按照以下规则进行转发:
- 访问
example.com/web的流量,转发到web-appService。 - 访问
example.com/api的流量,转发到api-serverService。
我们可以创建一个如下的 Ingress 规则:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: example.com
http:
paths:
- path: /web
pathType: Prefix
backend:
service:
name: web-app
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api-server
port:
number: 80
这个 YAML 文件定义了一个名为 my-ingress 的 Ingress 规则。rules 字段定义了流量转发的规则。host 字段指定了域名,paths 字段指定了 URL 路径。backend 字段指定了后端 Service 的名称和端口。
需要注意的是,nginx.ingress.kubernetes.io/rewrite-target: / 这个 annotation 的作用是将请求的 URL 路径重写为 /。这是因为我们的 web-app 和 api-server Service 可能只监听根路径 /。如果不进行重写,请求可能会因为找不到对应的路径而失败。
保存这个 YAML 文件,并使用以下命令创建 Ingress 规则:
kubectl apply -f my-ingress.yaml
3. 配置 DNS
最后,我们需要将域名 example.com 解析到 Ingress Controller 的外部 IP 地址。你可以通过以下命令获取 Ingress Controller 的外部 IP 地址:
kubectl get service -n ingress-nginx my-nginx-ingress-ingress-nginx-controller -o wide
找到 EXTERNAL-IP 字段,这就是 Ingress Controller 的外部 IP 地址。将域名 example.com 解析到这个 IP 地址,就可以通过域名访问你的服务了。
Ingress Controller 的高级用法
除了基本的流量转发功能,Ingress Controller 还提供了很多高级用法,可以满足更复杂的需求。
1. SSL Termination
如果你想使用 HTTPS 加密,可以在 Ingress Controller 上配置 SSL 证书。首先,你需要创建一个 Secret,存储 SSL 证书和私钥:
kubectl create secret tls my-tls-secret --key tls.key --cert tls.crt
然后,在 Ingress 规则中指定这个 Secret:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
spec:
tls:
- hosts:
- example.com
secretName: my-tls-secret
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-app
port:
number: 80
tls 字段指定了 SSL 证书的配置。hosts 字段指定了域名,secretName 字段指定了存储 SSL 证书的 Secret 的名称。
2. Load Balancing
Ingress Controller 可以对后端服务进行负载均衡,提高服务的可用性和性能。NGINX Ingress Controller 提供了多种负载均衡算法,例如:
- Round Robin: 轮询算法,将请求依次分配给后端服务。
- Least Connections: 最少连接算法,将请求分配给连接数最少的后端服务。
- IP Hash: IP 哈希算法,将来自同一个 IP 地址的请求分配给同一个后端服务。
你可以通过 annotation 配置负载均衡算法:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/upstream-hash-by: ip
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-app
port:
number: 80
nginx.ingress.kubernetes.io/upstream-hash-by: ip 这个 annotation 指定使用 IP 哈希算法进行负载均衡。
3. Canary Deployment
Ingress Controller 还可以用于实现灰度发布(Canary Deployment)。你可以将一部分流量转发到新版本的服务,观察新版本的运行情况。如果新版本运行稳定,可以将所有流量都切换到新版本。
你可以通过 annotation 配置灰度发布的权重:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
nginx.ingress.kubernetes.io/canary: "true"
nginx.ingress.kubernetes.io/canary-weight: "20"
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web-app
port:
number: 80
nginx.ingress.kubernetes.io/canary: "true" 这个 annotation 启用灰度发布。nginx.ingress.kubernetes.io/canary-weight: "20" 这个 annotation 指定将 20% 的流量转发到新版本的服务。
总结
Ingress Controller 是 K8s 集群中非常重要的一个组件,它可以帮助你实现外部流量的接入和负载均衡。通过本文的介绍,相信你已经对 Ingress Controller 的原理、配置和高级用法有了深入的了解。在实际应用中,你可以根据自己的需求选择合适的 Ingress Controller 实现,并灵活配置 Ingress 规则,从而构建稳定、高效的 K8s 集群。
希望这篇文章能帮助你更好地理解和使用 K8s Ingress Controller。如果你有任何问题或建议,欢迎在评论区留言。