144
107

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

kubeadmって何やってるの?公式ページをちゃんと読む

Posted at

はじめに

つい先日kubeadmを使ってKubernetes環境を構築しましたが、実際kubeadmは何をやっているのかよく分かっていませんでしたので、何か説明してくれているものはないか、と探しました。すると公式ページで説明してくれていたので、読んでみました。ただ幾つかのページにまたがって説明していることもあり、ある程度ここでまとめました。個人用のまとめの側面が強いため、間違いも含まれていると思われますので、そのような箇所がありましたらご指摘いただければ幸いです

kubeadmとは

公式ページ

kubeadmはKubernetesクラスター環境を高速に作成する方法としてkubeadm initkubeadm joinというコマンドを提供するツールです。Kubernetesのクラスターを立ち上げ、稼働させる上で最低限必要なものを提供します。

kubeadm詳細の説明

公式ページ

コアとなる設計指針

kubeadm initkubeadm 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.confschedulerごとのクライアント証明書が含まれます。
  • 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
    • 前段で作成した各証明書の利用

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-systemnamespace配下に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-publicnamespaceにcluster-infoというConfigMapを作成します。

Addonインストール

kube-proxyとDNSをインストールします。

  • kube-proxy: kube-systemnamespaceにkube-proxy用のServiceAccountが作成され、DaemonSetを使ってkube-proxyがデプロイされます。
  • DNS: こちらもkube-systemnamespaceに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を作成します。
  • 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です。
  • 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です。
  • 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-systemnamespaceのcluster-infoConfigMapから、クラスター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の概要は以下のようになるかと思います。

ただ、ここまでまとめて思ったのは、**本番環境ではkubeadmはどこまで利用できるのか?**という点でした。例えば証明書周りはあまりカスタマイズが出来ないようですが(ファイルの出力先などは指定できますが、証明書自体の設定はあまり出来ない)、それ以外は比較的色々とできるようにみえます。新たなクラスターの追加もkubeadm joinで簡便にできますし、十分使い物になるのでは、と思うのですが。。。引き続き本番環境へのkubeadm適用について調べていきたいと思います。

参考リンク

Kubernetes: v1.7 で導入された Node Authorization とは
Kubernetes の TLS 証明書について調べてみた
kubeadmインストール構成とthe-hard-wayインストール構成の違い

144
107
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
144
107

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?