継続は力なり

タイトル通り定期的な更新を心掛けるブログです。

Amazon EKS の構築・運用のエッセンスを学べる「 Amazon EKS Workshop」の紹介

タダです。

Amazon EKS(以下、EKS)が昨年東京リージョンに対応しました。 aws.amazon.com

東京リージョンに EKS がきたことで利用検討されている方も多いのではないでしょうか?

今回は、EKS の実践的な使い方を学べるワークショップに触れてみたので、ワークショップでどんなことを学べるのかを紹介します。 eksworkshop.com

TL;DR

記事の概要です。

  • EKS のワークショップで次のことを学べる
    • Kubernetes の基本的な用語とアーキテクチャ、 EKS の概要
    • CLI ツールによる EKS の作成/削除
    • パッケージマネージャの導入と、パッケージ管理方法
    • ログ基盤の構成例
    • AWS サービスでの CI / CD の構成例
    • スケールアウトの構成例
    • 監視設定の構成例

ワークショップの詳細

ワークショップでは、基本的にコマンド操作のみで完了するよう構成されています。

また、ワークショップ全体がボリュームがあるのですが、所要時間の目安として「約2~3時間」になります。

以下では、各章のサマリーを記載していくことにしていきます。

Kubernetes の基本的な用語とアーキテクチャ

Kubernetes の基本的な用語(オブジェクト)として以下のものが紹介されています。

  • Nodes: クラスターを構成するマシンを指す。マスターノードとワーカーノードの2種類がある。
  • Pod : Kubernetesで作成および管理できる、デプロイ可能な最小のコンピューティング単位である。
  • ReplicaSet : 定義された数の Pod が常に実行するための仕組み。
  • DaemonSet : ワーカーノードに Pod の単一インスタンスを実装する。
  • Deployment : 複数の ReplicaSet を管理することで、ローリングアップデートやロールバックなどを実現可能にするリソース。
  • Job : コンテナを利用して一度限りの処理を実行させるリソース。
  • Services : 固定IPを Pod の論理グループに割り当てる。
  • Label : Kubernetes 上のオブジェクトに関連付けとフィルタリングに使用されるキーと値のペア。

Kubernetesアーキテクチャ概要

Kubernetesアーキテクチャは次の3つで構成されています。

  • Cotrol Plane
    • API Servers: REST / kubectl のためのエンドポイントを提供する。
    • etcd: 分散型のキーバリューストア。
    • Controller-manager: ステータス管理。
    • Scheduler: ワーカーノードへ Pod のスケジューリングを行う。
  • Data Plane : ワーカーノードで構成されている。
    • kubelet:APIサーバーとノード間のコンジットとして機能する。
    • kube-proxy:IP変換とルーティングを管理する。

Kubernetes の管理ツール

EKS 及び Kubenetes の管理ツールとして以下のものが紹介されています。

調べた限りですが、他に以下のツールもあります。

EKS の概要

EKS は KubernetesAWS 上で簡単に展開できるフルマネージドサービスです。

EKS を構成するのは、AWSが管理するコントロールプレーン(マスターノード)と、ユーザーが管理するデータプレーン(ワーカーノード)になります。

3つの Availability Zone をまたいだマスターノードのプロビジョニングやスケールがユーザーが管理不要な点が特徴です。

また、異常なコントロールプレーンノードを自動的に検出して置き換え、コントロールプレーンへのパッチもしてくれます。

料金

料金としては以下の2要素で構成されています。

  • EKS クラスターごとに、1 時間あたり $0.20。
  • ワーカーノード実行用の EC2 インスタンス、EBS ボリュームなどに対して料金がかかる。
    • 通常の EC2 や EBS と課金モデルは同じです。

事前準備

事前準備では次のことを行います。

  • AWS Cloud9(以下、Cloud9)環境を作る。
  • kubectlaws-iam-authenticatorjq をインストールする。
  • アプリケーションのソースコードを clone する。
  • Cloud9 の EC2 インスタンスに IAM ロールをアタッチする。
  • Cloud9 のクレデンシャル設定を行う。

ツールのインストールは以下のコマンドで実行します。

# kubectl インストール
$ sudo curl --silent --location -o /usr/local/bin/kubectl "https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-07-26/bin/linux/amd64/kubectl"
$ sudo chmod +x /usr/local/bin/kubectl

