AWSのmanaged Kubernetesで、これまでプライベートベータだったElastic Container Service for KubernetesGAになった ということなので、さくっとクラスタを作成してみました。1

参考にしたのはAWS公式、EKSのGetting Started Guide です。

まずはEKSのページを見てみようとしたところ・・・ eks_top_ja ぶっ壊れてますね!これはなんかアレですね。 gettext的なのが上手くいっていないように見えるので、画面下から英語にしてみます。

eks_top_en 無事、正しいと思われるページが表示されました。 なんか、How it worksの説明の図がちょっとぼやけて見えるのは環境のせいでしょうか。

扨、ここからGetting Startedしていきます。

create_iam まずはEKS用のIAMロールを作っていきます。 IAMロール作成画面のサービスリストにEKSが追加されていますので、これを選択します。

eks_usecase ユースケースは一つしかなく、選択済みになっています。

eks_permission フムー。

iam_created IAMロールが出来ました。

cf_template CloudFormationでクラスタを組んでいきます。 今のところ、EKSが使えるリージョンはUS West(Oregon) (us-west-2)とUS East(N.Virginia) (us-east-1)の二カ所です。今回はUS Eastでやっていきます。

CloudFormationでCreate Stackをやっていきましょう。 S3 template URLが用意されていますので、これを入力します。 template URLはhttps://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-06-05/amazon-eks-vpc-sample.yamlです。

cf_template_view Viewしてみるとこんな感じです。なるほど。

細かい設定的なところは全くいじらず、さくさく進めていきます。Stack nameはGettingStartedにしました。

cf_stack_complete できた。

cf_stack_output-1 Outputのタグを選択して、SecurityGroupsとVpcIdとSubnetIdsを(一応)メモっておきます。2

次にkubectlの設定をしておきます。 最新のkubectl(1.10以降)をインストールしておいてください。まだインストールしていない場合はEKS側でも配信しているようなのでそれを使ってもOKです。

EKSでは認証にheptio-authenticator-awsを使用するようなので、こちらもドキュメントに従い導入します。 私はいろいろ考えるのが面倒だったため、go getしました。

1
$ go get -u -v github.com/heptio/authenticator/cmd/heptio-authenticator-aws

ヘルプを表示して、正常に導入出来たかざっくり確認します。

1
$ heptio-authenticator-aws help

ここで注意なのですが、ガイドではDownload and Install the Latest AWS CLIのところにOptionalってついてるんですが、これはほぼ必須です。 AWS CLIがないとクラスタに接続出来ないので、AWS CLIをインストールしておきます。

ではいよいよ、EKSでクラスタを作っていきます。 ここで私は若干手間取ったのですが、EKSでクラスタを作るのはルートクレデンシャルでログインしている状態ではだめで、IAMユーザを作る必要がありました。 普段からAWSをごりごり使っている人はアレですが、私みたいにほとんど使ってない人は注意が必要です。

account_menu account アカウントの詳細画面を開いて、アカウントIDをメモります。

add_user user_permission ざっくりIAMユーザを作ります。今回は適当にeks-userとしました。 権限も、何が必要なのかよくわからなかったのでAdministrator Accessとしておきました。 本番ではちゃんとやらなきゃだめですね。

user_created はい。

login_with_iam 一旦ログアウトし、IAMユーザを使ってログインします。

create_eks EKSのトップページでクラスタ名を入れます。今回はgetting-startedとしました。

eks_configure_1 いろいろな情報を入れていきます。 これらはCloudFormationで作った奴ですね。

error_subnet_region エラーが出ました。ガイドを見ると、どうしたら良いか書いてあります。

Important

You may receive an error that one of the Availability Zones in your request does not have sufficient capacity to create an Amazon EKS cluster. If this happens, the error output contains the Availability Zones that can support a new cluster. Retry creating your cluster with at least two subnets that are located in the supported Availability Zones for your account.

サブネットのアベイラビリティゾーン(AZ)がたりないよ、と。ふむ。

create_subnet VPCのページに行き、さくっとサブネットを作ってきます。 最低二つ、EKSが使えるAZが有ればOKとのことなので、一個足しておきます。

eks_configure_2 作ったサブネットを入れて再挑戦。

cluster_success 今度は上手くいきました。

cluster_creating_detail CREATINGで結構時間がかかるので、API server endpointとCertificate authorityの値をメモっておきます。

あと、このタイミングでAWS CLIに認証情報を設定しておきます。今回で言うと、eks-userの認証情報をaws configureで突っ込んでおきます。

加えて、kubectlの設定をしていきます。 ~/.kube/config-getting-startedとして次の内容で設定ファイルを作ります(getting-startedは適宜クラスタ名にする)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: v1
clusters:
- cluster:
    server: <endpoint-url>
    certificate-authority-data: <base64-encoded-ca-cert>
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: aws
  name: aws
current-context: aws
kind: Config
preferences: {}
users:
- name: aws
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      command: heptio-authenticator-aws
      args:
        - "token"
        - "-i"
        - "<cluster-name>"

