iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
Cloud Native

30 天學習 Pulumi:用各種程式語言控制雲端資源系列 第 16

[Day 16] 實戰練習 (3) - 建立 EKS Cluster

  • 分享至 

  • xImage
  •  

今天來練習建立 AWS EKS Cluster,AWS EKS 是 AWS 推出的 Kubernetes 代管服務,可以協助代管 K8S Control Plane。

在此,一樣使用 Component Resource 來建立一個 EKSCluster 類別。建立 Component Resource 的第一要件就是先用 Interface 來定義建立 Resource 所需要用到的參數。接著建構出 Component Resource 的雛形,將所有建立資源的程式都放在 initizlie 方法中。

interface EKSClusterArgs {
  clusterName: pulumi.Input<string>;
  vpcId: pulumi.Input<string>;
  subnetIds: pulumi.Input<pulumi.Input<string>[]>;

  version?: pulumi.Input<string>;
  roleArn?: pulumi.Input<string>;
}

export class EKSCluster extends pulumi.ComponentResource {
  constructor(name: string, args: EKSClusterArgs, opts: pulumi.ComponentResourceOptions = {}) {
    super("pulumi-practice:vpc:Vpc", name, {name, args, opts}, opts);
  }

  protected async initialize({name, args, opts}: {
    name: string;
    args: EKSClusterArgs;
    opts?: pulumi.ComponentResourceOptions;
  }) {
  
  }
}

接著就可以開始在 initialize 內撰寫建立資源的程式了!

建立 Cluster Role

第一個部分比較簡單,如果使用者沒有傳入 roleArn 的話,就建立一個 cluster role。

這邊參考官方文件——Amazon EKS 叢集 IAM 角色 建立 cluster iam role。

if (!args.roleArn) {
  this.role = new aws.iam.Role(`${name}-eksClusterRole`, {
    assumeRolePolicy: {
      Version: "2012-10-17",
      Statement: [
        {
          Action: "sts:AssumeRole",
          Principal: {
            Service: "eks.amazonaws.com"
          },
          Effect: "Allow"
        }
      ]
    }
  });
}

建立 NodeGroup Role

接著需要建立 NodeGroup Iam Role,這個 IAM role 是未來要建立 NodeGroup 時,要提供的 Role。由於在這不打算讓使用者設定,因此就在 component resource 中建立。

建立的方式一樣參考自 AWS EKS 文件:Amazon EKS 節點 IAM 角色

this.nodeGroupRole = new aws.iam.Role(`${name}-eks-nodeGroupRole`, {
  assumeRolePolicy: {
    Version: "2012-10-17",
    Statement: [
      {
        Action: "sts:AssumeRole",
        Principal: {
          Service: "ec2.amazonaws.com"
        },
        Effect: "Allow"
      }
    ]
  }
});
new aws.iam.RolePolicy(`${name}-eks-nodeGroupRolePolicy`, {
  role: this.nodeGroupRole,
  policy: {
    Version: "2012-10-17",
    Statement: [
      {
        Effect: "Allow",
        Action: [
          "ec2:AssignIpv6Addresses",
          "ec2:DescribeInstances",
          "ec2:DescribeTags",
          "ec2:DescribeNetworkInterfaces",
          "ec2:DescribeInstanceTypes"
        ],
        Resource: "*"
      },
      {
        Effect: "Allow",
        Action: [
          "ec2:CreateTags"
        ],
        Resource: [
          "arn:aws:ec2:*:*:network-interface/*"
        ]
      }
    ]
  }
});

建立 Cluster Security Group

接著建立 Cluster Security Group,這個 SG 會套用至 Control Plane 與 NodeGroup 之間的流量。這邊就使用 EKS Cluster 預設的方式去放行流量。如果需要客製化規則的話,須參考 AWS 文件:Amazon EKS 安全群組與考量 放行該放行的流量。如果 API Server 與 Worker Node 無法溝通,就會無法調度 Container。

this.clusterSecurityGroup = new aws.ec2.SecurityGroup(`${name}-eks-cluster-sg`, {
  vpcId: args.vpcId,
  ingress: [
    {
      protocol: "-1",
      fromPort: 0,
      toPort: 0,
      self: true
    }
  ],
  egress: [
    {
      protocol: "-1",
      fromPort: 0,
      toPort: 0,
      cidrBlocks: ["0.0.0.0/0"],
      ipv6CidrBlocks: ["::/0"]
    }
  ]
});

