適用於 EKS 的 AWS CDK:在真實世界多帳戶 Kubernetes 部署中的不足

AWS Cloud Development Kit (CDK) 旨在利用熟悉的程式語言簡化雲端基礎架構的佈建。雖然其 EKS 模組承諾簡化 Kubernetes 叢集的建立和管理,但仔細審視後會發現其重大缺陷,尤其是在考慮實際的多帳戶 EKS 部署時。本文將深入探討這些限制,並主張 AWS CDK 目前的 EKS 實作,特別是 Cluster.addManifest 函數,對於採用共享多帳戶 EKS 策略的組織而言並非真正實用。

簡單的假象:Cluster.addManifest 及其帳戶邊界

CDK 中的 Cluster.addManifest(id: string, ...manifest: Record<string, any>[]): KubernetesManifest 函數似乎提供了一種將 Kubernetes 清單部署到 EKS 叢集的直接方法。然而,在考慮到 EKS 叢集設計為在多個 AWS 帳戶之間共享的真實世界情境時,這種簡單性具有欺騙性。

在實務中,中央 EKS 叢集通常由位於不同 AWS 帳戶中的各個團隊或應用程式共享。這種多帳戶方法對於安全性、隔離性和成本管理至關重要。然而,Cluster.addManifest 是在單一帳戶和區域部署的隱含假設下運作的。

此限制的證據:

忽略網路基礎:沒有適當管線的房屋

一個真正實用的 EKS 解決方案,尤其是在多帳戶設定中,取決於穩固的網路基礎。這通常涉及:

然而,AWS CDK 的 EKS 實作,包括像 aws-quickstart/cdk-eks-blueprints 這樣的藍圖,通常忽略或簡化了這個關鍵的網路層。雖然這些工具可以自動化 EKS 叢集的建立甚至 VPC 的佈建,但它們往往無法提供全面、自動化的解決方案來設定 Transit Gateway 或 VPC 共享,作為 EKS 部署過程中不可或缺的一部分。

在真實世界的 EKS 架構中,網路層並非事後考量;它是建構安全、可擴展且多帳戶 Kubernetes 環境的基礎。CDK 專注於簡化叢集建立,同時抽象化網路複雜性,導致產生的解決方案不適合生產等級的共享 EKS 部署。

權杖解析失敗:CDK 的承諾受損

CDK 的優勢在於其使用權杖——在部署期間解析的預留位置,允許動態組態和資源參考。然而,Cluster.addManifest 無法正確解析這些權杖,進一步阻礙了其實用性。

CDK 權杖設計為在單一 CDK 應用程式和 CloudFormation 堆疊的範圍內解析。當嘗試使用 Cluster.addManifest 將清單部署到叢集中的資源的權杖時,權杖解析通常會失敗。CDK 的預設權杖解析機制根本不是為跨越帳戶邊界而設計的。

此限制迫使用戶放棄 CDK 優雅的基於權杖的方法,轉而手動將具體值(例如 VPC ID、子網路 ID 和安全群組 ID)作為內容參數或環境變數傳遞給其 CDK 應用程式。這種手動傳遞值不僅不夠優雅,而且還引入了更多錯誤的機會,並降低了最初使用 CDK 的整體效益。

解決方案始於網路:

先決條件:在雲端擁抱以應用程式為中心的基礎架構 1

在此圖中:

(原始文本參考此處未顯示的圖表)

AWS 帳戶網路執行兩個隔離的 enver:NT Enver LE 和 NT Enver Prod,以 NT Enver Prod 為例:

  1. 一個 Transit Gateway 連接多個帳戶中的多個 VPC(同一區域);
  2. 一個 NAT 與所有連接的 VPC 共享網際網路;
  3. 一個 IPAM 和 CIDR 集區,供所有連接的 VPC 的子網路使用,以避免 IP 衝突;
  4. 未顯示:子網路、路由、安全群組、DNS、託管區域、組織、管理員委派、憑證等...

