kubernetes
Z LabDay 22

addon-manager

これはなに?

https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/addon-manager

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を使わないと実現できない

方法2 master Nodeにstatic podで起動するようにしておく

方法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 として業務時間中に書きました。