AWS EKS Blueprints 快速部署

AWS EKS Blueprints Quick Deployment

EKS Blueprints 概述

AWS EKS Blueprints 是一套由 AWS 開發的開源框架,用於快速建立符合生產環境需求的 Amazon EKS(Elastic Kubernetes Service)叢集。它整合了最佳實踐、常用的 add-ons,以及多租戶和團隊管理功能,讓組織能夠以一致且可重複的方式部署 Kubernetes 基礎架構。

為什麼選擇 EKS Blueprints?

傳統的 EKS 叢集建置往往需要手動配置許多元件:網路、安全性群組、IAM 角色、add-ons 等。這個過程不僅耗時,還容易產生配置差異和安全漏洞。EKS Blueprints 解決了這些問題:

  • 標準化部署:提供經過驗證的叢集配置模板
  • 模組化設計:透過 add-ons 機制輕鬆擴展功能
  • 團隊管理:內建多團隊和多租戶支援
  • GitOps 整合:原生支援 ArgoCD 和 Flux
  • 基礎設施即程式碼:支援 Terraform 和 AWS CDK

EKS Blueprints 架構

EKS Blueprints 的核心架構包含以下元件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
┌─────────────────────────────────────────────────────────────┐
│                     EKS Blueprints                          │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │   Teams     │  │   Add-ons   │  │   GitOps    │          │
│  │  Management │  │  Management │  │ Integration │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
├─────────────────────────────────────────────────────────────┤
│                    EKS Cluster                              │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │ Control     │  │   Node      │  │   VPC &     │          │
│  │ Plane       │  │   Groups    │  │  Networking │          │
│  └─────────────┘  └─────────────┘  └─────────────┘          │
└─────────────────────────────────────────────────────────────┘

Terraform EKS Blueprints

Terraform EKS Blueprints 是使用 Terraform 語言實作的版本,適合已經採用 Terraform 進行基礎設施管理的團隊。

安裝前置需求

在開始之前,請確保已安裝以下工具:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 安裝 Terraform (version >= 1.0.0)
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform

# 驗證安裝
terraform version

# 安裝 AWS CLI
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# 配置 AWS 憑證
aws configure

# 安裝 kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

# 安裝 Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

基本叢集部署

建立專案目錄結構:

1
2
mkdir -p eks-blueprints-demo
cd eks-blueprints-demo

建立 versions.tf 檔案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
terraform {
  required_version = ">= 1.0.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.0.0"
    }
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = ">= 2.20.0"
    }
    helm = {
      source  = "hashicorp/helm"
      version = ">= 2.9.0"
    }
    kubectl = {
      source  = "gavinbunney/kubectl"
      version = ">= 1.14.0"
    }
  }
}

建立 main.tf 檔案:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
provider "aws" {
  region = var.region
}

# 取得可用區域資訊
data "aws_availability_zones" "available" {
  filter {
    name   = "opt-in-status"
    values = ["opt-in-not-required"]
  }
}

# 本地變數定義
locals {
  name            = "eks-blueprints-demo"
  cluster_version = "1.29"
  region          = var.region

  vpc_cidr = "10.0.0.0/16"
  azs      = slice(data.aws_availability_zones.available.names, 0, 3)

  tags = {
    Blueprint   = local.name
    Environment = "demo"
    Terraform   = "true"
  }
}

# VPC 模組
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name = local.name
  cidr = local.vpc_cidr

  azs             = local.azs
  private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 4, k)]
  public_subnets  = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 48)]
  intra_subnets   = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 52)]

  enable_nat_gateway   = true
  single_nat_gateway   = true
  enable_dns_hostnames = true

  # 為 EKS 標記子網路
  public_subnet_tags = {
    "kubernetes.io/role/elb" = 1
  }

  private_subnet_tags = {
    "kubernetes.io/role/internal-elb" = 1
  }

  tags = local.tags
}

