/

建立 Reliable EKS 記錄

前言

EKS 的建立方便快速,其中有些概念花了些時間才釐清,甚至有些拓墣一開始想錯了。經過幾週查閱文件與實驗後,寫個小的總結做個簡單的紀錄。

Architecture

  • EKS 只有維護 Control Plane,Worker 有 EC2 與 Fargate 可以選擇。其中 EC2 必須由使用者自行管理。
  • EKS Control Plane 的 VPC 與 Cluster 的 VPC 為不同的 VPC
  • 如果 EKS 有開啟 Private Access,會在 Cluster VPC 的 subnet 中安插 EKS-managed ENI 讓 Cluster VPC 流量穿透至 EKS 中
  • EKS 建立時選擇的 VPC 是為了部署 EKS-managed ENI(最少兩個)使用
  • EKS-managed ENI 直接存在於 subnet 之中,非 EC2 instance(or 其他 instance)之上

Nodegroup

如果 Nodegroup 完全無法存取外網,同時也就無法拉取必要的 Container Image,導致節點無法建立成功

Nodegroup 如果落在 private subnet,可以多開一台有 public subnet 的 EC2 作為 bastion 使用(同一個 VPC 下)

API Endpoint

public access

API endpoint domain 會對應到一組 Public IP 做為 API Endpoint 入口

可以使用 kubectl cluster-info 查看

1
2
[ec2-user@eks-bastion]$ kubectl cluster-info
Kubernetes control plane is running at https://.gr7..eks.amazonaws.com

private access

根據官方文件描述,在 Cluster VPC 下會有 Route 53 private hosted zone 將 API endpoint 解析成該 VPC 下的 IP

This private hosted zone is managed by Amazon EKS, and it doesn’t appear in your account’s Route 53 resources.

經過實驗會發現解出兩組 VPC 中的 private IP,同時為 EKS-managed ENI 的 IP

這組介面可以透過將 Cluster VPC 的流量直接導向至 EKS VPC 之中

啟用條件為 Cluster VPC 必須將 enableDnsHostnames, enableDnsSupport 設定為 true

並且 AmazonProvidedDNS 要在 VPC DHCP 的 domain name servers list

public and private access

外網因為沒有 Route 53 private hosted zone 所以會解析出外網 IP

Cluster VPC 下有 Route 53 private hosted zone 所以會解析出 EKS-managed ENI 的 IP

Pod Amount Limit

Pod limit 的根本問題是因為不同的 EC2 instance type 有先天的 VPC IP 數量限制

ENI 的數量有限制,每一個 ENI instance 可以指定的 IP 數量也有限制

官方有給出一份計算後的限制列表可以進行查閱 eni-max-pods.txt

突破限制前先釐清自己的叢集為何被限制,以下為幾種可能

limited by subnet CIDR

subnet 的 CIDR 一開始切太小,導致 Pod 數量超過 CIDR 範圍時,參考 VPC CNI 的 AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG 參數,來客製化 Pod 的 CIDR。

limited by EC2 instance type

最常見的情況,達到 EC2 上的 IP 數量限制,因此 VPC CNI 無法成功索取 IP。

方法一:

直接抽換 AWS VPC CNI,換掉之後 Node 就不會再持續索取 secondary private IPv4 addresses,不過抽換後,沒有辦法讓 Pod 的 IP 直接屬於 VPC 下的 IP(理論效能會差一些,流量可能須經過 NAT 轉換)。

方法二:

使用 2021 年 EC2 新推出的功能 prefix assignment。開啟 AWS VPC CNI 中的 ENABLE_PREFIX_DELEGATION 參數。將每一個 ENI 上原本可以附加的 secondary private IPv4 addresses 變成變為 /28 範圍(16 個 IPs)。

參考 Increase the amount of available IP addresses for your Amazon EC2 nodes

limited by insufficient IP’s

該 subnet 下的 IP 被其他節點或是其他應用索取完畢,導致某些節點的 aws-node (VPC CNI) 沒有辦法正常索取 IP。解決方法為設定 WARM_ENI_TARGETWARM_IP_TARGET 參數,來讓剛節點一被部署時就預先保留好可用的 IP,即時當時 Pod 還沒有被建立。

Customize kubelet Arguments

某些時候需要客製化我們的節點,例如修改 container runtime(EKS 1.23 已經將預設 container runtime 換成 containerd)

Amazon EKS optimized Amazon Linux AMI 在開機時會呼叫 /etc/eks/bootstrap.sh 在執行必要的初始化

然而該腳本就有提供參數可供調整,例如我想要替換 container runtime 可以在 launch template 中改寫 user-data 成

1
2
#!/bin/bash
/etc/eks/bootstrap.sh demo-k8s --container-runtime containerd

想要修改 kubelet 的啟動參數可以用 --kubelet-extra-args 來修改

後記

以上為這幾週第一次使用 EKS 的紀錄以及個人認為比較容易混淆或是模糊的點,要建構一個可信賴的 EKS 要考量的內容五花八門。這還只是一些在架構上的概念釐清而已,如果要往叢集內部鑽研,有更多要注意與可以調教的地方。這篇文章同時也給以後的自己參考,未來有機會再寫其他文章探討不同層面需要考量的議題。