zaki work log

作業ログやら生活ログやらなんやら

[AWS/EKS] eksctlコマンドを使ってK8sクラスタをコマンド1発で作成・削除

EKSのCLIツールであるeksctlを使ってEKSクラスタを作った時のメモ。
必要な操作はすべて公式ドキュメントに載っているので、野良記事を参考にせずに公式ドキュメントを見ること。

docs.aws.amazon.com

CLIツールをインストール

  • aws
  • kubectl
  • eksctl

の3つを用意。

awsはこちら

zaki-hmkc.hatenablog.com

kubectlkubeadm使って構築した時のkubectlがあるのでそれをそのまま使用。
(新たにインストールはしていない)

zaki-hmkc.hatenablog.com

そしてeksctl
と言ってもバイナリ落として/usr/local/binに配置するだけ。

[zaki@cloud-dev eksctl]$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
[zaki@cloud-dev eksctl]$ sudo mv /tmp/eksctl /usr/local/bin/
[zaki@cloud-dev eksctl]$ eksctl version
0.23.0

ちなみにこれらは全てAWSとは関係ない自宅PCのLinux(CentOS 7)に入れている。

EKSクラスタの作成

WebコンソールでEC2でVM作っていろいろ始めようとしたとき、ネットワークやら何やらいろいろ作成した面倒な記憶があったけど、eksctl使ったクラスタ作成は、コマンド1発。

ヘルプメッセージを見たかったのに、やらかしてhelpという名前のクラスタを作成する際の実行例です。

[zaki@cloud-dev eksctl]$ eksctl create cluster help
[ℹ]  eksctl version 0.23.0
[ℹ]  using region ap-northeast-1
[ℹ]  setting availability zones to [ap-northeast-1d ap-northeast-1a ap-northeast-1c]
[ℹ]  subnets for ap-northeast-1d - public:192.168.0.0/19 private:192.168.96.0/19
[ℹ]  subnets for ap-northeast-1a - public:192.168.32.0/19 private:192.168.128.0/19
[ℹ]  subnets for ap-northeast-1c - public:192.168.64.0/19 private:192.168.160.0/19
[ℹ]  nodegroup "ng-fe9db98d" will use "ami-0f3b1f2c30ccbc54d" [AmazonLinux2/1.16]
[ℹ]  using Kubernetes version 1.16
[ℹ]  creating EKS cluster "help" in "ap-northeast-1" region with un-managed nodes
[ℹ]  will create 2 separate CloudFormation stacks for cluster itself and the initial nodegroup
[ℹ]  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=ap-northeast-1 --cluster=help'
[ℹ]  CloudWatch logging will not be enabled for cluster "help" in "ap-northeast-1"
[ℹ]  you can enable it with 'eksctl utils update-cluster-logging --region=ap-northeast-1 --cluster=help'
[ℹ]  Kubernetes API endpoint access will use default of {publicAccess=true, privateAccess=false} for cluster "help" in "ap-northeast-1"
[ℹ]  2 sequential tasks: { create cluster control plane "help", 2 sequential sub-tasks: { no tasks, create nodegroup "ng-fe9db98d" } }
[ℹ]  building cluster stack "eksctl-help-cluster"
[ℹ]  deploying stack "eksctl-help-cluster"
[ℹ]  building nodegroup stack "eksctl-help-nodegroup-ng-fe9db98d"
[ℹ]  --nodes-min=2 was set automatically for nodegroup ng-fe9db98d
[ℹ]  --nodes-max=2 was set automatically for nodegroup ng-fe9db98d
[ℹ]  deploying stack "eksctl-help-nodegroup-ng-fe9db98d"
[ℹ]  waiting for the control plane availability...
[✔]  saved kubeconfig as "/home/zaki/.kube/config"
[ℹ]  no tasks
[✔]  all EKS cluster resources for "help" have been created
[ℹ]  adding identity "arn:aws:iam::********:role/eksctl-help-nodegroup-ng-fe9db98d-NodeInstanceRole-********" to auth ConfigMap
[ℹ]  nodegroup "ng-fe9db98d" has 0 node(s)
[ℹ]  waiting for at least 2 node(s) to become ready in "ng-fe9db98d"
[ℹ]  nodegroup "ng-fe9db98d" has 2 node(s)
[ℹ]  node "ip-192-168-29-220.ap-northeast-1.compute.internal" is ready
[ℹ]  node "ip-192-168-83-201.ap-northeast-1.compute.internal" is ready
[ℹ]  kubectl command should work with "/home/zaki/.kube/config", try 'kubectl get nodes'
[✔]  EKS cluster "help" in "ap-northeast-1" region is ready
[zaki@cloud-dev eksctl]$

