「Fargate for EKS」に対応したeksctlコマンドの使い方(初歩編)
みなさん、こんにちは!
AWS事業本部の青柳@福岡オフィスです。
このブログ記事は「Amazon EKS Advent Calendar 2019」の10日目のエントリです
re:Inventで公開された「Fargate for EKS」に合わせて、EKSのコマンドラインツール「eksctl」も version 0.11.0
で「Fargate for EKS」に対応しました。
今回は、「Fargate for EKS」に関係する部分を中心にeksctlコマンドの使い方を見ていきたいと思います。
はじめに:「eksctl」のススメ (特に初学者)
現在、EKSの環境を作成して使い始めるには、いくつかの方法があります。
- マネジメントコンソール
- AWS CLI
- eksctl
- Terraform
この中で、個人的に最も「お手軽」なのは「eksctl」だと思います。
というのも、他の方法だと「IAMロール」や「セキュリティグループ」などEKSに必要な関連リソースを事前に個別に作成する必要がありますが、eksctlを使うと自動的にこれらのリソースを作成してくれるからです。
(もちろん、これらの関連リソースがどのようなものが作成されるのかを知っておくことは重要です。機会があれば、公式ドキュメントを参照したり、eksctlで自動生成されたリソースを確認したりしてみることをお勧めします)
eksctlについては、以前に「入門ブログ」を書きましたので、併せて参考にして頂ければと思います。(Fargate for EKSに対応する前の内容です)
「eksctl」コマンドを使ったAmazon EKS構築入門 | Developers.IO
準備: eksctlおよびその他ツールのインストール
まだeksctlをインストールしていない方は、以下のeksctl公式サイトの「インストール手順」を参照して、インストールしましょう。
https://eksctl.io/introduction/installation/
既にeksctlをインストールしている方は、「Fargate for EKS」に対応したバージョン (0.11.0以降) にアップデートしておいてください。
また、「AWS CLI」「kubectl」などの関連するツールも最新バージョンにしておきましょう。
参考まで、今回のブログは以下の各ツールのバージョンを前提にしています。
$ eksctl version [i] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.11.1"} $ aws --version aws-cli/1.16.298 Python/3.6.7 Linux/4.4.0-18362-Microsoft botocore/1.13.34 $ kubectl version --client --short Client Version: v1.16.3
EKSクラスターを作成してPodを起動してみる (EC2/Fargate)
その1: EC2ワーカーノードのみに対応した従来のクラスターを作成する
「Fargate for EKS」について見ていく前に、まずは従来のEC2ワーカーノードのみに対応したEKSクラスターを作成してみます。
今回は、以下のようなオプションを指定して実行しました。
eksctl create cluster \ --name eks-example1 \ --nodegroup-name ng-example \ --node-type t3.large \ --nodes 2 \ --managed
最低限のオプションとして「ノードグループ名」「ノードタイプ」「ノード数」を指定しています。
また、re:Inventの直前にリリースされた「Managed Node Group」に対応させるため --managed
も指定しています。
(これを指定しないと、マネジメントコンソールにノードグループが表示されなくなりますので注意してください)
作成されたクラスターを確認する
EKSクラスターが作成されると、以下のようになります。
--managed
を付けたことにより、作成したノードグループがマネジメントコンソールに表示されています。
kubectlでNodeの一覧を確認します。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION ip-192-168-30-117.ap-northeast-1.compute.internal Ready <none> 8m54s v1.14.7-eks-1861c5 ip-192-168-73-252.ap-northeast-1.compute.internal Ready <none> 8m59s v1.14.7-eks-1861c5
ワーカーノードが2つ作成されていることが確認できます。
Podを起動してみる
では、作成したEKSクラスター上でPodを起動してみます。
以下のマニフェストファイルを用意します。
(nginxコンテナを6つ起動するというシンプルな内容です。コンテナのポート番号などを指定していますが、今回はnginxへのアクセスは行わず、Podを起動させる目的のみで使用します)
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 6 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.16.1 ports: - containerPort: 80
マニフェストを使ってDeploymentを作成します。
$ kubectl apply -f nginx-deployment.yaml deployment.apps/nginx-deployment created
作成されたリソースを確認します。
$ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 6/6 6 6 13s $ kubectl get replicasets NAME DESIRED CURRENT READY AGE nginx-deployment-59777878f8 6 6 6 33s $ kubectl get pods --output wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-59777878f8-2n4n9 1/1 Running 0 49s 192.168.70.25 ip-192-168-73-252.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-7wc95 1/1 Running 0 49s 192.168.20.63 ip-192-168-30-117.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-9cl8r 1/1 Running 0 49s 192.168.31.216 ip-192-168-30-117.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-j9cvw 1/1 Running 0 49s 192.168.71.66 ip-192-168-73-252.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-szfcc 1/1 Running 0 49s 192.168.90.80 ip-192-168-73-252.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-x6l6f 1/1 Running 0 49s 192.168.12.59 ip-192-168-30-117.ap-northeast-1.compute.internal <none> <none>
DeploymentによってReplicaSetが「レプリカ数: 6」(=マニフェストのreplicasで指定した値) で作成され、ReplicaSetによってPodが6つ起動されました。
Podは2台のNodeに分散して配置されていることが分かります。
その2: Fargateのみに対応したクラスターを作成する
では、いよいよ「Fargate for EKS」に対応したEKSクラスターを作成してみます。
eksctlを使って「Fargate for EKS」を使い始める最も簡単な方法は、eksctl version 0.11.0 で追加された --fargate
オプションを指定することです。
eksctl create cluster \ --name eks-example2 \ --fargate
--fargate
オプションを指定すると、「Fargate for EKS」で必要となる「Fargateプロファイル」が作成されます。
また、--fargate
オプションを指定した場合は、ノードグループは作成されません。
暗黙的に --without-nodegroup
が指定されていると考えて良いと思います。
作成されたクラスターを確認する
EKSクラスターが作成されると、以下のようになります。
ノードグループが作成されておらず、Fargateプロファイルが作成されていることが分かります。
--fargate
オプションの指定により作成されたFargateプロファイルは以下のようになります。
Fargateプロファイルには「Pod実行ロール」「サブネット」などいくつかの要素が含まれますが、最も重要な要素は「Podセレクター」です。
Podセレクターとは、Fargate上で実行させたいPodの条件を指定するための設定です。
具体的には、KubernetesのNamespaceを指定することで、特定のNamespaceに属するPodのみがFargate上で実行されるように制御することができます。
今回作成されたFargateプロファイルには、2つの「Podセレクター」が定義されており、それぞれ「default」「kube-system」というNamespaceが指定されています。
※ default
: Namespaceを明示しなかった場合にデフォルトで選択されるNamespace
※ kube-system
: Kubernetesがシステムで使用するリソースを配置する際に使用されるNamespace
eksctlコマンドでFargateプロファイルの内容を確認すると以下のようになります。
$ eksctl get fargateprofile --cluster eks-example2 --name fp-default --output yaml - name: fp-default podExecutionRoleARN: arn:aws:iam::123456789012:role/eksctl-eks-example2-cluste-FargatePodExecutionRole-ZNKQBZ3EU0Z5 selectors: - namespace: default - namespace: kube-system subnets: - subnet-08f33de655742dcbc - subnet-0bd0ddd636af6f0a2 - subnet-018418fe4c5f53bde
マネジメントコンソールで参照できる情報と同様に、「Pod実行ロール」「Podセレクター」「サブネット」の情報が確認できます。
Podを起動してみる
「その1」の時と同様のマニフェストを使ってDeploymentを作成します。
$ kubectl apply -f nginx-deployment.yaml deployment.apps/nginx-deployment created
作成されたリソースを確認します。
$ kubectl get deployments NAME READY UP-TO-DATE AVAILABLE AGE nginx-deployment 6/6 6 6 69s $ kubectl get replicasets NAME DESIRED CURRENT READY AGE nginx-deployment-59777878f8 6 6 6 88s $ kubectl get pods --output wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deployment-59777878f8-2v6bs 1/1 Running 0 101s 192.168.140.199 fargate-ip-192-168-140-199.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-65ss9 1/1 Running 0 101s 192.168.153.82 fargate-ip-192-168-153-82.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-76n5g 1/1 Running 0 101s 192.168.152.19 fargate-ip-192-168-152-19.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-mqlf8 1/1 Running 0 101s 192.168.131.119 fargate-ip-192-168-131-119.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-s5sms 1/1 Running 0 101s 192.168.97.193 fargate-ip-192-168-97-193.ap-northeast-1.compute.internal <none> <none> nginx-deployment-59777878f8-z826t 1/1 Running 0 101s 192.168.170.14 fargate-ip-192-168-170-14.ap-northeast-1.compute.internal <none> <none>
「その1」の時と同様に、Deployment、ReplicaSetが作成され、Podが6つ起動されています。
Podの「Node」欄を見てみましょう。
「fargate-~」で始まる「ノード」上にPodが配置されていることになっています。
6つのノードは全て異なる名前です。
実は、これがPodの起動要求によって作成された「Fargate」であり、6つのPodを動かすために6つのFargateが作成されていることを示します。
つまり、Fargate for EKSでは、Kubernetes上において1つのFargateは1台のワーカーノードのように見える、ということになります。
(あくまで「のように見える」というだけで、EC2インスタンスベースのワーカーノードと全く同じ物が作成される訳ではありません)
では、ここで、Nodeの一覧を表示してみましょう。
$ kubectl get nodes NAME STATUS ROLES AGE VERSION fargate-ip-192-168-118-124.ap-northeast-1.compute.internal Ready <none> 14m v1.14.8-eks fargate-ip-192-168-127-142.ap-northeast-1.compute.internal Ready <none> 14m v1.14.8-eks fargate-ip-192-168-131-119.ap-northeast-1.compute.internal Ready <none> 110s v1.14.8-eks fargate-ip-192-168-140-199.ap-northeast-1.compute.internal Ready <none> 115s v1.14.8-eks fargate-ip-192-168-152-19.ap-northeast-1.compute.internal Ready <none> 115s v1.14.8-eks fargate-ip-192-168-153-82.ap-northeast-1.compute.internal Ready <none> 115s v1.14.8-eks fargate-ip-192-168-170-14.ap-northeast-1.compute.internal Ready <none> 83s v1.14.8-eks fargate-ip-192-168-97-193.ap-northeast-1.compute.internal Ready <none> 99s v1.14.8-eks
「Fargate-~」で始まる「ノード」が8つ作成されていることが分かります。
ん? 「8つ」?
さっき「6つのPodを動かすために6つのFargateが作成されている」と書きましたよね。
なのに「8つ」とは一体・・・?
Namespace「kube-system」に作成されるPodの動作
正体を明かすと、「2つ」余分に作成されているFargateは、「CoreDNS」というKubernetesのシステムが使用する特殊なPodを起動するために作成されたものです。
CoreDNSの詳細な説明は割愛しますが、CoreDNSのリソースがどのように作成されたのかは、Namespace「kube-system」のDeployment、ReplicaSet、Podの一覧を表示すると分かります。
$ kubectl get deployments --namespace kube-system NAME READY UP-TO-DATE AVAILABLE AGE coredns 2/2 2 2 102m $ kubectl get replicasets --namespace kube-system NAME DESIRED CURRENT READY AGE coredns-699bb99bf8 0 0 0 102m coredns-6d75bbbf58 2 2 2 98m $ kubectl get pods --namespace kube-system --output wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES coredns-6d75bbbf58-8zlrg 1/1 Running 0 98m 192.168.127.142 fargate-ip-192-168-127-142.ap-northeast-1.compute.internal <none> <none> coredns-6d75bbbf58-q2kr9 1/1 Running 0 98m 192.168.118.124 fargate-ip-192-168-118-124.ap-northeast-1.compute.internal <none> <none>
Fargateプロファイルの内容を思い出してみましょう。
Podセレクターとして「default」Namespaceともう一つ「kube-system」Namespaceが条件として定義されていたと思います。
このように、Kubernetesのシステムが使用するPodもFargate上で実行させる必要があるため、「kube-system」NamespaceがPodセレクターに定義されていたのです。
Podセレクターに定義されていないNamespaceのPodを起動すると・・・?
では、ここで敢えて、Podセレクターに定義されていないNamespaceを指定して、Podの起動を試みてみます。
まず、適当に「hogehoge」という名前のNamespaceを作成します。
$ kubectl create namespace hogehoge namespace/hogehoge created
このNamespaceを指定してDeploymentを作成します。
(簡略化のためにマニフェストを使用せずに直接作成します)
$ kubectl create deployment nginx-hogehoge --image nginx --namespace hogehoge deployment.apps/nginx-hogehoge created
Podが起動されたかどうか見てみましょう。
$ kubectl get deployments --namespace hogehoge NAME READY UP-TO-DATE AVAILABLE AGE nginx-hogehoge 0/1 1 0 4m36s $ kubectl get replicasets --namespace hogehoge NAME DESIRED CURRENT READY AGE nginx-hogehoge-7b58884cf 1 1 0 4m43s $ kubectl get pods --namespace hogehoge NAME READY STATUS RESTARTS AGE nginx-hogehoge-7b58884cf-6jwlt 0/1 Pending 0 5m
Deploymentを作成して5分近く経過したのにもかかわらず、Podのステータスが「Pending」となっています。
何が起こっているのか、イベントを確認します。
$ kubectl get events --namespace hogehoge LAST SEEN TYPE REASON OBJECT MESSAGE 66s Warning FailedScheduling pod/nginx-hogehoge-7b58884cf-6jwlt 0/8 nodes are available: 8 Insufficient pods. 5m13s Normal SuccessfulCreate replicaset/nginx-hogehoge-7b58884cf Created pod: nginx-hogehoge-7b58884cf-6jwlt 5m13s Normal ScalingReplicaSet deployment/nginx-hogehoge Scaled up replica set nginx-hogehoge-7b58884cf to 1
Deployment、ReplicaSetは正常に作成されていますが、Podの起動において「Podの起動に十分なNodeが無い」というようなことを言われています。(ちょっと意訳入ってます?)
ともかく、Podセレクターに定義されていないNamespaceを指定してPodを起動しようとしても、Podが起動されないことが分かりました。
Fargate for EKSを利用する際は、使用するNamespaceを予めFargateプロファイルに登録しておく必要があるということですね。
おまけ: CoreDNSの起動時に起こっていること
さて、上の方で「CoreDNSを起動するために作成されるDeployment、ReplicaSet、Podの一覧」を掲載しましたが、ReplicaSetの表示内容にちょっと気になるところがありました。
$ kubectl get replicasets --namespace kube-system NAME DESIRED CURRENT READY AGE coredns-699bb99bf8 0 0 0 102m coredns-6d75bbbf58 2 2 2 98m
1つのDeploymentに対して2つのReplicaSetが作成されていて、しかも、一方のReplicaSetは「DESIRED」「CURRENT」「READY」が全て「0」になっています。
これは、eksctlによるEKSクラスターとFargateプロファイルの作成プロセスに理由があります。
eksctlは、まずEKSクラスター (コントロールプレーン) を作成し、その後にFargateプロファイルを作成します。
一方、CoreDNSはEKSクラスターが作成された直後に、Kubernetesのシステムによって作成されます。
このタイミングでは、まだFargateプロファイルが作成されておらず、またEC2インスタンスベースのワーカーノードも存在しないため、Deployment/ReplicaSetがPodを起動しようとしても配置先のノードが存在しない状態となります。
実際に、このタイミングでPodの一覧を表示すると、以下のような結果になります。
$ kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-699bb99bf8-9jm7r 0/1 Pending 0 3m42s kube-system coredns-699bb99bf8-lct9l 0/1 Pending 0 3m42s
前項の「Podセレクターに定義されていないNamespaceのPodを実行すると・・・?」の時と同じ状況になっているのが分かります。
eksctlは、Fargateプロファイルの作成が完了した後に、この「行き場が無くPodを起動できないDeployment/ReplicaSet」に対して、一度「リフレッシュ」を掛けます。
(Kubernetesの正式な用語では「rollout」と言います)
リフレッシュを掛けられたDeploymentは、Podを配置することができないReplicaSsetに見切りを付け、新たに別のReplicaSetを作成します。
そして、そのReplicaSetが、今度はFargateを使用してPodを無事起動することができた、という訳です。
ReplicaSetが2つ表示されるのは、そういうことなんですね。
(「DESIRE」が「0」になっているというのは「見切りを付けられた」ということなのです)
おわりに
eksctlを使用した「Fargate for EKS」に対応したEKSクラスターの作成を、従来の従来のEC2ワーカーノードのみに対応したEKSクラスターの場合と比較しながら行ってみました。
今回は、作成した「Fargate for EKS」なEKSクラスターの上で単純なPodの起動しか試せませんでしたが、「Service」や「Ingress」など、他のKubernetesリソースと組み合わせた場合についても試してみたいと思います。