# IAM Authenticator インストール
$ go get -u -v github.com/kubernetes-sigs/aws-iam-authenticator/cmd/aws-iam-authenticator
$ sudo mv ~/go/bin/aws-iam-authenticator /usr/local/bin/aws-iam-authenticator

# jq インストール
sudo yum -y install jq

Cloud9 のクレデンシャル設定で、EKS などリソース作成のデフォルトのリージョンを設定します。

シンガポールリージョンの Cloud9 を利用したので、「ap-southeast-1」になっています。

$ export AWS_REGION=$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r .region)
$ echo "export AWS_REGION=${AWS_REGION}" >> ~/.bash_profile
$ aws configure set default.region ${AWS_REGION}
$ aws configure get default.region
ap-southeast-1

参考情報

docs.aws.amazon.com

EKS クラスターの作成

次に、EKS クラスターを作ります。

ワークショップではeksctlというCLIツールを使って EKS クラスターを作ります。バージョンは0.1.23です。

eksctl.io

$ eksctl version
[]  version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.1.23"}

クラスターを作るのは以下のコマンドで実行し、3つのノードを作ります。クラスター起動には約15分ほどかかります。

$ eksctl create cluster --name=eksworkshop-eksctl --nodes=3 --node-ami=auto --region=${AWS_REGION}
[]  using region ap-southeast-1
[]  setting availability zones to [ap-southeast-1a ap-southeast-1c ap-southeast-1b]
[]  subnets for ap-southeast-1a - public:192.168.0.0/19 private:192.168.96.0/19
[]  subnets for ap-southeast-1c - public:192.168.32.0/19 private:192.168.128.0/19
[]  subnets for ap-southeast-1b - public:192.168.64.0/19 private:192.168.160.0/19
[]  nodegroup "ng-74de009b" will use "ami-038d55c26bf01998f" [AmazonLinux2/1.11]
[]  creating EKS cluster "eksworkshop-eksctl" in "ap-southeast-1" region
[]  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-southeast-1 --name=eksworkshop-eksctl'
[]  creating cluster stack "eksctl-eksworkshop-eksctl-cluster"
[]  creating nodegroup stack "eksctl-eksworkshop-eksctl-nodegroup-ng-74de009b"
[]  --nodes-min=3 was set automatically for nodegroup ng-74de009b
[]  --nodes-max=3 was set automatically for nodegroup ng-74de009b
[]  all EKS cluster resource for "eksworkshop-eksctl" had been created
[]  saved kubeconfig as "/home/ec2-user/.kube/config"
[]  nodegroup "ng-74de009b" has 0 node(s)
[]  waiting for at least 3 node(s) to become ready in "ng-74de009b"
[]  nodegroup "ng-74de009b" has 3 node(s)
[]  node "ip-192-168-16-181.ap-southeast-1.compute.internal" is ready
[]  node "ip-192-168-49-231.ap-southeast-1.compute.internal" is ready
[]  node "ip-192-168-75-222.ap-southeast-1.compute.internal" is ready
[]  kubectl command should work with "/home/ec2-user/.kube/config", try 'kubectl get nodes'
[]  EKS cluster "eksworkshop-eksctl" in "ap-southeast-1" region is ready

クラスターが立ち上がった後、kubectl get nodes で3つのノードがいるのでOKです。

$ kubectl get nodes
NAME                                                STATUS    ROLES     AGE       VERSION
ip-192-168-16-181.ap-southeast-1.compute.internal   Ready     <none>    1m        v1.11.5
ip-192-168-49-231.ap-southeast-1.compute.internal   Ready     <none>    1m        v1.11.5
ip-192-168-75-222.ap-southeast-1.compute.internal   Ready     <none>    1m        v1.11.5

管理画面の起動

Kubernetes では管理画面が標準であるため、アクセスしてクラスターの状態を確認します。

ただ、ワークショップに記載のコマンドですとエラーで失敗してしまいます。

 $ kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
error: unable to read URL "https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml", server reported 404 Not Found, status code=404

指定する URL に誤りがあるようなので、以下のコマンドであれば起動します。削除するときも同様です。

