はじめに
つい先日kubeadmを使ってKubernetes環境を構築しましたが、実際kubeadmは何をやっているのかよく分かっていませんでしたので、何か説明してくれているものはないか、と探しました。すると公式ページで説明してくれていたので、読んでみました。ただ幾つかのページにまたがって説明していることもあり、ある程度ここでまとめました。個人用のまとめの側面が強いため、間違いも含まれていると思われますので、そのような箇所がありましたらご指摘いただければ幸いです。
kubeadmとは
kubeadmはKubernetesクラスター環境を高速に作成する方法としてkubeadm init
とkubeadm join
というコマンドを提供するツールです。Kubernetesのクラスターを立ち上げ、稼働させる上で最低限必要なものを提供します。
kubeadm詳細の説明
コアとなる設計指針
kubeadm init
とkubeadm join
で構築されるクラスターは、以下のような条件を満たしているべきと考えられています。
- セキュアである
- RBACを使用する
- Node Authorizationを利用する
- control planeコンポーネント間でのセキュアなやりとり
- API serverとkubelet間でのセキュアなやりとり
- kubelet APIを厳重にする
- システムコンポーネントが安全にAPIにアクセスできる
- Bootstrap Tokenがアクセスできるものを厳重にする
- etc...
- 簡単に使える
- 数コマンドで構築が完了する
- 拡張可能である
- 特定のネットワークプロバイダーに依存しない
- 幅広いパラメータをカスタマイズしたconfigを利用できる
Kubernetesをシンプルに構築できるようにするため、kubeadmは限られた定数・変数、そしてファイルしか使用しません。
ディレクトリ構造、使用するファイルは以下のようになります。
-
/etc/kubernetes
: アプリケーションの中心となるディレクトリ。また各control planeコンポーネントのコンフィグファイル(kubeconfig)の格納先ともなります。kubelet.conf
controller-manager.conf
scheduler.conf
-
admin.conf
: クラスター認証、kubeadmのために利用する
-
/etc/kubernetes/manifests
: kubeletが静的なPodマニフェストを探す際の場所となります。etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml
kube-scheduler.yaml
- 各種証明書とキーファイル
-
ca.crt
,ca.key
: Kubernetes Certificate Authority(認証局) -
apiserver.crt
,apiserver.key
: APIサーバ認証書とキーファイル -
apiserver-kubelet-client.crt
,apiserver-kubelet-client.key
:APIサーバで使われるクライアント認証書とキーファイル。これを使ってkubeletと安全に接続します。 -
sa.pub, sa.key
: ServiceAccountに署名するときにcontroller managerで使われるキーファイル -
front-proxy-ca.crt, front-proxy-ca.key
:front proxy認証局 -
front-proxy-client.crt, front-proxy-client.key
: front proxyクライアントの証明書とキーファイル
-
kubeadm initで何を行っているか
全体の流れは以下のようになります。
- init前のチェック(preflight checks)
- kubelet起動
- 各種証明書の作成
- control plane用のファイル作成(kubeconfig, manifest)
- etcd用のファイル作成(manifest)
- control planeの起動待ち
- kubeadm,kubeletのコンフィグアップロード
- control planeラベリング
- TLS Bootstrap
- addonsインストール(kube-proxy, DNS)
Preflight checks
クラスターを立ち上げ前のチェックになります。--ignore-preflight-errors
オプションをつけることでこの項目をスキップすることができます。
チェックする項目は以下になります。太字の項目はエラー発生項目で、条件を満たさないとエラーとなります。
- Kubernetesのバージョンがkubeadmより上かどうか(マイナーバージョンも含む)
- Kubernetesシステム要件
- OS: linux上か
- Kernel: バージョンが3.10+、4+か
- cgroupがセットアップ状態か
- (Dockerを使っている場合)Dockerサービスが起動しているか、Docker endpointが存在するか、バージョンは17.03より上か
- (他のCRIを使う場合)crictl socketが反応しないか
- ユーザがrootか
- ホスト名がDNSサブドメインか
- ホスト名がネットワーク的にreachableか
- kubeletバージョンがkubeadmでサポートするものより上か
- kubeletサービスが存在してenableか
- firewalldが停止しているか
- APIサーバのbindPort、あるいは10250~10252のポート番号が空いているか
/etc/kubernetes/manifest
フォルダが既に存在していないか、存在してもファイルが存在しないか/proc/sys/net/bridge/bridge-nf-call-iptables
の値が1か- advertiseアドレスがIPv6の場合
/proc/sys/net/bridge/bridge-nf-call-ip6tables
の値が1か - swapがオフか
- 以下のコマンドがコマンドパスに存在するか
- ip, iptables, mount, nsenter
- ebtables, ethtool, socat, tc, touch, crictl
- API server, controller manager, scheduler用の外部のarg flagが有効でないオプションを使っていないか
-
https://API.AdvertiseAddress:API.BindPort
がproxyを介して接続していないか - Podサブネットとの接続がproxyを介していないか
- (外部etcdを利用する場合)etcdバージョンは3.0.14より上か、証明書とキーが提供されているか
- (外部etcdを利用しない場合)ポート番号2379は使われていないか、etcdデータフォルダが既に存在しないか、またはファイルが存在しないか
- (ABACを利用する場合)abac_policy.jsonが存在するか
- (Webhookを利用する場合)webhook_authz.confが存在するか
各種証明書の作成
kubeadmで作成する証明書は上に書いていますが、その利用目的はそれぞれ異なります。これらの証明書はデフォルトで/etc/kubernetes/pki
に保存されますが、--cert-dir
を用いることで指定ができます。
- Kubernetesクラスターの自己証明書: ca.crt, ca.key
- API server用のサーバ証明書: apiserver.crt, apiserver.key。ca.crtを用いて作成します。
- API server用のクライアント証明書: apiserver-kubelet-client.crt, apiserver-kubelet-client.key。kubeletと安全に接続するために使用します。
- ServiceAccountトークン署名用の個人鍵と公開鍵: sa.key, sa.pub
- front proxy用の認証局: front-proxy-ca.crt, front-proxy-ca.key
control planeコンポーネント用kubeconfigファイルの作成
- kubelet:
/etc/kubernetes/kubelet.conf
ファイル中ではkubeletごとのクライアント証明書が含まれています。 - controller manager:
/etc/kubernetes/controller-manager.conf
ファイル中にはcontroller managerごとのクライアント証明書が含まれます。 - scheduler:
/etc/kubernetes/scheduler.conf
schedulerごとのクライアント証明書が含まれます。 - kubeadm:
/etc/kubernetes/admin.conf
クラスターをまたがって全権を持つユーザ(root)を定義します。
control planeコンポーネント用manifestファイルの作成
各control planeの設定はオプションで指定できます。
- Podマニフェスト共通の設定
- namespace: kube-system
- label:
tier:control-plane
,component:{component-name}
- annotation:
scheduler.alpha.kubernetes.io/critical-pod
- hostNetwork: true
- controller managerとschedulerがAPI server参照先とするアドレス: 127.0.0.1
- local etcdを使用する場合のアドレス: 127.0.0.1:2379
- デフォルトではコンテナイメージは
k8s.gcr.io
からpullされる -
--dry-run
: 一時フォルダにmanifestファイルが作成される
API server
- ユーザが設定可能な値(Pod manifest)
- apiserver-advertise-address, apiserver-bind-port
- service-cluster-ip-range
- (外部etcdを利用する場合)etcd-servers, etcd-cafile, etcd-certfile, etcd-keyfile
- (cloud providerを利用している場合)--cloud-provider
- ユーザが設定可能な値(その他)
- --insecure-port
- --enable-bootstrap-token-auth: TLS bootstrapで
BootstrapTokenAuthenticator
を有効にすることができます - --allow-privileged: true。kube-proxyなどで要求されます。
- --requestheader-client-ca-file: front-proxy-ca.crt
- --enable-admission-plugins: Dynamic Admission Controlなどのpluginを有効にすることができます。
- --kubelet-preferred-address-types: InternalIP, ExternalIP, Hostname。Nodeの名前解決ができない場合に
kubectl log
と他のAPIサーバのkubeletとの通信を可能にします。 - 前段で作成した各証明書の利用
Controller manager
- ユーザが設定可能な値(Pod manifest)
- --allocate-node-cidrs
- --cluster-cidr
- --cloud-provider
- ユーザが設定可能な値(その他)
- --controllers: TLS bootstrapでデフォルトのcontrollerに加えて
BootstrapSigner
,TokenCleaner
を有効にできます - --use-service-account-credentials
- 前段で作成した各証明書の利用
- --controllers: TLS bootstrapでデフォルトのcontrollerに加えて
Local Etcd用manifestファイルの作成
- localhost:2379を使用
- HostNetwork=True
- hostPathマウント: dataDirからホストのファイルシステムにマウントします
Control planeの起動を待つ
localhost:6443/healthz
がOKを返すまで待機しますが、localhost:10255/healthz
(kubelet liveness)やlocalhost:10255/healthz/syncloop
(kubelet readiness)がOKを返さない(それぞれ40秒と60秒)と、deadlockを探知してfailします。
kubeadm ClusterConfigurationのConfigMapの保存
kube-system
namespace配下にkubeadm-config
というConfigMapを作成します。これにより、将来的に行われるであろうkubeadm upgradeなどの実行コマンドが実行時のクラスター環境を定義し、そのデータを基に新たな定義をすることが可能になります。kubeadmのバージョンが1.7.xより低い場合は、kubeadm upgrade実行より前に、手動でConfigMapを作成する必要があります。
masterノードのラベリング
Control planeが立ち上がるとすぐに2つのアクションを行います。
-
node-role.kubernetes.io/master=""
のラベリング -
node-role.kubernetes.io/master:NoSchedule
のTaint: masterノードをスケジュール対象外にし、Podなどが作られないようにします。
TLS Bootstrapのコンフィグ
kubeadmでは新たなノードをジョインさせるためにBootstrap Tokenを使用します。Bootstrap TokenはシンプルにTokenを作成することのできるもので、基本的にはkubeadmをサポートするものとなります。このステップでは以下のようなアクションが行われます。公式ページはこちら。
- Bootstrap Tokenの作成: 自動的に作成することも、
--token
でユーザが指定したTokenを作成することもできます。一度作成したTokenは24時間有効で、新たなTokenを作成するにはkubeadm token
コマンドを使用します。 - 新規ノードのCSR(Certificate Signing Request) API呼び出しの許可: デフォルトで作成されるユーザグループ
system:bootstrappers:kubeadm:default-node-token
に所属するユーザは許可されます。 - 新規作成Tokenの自動承認の設定
- ノードの証明書ローテーションの設定(自動承認付き): TLS証明書の有効期限が1年のため、証明書のローテーションを行う場合があります。参考リンク
- cluster-info ConfigMapの作成:
kube-public
namespaceにcluster-infoというConfigMapを作成します。
Addonインストール
kube-proxyとDNSをインストールします。
- kube-proxy:
kube-system
namespaceにkube-proxy用のServiceAccountが作成され、DaemonSetを使ってkube-proxyがデプロイされます。 - DNS: こちらも
kube-system
namespaceにServiceAccountを作成し、kube-dns
という名前のDNSをDployment, Serviceでデプロイします。
Kubernetes 1.11以降はデフォルトDNSはCoreDNSとなり、それ以前のバージョンのKubernetesを使用する場合はCoreDNSを利用可能にする必要があります(--feature-gates=CoreDNS=true
)。kube-dnsという名前でデプロイされますが、実態はCoreDNSです。
kubeadm initオプションの利用
kubeadm initコマンド時にオプションをつけることで、ユーザが一部設定をすることができます。ここではよく使うのでは?と思ったオプションを紹介します。
- --apiserver-advertise-address: API serverがadvertiseする予定のIPアドレスを指定できます。
- --apiserver-bind-port: API serverと接続する際のポート番号を指定できます。
- --dry-run
- --ignore-preflight-errors: preflight checkのステップをスキップします。
- --image-repository: コンテナイメージのリポジトリ先を指定できます。デフォルトは
k8s.gcr.io
です。 - --pod-network-cidr: PodネットワークのIPアドレスレンジを指定できます。
- --service-cidr: Service VIPで利用するIPアドレスレンジを指定できます。
- --skip-token-print: kubeadm init実行時のデフォルトで発行されるtokenの表示をスキップします。
- --token: 利用するtokenをユーザが指定できます。
- --token-ttl: 発行するtokenの有効期限を指定できます。デフォルトは
24h0m0s
です。0
を指定すると有効期限がなくなります。
kubeadm init phaseの利用
kubeadm init phase
コマンドを利用することで、上記ステップごとでの詳細な設定を可能にすることができます。kubeadm v1.8ではkubeadm alpha phase
だったものが、v1.13ではkubeadm init phase
として利用できるようになりました。ここでは各ステップでよく使うのでは?と思ったオプションを紹介します。
- 共通コマンド
- --config: kubeadmコンフィグファイルを指定します(まだ実験的なもののようです)
- -h,--help: ヘルプコマンド
- kubeadm init phase preflight
- --ignore-preflight-errors
- kubeadm init phase certs: 各種証明書に対して個別に指定ができます。
- --cert-dir: 発行した証明書の保存先を指定できます。デフォルトは
/etc/kubernetes/pki
です。 - --csr-dir: CSRとprivate keyの出力先を指定できます。
- --csr-only: 証明書を発行する代わりにCSRを作成します。
- --cert-dir: 発行した証明書の保存先を指定できます。デフォルトは
- kubeadm init phase kubeconfig: control plane用のkubeconfigファイル作成です。各種control planeに対して個別に設定できます。
- --apiserver-advertise-address
- --apiserver-bind-port
- kubeadm init phase kubelet-start
- --cri-socket: CRI socketを指定できます。デフォルトは
/var/run/dockershim.sock
です。
- --cri-socket: CRI socketを指定できます。デフォルトは
- kubeadm init phase control-plane
- --apiserver-advertise-address
- --apiserver-bind-port
- --feature-gates: 前章addonsでCoreDNSを指定する際に利用します。
- --image-repository
- --pod-network-cidr
- --service-cidr
- kubeadm init phase etcd
- --image-repository
- kubeadm init phase mark-control-plane
- kubeadm init phase bootstrap-token
- --skip-token-print
- kubeadm init phase upload-config: このコマンドの代わりに
kubeadm config
コマンドを利用することもできます。- --kubeconfig: 利用するkubeconfigファイルを指定できます。デフォルトは
/etc/kubernetes/admin.conf
です。
- --kubeconfig: 利用するkubeconfigファイルを指定できます。デフォルトは
- kubeadm init phase addon
- --apiserver-advertise-address
- --apiserver-bind-port
- --image-repository
- --pod-network-cidr
- --service-cidr
- --service-dns-domain: ドメインを指定できます。デフォルトは
cluster.local
です。
kubeadm joinで何を行っているか
kubeadmでクラスターを開始する際、双方向でのtrustが必要になります。ここではdiscoveryとTLS bootstrapの2つのステップに分かれます。
discoveryでは、API serverのIPアドレスとkubeconfigファイルを利用するために探索するステップになります。ユーザが指定することもできます。
全体の流れは以下のようになります。
- init前のチェック
- cluster-infoのdiscovery
- TLS Bootstrap
Preflight Checks
基本的にはkubeadm init
コマンドでのpreflight checkのサブセットとなる項目をチェックします。
Discovery cluster-info
ここでは2つの主目的があります。
- shared token discovery:
kubeadm join
で--discovery-token
を実行した場合は、kube-system
namespaceのcluster-info
ConfigMapから、クラスターCA証明書を取り出します。ここでは中間者攻撃を避けるため、幾つかのステップを実行します。 - File/https discovery:
kubeadm join
で--discovery-file
を実行した場合は、ローカルに置かれたファイルかhttps経由でのダウンロードファイルから該当ファイルを検索します。
TLS Bootstrap
cluster-infoがわかると、bootstrap-kubelet.conf
ファイルが書き込まれ、kubeletがTLS Bootstrapを実行することが可能になります。TLS Bootstrapでは事前に作成されたshared tokenを用いてCSRを投稿し、承認されてca.crt
,kubelet.conf
ファイルが作成されることで完了します。これらはbootstrao-kubelet.conf
ファイルが削除されるまで有効となります。
kubeadm joinオプションの利用
kubeadm joinコマンド時にもオプションをつけることで、ユーザが一部設定をすることができます。
- --apiserver-advertise-address
- --apiserver-bind-port
- --discovery-file: クラスター情報を持つファイル、またはURLを指定できます。
- --discovery-token: 使用するtokenを指定できます。
- --ignore-preflight-errors
まとめ・感想
書いているうちに頭が混乱してきてしまったのですが、とにかくkubeadmの概要は以下のようになるかと思います。
- (実行環境を整えれば)数コマンドでKubernetesのクラスターが構築できる。
- オプションをつけることでユーザが比較的カスタマイズできる。
- コンフィグファイルを利用してkubeletを設定する、コンフィグファイルを指定してkubeadmの設定をするなど、まだ実験段階のものも幾つかあり、より幅広い設定をできる可能性もある。
ただ、ここまでまとめて思ったのは、**本番環境ではkubeadmはどこまで利用できるのか?**という点でした。例えば証明書周りはあまりカスタマイズが出来ないようですが(ファイルの出力先などは指定できますが、証明書自体の設定はあまり出来ない)、それ以外は比較的色々とできるようにみえます。新たなクラスターの追加もkubeadm join
で簡便にできますし、十分使い物になるのでは、と思うのですが。。。引き続き本番環境へのkubeadm適用について調べていきたいと思います。
参考リンク
Kubernetes: v1.7 で導入された Node Authorization とは
Kubernetes の TLS 証明書について調べてみた
kubeadmインストール構成とthe-hard-wayインストール構成の違い