个人随记 —— 不同 VPC 下 EKS 跨集群服务访问

背景

在本文的问题前,需要对 AWS 的产品进行解释:

  • VPC:Virtual Private Cloud,AWS 在单 region 下提供的私有网络,每个 VPC 都拥有一个独立网段,并且和其他 VPC 进行完全的私网隔离-
  • EC2:Elastic Compute Cloud,AWS 提供的弹性计算虚拟节点
  • EKS:Elastic Kubernetes Service,AWS 提供的全托管 K8S 服务

在两个不同的 VPC 下,我们各创建一个 EKS 部署服务,当出现其中一个集群的 Pod 需要通过访问另一个集群的服务时应该如何解决?

image

解决方案

VPC 网络打通

面临的第一个问题就是如何联通两个 VPC 网络,AWS 提供了两种方式:VPC Peering 和 PraviteLink:

  • 前者是直接打通两个 VPC 的整个网段,使双方访问对方网段时和自身网段一样;
  • 而后者是在两个 VPC 上打通一个通道,提供服务方创建一个 endpoint service,访问方创建一个 endpoint,访问方只能通过这个 PraviteLink 通道访问对方提供的服务。
方案 优势 劣势
VPC Peering - 建立方便 - 几乎没有成本 - 可以跨region - 依赖 vpc cidr 互不冲突 - 打通后隔离性依赖安全组设置
PraviteLink - vpc cidr无限制 - 只能通过 endpoint 访问,安全性较好 - 不可以跨region - 成本高 - 使用较复杂

image

  • 首先我们可以先给服务集群挂在一个内网 LB Service,这样子在 EKS A 集群中就可以有一个四层的负载均衡设施
  • 再给 LB 上创建一个 PrivateLink Service,把服务提供出去
  • EKS B 中创建一个和 PrivateLink Service 对接的 endpoint,EKS B 中的 pod 通过 endpoint 通信访问 Service。

方案二:VPC Peering + k8s LB Service

image

  • 首先我们可以先给服务集群挂在一个内网 LB Service,这样子在 EKS A 集群中就可以有一个四层的负载均衡设施
  • 通过 VPC Peering 打通两个 VPC
  • EKS B 中的 pod 通过 LB 来 通信访问 Service。

方案三:VPC Peering + Local DNS

通过 VPC Peering 打通两个 VPC 的网络隔离后,其实每个 EKS 中的服务一般都会使用 K8S 原生的 Service,使得集群内部可以通过这个 Service 来访问各自的服务,那我们只要能够使得 EKS B 集群的 Pod 能够解析 EKS A 中的 Service DNS 就好了。
目前 K8S 提供两种 DNS 解析服务:

KubeDNS

KubeDNS是Kubernetes官方推荐的DNS解析服务,kubeDNS由3个部分组成:

image

  • kubedns: 依赖 client-go 中的 informer 机制监视 k8s 中的 Service 和 Endpoint 的变化,并将这些结构维护进内存来服务内部 DNS 解析请求
  • dnsmasq: 区分 Domain 是集群内部还是外部,给外部域名提供上游解析,内部域名发往 10053 端口,并将解析结果缓存,提高解析效率。
  • sidecar: 对 kubedns 和 dnsmasq 进行健康检查和收集监控指标。

此外 kubeDNS 提供配置文件实现不同DNS域名解析的路由,两种都可以使用

点击查看代码
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
  name: kube-dns
  namespace: kube-system
data:
  stubDomains: |
    {
      "upstream.svc.cluster.local": [
        "nlb address"
      ]
    }

CoreDNS

CoreDNS 是由 CNCF 托管的可扩展的 DNS 服务, 允许用户通过编写插件的形式去自行处理 DNS 数据,同样提供 corefile 配置文件形式,实现不同 DNS 域名解析路由的功能

点击查看代码
apiVersion: v1
kind: ConfigMap
metadata:
  labels:
    addonmanager.kubernetes.io/mode: EnsureExists
  name: kube-dns
  namespace: kube-system
data:
    .:53 {
       log
       errors
       health
       ready
       kubernetes cluster.local in-addr.arpa ip6.arpa {
          pods insecure
          fallthrough in-addr.arpa ip6.arpa
       }
        prometheus :9153
        forward . /etc/resolv.conf
       cache 30
       loop
       reload
       loadbalance round_robin
    }
    upstream.svc.cluster.local:53 {
       errors
       cache 30
       forward . [nlb address] {
           prefer_udp
       }
    }

image
那么我们的方案也就出来了:

  1. 通过 VPC peering打通网络
  2. 在 EKS A 集群里创建 LB 挂在到 EKS A 集群 CoreDNS 服务的端口
  3. 在 EKS B集群创建 CoreDNS 的配置文件,将 EKS A 集群的域名解析到 EKS A 申请的 LB IP 上,EKS B 集群的域名解析到本地的 CoreDNS 服务上,这样我们可以通过自建的 CoreDNS 服务 route 对应的域名
  4. 修改 Pod 的 DNSConfig 填写我们自建的 CoreDNS Service 的 ClusterIP,DnsPolicy 填 None。
  5. EKS B 中 POD 可以通过解析 EKS A Service 的 IP 来访问,因为 VPC Peering 已经打通了网络。

总结

  • 方案一:
    优点:安全性高,无 CIDR 依赖
    缺点:成本高,不可跨 Region
  • 方案二:
    优点:成本较低,操作较简单,可跨 Region
    缺点:有 CIDR 依赖,安全性依赖安全组设置
  • 方案三:
    优点:打通两套 K8S 的 DNS 解析,更加灵活。
    缺点:有 CIDR 依赖,安全性依赖安全组设置,操作复杂。
posted @ 2023-02-23 22:19  Blue Mountain  阅读(379)  评论(0编辑  收藏  举报