$ kubectl create -f https://raw.githubusercontent.com/kubernetes/dashboard/master/aio/deploy/recommended/kubernetes-dashboard.yaml
secret "kubernetes-dashboard-certs" created
secret "kubernetes-dashboard-csrf" created
serviceaccount "kubernetes-dashboard" created
role.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
rolebinding.rbac.authorization.k8s.io "kubernetes-dashboard-minimal" created
deployment.apps "kubernetes-dashboard" created
service "kubernetes-dashboard" created
$ kubectl proxy --port=8080 --address='0.0.0.0' --disable-filter=true &

また、管理画面へはaws-iam-authenticatorで発行されるトークンを使ってログインできるためこの機能を使います。以下のコマンドの実行した際に出力される文字列を控えて、ログイン確認しましょう。

 $ aws-iam-authenticator token -i eksworkshop-eksctl --token-only

管理画面にアクセスできました。

f:id:sadayoshi_tada:20190311074906p:plain

サンプルアプリケーションのデプロイ

次に、EKS にサンプルアプリケーションをデプロイしていきます。

デプロイするのは以下のものになります。

  • NodeJS API
  • Crystal の API
  • Ruby のフロントエンド API

デプロイには、マニフェストファイルを使います。マニフェストファイルは Kubernetes の処理を定義するファイルです。

2つのファイルを適用していきます。

$ kubectl apply -f kubernetes/deployment.yaml
deployment.apps "ecsdemo-nodejs" created
 $ kubectl apply -f kubernetes/service.yaml
service "ecsdemo-nodejs" created

デプロイが完了した段階では、それぞれレプリカ数が1つずつの構成です。

$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
ecsdemo-crystal    1         1         1            1           9m
ecsdemo-frontend   1         1         1            1           4m
ecsdemo-nodejs     1         1         1            1           11m

サンプルアプリケーションにアクセスしてみると、以下のようなページが表示されます。

f:id:sadayoshi_tada:20190311201943p:plain

レプリカのスケールアウト

これをスケールアウトさせます。バックエンドの NodeJS と Crystal のデプロイされたレプリカ数が3つに増えています。

 $ kubectl scale deployment ecsdemo-nodejs --replicas=3
deployment.extensions "ecsdemo-nodejs" scaled
$ kubectl scale deployment ecsdemo-crystal --replicas=3
deployment.extensions "ecsdemo-crystal" scaled
$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
ecsdemo-crystal    3         3         3            1           10m
ecsdemo-frontend   1         1         1            1           6m
ecsdemo-nodejs     3         3         3            1           13m

フロントエンド側もスケールさせます。これで最初のデプロイ時点では1つでしか受けていなかったリクエストを複数のフロントエンド API が受ける形になりました。

$ kubectl scale deployment ecsdemo-frontend --replicas=3
deployment.extensions "ecsdemo-frontend" scaled
$ kubectl get deployments
NAME               DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
ecsdemo-crystal    3         3         3            3           16m
ecsdemo-frontend   3         3         3            3           12m
ecsdemo-nodejs     3         3         3            3           19m

再度、サンプルアプリケーションのページにアクセスすると、トラフィックの振り先がランダムになりました。

最初に確認した際は、単一でしたが複数のコンテナでリクエストを受けられるようになりました。

f:id:sadayoshi_tada:20190311202103p:plain f:id:sadayoshi_tada:20190311202028p:plain

Kubernetes のパッケージ管理ツール Helm の導入

Kubernetes のパッケージ管理ツール Helm を導入します。

helm.sh

まず、初期セットアップを行います。

$ curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  7234  100  7234    0     0  17431      0 --:--:-- --:--:-- --:--:-- 17389
$ chmod +x get_helm.sh
$ ./get_helm.sh
Downloading https://kubernetes-helm.storage.googleapis.com/helm-v2.13.0-linux-amd64.tar.gz
Preparing to install helm and tiller into /usr/local/bin
helm installed into /usr/local/bin/helm
tiller installed into /usr/local/bin/tiller
Run 'helm init' to configure helm.

Helm は、Kubernetes に対する特別な許可を必要とするtiller と呼ばれるサービスに依存しているので、tillerが使用するサービスアカウントを作成する必要があります。

github.com

これをクラスタに適用するために、サービスアカウント用マニフェストファイルを作ります。

