Kubernetesにて複数人開発する際にぶつかったRBACの壁


# はじめに
それまで1人で開発していたEKS環境に新しい開発者が参加する際にいくつかの壁にぶつかりました。
それらは後から見てみれば、どれもKubernetes(EKS)が搭載するロールベースアクセス制御(RBAC)の話で、"適切に権限を付与しましょう"と言うお話です。
しかし、エラーログが分かりづらかったり、ロールを付与する対象が複数あったり、クラスター作成者は自動的に権限が付与されて問題が起きなかったりなので、トラブルシューティングの参考になればと思います。


# RBACの壁たち

## 1つ目の壁: IAMユーザーに紐付ける権限

AWSへのアクセス権が適切に設定されたIAM USERをkubeconfigに設定された状況で `kubectl get pods` など Kubernetesにアクセスしようとすると次のようなエラーが出ました。

```
$ kubectl get pods
error: You must be logged in to the server (Unauthorized)
```

これだけ。
AWSへのアクセスは出来てるし、適切にprofileは設定してるし、いろいろIAMの権限を付け替えてみても、Adminにしても、この１文のみなので困惑しました。

これは実はIAMの認証が通った後、EKSのRBAC認証機能で弾かれていました。
実はEKSは認証が2段階ある。

![eks-iam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121645/2f3d1a9d-262a-aaf4-6f12-e0d4a823b4d3.png)

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

そのためこの場合は、現在アクセスしているIAMユーザーに対してRBACのロールを与えなければいけません。

ということで[この様にIAMユーザーにロールを付与します。](#eksにてrbacロールを付与する方法)

## 2つ目の壁: IAMユーザーに紐付ける権限の間違い

ある時IAMユーザーに対してRBACのロールを付与したとき、次のようなエラーが出ました。

```
$ kubectl get pods
Error from server (Forbidden): services is forbidden: User "sample-username" cannot list services in the namespace "sample-namespace"
```

これはRBACのロール付与は成功していてユーザーが認証はされていますが、付与するロールが適切でないためRBACの認可がされなかった例です。
これは付与するロールを修正しましょう（それはそれで難しい）。
この問題は開発者に制限したロールを付与しようと探っていた時に出たエラーで、[RBACで全権付与した場合](#eksにてrbacロールを付与する方法)は発生しないと思われます。

## 3つ目の壁: IAMロールに紐付ける権限

IAMユーザーにRBACロールを付与して、KubernetesもといEKSへのアクセスができました。

```
$ kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
samplepod-0123456789-abcde   2/2     Running   0          1m
```

そこでデプロイに移ろうとしたときに次のような問題が発生しました。

```
$ kubectl apply -f xxx.yaml
NAME                     READY   STATUS    RESTARTS   AGE
samplepod-0123456789-abcde   2/2     Running   0          1h
samplepod-9876543210-vwxyz   0/2     Pending   0          5m
```

ずっとPendingのままなため、ここでEventの確認、Podの状況を確認してトラブルシューティングします。
`describe`すると次の様でした。

```
$ kubectl describe pod samplepod-9876543210-vwxyz
Name:           image_name
Namespace:      xxx
Node:           <none>
Labels:         app=label
Annotations:    <none>
Status:         Pending
IP:
Controlled By:  ReplicationController/label
Containers:

...
...
...

Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  10s (x7 over 41s)  default-scheduler  0/2 nodes are available: 2 node(s) were not ready, 2 node(s) were out of disk space.
```

上記ログの最下部を見ると、どうやらDisk容量が足りていないらしい。
しかし実はこのメッセージが罠で、これはインスタンスのスペックをいくらいじっても解決せず、実態としては**EKSのIAMロールに対して付与するRBACロールの誤り**でした。

実はEKSにおけるRBACのロール付与は、IAMユーザーのみならずIAMロールにも付与する必要があります。
ここではEKSを構成するクラスタのEC2にKubernetesのpodをデプロイする権限がかったため、直前で停止しっぱなしと言う状況でした。
(それなのにエラーメッセージが `out of disk space.`なのはひどい)

ということなのでこの場合はクラスタを構成するEC2に付与しているIAMロールに対して[RBACロールを付与してあげます。](#eksにてrbacロールを付与する方法)


## (余談)0つ目の壁: AWSのアクセス権限

```
$ kubectl get pods
could not get token: NoCredentialProviders: no valid providers in chain. Deprecated.
	For verbose messaging see aws.Config.CredentialsChainVerboseErrors
Unable to connect to the server: getting credentials: exec: exit status 1
```

これは`aws-iam-authenticator`が吐いているエラーで、適切にアクセスキーなどが設定されてません。 
`~/.aws/credentials` や `profile` が適切に設定されているか確認しましょう。


# EKSにてRBACロールを付与する方法

EKSにてRBACロールを付与する方法は、すでにRBAC認証されているユーザーがクラスタに対してConfigMapを適応するのが適切のようです。
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html

ここでは1つ目の壁のために、開発者にRBACの全権(master)を付与しました。
また3つ目の壁のために、EC2 IAMにはノードの標準権限・ブートストラッピングの権限を付与しました。

```aws-auth.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapUsers: |
    - userarn: arn:aws:iam::123456789012:user/sample-username
      username: sample-username
      groups:
        - system:masters # <- これが全権限
  mapRoles: |
    - rolearn: arn:aws:iam::987654321021:role/sample-rolename
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
```

```
$ kubectl apply -f aws-auth.yaml
```

これで完了です。
付与したConfigMapは次で確認できます。

```
$ kubectl describe configmap -n kube-system aws-auth
```

これで今回のトラブルシューティングは以上です。

# 参考

[Amazon EKS トラブルシューティング](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/troubleshooting.html)
[クラスターのユーザーまたは IAM ロールの管理](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html)
[EKSでIAMユーザをアクセスコントロール (RBAC)](https://qiita.com/taishin/items/dfb9a5620f37ffb74fe9)
[EKSのIAMとRBACの認証・認可を試してみる](https://qiita.com/abe-ma/items/c1f6dffe810579cb87b6)

### EKSトラブルシューティングについて
[Pod の問題が起きた場合の確認方法を色々やってみる](https://qiita.com/toshihirock/items/1f03c226a807c5f8cd4c)
[Kubernetesのポッドが起動しない原因と対策](https://qiita.com/minodisk/items/547741b73763f2bab6b8)

### RBACと独自ロールの作成に関して
[GKEでRBACを使ってアクセス可能なnamespaceを限定する](https://qiita.com/HirokiSakonju/items/ff2f5560d58403858fec)
[KubernetesのRBACについて](https://qiita.com/sheepland/items/67a5bb9b19d8686f389d)