🐳

kubectlの適切なクラスター接続設定を考えてみた

2023/07/27に公開

はじめに

D2Cのエンジニアの小川です。

D2Cでは社内のデータサイエンティスト向けのサービスを一部Amazon EKS上で運用しています。
チームで運用しているためkubectlでのEKSクラスターへの接続設定を定期的に変更するのですが、その運用が適切でなく、先日一時的にクラスターに誰もアクセスできない状態になるというインシデントがありました。
その経緯や解決策の紹介と、あわせてクラスターアクセスの認証の仕組みについてなど、忘備録としてまとめたいと思います。

クラスターのユーザー認証・認可の仕組み

コンポーネント

クラスターのユーザー認証管理は、下記コンポーネントから成り立っています。

  • kubeconfig:
    ユーザーがクラスター内のAPIサーバーと通信するために必要な情報を定義しており、これを接続元(ユーザーのkubectl実行環境)に設定することで、クラスターに接続できるようになります。
    kubeconfigは下記awsコマンドの実行により自動生成され、~/.kube/configに配置されます。
$ aws eks update-kubeconfig --region {region-code} --name {my-cluster}
  • aws-auth:
    クラスターのkube-system namespace内に予め配置されているConfigMapです。IAMプリンシパル(IAMユーザー・IAMロール)がクラスター内で所属するグループをaws-authに定義することで、クラスターへの操作権限を設定します。具体的には、操作権限自体はRBAC(ClusterRoleBinding・ClusterRole)により定義されており、aws-authでIAMプリンシパルに対し設定したGroupに紐づいているRBACの権限が反映されます。

クラスター作成者のアクセス権限

下記にあるように、aws-authの設定とは関係なく、クラスターを作成したIAMプリンシパルにはsystem:mastersのGroupの操作権限でクラスターにアクセスできます。

Amazon EKS クラスターを作成すると、このクラスターを作成する IAM プリンシパルには、Amazon EKS コントロールプレーンのクラスターロールベースアクセスコントロール (RBAC) 設定で、system:masters グループの許可が自動的に付与されます。
ー クラスターに対する IAM プリンシパルのアクセスの有効化

system:mastersのGroupは下記RBACに紐づいています。またこのRBACはデフォルトで存在しているもので、スーパーユーザーとして任意のリソースに任意のアクションを実行できる設定になっています。

$ kubectl get -n kube-system clusterrolebinding cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata: 
 ・・・
  name: cluster-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:masters
$ kubectl get -n kube-system clusterrole cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 ・・・
  name: cluster-admin
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'
- nonResourceURLs:
  - '*'
  verbs:
  - '*'

ユーザー認証・認可処理の流れ

ユーザーがクラスターに接続する際のユーザー認証・認可処理の流れは下記のとおりです。
ユーザー認証・認可の流れ

[1] ユーザーによりkubectlが実行された後、kubeconfigに記載されているクラスターエンドポイントやトークン取得コマンドを取得
[2] トークン取得コマンドを実行し、生成したトークンを使いクラスター内のAPIサーバーへアクセス
[3] IAMがトークン認証をし、正しいIAMユーザーであることを確認
[4] aws-auth(ConfigMap)を取得し、IAMユーザーに紐づいているRBACを確認
[5] RBACを取得し、ユーザーの操作権限を確認
[6] 要求されたkubectlの操作を許可or拒否する

クラスターに誰もアクセスできない状態になった原因・解決策・再発防止策

原因

クラスター作成後、下記のようにaws-authのmapUsersにクラスター運用者を追加していました。

apiVersion: v1
data:
  mapRoles: 
    ・・・
  mapUsers: |
    - groups:
      - system:masters
      userarn: arn:aws:iam::XXXXXXXXXXXX:user/user1
    - groups:
      - system:masters
      userarn: arn:aws:iam::XXXXXXXXXXXX:user/user2
kind: ・・・

また、クラスター運用者追加を手動で行う運用をしていました。(下記コマンドを実行すると、aws-authファイルの編集画面に遷移します)

$ kubectl edit -n kube-system configmap/aws-auth

今回のインシデントが起きた発端は、手動でaws-authを編集している中で、文法を誤った状態で保存してしまったことです。それにより、まずaws-authに登録していた全IAMユーザーがクラスターにアクセスできない状態になりました。
また、クラスターを作成したIAMプリンシパルの情報を記録していない状態だったため、クラスターに誰もアクセスできない状態になりました。

解決策

幸い、クラスターを作成したIAMプリンシパルを特定することができ、クラスター作成者としてクラスターに接続、aws-authを修正し解決に至りました。
ですが、調査に長時間要してしまい、クラスターを作成したIAMプリンシパルを記録しておくことの重要性を痛感しました。

他チームでも、クラスターを作成したユーザーが退職したためIAMユーザーを削除しており、同様のインシデントが発生したことがあったようです。
この場合の解決策としては、クラスターを作成したIAMプリンシパルと同じARN(Amazonリソースネーム)になるように作成し、そのIAMプリンシパルでクラスターにアクセスするというものです。EKSクラスターはIAMプリンシパルをARNで認識しているため、アクセスキーの値などが変わっても、同一のIAMプリンシパルとして認識されるようです。

再発防止策

1. IAMロールを使いクラスターを作成する

IAMユーザーでクラスターを作成すると、部署移動や退職等の理由でIAMユーザーを削除しており、なおかつARNが特定できないなど、クラスターに誰もアクセスできない状況に陥る可能性が高いです。
ですので、そもそもクラスター作成時に、専用のIAMロールを使うようにすることで、チーム内の認識合わせがしやすくなります。

2. IAMロールにクラスターへのアクセス許可をする

下記にもある通り、1と同じ理由で、aws-authの設定についても、IAMユーザーではなくIAMロールに対し設定するように運用を改善しました。

クラスターを作成したユーザーでない場合は、以降の手順を実行して、他の IAM プリンシパルのクラスターへのアクセスを有効にする必要があります。IAM のベストプラクティスでは、ユーザーではなくロールに許可を付与することが推奨されています。
ー クラスターに対する IAM プリンシパルのアクセスの有効化

3. aws-authをyamlファイル管理にする

ヒューマンエラーを最小限にするため、kubectl editを使った手動での変更はしないのが一番です。下記のように、yamlファイル管理にすること、eksctlを使うことで、aws-authを安全に修正するような運用に改善しました。

cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
・・・
iamIdentityMappings:
- arn: arn:aws:iam::XXXXXXXXXXXX:role/administrator-role
  groups:
    - system:masters
  username: administrator
$ eksctl create iamidentitymapping -f cluster.yaml

おわりに

今回は、クラスターの接続設定管理に関するインシデントの紹介にあわせ、再発防止策として自分なりのベストプラクティスを紹介しました。
かなり基礎的かつ地味な内容だと思いますが、そのような運用こそおろそかにならないように気を付けなければいけないなと思います。
最後までお読みいただき、ありがとうございました。

参考

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/cluster-auth.html

https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/create-kubeconfig.html

https://kubernetes.io/ja/docs/reference/access-authn-authz/rbac/#ユーザー向けrole

https://eksctl.io/usage/iam-identity-mappings/

D2C m-tech

Discussion