$ cat <<EoF > ~/environment/rbac.yaml
> ---
> apiVersion: v1
> kind: ServiceAccount
> metadata:
>   name: tiller
>   namespace: kube-system
> ---
> apiVersion: rbac.authorization.k8s.io/v1beta1
> kind: ClusterRoleBinding
> metadata:
>   name: tiller
> roleRef:
>   apiGroup: rbac.authorization.k8s.io
>   kind: ClusterRole
>   name: cluster-admin
> subjects:
>   - kind: ServiceAccount
>     name: tiller
>     namespace: kube-system
> EoF
$ kubectl apply -f ~/environment/rbac.yaml
serviceaccount "tiller" created
clusterrolebinding.rbac.authorization.k8s.io "tiller" created
$ helm init --service-account tiller
Creating /home/ec2-user/.helm 
Creating /home/ec2-user/.helm/repository 
Creating /home/ec2-user/.helm/repository/cache 
Creating /home/ec2-user/.helm/repository/local 
Creating /home/ec2-user/.helm/plugins 
Creating /home/ec2-user/.helm/starters 
Creating /home/ec2-user/.helm/cache/archive 
Creating /home/ec2-user/.helm/repository/repositories.yaml 
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com 
Adding local repo with URL: http://127.0.0.1:8879/charts 
$HELM_HOME has been configured at /home/ec2-user/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
To prevent this, run `helm init` with the --tiller-tls-verify flag.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

これで設定が完了のため、クラスタ内のリソースを管理できるようになります。

Helm を使って Jenkins をデプロイする

試しにHelm を使って Jenkins をデプロイします。

helm install stable/jenkins --set rbac.install=true --name cicd

上記のコマンド実行後、 Jenkins の管理画面ヘアクセスするための情報が出力されるため順次実行します。

$ printf $(kubectl get secret --namespace default cicd-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo
xxxxxxxx # admin ユーザーのパスワード
$ export SERVICE_IP=$(kubectl get svc --namespace default cicd-jenkins --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
$ echo http://$SERVICE_IP:8080/login
http://acc58d1ea435c11e9820806e6ac3f061-1693712465.ap-southeast-1.elb.amazonaws.com:8080/login # ログインのURL

URL先にアクセスしてみて、ログイン確認もできました。 f:id:sadayoshi_tada:20190311025536p:plain

EFK でのログ管理基盤の構成

EKS のログ管理基盤を構成を行うチャプターになります。

Fluentd / ElasticSearch / Kibana を使ってログの収集と保存、可視化を行います。

これら3つを合わせて「EFK スタック」と呼ばれています。

Fluentd で CloudWatch Logs に EKS のログを出力し、 Amazon Elasticsearch(以下、AES) でログの取り込みと、 Kibana による可視化します。

IAM ロールへログ用のポリシー追加

クラスター作成時に、作成された IAM ロール(eksctl-eksworkshop-eksctl-nodegro-NodeInstanceRole-xxxx)にログ用のポリシーを追加します。

追加する IAM ポリシーは以下の通りです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:DescribeLogGroups",
                "logs:DescribeLogStreams",
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

注意点として、ワークショップで実行するコマンドで、以下のコマンドがあります。ただ、このコマンドはスタック名に誤りがある等後続処理が失敗します。

INSTANCE_PROFILE_PREFIX=$(aws cloudformation describe-stacks --stack-name eksctl-eksworkshop-eksctl-nodegroup-0 | jq -r '.Stacks[].Outputs[].ExportName' | sed 's/:.*//')
INSTANCE_PROFILE_NAME=$(aws iam list-instance-profiles | jq -r '.InstanceProfiles[].InstanceProfileName' | grep $INSTANCE_PROFILE_PREFIX)
ROLE_NAME=$(aws iam get-instance-profile --instance-profile-name $INSTANCE_PROFILE_NAME | jq -r '.InstanceProfile.Roles[] | .RoleName')

そのため、ここで設定したいのはワーカーノードの IAM ロール名になりますので、 CloudFormation の出力から個々に確認するのが良いかと思います。

ROLE_NAME=$(aws iam get-instance-profile --instance-profile-name eksctl-eksworkshop-eks-nodegroup-ng-d3bf1805-NodeInstanceProfile-1LHFYP99YV221 | jq -r '.InstanceProfile.Roles[] | .RoleName')

AES を作成する

AES を作成します。

aws es create-elasticsearch-domain \
  --domain-name kubernetes-logs \
  --elasticsearch-version 6.3 \
  --elasticsearch-cluster-config \
  InstanceType=m4.large.elasticsearch,InstanceCount=2 \
  --ebs-options EBSEnabled=true,VolumeType=standard,VolumeSize=100 \
  --access-policies '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},"Action":["es:*"],"Resource":"*"}]}'

以下のようにfalseステータスになりましたら、完了です。

$ aws es describe-elasticsearch-domain --domain-name kubernetes-logs --query 'DomainStatus.Processing'
false

Fluentd をセットアップする

Flunetd をセットアップします。

Fluentd ログエージェント設定は Kubernetes ConfigMap にあります。

Fluentd は ワーカーノードごとに1つの Pod として展開されます。

ワークショップでは、3ノードクラスタが使用されているため、展開すると3つの Pod が出力に表示されます。

$ kubectl get pods -w --namespace=kube-system
NAME                                    READY     STATUS    RESTARTS   AGE
~中略~
fluentd-cloudwatch-98xvb                1/1       Running   0          1m
fluentd-cloudwatch-hqdzd                1/1       Running   0          1m
fluentd-cloudwatch-hrxfw                1/1       Running   0          1m
~中略~

CloudWatch Logs にも出力されています。 f:id:sadayoshi_tada:20190310190944p:plain

CloudWatch Logs のログを AES に統合する

CloudWatch Logs のログには AES に統合機能があります。

機能自体の詳細は以下のドキュメントを参照ください。

docs.aws.amazon.com

統合した結果、ログが Kibana でも閲覧可能な状態になりました。 f:id:sadayoshi_tada:20190310191841p:plain

CI / CD フローの作成

AWS CodePipeline(以下、Codepipeline)と、AWS CodeBuild(以下、CodeBuild)を使って、CI / CD フローを作ります。

CodeBuild の IAM ロールを作成する

kubectl を介して EKS クラスターへアクセスするために CodeBuild で使用するインラインポリシーを追加します。

IAM ポリシーとしては以下のものを追加します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "eks:Describe*",
            "Resource": "*"
        }
    ]
}

