サービスロールをEKSクラスターのaws-authに設定すると認証エラーになる
はじめに
Reading this article in the hope it saves someone else a few hours of their life.
(この記事を読むことで他の誰かの生命を数時間節約できることを願っています)
※元ネタ
事象(エラー内容)
EKSクラスターに対してkubernetesコマンド(たとえばkubectl clsuter-infoなど)を実行すると、下記エラーメッセージが出力。
error: You must be logged in to the server (Unauthorized)
EKSのクラスターログ(Authenticator)には下記が出力。
エラーのメッセージだけだと「見たままやんけ」と思うところですが、何度設定を見直しても合っているはずなのにこのエラーが出てだいぶハマった、というものです。
環境情報
-
EKS:1.21
-
kubectl:1.22.11
詳細
案件でEKSクラスターをTerraform(EKS Module)で構築しました。
EKSはデフォルトだとクラスターを構築したユーザー(またはロール)しかkubernetesリソースへのアクセス権が無いため、必要なら個別に追加する必要があります。
今回はTerraformで追加していますが、手動で(kubernetesの構文で)追加する場合は下記を参考にして実施できます。
案件ではメンテナンス環境としてCloud9を利用しているので、Cloud9のIAMロールをsystem:mastersグループに追加しました。
設定値は下記のような感じです。
(関係無い部分は省略)
--------------------------------------------------------------------------
mapRoles:
----
- "groups":
- "system:bootstrappers"
- "system:nodes"
"rolearn": "arn:aws:iam::123456789012:role/xxxxxxxx-nodegroup-role"
"username": "system:node:{{EC2PrivateDNSName}}"
- "groups":
- "system:masters"
"rolearn": "arn:aws:iam::555807401321:role/service-role/AWSCloud9SSMAccessRole"
"username": "maintenance_role"
--------------------------------------------------------------------------
その後こちらを参考にkubeconfigを設定しました。
設定後の結果は下記の通りです。
(こちらも関係ないところは省略)
--------------------------------------------------------------------------
- context:
cluster: ''
user: ''
name: xxxxxxxx-cluster
current-context: arn:aws:eks:ap-northeast-1:123456789012:cluster/
xxxxxxxx-cluster
kind: Config
preferences: {}
users:
- name: arn:aws:eks:ap-northeast-1:123456789012:cluster/xxxxxxxx-cluster
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
args:
- --region
- ap-northeast-1
- eks
- get-token
- --cluster-name
- xxxxxxxx-cluster
- --role
- arn:aws:iam::123456789012:role/service-role/AWSCloud9SSMAccessRole
command: aws
--------------------------------------------------------------------------
この状態でkubernetesのコマンドを実行したところ、先述のエラーが出力されました。
-
IAMロールのARN名など間違っていないことは何度も確認
-
一方で上記とは別に設定しているIAMロール(AWS SSOのロール)ではアクセスできている
という状況であり、何が違うのかわからず、ネットワークやkubectlの問題なども疑ったりしましたが、調査はかなり難航しました。
原因
最初にも貼ったGithubのIssueに答えがありました。
現行のaws-authにはIAMロールのパスを認識できない不具合があり、暫定としてARN名からパスを除去すると正常に認識できるようになるようです。
それを踏まえ、rolearnの部分を下記のように修正すると正常にコマンドが通るようになりました。
--------------------------------------------------------------------------
"rolearn": "arn:aws:iam::123456789012:role/AWSCloud9SSMAccessRole"
--------------------------------------------------------------------------
おまけ
以降は切り分けとしてやったことを五月雨に記載します。
(結論として全く関係無かったので、参考まで)
仮説その①:Kubernetes BoundServiceAccountTokenVolume 機能(1.21)で認証の有効期間が切れている説
EKSの1.21以降、サービスアカウントトークンの有効期限が設定されるようになったため、そのせいで有効期限が切れて認証できなくなっているのではないかと考えました。
しかしこれは認証情報を更新できないkubernetesクライアント(CNIやkube-proxyなど)の話で、Cloudwatchログ上も該当するログは出ていなかったので関係ないと判断。
仮説その②:kubectlのバージョンが違うせいで繋がらなくなった説
残課題として残った、「別クラスターでは同じ設定で接続できている」に対するアプローチです。
実際、同じkubectl 1.21でも1.21.0と1.21.11で機能が変わっているようで、具体的にはkubeconfigの
apiVersion
がv1alpha1
からv1beta1
に変わっていました。1.21.11のkubectlでv1alpha1のapiを実行すると、下記のメッセージが出力されます。
--------------------------------------------------------------------------
$ kubectl cluster-info
Kubeconfig user entry is using deprecated API version client.authentication.k8s.io/v1alpha1. Run 'aws eks update-kubeconfig' to update.
Kubernetes control plane is running at https://1EB6266FBE6ECC2DBBB800FED679AB84.gr7.ap-northeast-1.eks.amazonaws.com
CoreDNS is running at https://1EB1234FBE6ECC2DBBB800FED679AB84.gr7.ap-northeast-1.eks.amazonaws.com/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
--------------------------------------------------------------------------
ただこれもdeprecatedの警告であり、認証自体は通るので関係ありませんでした。