# EKS Blueprints 模組
module "eks_blueprints" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints?ref=v4.32.1"

  cluster_name    = local.name
  cluster_version = local.cluster_version

  vpc_id             = module.vpc.vpc_id
  private_subnet_ids = module.vpc.private_subnets

  # EKS 管理的節點群組
  managed_node_groups = {
    initial = {
      node_group_name = "managed-ondemand"
      instance_types  = ["m5.large"]
      min_size        = 2
      max_size        = 5
      desired_size    = 3
      subnet_ids      = module.vpc.private_subnets
    }
  }

  tags = local.tags
}

# Kubernetes 與 Helm Provider 配置
provider "kubernetes" {
  host                   = module.eks_blueprints.eks_cluster_endpoint
  cluster_ca_certificate = base64decode(module.eks_blueprints.eks_cluster_certificate_authority_data)

  exec {
    api_version = "client.authentication.k8s.io/v1beta1"
    command     = "aws"
    args        = ["eks", "get-token", "--cluster-name", module.eks_blueprints.eks_cluster_id]
  }
}

provider "helm" {
  kubernetes {
    host                   = module.eks_blueprints.eks_cluster_endpoint
    cluster_ca_certificate = base64decode(module.eks_blueprints.eks_cluster_certificate_authority_data)

    exec {
      api_version = "client.authentication.k8s.io/v1beta1"
      command     = "aws"
      args        = ["eks", "get-token", "--cluster-name", module.eks_blueprints.eks_cluster_id]
    }
  }
}

建立 variables.tf 檔案:

1
2
3
4
5
variable "region" {
  description = "AWS region"
  type        = string
  default     = "ap-northeast-1"
}

建立 outputs.tf 檔案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
output "cluster_name" {
  description = "EKS cluster name"
  value       = module.eks_blueprints.eks_cluster_id
}

output "cluster_endpoint" {
  description = "EKS cluster endpoint"
  value       = module.eks_blueprints.eks_cluster_endpoint
}

output "cluster_version" {
  description = "EKS cluster version"
  value       = module.eks_blueprints.eks_cluster_version
}

output "configure_kubectl" {
  description = "Configure kubectl command"
  value       = "aws eks update-kubeconfig --region ${var.region} --name ${module.eks_blueprints.eks_cluster_id}"
}

部署叢集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 初始化 Terraform
terraform init

# 檢視執行計畫
terraform plan

# 執行部署(約需 15-20 分鐘)
terraform apply -auto-approve

# 配置 kubectl
aws eks update-kubeconfig --region ap-northeast-1 --name eks-blueprints-demo

# 驗證叢集
kubectl get nodes
kubectl cluster-info

CDK EKS Blueprints

AWS CDK(Cloud Development Kit)版本的 EKS Blueprints 讓開發者能夠使用熟悉的程式語言(如 TypeScript、Python)來定義基礎架構。

安裝 CDK 環境

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 安裝 Node.js (如果尚未安裝)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

# 安裝 AWS CDK
npm install -g aws-cdk

# 驗證安裝
cdk --version

# Bootstrap CDK(首次使用需要執行)
cdk bootstrap aws://ACCOUNT_ID/REGION

建立 CDK 專案

1
2
3
4
5
6
7
8
# 建立專案目錄
mkdir eks-blueprints-cdk && cd eks-blueprints-cdk

# 初始化 TypeScript CDK 專案
cdk init app --language typescript

# 安裝 EKS Blueprints 套件
npm install @aws-quickstart/eks-blueprints

實作 EKS Blueprint

編輯 lib/eks-blueprints-cdk-stack.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as blueprints from '@aws-quickstart/eks-blueprints';