信頼関係として以下のものを追加します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxxx:role/eksworkshop-codepipeline-CodeBuildServiceRole-1R93P86RZPBW6"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::xxxxxxxxxxxxx:role:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

ConfigMap に上記のロールを含める設定を行うと、パイプラインのCodeBuild のkubectl は IAM ロールを介して EKSクラスターにアクセスできるようになります。

docs.aws.amazon.com

ソースコードのデプロイ

GitHub の以下のソースコードforkします。

github.com

上記のソースを変更したことをトリガーに CodePipeline と CodeBuild がソースコードをビルドして、デプロイされます。

Hello World!」と表示されるところを、「Hello EKS World!!」に変更してデプロイします。

環境にアクセスしてみると、編集したメッセージが表示されました。

f:id:sadayoshi_tada:20190312052607p:plain

Kubernetes のスケーリング

Kubernetes のスケーリングには次の2つのパターンがあり、2つのパターンを実践します。

  • Horizontal Pod Autoscaler (HPA) : レプリカセット内の Pod をスケールイン/アウトする。
  • Cluster Autoscaler(CA) : Kubernetes のデフォルトコンポーネントクラスターノードと、Pod もスケールさせる。

Horizontal Pod Autoscaler の設定と実践

Metrics Server は、リソース使用量データをクラスター全体で集約し、スケールアウトのための材料とします。

Helmで以下のコマンドを実行します。

helm install stable/metrics-server \
    --name metrics-server \
    --version 2.0.2 \
    --namespace metrics

サンプルアプリをデプロイし、CPU 50%を超えたらスケーリングされるよう設定します。

kubectl run php-apache --image=k8s.gcr.io/hpa-example --requests=cpu=200m --expose --port=80
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10

意図的に負荷をかけてみます。

kubectl run -i --tty load-generator --image=busybox /bin/sh
while true; do wget -q -O - http://php-apache; done

負荷が増えると、レプリカの数が増えました。