中央 VPC 作為跨 VPC 部署資源的代理:

  1. 執行 Lambda 將 Kubernetes 清單部署到來自不同 enver 的不同 EKS 叢集。
  2. 執行 Lambda 將資料庫/結構描述/角色/使用者部署到來自不同 enver 的不同 RDS 叢集。

中央 VPC 作為跨 VPC 連接的代理/中樞:EKS 中的 Pod、ECS 中的任務連接到來自不同 enver 的不同 RDS 叢集中的不同資料庫:

Enver 1:

在邏輯上聲明/控制內部所有資源(標記為綠色),包括 Kubernetes 清單和資料庫相關資源(資料庫、結構描述、角色等),並以交易方式部署或復原。

  1. 清單部署到 EKS Enver1 的叢集,Pod 擔任 Iam 角色 1(透過 SA/OIDC)存取 DynamoDB。
  2. 資料庫、結構描述、角色/使用者部署到 RDS Enver Prod,ECS 任務內部擔任 IAM 角色 2 透過 TGW 存取託管的資料庫。

Enver 2:

同樣在邏輯上聲明/控制內部所有資源(標記為紫色),在清單部署到 EKS Enver1 的叢集後,Pod 將:

  1. 擔任 IAM 角色 A 透過 Transit Gateway 存取資料庫(Enver 2 中不需要 VPC!)。
  2. 擔任 IAM 角色 B 存取 S3 儲存貯體中的檔案。

平台負責部署,因此應用程式和服務只需專注於商業邏輯/功能:

  1. 在 Enver 1 和 Enver 2 中聲明的 Kubernetes 清單將透過中央帳戶 VPC-Prod 中的 Lambda 函數傳送到 EKS 叢集。
  2. 在 Enver 1 和 Enver 2 中聲明的資料庫結構描述/角色/使用者將透過中央帳戶 VPC-Prod 中的 Lambda 函數傳送到 RDS 叢集。

以 Enver 為中心的設計工作範例

https://github.com/ondemandenv/spring-boot-swagger-3-example

此專案例證了以應用程式為中心的雲端原生開發方法,其中所有資源(應用程式程式碼、基礎架構、相依性)都定義為單一垂直的「enver」——一個自足的有界上下文,作為一個單元進行部署/復原。

1. 垂直資源所有權

提供此教學 API 功能所需的所有資源都位於同一位置:

2. 作為版本化單元的環境

每個「enver」包含:

3. 平台服務抽象化

(原始文本可能包含更多內容)

關鍵整合點

1. IAM 角色繫結 (CDK 堆疊)

// cdk/lib/cdk-stack.ts
const podSaRole = new Role(this, 'podSaRole', {
    assumedBy: new FederatedPrincipal(
        myEnver.oidcProvider.getSharedValue(this), // From platform enver
        {
            StringEquals: {
                [`${oidcProvider}:aud`]: 'sts.amazonaws.com',
                [`${oidcProvider}:sub`]: `system:serviceaccount:${namespace}:${serviceAccountName}`
            }
        },
        'sts:AssumeRoleWithWebIdentity'
    )
});

2. 環境感知組態

// src/main/java/com/bezkoder/spring/swagger/config/OpenAPIConfig.java
@Value("${aws.s3.bucket-name}")
private String bucketName; // Injected from enver-specific config

@Bean
public S3Client s3Client() {
    return S3Client.builder()
        .credentialsProvider(WebIdentityTokenFileCredentialsProvider.create())
        .build(); // Auto-utilizes IRSA credentials
}

3. 基礎架構一致性

// cdk/lib/cdk-stack.ts
new cdk8splus.Deployment(chart, 'to-eks', {
    containers: [{
        image: ContainerImage.fromEcrRepository(
            Repository.fromRepositoryName(this, 'repo',
                myEnver.appImgRepoRef.getSharedValue(this)), // Shared ECR
            Fn.select(0, Fn.split(',', // Git SHA-based tagging
                myEnver.appImgLatestRef.getSharedValue(this)))
        ),
        envVariables: {
            bucket_arn: {value: bucket.bucketArn}, // Enver-owned bucket
            region: {value: this.region} // Inherited from platform
        }
    }]
});

主要優點

顯然,整個設計和實作將取決於平台: