Amazon EKS Clusterを作成する

Amazon Elastic Kubernetes Service(EKS)で、Kubernetes Clusterを、eksctlを利用して作成します。

環境

eksctlのインストール

素のkubernetesでは、kubeadmあたりを利用するのでしょうが、EKSのClusterを管理するためのCLIとして、eksctlが用意されています。

eksctl is a simple CLI tool for creating clusters on EKS - Amazon’s new managed Kubernetes service for EC2.

eksctl.io

インストールします。

$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
$ sudo mv /tmp/eksctl /usr/local/bin
$ eksctl version
[]  version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.12.0"}

シェルの補完機能を設定。

$ cat ~/.bash_profile
# eksctl completion
eval "$(eksctl completion bash)"

eksctl - installation

EKS Clusterの作成

作成していきます。

VPCの作成

Kubernetes Clusterを配置するVPCを作成します。eksctlを利用すると、Clusterと一緒にVPCを作成してくれるのですが、VPC系の設定はeksctlとは別途管理する方針とします。理由としては、下記ブログが参考になりました。

eksctl で VPC を作るのをやめて Terraform で作るようにしました

EKS だけで構築しているサービスなら問題ないけど Anket のように RDS や ElasticCache のような VPC 内にサービスをおくようなものを使っているとVPCまたぐことになるので不都合が生じてしまう。

VPC内に、Kubernetes ClusterとRDSやElastiCacheのようなVPC系サービスが共存している場合、VPCをeksctlで作成してしまうと、確かに何かしら問題ありそうな予感がありますね。

VPC一式を作成するためのCloudFormationを置いておきます。

https://raw.githubusercontent.com/goodbyegangster/cloudformation/master/vpc/cf-vpc.yml

worker node用のkey pair作成

Kubernetes ClusterのWorker Nodeは、EC2インスタンスとして作成されるのですが、そのEC2インスタンスで利用される事になるKey Pairを作成しておきます。

Amazon EC2 を使用してキーペアを作成する

EKS Clusterの作成

Kubernetes ClusterのMaster Nodeにあたるコントロールプレーンを作成します。EKSにおていは、コントールプレーン部分は、利用者側からは隠蔽されたManaged Serviceとなっています。

作成する方法は、eksctlによりコマンドを実行する方法と、YAMLマニフェストファイルを作成してeksctlに渡して実行する方法があります。マニフェストファイルによる実行方法が推奨さています。

今回の、既存VPC内にKubernetes Clusterを作成する場合のサンプルは、下記となります。コントロールプレーンのログを、CloudwatchLogsへ出力する設定を併せて実施しています。

cluster.yml

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: "cluster-sample"
  region: "ap-northeast-1"
  version: "1.14"
  tags:
    'cfn-key-string': 'cfn-value-string'

vpc:
  id: "vpc-xxx"
  cidr: "172.31.0.0/16"
  # autoAllocateIPv6: boolean
  clusterEndpoints:
    privateAccess: true
    publicAccess: true
  # extraCIDRs:
  #   cidr: String
  # nat:
  #   gateway: Disable, Single, HighlyAvailable
  publicAccessCIDRs:
    - "xx.xx.xx.xx/32"
  # securityGroup: String
  # sharedNodeSecurityGroup: xxx
  subnets:
    public:
      ap-northeast-1a:
        id: "subnet-xxx"
        cidr: "172.31.32.0/20"
      ap-northeast-1c:
        id: "subnet-xxx"
        cidr: "172.31.0.0/20"
      ap-northeast-1d:
        id: "subnet-xxx"
        cidr: "172.31.16.0/20"

cloudWatch:
  clusterLogging:
    enableTypes: ["api", "audit", "authenticator", "controllerManager", "scheduler"]

マニフェストファイル作成の参考となるページ。

eksctl/examples/04-existing-vpc.yaml

eksctl/examples/11-cloudwatch-cluster-logging.yaml

作成したマニフェストファイルを使って、eksctlを実行します。

$ eksctl create cluster -f /path/to/manifest/cluster.yml --profile xxx

実行すると、CloudFormationのStackが作成されます。コントールプレーン作成完了まで、15分くらい時間がかかるので気長に待ちます。

コマンド完了後、以下にて確認。

$ eksctl get cluster --profile xxx
NAME            REGION
cluster-sample  ap-northeast-1

managed worker nodeの作成

Kubernetes ClusterのWorker NodeとなるAmazon EKS Managed Node Groupを作成します。こちらもマニフェストファイルを作成して実行します。

nodegroup.yml

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: "cluster-sample"
  region: "ap-northeast-1"