kubectl get hpa -w
NAME         REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
php-apache   Deployment/php-apache   59%/50%   1         10        8          8m

Cluster Autoscale の設定と実践

Cluster Autoscaler は Auto Scaling グループとの統合が可能で、4つのオプションがあります。

  • One Auto Scaling group
  • Multiple Auto Scaling groups
  • Auto-Discovery
  • Master Node setup

Auto Scaling と Cluster Autoscaler の設定を行う必要があります。

Auto Scaling は Auto Scaling グループの最小と最大の数を編集し、Cluster Autoscaler は設定ファイルの以下の--nodesと、envのリージョンを変更します。

command:
  - ./cluster-autoscaler
  - --v=4
  - --stderrthreshold=info
  - --cloud-provider=aws
  - --skip-nodes-with-local-storage=false
  - --nodes=2:8:eksctl-eksworkshop-eksctl-nodegroup-ng-74de009b-NodeGroup-26BV6BK2H39E
env:
  - name: AWS_REGION
     value: ap-southeast-1

そして、ワーカーノードの IAM インスタンスプロファイルを設定します。

{
    "RoleName": "eksctl-eksworkshop-eksctl-nodegro-NodeInstanceRole-67FXBWETY0OH", 
    "PolicyDocument": {
        "Version": "2012-10-17", 
        "Statement": [
            {
                "Action": [
                    "autoscaling:DescribeAutoScalingGroups", 
                    "autoscaling:DescribeAutoScalingInstances", 
                    "autoscaling:SetDesiredCapacity", 
                    "autoscaling:TerminateInstanceInAutoScalingGroup"
                ], 
                "Resource": "*", 
                "Effect": "Allow"
            }
        ]
    }, 
    "PolicyName": "ASG-Policy-For-Worker"
}

アプリケーションのデプロイを行い、レプリカのスケーリングを行ってみます。

kubectl apply -f ~/environment/cluster-autoscaler/cluster_autoscaler.yml
$ kubectl get deployment/nginx-to-scaleout
NAME                DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-to-scaleout   1         1         1            0           2s
$ kubectl scale --replicas=10 deployment/nginx-to-scaleout
deployment.extensions "nginx-to-scaleout" scaled

10個のレプリカができています。

$ kubectl get pods -o wide --watch
nginx-to-scaleout-ff975c58d-7gh42   0/1       Pending   0          29s       <none>           <none>
nginx-to-scaleout-ff975c58d-9krg5   1/1       Running   0          29s       192.168.25.240   ip-192-168-16-181.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-gqq9v   1/1       Running   0          29s       192.168.55.8     ip-192-168-49-231.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-kpcxk   1/1       Running   0          29s       192.168.72.203   ip-192-168-75-222.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-llk67   1/1       Running   0          29s       192.168.30.63    ip-192-168-16-181.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-nttnc   1/1       Running   0          29s       192.168.53.56    ip-192-168-49-231.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-sqh7l   1/1       Running   0          29s       192.168.56.31    ip-192-168-49-231.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-t5nw5   1/1       Running   0          29s       192.168.12.128   ip-192-168-16-181.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-wxfr6   1/1       Running   0          1m        192.168.88.205   ip-192-168-75-222.ap-southeast-1.compute.internal
nginx-to-scaleout-ff975c58d-z9sc4   1/1       Running   0          29s       192.168.77.198   ip-192-168-75-222.ap-southeast-1.compute.internal

Prometheus と Grafana での監視

最後に、監視設定の章です。

監視ツールとして Prometheus とダッシュボードのツールとして Grafana で Kubernetes クラスターを監視します。

Prometheus の導入

Prometheus の導入を行います。

前準備としてダウンロードした、prometheus-values.yamlを次のように編集します。

# 175行目と712行目あたりのコメントアウトを外して編集する
storageClass: "prometheus"

# 767行目以降を編集する
externalIPs: []

loadBalancerIP: ""
loadBalancerSourceRanges: []
servicePort: 80
nodePort: 30900
type: NodePort

Helm で Prometheus をデプロイします。

helm install -f prometheus-values.yaml stable/prometheus --name prometheus --namespace prometheus

デプロイが期待通りに行えたかを確認します。以下の状態になっていればデプロイは成功しています。

 $ kubectl get all -n prometheus