export class EksBlueprintsCdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const account = props?.env?.account || process.env.CDK_DEFAULT_ACCOUNT;
    const region = props?.env?.region || process.env.CDK_DEFAULT_REGION;

    // 定義 Add-ons
    const addOns: Array<blueprints.ClusterAddOn> = [
      new blueprints.addons.VpcCniAddOn(),
      new blueprints.addons.CoreDnsAddOn(),
      new blueprints.addons.KubeProxyAddOn(),
      new blueprints.addons.AwsLoadBalancerControllerAddOn(),
      new blueprints.addons.MetricsServerAddOn(),
      new blueprints.addons.ClusterAutoScalerAddOn(),
      new blueprints.addons.ContainerInsightsAddOn(),
    ];

    // 定義 Teams
    const platformTeam = new blueprints.PlatformTeam({
      name: 'platform-admin',
      users: [
        new blueprints.ArnPrincipal(`arn:aws:iam::${account}:user/platform-admin`),
      ],
    });

    const applicationTeam = new blueprints.ApplicationTeam({
      name: 'app-team',
      users: [
        new blueprints.ArnPrincipal(`arn:aws:iam::${account}:user/app-developer`),
      ],
      teamManifestDir: './teams/app-team',
    });

    // 建立 Blueprint
    blueprints.EksBlueprint.builder()
      .account(account)
      .region(region)
      .version('auto')
      .addOns(...addOns)
      .teams(platformTeam, applicationTeam)
      .build(scope, 'eks-blueprints-cluster');
  }
}

編輯 bin/eks-blueprints-cdk.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { EksBlueprintsCdkStack } from '../lib/eks-blueprints-cdk-stack';

const app = new cdk.App();

new EksBlueprintsCdkStack(app, 'EksBlueprintsCdkStack', {
  env: {
    account: process.env.CDK_DEFAULT_ACCOUNT,
    region: process.env.CDK_DEFAULT_REGION || 'ap-northeast-1',
  },
});

部署 CDK Stack

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 編譯 TypeScript
npm run build

# 檢視 CloudFormation 模板
cdk synth

# 部署
cdk deploy

# 部署完成後配置 kubectl
aws eks update-kubeconfig --region ap-northeast-1 --name eks-blueprints-cluster

Add-ons 管理

EKS Blueprints 的核心優勢之一是其豐富的 add-ons 生態系統。Add-ons 是預先配置好的 Kubernetes 元件,可以透過簡單的配置啟用。

常用 Add-ons 清單

網路與服務發現

Add-on說明
VPC CNIAWS 原生的容器網路介面
CoreDNSKubernetes DNS 服務
AWS Load Balancer Controller自動配置 ALB/NLB
External DNS自動管理 Route53 記錄
Ingress NGINXNGINX Ingress Controller

監控與可觀測性

Add-on說明
Metrics Server資源指標收集
Container InsightsCloudWatch 容器監控
Prometheus開源監控系統
Grafana視覺化儀表板
AWS Distro for OpenTelemetry分散式追蹤

安全性

Add-on說明
AWS Secrets Manager CSI Driver機密管理整合
External Secrets Operator外部機密同步
Cert ManagerTLS 憑證管理
KyvernoPolicy 引擎
OPA Gatekeeper政策合規

GitOps 與 CI/CD

Add-on說明
ArgoCDGitOps 持續部署
FluxGitOps 工具套件

Terraform Add-ons 配置範例

建立 addons.tf 檔案:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
module "eks_blueprints_kubernetes_addons" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints//modules/kubernetes-addons?ref=v4.32.1"

  eks_cluster_id       = module.eks_blueprints.eks_cluster_id
  eks_cluster_endpoint = module.eks_blueprints.eks_cluster_endpoint
  eks_oidc_provider    = module.eks_blueprints.oidc_provider
  eks_cluster_version  = module.eks_blueprints.eks_cluster_version

  # EKS Managed Add-ons
  enable_amazon_eks_vpc_cni            = true
  enable_amazon_eks_coredns            = true
  enable_amazon_eks_kube_proxy         = true
  enable_amazon_eks_aws_ebs_csi_driver = true

  # Self-managed Add-ons
  enable_aws_load_balancer_controller = true
  enable_metrics_server               = true
  enable_cluster_autoscaler           = true
  enable_aws_cloudwatch_metrics       = true

  # 監控
  enable_prometheus                    = true
  enable_amazon_prometheus             = true
  enable_grafana                       = true

  # 安全性
  enable_cert_manager                  = true
  enable_external_secrets              = true
  enable_aws_secrets_manager_csi_driver = true

  # GitOps
  enable_argocd = true
  argocd_helm_config = {
    set = [
      {
        name  = "server.service.type"
        value = "LoadBalancer"
      }
    ]
  }

  tags = local.tags
}