managedNodeGroups:
  -
    name: "sample-node-group"
    desiredCapacity: 2
    maxSize: 2
    minSize: 2
    volumeSize: 20
    amiFamily: "AmazonLinux2"
    availabilityZones:
      - "ap-northeast-1a"
      - "ap-northeast-1c"
      - "ap-northeast-1d"
    iam:
      # instanceProfileARN: String
      # instanceRoleARN: String
      attachPolicyARNs:
        - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
        - arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
        - arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      # instanceRoleName: String
      withAddonPolicies:
        albIngress: true
        appMesh: true
        autoScaler: true
        certManager: true
        cloudWatch: true
        ebs: true
        efs: true
        externalDNS: true
        fsx: true
        imageBuilder: true
        xRay: true
    instanceType: "t3.medium"
    labels:
      'label-key': 'label-value'
    ssh:
      allow: true
      # publicKey: String
      publicKeyName: key-pair-name
      # publicKeyPath: String
      sourceSecurityGroupIds:
        - "sg-xxxxxxxxx"
    tags:
      tag-key: tag-value

マニフェストファイル作成の参考となるページ。

eksctl/examples/15-managed-nodes.yaml

作成したマニフェストファイルを使って、eksctlを実行します。

$ eksctl create nodegroup -f /path/to/manifest/nodegroup.yml --profile xxx

コマンド完了後、以下にて確認。AWSコンソール画面を見に行くと、Worker NodeにあたるEC2が作成されています。

$ eksctl get nodegroup --cluster cluster-sample --profile xxx
CLUSTER         NODEGROUP               CREATED                 MIN SIZE        MAX SIZE        DESIRED CAPACITY        INSTANCE TYPE   IMAGE ID
cluster-sample  sample-node-group       2020-01-22T11:05:27Z    2               2               2                       t3.medium

これにて、EKSのKubernetes Clusterを利用するにあたり、最低限の設定が完了しました。

eksctlでは、非パブリックサブネットにManaged Nodegroupを作成できない、という話

調べている過程で分かったのですが、eksctlではプライベートサブネット(非パブリックサブネット)に、Managed Nodegroupが作成できませんでした。

プライベートサブネットに対してManaged Nodegroupを作成しようとすると、eksctlより実行されたCloudFormationのStackにて、以下のエラーが出力されて、処理が失敗します。

No export named eksctl-cluster-sample-2-cluster::SubnetsPublic found. Rollback requested by user.

詳しくは下記。eksctlで未対応という状況みたいです。

GitHub issu: --node-private-networking is not supported for Managed Nodegroups (--managed=true)

手動で作成や、CloudFormationのテンプレートを利用した方法であれば、プライベートサブネットにも作成できるので、現状でeksctlを利用する場合、検討しておく項目だと思います。

その他に、現時点のeksctlではサポートされていない機能は、下記ページより確認できます。

Feature parity with unmanaged nodegroups

iam.instanceProfileARN and iam.instanceRoleARN are not supported for managed nodegroups.

上記あたりが未サポートのため、worker nodeで利用されるIAM Roleを、eksctl別途管理とできないのが地味につらいところです。

作成されるセキュリティグループについて

本手順で実行した場合、作成されるセキュリティグループと、そのセキュリティグループがアタッチされるElastic Network Interface(ENI)の情報についてまとめておきます。

  • 作成されるセキュリティグループ一覧
    • eks-cluster-sg-xxxxxxxxx
      • EKS Cluster内の通信を全疎通させるSG
      • コントロールプレーンとWorker Nodeにデフォルト付与される
    • eksctl-xxx/ControlPlaneSecurityGroup
      • コントロールプレーンのみにアクセスさせたい通信を定義するSG
      • デフォルトのInbound Ruleは空
    • eksctl-xxx/ClusterSharedNodeSecurityGroup
      • EKS Clusterと全疎通させたいインスタンスに付与するSG、なのかな?
      • 作成されるけど、どのENIにもアタッチされていない
    • eks-remoteAccess-xxx
      • EKS Worker Node向けのSG
      • 以下のInbound Ruleが作成されている
        • 22/tcp
        • nodegroup.ymlsourceSecurityGroupIds で指定したSGがSourceとなる

SGがアタッチされるENI

セキュリティグループ ENI:コントロールプレーン ENI:EKS Worker Node ENI:EKS Woker Node(Secondary)
eks-cluster-sg-xxxxxxxxx
eksctl-xxx/ControlPlaneSecurityGroup
eksctl-xxx/ClusterSharedNodeSecurityGroup
eks-remoteAccess-xxx

その他参考ページ