これはなに?
Kubernetesクラスタでデフォルトで動いておく必要のあるmanifestを自動的にデプロイするソフトウェア。GKEやminikubeでも利用されています。
LeaderElectionの機能があり、クラスタ内で複数動作させることでHAを実現できます。
実態はこのシェルスクリプトです https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/addon-manager/kube-addons.sh
k8sクラスタにあらかじめ特定のPodを稼働させておく場合などに使えそうなので、詳細を調べてみました。
addonの管理方法
addon-managerは $ADDON_PATH
(デフォルトは /etc/kubernetes/addons/
)にあるマニフェストテンプレートを管理します。
2種類の管理方法があり、これらをラベルで指定します。
-
addonmanager.kubernetes.io/mode=Reconcile
- もしリソースが消されていれば作り直す
- もしテンプレートがが変更されていたら反映し直す
- もしテンプレートが消されていたらリソースを消す
- バージョン・設定値も含めて固定で動く必要のあるmanifestの管理に使えそう
-
addonmanager.kubernetes.io/mode=EnsureExists
- 存在があることを保証する
- そのリソースがないときは作成・再作成する
- テンプレートが消えていても作ったリソースはそのまま
- バージョン・設定値は利用者にカスタマイズさせるようなmanifestの管理に使えそう
注意すること
- 上記どちらかの管理方法をラベルで指定する必要がある
- namespaceに属するリソースについてはkube-systemのものにする必要がある
要するにaddon-managerというのは、あるディレクトリにあるマニフェストをapplyし続けるデーモンのようなアプリケーションなのです。
リーダー選出はどうやっているのか?
addon-managerは、HAでマスターを構成している場合に、kube-controller-managerのリーダー選出を借りて自身のリーダー選出に利用しています。
(HAでのクラスタの構成はこちらを参照 https://kubernetes.io/docs/admin/high-availability/ )
下記でkube-controller-managerがどのホストで動いているかを知ることができます。
$ kubectl get ep -n kube-system kube-controller-manager -o yaml
apiVersion: v1
kind: Endpoints
metadata:
annotations:
control-plane.alpha.kubernetes.io/leader: '{"holderIdentity":"現在のリーダーのホスト名","leaseDurationSeconds":15,"acquireTime":"2017-12-07T08:02:04Z","renewTime":"2017-12-08T02:59:44Z","leaderTransitions":49}'
creationTimestamp: 2017-10-24T05:00:36Z
name: kube-controller-manager
namespace: kube-system
resourceVersion: "7842073"
selfLink: /api/v1/namespaces/kube-system/endpoints/kube-controller-manager
uid: 45ac6cb7-b878-11e7-bc9c-fa163e6b368e
subsets: null
addon-managerはmaster nodeで動くことを想定しており、上記コマンドで取得した現在のリーダーのホスト名と、自身のホスト名が同じであれば動作するようになってます。 ( https://github.com/kubernetes/kubernetes/blob/master/cluster/addons/addon-manager/kube-addons.sh#L156 )
ちょっとトリッキーな方法だが簡単にHAが実現できる方法です。
addon-managerをどうやってデプロイするか?
addon-managerはコンテナとして提供されています ( https://console.cloud.google.com/gcr/images/google-containers/GLOBAL/kube-addon-manager ) これをデプロイするにはいくつかの方法が考えられます。
方法1 master NodeにDaemonSetsで起動するようにしておく
- クラスタ提供者からすると、利用者に消される恐れがある
- そのdaemonsetsを提供する仕組みで必要なmanifestをデプロイすれば良いのではないか
- kube-systemを触る権限がある人はこの機能を停止できてしまう
- RBACでkube-systemの操作を限定するならそれでも良さそう
- EnsureExistsの挙動はaddon-mangerを使わないと実現できない
- kube-systemを触る権限がある人はこの機能を停止できてしまう
方法2 master Nodeにstatic podで起動するようにしておく
- Static pod と呼ばれる方法 https://kubernetes.io/docs/tasks/administer-cluster/static-pod/
- kubectlで消すことができない
- minikubeもこの方法を使っている(後述)
方法3 master Nodeにsystemdで起動するようにしておく
- kubectlで消すことができない
- static pod(方法2)より大袈裟なので使う利点がなさそう
方法まとめ
方法を3つ書きましたが、利用者に消して欲しくないmanifestを提供するには 方法2がよさそうです。
minikubeでの事例
minikubeはStatic podと呼ばれる方法。具体的には /etc/kubernetes/manifestにaddon-manager
に
https://github.com/kubernetes/minikube/blob/master/deploy/addons/addon-manager.yaml のようなマニフェストを配置することで、addon-managerをデプロイしています。
このmanifestでは環境変数でkubeconfigを渡し、hostPathで/etc/kubernetes/addons/
をマウントしています。
minikube addons enable
したときはminikueがlocalkubeに指令を出し、localkubeが /etc/kubernetes/addons
にファイルをコピーし、 それをhostPathでマウントしているaddon-managerが検知して、Kubernetesにaddonをデプロイするという流れになっています。
どういう時に嬉しいか?
kube-dnsなどクラスタを構成するために必要なコンポーネントを立ち上げる時に便利そうです。
さらに、この方式を使ったmanifestは通常のkubectlでの更新ができなくなる(mode=Reconcileのとき)ため、Kubernetesクラスタを第三者に提供する時に、クラスタを構成するのに不可欠なリソースを注入する場合に利用できそうです。 (managed kubernetes提供業者はこういうことをしたいのでは?)
おわりに
このエントリは、Z Lab のメンバーによる Z Lab Advent Calendar 2017 として業務時間中に書きました。