自訂 Add-on 配置

每個 add-on 都可以透過 Helm values 進行自訂:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 自訂 AWS Load Balancer Controller
enable_aws_load_balancer_controller = true
aws_load_balancer_controller_helm_config = {
  name       = "aws-load-balancer-controller"
  chart      = "aws-load-balancer-controller"
  repository = "https://aws.github.io/eks-charts"
  version    = "1.6.2"
  namespace  = "kube-system"

  values = [
    <<-EOT
    replicaCount: 2
    enableShield: false
    enableWaf: false
    enableWafv2: true
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 200m
        memory: 256Mi
    EOT
  ]
}

# 自訂 Prometheus
enable_prometheus = true
prometheus_helm_config = {
  name       = "prometheus"
  repository = "https://prometheus-community.github.io/helm-charts"
  chart      = "prometheus"
  version    = "25.8.0"
  namespace  = "prometheus"

  values = [
    <<-EOT
    server:
      persistentVolume:
        size: 50Gi
      retention: 15d
      resources:
        requests:
          cpu: 500m
          memory: 512Mi
        limits:
          cpu: 1000m
          memory: 1024Mi
    alertmanager:
      enabled: true
    EOT
  ]
}

Team 與 Workload 管理

EKS Blueprints 提供了強大的多租戶管理功能,讓不同團隊能夠安全地共享叢集資源。

團隊類型

EKS Blueprints 定義了兩種團隊類型:

  1. Platform Team:叢集管理員,擁有完整的叢集存取權限
  2. Application Team:應用程式開發團隊,僅能存取指定的 namespace

Terraform Team 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
module "eks_blueprints" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints?ref=v4.32.1"

  # ... 叢集配置 ...

  # Platform Team
  platform_teams = {
    admin = {
      users = [
        "arn:aws:iam::123456789012:user/admin-user",
        "arn:aws:iam::123456789012:role/admin-role"
      ]
    }
  }

  # Application Teams
  application_teams = {
    team-frontend = {
      "labels" = {
        "team"        = "frontend"
        "environment" = "production"
      }
      "quota" = {
        "requests.cpu"    = "10"
        "requests.memory" = "20Gi"
        "limits.cpu"      = "20"
        "limits.memory"   = "40Gi"
        "pods"            = "50"
        "secrets"         = "20"
        "services"        = "20"
      }

      # 團隊成員
      users = [
        "arn:aws:iam::123456789012:user/frontend-dev-1",
        "arn:aws:iam::123456789012:user/frontend-dev-2"
      ]
    }

    team-backend = {
      "labels" = {
        "team"        = "backend"
        "environment" = "production"
      }
      "quota" = {
        "requests.cpu"    = "20"
        "requests.memory" = "40Gi"
        "limits.cpu"      = "40"
        "limits.memory"   = "80Gi"
        "pods"            = "100"
        "secrets"         = "50"
        "services"        = "30"
      }

      users = [
        "arn:aws:iam::123456789012:user/backend-dev-1",
        "arn:aws:iam::123456789012:role/backend-developer-role"
      ]
    }
  }

  tags = local.tags
}

團隊 Manifest 配置

為每個團隊建立額外的 Kubernetes 資源:

1
2
mkdir -p teams/team-frontend
mkdir -p teams/team-backend

建立 teams/team-frontend/network-policy.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: team-frontend
spec:
  podSelector: {}
  policyTypes:
    - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: team-frontend
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - podSelector: {}

建立 teams/team-frontend/limit-range.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-frontend
spec:
  limits:
    - default:
        cpu: "500m"
        memory: "512Mi"
      defaultRequest:
        cpu: "100m"
        memory: "128Mi"
      type: Container

CDK Team 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import * as blueprints from '@aws-quickstart/eks-blueprints';

// Platform Team
const platformTeam = new blueprints.PlatformTeam({
  name: 'platform-admin',
  users: [
    new blueprints.ArnPrincipal('arn:aws:iam::123456789012:user/admin'),
  ],
});