建立 EKS Cluster

現在萬事俱備只欠東風,所有相關的資源都準備好了,只剩下建立 EKS Cluster 了!這邊建立的 Cluster 為 Public + Private Endpoint。在 VPC 內會使用 Private Endpoint 連線至 Control Plane;在 VPC 之外,就只用 Public Endpoint 連線至 Cluster。

this.cluster = new aws.eks.Cluster(name, {
  name: name,
  roleArn: args.roleArn || this.role!.arn,
  version: pulumi.output(args.version).apply(v => v || "1.27"),
  vpcConfig: {
    subnetIds: args.subnetIds,
    clusterSecurityGroupId: this.clusterSecurityGroup.id,
    endpointPrivateAccess: true,
    endpointPublicAccess: true
  }
});

使用 EKSCluster 類別建立 AWS EKS Cluster

建立完 EKSCluster 類別後,就可以來使用它建立 EKS Cluster 了。這邊我們用到了之前所建立的 Vpc 基礎設施中所公開的成員——vpc、privateSubnetIds 來建立 EKS Cluster。

const eksCluster = new EKSCluster('project-eks-cluster', {
  vpcId: vpc.vpc.id,
  subnetIds: vpc.privateSubnetIds,
  clusterName: 'project-eks-cluster',
  version: '1.26',
});

建立 Worker Node

有了 Control Plance 後,還需要有 worker node 才能調度 Pod。在此,希望可以透過 EKSCluster 物件中的方法來建立 NodeGroup。

使用起來類似這樣:

eksCluster.addWorkerNode('work1', 't3.large', 3);

填入 NodeGroup 的名字、機器大小、數量,即可幫我們建立 NodeGroup。
要達到這點,我們只需要在 EKSCluster 類別中加入 addWorkerNode 方法,如下:

  public addWorkerNode(
    name: string,
    instanceType: string,
    desiredSize: number,
    maxSize?: number,
    minSize?: number
  ) {
    new aws.eks.NodeGroup(name, {
      instanceTypes: [instanceType],
      clusterName: this.cluster!.name,
      nodeRoleArn: this.nodeGroupRole.arn,
      subnetIds: this.cluster!.vpcConfig.subnetIds,
      scalingConfig: {
        desiredSize: desiredSize,
        maxSize: maxSize ?? desiredSize,
        minSize: minSize ?? desiredSize,
      }
    });
  }

這樣就可以建立 NodeGroup 了。

建立 kubeconfig 用來存取 cluster

最後我們需要產生 kubeconfig,這樣才能透過 kubectl 或是 k8s api 對 API Server 下指令。

產生 kubeconfig 的方法:

  public getKubeconfig(): pulumi.Output<string> {
    return pulumi.all([this.cluster.name, this.cluster.endpoint, this.cluster.certificateAuthority.data]).apply(([clusterName, endpoint, ca]) => {
      return `
apiVersion: "v1",
clusters:
- cluster:
    server: ${endpoint}
    certificate-authority-data: ${ca}
    name: "${clusterName}"
contexts:
- context:
    cluster: "${clusterName}"
    user: "aws"
  name: "aws"
current-context: "aws"
kind: "Config"
users:
- name: "aws"
  user:
    exec:
      apiVersion: "client.authentication.k8s.io/v1alpha1"
      command: "aws-iam-authenticator"
      args:
      - eks
      - get-token
      - --cluster-name
      - ${clusterName}
      `;
    });
  }

這樣產生出來的 kubeconfig 內容,我們可以再透過程式語言內建的檔案操作 API 將資料寫入檔案。就不在此示範了。

建立完 EKS Cluter 後,下一篇文章就會來部署一些服務在 Cluster 中。


上一篇
[Day 15] 實戰練習 (2) - 建立 AWS Network Infrastructure 後半
下一篇
[Day 17] 實戰練習(4) - 在 EKS 中部署應用程式
系列文
30 天學習 Pulumi:用各種程式語言控制雲端資源30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言