在云原生架构中,Kubernetes 已经成为容器编排的事实标准。随着业务的不断发展,我们经常需要对现有的 Kubernetes 集群进行升级和改造。本文将重点探讨如何将现有的 Kubernetes HTTPS 服务从 Ingress 迁移到 Gateway API,解决常见的痛点,并提供可操作的实践方案。尤其是涉及到 HTTPS 迁移,经常会遇到证书管理、流量切换等问题,如果处理不当,会导致服务中断,影响用户体验。本文将帮助你平滑的完成这个迁移过程。
问题背景:Ingress 的局限性
Ingress 作为 Kubernetes 的七层负载均衡器,在早期版本中扮演着重要的角色。然而,随着 Kubernetes 社区的不断发展,Ingress 的局限性也逐渐显现出来:
- 配置复杂:Ingress 的配置通常需要依赖 Ingress Controller 的特定注解,不同的 Ingress Controller (例如 Nginx Ingress Controller、Traefik 等) 可能支持不同的注解,这导致配置的复杂性和可移植性降低。
- 功能受限:Ingress 的功能相对简单,对于一些高级的流量管理需求,例如灰度发布、流量镜像等,需要借助额外的插件或者自定义 Lua 脚本来实现,这增加了维护成本。
- 扩展性差:Ingress 的扩展性受到 Ingress Controller 的限制,如果 Ingress Controller 无法满足业务的需求,就需要自行开发或者寻找其他的解决方案。
因此,Kubernetes 社区推出了 Gateway API,旨在解决 Ingress 的局限性,提供更强大、更灵活、更易用的流量管理方案。
Gateway API:下一代 Kubernetes 流量管理
Gateway API 是 Kubernetes 的一个新 API,它提供了一种更标准、更灵活的方式来管理 Kubernetes 集群的流量。Gateway API 具有以下优势:
- 标准化的 API:Gateway API 定义了一套标准的 API 对象,包括 GatewayClass、Gateway、HTTPRoute、TCPRoute、TLSRoute 等,这些对象可以用来描述流量的入口、路由规则、TLS 配置等。
- 角色分离:Gateway API 将流量管理的职责分离为基础设施提供者和应用开发者,基础设施提供者负责配置 GatewayClass 和 Gateway,应用开发者负责配置 HTTPRoute 和 TCPRoute,这使得流量管理更加清晰和可维护。
- 高级流量管理:Gateway API 支持高级的流量管理功能,例如流量分割、流量镜像、请求头修改等,这些功能可以用来实现灰度发布、A/B 测试等场景。
- 可扩展性强:Gateway API 允许自定义 GatewayClass 和 Gateway Controller,这使得用户可以根据自己的需求选择合适的流量管理方案。
实战:从 Ingress 迁移到 Gateway API
下面我们将通过一个具体的例子来演示如何将现有的 Kubernetes HTTPS 服务从 Ingress 迁移到 Gateway API。假设我们有一个名为 example.com 的域名,需要通过 HTTPS 访问我们的服务。
1. 安装 Gateway API CRD 和 Gateway Controller
首先,我们需要安装 Gateway API 的 CRD(Custom Resource Definition)和 Gateway Controller。这里我们以 Contour 作为 Gateway Controller 的例子:
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.8.0/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.8.0/config/crd/standard/gateway.networking.k8s.io_gateways.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.8.0/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.8.0/config/crd/standard/gateway.networking.k8s.io_tcproutes.yaml
kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v0.8.0/config/crd/standard/gateway.networking.k8s.io_tlsroutes.yaml
kubectl apply -f https://raw.githubusercontent.com/projectcontour/contour/main/examples/contour/01-crds.yaml
kubectl apply -f https://raw.githubusercontent.com/projectcontour/contour/main/examples/contour/02-namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/projectcontour/contour/main/examples/contour/03-configmap.yaml
kubectl apply -f https://raw.githubusercontent.com/projectcontour/contour/main/examples/contour/04-daemonset.yaml
kubectl apply -f https://raw.githubusercontent.com/projectcontour/contour/main/examples/contour/05-service.yaml
2. 创建 GatewayClass
GatewayClass 定义了 Gateway 的类型和行为。我们需要创建一个 GatewayClass 对象,指定使用的 Gateway Controller:
# gatewayclass.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: contour
spec:
controllerName: projectcontour.io/contour
kubectl apply -f gatewayclass.yaml
3. 创建 Gateway
Gateway 定义了流量的入口。我们需要创建一个 Gateway 对象,指定监听的端口和协议,以及使用的 GatewayClass:
# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: contour-gateway
namespace: projectcontour
spec:
gatewayClassName: contour
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: tls-secret # 替换为你的 TLS secret 名称
namespace: default # 替换为你的 TLS secret 所在的 namespace
allowedRoutes:
namespaces:
from: All
需要注意的是,certificateRefs 字段指定了 TLS 证书的 Secret 名称和 namespace。你需要将 tls-secret 替换为你自己的 TLS Secret 名称,并将 default 替换为你自己的 namespace。通常 TLS Secret 可以通过 cert-manager 自动管理。
kubectl apply -f gateway.yaml
4. 创建 HTTPRoute
HTTPRoute 定义了 HTTP 流量的路由规则。我们需要创建一个 HTTPRoute 对象,指定域名、路径和后端服务:
# httproute.yaml
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: example-httproute
spec:
parentRefs:
- name: contour-gateway
namespace: projectcontour
hostnames:
- "example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: example-service # 替换为你的 service 名称
port: 8080 # 替换为你的 service 端口
需要注意的是,parentRefs 字段指定了关联的 Gateway 名称和 namespace。你需要将 contour-gateway 替换为你的 Gateway 名称,并将 projectcontour 替换为你的 Gateway 所在的 namespace。backendRefs 字段指定了后端服务的名称和端口。你需要将 example-service 替换为你自己的 Service 名称,并将 8080 替换为你自己的 Service 端口。
kubectl apply -f httproute.yaml
5. 逐步切换流量
为了保证服务的平滑过渡,我们可以采用逐步切换流量的方式。例如,我们可以先将 10% 的流量切换到 Gateway API,然后逐渐增加流量的比例,直到 100% 的流量都切换到 Gateway API。可以使用 Helm Chart 进行自动化部署和管理,方便进行版本回滚和参数调整。
6. 删除 Ingress
当所有流量都切换到 Gateway API 之后,我们可以删除旧的 Ingress 对象。
避坑经验总结
- 证书管理:在迁移过程中,证书管理是一个重要的环节。建议使用 cert-manager 自动管理证书,可以简化证书的申请、更新和续订过程。
- 流量监控:在切换流量的过程中,要密切关注服务的监控指标,例如 CPU 使用率、内存使用率、请求延迟、错误率等。如果发现异常情况,要及时回滚到旧的 Ingress。
- 版本兼容性:Gateway API 还在不断发展中,不同的 Gateway Controller 可能支持不同的 Gateway API 版本。在选择 Gateway Controller 时,要仔细阅读其文档,了解其支持的 Gateway API 版本。
- 灰度发布:在迁移过程中,可以采用灰度发布的方式,先将少量的流量切换到 Gateway API,然后逐渐增加流量的比例。这样可以降低迁移的风险。
- Ingress Controller 卸载: 在确认所有流量都已切换到 Gateway API 之后,并且运行稳定了一段时间,才可以卸载 Ingress Controller 组件。
总结
本文详细介绍了如何将 Kubernetes HTTPS 服务从 Ingress 迁移到 Gateway API。通过本文的指导,你可以平滑地完成这个迁移过程,并享受到 Gateway API 带来的优势。 Gateway API 提供了更强大、更灵活、更易用的流量管理方案,可以帮助你更好地管理 Kubernetes 集群的流量。希望本文对你有所帮助!在生产环境中,务必进行充分的测试和验证,确保服务的稳定性和可靠性。例如在高并发场景下,需要关注 Gateway Controller 的并发连接数,合理配置资源限制。
冠军资讯
代码一只喵