// Application Team with custom configurations
const frontendTeam = new blueprints.ApplicationTeam({
  name: 'frontend',
  users: [
    new blueprints.ArnPrincipal('arn:aws:iam::123456789012:user/frontend-dev'),
  ],
  namespaceLabels: {
    team: 'frontend',
    environment: 'production',
  },
  namespaceAnnotations: {
    'scheduler.alpha.kubernetes.io/node-selector': 'workload=frontend',
  },
  teamManifestDir: './teams/frontend',
});

const backendTeam = new blueprints.ApplicationTeam({
  name: 'backend',
  users: [
    new blueprints.ArnPrincipal('arn:aws:iam::123456789012:user/backend-dev'),
  ],
  namespaceLabels: {
    team: 'backend',
    environment: 'production',
  },
  teamManifestDir: './teams/backend',
});

// 建立 Blueprint
blueprints.EksBlueprint.builder()
  .teams(platformTeam, frontendTeam, backendTeam)
  // ... 其他配置
  .build(scope, 'multi-team-cluster');

GitOps 整合

EKS Blueprints 原生支援 GitOps 工作流程,主要透過 ArgoCD 和 Flux 兩種工具實現。

ArgoCD 整合

Terraform 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
module "eks_blueprints_kubernetes_addons" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints//modules/kubernetes-addons?ref=v4.32.1"

  # ... 基本配置 ...

  enable_argocd = true

  argocd_helm_config = {
    name             = "argocd"
    chart            = "argo-cd"
    repository       = "https://argoproj.github.io/argo-helm"
    version          = "5.51.6"
    namespace        = "argocd"
    create_namespace = true

    values = [
      <<-EOT
      server:
        service:
          type: LoadBalancer
        extraArgs:
          - --insecure
      configs:
        params:
          server.insecure: true
      EOT
    ]
  }

  # ArgoCD 管理的應用程式
  argocd_manage_add_ons = true

  argocd_applications = {
    workloads = {
      path               = "envs/dev"
      repo_url           = "https://github.com/your-org/gitops-workloads.git"
      target_revision    = "main"
      destination        = "https://kubernetes.default.svc"
      project            = "default"

      values = {
        environment = "development"
      }
    }

    platform-services = {
      path               = "platform"
      repo_url           = "https://github.com/your-org/platform-services.git"
      target_revision    = "main"
      destination        = "https://kubernetes.default.svc"
      project            = "platform"
    }
  }

  tags = local.tags
}

存取 ArgoCD UI

1
2
3
4
5
6
7
8
# 取得 ArgoCD 服務 URL
kubectl get svc argocd-server -n argocd

# 取得初始 admin 密碼
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

# 或使用 port-forward
kubectl port-forward svc/argocd-server -n argocd 8080:443

ArgoCD Application 範例

建立 gitops/apps/sample-app.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: sample-application
  namespace: argocd
  finalizers:
    - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/sample-app.git
    targetRevision: HEAD
    path: kubernetes
    helm:
      valueFiles:
        - values-production.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: sample-app
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

Flux 整合

Terraform 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
module "eks_blueprints_kubernetes_addons" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints//modules/kubernetes-addons?ref=v4.32.1"

  # ... 基本配置 ...

  enable_flux = true

  flux_helm_config = {
    create_namespace = true
    namespace        = "flux-system"
  }

  flux_git_repo_url    = "https://github.com/your-org/gitops-config.git"
  flux_git_branch      = "main"
  flux_git_path        = "clusters/production"
  flux_git_poll_interval = "1m"

  tags = local.tags
}

Flux Kustomization 範例

建立 clusters/production/apps.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/production
  prune: true
  wait: true
  timeout: 5m0s
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: sample-app
      namespace: sample-app

建立 clusters/production/infrastructure.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: infrastructure
  namespace: flux-system
spec:
  interval: 1h0m0s
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure
  prune: true
  wait: true
  dependsOn:
    - name: sources

多叢集架構

EKS Blueprints 支援多叢集架構的部署與管理,適用於多區域、多環境的企業需求。