作成中はwebコンソールで見ると「作成中」になってるのが分かる。

f:id:zaki-hmkc:20200707000557p:plain

timeコマンドもつけ忘れてたから正確にはわからないけど、たぶん20分くらいでクラスタ完成。

認証情報

この時点で~/.kube/configも更新されて、作成したEKSクラスタの認証情報が設定される。

[zaki@cloud-dev eksctl]$ kubectl config get-contexts
CURRENT   NAME                                 CLUSTER                         AUTHINFO                             NAMESPACE
          kubernetes-admin@kubernetes          kubernetes                      kubernetes-admin
*         zaki@help.ap-northeast-1.eksctl.io   help.ap-northeast-1.eksctl.io   zaki@help.ap-northeast-1.eksctl.io

version

[zaki@cloud-dev eksctl]$ kubectl version
Client Version: version.Info{Major:"1", Minor:"18", GitVersion:"v1.18.5", GitCommit:"e6503f8d8f769ace2f338794c914a96fc335df0f", GitTreeState:"clean", BuildDate:"2020-06-26T03:47:41Z", GoVersion:"go1.13.9", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.8-eks-e16311", GitCommit:"e163110a04dcb2f39c3325af96d019b4925419eb", GitTreeState:"clean", BuildDate:"2020-03-27T22:37:12Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"linux/amd64"}

ノード情報

オプション無しでクラスタ作成したときのノード情報。

[zaki@cloud-dev eksctl]$ kubectl get node
NAME                                                STATUS   ROLES    AGE     VERSION
ip-192-168-29-220.ap-northeast-1.compute.internal   Ready    <none>   3m58s   v1.16.8-eks-fd1ea7
ip-192-168-83-201.ap-northeast-1.compute.internal   Ready    <none>   3m58s   v1.16.8-eks-fd1ea7

ノードのスペック情報

[zaki@cloud-dev eksctl]$ kubectl describe node ip-192-168-29-220.ap-northeast-1.compute.internal
Name:               ip-192-168-29-220.ap-northeast-1.compute.internal
Roles:              <none>
:
:
Capacity:
  attachable-volumes-aws-ebs:  25
  cpu:                         2
  ephemeral-storage:           83873772Ki
  hugepages-1Gi:               0
  hugepages-2Mi:               0
  memory:                      7865020Ki
  pods:                        29
Allocatable:
  attachable-volumes-aws-ebs:  25
  cpu:                         1930m
  ephemeral-storage:           76224326324
  hugepages-1Gi:               0
  hugepages-2Mi:               0
  memory:                      5875388Ki
  pods:                        29

Webで確認するとこの通りで、m5.largeインスタンスがノードとして作成されたのが分かる。

f:id:zaki-hmkc:20200707000656p:plain

namespaceとpod

[zaki@cloud-dev eksctl]$ kubectl get ns
NAME              STATUS   AGE
default           Active   13m
kube-node-lease   Active   13m
kube-public       Active   13m
kube-system       Active   13m
[zaki@cloud-dev eksctl]$ kubectl get pod -A
NAMESPACE     NAME                      READY   STATUS    RESTARTS   AGE
kube-system   aws-node-gflrw            1/1     Running   0          5m38s
kube-system   aws-node-w4rz9            1/1     Running   0          5m38s
kube-system   coredns-cdd78ff87-kbwsf   1/1     Running   0          13m
kube-system   coredns-cdd78ff87-krws4   1/1     Running   0          13m
kube-system   kube-proxy-9w4xg          1/1     Running   0          5m38s
kube-system   kube-proxy-zh99j          1/1     Running   0          5m38s

サンプルアプリ(自前)

こんなマニフェストでデプロイしてみる。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: sample-http
  name: sample-http
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-http
  template:
    metadata:
      labels:
        app: sample-http
    spec:
      containers:
      - image: httpd
        name: httpd
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: sample-http
  name: sample-http
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: sample-http
  type: LoadBalancer
