この記事はBeeX Advent Calendar 2020の12/4の記事です。
直接インターネット接続不可の環境に構築したEKSのPrivate ClusterでContainer Insightsを動かそうとしたら、ハマりどころが多かったので残しておきます。
前提
Private Cluster作成後、必要なVPC Endpointが作成されていることが前提となります。VPC Endpointは以下に記載があります。
方針
当然、AWSの公式ドキュメントにもContainer Insightsの設定方法の記載はあります。ただ、Private Clusterには対応していなかったので、手順に調整が必要になります。
手順を一つ一つ説明するのも膨大なので、こちらのクイックスタートを調整する形にしたいと思います。
Amazon EKS および Kubernetes の Container Insights のクイックスタートセットアップ - Amazon CloudWatch
クイックスタートは本当にクイックで以下のワンライナー実行でデプロイ終わりです。(Private Clusterでは動きません)
curl https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluentd-quickstart.yaml | sed "s/{{cluster_name}}/cluster-name/;s/{{region_name}}/cluster-region/" | kubectl apply -f -
内部的には以下のファイルをダウンロードして一部置換して kubectl apply
しています。これを書いている時点では Gitタグが 1.2.4
が最新なので、このファイルの中身を修正してPrivate Clusterで動くContainer Insightsの定義に変更していこうと思います。
Container Insights設定事前作業
Service AccountとIAM Role作成
こちらの記事に記載したスクリプトを利用して作成します。
Amazon EKSのService Accountをawscliやkubectl使ったスクリプトで作成する - YOMON8.NET
CLUSTER_NAME=my-cluster SA_NAMESPACE=amazon-cloudwatch SA_NAME=cloudwatch-agent /bin/bash ./create_service_account.sh ${CLUSTER_NAME} ${SA_NAMESPACE} ${SA_NAME}
このために作ったスクリプトでないので、最後にnamespace無いとエラー出ますが無視します。
Error from server (NotFound): error when creating "STDIN": namespaces "amazon-cloudwatch" not found
IAM RoleにCloudWatch送信用ポリシーをアタッチ
上記のスクリプトでは eks-role-my-cluster-amazon-cloudwatch-cloudwatch-agent
というロールが作成されたので、ここに CloudWatchAgentServerPolicy
のポリシーをアタッチします。
QuickStartダウンロード
まずは方針でも書いた通りQuickStartのManufestをダウンロードして、これを調整していきます。
curl -o my-cwagent-fluentd.yaml https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/k8s/1.2.4/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluentd-quickstart.yaml
Dockerイメージ整理
Docker Hubも使えない状態を想定しますので、ECRに必要なイメージを入れておきます。
必要なイメージは先程ダウンロードしたyamlファイルから抽出できます。
$ cat my-cwagent-fluentd.yaml | grep image: image: amazon/cloudwatch-agent:1.247346.0b249609 image: busybox image: busybox image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-cloudwatch-1.0
ということで以下のようにEKSから接続できないDockerHubからECRに移動してきます。
- https://hub.docker.com/r/amazon/cloudwatch-agent
- https://hub.docker.com/_/busybox
- https://hub.docker.com/r/fluent/fluentd-kubernetes-daemonset
説明の簡素化のためにECRの方はlatestタグ使ってますが、適宜変更してください。
DockerHub | mv | ECR |
---|---|---|
amazon/cloudwatch-agent:1.247346.0b249609 | ⇒ | {ECR}/cw-insight/busybox:latest |
busybox{ECR} | ⇒ | {ECR}/cw-insight/cloudwatch-agent:latest |
fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-cloudwatch-1.0 | ⇒ | {ECR}/cw-insight/fluentd-kubernetes-daemonset:latest |
ECR側にRepositoryを作っておきます。
Dockerイメージ移動
上記で整理した通り移動してきます。この作業はDockerHubに接続可能な端末で実施する必要があります。
ACCOUNT_ID=$(aws sts get-caller-identity --query 'Account' --output text) AWS_REGION=ap-northeast-1 ECR_REPO_BASE=${ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com SRC=amazon/cloudwatch-agent:1.247346.0b249609 TGT=${ECR_REPO_BASE}/cw-insight/cloudwatch-agent:latest docker pull ${SRC} && docker tag ${SRC} ${TGT} && docker push ${TGT} SRC=fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-cloudwatch-1.0 TGT=${ECR_REPO_BASE}/cw-insight/fluentd-kubernetes-daemonset docker pull ${SRC} && docker tag ${SRC} ${TGT} && docker push ${TGT} SRC=busybox TGT=${ECR_REPO_BASE}/cw-insight/busybox docker pull ${SRC} && docker tag ${SRC} ${TGT} && docker push ${TGT}
Container Insights用マニュフェスト作成
Cluster名とRegionを設定
まずはQuickstartの手順にもある、クラスタ名とリージョン名を置換します。
CLUSTER_NAME=my-cluster AWS_REGION=ap-northeast-1 sed -i.org "s/{{cluster_name}}/${CLUSTER_NAME}/;s/{{region_name}}/${AWS_REGION}/" my-cwagent-fluentd.yaml
その他の変更点整理
その他と言いながらこの項目がこの記事の一番重要ポイントになります。
ServiceAccountの変更点
Service Accountに先程作成したロールを紐付けます。
apiVersion: v1 kind: ServiceAccount metadata: name: cloudwatch-agent namespace: amazon-cloudwatch + annotations: + eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/eks-role-my-cluster-amazon-cloudwatch-cloudwatch-agent
Podの変更点
大きく分けて二つの変更点があります。一つはイメージの取得元をECRに変更すること。もう一つはstsのendpointをVPC Endpointに向けるための以下の設定です。
AWS_STS_REGIONAL_ENDPOINTS=regional
この設定が無いとインターネットにstsのエンドポイントを見に行こうとして以下のようなタイムアウトのメッセージになります。
caused by: RequestError: send request failed caused by: Post "https://sts.amazonaws.com/": dial tcp 54.239.21.217:443: i/o timeout
この辺りが参考になります。
その他の実際の変更箇所
以下、変更箇所を見ていきます。
Busybox
Busyboxはイメージの宛先を変更します。
initContainers: - name: copy-fluentd-config - image: busybox + image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/cw-insight/busybox command: ['sh', '-c', 'cp /config-volume/..data/* /fluentd/etc'] volumeMounts: - name: config-volume mountPath: /config-volume - name: fluentdconf mountPath: /fluentd/etc - name: update-log-driver - image: busybox + image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/cw-insight/busybox command: ['sh','-c','']
cloudwatch-agent
cloudwatch-agentはイメージをECRから取得する変更と、AWS_STS_REGIONAL_ENDPOINTSの設定を行います。
apiVersion: apps/v1 kind: DaemonSet metadata: name: cloudwatch-agent namespace: amazon-cloudwatch spec: selector: matchLabels: name: cloudwatch-agent template: metadata: labels: name: cloudwatch-agent spec: containers: - name: cloudwatch-agent - image: amazon/cloudwatch-agent:1.247346.0b249609 + image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/cw-insight/cloudwatch-agent:latest #ports: # - containerPort: 8125 # hostPort: 8125 # protocol: UDP resources: limits: cpu: 200m memory: 200Mi requests: cpu: 200m memory: 200Mi # Please don't change below envs env: + - name: AWS_STS_REGIONAL_ENDPOINTS + value: regional - name: HOST_IP valueFrom: fieldRef: fieldPath: status.hostIP
fluentd-cloudwatch
fluentd-cloudwatchもイメージをECRから取得する変更と、AWS_STS_REGIONAL_ENDPOINTSの設定を行います。
- name: fluentd-cloudwatch - image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-cloudwatch-1.0 + image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/cw-insight/fluentd-kubernetes-daemonset env: + - name: AWS_STS_REGIONAL_ENDPOINTS + value: regional - name: AWS_REGION valueFrom: configMapKeyRef: name: cluster-info key: logs.region
デプロイ
後はマニュフェストファイルをApplyするだけです。ここまでの手順が合っていれば、ここはあっさりいくはずです。
$ kubectl apply -f my-cwagent-fluentd.yaml
namespace/amazon-cloudwatch created
serviceaccount/cloudwatch-agent created
clusterrole.rbac.authorization.k8s.io/cloudwatch-agent-role created
clusterrolebinding.rbac.authorization.k8s.io/cloudwatch-agent-role-binding created
configmap/cwagentconfig created
daemonset.apps/cloudwatch-agent created
configmap/cluster-info created
serviceaccount/fluentd created
clusterrole.rbac.authorization.k8s.io/fluentd-role created
clusterrolebinding.rbac.authorization.k8s.io/fluentd-role-binding created
configmap/fluentd-config created
daemonset.apps/fluentd-cloudwatch created
DaemonSetなので2Pod/NodeのPodが立ち上がります。
$ kubectl get po -n amazon-cloudwatch NAME READY STATUS RESTARTS AGE cloudwatch-agent-bj7fw 1/1 Running 0 46s cloudwatch-agent-ph74f 1/1 Running 0 46s fluentd-cloudwatch-qlb86 1/1 Running 0 46s fluentd-cloudwatch-vwkqr 1/1 Running 0 46s
Container Insightsの画面を見ると、情報取得できてそうです。
追記)ログが取得できない
AWSからダウンロードしてきたマニュフェストのfluentd-kubernetes-daemonsetのバージョン( fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-cloudwatch-1.0
) だとサービスアカウントの認証に対応してないようです。
新しいイメージを落としてくると動きます。
以下のイメージで動作確認しました。
fluent/fluentd-kubernetes-daemonset:v1.11.5-debian-cloudwatch-1.0
CloudWatch Logsで以下のように、Performance以外のログも表示されるようになります。
Container Insightsからは以下のようにアイテム選ぶと「ログを表示」がクリックできるようになります。クリックするとCloudWatch Logs Insightsに飛びます。
掃除
もし削除したくなったら、 kubectl delete
使えば一気に関連項目を削除可能です。
$ kubectl delete -f my-cwagent-fluentd.yaml namespace "amazon-cloudwatch" deleted serviceaccount "cloudwatch-agent" deleted clusterrole.rbac.authorization.k8s.io "cloudwatch-agent-role" deleted clusterrolebinding.rbac.authorization.k8s.io "cloudwatch-agent-role-binding" deleted configmap "cwagentconfig" deleted daemonset.apps "cloudwatch-agent" deleted configmap "cluster-info" deleted serviceaccount "fluentd" deleted clusterrole.rbac.authorization.k8s.io "fluentd-role" deleted clusterrolebinding.rbac.authorization.k8s.io "fluentd-role-binding" deleted configmap "fluentd-config" deleted daemonset.apps "fluentd-cloudwatch" deleted
最後に
ちょうど昨日のAWS re:Invent 2020でEKSの管理画面が拡張されました。Container Insightsほどでは無いですが、PodやNodeの状態が見られるようになりました。
Amazon EKS Console Now Includes Kubernetes Resources to Simplify Cluster Management
IAMにRBACマッピングすれば、Private Clusterでも使えることが確認できました。今までは管理画面を使うことほとんど無かったですが、ちょっと中身見るような時にはこちらも使えそうです。