多叢集架構模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
                    ┌─────────────────┐
                    │   GitOps Repo   │
                    │   (ArgoCD Hub)  │
                    └────────┬────────┘
              ┌──────────────┼──────────────┐
              │              │              │
     ┌────────▼────────┐ ┌───▼───┐ ┌────────▼────────┐
     │   Hub Cluster   │ │       │ │   Hub Cluster   │
     │  (ap-northeast) │ │       │ │   (us-west-2)   │
     └────────┬────────┘ │       │ └────────┬────────┘
              │          │       │          │
      ┌───────┴───────┐  │       │  ┌───────┴───────┐
      │               │  │       │  │               │
┌─────▼─────┐ ┌───────▼──▼┐   ┌──▼──▼───────┐ ┌─────▼─────┐
│  Dev      │ │  Staging  │   │  Staging    │ │   Prod    │
│  Cluster  │ │  Cluster  │   │  Cluster    │ │  Cluster  │
└───────────┘ └───────────┘   └─────────────┘ └───────────┘

Terraform 多叢集配置

建立 environments/ 目錄結構:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
environments/
├── dev/
   ├── main.tf
   ├── variables.tf
   └── terraform.tfvars
├── staging/
   ├── main.tf
   ├── variables.tf
   └── terraform.tfvars
├── production/
   ├── main.tf
   ├── variables.tf
   └── terraform.tfvars
└── modules/
    └── eks-blueprint/
        ├── main.tf
        ├── variables.tf
        └── outputs.tf

建立共用模組 environments/modules/eks-blueprint/main.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
module "eks_blueprints" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints?ref=v4.32.1"

  cluster_name    = "${var.project_name}-${var.environment}"
  cluster_version = var.cluster_version

  vpc_id             = var.vpc_id
  private_subnet_ids = var.private_subnet_ids

  managed_node_groups = {
    primary = {
      node_group_name = "${var.environment}-primary"
      instance_types  = var.instance_types
      min_size        = var.min_nodes
      max_size        = var.max_nodes
      desired_size    = var.desired_nodes
      subnet_ids      = var.private_subnet_ids
    }
  }

  platform_teams     = var.platform_teams
  application_teams  = var.application_teams

  tags = merge(var.tags, {
    Environment = var.environment
  })
}

module "kubernetes_addons" {
  source = "github.com/aws-ia/terraform-aws-eks-blueprints//modules/kubernetes-addons?ref=v4.32.1"

  eks_cluster_id       = module.eks_blueprints.eks_cluster_id
  eks_cluster_endpoint = module.eks_blueprints.eks_cluster_endpoint
  eks_oidc_provider    = module.eks_blueprints.oidc_provider
  eks_cluster_version  = module.eks_blueprints.eks_cluster_version

  # 基本 add-ons
  enable_amazon_eks_vpc_cni    = true
  enable_amazon_eks_coredns    = true
  enable_amazon_eks_kube_proxy = true
  enable_metrics_server        = true

  # 環境特定 add-ons
  enable_cluster_autoscaler           = var.enable_cluster_autoscaler
  enable_aws_load_balancer_controller = var.enable_alb_controller
  enable_argocd                       = var.enable_argocd

  tags = var.tags
}

建立環境配置 environments/production/terraform.tfvars

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
project_name    = "mycompany"
environment     = "production"
region          = "ap-northeast-1"
cluster_version = "1.29"

instance_types = ["m5.xlarge", "m5.2xlarge"]
min_nodes      = 3
max_nodes      = 20
desired_nodes  = 5

enable_cluster_autoscaler = true
enable_alb_controller     = true
enable_argocd             = true

platform_teams = {
  admin = {
    users = ["arn:aws:iam::123456789012:role/PlatformAdmin"]
  }
}

application_teams = {
  production-apps = {
    labels = {
      environment = "production"
    }
    quota = {
      "requests.cpu"    = "100"
      "requests.memory" = "200Gi"
      "pods"            = "500"
    }
    users = ["arn:aws:iam::123456789012:role/ProductionDeveloper"]
  }
}