ここで、<endpoint-url><base64-encoded-ca-cert>はそれぞれさっきメモをしたAPI server endpointとCertificate authorityで、<cluster-name>はクラスタ名(今回だとgetting-started)で置き換えます。

shellでexport KUBECONFIG=$KUBECONFIG:~/.kube/config-getting-startedとして、設定ファイルを読み込みます。

cluster_active そうこうしている間にクラスタがActiveになったりならなかったり(意外と時間がかかるので)するので、Activeになったら、次のコマンドで設定の確認をします。

1
2
3
$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.100.0.1   <none>        443/TCP   23m

私はここで、kubectlのバージョンが古く、かつAWS CLIの設定をしていなかったがために結構困りました。 ユーザ名とパスワードを聞かれたり、答えてもForbiddenだったり、error: You must be logged in to the server (Unauthorized)とか言われたり。 これらはまだ良いのですが、error: the server doesn't have a resource type "cronjobs"とかって訳のわからんエラーが出たりして大変困りました。 kubectlのバージョンとAWS CLIの設定に要注意です。

上手くいったら、ワーカーノードを立てていきます。 ワーカーノードの作成もCloudFormationでさくっとやりましょう。

cf_worker_template 先ほどと同じく、S3 template URLが用意されています。https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-06-05/amazon-eks-nodegroup.yamlを入力しましょう。

configure_worker_stack Stack名はgetting-started-worker-nodesとしました。 ClusterNameにはそのままクラスタ名(getting-started)を入力。 NodeGroupNameは適当につけておきます。 MinSizeとMazSizeはそのまま、NodeInstanceTypeはt2.smallにしました(今回は検証なので)。 NodeImageIdなんですが、これはリージョンによって違います。

RegionAMI ID
US Westami-73a6e20b
US Eastami-dea4d5a1

今回はUS Eastなのでami-dea4d5a1と入力しました。 KeyNameにはキーペアを選択して入れます。EC2インスタンスに直接SSHする予定がなくても、選択しないと、作成中に失敗しますので、入れておきます。 VpcIdとSubnetsはクラスタに使ったものを入れておきます。

node_created できました。Outputのタブを選択して、NodeInstanceRoleをメモっておきます。

コマンドラインで、ノードをクラスタに追加します。

1
$ curl -O https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-06-05/aws-auth-cm.yaml

設定ファイルをダウンロードしてきて、<ARN of instance role (not instance profile>の部分に先ほどのNodeInstanceRoleを書き込みます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles: |
    - rolearn: <ARN of instance role (not instance profile)>
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes    

で、applyします。

1
$ kubectl apply -f aws-auth-cm.yaml

ざっくりノードが追加されたことを確認します。

1
2
3
4
$ kubectl get nodes
NAME                              STATUS    ROLES     AGE       VERSION
ip-192-168-132-251.ec2.internal   Ready     <none>    2m        v1.10.3
ip-192-168-229-157.ec2.internal   Ready     <none>    2m        v1.10.3

問題なさそうですね。

一応、guest bookアプリもやっておきます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-master-controller.json
replicationcontroller "redis-master" created
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-master-service.json
service "redis-master" created
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-slave-controller.json
replicationcontroller "redis-slave" created
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/redis-slave-service.json
service "redis-slave" created
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/guestbook-controller.json
replicationcontroller "guestbook" created
$ kubectl apply -f https://raw.githubusercontent.com/kubernetes/kubernetes/v1.10.3/examples/guestbook-go/guestbook-service.json
service "guestbook" created
$ kubectl get services -o wide
NAME           TYPE           CLUSTER-IP       EXTERNAL-IP                                                             PORT(S)          AGE       SELECTOR
guestbook      LoadBalancer   10.100.178.116   ad0f4fcee692d11e88ee612f8cc97e4d-88389123.us-east-1.elb.amazonaws.com   3000:32656/TCP   5m        app=guestbook
kubernetes     ClusterIP      10.100.0.1       <none>                                                                  443/TCP          47m       <none>
redis-master   ClusterIP      10.100.24.130    <none>                                                                  6379/TCP         6m        app=redis,role=master
redis-slave    ClusterIP      10.100.195.26    <none>                                                                  6379/TCP         5m        app=redis,role=slave

出来ました。 ブラウザからアクセスしてみます。

guestbook よさそうですね。

動作確認が出来たらもういらないのでguestbookは消してしまいます。

1
2
3
4
5
6
7
$ kubectl delete rc/redis-master rc/redis-slave rc/guestbook svc/redis-master svc/redis-slave svc/guestbook
replicationcontroller "redis-master" deleted
replicationcontroller "redis-slave" deleted
replicationcontroller "guestbook" deleted
service "redis-master" deleted
service "redis-slave" deleted
service "guestbook" deleted

はい。 なかなか手数は多いですが、難しいことはあまりありませんでした。 AWS CLIが暗黙的に使われてて、Optionalとか書かれてたのがちょっとくせ者ですね。


  1. GA: Generally Availableの略。一般にProduction Readyと同じような意味合いで取られることが多い。 ↩︎

  2. だいたいは選択出来るUIなので、判別出来るならいらないですが ↩︎