Aggregated ClusterRolesとクラスタアップデート時の挙動

# Aggregated ClusterRoles

https://kubernetes.io/docs/admin/authorization/rbac/#aggregated-clusterroles

Kubernetes v1.9から ClusterRoleでロール集約機能（Aggregation）が使えるようになりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/100375/a37b7ac5-3639-0ea2-828f-fef66f9185bf.png)

```
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # 自動的に該当するラベルを持つClusterRoleのルールが追加される

```

このように`.aggregationRule.clusterRoleSelectors.matchLabels` を記載することで、該当するラベルを持つClusterRoleの内容が取り込めるようになります。
上記manifestをデプロイすると、しばらくすると自動的に`.rules`にaggregateしているClusterRoleのルールが追加されるという動きになります。

## User-facing roles

Kuberntes v1.9から cluster-admin, admin, edit, viewのClusterRoleも、このAggregatedClusterRolesを利用するものに変更されています。

- `rbac.authorization.k8s.io/aggregate-to-admin: "true"`
- `rbac.authorization.k8s.io/aggregate-to-edit: "true"`
- `rbac.authorization.k8s.io/aggregate-to-view: "true"`


といった、ラベルを元に権限を集約するようになっています。

具体的にはこんな感じです。

```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: admin
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules: [] # そのうち集約したroleの内容になる
```

実際のrulesの中身は `rbac.authorization.k8s.io/aggregate-to-admin: "true"` ラベルのついた下記ClusterRoleです。

```
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
    rbac.authorization.k8s.io/aggregate-to-admin: "true"
  name: system:aggregate-to-admin
rules:
  ... (省略。　adminにつけるべきrulesが続きます)
```

この仕組みを利用すると、CRDなどで新しく作ったリソースの権限を、簡単にこれらのClusterRoleに含めることができます。

## Kubernetes のアップデートとUser-facing roles

マイナーバージョンアップデートを繰り返しているKubernetesクラスタのUser-facing rolesは、KubernetesのRoleのマイグレーションにより少し不思議な状態になります。
これによりなにか問題が起きる訳ではないのですが、初めて見た時にギョッとしたので、状況を共有します。

Kubernetesクラスタをアップグレードする際、Kubernetesは以前のRoleで存在していたRuleと、これから作るRuleを混ぜ合わせて、新しいRuleを作成します。

(v1.8 -> v1.9の際は 旧`admin`ルール + 新ルール = `system:aggregate-to-admin` のように対応するaggregate元のロールに引き継がれます https://github.com/kubernetes/kubernetes/blob/317853c90c674920bfbbdac54fe66092ddc9f15f/pkg/registry/rbac/rest/storage_rbac.go#L309 )

その結果ルールがこんな感じになります。

```
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.authorization.k8s.io/aggregate-to-admin: "true"
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: admin
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - replicationcontrollers
  - replicationcontrollers/scale
  - secrets
  - serviceaccounts
  - services
  - services/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - impersonate
- apiGroups:
  - apps
  resources:
  - deployments
  - deployments/rollback
  - deployments/scale
  - statefulsets
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  - scheduledjobs # 1.9ではサポート終了したscheduledjobsのルールが未だに存在する
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - ingresses
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch
- apiGroups:
  - authorization.k8s.io
  resources:
  - localsubjectaccessreviews
  verbs:
  - create
- apiGroups:
  - rbac.authorization.k8s.io
  resources:
  - rolebindings
  - roles
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch
- apiGroups: # 以降しばらく冗長なdaemonsetsのroleが続く
  - apps
  resources:
  - daemonsets
  verbs:
  - create
- apiGroups:
  - apps
  resources:
  - daemonsets
  verbs:
  - delete
- apiGroups:
  - apps
  resources:
  - daemonsets
  verbs:
  - deletecollection
- apiGroups:
  - apps
  resources:
  - daemonsets
  verbs:
  - get
- apiGroups:
  - apps
  resources:
  - daemonsets
  verbs:
  - list
- apiGroups:
  - apps
  resources:
  - daemonsets
  verbs:
  - patch
- apiGroups:
  - apps
  resources:
  - daemonsets
  verbs:
  - update
- apiGroups:
  - apps
  resources:
  - daemonsets
  verbs:
  - watch
- apiGroups:# 以降しばらく冗長なreplicasetsのroleが続く
  - apps
  resources:
  - replicasets
  verbs:
  - create
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - delete
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - deletecollection
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - get
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - list
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - patch
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - update
- apiGroups:
  - apps
  resources:
  - replicasets
  verbs:
  - watch
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - create
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - delete
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - deletecollection
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - get
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - list
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - patch
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - update
- apiGroups:
  - apps
  resources:
  - replicasets/scale
  verbs:
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - create
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - delete
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - deletecollection
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - get
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - list
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - patch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - update
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - watch
```

- もうサポートが切れたルールが延々残り続ける
- アップグレード時に新たに増えたルールはverbsがまとめられず冗長に追記される

見辛い以外に大きな実害はないのですが、初めて見た時にギョッとしました。

# まとめ

Kubernetes1.9から User-facing rolesはAggregated ClusterRolesを使ったものになりました。
またUser-facing rolesはバージョンアップ時にいい感じにマージされますが、初めて見るとギョッとするので、何が起きているかをまとめました。