tags = {
  Project     = "EKS-Blueprints"
  ManagedBy   = "Terraform"
  CostCenter  = "Platform"
}

跨叢集服務網格

對於需要跨叢集通訊的場景,可以整合 Istio 服務網格:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
module "kubernetes_addons" {
  # ... 基本配置 ...

  enable_istio = true
  istio_helm_config = {
    name       = "istio"
    repository = "https://istio-release.storage.googleapis.com/charts"
    chart      = "base"
    version    = "1.20.0"
    namespace  = "istio-system"

    values = [
      <<-EOT
      global:
        meshID: mesh1
        multiCluster:
          clusterName: ${var.cluster_name}
        network: network1
      EOT
    ]
  }
}

自訂 Blueprint 開發

當標準的 add-ons 無法滿足需求時,您可以開發自訂的 Blueprint 元件。

自訂 Terraform Add-on

建立 modules/custom-addon/main.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
resource "helm_release" "custom_addon" {
  name             = var.addon_name
  namespace        = var.namespace
  create_namespace = var.create_namespace
  repository       = var.helm_repo
  chart            = var.helm_chart
  version          = var.helm_version

  dynamic "set" {
    for_each = var.helm_settings
    content {
      name  = set.key
      value = set.value
    }
  }

  values = var.helm_values

  depends_on = [var.addon_dependencies]
}

# 如果需要 IAM 角色
module "irsa" {
  source  = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
  version = "~> 5.0"

  count = var.create_irsa ? 1 : 0

  role_name = "${var.addon_name}-irsa"

  oidc_providers = {
    main = {
      provider_arn               = var.oidc_provider_arn
      namespace_service_accounts = ["${var.namespace}:${var.service_account_name}"]
    }
  }

  role_policy_arns = var.irsa_policies

  tags = var.tags
}

建立 modules/custom-addon/variables.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
variable "addon_name" {
  description = "Name of the addon"
  type        = string
}

variable "namespace" {
  description = "Kubernetes namespace"
  type        = string
  default     = "default"
}

variable "create_namespace" {
  description = "Create namespace if it doesn't exist"
  type        = bool
  default     = true
}

variable "helm_repo" {
  description = "Helm repository URL"
  type        = string
}

variable "helm_chart" {
  description = "Helm chart name"
  type        = string
}

variable "helm_version" {
  description = "Helm chart version"
  type        = string
}

variable "helm_settings" {
  description = "Helm chart settings"
  type        = map(string)
  default     = {}
}

variable "helm_values" {
  description = "Helm chart values as list of strings"
  type        = list(string)
  default     = []
}

variable "create_irsa" {
  description = "Create IAM role for service account"
  type        = bool
  default     = false
}

variable "oidc_provider_arn" {
  description = "OIDC provider ARN"
  type        = string
  default     = ""
}

variable "service_account_name" {
  description = "Service account name"
  type        = string
  default     = "default"
}

variable "irsa_policies" {
  description = "IAM policies for IRSA"
  type        = list(string)
  default     = []
}

variable "addon_dependencies" {
  description = "Dependencies for the addon"
  type        = list(any)
  default     = []
}

variable "tags" {
  description = "Tags"
  type        = map(string)
  default     = {}
}

使用自訂 Add-on

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
module "custom_monitoring" {
  source = "./modules/custom-addon"

  addon_name       = "custom-monitoring"
  namespace        = "monitoring"
  create_namespace = true

  helm_repo    = "https://charts.example.com"
  helm_chart   = "custom-monitoring"
  helm_version = "1.0.0"

  helm_settings = {
    "replicaCount"     = "2"
    "resources.cpu"    = "500m"
    "resources.memory" = "512Mi"
  }

  helm_values = [
    <<-EOT
    ingress:
      enabled: true
      hosts:
        - monitoring.example.com
    persistence:
      enabled: true
      size: 100Gi
    EOT
  ]

  create_irsa          = true
  oidc_provider_arn    = module.eks_blueprints.oidc_provider_arn
  service_account_name = "custom-monitoring"
  irsa_policies        = ["arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"]

  addon_dependencies = [module.eks_blueprints]