[zaki@cloud-dev sample]$ kubectl apply -f sample-http.yaml 
deployment.apps/sample-http created
service/sample-http created

type:LoadBalancer Serviceが作成される。

[zaki@cloud-dev sample]$ kubectl get svc
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP                                                                   PORT(S)        AGE
kubernetes    ClusterIP      10.100.0.1      <none>                                                                        443/TCP        15m
sample-http   LoadBalancer   10.100.58.190   ac728d278df6846269a1ebf87b983b98-497542522.ap-northeast-1.elb.amazonaws.com   80:32106/TCP   6s

確認し忘れたけど、webコンソールで見てもロードバランサーが作成されてたはず。

[zaki@cloud-dev sample]$ kubectl get pod
NAME                           READY   STATUS    RESTARTS   AGE
sample-http-748f7cdcf4-4d4qt   1/1     Running   0          68s
sample-http-748f7cdcf4-jslz8   1/1     Running   0          68s

DNSの名前解決ができるようになるまでちょっとタイムラグあるけど

[zaki@cloud-dev sample]$ curl ac728d278df6846269a1ebf87b983b98-497542522.ap-northeast-1.elb.amazonaws.com
<html><body><h1>It works!</h1></body></html>

f:id:zaki-hmkc:20200706231014p:plain

この通り。

クラスタ一覧

[zaki@cloud-dev sample]$ eksctl get cluster 
NAME    REGION
help    ap-northeast-1

今作ったhelpという名前のクラスタがある。

クラスタ削除

[zaki@cloud-dev sample]$ eksctl delete cluster help
[ℹ]  eksctl version 0.23.0
[ℹ]  using region ap-northeast-1
[ℹ]  deleting EKS cluster "help"
[ℹ]  deleted 0 Fargate profile(s)
[✔]  kubeconfig has been updated
[ℹ]  cleaning up LoadBalancer services
[ℹ]  2 sequential tasks: { delete nodegroup "ng-fe9db98d", delete cluster control plane "help" [async] }
[ℹ]  will delete stack "eksctl-help-nodegroup-ng-fe9db98d"
[ℹ]  waiting for stack "eksctl-help-nodegroup-ng-fe9db98d" to get deleted
[ℹ]  will delete stack "eksctl-help-cluster"
[✔]  all cluster resources were deleted

削除は5分ほど。
削除されると~/.kube/configからも消える。

[zaki@cloud-dev sample]$ kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
          kubernetes-admin@kubernetes   kubernetes   kubernetes-admin

--help

[zaki@cloud-dev sample]$ eksctl create cluster --help
Create a cluster

Usage: eksctl create cluster [flags]

General flags:
  -n, --name string               EKS cluster name (generated if unspecified, e.g. "attractive-sheepdog-1594048272")
      --tags stringToString       Used to tag the AWS resources. List of comma separated KV pairs "k1=v1,k2=v2" (default [])
  -r, --region string             AWS region
      --zones strings             (auto-select if unspecified)
      --version string            Kubernetes version (valid options: 1.14, 1.15, 1.16) (default "1.16")
  -f, --config-file string        load configuration from a file (or stdin if set to '-')
      --timeout duration          maximum waiting time for any long-running operation (default 25m0s)
      --install-vpc-controllers   Install VPC controller that's required for Windows workloads
      --managed                   Create EKS-managed nodegroup
      --fargate                   Create a Fargate profile scheduling pods in the default and kube-system namespaces onto Fargate

Initial nodegroup flags:
      --nodegroup-name string          name of the nodegroup (generated if unspecified, e.g. "ng-e7cda11c")
      --without-nodegroup              if set, initial nodegroup will not be created
  -t, --node-type string               node instance type (default "m5.large")
  -N, --nodes int                      total number of nodes (for a static ASG) (default 2)
  -m, --nodes-min int                  minimum nodes in ASG (default 2)
  -M, --nodes-max int                  maximum nodes in ASG (default 2)
      --node-volume-size int           node volume size in GB (default 80)
      --node-volume-type string        node volume type (valid options: gp2, io1, sc1, st1) (default "gp2")
      --max-pods-per-node int          maximum number of pods per node (set automatically if unspecified)
      --ssh-access                     control SSH access for nodes. Uses ~/.ssh/id_rsa.pub as default key path if enabled
      --ssh-public-key string          SSH public key to use for nodes (import from local path, or use existing EC2 key pair)
      --node-ami string                Advanced use cases only. If 'ssm' is supplied (default) then eksctl will use SSM Parameter; if 'auto' is supplied then eksctl will 
