困っていること
EKSクラスターを、TerraformのEKS公開モジュールを使ってプロビジョニングしています。現在使っているversionは19.17.1です。クラスターのversionは1.27です。
2月初旬頃から、EKSクラスターのkube-system
namespaceのConfigMap aws-auth
の内容が何者かによってTerraform外で更新されるようになっており、それによってterraform plan
や terraform apply
で以下のようなdiffが検出されることがあります。
mapRoles.groups
配列内の要素順が異なるmapRoles.groups
配列内の文字列が全般「"」で囲まれていない→囲まれている
# module.eks.kubernetes_config_map_v1_data.aws_auth[0] will be updated in-place
~ resource "kubernetes_config_map_v1_data" "aws_auth" {
~ data = {
~ "mapRoles" = <<-EOT
- - groups:
- - system:bootstrappers
- - system:nodes
- rolearn: arn:aws:iam::012345678901:role/my-node-role
- username: system:node:{{EC2PrivateDNSName}}
- - groups:
- - system:masters
- rolearn: arn:aws:iam::012345678901:role/AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b
- username: AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b:{{SessionName}}
- - groups:
- - system:bootstrappers
- - system:nodes
- - system:node-proxier
- rolearn: arn:aws:iam::012345678901:role/my-fargate-profile-role
- username: system:node:{{SessionName}}
+ - "groups":
+ - "system:bootstrappers"
+ - "system:nodes"
+ "rolearn": "arn:aws:iam::012345678901:role/my-node-role"
+ "username": "system:node:{{EC2PrivateDNSName}}"
+ - "groups":
+ - "system:bootstrappers"
+ - "system:nodes"
+ - "system:node-proxier"
+ "rolearn": "arn:aws:iam::012345678901:role/my-fargate-profile-role"
+ "username": "system:node:{{SessionName}}"
+ - "groups":
+ - "system:masters"
+ "rolearn": "arn:aws:iam::012345678901:role/AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b"
+ "username": "AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b:{{SessionName}}"
EOT
# (2 unchanged elements hidden)
}
id = "kube-system/aws-auth"
# (2 unchanged attributes hidden)
<pre><code> # (1 unchanged block hidden)
}
</code></pre>
aws-auth
ConfigMapとは、クラスターにアクセスできるIAMプリンシパル(IAM RoleやIAM UserやAWSアカウントのルートユーザーのこと)を設定するために使うConfigMapです。
ここに書かれているIAMプリンシパルもしくはクラスターを作成したIAMプリンシパルでないと、クラスターにアクセスできません。間違った変更が入った場合、その後クラスターにアクセスできなくなるおそれがあります。ですのでとても重要な設定です。なのですが、毎度前述のようなdiffが検出されてしまうと、diff確認が疎かになって意図せぬ変更を見落としてしまうおそれがあります。
※ 厳密に言うと、aws-auth
ConfigMapが必要になるのは、クラスターの設定項目Authentication modeでConfigMapを含んでいる場合のみです。以前はこの方法しか無かったのですが、このアップデートにより別の方法でも設定できるようになりました。
原因究明: だれがこの変更を実施しているのか
前述のとおり重大な障害を発生させるリスクがありますし、そうでなくても毎度よくわからないdiffが検出されるのはストレスなので、この問題を早急に解決したいと考えました。まずは原因究明、つまり誰がこの変更をTerraform外で実施しているのかの調査を行ないました。
EKSは監査ログを簡単にCloudWatch Logsに記録できる機能があります。
こちらを漁れば、aws-auth
ConfigMapの変更履歴を把握できます。CloudWatch Logs Insightsで該当クラスターのコントロールプレーンのログを記録しているLog Groupに対して、以下の様なクエリを実行しました。
fields @timestamp, verb, user.username, user.extra.arn.0
| filter @logStream like "kube-apiserver-audit"
| filter objectRef.resource = "configmaps"
| filter objectRef.namespace = "kube-system"
| filter objectRef.name = "aws-auth"
| filter verb NOT IN ["get", "watch"]
| sort @timestamp desc
| limit 1000
結果、Terraform外で2回変更が実行されていることがわかりました。以下、時系列で説明します。
1. 弊社メンバーがTerraform経由で変更(terraform apply
)
当然ですが、これは想定内の履歴です。
2. AWSWesleyClusterManagerLambda-NodeManagerRole〜
というIAM Roleが変更を実施
変更内容
Terraformでの定義内容と比べて、以下が異なります。
- 文字列が「"」で囲まれていない
- Fargate Profile用のロールについての定義がない
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::012345678901:role/my-node-role
username: system:node:{{EC2PrivateDNSName}}
- groups:
- system:masters
rolearn: arn:aws:iam::012345678901:role/AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b
username: AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b:{{SessionName}}
AWSWesleyClusterManagerLambda-NodeManagerRole〜
IAM Roleについて
このロールは、このクラスターの存在するAWSアカウント内のロールではなく、外部アカウントのロールでした。かつその外部アカウントは同一Organizations内にあるわけでもない、完全に外部のアカウントでした。
調べてみると、NodeManagerRole
が付くIAM Roleは「Amazon EKS の内部サービスロールです。」という記述がありました。
Amazon CloudWatch で Amazon EKS の認証ログをチェックすると、次のサンプルテキストのようなテキストを含むエントリが表示されます。
level=info msg="mapping IAM role" groups="[]" role="arn:aws:iam::111122223333:role/XXXXXXXXXXXXXXXXXX-NodeManagerRole-XXXXXXXX" username="eks:node-manager"
このテキストを含むエントリが必要です。username は、マネージド型ノードグループと Fargate の特定のオペレーションを実行する、Amazon EKS の内部サービスロールです。
サービスロールとは、お客様に代わって AWS のサービスがアクションを実行するために引き受けるロールです。ということで、このロールはAWSが管理しているロールで、アカウントもAWSが使っているアカウントのようです。
Stack Overflowにも同様にAWS管理のIAM Role/アカウントであるというコメントが見つかりました。
権限を確認
また、このIAM ロールが紐づいているk8sユーザーが所属するk8sグループに紐づくk8sのロール(ややこしいな!)はkube-system
namespaceのeks:node-manager
であり、権限を確認すると以下だったので確かに aws-auth
ConfigMapを更新する権限がありました。
kubectl get role eks:node-manager -o yaml -n kube-system出力結果抜粋
rules:
- apiGroups:
- ""
resourceNames:
- aws-auth
resources:
- configmaps
verbs:
- get
- update
- patch
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- events
verbs:
- get
- list
3. 2の直後AWSWesleyClusterManagerLambda-FargateManagerRole〜
というIAM Roleがさらに変更を実施
「直後」は数十秒後だったり約15分後だったりバラツキがありました。
変更内容
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::012345678901:role/my-node-role
username: system:node:{{EC2PrivateDNSName}}
- groups:
- system:masters
rolearn: arn:aws:iam::012345678901:role/AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b
username: AWSReservedSSO_AdministratorAccess_3e3617e16cf3782b:{{SessionName}}
- groups:
- system:bootstrappers
- system:nodes
- system:node-proxier
rolearn: arn:aws:iam::012345678901:role/my-fargate-profile-role
username: system:node:{{SessionName}}
2の変更に、Fargate Profile用のロールについての定義が追加されています。
Terraformでの定義内容と比べて、以下が異なります。
- 文字列が「"」で囲まれていない
mapRoles.groups
配列内の要素順が異なる
AWSWesleyClusterManagerLambda-FargateManagerRole〜
IAM Roleについて
2を実施した「NodeManagerRole」と同じアカウントのIAM Roleでした。ですのでこちらもAWS管理のアカウントの、AWS管理のIAM Roleと思われます。ただし2とは違って、公式ドキュメントにこのロールについての記述は見つけることができませんでした。
権限を確認
2と同様、このIAM ロールが紐づいているk8sユーザーが所属するk8sグループに紐づくk8sのロール(ややこしいな!)を調べました。するとkube-system
namespaceのeks:fargate-manager
ロールであり、権限を確認すると以下だったので確かに aws-auth
ConfigMapを更新する権限がありました。
kubectl get role eks:fargate-manager -o yaml -n kube-system出力結果抜粋
rules:
- apiGroups:
- ""
resourceNames:
- aws-auth
resources:
- configmaps
verbs:
- get
- update
- patch
- delete
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- events
verbs:
- get
- list
4. diff発生
2,3実施後にterraform plan
やterraform apply
を行なうと最初に説明したdiffが発生してしまいます。
解決方法の検討
前述の2と3の変更は一度きりではなく、定期的に実施されています。
解決方法の検討をした結果、「diff抑止は無理そう」→「aws-auth
ConfigMapの使用をやめる」ということになりました。
diff抑止は無理そう
まず、2と3のAWS管理ロールによる変更実施を止める術は無さそうでした。2(NodeManagerRole)については「必要です」とドキュメントにも書いてあったので仕方ないですね。 正直 2と3の操作でAWSが何をしたいのかよくわからないですが…
また、別角度の解決法として「このような変更が入る前提で、Terraformのコードを修正してdiffが出ないようにする」が考えられます。なのですが、最初にお伝えした通り、EKSの公開モジュールを使っており、aws-auth
ConfigMapの定義もこのモジュール内で行なっているので修正が難しいです。この部分だけ公開モジュール外で定義することも考えられますが、そうするくらいだったら後述の方法の方が望ましいと考えました。
aws-auth
ConfigMapの使用をやめる
冒頭の方の注釈で軽く説明しましが、現在はEKSのアップデートにより aws-auth
ConfigMapを使わずともIAMプリンシパルによるクラスターアクセスを設定する方法があります。
こちらの方法に移行すれば今回の問題も発生し無さそうと考えました。現在はまだ移行の検証中なのであくまで予測ですが。(今後結果を追記しようと思います。) また、こちらの方法にするほうが他にも色々メリットがあります。メリット詳細は↑のエントリをご確認ください!