NAME                                                READY     STATUS    RESTARTS   AGE
pod/prometheus-alertmanager-5bfcddf64-8skm4         0/2       Pending   0          5m
pod/prometheus-kube-state-metrics-7c54bd8d8-t46c6   1/1       Running   0          5m
pod/prometheus-node-exporter-dq5sj                  1/1       Running   0          5m
pod/prometheus-node-exporter-m4mx9                  1/1       Running   0          5m
pod/prometheus-node-exporter-w2crn                  1/1       Running   0          5m
pod/prometheus-pushgateway-6985db8447-rr7pj         1/1       Running   0          5m
pod/prometheus-server-7f677fdd8d-m4vpq              0/2       Pending   0          5m

NAME                                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
service/prometheus-alertmanager         ClusterIP   10.100.110.221   <none>        80/TCP         5m
service/prometheus-kube-state-metrics   ClusterIP   None             <none>        80/TCP         5m
service/prometheus-node-exporter        ClusterIP   None             <none>        9100/TCP       5m
service/prometheus-pushgateway          ClusterIP   10.100.149.87    <none>        9091/TCP       5m
service/prometheus-server               NodePort    10.100.114.114   <none>        80:30900/TCP   5m

NAME                                      DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
daemonset.apps/prometheus-node-exporter   3         3         3         3            3           <none>          5m

NAME                                            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/prometheus-alertmanager         1         1         1            0           5m
deployment.apps/prometheus-kube-state-metrics   1         1         1            1           5m
deployment.apps/prometheus-pushgateway          1         1         1            1           5m
deployment.apps/prometheus-server               1         1         1            0           5m

NAME                                                      DESIRED   CURRENT   READY     AGE
replicaset.apps/prometheus-alertmanager-5bfcddf64         1         1         0         5m
replicaset.apps/prometheus-kube-state-metrics-7c54bd8d8   1         1         1         5m
replicaset.apps/prometheus-pushgateway-6985db8447         1         1         1         5m
replicaset.apps/prometheus-server-7f677fdd8d              1         1         0         5m

Grafana の導入

Grafana の導入を行います。

grafana-values.yamlを次のように編集します。

# 74行目以下を次のように変更する
service:
  type: LoadBalancer
  port: 80
  targetPort: 3000
    # targetPort: 4181 To be used with a proxy extraContainer
  annotations: {}
  labels: {}

# 142行目を次のように変更する
storageClassName: prometheus

# 152行目を次のように変更する
adminPassword: EKS!sAWSome

# 204行目以下を次のように変更する
datasources:
 datasources.yaml:
   apiVersion: 1
   datasources:
   - name: Prometheus
     type: prometheus
     url: http://prometheus-server.prometheus.svc.cluster.local
     access: proxy
     isDefault: true

Helm で Grafana をデプロイします。

helm install -f grafana-values.yaml stable/grafana --name grafana --namespace grafana

デプロイ後の確認を行います。以下の表示が出力されば、デプロイ成功になります。

$ kubectl get all -n grafana
NAME                           READY     STATUS    RESTARTS   AGE
pod/grafana-5b8c7b48c6-szlrt   1/1       Running   0          17s

NAME              TYPE           CLUSTER-IP     EXTERNAL-IP        PORT(S)        AGE
service/grafana   LoadBalancer   10.100.22.24   ae601dcc143e9...   80:31524/TCP   17s

NAME                      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/grafana   1         1         1            1           17s

NAME                                 DESIRED   CURRENT   READY     AGE
replicaset.apps/grafana-5b8c7b48c6   1         1         1         17s

ダッシュボードの作成

Grafana でダッシュボードを作成します。

ダッシュボード ID 3131 を設定し、 Kubernetes All Nodes のメトリクスを表示させてみました。

f:id:sadayoshi_tada:20190311202337p:plain

まとめ

EKS オンラインワークショップの内容を一通り紹介しました。

EKS の構成から ログ、 CI / CD 、パッケージ管理、スケールアウト、監視など様々な実践的な内容になっています。

コンテナのワークロードにおいて、 Kubernetes を扱う事例も増えてきています。

EKS を検討する際に、体系的に学べるこのワークショップを一度触れてみてはいかがでしょうか?

参考情報

kubernetes.io docs.aws.amazon.com