亚马逊AWS官方博客
如何实现私有Amazon EKS集群通过Http代理访问互联网
应用容器化是企业应用现代化进程中的重要环节之一, 基于Kubernetes的容器集群被大量用户在云上和云下使用。Amazon EKS服务可以帮助用户快速创建基于Kubernetes的集群,Amazon EKS会把Kubernetes的控制平面进行托管,这将大大降低了部署Kubernetes集群的复杂度。与此同时,Amazon EKS服务也提供了高可用的架构以及丰富的安全管理功能。
在很多大型企业内部,基于安全的考虑,也有大量的业务希望部署在纯私有的网络环境内,业务底层的容器不需要被Internet直接访问,但容器集群的Worker node以及内部容器需要能够通过被严格管理的代理来访问Internet安装软件或者进行必要的互联网交互。本篇博客将会演示如何在中国区搭建一个私有的Amazon EKS集群,并利用Http代理的方式让Worker Node可以访问互联网。
Amazon EKS集群网络模式
Amazon EKS集群由2个VPC组成,一个被托管的控制平面的VPC和一个属于客户管理的数据平面的VPC,客户自己的容器运行在数据平面的VPC内。按照集群API Servers终端节点不同访问模式分为三种:
- 公有:集群终端节点可从您 的 VPC 外部访问。Worker Node流量将会离开客户的VPC 以连接到终端节点。
- 公有和私有:集群终端节点可从您 的 VPC 外部访问。Worker Node流量到终端节点的流量将始终位于客户的VPC 中。
- 私有:集群终端节点仅可通过您的 VPC 访问。从Worker Node流量到终端节点的流量将始终位于客户的VPC 中。
解决方案
为了保证客户EKS在纯私有的网络环境中,我们需要使用到私有的EKS集群,关于私有的EKS集群请参考:https://docs.amazonaws.cn/eks/latest/userguide/private-clusters.html
私有EKS集群虽然可以支持EKS集群本身的全内网环境,但EKS集群必须要和云上包括(EC2,ECR以及S3)等其它云服务正常通信才能实现整个集群的正常运行,这一部分主要依赖VPC终端节点(PrivateLink和Gateway Endpoint)实现内网的通信的需求。除此之外,Worker Node访问Internet部分需要借助于部署在相同VPC内public subnet的AWS NAT Gateway或者Internet Proxy实现。很多企业习惯使用自建Proxy的方式更加精细的控制互联网的访问,本方案我们仅讨论自建Proxy的方式。
整体架构
这次的方案部署在宁夏区域,本次需要的服务和架构如下图:
部署过程
- 创建VPC
本次创建的VPC包含2个私有子网作为数据平面的子网,另外还有1个公有子网用来安装代理服务器。
创建VPC过程具体过程省略,但需要注意Worker Node所在的VPC的dhcp options sets配置必须要包含domain-name 和 domain-name-servers,否则会遇到Nodes fail to join cluster报错。
其它更多EKS故障定位可参考:https://docs.aws.amazon.com/eks/latest/userguide/troubleshooting.html
- 创建Amazon EC2,STS, S3以及Amazon ECR服务的VPC Endpoint
创建Amazon EC2, STS和ECR服务的PrivateLink,其中ECR包含ecr.api和ecr.dkr两个, 其中ECR.API用于对 Amazon ECR API 执行的调用,ecr.dkr用于 Docker Registry API, 如 push 和 pull 这样的 Docker 客户端命令使用此终端节点。Subnet选择第一步创建的两个 私有子网,安全组选择创建默认的安全组即可,后面我们还会用到这个安全组创建EKS集群,其它保持默认即可, 同样的方法创建完成共计4个PrivateLink。
创建S3的Gateway Endpoint, 路由表选择2个私有子网使用的路由表.
创建完成后,查看所有的Endpoint如下图所示:
如需要访问其它云上服务,请使用相同方法添加其他Endpoint。
- 创建EC2,部署Squid代理
选择在创建的公有子网中新建一个EC2作为代理,镜像选择标准的Amazon Linux2即可。 需要注意的是:
Squid默认使用3128端口作为代理,注意EC2的安全组需要允许VPC网段访问3128端口。
修改EC2的安全组,增加一个Default的安全组,以便这台代理服务器可以使用第二步创建的Endpoint。
由这台充当代理的EC2需要有利用eksctl创建EKS集群的权限,我们可以新建一个IAM的用户来创建集群,并配置。
关于创建IAM用户可以参考:https://docs.amazonaws.cn/en_us/IAM/latest/UserGuide/id_users_create.html
具体权限配置可以参考:https://eksctl.io/usage/minimum-iam-policies/
登录到代理服务器中,安装并配置Squid代理, 编辑配置文件squid.conf
添加:
acl local src 192.168.0.0/16 #允许VPC所在网段内所有客户机访问代理服务器
http_access allow local #该记录一定要添在deny all之前,允许本地访问
启动squid服务
安装kubectl和jq等工具
安装eksctl
- 创建私有EKS集群
登录代理服务器,替换黄色部分子网id,运行脚本利用eksctl新建一个私有的EKS集群。
在创建完成后,可以看到如下的输出:
红色的报错部分是因为新建的集群是私有集群,为了让本机器能够访问新建的集群,我们需要修改EKS 集群的安全组,让代理机器可以连接到集群。
修改Endpoint的默认安全组,添加入站规则允许EKS集群的安全组访问到Endpoint,类型为https(443),以便集群内的Worker Node可以通过Endpoint访问对应的服务。
关于集群的创建,完整创建步骤也可参考:
https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html
https://eksctl.io/usage/eks-private-cluster/
配置ConfigMap将代理地址写入到kube-proxy以及aws-node
首先,确认EKS集群的CIDR Block
返回结果会是10.100.0.1和172.20.0.1两者中的一个, 这里以10.100.0.1为例。
更新aws-node和 kube-proxy的pods
- 创建Worker NodeGroup
创建EC2 启动模版, 供后续创建Worker Node使用。
选择AWS Managed EKS AMI,注意AMI中的K8s版本需要和EKS集群的保持一致,笔者选择的版本如下(K8s-1.22), 为了能够通过ssh访问Worker Node,建议配置Key Pair。
需要注意的是,安全组的配置,选择VPC Endpoint所使用的安全组,本例中使用的是名为Default的安全组,以保证利用Launch Template创建的EC2能够正常访问Endpoint。
编辑高级设置下的User Data,将代理服务器地址信息写入到EKS集群中, 如果您已为 Amazon EKS 集群启用终端节点私有访问,则必须将 Amazon EKS 终端节点添加到 NO_PROXY 变量。
关于User Data的编写规则请参考:https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/launch-templates.html
示例代码:请查看并确认标蓝部分
创建完成后会生成如下启动模版实例
- 创建EKS Node group
继续上面的操作,登录操作的代理服务器,修改下面的脚本,替换掉启动模版id和集群名称的参数, 使用eksctl在EKS集群中新建一个托管节点组。
- 验证集群node和pod正常工作,并能够通过代理访问互联网
登录代理服务器, 运行get node -A查看所有的node状态。
从输出可以看到,新建的两个node节点已经添加到集群中,状态为Ready。
利用ssh运行命令行可以看到,该node可以通过代理访问互联网(需要替换掉pem文件)。
该命令行返回可以看到,可以正常访问www.amazonaws.cn的网站。
运行get pods -A查看所有的pod状态。
从输出结果可以看到,aws-node/coredns/kube-proxy的pods都在运行状态。
查看其中一个kube-proxy的详细信息。
部分截图如下:
从截图可以看出,kube-proxy的环境变量HTTPS_PROXY,HTTP_PROXY,NO_PROXY取自我们创建的名字为proxy-environment-variables 的ConfigMap, 设置的http代理变量。
总结:
- Amazon EKS私有集群的Worker Node可以通过Endpoint内网完成注册,并添加到私有集群中, 也可以利用com.amazonaws.region-code.ecr.api 和com.amazonaws.region-code.ecr.dkr 以及 Amazon S3 网关端点访问到ECR摘取镜像。
- Amazon EKS私有集群通过部署在Public Subnet中的Http Proxy代理可以连接互联网,Worker Node可以正常访问互联网。
参考文档
- Amazon EKS Worker Node网络设计: https://aws.amazon.com/blogs/containers/de-mystifying-cluster-networking-for-amazon-eks-worker-nodes/)
- Amazon EKS with proxy:https://aws.amazon.com/premiumsupport/knowledge-center/eks-http-proxy-configuration-automation/?nc1=h_ls
- EKSCTL创建私有集群: https://eksctl.io/usage/eks-private-cluster/