automatically set the AMI based on version/region/instance type; if static is supplied (deprecated), then static AMIs will be used; if any other value is supplied it will override the AMI to use for the nodes. Use with extreme care.
      --node-ami-family string         Advanced use cases only. If 'AmazonLinux2' is supplied (default), then eksctl will use the official AWS EKS AMIs (Amazon Linux 2); 
if 'Ubuntu1804' is supplied, then eksctl will use the official Canonical EKS AMIs (Ubuntu 18.04). (default "AmazonLinux2")
  -P, --node-private-networking        whether to make nodegroup networking private
      --node-security-groups strings   Attach additional security groups to nodes, so that it can be used to allow extra ingress/egress access from/to pods
      --node-labels stringToString     Extra labels to add when registering the nodes in the nodegroup. List of comma separated KV pairs "k1=v1,k2=v2" (default [])       
      --node-zones strings             (inherited from the cluster if unspecified)
      --instance-prefix string         Add a prefix value in front of the instance's name.
      --instance-name string           Overrides the default instance's name. It can be used in combination with the instance-prefix flag.

Cluster and nodegroup add-ons flags:
      --install-neuron-plugin    Install Neuron plugin for Inferentia nodes (default true)
      --asg-access               enable IAM policy for cluster-autoscaler
      --external-dns-access      enable IAM policy for external-dns
      --full-ecr-access          enable full access to ECR
      --appmesh-access           enable full access to AppMesh
      --appmesh-preview-access   enable full access to AppMesh Preview
      --alb-ingress-access       enable full access for alb-ingress-controller

VPC networking flags:
      --vpc-cidr ipNet                 global CIDR to use for VPC (default 192.168.0.0/16)
      --vpc-private-subnets strings    re-use private subnets of an existing VPC
      --vpc-public-subnets strings     re-use public subnets of an existing VPC
      --vpc-from-kops-cluster string   re-use VPC from a given kops cluster
      --vpc-nat-mode string            VPC NAT mode, valid options: HighlyAvailable, Single, Disable (default "Single")

AWS client flags:
  -p, --profile string        AWS credentials profile to use (overrides the AWS_PROFILE environment variable)
      --cfn-role-arn string   IAM role used by CloudFormation to call AWS API on your behalf

Output kubeconfig flags:
      --kubeconfig string               path to write kubeconfig (incompatible with --auto-kubeconfig) (default "/home/zaki/.kube/config")
      --authenticator-role-arn string   AWS IAM role to assume for authenticator
      --set-kubeconfig-context          if true then current-context will be set in kubeconfig; if a context is already set then it will be overwritten (default true)    
      --auto-kubeconfig                 save kubeconfig file by cluster name, e.g. "/home/zaki/.kube/eksctl/clusters/attractive-sheepdog-1594048272"
      --write-kubeconfig                toggle writing of kubeconfig (default true)

Common flags:
  -C, --color string   toggle colorized logs (valid options: true, false, fabulous) (default "true")
  -h, --help           help for this command
  -v, --verbose int    set log level, use 0 to silence, 4 for debugging and 5 for debugging with AWS debug logging (default 3)

Use 'eksctl create cluster [command] --help' for more information about a command.

helpじゃなくて--helpにすれば、ちゃんと見れる。

  -t, --node-type string               node instance type (default "m5.large")

デフォルトでm5.largeのノードが作成されるのはこのオプションによるもの。
また、デフォルトではeksctl create clusterでノードグループが作成されるが、別途ノードグループを作成しておいて、それを後からアタッチするなど柔軟な構築もできる。
(その辺また別記事にしよう。。ちなみにinductorさんに少しお話聞いてみたら、普通は別々に作る方が良いらしい)


kubeadmで手作りもいいぞ

zaki-hmkc.hatenablog.com