客座文章最初由 Saaras 团队在Saaras 博客[1]上发表
在公有云或私有云上无法访问 Kubernetes 中运行的服务。这就是 Kubernetes 在设计时考虑到服务安全性的方式。
集群外要安全地访问服务需要了解网络的设置方式以及驱动网络选择的不同需求。
我们首先简要地探讨 kubernetes 集群在服务隔离、服务扩展和服务交付方面的期望。一旦提出了高层次的需求,就更容易理解不同构造和抽象的重要性。
通过对比使用 Ingress 在 Kubernetes 内部运行的服务之前运行 L7 策略层(或代理)的优势,我们得出结论。
理解 Kubernetes Ingress 是运行微服务和安全访问这些服务的关键。本文试图揭开 Kubernetes 网络设置的神秘面纱。
我们将在创建服务、创建不同的 Kubernetes 构件、满足不同需求所需的网络机制时查看网络。
我们还描述了不同类型的 IP 的重要性,如外部 IP、节点 IP、集群 ip、Pod-IP,并描述了流量如何通过每一个 IP。
从集群网络需求开始,我们了解为什么要这样设置网络。
Kubernetes 中的集群网络有几个要求
服务的安全性和隔离
pod 的连接、网络和 IP 分配
设置网络以从几个物理节点构建集群抽象
跨服务的多个实例的流量负载平衡
控制服务的外部访问
在公共和私有云环境中使用 Kubernetes 网络。
为了理解 Kubernetes 网络的这些不同方面,我们从描述在 pod 中创建服务到从公有云和私有云中访问服务的过程开始。
我们强调了对 Ingress 的需求,以及它如何适应整个 Kubernetes 网络模型。
让我们考虑一个具有两个节点的简单 Kubernetes 集群
Kubernetes 编排容器或 pod(即一组容器)。当 Kubernetes 创建 pod 时,它在自己的独立网络中运行(使用网络命名空间)。
下图显示了在每个节点上创建的两个 pod。
这对服务来说意味着什么?服务在 pod 网络中的 pod 中运行。在 pod 网络上分配的 IP 地址(用于服务)在 pod 之外是不可访问的。
那么如何访问这个服务呢?
Kubernetes 在多个物理节点或机器上构建了集群的抽象。物理节点有自己的网络堆栈。Kubernetes 创建的 pod 为运行在 pod 内的服务创建一个隔离的网络堆栈。
要到达这个服务(或 pod 内的 IP 地址),需要路由/桥接在 pod 网络和主机网络之间创建一条路径。容器网络接口(Container Networking Interface)或 CNI 设置与在节点和 pod 之间创建流量路径相关的网络。常见的 CNI 有 calico、cilium、flannel 等。
当 Kubernetes 创建一个 pod 时,它会调用 CNI 回调。这些回调导致调用 CNI 提供者服务来设置 pod 的 IP 地址并将 pod 网络与主机网络连接。
一个服务驻留在一个或几个 pod 中。每个 pod 可以驻留在一个或多个物理节点上。例如,假设一个服务分布在驻留在两个物理节点上的两个 pod 上。
当流量指定到此服务时(分布在两个节点上的两个 pod 上),Kubernetes 如何在它们之间负载平衡流量?
Kubernetes 使用了 Cluster IP 的抽象。任何指向 Cluster IP 的流量都是跨 pod(服务在其中运行)进行负载平衡的。
为了对 pod 中的服务实例进行负载平衡,需要设置网络以访问这些 pod 中的服务。这些 pod 可能运行在集群的不同物理节点上。连接一个服务的 Cluster IP 可以确保发送到 Cluster IP 的流量可以发送到所有运行该服务的 pod;不管 pod 运行在哪个物理节点上。
Cluster IP 的实现是通过 kube-proxy 组件和 iptables、ipvs 或用户空间流量控制等机制来实现的。
发送到 ClusterIP 的流量是跨多个 pod 进行负载平衡的,这些 pod 可能跨越多个物理节点。但是 ClusterIP 只能从集群中的节点访问。或者,换句话说,Kubernetes 中的网络确保了对 ClusterIP 的外部访问是受限制的。
访问集群外部的 ClusterIP 需要显式声明,以便在 Kubernetes 集群的节点外部可以访问它。这是 NodePort。
Kubernetes 中的 NodePort 将节点 IP(和端口)与 ClusterIP 连接起来。
定义 NodePort 提供本地网络的 IP 地址。发送到这个 NodePort IP(和端口)的流量随后被路由到 ClusterIP,最终负载均衡到 pod(和服务)。
NodePort 使服务可以在集群外部访问,但 IP 地址仅在本地可用。LoadBalancer 服务是一种将公共 IP(或 DNS)与 NodePort 服务关联的方法。
当在 Kubernetes 集群中创建 LoadBalancer 类型的服务时,它会分配一个公共 IP,并在云提供商(如 AWS、GCP、OCI、Azure 等)上设置负载均衡器。云负载均衡器被配置为将发送到外部 IP 的流量通过管道发送到 NodePort 服务。
在私有云中运行时,创建 LoadBalancer 类型的服务需要 Kubernetes 控制器来提供负载均衡器。其中一个实现是MetalLb[2],它分配一个 IP 来在集群内路由外部流量。
有几种方法可以访问在公有云上的 Kubernetes 集群中运行的服务。在公有云中,当服务类型为 LoadBalancer 时,会为外部访问分配一个 External IP。
服务可以直接声明为 LoadBalancer 类型。
或者,控制和配置代理的 Ingress 服务可以声明为 LoadBalancer 类型。然后可以在这个入口服务上创建路由和策略,以将外部流量路由到目标服务。
像 Envoy/Nginx/HAProxy 这样的代理可以接收所有进入集群的外部流量,方法是将其作为服务运行,并将此服务定义为 LoadBalancer 类型。可以使用 L7 路由和安全规则配置这些代理。这些规则的集合形成了入口规则。
当服务被声明为 LoadBalancer 类型时,它直接接收来自外部负载均衡器的流量。在下面的图表中,helloenroute 服务被声明为 LoadBalancer 类型。它直接接收来自外部负载均衡器的流量。
可以在服务之前放置一层 L7 代理,以应用 L7 路由和策略。为了实现这一点,需要一个 Ingress Controller(入口控制器)。
Ingress Controller 是 Kubernetes 集群中的一个服务,它被配置为 LoadBalancer 类型,以接收外部流量。Ingress Controller 使用定义的 L7 路由规则和 L7 策略将流量路由到服务。
在下面的示例中,helloenroute 服务接收来自 EnRoute 入口控制器的流量,该入口控制器接收来自外部负载均衡器的流量。
运行入口控制器和在入口执行策略有几个明显的优势。
Ingress 提供了一种可移植的机制来在 Kubernetes 集群内强制执行策略。在集群内实施的策略更容易跨云移植。
可以使用 Kubernetes 服务扩展来水平扩展多个代理。L7 面料的弹性,便于操作和缩放。
L7 策略可以与服务一起驻留在具有集群原生状态存储的集群中*
让 L7 策略更接近服务简化了策略实施和服务和 API 的故障排除。
EnRoute 使用 Envoy 作为底层代理来提供 L7 入口功能。EnRoute 有一个模块化的架构,紧密反映了 Envoy 的可扩展模型。
可以在路由级别或服务级别定义插件/过滤器[3],以便在入口执行 L7 策略。EnRoute 在社区版中提供了高级的限速插件,完全免费,没有任何限制。使用深度 L7 状态为 API 和微服务计时[4]是一个关键需求,EnRoutes 灵活的限速功能提供了巨大的灵活性,以匹配各种限速用例。
EnRoute 企业版[5]包括支持和企业插件,帮助保护 Kubernetes Ingress 的流量。
小贴士:要快速浏览文章,请通读粗体文本以获得整体理解。
使用 EnRoute Ingress API Gateway 是按照以下步骤组织的
第一步:使用 Helm 和 Envoy 在 Kubernetes 入口驱动 API 安全[6]
第二步:EnRoute Kubernetes Ingress Gateway 入门指南[7]
第三步:Kubernetes Ingress(和网络)的 Why 以及 How
[1]
Saaras 博客: https://getenroute.io/blog/ingress-controller-kubernetes-api-gateway-secure-service-jwt-oauth-oidc-network-namespace/
[2]
MetalLb: https://metallb.universe.tf/
[3]
插件/过滤器: https://getenroute.io/features/
[4]
为 API 和微服务计时: https://getenroute.io/blog/why-every-api-needs-a-clock/
[5]
EnRoute 企业版: https://getenroute.io/features/
[6]
第一步:使用 Helm 和 Envoy 在 Kubernetes 入口驱动 API 安全: https://getenroute.io/docs/ingress-filter-legos-secure-microservices-apis-using-helm-envoy/
[7]
第二步:EnRoute Kubernetes Ingress Gateway 入门指南: https://getenroute.io/docs/getting-started-enroute-ingress-controller/