  tags = local.tags
}

CDK 自訂 Add-on

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import * as blueprints from '@aws-quickstart/eks-blueprints';
import { Construct } from 'constructs';
import * as cdk from 'aws-cdk-lib';

export interface CustomAddonProps extends blueprints.addons.HelmAddOnUserProps {
  customSetting?: string;
}

export class CustomAddon extends blueprints.addons.HelmAddOn {
  readonly options: CustomAddonProps;

  constructor(props?: CustomAddonProps) {
    super({
      name: 'custom-addon',
      namespace: 'custom-namespace',
      chart: 'custom-chart',
      repository: 'https://charts.example.com',
      version: '1.0.0',
      release: 'custom-addon',
      ...props,
    });
    this.options = props ?? {};
  }

  deploy(clusterInfo: blueprints.ClusterInfo): Promise<Construct> {
    const cluster = clusterInfo.cluster;

    // 建立 IRSA
    const serviceAccount = cluster.addServiceAccount('custom-addon-sa', {
      name: 'custom-addon',
      namespace: this.options.namespace,
    });

    // 附加 IAM 政策
    serviceAccount.role.addManagedPolicy(
      cdk.aws_iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchAgentServerPolicy')
    );

    // 設定 Helm values
    const values = {
      serviceAccount: {
        create: false,
        name: serviceAccount.serviceAccountName,
      },
      customSetting: this.options.customSetting ?? 'default-value',
    };

    // 部署 Helm chart
    return Promise.resolve(
      this.addHelmChart(clusterInfo, values)
    );
  }
}

使用自訂 add-on:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
const addOns: Array<blueprints.ClusterAddOn> = [
  // 標準 add-ons
  new blueprints.addons.VpcCniAddOn(),
  new blueprints.addons.CoreDnsAddOn(),

  // 自訂 add-on
  new CustomAddon({
    customSetting: 'my-custom-value',
    values: {
      replicaCount: 2,
    },
  }),
];

blueprints.EksBlueprint.builder()
  .addOns(...addOns)
  .build(scope, 'custom-cluster');

驗證與測試

部署完成後,驗證叢集狀態:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# 檢查節點狀態
kubectl get nodes -o wide

# 檢查所有 namespace 的 pods
kubectl get pods --all-namespaces

# 檢查 add-ons 狀態
kubectl get pods -n kube-system
kubectl get pods -n argocd
kubectl get pods -n monitoring

# 檢查服務
kubectl get svc --all-namespaces

# 檢查 Ingress
kubectl get ingress --all-namespaces

# 檢查 PVC
kubectl get pvc --all-namespaces

總結

AWS EKS Blueprints 提供了一個強大且靈活的框架,用於快速部署符合企業需求的 Kubernetes 叢集。透過本文介紹的內容,您已經學會:

  1. EKS Blueprints 基礎:理解架構設計和核心概念
  2. Terraform 部署:使用 Terraform 建立和管理 EKS 叢集
  3. CDK 部署:使用 AWS CDK 以程式化方式定義基礎架構
  4. Add-ons 管理:配置和自訂各種 Kubernetes 元件
  5. 團隊管理:實作多租戶和資源配額
  6. GitOps 整合:透過 ArgoCD 和 Flux 實現持續部署
  7. 多叢集架構:設計和部署跨區域、多環境的叢集
  8. 自訂開發:建立符合特定需求的自訂 add-ons

最佳實踐建議

  • 版本控制:將所有 Blueprint 配置存放在 Git 儲存庫中
  • 模組化設計:使用可重複使用的模組來管理共用配置
  • 環境隔離:為不同環境(dev、staging、production)維護獨立的配置
  • 安全優先:啟用必要的安全 add-ons,如 Secrets Manager、Cert Manager
  • 監控完善:確保部署監控和日誌收集工具
  • GitOps 實踐:採用 GitOps 工作流程管理應用程式部署
  • 定期更新:定期更新 EKS 版本和 add-ons 以獲取安全修復

透過遵循這些最佳實踐,您可以建立一個穩定、安全且易於管理的 Kubernetes 平台。

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy