この記事はAmazon EKS Advent Calendar 2019の17日目の記事になります。
はじめに
こんにちは、OPENREC.tvでSREに所属している@toro_ponzです。白米が好きです。
先日のリニューアルで、OPENRECではAmazon EKSによるマイクロサービスの運用が始まりました。
本記事では、EKSを運用するにあたってOPENRECで採っているEKSクラスターの構成管理について触れられればと思います。
Amazon EKSとは
AWSが提供するKubernetesのマネージドのサービスです。2019/12/17現在、Kubernetes1.14までをサポートしています。つい先日マネージドなKubernetesワーカーノードがサポートされる旨がアナウンスされましたが、私たちのプロダクトではまだ採用していません。
さて、コントロールプレーンがフルマネージドであることで、Kubernetesクラスターの管理はかなり容易になっているのは言うまでもありません。しかしその構築物は少なくなく、いくつかの構築方法が挙げられます。LTSがなく数か月に一度バージョンが更新されるKubernetesでは、ワーカーノードだけでなくコントロールプレーンの更新容易性も重要になることは必至です。
AWSマネジメントコンソールを使った構築方法
これまでマネジメントコンソールから作成できるリソースはコントロールプレーンのみでしたが、先述したマネージドノードグループのサポートが発表され、ノードグループの作成もWeb上から簡単に行えるようになりました。
「Add node group」からノードグループ作成画面へ行き、
ロールやサブネット、ノードのスケーリングの設定値を入力して、
ノードグループを作成することができます。
オートスケーリンググループや起動テンプレートを自分で作成しなくても良くなり、EKSクラスターの構築はある程度楽になりました。
しかし依然として指定するリソースや構成物は多いため、可能であればInfrastructure as Code(以下IaC)として構成管理しておきたいところです。
eksctlを使ったEKS構築
現状最も簡単にEKSクラスターを構築できるであろう手法が、eksctlを使った方法です。eksctlはWeaveworks社が開発しているEKSの操作を容易にする公式のCLIツールで、eksctl create cluster
コマンドではVPCからコントロールプレーン、ノードグループまでをCloudFormationで構築した後、kubectlで接続情報の構成を行ってくれます。
eksctl create cluster --name test-cluster
試しに上のコマンドを実行すると、以下の2つのCloudFormationスタックが作成され、VPCからノードグループまでが作成されます。コマンド一つでEKSを利用できる状態になるため、マネジメントコンソールでEKSを構築するよりも気軽に行えます。CloudFormationのリソース欄を見ると、その構築物の多さがうかがえます。
control plane | nodegroup |
---|---|
作成された1つ目のスタックを見ると、VPCやルートテーブル、そしてEKSのコントロールプレーンが含まれていることが分かります。VPC等とコントロールプレーンといったリソースが同一のスタックで管理されていることはあまり好ましくないように感じます。eksctlはコマンドライン引数で外部で作成したリソースを指定することもできるため、コントロールプレーンとそれ以外のものは管理を分けた方が運用しやすいでしょう。
eksctl create cluster \
--name xxxx
--vpc-private-subnets=subnet-xxxxxxxx,subnet-xxxxxxxx,subnet-xxxxxxxx \
--vpc-public-subnets=subnet-xxxxxxxx,subnet-xxxxxxxx,subnet-xxxxxxxx
しかし、CLIでの実行となるため、宣言的にクラスターの構成管理を行うことができません。宣言的なTerraformでの構成管理にシフトしていっている私たちとしては、指示的に構築するAWSリソースは最小限に抑えたいものです。
そこで私たちは、EKSクラスターの構築にTerraformとeksctlを組み合わせて利用しています。
OPENRECでのEKS構築
先述したとおり、Terraformでの構成管理は宣言的です。EKS環境を構築するにあたって、VPCやルートテーブル、サブネットなどは基本的に変更しないこともあり、Terraformで管理します。一方で、コントロールプレーンや、ワーカーノード(ノードグループ)はeksctlで作成します。
しかし、ここでeksctlコマンドにTerraformで作成したリソースを引数で渡す様なことはしません。eksctlはyamlファイルでのクラスター構築をサポートしているため、以下の様な形式でEKSを配置するVPCやサブネット、ノードグループを指定することができます。
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: xxxxxxxxxxxxxxxxx
region: ap-northeast-1
version: "1.14"
iam:
withOIDC: true
cloudWatch:
clusterLogging:
enableTypes: ["api", "authenticator", "controllerManager", "scheduler"]
vpc:
id: vpc-xxxxxxxxxxxxxxxxx
cidr: xxxxxxxxxxxxxxxxx/xx
subnets:
public:
ap-northeast-1a:
id: subnet-xxxxxxxxxxxxxxxxx
cidr: xxxxxxxxxxxxxxxxx/xx
ap-northeast-1c:
id: subnet-xxxxxxxxxxxxxxxxx
cidr: xxxxxxxxxxxxxxxxx/xx
ap-northeast-1d:
id: subnet-xxxxxxxxxxxxxxxxx
cidr: xxxxxxxxxxxxxxxxx/xx
private:
ap-northeast-1a:
id: subnet-xxxxxxxxxxxxxxxxx
cidr: xxxxxxxxxxxxxxxxx/xx
ap-northeast-1c:
id: subnet-xxxxxxxxxxxxxxxxx
cidr: xxxxxxxxxxxxxxxxx/xx
ap-northeast-1d:
id: subnet-xxxxxxxxxxxxxxxxx
cidr: xxxxxxxxxxxxxxxxx/xx
nodeGroups:
- name: xxxxxxxxxxxxxxxxx
minSize: 3
maxSize: 10
iam:
instanceProfileARN: arn:aws:iam::0000000000:instance-profile/xxxxxxxxxxxxxxxxx
instanceRoleARN: arn:aws:iam::0000000000:role/xxxxxxxxxxxxxxxxx
instancesDistribution:
instanceTypes: [m5.large]
onDemandBaseCapacity: 0
onDemandPercentageAboveBaseCapacity: 0
privateNetworking: true
preBootstrapCommands:
- "yum install -y https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/linux_amd64/amazon-ssm-agent.rpm"
- "systemctl enable amazon-ssm-agent"
- "systemctl start amazon-ssm-agent"
securityGroups:
attachIDs: [sg-xxxxxxxxxxxxxxxxx]
ami: ami-xxxxxxxxxxxxxxxxx
amiFamily: AmazonLinux2
tags:
"k8s.io/cluster-autoscaler/enabled" : "1"
"k8s.io/cluster-autoscaler/xxxxxxxxxxxxxxxxx" : "1"
私たちはこのyamlファイルの生成までをTerraformで行い、それをoutputとして吐き出してgitにステージングしています。Terraformのコードでいうと、null_resource
でechoコマンドを実行して、yamlファイルに書き出している形です。
resource "null_resource" "cluster" {
provisioner "local-exec" {
command = "echo '${data.template_file.cluster.rendered}' > outputs/${var.eks_cluster_name}.yaml"
}
triggers = {
template = data.template_file.cluster.rendered
}
}
Terraformによって吐き出されたyamlファイルを使い、eksctlを実行します。こうすることでeksctlから可能な限り指示的な要素を減らし、EKSクラスターのIaCを実現しています。
eksctl create cluster -f xxxxxxxxxx.yaml
ノードグループの変更などをする際も直接eksctlを打ったり、yamlファイルを書き換えたりすることはせず、Terraformでの出力から変更を適用します。Terraformのリポジトリ1つで完結するため、管理・運用が比較的わかりやすくなっています。
おわりに
eksctl create clusterをyamlファイルで実行されている方は多いと思いますが、yamlファイル自体をTerraformから生成しているところはそう多くないかもしれません。サブネットやセキュリティグループの番号はPRレビューでも見落としがちなパラメータだと思いますので、そういったリスクを減らせるのはこの構成の良い利点だと思っています。
依然としてノードグループの移行などではノードグループ追加、drain、ノードグループ削除のフローは変わらないですが、出来るだけTerraformによるIaCに落とし込みたい私としてはこの構成管理はしっくりきています。ご参考になれば幸いです。