これは、このセクションの複数ページの印刷可能なビューです。 印刷するには、ここをクリックしてください.

このページの通常のビューに戻る.

はじめに

このセクションではKubernetesをセットアップして動かすための複数のやり方について説明します。 Kubernetesをインストールする際には、メンテナンスの容易さ、セキュリティ、制御、利用可能なリソース、クラスターの運用および管理に必要な専門知識に基づいてインストレーションタイプを選んでください。

Kuerbetesクラスターをローカルマシン、クラウド、データセンターにデプロイするために、Kubernetesをダウンロードできます。

kube-apiserverkube-proxyのようないくつかのKubernetesのコンポーネントも、コンテナイメージとしてクラスター内にデプロイできます。

可能であればコンテナイメージとしてKubernetesのコンポーネントを実行し、それらのコンポーネントをKubernetesで管理するようにすることを推奨します。 コンテナを実行するコンポーネント(特にkubelet)は、このカテゴリーには含まれません。

Kubernetesクラスターを自分で管理するのを望まないなら、認定プラットフォームをはじめとする、マネージドのサービスを選択することもできます。 複数のクラウドやベアメタル環境にまたがった、その他の標準あるいはカスタムのソリューションもあります。

環境について学ぶ

Kubernetesについて学んでいる場合、Kubernetesコミュニティにサポートされているツールや、Kubernetesクラスターをローカルマシンにセットアップするエコシステム内のツールを使いましょう。 ツールのインストールを参照してください。

プロダクション環境

プロダクション環境用のソリューションを評価する際には、Kubernetesクラスター(または抽象概念)の運用においてどの部分を自分で管理し、どの部分をプロバイダーに任せるのかを考慮してください。

自分で管理するクラスターであれば、Kubernetesをデプロイするための公式にサポートされているツールはkubeadmです。

次の項目

Kubernetesは、そのコントロールプレーンがLinux上で実行されるよう設計されています。 クラスター内では、Linux上でも、Windowsを含めた別のオペレーティングシステム上でも、アプリケーションを実行できます。

1 - 学習環境

2 - プロダクション環境

プロダクション品質のKubernetesクラスターを作成します。

プロダクション環境向けのKubernetesクラスターには計画と準備が必要です。Kubernetesクラスターが重要なワークロードを動かしている場合、耐障害性のある構成にしなければいけません。このページはプロダクション環境で利用できるクラウターのセットアップをするための手順や既存のクラスターをプロダクション環境で利用できるように昇格するための手順を説明します。 既にプロダクション環境のセットアップを理解している場合、次の項目に進んでください。

プロダクション環境の考慮事項

通常、プロダクション用のKubernetesクラスター環境は個人学習の環境や開発環境、テスト環境より多くの要件があります。プロダクション環境は多くのユーザーによるセキュアなアクセスや安定した可用性、変化する需要に適用するためのリソースが必要になる場合があります。

プロダクション用のKubernetes環境をどこに配置するか(オンプレミスまたはクラウド)、どの程度の管理を自分で行うか、それとも他に任せるかを決定する際には、以下の問題がKubernetesクラスターに対する要件にどのように影響を与えるかを考慮してください。

  • 可用性: 単一のマシンで動作するKubernetes学習環境には単一障害点があります。高可用性のクラスターの作成するには下記の点を考慮する必要があります。

    • ワーカーノードからのコントロールプレーンの分離
    • 複数ノードへのコントロールプレーンのレプリケーション
    • クラスターのAPIサーバーへのトラフィックの負荷分散
    • 変化するワークロードに応じて、十分な数のワーカーノードが利用可能であること、または迅速に利用可能になること
  • スケール: プロダクション用のKubernetes環境が安定した要求を受けることが予測できる場合、必要なキャパシティをセットアップすることができるかもしれません。しかし、時間の経過と共に成長する需要やシーズンや特別なイベントのようなことで大幅な変化を予測する場合、コントロールプレーンやワーカーノードへの多くのリクエストにより増加する負荷を軽減するスケールの方法や未使用のリソースを削減するためのスケールダウンの方法を計画する必要があリます。

  • セキュリティやアクセス管理: 自身のKubernetes学習クラスターでは全管理者権限を持っています。しかし、重要なワークロードを保持していたり、複数のユーザーが利用する共有クラスターでは、誰がどのクラスターのリソースに対してアクセスできるかをより制限されたアプローチを必要とします。ユーザーやワークロードが必要なリソースへアクセスできることを実現するロールベースアクセス制御(RBAC)や他のセキュリティメカニズムを使用し、ワークロードやクラスターを保護することができます。ポリシーコンテナリソースを管理することによってユーザーやワークロードがアクセスできるリソースの制限を設定できます。

自身のプロダクション環境のKubernetesを構築する前に、ターンキークラウドソリューションや プロバイダーや他のKubernetesパートナーへ仕事の一部や全てを委託することを考えてください。オプションには次のものが含まれます。

  • サーバーレス: クラスターを全く管理せずに第三者の設備上でワークロードを実行します。CPU使用量やメモリ、ディスクリクエストなどの利用に応じて課金します。
  • マネージドコントロールプレーン: クラスターのコントロールプレーンのスケールと可用性やパッチとアップグレードの実行をプロバイダーに管理してもらいます。
  • マネージドワーカーノード: 需要に合わせてノードのプールを構成し、プロバイダーがワーカーノードが利用可能であることを保証し、需要に応じたアップグレードを実施できるようにします。
  • 統合: ストレージ、コンテナレジストリ、認証方法、開発ツールなどの他の必要なサービスとKubernetesを統合するプロバイダーも存在します。

プロダクション用のKubernetesクラスターを自身で構築する場合でもパートナーと連携する場合でもクラスターのコントロールプレーンワーカーノードユーザーアクセス、およびワークロードリソースに関連する要件を評価するために以下のセクションのレビューを行なってください。

プロダクション環境のクラスターのセットアップ

プロダクション環境向けのKubernetesクラスターでは、コントロールプレーンが異なる方法で複数のコンピューターに分散されたサービスからクラスターを管理します。一方で、各ワーカーノードは単一のエンティティとして表され、KubernetesのPodを実行するように設定されています。

プロダクション環境のコントロールプレーン

最もシンプルなKubernetesクラスターはすべてのコントロールプレーンとワーカーノードサービスが同一のマシン上で稼働しています。Kubernetesコンポーネントの図に示すようにワーカーノードの追加によって環境をスケールさせることができます。クラスターが短時間の稼働や深刻な問題が起きたときに破棄してもよい場合は、同一マシン上での構成で要件を満たしているかもしれません。

永続性や高可用性のクラスターが必要であれば、コントロールプレーンの拡張方法を考えなければいけません。設計上、単一のマシンで動作するコントロールプレーンサービスは高可用性ではありません。クラスターを常に稼働させ、何か問題が発生した場合に修復できる保証が重要な場合は、以下のステップを考えてください。

  • デプロイツールの選択: kubeadm、kopsやkubesprayなどのツールを使ってコントロールプレーンをデプロイできます。これらのデプロイメント方法を使用したプロダクション環境向けののデプロイのヒントを学ぶためにデプロイツールによるKubernetesのインストールをご覧になってください。異なるコンテナランタイムをデプロイに使用することができます。
  • 証明書の管理: コントロールプレーンサービス間の安全な通信は証明書を使用して実装されています。証明書はデプロイ時に自動で生成したり、独自の認証局を使用し生成することができます。詳細はPKI証明書と要件をご覧ください。
  • APIサーバー用のロードバランサーの構成: 外部からのAPIリクエストを異なるノード上で稼働しているAPIサーバーサービスインスタンスに分散させるためにロードバランサーを設定します。詳細は 外部ロードバランサーの作成をご覧ください。
  • etcdサービスの分離とバックアップ: etcdサービスは他のコントロールプレーンサービスと同じマシン上で動作させることも、追加のセキュリティと可用性のために別のマシン上で動作させることもできます。etcdはクラスターの構成データを格納しており、必要に応じてデータベースを修復できるようにするためにetcdデータベースのバックアップは定期的に行うべきです。etcdの構成と使用に関する詳細はetcd FAQをご覧ください。また、Kubernetes向けのetcdクラスターの運用kubeadmを使用した高可用性etcdクラスターのセットアップもご覧ください。
  • 複数のコントロールプレーンシステムの作成: 高可用性のためにコントロールプレーンは単一のマシンに限定されるべきではありません。コントロールプレーンサービスはinitサービス(systemdなど)によって実行される場合、各サービスは少なくとも3台のマシンで実行されるべきです。しかし、Kubernetes内でPodとしてコントロールプレーンサービスを実行することで、リクエストしたサービスのレプリカ数が常に利用可能であることが保証されます。スケジューラーは耐障害性が備わっているべきですが、高可用性は必要ありません。一部のデプロイメントツールはKubernetesサービスのリーダー選出のためにRaftコンセンサスアルゴリズムを設定しています。プライマリが失われた場合、別のサービスが自らを選出して引き継ぎます。
  • 複数ゾーンへの配置: クラスターを常に利用可能に保つことが重要である場合、複数のデータセンターにまたがって実行されるクラスターを作成することを検討してください。クラウド環境ではゾーンと呼ばれます。ゾーンのグループはリージョンと呼ばれます。同リージョンで複数のゾーンにクラスターを分散させることで、一つのゾーンが利用不可能になったとしても、クラスターが機能し続ける可能性を向上できます。詳細は、複数ゾーンでの稼働をご覧ください。
  • 継続的な機能の管理: クラスターを長期間稼働する計画がある場合、正常性とセキュリティを維持するために行うべきタスクがあります。例えば、kubeadmを使用してインストールした場合、証明書管理kubeadmによるクラスターのアップグレードを支援するドキュメントがあります。より多くのKubernetes管理タスクのリストについては、クラスターの管理をご覧ください。

コントロールプレーンサービスを実行する際の利用可能なオプションについて学ぶためには、kube-apiserverkube-controller-managerkube-schedulerのコンポーネントページをご覧ください。高可用性のコントロールプレーンの例については、高可用性トポロジーのオプションkubeadmを使用した高可用性クラスターの作成Kubernetes向けetcdクラスターの運用をご覧ください。etcdクラスターのバックアップ計画の作成については、etcdクラスターのバックアップをご覧ください。

プロダクション環境のワーカーノード

プロダクション向けのワークロードとそのワークロードが依存するサービス(CoreDNSなど)は耐障害性を必要とします。自身でコントロールプレーンを管理するか、クラウドプロバイダーに任せるかに関わらず、ワーカーノード(単にノードとも呼ばれます)の管理方法を考える必要があります。

  • ノードの構成: ノードは物理マシンもしくは仮想マシンになります。ノードを自身で作成し管理したい場合、サポートされてるオペレーティングシステムをインストールし、適切なノードサービスを追加し、実行します。

    • ノードをセットアップする際に、ワークロードの需要に合わせた適切なメモリ、CPU、ディスク速度、ストレージ容量を確保することを考えること
    • 汎用コンピュータシステムで十分か、GPUプロセッサやWindowsノード、VMの分離を必要とするワークロードがあるかどうかを考えること
  • ノードの検証: ノードがKubernetesクラスターに参加するための要件を満たしていることを保証する方法についての情報は有効なノードのセットアップをご覧ください。

  • クラスターへのノードの追加: 自身でクラスターを管理している場合、自身のマシンをセットアップし手動で追加するか、または自動でクラスターのAPIサーバーに登録させることによってノードを追加できます。これらのKubernetesへノードを追加するためのセットアップ方法については、ノードセクションをご覧ください。

  • ノードのスケール: クラスターのキャパシティの拡張プランを作成することは最終的に必要になります。稼働させなければいけないPod数やコンテナ数を基にどのくらいのノード数が必要なのかを決定をするための助けとなる大規模クラスターの考慮事項をご覧ください。自身でノードを管理する場合、自身で物理機材を購入し設置することを意味します。

  • ノードのオートスケーリング: ノードやノードが提供するキャパシティを自動的に管理するために利用できるツールについて学ぶために、クラスターのオートスケーリングをご覧ください。

  • ノードのヘルスチェックのセットアップ: 重要なワークロードのためにノード上で稼働しているノードとPodが正常であることを確認しなければいけません。Node Problem Detectorデーモンを使用し、ノードが正常であることを保証してください。

プロダクション環境のユーザー管理

プロダクション環境では、自身または少人数の小さなグループがクラスターにアクセスするモデルから、数十人から数百人がアクセスする可能性のあるモデルへと移行するかもしれません。学習環境やプラットフォームのプロトタイプでは、すべての作業を行うための1つの管理アカウントを持っているかもしれません。プロダクション環境では、異なる名前空間へのアクセスレベルが異なる複数のアカウントを持つことになリます。

プロダクション環境向けのクラスターを運用することは、他のユーザーによるアクセスを選択的に許可する方法を決定することを意味します。特に、クラスターにアクセスをしようとするユーザーの身元を検証するための戦略を選択し(認証)、ユーザーが要求する操作に対して権限があるかどうかを決定する必要があります(認可)。:

  • 認証: APIサーバーはクライアント証明書、bearerトークン、認証プロキシまたはHTTPベーシック認証を使用し、ユーザーを認証できます。使用したい認証の方法を選択できます。プラグインを使用することで、APIサーバーはLDAPやKerberosなどの組織の既存の認証方法を活用できます。Kubernetesユーザーを認証する様々な方法の説明は認証をご覧ください。
  • 認可: 通常のユーザーを認可する際には、おそらくRBACとABACの認可方法のどちらかを選択することになります。様々なユーザーアカウントの認可方式(およびサービスアカウントによるクラスターがアクセスするための認可方式)を評価するために、認可の概要をご覧ください。
  • ロールベースアクセスコントロール: (RBAC): 認証されたユーザーに特定の権限のセットを許可することによってクラスターへのアクセスを割り当てることができます。特定のNamespace(Role)やクラスター全体(ClusterRole)に権限を割り当てることができます。RoleBindingsやClusterRoleBindingsを使用することによって、権限を特定のユーザーに付与することができます。
  • 属性ベースアクセスコントロール (ABAC): クラスターのリソース属性に基づいたポリシーを作成し、その属性に基づいてアクセスを許可または拒否することができます。ポリシーファイルの各行は、バージョニングプロパティ(apiVersionとkind)やsubject(ユーザーやグループ)に紐づくプロパティとリソースに紐づくプロパティとリソースに紐づかないプロパティ(/version or /apis)と読み取り専用プロパティを持つmapのspecプロパティを特定します。詳細は、Examplesをご覧ください。

プロダクション用のKubernetesクラスターの認証認可をセットアップするにあたって、いくつかの考慮事項があります。

  • 認証モードの設定: Kubernetes APIサーバー (kube-apiserver)の起動時に、--authorization-modeフラグを使用しサポートされた認証モードを設定しなければいけません。例えば、/etc/kubernetes/manifests配下のkube-adminserver.yamlファイルで*--authorization-mode*フラグにNodeやRBACを設定することで、認証されたリクエストに対してノードやRBACの認証を許可することができます。
  • ユーザー証明書とロールバインディングの作成(RMAC): RBAC認証を使用している場合、ユーザーはクラスター証明機関により署名された証明書署名要求(CSR)を作成でき、各ユーザーにRolesとClusterRolesをバインドすることができます。詳細は証明書署名要求をご覧ください。
  • 属性を組み合わせたポリシーの作成(ABAC): ABAC認証を使用している場合、特定のリソース(例えばPod)、Namespace、またはAPIグループにアクセスするために、選択されたユーザーやグループに属性の組み合わせで形成されたポリシーを割り当てることができます。より多くの情報はExamplesをご覧ください。
  • アドミッションコントローラーの考慮事項: APIサーバーを経由してくるリクエストのための追加の認証形式にWebhookトークン認証があります。Webhookや他の特別な認証形式はAPIサーバーへアドミッションコントローラーを追加し有効化される必要があります。

ワークロードリソースの制限の設定

プロダクションワークロードからの要求はKubernetesのコントロールプレーンの内外の両方で負荷が生じる原因になります。クラスターのワークロードの需要に合わせて設定するためには、次の項目を考慮してください。

  • Namespaceの制限の設定: メモリやCPUなどの項目のクォートをNamespaceごとに設定します。詳細については、メモリー、CPU、APIリソースの管理をご覧ください。制限を継承するために階層型Namespaceを設定することもできます。
  • DNS要求のための準備: ワークロードの急激なスケールアップを予測するのであれば、DNSサービスもスケールアップする準備をする必要があります。詳細については、クラスター内のDNSサービスのオートスケールをご覧ください。
  • 追加のサービスアカウントの作成: ユーザーアカウントはクラスターで何ができるかを決定し、サービスアカウントは特定のNamespace内でのPodへのアクセスを定義します。 デフォルトでは、Podは名前空間のデフォルトのサービスアカウントを引き受けます。新規のサービスアカウントの作成についての情報はサービスアカウントの管理をご覧ください。例えば、以下のようなことが考えられます:

次の項目

2.1 - コンテナランタイム

備考: dockershimは1.24のリリースをもってKubernetesプロジェクトから削除されました。詳しくは、dockershimの削除に関するFAQをご覧ください。

クラスター内の各ノードがPodを実行できるようにするため、コンテナランタイムをインストールする必要があります。 このページでは、ノードをセットアップするための概要と関連する作業について説明します。

Kubernetes 1.36においては、Container Runtime Interface (CRI)に準拠したランタイムを使用する必要があります。

詳しくはサポートするCRIのバージョンをご覧ください。

このページではいくつかの一般的なコンテナランタイムをKubernetesで使用する方法の概要を説明します。

備考:

v1.24以前のKubernetesリリースでは、 dockershim という名前のコンポーネントを使用したDocker Engineとの直接の統合が含まれていました。 この特別な直接統合は、もはやKubernetesの一部ではありません(この削除はv1.20リリースの一部として発表されています)。 dockershimの廃止がどのような影響を与えるかについては、dockershim削除の影響範囲を確認する をご覧ください。 dockershimからの移行について知りたい場合、dockershimからの移行を参照してください。

v1.36以外のバージョンのKubernetesを実行している場合、そのバージョンのドキュメントを確認してください。

インストールと設定の必須要件

ネットワーク構成

デフォルトでは、Linuxカーネルはインターフェース間でのIPv4パケットのルーティングを許可していません。 Kubernetesクラスターのネットワーク実装の多くは、必要に応じてこの設定を変更しますが、管理者が設定することを想定しているものもあります。 (他のsysctlパラメーターの設定やカーネルモジュールの読み込みなども必要になる場合があります。使用しているネットワーク実装のドキュメントを参照してください。)

IPv4パケットフォワーディングを有効化する

IPv4パケットフォワーディングを手動で有効にするには、以下のコマンドを実行します。

# セットアップに必要なsysctlパラメーター。値は再起動後も保持されます
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
EOF

# 再起動せずにsysctlパラメーターを適用
sudo sysctl --system

以下のコマンドを実行して、net.ipv4.ip_forwardが1に設定されていることを確認します。

sysctl net.ipv4.ip_forward

cgroupドライバー

Linuxでは、プロセスに割り当てられるリソースを制約するためにcgroupが使用されます。

kubeletと基盤となるコンテナランタイムは、コンテナのリソース管理を実施し、CPU/メモリーの要求や制限などのリソースを設定するため、cgroupとインターフェースする必要があります。 cgroupとインターフェースするために、kubeletおよびコンテナランタイムはcgroupドライバーを使用する必要があります。 この際、kubeletとコンテナランタイムが同一のcgroupドライバーを使用し、同一の設定を適用することが不可欠となります。

利用可能なcgroupドライバーは以下の2つです。

cgroupfsドライバー

cgroupfsドライバーは、kubeletのデフォルトのcgroupドライバーです。 cgroupfsドライバーを使用すると、kubeletとコンテナランタイムはcgroupファイルシステムと直接インターフェースし、cgroupを設定します。

systemdがinitシステムである場合、cgroupfsドライバーは推奨されません。 なぜなら、systemdはシステム上のcgroupマネージャーが単一であると想定しているからです。 また、cgroup v2を使用している場合は、cgroupfsの代わりにsystemd cgroupドライバーを使用してください。

systemd cgroupドライバー

Linuxディストリビューションのinitシステムにsystemdが選択されている場合、 initプロセスはルートcgroupを生成・消費し、cgroupマネージャーとして動作します。

systemdはcgroupと密接に連携しており、systemdユニットごとにcgroupを割り当てます。 その結果、initシステムにsystemdを使用した状態でcgroupfsドライバーを使用すると、 システムには2つの異なるcgroupマネージャーが存在することになります。

2つのcgroupマネージャーが存在することで、システムで利用可能なリソースおよび使用中のリソースに、2つの異なる見え方が与えられることになります。 特定の場合において、kubeletとコンテナランタイムにcgroupfsを、残りのプロセスにsystemdを使用するように設定されたノードが高負荷時に不安定になることがあります。

このような不安定性を緩和するためのアプローチは、systemdがinitシステムに採用されている場合にkubeletとコンテナランタイムのcgroupドライバーとしてsystemdを使用することです。

cgroupドライバーにsystemdを設定するには、以下のようにKubeletConfigurationcgroupDriverオプションを編集してsystemdを設定します。

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
...
cgroupDriver: systemd

kubelet用のcgroupドライバーとしてsystemdを設定する場合、コンテナランタイムのcgroupドライバーにもsystemdを設定する必要があります。 具体的な手順については、以下のリンクなどの、お使いのコンテナランタイムのドキュメントを参照してください。

注意:

クラスターに参加したノードのcgroupドライバーを変更するのはデリケートな操作です。 kubeletが特定のcgroupドライバーのセマンティクスを使用してPodを作成していた場合、 コンテナランタイムを別のcgroupドライバーに変更すると、そのような既存のPodに対してPodサンドボックスを再作成しようとしたときにエラーが発生することがあります。 kubeletを再起動してもこのようなエラーは解決しない可能性があります。

もしあなたが適切な自動化の手段を持っているのであれば、更新された設定を使用してノードを別のノードに置き換えるか、自動化を使用して再インストールを行ってください。

kubeadmで管理されたクラスターでのsystemdドライバーへの移行

既存のkubeadm管理クラスターでsystemd cgroupドライバーに移行したい場合は、cgroupドライバーの設定に従ってください。

サポートするCRIのバージョン

コンテナランタイムは、Container Runtime Interfaceのv1alpha2以上をサポートする必要があります。

Kubernetes 1.36は、デフォルトでCRI APIのv1を使用します。 コンテナランタイムがv1 APIをサポートしていない場合、kubeletは代わりに(非推奨の)v1alpha2 APIにフォールバックします。

コンテナランタイム

備考: このセクションでは、Kubernetesが必要とする機能を提供するサードパーティプロジェクトにリンクしています。これらのプロジェクトはアルファベット順に記載されていて、Kubernetesプロジェクトの作者は責任を持ちません。このリストにプロジェクトを追加するには、変更を提出する前にコンテンツガイドをお読みください。詳細はこちら。

containerd

このセクションでは、CRIランタイムとしてcontainerdを使用するために必要な手順の概要を説明します。

以下のコマンドを使用して、システムにcontainerdをインストールします:

まずはcontainerdの使用を開始するの指示に従ってください。有効なconfig.toml設定ファイルを作成したら、このステップに戻ります。

このファイルはパス/etc/containerd/config.tomlにあります。

このファイルはC:\Program Files\containerd\config.tomlにあります。

Linuxでは、containerd用のデフォルトのCRIソケットは/run/containerd/containerd.sockです。 Windowsでは、デフォルトのCRIエンドポイントはnpipe://./pipe/containerd-containerdです。

systemd cgroupドライバーを構成する

/etc/containerd/config.toml内でruncsystemd cgroupドライバーを使うようにするには、Containerdのバージョンに基づいて以下の設定を行ってください。

Containerdバージョン1.x:

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

Containerdバージョン2.x:

[plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc]
  ...
  [plugins.'io.containerd.cri.v1.runtime'.containerd.runtimes.runc.options]
    SystemdCgroup = true

cgroup v2を使用する場合はsystemd cgroupドライバーの利用を推奨します。

備考:

パッケージ(RPMや.debなど)からcontainerdをインストールした場合、 CRI統合プラグインがデフォルトで無効になっていることがあります。

Kubernetesでcontainerdを使用するには、CRIサポートを有効にする必要があります。 /etc/containerd/config.toml内のdisabled_pluginsリストにcriが含まれていないことを確認してください。 このファイルを変更した場合、containerdも再起動してください。

クラスターの初回構築後、またはCNIをインストールした後にコンテナのクラッシュループが発生した場合、 パッケージと共に提供されるcontainerdの設定に互換性のないパラメーターが含まれている可能性があります。 get-started.mdにあるように、 containerd config default > /etc/containerd/config.tomlでcontainerdの設定をリセットした上で、 上記の設定パラメーターを使用することを検討してください。

この変更を適用した場合、必ずcontainerdを再起動してください。

sudo systemctl restart containerd

kubeadmを使用している場合、手動でkubelet cgroupドライバーの設定を行ってください。

サンドボックス(pause)イメージの上書き

containerdの設定で以下の設定をすることで、サンドボックスのイメージを上書きすることができます。

[plugins."io.containerd.grpc.v1.cri"]
  sandbox_image = "registry.k8s.io/pause:3.2"

この場合も、設定ファイルの更新後にsystemctl restart containerdを実行してcontainerdも再起動する必要があるでしょう。

CRI-O

本セクションでは、コンテナランタイムとしてCRI-Oをインストールするために必要な手順を説明します。

CRI-Oをインストールするには、CRI-Oのインストール手順に従ってください。

cgroupドライバー

CRI-Oはデフォルトでsystemd cgroupドライバーを使用し、おそらく問題なく動作します。 cgroupfs cgroupドライバーに切り替えるには、/etc/crio/crio.conf を編集するか、 /etc/crio/crio.conf.d/02-cgroup-manager.confにドロップイン設定ファイルを置いて、以下のような設定を記述してください。

[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "cgroupfs"

上記でconmon_cgroupも変更されていることに注意してください。 CRI-Oでcgroupfsを使用する場合、ここにはpodという値を設定する必要があります。 一般に、kubeletのcgroupドライバーの設定(通常はkubeadmによって行われます)とCRI-Oの設定は一致させる必要があります。

CRI-Oの場合、CRIソケットはデフォルトで/var/run/crio/crio.sockとなります。

サンドボックス(pause)イメージの上書き

CRI-Oの設定において、以下の値を設定することができます。

[crio.image]
pause_image="registry.k8s.io/pause:3.6"

このオプションはライブ設定リロードによる変更の適用に対応しています。 systemctl reload crioまたはcrioプロセスにSIGHUPを送信することで変更を適用できます。

Docker Engine

備考:

この手順では、Docker EngineとKubernetesを統合するためにcri-dockerdアダプターを使用することを想定しています。
  1. 各ノードに、使用しているLinuxディストリビューション用のDockerをDocker Engineのインストールに従ってインストールします。

  2. cri-dockerdをリポジトリ内の指示に従ってインストールします。

cri-dockerdの場合、CRIソケットはデフォルトで/run/cri-dockerd.sockになります。

Mirantis Container Runtime

Mirantis Container Runtime(MCR)は、 以前はDocker Enterprise Editionとして知られていた、商業的に利用可能なコンテナランタイムです。

MCRに含まれるオープンソースのcri-dockerdコンポーネントを使用することで、 Mirantis Container RuntimeをKubernetesで使用することができます。

Mirantis Container Runtimeのインストール方法について知るには、MCRデプロイガイドを参照してください。

CRIソケットのパスを見つけるには、systemdのcri-docker.socketという名前のユニットを確認してください。

サンドボックス(pause)イメージを上書きする

cri-dockerdアダプターは、Podインフラコンテナ("pause image")として使用するコンテナイメージを指定するためのコマンドライン引数を受け付けます。 使用するコマンドライン引数は --pod-infra-container-imageです。

次の項目

コンテナランタイムに加えて、クラスターには動作するネットワークプラグインが必要です。

2.2 - Kubernetesをデプロイツールでインストールする

2.2.1 - kubeadmを使ってクラスターを構築する

2.2.1.1 - kubeadmのインストール

このページではkubeadmコマンドをインストールする方法を示します。このインストール処理実行後にkubeadmを使用してクラスターを作成する方法については、kubeadmを使用したシングルマスタークラスターの作成を参照してください。

始める前に

  • 次のいずれかが動作しているマシンが必要です
    • Ubuntu 16.04+
    • Debian 9+
    • CentOS 7
    • Red Hat Enterprise Linux (RHEL) 7
    • Fedora 25+
    • HypriotOS v1.0.1+
    • Container Linux (tested with 1800.6.0)
  • 1台あたり2GB以上のメモリ(2GBの場合、アプリ用のスペースはほとんどありません)
  • 2コア以上のCPU
  • クラスター内のすべてのマシン間で通信可能なネットワーク(パブリックネットワークでもプライベートネットワークでも構いません)
  • ユニークなhostname、MACアドレス、とproduct_uuidが各ノードに必要です。詳細はここを参照してください。
  • マシン内の特定のポートが開いていること。詳細はここを参照してください。
  • Swapがオフであること。kubeletが正常に動作するためにはswapは必ずオフでなければなりません。

MACアドレスとproduct_uuidが全てのノードでユニークであることの検証

  • ネットワークインターフェースのMACアドレスはip linkもしくはifconfig -aコマンドで取得できます。
  • product_uuidはsudo cat /sys/class/dmi/id/product_uuidコマンドで確認できます。

ハードウェアデバイスではユニークなアドレスが割り当てられる可能性が非常に高いですが、VMでは同じになることがあります。Kubernetesはこれらの値を使用して、クラスター内のノードを一意に識別します。これらの値が各ノードに固有ではない場合、インストール処理が失敗することもあります。

ネットワークアダプタの確認

複数のネットワークアダプターがあり、Kubernetesコンポーネントにデフォルトで到達できない場合、IPルートを追加して、Kubernetesクラスターのアドレスが適切なアダプターを経由するように設定することをお勧めします。

必須ポートの確認

Kubernetesのコンポーネントが互いに通信するためには、これらの必要なポートが開いている必要があります。 netcatなどのツールを使用することで、下記のようにポートが開いているかどうかを確認することが可能です。

nc 127.0.0.1 6443 -zv -w 2

使用するPodネットワークプラグインによっては、特定のポートを開く必要がある場合もあります。 これらは各Podネットワークプラグインによって異なるため、どのようなポートが必要かについては、プラグインのドキュメントを参照してください。

ランタイムのインストール

Podのコンテナを実行するために、Kubernetesはコンテナランタイムを使用します。

デフォルトでは、Kubernetesは選択されたコンテナランタイムと通信するためにContainer Runtime Interface (CRI)を使用します。

ランタイムを指定しない場合、kubeadmはよく知られたUnixドメインソケットのリストをスキャンすることで、インストールされたコンテナランタイムの検出を試みます。 次の表がコンテナランタイムと関連するソケットのパスリストです。

コンテナランタイムとソケットパス
ランタイムUnixドメインソケットのパス
Docker/var/run/docker.sock
containerd/run/containerd/containerd.sock
CRI-O/var/run/crio/crio.sock

Dockerとcontainerdの両方が同時に検出された場合、Dockerが優先されます。Docker 18.09にはcontainerdが同梱されており、両方が検出可能であるため、この仕様が必要です。他の2つ以上のランタイムが検出された場合、kubeadmは適切なエラーメッセージで終了します。

kubeletは、組み込まれたdockershimCRIを通してDockerと連携します。

詳細は、コンテナランタイムを参照してください。

デフォルトでは、kubeadmはDockerをコンテナランタイムとして使用します。 kubeletは、組み込まれたdockershimCRIを通してDockerと連携します。

詳細は、コンテナランタイムを参照してください。

kubeadm、kubelet、kubectlのインストール

以下のパッケージをマシン上にインストールしてください

  • kubeadm: クラスターを起動するコマンドです。

  • kubelet: クラスター内のすべてのマシンで実行されるコンポーネントです。 Podやコンテナの起動などを行います。

  • kubectl: クラスターにアクセスするためのコマンドラインツールです。

kubeadmはkubeletkubectlをインストールまたは管理しないため、kubeadmにインストールするKubernetesコントロールプレーンのバージョンと一致させる必要があります。そうしないと、予期しないバグのある動作につながる可能性のあるバージョン差異(version skew)が発生するリスクがあります。ただし、kubeletとコントロールプレーン間のマイナーバージョン差異(minor version skew)は_1つ_サポートされていますが、kubeletバージョンがAPIサーバーのバージョンを超えることはできません。たとえば、1.7.0を実行するkubeletは1.8.0 APIサーバーと完全に互換性がありますが、その逆はできません。

kubectlのインストールに関する詳細情報は、kubectlのインストールおよびセットアップを参照してください。

警告:

これらの手順はシステムアップグレードによるすべてのKubernetesパッケージの更新を除きます。これはkubeadmとKubernetesがアップグレードにおける特別な注意を必要とするからです。

バージョン差異(version skew)に関しては下記を参照してください。

  1. aptのパッケージ一覧を更新し、Kubernetesのaptリポジトリーを利用するのに必要なパッケージをインストールします:

    sudo apt-get update
    # apt-transport-httpsはダミーパッケージの可能性があります。その場合、そのパッケージはスキップできます
    sudo apt-get install -y apt-transport-https ca-certificates curl gpg
    
  2. Kubernetesパッケージリポジトリーの公開署名キーをダウンロードします。すべてのリポジトリーに同じ署名キーが使用されるため、URL内のバージョンは無視できます:

    # `/etc/apt/keyrings`フォルダーが存在しない場合は、curlコマンドの前に作成する必要があります。下記の備考を参照してください。
    # sudo mkdir -p -m 755 /etc/apt/keyrings
    curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
    

備考:

Debian 12とUbuntu 22.04より古いリリースでは、/etc/apt/keyringsフォルダーはデフォルトでは存在しないため、curlコマンドの前に作成する必要があります。
  1. 適切なKubernetes aptリポジトリーを追加します。このリポジトリーには、Kubernetes 1.36用のパッケージのみがあることに注意してください。他のKubernetesマイナーバージョンの場合は、目的のマイナーバージョンに一致するようにURL内のKubernetesマイナーバージョンを変更する必要があります(インストールする予定のKubernetesバージョンのドキュメントも読んでください):

    # これにより、/etc/apt/sources.list.d/kubernetes.listにある既存の設定が上書きされます
    echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.36/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
    
  2. aptのパッケージ一覧を更新し、kubelet、kubeadm、kubectlをインストールします。そしてバージョンを固定します:

    sudo apt-get update
    sudo apt-get install -y kubelet kubeadm kubectl
    sudo apt-mark hold kubelet kubeadm kubectl
    
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

# SELinuxをpermissiveモードに設定する(効果的に無効化する)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

systemctl enable --now kubelet

Note:

  • setenforce 0およびsed ...を実行することによりSELinuxをpermissiveモードに設定し、効果的に無効化できます。 これはコンテナがホストのファイルシステムにアクセスするために必要です。例えば、Podのネットワークに必要とされます。 kubeletにおけるSELinuxのサポートが改善されるまでは、これを実行しなければなりません。

CNIプラグインをインストールする(ほとんどのPodのネットワークに必要です):

CNI_VERSION="v0.8.2"
ARCH="amd64"
mkdir -p /opt/cni/bin
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz

crictlをインストールする (kubeadm / Kubelet Container Runtime Interface (CRI)に必要です)

CRICTL_VERSION="v1.22.0"
ARCH="amd64"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz

kubeadmkubeletkubectlをインストールしkubeletをsystemd serviceに登録します:

RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
ARCH="amd64"
mkdir -p /opt/bin
cd /opt/bin
curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet,kubectl}
chmod +x {kubeadm,kubelet,kubectl}

curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/kubelet.service" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service
mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/10-kubeadm.conf" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

kubeletを有効化し起動します:

systemctl enable --now kubelet

kubeadmが何をすべきか指示するまで、kubeletはクラッシュループで数秒ごとに再起動します。

コントロールプレーンノードのkubeletによって使用されるcgroupドライバーの設定

Dockerを使用した場合、kubeadmは自動的にkubelet向けのcgroupドライバーを検出し、それを実行時に/var/lib/kubelet/kubeadm-flags.envファイルに設定します。

もしあなたが異なるCRIを使用している場合、/etc/default/kubelet(CentOS、RHEL、Fedoraでは/etc/sysconfig/kubelet)ファイル内のcgroup-driverの値を以下のように変更する必要があります。

KUBELET_EXTRA_ARGS=--cgroup-driver=<value>

このファイルは、kubeletの追加のユーザー定義引数を取得するために、kubeadm initおよびkubeadm joinによって使用されます。

CRIのcgroupドライバーがcgroupfsでない場合にのみそれを行う必要があることに注意してください。なぜなら、これはすでにkubeletのデフォルト値であるためです。

kubeletをリスタートする方法:

systemctl daemon-reload
systemctl restart kubelet

CRI-Oやcontainerdといった他のコンテナランタイムのcgroup driverは実行中に自動的に検出されます。

トラブルシュート

kubeadmで問題が発生した場合は、トラブルシューティングを参照してください。

次の項目

2.2.1.2 - kubeadmのトラブルシューティング

どのプログラムでもそうですが、kubeadmのインストールや実行でエラーが発生することがあります。このページでは、一般的な失敗例をいくつか挙げ、問題を理解して解決するための手順を示しています。

本ページに問題が記載されていない場合は、以下の手順を行ってください:

  • 問題がkubeadmのバグによるものと思った場合:

  • kubeadmがどのように動作するかわからない場合は、Slackの#kubeadmチャンネルで質問するか、StackOverflowで質問をあげてください。その際は、他の方が助けを出しやすいように#kubernetes#kubeadmといったタグをつけてください。

RBACがないため、v1.18ノードをv1.17クラスターに結合できない

v1.18では、同名のノードが既に存在する場合にクラスター内のノードに参加しないようにする機能を追加しました。これには、ブートストラップトークンユーザーがNodeオブジェクトをGETできるようにRBACを追加する必要がありました。

しかし、これによりv1.18のkubeadm joinがkubeadm v1.17で作成したクラスターに参加できないという問題が発生します。

この問題を回避するには、次の2つの方法があります。

  • kubeadm v1.18を用いて、コントロールプレーンノード上でkubeadm init phase bootstrap-tokenを実行します。 これには、ブートストラップトークンの残りのパーミッションも同様に有効にすることに注意してください。

  • kubectl apply -f ...を使って以下のRBACを手動で適用します。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kubeadm:get-nodes
rules:
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubeadm:get-nodes
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubeadm:get-nodes
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:bootstrappers:kubeadm:default-node-token

インストール中にebtablesもしくは他の似たような実行プログラムが見つからない

kubeadm initの実行中に以下のような警告が表示された場合は、以降に記載するやり方を行ってください。

[preflight] WARNING: ebtables not found in system path
[preflight] WARNING: ethtool not found in system path

このような場合、ノード上にebtables, ethtoolなどの実行ファイルがない可能性があります。これらをインストールするには、以下のコマンドを実行します。

  • Ubuntu/Debianユーザーは、apt install ebtables ethtoolを実行してください。
  • CentOS/Fedoraユーザーは、yum install ebtables ethtoolを実行してください。

インストール中にkubeadmがコントロールプレーンを待ち続けて止まる

以下のを出力した後にkubeadm initが止まる場合は、kubeadm initを実行してください:

[apiclient] Created API client, waiting for the control plane to become ready

これはいくつかの問題が原因となっている可能性があります。最も一般的なのは:

  • ネットワーク接続の問題が挙げられます。続行する前に、お使いのマシンがネットワークに完全に接続されていることを確認してください。

  • kubeletのデフォルトのcgroupドライバーの設定がDockerで使用されているものとは異なっている場合も考えられます。 システムログファイル(例: /var/log/message)をチェックするか、journalctl -u kubeletの出力を調べてください:

    error: failed to run Kubelet: failed to create kubelet:
    misconfiguration: kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"
    

    以上のようなエラーが現れていた場合、cgroupドライバーの問題を解決するには、以下の2つの方法があります:

  1. ここの指示に従ってDockerを再度インストールします。

  2. Dockerのcgroupドライバーに合わせてkubeletの設定を手動で変更します。その際は、マスターノード上でkubeletが使用するcgroupドライバーを設定するを参照してください。

  • control plane Dockerコンテナがクラッシュループしたり、ハングしたりしています。これはdocker psを実行し、docker logsを実行して各コンテナを調査することで確認できます。

管理コンテナを削除する時にkubeadmが止まる

Dockerが停止して、Kubernetesで管理されているコンテナを削除しないと、以下のようなことが起こる可能性があります:

sudo kubeadm reset
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
(block)

考えられる解決策は、Dockerサービスを再起動してからkubeadm resetを再実行することです:

sudo systemctl restart docker.service
sudo kubeadm reset

dockerのログを調べるのも有効な場合があります:

journalctl -u docker

Podの状態がRunContainerErrorCrashLoopBackOff、またはErrorとなる

kubeadm initの直後には、これらの状態ではPodは存在しないはずです。

  • kubeadm init直後 にこれらの状態のいずれかにPodがある場合は、kubeadmのリポジトリにIssueを立ててください。ネットワークソリューションをデプロイするまではcoredns(またはkube-dns)はPending状態でなければなりません。
  • ネットワークソリューションをデプロイしてもcoredns(またはkube-dns)に何も起こらない場合にRunContainerErrorCrashLoopBackOffError`の状態でPodが表示された場合は、インストールしたPodネットワークソリューションが壊れている可能性が高いです。より多くのRBACの特権を付与するか、新しいバージョンを使用する必要があるかもしれません。PodネットワークプロバイダーのイシュートラッカーにIssueを出して、そこで問題をトリアージしてください。
  • 1.12.1よりも古いバージョンのDockerをインストールした場合は、systemddockerdを起動する際にMountFlags=slaveオプションを削除してdockerを再起動してください。マウントフラグは/usr/lib/systemd/system/docker.serviceで確認できます。MountFlagsはKubernetesがマウントしたボリュームに干渉し、PodsをCrashLoopBackOff状態にすることがあります。このエラーは、Kubernetesがvar/run/secrets/kubernetes.io/serviceaccountファイルを見つけられない場合に発生します。

coredns(もしくはkube-dns)がPending状態でスタックする

kubeadmはネットワークプロバイダーに依存しないため、管理者は選択したPodネットワークソリューションをインストールをする必要があります。CoreDNSを完全にデプロイする前にPodネットワークをインストールする必要があります。したがって、ネットワークがセットアップされる前の Pending状態になります。

HostPortサービスが動かない

HostPortHostIPの機能は、ご使用のPodネットワークプロバイダーによって利用可能です。Podネットワークソリューションの作者に連絡して、HostPortHostIP機能が利用可能かどうかを確認してください。

Calico、Canal、FlannelのCNIプロバイダーは、HostPortをサポートしていることが確認されています。

詳細については、[CNI portmap documentation] (https://github.com/containernetworking/plugins/blob/master/plugins/meta/portmap/README.md) を参照してください。

ネットワークプロバイダーが portmap CNI プラグインをサポートしていない場合は、NodePortサービスを使用するか、HostNetwork=trueを使用してください。

サービスIP経由でPodにアクセスすることができない

  • 多くのネットワークアドオンは、PodがサービスIPを介して自分自身にアクセスできるようにするヘアピンモードを有効にしていません。これはCNIに関連する問題です。ヘアピンモードのサポート状況については、ネットワークアドオンプロバイダーにお問い合わせください。

  • VirtualBoxを使用している場合(直接またはVagrant経由)は、hostname -iがルーティング可能なIPアドレスを返すことを確認する必要があります。デフォルトでは、最初のインターフェースはルーティング可能でないホスト専用のネットワークに接続されています。これを回避するには/etc/hostsを修正する必要があります。例としてはこのVagrantfileを参照してください。

TLS証明書のエラー

以下のエラーは、証明書の不一致の可能性を示しています。

# kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
  • HOME/.kube/configファイルに有効な証明書が含まれていることを確認し、必要に応じて証明書を再生成します。kubeconfigファイル内の証明書はbase64でエンコードされています。証明書をデコードするにはbase64 --decodeコマンドを、証明書情報を表示するにはopenssl x509 -text -nooutコマンドを用いてください。

  • 環境変数KUBECONFIGの設定を解除するには以下のコマンドを実行するか:

    unset KUBECONFIG
    

    設定をデフォルトのKUBECONFIGの場所に設定します:

    export KUBECONFIG=/etc/kubernetes/admin.conf
    
  • もう一つの回避策は、既存のkubeconfigを"admin"ユーザーに上書きすることです:

    mv  $HOME/.kube $HOME/.kube.bak
    mkdir $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
    

Vagrant内でPodネットワークとしてflannelを使用する時のデフォルトNIC

以下のエラーは、Podネットワークに何か問題があったことを示している可能性を示しています:

Error from server (NotFound): the server could not find the requested resource
  • Vagrant内のPodネットワークとしてflannelを使用している場合は、flannelのデフォルトのインターフェース名を指定する必要があります。

    Vagrantは通常、2つのインターフェースを全てのVMに割り当てます。1つ目は全てのホストにIPアドレス10.0.2.15が割り当てられており、NATされる外部トラフィックのためのものです。

    これは、ホストの最初のインターフェースをデフォルトにしているflannelの問題につながるかもしれません。これは、すべてのホストが同じパブリックIPアドレスを持っていると考えます。これを防ぐには、2番目のインターフェースが選択されるように --iface eth1フラグをflannelに渡してください。

公開されていないIPがコンテナに使われている

状況によっては、kubectl logskubectl runコマンドが以下のようなエラーを返すことがあります:

Error from server: Get https://10.19.0.41:10250/containerLogs/default/mysql-ddc65b868-glc5m/mysql: dial tcp 10.19.0.41:10250: getsockopt: no route to host
  • これには、おそらくマシンプロバイダーのポリシーによって、一見同じサブネット上の他のIPと通信できないIPをKubernetesが使用している可能性があります。

  • DigitalOceanはパブリックIPとプライベートIPをeth0に割り当てていますが、kubeletはパブリックIPではなく、ノードのInternalIPとして後者を選択します。

    ifconfigではエイリアスIPアドレスが表示されないため、ifconfigの代わりにip addr showを使用してこのシナリオをチェックしてください。あるいは、DigitalOcean専用のAPIエンドポイントを使用して、ドロップレットからアンカーIPを取得することもできます:

    curl http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address
    

    回避策としては、--node-ipを使ってどのIPを使うかをkubeletに伝えることです。DigitalOceanを使用する場合、オプションのプライベートネットワークを使用したい場合は、パブリックIP(eth0に割り当てられている)かプライベートIP(eth1に割り当てられている)のどちらかを指定します。これにはkubeadm NodeRegistrationOptions構造体の KubeletExtraArgsセクション が利用できます。

    kubeletを再起動してください:

    systemctl daemon-reload
    systemctl restart kubelet
    

corednsのPodがCrashLoopBackOffもしくはError状態になる

SELinuxを実行しているノードで古いバージョンのDockerを使用している場合、coredns Podが起動しないということが起きるかもしれません。この問題を解決するには、以下のオプションのいずれかを試してみてください:

kubectl -n kube-system get deployment coredns -o yaml | \
  sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
  kubectl apply -f -

CoreDNSにCrashLoopBackOffが発生する別の原因は、KubernetesにデプロイされたCoreDNS Podがループを検出したときに発生します。CoreDNSがループを検出して終了するたびに、KubernetesがCoreDNS Podを再起動しようとするのを避けるために、いくつかの回避策が用意されています。

警告:

SELinuxを無効にするかallowPrivilegeEscalationtrueに設定すると、クラスターのセキュリティが損なわれる可能性があります。

etcdのpodが継続的に再起動する

以下のエラーが発生した場合は:

rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "process_linux.go:110: decoding init error from pipe caused \"read parent: connection reset by peer\""

この問題は、CentOS 7をDocker 1.13.1.84で実行した場合に表示されます。このバージョンのDockerでは、kubeletがetcdコンテナに実行されないようにすることができます。

この問題を回避するには、以下のいずれかのオプションを選択します:

  • 1.13.1-75のような以前のバージョンのDockerにロールバックする
yum downgrade docker-1.13.1-75.git8633870.el7.centos.x86_64 docker-client-1.13.1-75.git8633870.el7.centos.x86_64 docker-common-1.13.1-75.git8633870.el7.centos.x86_64
  • 18.06のような最新の推奨バージョンをインストールする:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce-18.06.1.ce-3.el7.x86_64

コンマで区切られた値のリストを--component-extra-argsフラグ内の引数に渡すことができない

-component-extra-argsのようなkubeadm initフラグを使うと、kube-apiserverのようなコントロールプレーンコンポーネントにカスタム引数を渡すことができます。しかし、このメカニズムは値の解析に使われる基本的な型 (mapStringString) のために制限されています。

もし、--apiserver-extra-args "enable-admission plugins=LimitRanger,NamespaceExists"のようにカンマで区切られた複数の値をサポートする引数を渡した場合、このフラグはflag: malformed pair, expect string=stringで失敗します。これは--apiserver-extra-argsの引数リストがkey=valueのペアを期待しており、この場合NamespacesExistsは値を欠いたキーとみなされるためです。

別の方法として、key=valueのペアを以下のように分離してみることもできます: --apiserver-extra-args "enable-admission-plugins=LimitRanger,enable-admission-plugins=NamespaceExists"しかし、この場合は、キーenable-admission-pluginsNamespaceExistsの値しか持ちません。既知の回避策としては、kubeadm設定ファイルを使用することが挙げられます。

cloud-controller-managerによってノードが初期化される前にkube-proxyがスケジューリングされる

クラウドプロバイダーのシナリオでは、クラウドコントローラーマネージャがノードアドレスを初期化する前に、kube-proxyが新しいワーカーノードでスケジューリングされてしまうことがあります。これにより、kube-proxyがノードのIPアドレスを正しく拾えず、ロードバランサを管理するプロキシ機能に悪影響を及ぼします。

kube-proxy Podsでは以下のようなエラーが発生します:

server.go:610] Failed to retrieve node IP: host IP unknown; known addresses: []
proxier.go:340] invalid nodeIP, initializing kube-proxy with 127.0.0.1 as nodeIP

既知の解決策は、初期のガード条件が緩和されるまで他のノードから離しておき、条件に関係なくコントロールプレーンノード上でスケジューリングできるように、キューブプロキシDaemonSetにパッチを当てることです:

kubectl -n kube-system patch ds kube-proxy -p='{ "spec": { "template": { "spec": { "tolerations": [ { "key": "CriticalAddonsOnly", "operator": "Exists" }, { "effect": "NoSchedule", "key": "node-role.kubernetes.io/master" } ] } } } }'

Tこの問題のトラッキング問題はこちら

kubeadmの設定をマーシャリングする際、NodeRegistration.Taintsフィールドが省略される

注意: このIssueは、kubeadmタイプをマーシャルするツール(YAML設定ファイルなど)にのみ適用されます。これはkubeadm API v1beta2で修正される予定です。

デフォルトでは、kubeadmはコントロールプレーンノードにnode-role.kubernetes.io/master:NoScheduleのテイントを適用します。kubeadmがコントロールプレーンノードに影響を与えないようにし、InitConfiguration.NodeRegistration.Taintsを空のスライスに設定すると、マーシャリング時にこのフィールドは省略されます。フィールドが省略された場合、kubeadmはデフォルトのテイントを適用します。

少なくとも2つの回避策があります:

  1. 空のスライスの代わりにnode-role.kubernetes.io/master:PreferNoScheduleテイントを使用します。他のノードに容量がない限り、Podsはマスター上でスケジュールされます

  2. kubeadm init終了後のテイントの除去:

kubectl taint nodes NODE_NAME node-role.kubernetes.io/master:NoSchedule-

ノード{#usr-mounted-read-only}に/usrが読み取り専用でマウントされる

Fedora CoreOSなどのLinuxディストリビューションでは、ディレクトリ/usrが読み取り専用のファイルシステムとしてマウントされます。 flex-volumeサポートでは、kubeletやkube-controller-managerのようなKubernetesコンポーネントはデフォルトで/usr/libexec/kubernetes/kubelet-plugins/volume/exec/のパスを使用していますが、この機能を動作させるためにはflex-volumeディレクトリは 書き込み可能 な状態でなければなりません。

この問題を回避するには、kubeadm設定ファイルを使用してflex-volumeディレクトリを設定します。

プライマリコントロールプレーンノード(kubeadm initで作成されたもの)上で、--configで以下のファイルを渡します:

apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
nodeRegistration:
  kubeletExtraArgs:
    volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
controllerManager:
  extraArgs:
    flex-volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"

ノードをジョインするには:

apiVersion: kubeadm.k8s.io/v1beta2
kind: JoinConfiguration
nodeRegistration:
  kubeletExtraArgs:
    volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"

あるいは、/usrマウントを書き込み可能にするために /etc/fstabを変更することもできますが、これはLinuxディストリビューションの設計原理を変更していることに注意してください。

kubeadm upgrade plancontext deadline exceededエラーメッセージを表示する

このエラーメッセージは、外部etcdを実行している場合にkubeadmでKubernetesクラスターをアップグレードする際に表示されます。これは致命的なバグではなく、古いバージョンのkubeadmが外部etcdクラスターのバージョンチェックを行うために発生します。kubeadm upgrade apply ...で進めることができます。

この問題はバージョン1.19で修正されます。

2.2.1.3 - kubeadmを使用したクラスターの作成

ベストプラクティスに準拠した実用最小限のKubernetesクラスターを作成します。 実際、kubeadmを使用すれば、Kubernetes Conformance testsに通るクラスターをセットアップすることができます。 kubeadmは、ブートストラップトークンやクラスターのアップグレードなどのその他のクラスターのライフサイクルの機能もサポートします。

kubeadmツールは、次のようなときに適しています。

  • 新しいユーザーが初めてKubernetesを試すためのシンプルな方法が必要なとき。
  • 既存のユーザーがクラスターのセットアップを自動化し、アプリケーションをテストする方法が必要なとき。
  • より大きなスコープで、他のエコシステムやインストーラーツールのビルディングブロックが必要なとき。

kubeadmは、ラップトップ、クラウドのサーバー群、Raspberry Piなどの様々なマシンにインストールして使えます。クラウドとオンプレミスのどちらにデプロイする場合でも、kubeadmはAnsibleやTerraformなどのプロビジョニングシステムに統合できます。

始める前に

このガイドを進めるには、以下の環境が必要です。

  • UbuntuやCentOSなど、deb/rpmパッケージと互換性のあるLinux OSが動作している1台以上のマシンがあること。
  • マシンごとに2GiB以上のRAMが搭載されていること。それ以下の場合、アプリ実行用のメモリがほとんど残りません。
  • コントロールプレーンノードとして使用するマシンには、最低でも2CPU以上あること。
  • クラスター内の全マシン間に完全なネットワーク接続があること。パブリックネットワークとプライベートネットワークのいずれでも使えます。

また、新しいクラスターで使いたいKubernetesのバージョンをデプロイできるバージョンのkubeadmを使用する必要もあります。

Kubernetesのバージョンとバージョンスキューポリシーは、kubeadmにもKubernetes全体と同じように当てはまります。 Kubernetesとkubeadmがサポートするバージョンを理解するには、上記のポリシーを確認してください。このページは、Kubernetes v1.36向けに書かれています。

kubeadmツールの全体の機能の状態は、一般利用可能(GA)です。一部のサブ機能はまだ活発に開発が行われています。クラスター作成の実装は、ツールの進化に伴ってわずかに変わるかもしれませんが、全体の実装は非常に安定しているはずです。

備考:

kubeadm alpha以下のすべてのコマンドは、定義通り、アルファレベルでサポートされています。

目的

  • シングルコントロールプレーンのKubernetesクラスターをインストールします
  • クラスター上にPodネットワークをインストールして、Podがお互いに通信できるようにします

手順

ホストの準備

コンポーネントのインストール

コンテナランタイムと、kubeadmを全てのホストにインストールしてください。 インストールの詳細やその他の準備については、kubeadmのインストールを読んでください。

備考:

すでにkubeadmがインストール済みである場合は、kubeadmのアップグレード手順についてはLinuxノードのアップグレードの最初の2ステップを確認してください。

アップグレード中、kubeletはクラッシュループによってkubeadmの指示を待つため、数秒ごとに再起動します。 このクラッシュループは想定内の正常な動作です。 コントロールプレーンの初期化が完了すれば、kubeletは正常に動作します。

ネットワークの設定

kubeadmは他のKubernetesコンポーネントと同様に、ホスト上のデフォルトゲートウェイとなっているネットワークインターフェースと関連づけられた利用可能なIPアドレスを探索します。 このIPアドレスは、コンポーネントによるアドバタイズや受信に使用されます。

Linuxのホスト上でこのIPを確認するには次のようにします:

ip route show # "default via"で始まる行を探してください。

備考:

2つ以上のデフォルトゲートウェイがホスト上に存在する場合、Kubernetesコンポーネントは、適切なグローバルユニキャストIPアドレスを持つ最初に検出したゲートウェイを使用しようとします。 この選択を行う際、ゲートウェイの正確な順序は、オペレーティングシステムやカーネルのバージョンにより異なる場合があります。

Kubernetesコンポーネントはカスタムネットワークインターフェースをオプションとして受け入れないため、カスタム構成を必要とする全てのコンポーネントのインスタンスにカスタムIPアドレスをフラグとして渡す必要があります。

備考:

ホストにデフォルトゲートウェイが存在せず、カスタムIPがKubernetesコンポーネントに渡されない場合、コンポーネントはエラーで終了する可能性があります。

initおよびjoinで作成されたコントロールプレーンに対してAPIサーバーのアドバタイズアドレスを設定するには、--apiserver-advertise-addressフラグを使用します。 このオプションは、可能であればkubeadm APIにおいてInitConfiguration.localAPIEndpointおよびJoinConfiguration.controlPlane.localAPIEndpointとして設定するのが望ましいです。

全てのノード上のkubeletに対して、--node-ipオプションはkubeadmの設定ファイル(InitConfigurationまたはJoinConfiguration)の.nodeRegistration.kubeletExtraArgsにて指定することができます。

デュアルスタックについては、kubeadmによるデュアルスタックのサポートを参照してください。

コントロールプレーンのコンポーネントに割り当てたIPアドレスは、X.509証明書のSubject Alternative Nameフィールドの一部になります。 これらのIPアドレスを変更するには、新しい証明書に署名し、影響を受けるコンポーネントを再起動する必要があります。 これにより、証明書ファイルの変更が反映されます。 詳細は、kubeadmによる証明書管理を参照してください。

警告:

Kubernetesプロジェクトは、このアプローチ(全てのコンポーネントのインスタンスにカスタムIPアドレスを設定すること)を推奨していません。 代わりに、Kubernetesメンテナーはホストネットワークを設定することを推奨しています。 これにより、KubernetesコンポーネントがデフォルトゲートウェイのIPを自動検出し使用できるようになります。 Linuxノード上では、ネットワーク設定にip routeのようなコマンドを使用できます。 また、オペレーティングシステムによってはより高レベルなネットワーク管理ツールが提供される場合もあります。 ノードのデフォルトゲートウェイがパブリックアドレスの場合、ノードやクラスターを保護するためにパケットフィルタリングなどのセキュリティ対策を行う必要があります。

必要なコンテナイメージの準備

このステップは任意で、kubeadm initおよびkubeadm join実行時にregistry.k8s.ioに存在するデフォルトのコンテナイメージをダウンロードしない場合のみ行います。

kubeadmは、ノードにインターネット接続がない状態でクラスターを構築する際に、必要なイメージを事前に取得するのに役立つコマンドがあります。 詳細は、インターネット接続無しでのkubeadmの稼働を参照してください。

kubeadmはカスタムイメージリポジトリから必要なイメージを使用することもできます。 詳細はカスタムイメージの使用を参照してください。

コントロールプレーンノードの初期化

コントロールプレーンノードとは、etcd(クラスターのデータベース)やAPIサーバー(kubectlコマンドラインツールが通信する相手)などのコントロールプレーンのコンポーネントが実行されるマシンです。

  1. (推奨)シングルコントロールプレーンのkubeadmクラスターを高可用性クラスターにアップグレードする予定がある場合、--control-plane-endpointを指定して、すべてのコントロールプレーンノードとエンドポイントを共有する必要があります。 エンドポイントにはDNS名やロードバランサーのIPアドレスが使用できます。
  2. Podネットワークアドオンを選んで、kubeadm initに引数を渡す必要があるかどうか確認してください。 選んだサードパーティのプロバイダーによっては、--pod-network-cidrをプロバイダー固有の値に設定する必要がある場合があります。 詳しくは、Podネットワークアドオンのインストールを参照してください。
  3. (オプション)kubeadmは既知のエンドポイントの一覧を用いて、コンテナランタイムの検出を試みます。 異なるコンテナランタイムを使用する場合やプロビジョニングするノードに2つ以上のランタイムがインストールされている場合、kubeadm--cri-socket引数を指定してください。 詳しくは、ランタイムのインストールを参照してください。

コントロールプレーンノードを初期化するには、次のコマンドを実行します。

kubeadm init <args>

apiserver-advertise-addressとControlPlaneEndpointに関する検討

--apiserver-advertise-addressは、特定のコントロールプレーンノードのAPIサーバーがアドバタイズするアドレスを設定するために使用できます。 一方--control-plane-endpointは、すべてのコントロールプレーンノード共有のエンドポイントを設定するために使用できます。

--control-plane-endpointはIPアドレスと、IPアドレスへマッピングできるDNS名を使用できます。利用可能なソリューションをそうしたマッピングの観点から評価するには、ネットワーク管理者に相談してください。

以下にマッピングの例を示します。

192.168.0.102 cluster-endpoint

ここでは、192.168.0.102がこのノードのIPアドレスであり、cluster-endpointがこのIPアドレスへとマッピングされるカスタムDNS名です。 このように設定することで、--control-plane-endpoint=cluster-endpointkubeadm initに渡せるようになり、kubeadm joinにも同じDNS名を渡せます。 後でcluster-endpointを修正して、高可用性が必要なシナリオでロードバランサーのアドレスを指すようにすることができます。

kubeadmでは、--control-plane-endpointを渡さずに構築したシングルコントロールプレーンのクラスターを高可用性クラスターに切り替えることはサポートされていません。

詳細な情報

kubeadm initの引数のより詳細な情報は、kubeadmリファレンスガイドを参照してください。

kubeadm initを設定ファイルにて設定するには、設定ファイルのドキュメントを参照してください。

コントロールプレーンコンポーネントやetcdサーバーのliveness probeへのオプションのIPv6の割り当てなど、コントロールプレーンのコンポーネントをカスタマイズしたい場合は、カスタムの引数に示されている方法で各コンポーネントに追加の引数を与えてください。

既存のクラスターの再設定を行う場合は、kubeadmクラスターの再設定を参照してください。

kubeadm initを再び実行する場合は、初めにクラスターの破棄を行う必要があります。

もし異なるアーキテクチャのノードをクラスターにjoinさせたい場合は、デプロイしたDaemonSetがそのアーキテクチャ向けのコンテナイメージをサポートしているか確認してください。

初めにkubeadm initは、マシンがKubernetesを実行する準備ができているかを確認するための、一連の事前チェックを行います。 これらの事前チェックは、エラー発生時には警告を表示して終了します。 次に、kubeadm initはクラスターのコントロールプレーンのコンポーネントをダウンロードしてインストールします。 これには数分掛かるかもしれません。 これらが終了すると以下が出力されます。

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  /docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

  kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

kubectlをroot以外のユーザーでも実行できるようにするには、次のコマンドを実行します。これらのコマンドは、kubeadm initの出力の中にも書かれています。

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

rootユーザーの場合は、代わりに次のコマンドを実行します。

export KUBECONFIG=/etc/kubernetes/admin.conf

警告:

kubeadm initによって生成されたkubeconfigファイルのadmin.confは、Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin の証明書を内包しています。 kubeadm:cluster-adminsグループは、ビルトインのClusterRoleであるcluster-adminと紐づいています。 admin.confは誰とも共有しないでください。

kubeadm initは、別のkubeconfigファイルであるsuper-admin.confも生成します。 これは、Subject: O = system:masters, CN = kubernetes-super-adminの証明書を内包しています。 system:mastersは認可のレイヤー(例: RBAC)をバイパスする、緊急用のスーパーユーザーグループです。 super-admin.confは誰とも共有しないでください。 このファイルは安全な場所に退避させることを推奨します。

追加ユーザーへkubeconfigファイルを生成するためにkubeadm kubeconfig userを実行するには、追加ユーザーのためのkubeconfigファイルの生成を参照してください。

kubeadm initが出力したkubeadm joinコマンドをメモしておいてください。クラスターにノードを追加するために、このコマンドが必要です。

トークンは、コントロールプレーンノードと追加ノードの間の相互認証に使用します。ここに含まれるトークンには秘密の情報が含まれます。 このトークンを知っていれば、誰でもクラスターに認証済みノードを追加できてしまうため、取り扱いには注意してください。 kubeadm tokenコマンドを使用すると、これらのトークンの一覧、作成、削除ができます。 詳しくはkubeadmリファレンスガイドを参照してください。

Podネットワークアドオンのインストール

注意:

このセクションには、ネットワークのセットアップとデプロイの順序に関する重要な情報が書かれています。 先に進む前に以下のすべてのアドバイスを熟読してください。

Pod同士が通信できるようにするには、Container Network Interface(CNI)をベースとするPodネットワークアドオンをデプロイしなければなりません。 ネットワークアドオンをインストールする前には、Cluster DNS(CoreDNS)は起動しません。

  • Podネットワークがホストネットワークと決して重ならないように気をつけてください。 もし重なると、様々な問題が起こってしまう可能性があります(ネットワークプラグインが優先するPodネットワークとホストのネットワークの一部が衝突することが分かった場合、適切な代わりのCIDRを考える必要があります。そして、kubeadm initの実行時に--pod-network-cidrにそのCIDRを指定し、ネットワークプラグインのYAMLでは代わりにそのCIDRを使用してください)。
  • デフォルトでは、kubeadmRBAC(role based access control)の使用を強制します。 PodネットワークプラグインがRBACをサポートしており、またそのデプロイに使用するマニフェストもRBACをサポートしていることを確認してください。
  • クラスターでIPv6を使用したい場合、デュアルスタック、IPv6のみのシングルスタックのネットワークのいずれであっても、PodネットワークプラグインがIPv6をサポートしていることを確認してください。 IPv6のサポートは、CNIのv0.6.0で追加されました。

備考:

kubeadmはCNIに依存すべきではないため、CNIプロバイダーの検証は現在e2eテストの範囲外です。 CNIプラグインに関する問題を見つけた場合、kubeadmやKubernetesではなく、そのCNIプラグインの課題管理システムへ問題を報告してください。

CNIを使用するKubernetes Podネットワークを提供する外部のプロジェクトがいくつかあります。一部のプロジェクトでは、ネットワークポリシーもサポートしています。

Kubernetesのネットワークモデルを実装したアドオンの一覧も確認してください。

Kubernetesでサポートされているネットワークアドオンの非網羅的な一覧については、アドオンのインストールのページを参照してください。 Podネットワークアドオンをインストールするには、コントロールプレーンノード上またはkubeconfigクレデンシャルを持っているノード上で、次のコマンドを実行します。

kubectl apply -f <add-on.yaml>

備考:

WindowsをサポートするCNIプラグインは少数です。 詳細とセットアップ手順は、Windowsワーカーノードの追加を参照してください。

インストールできるPodネットワークは、クラスターごとに1つだけです。

Podネットワークがインストールされたら、kubectl get pods --all-namespacesの出力結果でCoreDNS PodがRunning状態であることをチェックすることで、ネットワークが動作していることを確認できます。そして、一度CoreDNS Podが動作すれば、続けてノードを追加できます。

ネットワークやCoreDNSがRunning状態にならない場合は、kubeadmトラブルシューティングガイドをチェックしてください。

管理されたノードラベル

デフォルトでは、kubeadmはNodeRestrictionという、ノード登録時にkubeletが自己適用するラベルを制限するアドミッションコントローラーを有効化します。 このアドミッションコントローラーのドキュメントでは、kubeletの--node-labelsオプションで使用できるラベルについて説明しています。 node-role.kubernetes.io/control-planeは上記のような制限されたラベルであり、ノード作成後に特権クライアントを使用してkubeadmがマニュアルで適用します。 これを手動で行うには、kubeadm管理の/etc/kubernetes/admin.confのような特権kubeconfigを使用していることを確認し、kubectl labelコマンドを使用してください。

コントロールプレーンノードの隔離

デフォルトでは、セキュリティ上の理由により、クラスターはコントロールプレーンノードにPodをスケジューリングしません。 たとえば、開発用のKubernetesシングルマシンのクラスターなどで、Podをコントロールプレーンノードにスケジューリングしたい場合は、次のコマンドを実行します。

kubectl taint nodes --all node-role.kubernetes.io/control-plane-

出力は次のようになります。

node "test-01" untainted
...

このコマンドは、コントロールプレーンノードを含むすべてのノードからnode-role.kubernetes.io/control-plane:NoSchedule taintを削除します。 その結果、スケジューラーはどこにでもPodをスケジューリングできるようになります。

さらに、以下のコマンドを実行することでコントロールプレーンノードからnode.kubernetes.io/exclude-from-external-load-balancersラベルを削除できます。 このラベルは、バックエンドサーバーの一覧からコントロールプレーンノードを除外するものです。

kubectl label nodes --all node.kubernetes.io/exclude-from-external-load-balancers-

コントロールプレーンノードの追加

コントロールプレーンノードの追加によって高可用性kubeadmクラスターを構築する手順は、kubeadmを使用した高可用性クラスターの作成を参照してください。

ワーカーノードの追加

ワーカーノードは、ワークロード(コンテナやPodなど)が実行される場所です。

kubeadm joinコマンドを使用したLinux、Windowsワーカーノードの追加方法は、以下のページを参照してください。

(オプション)コントロールプレーンノード以外のマシンからのクラスター操作

他のコンピューター(例: ラップトップ)上のkubectlがクラスターと通信できるようにするためには、次のようにして管理者のkubeconfigファイルをコントロールプレーンノードから対象のコンピューター上にコピーする必要があります。

scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf get nodes

備考:

上の例では、rootユーザーに対するSSH接続が有効であることを仮定しています。 そうでない場合は、admin.confファイルを他のユーザーからアクセスできるようにコピーした上で、代わりにそのユーザーを使ってscpしてください。

admin.confファイルはユーザーにクラスターに対する スーパーユーザー の権限を与えます。 そのため、このファイルは慎重に使用しなければなりません。 通常のユーザーには、明示的に許可した権限を持つユニークなクレデンシャルを生成することを推奨します。 これには、kubeadm kubeconfig user --client-name <CN>コマンドが使えます。 このコマンドを実行すると、KubeConfigファイルがSTDOUTに出力されるため、ファイルに保存してユーザーに配布します。 その後、kubectl create (cluster)rolebindingコマンドを使って権限を付与します。

(オプション)APIサーバーをlocalhostへプロキシする

クラスターの外部からAPIサーバーに接続したいときは、次のようにkubectl proxyコマンドが使えます。

scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf proxy

これで、ローカルのhttp://localhost:8001/api/v1からAPIサーバーにアクセスできるようになります。

クリーンアップ

テストのためにクラスターに破棄可能なサーバーを使用した場合、サーバーのスイッチをオフにすれば、以降のクリーンアップの作業は必要ありません。 クラスターのローカルの設定を削除するには、kubectl config delete-clusterを実行します。

しかし、よりきれいにクラスターのプロビジョンをもとに戻したい場合は、初めにノードのdrainを行い、ノードが空になっていることを確認した後、ノードの設定を削除する必要があります。

ノードの削除

適切なクレデンシャルを使用してコントロールプレーンノードに指示を出します。次のコマンドを実行してください。

kubectl drain <node name> --delete-emptydir-data --force --ignore-daemonsets

ノードを削除する前に、kubeadmによってインストールされた状態をリセットします。

kubeadm reset

リセットプロセスでは、iptablesのルールやIPVS tablesのリセットやクリーンアップは行われません。 iptablesをリセットしたい場合は、次のように手動でコマンドを実行する必要があります。

iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

IPVS tablesをリセットしたい場合は、次のコマンドを実行する必要があります。

ipvsadm -C

ノードを削除します。

kubectl delete node <node name>

クラスターのセットアップを最初から始めたいときは、kubeadm initkubeadm joinを適切な引数を付けて実行すればいいだけです。

コントロールプレーンのクリーンアップ

コントロールホスト上でkubeadm resetを実行すると、ベストエフォートでのクリーンアップが実行できます。

このサブコマンドとオプションに関するより詳しい情報は、kubeadm resetリファレンスドキュメントを読んでください。

バージョンスキューポリシー

kubeadmは、kubeadmが管理するコンポーネントに対してバージョンの差異を許容しますが、kubeadmのバージョンをコントロールプレーンのコンポーネント、kube-proxy、kubeletと一致させることを推奨します。

Kubernetesのバージョンに対するkubeadmのバージョンの差異

kubeadmは、kubeadmと同じバージョンか、1つ前のバージョンのKubernetesコンポーネントで使用できます。 Kubernetesのバージョンはkubeadm init--kubernetes-version、もしくは--configを使用する場合のClusterConfiguration.kubernetesVersionフィールドで指定できます。 このオプションはkube-apiserver、kube-controller-manager、kube-scheduler、kube-proxyのバージョンを制御します。

例:

  • kubeadmのバージョン: 1.36
  • kubernetesVersionは、1.36または1.35でなければならない

kubeletに対するkubeadmのバージョンの差異

Kubernetesのバージョンと同様に、kubeadmは、kubeadmと同じバージョン、もしくは3つ前までのバージョンをkubeletに使用できます。

例:

  • kubeadmのバージョン: 1.36
  • ホスト上のkubeletのバージョンは、1.36、1.35、1.34、もしくは1.33でなければならない

kubeadmに対するkubeadmのバージョンの差異

kubeadmによって管理されている既存のノードまたはクラスター全体を、kubeadmコマンドが操作するには一定の制限が存在します。

新たなノードをクラスターに参加させる場合、kubeadm joinを実行するkubeadmのバイナリは、kubeadm initによるクラスター構築、もしくはkubeadm upgradeによるノードのアップグレードのいずれかに使用されたkubeadmの最新バージョンと一致している必要があります。 同様の制限はkubeadm upgradeを除く他のkubeadmのコマンドにも適用されます。

kubeadm joinの例:

  • kubeadm initによるクラスター構築で使用したkubeadmのバージョン: 1.36
  • 参加するノードは、1.36のバージョンのkubeadmバイナリを使用しなければならない

アップグレードするノードでは、そのノードの管理に使用しているkubeadmのバージョンと同じマイナーバージョン、もしくはマイナーバージョンが1つ新しいkubeadmを使用する必要があります。

kubeadm upgradeの例:

  • クラスター構築またはノードのアップグレードに使用されたkubeadmのバージョン: 1.35
  • ノードのアップグレードで使用するkubeadmのバージョンは、1.35または1.36でなければならない

異なるKubernetesコンポーネント間のバージョン差異についてさらに学ぶには、バージョンスキューポリシーを参照してください。

制限事項

クラスターの弾力性

ここで作られたクラスターは、1つのコントロールプレーンノードと、その上で動作する1つのetcdデータベースしか持ちません。 つまり、コントロールプレーンノードが故障した場合、クラスターのデータは失われ、クラスターを最初から作り直す必要がある可能性があります。

対処方法:

プラットフォームの互換性

kubeadmのdeb/rpmパッケージおよびバイナリは、multi-platform proposalに従い、amd64、arm(32ビット)、arm64、ppc64le、およびs390x向けにビルドされています。

マルチプラットフォームのコントロールプレーンおよびアドオン用のコンテナイメージも、v1.12からサポートされています。

すべてのプラットフォーム向けのソリューションを提供しているネットワークプロバイダーは一部のみです。それぞれのプロバイダーが選択したプラットフォームをサポートしているかどうかを確認するには、前述のネットワークプロバイダーのリストを参照してください。

トラブルシューティング

kubeadmに関する問題が起きたときは、トラブルシューティングドキュメントを確認してください。

次の項目

フィードバック

2.2.1.4 - kubeadmを使ったコントロールプレーンの設定のカスタマイズ

FEATURE STATE: Kubernetes 1.12 [stable]

kubeadmのClusterConfigurationオブジェクトはAPIServer、ControllerManager、およびSchedulerのようなコントロールプレーンの構成要素に渡されたデフォルトのフラグを上書きすることができる extraArgsの項目があります。 その構成要素は次の項目で定義されています。

  • apiServer
  • controllerManager
  • scheduler

extraArgs の項目は キー: 値 のペアです。コントロールプレーンの構成要素のフラグを上書きするには:

  1. 設定内容に適切な項目を追加
  2. フラグを追加して項目を上書き
  3. --config <任意の設定YAMLファイル>kubeadm initを実行

各設定項目のより詳細な情報はAPIリファレンスのページを参照してください。

備考:

kubeadm config print init-defaultsを実行し、選択したファイルに出力を保存することで、デフォルト値でClusterConfigurationオブジェクトを生成できます。

APIServerフラグ

詳細はkube-apiserverのリファレンスドキュメントを参照してください。

使用例:

apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
apiServer:
  extraArgs:
    advertise-address: 192.168.0.103
    anonymous-auth: "false"
    enable-admission-plugins: AlwaysPullImages,DefaultStorageClass
    audit-log-path: /home/johndoe/audit.log

ControllerManagerフラグ

詳細はkube-controller-managerのリファレンスドキュメントを参照してください。

使用例:

apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
controllerManager:
  extraArgs:
    cluster-signing-key-file: /home/johndoe/keys/ca.key
    bind-address: 0.0.0.0
    deployment-controller-sync-period: "50"

Schedulerフラグ

詳細はkube-schedulerのリファレンスドキュメントを参照してください。

使用例:

apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
scheduler:
  extraArgs:
    bind-address: 0.0.0.0
    config: /home/johndoe/schedconfig.yaml
    kubeconfig: /home/johndoe/kubeconfig.yaml

2.2.1.5 - 高可用性トポロジーのためのオプション

このページでは、高可用性(HA)Kubernetesクラスターのトポロジーを設定するための2つのオプションについて説明します。

HAクラスターは次の方法で設定できます。

  • 積層コントロールプレーンノードを使用する方法。こちらの場合、etcdノードはコントロールプレーンノードと同じ場所で動作します。
  • 外部のetcdノードを使用する方法。こちらの場合、etcdがコントロールプレーンとは分離されたノードで動作します。

HAクラスターをセットアップする前に、各トポロジーの利点と欠点について注意深く考慮する必要があります。

備考:

kubeadmは、etcdクラスターを静的にブートストラップします。 詳細については、etcdクラスタリングガイドをご覧ください。

積層etcdトポロジー

積層HAクラスターは、コントロールプレーンのコンポーネントを実行する、kubeadmで管理されたノードで構成されるクラスターの上に、etcdにより提供される分散データストレージクラスターがあるようなトポロジーです。

各コントロールプレーンノードは、kube-apiserverkube-scheduler、およびkube-controller-managerを実行します。kube-apiserver はロードバランサーを用いてワーカーノードに公開されます。

各コントロールプレーンノードはローカルのetcdメンバーを作り、このetcdメンバーはそのノードのkube-apiserverとだけ通信します。ローカルのkube-controller-managerkube-schedulerのインスタンスも同様です。

このトポロジーは、同じノード上のコントロールプレーンとetcdのメンバーを結合します。外部のetcdノードを使用するクラスターよりはセットアップがシンプルで、レプリケーションの管理もシンプルです。

しかし、積層クラスターには、結合による故障のリスクがあります。1つのノードがダウンすると、etcdメンバーとコントロールプレーンのインスタンスの両方が失われ、冗長性が損なわれます。より多くのコントロールプレーンノードを追加することで、このリスクは緩和できます。

そのため、HAクラスターのためには、最低でも3台の積層コントロールプレーンノードを実行しなければなりません。

これがkubeadmのデフォルトのトポロジーです。kubeadm initkubeadm join --control-placeを実行すると、ローカルのetcdメンバーがコントロールプレーンノード上に自動的に作成されます。

積層etcdトポロジー

外部のetcdトポロジー

外部のetcdを持つHAクラスターは、コントロールプレーンコンポーネントを実行するノードで構成されるクラスターの外部に、etcdにより提供される分散データストレージクラスターがあるようなトポロジーです。

積層etcdトポロジーと同様に、外部のetcdトポロジーにおける各コントロールプレーンノードは、kube-apiserverkube-scheduler、およびkube-controller-managerのインスタンスを実行します。そして、kube-apiserverは、ロードバランサーを使用してワーカーノードに公開されます。しかし、etcdメンバーは異なるホスト上で動作しており、各etcdホストは各コントロールプレーンノードのkube-api-serverと通信します。

このトポロジーは、コントロールプレーンとetcdメンバーを疎結合にします。そのため、コントロールプレーンインスタンスまたはetcdメンバーを失うことによる影響は少なく、積層HAトポロジーほどクラスターの冗長性に影響しないHAセットアップが実現します。

しかし、このトポロジーでは積層HAトポロジーの2倍の数のホストを必要とします。このトポロジーのHAクラスターのためには、最低でもコントロールプレーンのために3台のホストが、etcdノードのために3台のホストがそれぞれ必要です。

外部のetcdトポロジー

次の項目

2.2.1.6 - kubeadmを使用した高可用性クラスターの作成

このページでは、kubeadmを使用して、高可用性クラスターを作成する、2つの異なるアプローチを説明します:

  • 積層コントロールプレーンノードを使う方法。こちらのアプローチは、必要なインフラストラクチャーが少ないです。etcdのメンバーと、コントロールプレーンノードは同じ場所に置かれます。
  • 外部のetcdクラスターを使う方法。こちらのアプローチには、より多くのインフラストラクチャーが必要です。コントロールプレーンノードと、etcdのメンバーは分離されます。

先へ進む前に、どちらのアプローチがアプリケーションの要件と、環境に適合するか、慎重に検討してください。こちらの比較が、それぞれの利点/欠点について概説しています。

高可用性クラスターの作成で問題が発生した場合は、kueadmのissue trackerでフィードバックを提供してください。

高可用性クラスターのアップグレードも参照してください。

注意:

このページはクラウド上でクラスターを構築することには対応していません。ここで説明されているどちらのアプローチも、クラウド上で、LoadBalancerタイプのServiceオブジェクトや、動的なPersistentVolumeを利用して動かすことはできません。

始める前に

どちらの方法でも、以下のインフラストラクチャーが必要です:

  • master用に、kubeadmの最小要件を満たす3台のマシン
  • worker用に、kubeadmの最小要件を満たす3台のマシン
  • クラスター内のすべてのマシン間がフルにネットワーク接続可能であること(パブリック、もしくはプライベートネットワーク)
  • すべてのマシンにおいて、sudo権限
  • あるデバイスから、システム内のすべてのノードに対しSSH接続できること
  • kubeadmkubeletがすべてのマシンにインストールされていること。 kubectlは任意です。

外部etcdクラスターには、以下も必要です:

  • etcdメンバー用に、追加で3台のマシン

両手順における最初のステップ

kube-apiserver用にロードバランサーを作成

備考:

ロードバランサーには多くの設定項目があります。以下の例は、一選択肢に過ぎません。あなたのクラスター要件には、異なった設定が必要かもしれません。
  1. DNSで解決される名前で、kube-apiserver用ロードバランサーを作成する。

    • クラウド環境では、コントロールプレーンノードをTCPフォワーディングロードバランサーの後ろに置かなければなりません。このロードバランサーはターゲットリストに含まれる、すべての健全なコントロールプレーンノードにトラフィックを分配します。apiserverへのヘルスチェックはkube-apiserverがリッスンするポート(デフォルト値: :6443)に対する、TCPチェックです。

    • クラウド環境では、IPアドレスを直接使うことは推奨されません。

    • ロードバランサーは、apiserverポートで、全てのコントロールプレーンノードと通信できなければなりません。また、リスニングポートに対する流入トラフィックも許可されていなければなりません。

    • ロードバランサーのアドレスは、常にkubeadmのControlPlaneEndpointのアドレスと一致することを確認してください。

    • 詳細はOptions for Software Load Balancingをご覧ください。

  2. ロードバランサーに、最初のコントロールプレーンノードを追加し、接続をテストする:

    nc -v LOAD_BALANCER_IP PORT
    
    • apiserverはまだ動いていないので、接続の拒否は想定通りです。しかし、タイムアウトしたのであれば、ロードバランサーはコントロールプレーンノードと通信できなかったことを意味します。もし、タイムアウトが起きたら、コントロールプレーンノードと通信できるように、ロードバランサーを再設定してください。
  3. 残りのコントロールプレーンノードを、ロードバランサーのターゲットグループに追加します。

積層コントロールプレーンとetcdノード

最初のコントロールプレーンノードの手順

  1. 最初のコントロールプレーンノードを初期化します:

    sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
    
    • --kubernetes-versionフラグで使用するKubernetesのバージョンを設定できます。kubeadm、kubelet、kubectl、Kubernetesのバージョンを一致させることが推奨されます。
    • --control-plane-endpointフラグは、ロードバランサーのIPアドレスまたはDNS名と、ポートが設定される必要があります。
    • --upload-certsフラグは全てのコントロールプレーンノードで共有する必要がある証明書をクラスターにアップロードするために使用されます。代わりに、コントロールプレーンノード間で手動あるいは自動化ツールを使用して証明書をコピーしたい場合は、このフラグを削除し、以下の証明書の手動配布のセクションを参照してください。

    備考:

    kubeadm init--configフラグと--certificate-keyフラグは混在させることはできないため、kubeadm configurationを使用する場合はcertificateKeyフィールドを適切な場所に追加する必要があります(InitConfigurationJoinConfiguration: controlPlaneの配下)。

    備考:

    いくつかのCNIネットワークプラグインはPodのIPのCIDRの指定など追加の設定を必要としますが、必要としないプラグインもあります。CNIネットワークドキュメントを参照してください。PodにCIDRを設定するには、ClusterConfigurationnetworkingオブジェクトにpodSubnet: 192.168.0.0/16フィールドを設定してください。
    • このような出力がされます:
    ...
    You can now join any number of control-plane node by running the following command on each as a root:
        kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
    
    Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
    As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward.
    
    Then you can join any number of worker nodes by running the following on each as root:
        kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
    
    • この出力をテキストファイルにコピーします。あとで、他のコントロールプレーンノードとワーカーノードをクラスターに参加させる際に必要です。

    • --upload-certsフラグをkubeadm initで使用すると、プライマリコントロールプレーンの証明書が暗号化されて、kubeadm-certs Secretにアップロードされます。

    • 証明書を再アップロードして新しい復号キーを生成するには、すでにクラスターに参加しているコントロールプレーンノードで次のコマンドを使用します:

    sudo kubeadm init phase upload-certs --upload-certs
    
    • また、後でjoinで使用できるように、init中にカスタムした--certificate-keyを指定することもできます。このようなキーを生成するには、次のコマンドを使用します:
    kubeadm alpha certs certificate-key
    

    備考:

    `kubeadm-certs`のSecretと復号キーは2時間で期限切れとなります。
    

    注意:

    コマンド出力に記載されているように、証明書キーはクラスターの機密データへのアクセスを提供します。秘密にしてください!
    
  2. 使用するCNIプラグインを適用します:
    こちらの手順に従いCNIプロバイダーをインストールします。該当する場合は、kubeadmの設定で指定されたPodのCIDRに対応していることを確認してください。

    Weave Netを使用する場合の例:

    kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
    
  3. 以下のコマンドを入力し、コンポーネントのPodが起動するのを確認します:

    kubectl get pod -n kube-system -w
    

残りのコントロールプレーンノードの手順

備考:

kubeadmバージョン1.15以降、複数のコントロールプレーンノードを並行してクラスターに参加させることができます。 このバージョンの前は、最初のノードの初期化が完了した後でのみ、新しいコントロールプレーンノードを順番にクラスターに参加させる必要があります。

追加のコントロールプレーンノード毎に、以下の手順を行います。

  1. kubeadm initを最初のノードで実行した際に取得したjoinコマンドを使って、新しく追加するコントロールプレーンノードでkubeadm joinを開始します。このようなコマンドになるはずです:

    sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
    
    • --control-planeフラグによって、kubeadm joinの実行は新しいコントロールプレーンを作成します。
    • -certificate-key ...を指定したキーを使って、クラスターのkubeadm-certs Secretからダウンロードされたコントロールプレーンの証明書が復号されます。

外部のetcdノード

外部のetcdノードを使ったクラスターの設定は、積層etcdの場合と似ていますが、最初にetcdを設定し、kubeadmの設定ファイルにetcdの情報を渡す必要があります。

etcdクラスターの構築

  1. こちらの手順にしたがって、etcdクラスターを構築してください。

  2. こちらの手順にしたがって、SSHを構築してください。

  3. 以下のファイルをクラスター内の任意のetcdノードから最初のコントロールプレーンノードにコピーしてください:

    export CONTROL_PLANE="ubuntu@10.0.0.7"
    scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}":
    scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}":
    scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":
    
    • CONTROL_PLANEの値を、最初のコントロールプレーンノードのuser@hostで置き換えます。

最初のコントロールプレーンノードの構築

  1. 以下の内容で、kubeadm-config.yamlという名前の設定ファイルを作成します:

    apiVersion: kubeadm.k8s.io/v1beta2
    kind: ClusterConfiguration
    kubernetesVersion: stable
    controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT"
    etcd:
        external:
            endpoints:
            - https://ETCD_0_IP:2379
            - https://ETCD_1_IP:2379
            - https://ETCD_2_IP:2379
            caFile: /etc/kubernetes/pki/etcd/ca.crt
            certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt
            keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
    

    備考:

    ここで、積層etcdと外部etcdの違いは、外部etcdの構成では`etcd`の`external`オブジェクトにetcdのエンドポイントが記述された設定ファイルが必要です。積層etcdトポロジーの場合、これは自動で管理されます。
    
    • テンプレート内の以下の変数を、クラスターに合わせて適切な値に置き換えます:

      • LOAD_BALANCER_DNS
      • LOAD_BALANCER_PORT
      • ETCD_0_IP
      • ETCD_1_IP
      • ETCD_2_IP

以下の手順は、積層etcdの構築と同様です。

  1. sudo kubeadm init --config kubeadm-config.yaml --upload-certsをこのノードで実行します。

  2. 表示されたjoinコマンドを、あとで使うためにテキストファイルに書き込みます。

  3. 使用するCNIプラグインを適用します。以下はWeave CNIの場合です:

    kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
    

残りのコントロールプレーンノードの手順

手順は、積層etcd構築の場合と同じです:

  • 最初のコントロールプレーンノードが完全に初期化されているのを確認します。
  • テキストファイルに保存したjoinコマンドを使って、それぞれのコントロールプレーンノードをクラスターへ参加させます。コントロールプレーンノードは1台ずつクラスターへ参加させるのを推奨します。
  • --certificate-keyで指定する復号キーは、デフォルトで2時間で期限切れになることを忘れないでください。

コントロールプレーン起動後の共通タスク

workerのインストール

kubeadm initコマンドから返されたコマンドを利用して、workerノードをクラスターに参加させることが可能です。

sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866

証明書の手動配布

--upload-certsフラグを指定してkubeadm initを実行しない場合、プライマリコントロールプレーンノードから他のコントロールプレーンノードへ証明書を手動でコピーする必要があります。

コピーを行うには多くの方法があります。次の例ではsshscpを使用しています。

1台のマシンから全てのノードをコントロールしたいのであれば、SSHが必要です。

  1. システム内の全ての他のノードにアクセスできるメインデバイスで、ssh-agentを有効にします

    eval $(ssh-agent)
    
  2. SSHの秘密鍵を、セッションに追加します:

    ssh-add ~/.ssh/path_to_private_key
    
  3. 正常に接続できることを確認するために、ノード間でSSHします。

    • ノードにSSHする際は、必ず-Aフラグをつけます:

      ssh -A 10.0.0.7
      
    • ノードでsudoするときは、SSHフォワーディングが動くように、環境変数を引き継ぎます:

      sudo -E -s
      
  4. 全てのノードでSSHを設定したら、kubeadm initを実行した後、最初のコントロールノードプレーンノードで次のスクリプトを実行します。このスクリプトは、最初のコントロールプレーンノードから残りのコントロールプレーンノードへ証明書ファイルをコピーします:

    次の例の、CONTROL_PLANE_IPSを他のコントロールプレーンノードのIPアドレスに置き換えます。

    USER=ubuntu # 環境に合わせる
    CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8"
    for host in ${CONTROL_PLANE_IPS}; do
        scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
        scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
        scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
        scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
        scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
        scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
        scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
        # 外部のetcdノード使用時はこちらのコマンドを実行
        scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
    done
    

    注意:

    上のリストにある証明書だけをコピーしてください。kubeadmが、参加するコントロールプレーンノード用に、残りの証明書と必要なSANの生成を行います。間違って全ての証明書をコピーしてしまったら、必要なSANがないため、追加ノードの作成は失敗するかもしれません。
    
  5. 次に、クラスターに参加させる残りの各コントロールプレーンノードでkubeadm joinを実行する前に次のスクリプトを実行する必要があります。このスクリプトは、前の手順でコピーした証明書をホームディレクトリから/etc/kubernetes/pkiへ移動します:

    USER=ubuntu # 環境に合わせる
    mkdir -p /etc/kubernetes/pki/etcd
    mv /home/${USER}/ca.crt /etc/kubernetes/pki/
    mv /home/${USER}/ca.key /etc/kubernetes/pki/
    mv /home/${USER}/sa.pub /etc/kubernetes/pki/
    mv /home/${USER}/sa.key /etc/kubernetes/pki/
    mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
    mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/
    mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
    # 外部のetcdノード使用時はこちらのコマンドを実行
    mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
    

2.2.1.7 - kubeadmを使用した高可用性etcdクラスターの作成

kubeadmはデフォルトで、各コントロールプレーンノード上でローカルのetcdインスタンスを実行します。 また、コントロールプレーンノードとは別のホスト上にetcdインスタンスを構築し、外部etcdクラスターとして扱うこともできます。 これら2つのアプローチの違いについては高可用性トポロジーのためのオプションを参照してください。

このタスクでは、kubeadmによるKubernetesクラスター作成時に使用できる、3メンバー構成の高可用性外部etcdクラスターを構築する手順を説明します。

始める前に

  • 3台のホストが、TCPポート2379および2380を介して相互に通信できる必要があります。このドキュメントでは、これらがデフォルトポートであることを前提としていますが、kubeadmの設定ファイルで変更することもできます。
  • 各ホストには、systemdおよびbash互換シェルがインストールされている必要があります。
  • 各ホストに、コンテナランタイム、kubelet、およびkubeadmをインストールしておく必要があります
  • 各ホストはKubernetesコンテナイメージレジストリ(registry.k8s.io)にアクセスできるか、kubeadm config images list/pullを使用して必要なetcdイメージを一覧表示または取得できる必要があります。このガイドでは、kubeletによって管理されるStatic Podとしてetcdインスタンスを構築します。
  • ホスト間でファイルをコピーするための仕組みが必要です。たとえば、sshscpを利用できます。

クラスターの構築

一般的な方法では、1つのノードですべての証明書を生成し、他のノードには必要なファイルだけを配布します。

備考:

kubeadmには、以下で説明する証明書の生成に必要な暗号処理機能がすべて備わっています。この例では、他の暗号化ツールは必要ありません。

備考:

以下の例ではIPv4アドレスを使用していますが、kubeadm、kubelet、etcdでIPv6アドレスを使用するように設定することもできます。 デュアルスタックはKubernetesの一部の機能ではサポートされていますが、etcdではサポートされていません。 Kubernetesのデュアルスタックのサポートについて詳しくは、kubeadmによるデュアルスタックのサポートを参照してください。
  1. etcdのサービスマネージャーとしてkubeletを設定します。

    備考:

    etcdを実行するすべてのホストでこの設定を行う必要があります。
    etcdを先に作成するため、kubeadmが提供するkubeletユニットファイルよりも優先順位の高い新しいユニットファイルを作成し、サービスの優先順位を上書きする必要があります。

    cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf
    # "systemd"をコンテナランタイムのcgroupドライバーに置き換えます。kubeletのデフォルト値は"cgroupfs"です。
    # 別のコンテナランタイムを使用する場合は、必要に応じて"containerRuntimeEndpoint"の値を置き換えます。
    #
    apiVersion: kubelet.config.k8s.io/v1beta1
    kind: KubeletConfiguration
    authentication:
      anonymous:
        enabled: false
      webhook:
        enabled: false
    authorization:
      mode: AlwaysAllow
    cgroupDriver: systemd
    address: 127.0.0.1
    containerRuntimeEndpoint: unix:///var/run/containerd/containerd.sock
    staticPodPath: /etc/kubernetes/manifests
    EOF
    
    cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
    [Service]
    ExecStart=
    ExecStart=/usr/bin/kubelet --config=/etc/systemd/system/kubelet.service.d/kubelet.conf
    Restart=always
    EOF
    
    systemctl daemon-reload
    systemctl restart kubelet
    

    kubeletのステータスを確認し、実行中であることを確かめます。

    systemctl status kubelet
    
  2. kubeadmの設定ファイルを作成します。

    以下のスクリプトを使用して、etcdメンバーを実行する各ホスト用にkubeadm設定ファイルを1つずつ生成します。

    # HOST0、HOST1、HOST2を各ホストのIPアドレスに変更します
    export HOST0=10.0.0.6
    export HOST1=10.0.0.7
    export HOST2=10.0.0.8
    
    # NAME0、NAME1、NAME2を各ホストのホスト名に変更します
    export NAME0="infra0"
    export NAME1="infra1"
    export NAME2="infra2"
    
    # 他のホストに配置するファイルを格納する一時ディレクトリを作成します
    mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/
    
    HOSTS=(${HOST0} ${HOST1} ${HOST2})
    NAMES=(${NAME0} ${NAME1} ${NAME2})
    
    for i in "${!HOSTS[@]}"; do
    HOST=${HOSTS[$i]}
    NAME=${NAMES[$i]}
    cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
    ---
    apiVersion: "kubeadm.k8s.io/v1beta4"
    kind: InitConfiguration
    nodeRegistration:
        name: ${NAME}
    localAPIEndpoint:
        advertiseAddress: ${HOST}
    ---
    apiVersion: "kubeadm.k8s.io/v1beta4"
    kind: ClusterConfiguration
    etcd:
        local:
            serverCertSANs:
            - "${HOST}"
            peerCertSANs:
            - "${HOST}"
            extraArgs:
            - name: initial-cluster
              value: ${NAMES[0]}=https://${HOSTS[0]}:2380,${NAMES[1]}=https://${HOSTS[1]}:2380,${NAMES[2]}=https://${HOSTS[2]}:2380
            - name: initial-cluster-state
              value: new
            - name: name
              value: ${NAME}
            - name: listen-peer-urls
              value: https://${HOST}:2380
            - name: listen-client-urls
              value: https://${HOST}:2379
            - name: advertise-client-urls
              value: https://${HOST}:2379
            - name: initial-advertise-peer-urls
              value: https://${HOST}:2380
    EOF
    done
    
  3. 認証局を生成します。

    すでにCAがある場合は、そのCAのcrtファイルとkeyファイルを/etc/kubernetes/pki/etcd/ca.crt/etc/kubernetes/pki/etcd/ca.keyにコピーするだけです。 これらのファイルをコピーしたら、次の手順「各メンバーの証明書を作成します」に進みます。

    まだCAがない場合は、kubeadmの設定ファイルを生成した$HOST0上で次のコマンドを実行します。

    kubeadm init phase certs etcd-ca
    

    これにより、次の2つのファイルが作成されます。

    • /etc/kubernetes/pki/etcd/ca.crt
    • /etc/kubernetes/pki/etcd/ca.key
  4. 各メンバーの証明書を作成します。

    kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
    kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
    cp -R /etc/kubernetes/pki /tmp/${HOST2}/
    # 再利用できない証明書を削除します
    find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
    
    kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
    kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
    cp -R /etc/kubernetes/pki /tmp/${HOST1}/
    find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
    
    kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml
    kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
    kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
    # HOST0用の証明書のため、移動する必要はありません
    
    # このホストの外部にコピーすべきでない証明書を削除します
    find /tmp/${HOST2} -name ca.key -type f -delete
    find /tmp/${HOST1} -name ca.key -type f -delete
    
  5. 証明書とkubeadmの設定ファイルをコピーします。

    生成した証明書を、それぞれのホストへ移動します。

    USER=ubuntu
    HOST=${HOST1}
    scp -r /tmp/${HOST}/* ${USER}@${HOST}:
    ssh ${USER}@${HOST}
    USER@HOST $ sudo -Es
    root@HOST $ chown -R root:root pki
    root@HOST $ mv pki /etc/kubernetes/
    
  6. 必要なファイルがすべて存在することを確認します。

    $HOST0上に必要なファイルの完全な一覧は次のとおりです。

    /tmp/${HOST0}
    └── kubeadmcfg.yaml
    ---
    /etc/kubernetes/pki
    ├── apiserver-etcd-client.crt
    ├── apiserver-etcd-client.key
    └── etcd
        ├── ca.crt
        ├── ca.key
        ├── healthcheck-client.crt
        ├── healthcheck-client.key
        ├── peer.crt
        ├── peer.key
        ├── server.crt
        └── server.key
    

    $HOST1上では次のとおりです。

    $HOME
    └── kubeadmcfg.yaml
    ---
    /etc/kubernetes/pki
    ├── apiserver-etcd-client.crt
    ├── apiserver-etcd-client.key
    └── etcd
        ├── ca.crt
        ├── healthcheck-client.crt
        ├── healthcheck-client.key
        ├── peer.crt
        ├── peer.key
        ├── server.crt
        └── server.key
    

    $HOST2上では次のとおりです。

    $HOME
    └── kubeadmcfg.yaml
    ---
    /etc/kubernetes/pki
    ├── apiserver-etcd-client.crt
    ├── apiserver-etcd-client.key
    └── etcd
        ├── ca.crt
        ├── healthcheck-client.crt
        ├── healthcheck-client.key
        ├── peer.crt
        ├── peer.key
        ├── server.crt
        └── server.key
    
  7. Static Podマニフェストを作成します。

    証明書と設定ファイルの準備が整ったため、マニフェストを作成します。 各ホストでkubeadmコマンドを実行し、etcd用のStatic Podマニフェストを生成します。

    root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
    root@HOST1 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
    root@HOST2 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
    
  8. オプション: クラスターの健全性を確認します。

    etcdctlを利用できない場合は、コンテナイメージ内でこのツールを実行できます。 その場合はKubernetes経由ではなく、crictl runなどのツールを使用してコンテナランタイムから直接実行します。

    ETCDCTL_API=3 etcdctl \
    --cert /etc/kubernetes/pki/etcd/peer.crt \
    --key /etc/kubernetes/pki/etcd/peer.key \
    --cacert /etc/kubernetes/pki/etcd/ca.crt \
    --endpoints https://${HOST0}:2379 endpoint health
    ...
    https://[HOST0 IP]:2379 is healthy: successfully committed proposal: took = 16.283339ms
    https://[HOST1 IP]:2379 is healthy: successfully committed proposal: took = 19.44402ms
    https://[HOST2 IP]:2379 is healthy: successfully committed proposal: took = 35.926451ms
    
    • ${HOST0}を、確認対象ホストのIPアドレスに設定します。

次の項目

稼働中の3つのメンバーで構成されるetcdクラスターを用意できたら、kubeadmで外部etcdを使用する方法による高可用性コントロールプレーンの構築に進むことができます。

2.2.1.8 - kubeadmを使用したクラスター内の各kubeletの設定

FEATURE STATE: Kubernetes 1.11 [stable]

kubeadm CLIツールのライフサイクルは、Kubernetesクラスター内の各ノード上で稼働するデーモンであるkubeletから分離しています。kubeadm CLIツールはKubernetesを初期化またはアップグレードする際にユーザーによって実行されます。一方で、kubeletは常にバックグラウンドで稼働しています。

kubeletはデーモンのため、何らかのinitシステムやサービスマネージャーで管理する必要があります。DEBパッケージやRPMパッケージからkubeletをインストールすると、systemdはkubeletを管理するように設定されます。代わりに別のサービスマネージャーを使用することもできますが、手動で設定する必要があります。

いくつかのkubeletの設定は、クラスターに含まれる全てのkubeletで同一である必要があります。一方で、特定のマシンの異なる特性(OS、ストレージ、ネットワークなど)に対応するために、kubeletごとに設定が必要なものもあります。手動で設定を管理することも可能ですが、kubeadmは一元的な設定管理のためのKubeletConfigurationAPIを提供しています。

Kubeletの設定パターン

以下のセクションでは、kubeadmを使用したkubeletの設定パターンについて説明します。これは手動で各Nodeの設定を管理するよりも簡易に行うことができます。

各kubeletにクラスターレベルの設定を配布

kubeadm initおよびkubeadm joinコマンドを使用すると、kubeletにデフォルト値を設定することができます。興味深い例として、異なるCRIランタイムを使用したり、Serviceが使用するデフォルトのサブネットを設定したりすることができます。

Serviceが使用するデフォルトのサブネットとして10.96.0.0/12を設定する必要がある場合は、--service-cidrパラメーターを渡します。

kubeadm init --service-cidr 10.96.0.0/12

これによってServiceの仮想IPはこのサブネットから割り当てられるようになりました。また、--cluster-dnsフラグを使用し、kubeletが用いるDNSアドレスを設定する必要もあります。この設定はクラスター内の全てのマネージャーとNode上で同一である必要があります。kubeletは、kubeletのComponentConfigと呼ばれる、バージョン管理と構造化されたAPIオブジェクトを提供します。これはkubelet内のほとんどのパラメーターを設定し、その設定をクラスター内で稼働中の各kubeletへ適用することを可能にします。以下の例のように、キャメルケースのキーに値のリストとしてクラスターDNS IPアドレスなどのフラグを指定することができます。

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
clusterDNS:
- 10.96.0.10

ComponentConfigの詳細については、このセクションをご覧ください

インスタンス固有の設定内容を適用

いくつかのホストでは、ハードウェア、オペレーティングシステム、ネットワーク、その他ホスト固有のパラメーターの違いのため、特定のkubeletの設定を必要とします。以下にいくつかの例を示します。

  • DNS解決ファイルへのパスは--resolv-confフラグで指定することができますが、オペレーティングシステムやsystemd-resolvedを使用するかどうかによって異なる場合があります。このパスに誤りがある場合、そのNode上でのDNS解決は失敗します。
  • クラウドプロバイダーを使用していない場合、Node APIオブジェクト.metadata.nameはデフォルトでマシンのホスト名に設定されます。異なるNode名を指定する必要がある場合には、--hostname-overrideフラグによってこの挙動を書き換えることができます。
  • 現在のところ、kubletはCRIランタイムが使用するcgroupドライバーを自動で検知することができませんが、kubeletの稼働を保証するためには、--cgroup-driverの値はCRIランタイムが使用するcgroupドライバーに一致していなければなりません。
  • クラスターが使用するCRIランタイムによっては、異なるフラグを指定する必要があるかもしれません。例えば、Dockerを使用している場合には、--network-plugin=cniのようなフラグを指定する必要があります。外部のランタイムを使用している場合には、--container-runtime=remoteと指定し、--container-runtime-endpoint=<path>のようにCRIエンドポイントを指定する必要があります。

これらのフラグは、systemdなどのサービスマネージャー内のkubeletの設定によって指定することができます。

kubeadmを使用したkubeletの設定

kubeadm ... --config some-config-file.yamlのように、カスタムのKubeletConfigurationAPIオブジェクトを設定ファイルを介して渡すことで、kubeadmによって起動されるkubeletに設定を反映することができます。

kubeadm config print init-defaults --component-configs KubeletConfigurationを実行することによって、この構造体の全てのデフォルト値を確認することができます。

また、各フィールドの詳細については、kubelet ComponentConfigに関するAPIリファレンスを参照してください。

kubeadm init実行時の流れ

kubeadm initを実行した場合、kubeletの設定は/var/lib/kubelet/config.yamlに格納され、クラスターのConfigMapにもアップロードされます。ConfigMapはkubelet-config-1.Xという名前で、Xは初期化するKubernetesのマイナーバージョンを表します。またこの設定ファイルは、クラスター内の全てのkubeletのために、クラスター全体設定の基準と共に/etc/kubernetes/kubelet.confにも書き込まれます。この設定ファイルは、kubeletがAPIサーバと通信するためのクライアント証明書を指し示します。これは、各kubeletにクラスターレベルの設定を配布することの必要性を示しています。

二つ目のパターンである、インスタンス固有の設定内容を適用するために、kubeadmは環境ファイルを/var/lib/kubelet/kubeadm-flags.envへ書き出します。このファイルは以下のように、kubelet起動時に渡されるフラグのリストを含んでいます。

KUBELET_KUBEADM_ARGS="--flag1=value1 --flag2=value2 ..."

kubelet起動時に渡されるフラグに加えて、このファイルはcgroupドライバーや異なるCRIランタイムソケットを使用するかどうか(--cri-socket)といった動的なパラメーターも含みます。

これら二つのファイルがディスク上に格納されると、systemdを使用している場合、kubeadmは以下の二つのコマンドを実行します。

systemctl daemon-reload && systemctl restart kubelet

リロードと再起動に成功すると、通常のkubeadm initのワークフローが続きます。

kubeadm join実行時の流れ

kubeadm joinを実行した場合、kubeadmはBootstrap Token証明書を使用してTLS bootstrapを行い、ConfigMapkubelet-config-1.Xをダウンロードするために必要なクレデンシャルを取得し、/var/lib/kubelet/config.yamlへ書き込みます。動的な環境ファイルは、kubeadm initの場合と全く同様の方法で生成されます。

次に、kubeadmは、kubeletに新たな設定を読み込むために、以下の二つのコマンドを実行します。

systemctl daemon-reload && systemctl restart kubelet

kubeletが新たな設定を読み込むと、kubeadmは、KubeConfigファイル/etc/kubernetes/bootstrap-kubelet.confを書き込みます。これは、CA証明書とBootstrap Tokenを含みます。これらはkubeletがTLS Bootstrapを行い/etc/kubernetes/kubelet.confに格納されるユニークなクレデンシャルを取得するために使用されます。ファイルが書き込まれると、kubeletはTLS Bootstrapを終了します。

kubelet用のsystemdファイル

kubeadmには、systemdがどのようにkubeletを実行するかを指定した設定ファイルが同梱されています。 kubeadm CLIコマンドは決してこのsystemdファイルには触れないことに注意してください。

kubeadmのDEBパッケージまたはRPMパッケージによってインストールされたこの設定ファイルは、/etc/systemd/system/kubelet.service.d/10-kubeadm.confに書き込まれ、systemdで使用されます。基本的なkubelet.service(RPM用または、 DEB用)を拡張します。

[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf
--kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generate at runtime, populating
the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably,
# the user should use the .NodeRegistration.KubeletExtraArgs object in the configuration files instead.
# KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS

このファイルは、kubeadmがkubelet用に管理する全ファイルが置かれるデフォルトの場所を指定します。

  • TLS Bootstrapに使用するKubeConfigファイルは/etc/kubernetes/bootstrap-kubelet.confですが、/etc/kubernetes/kubelet.confが存在しない場合にのみ使用します。
  • ユニークなkublet識別子を含むKubeConfigファイルは/etc/kubernetes/kubelet.confです。
  • kubeletのComponentConfigを含むファイルは/var/lib/kubelet/config.yamlです。
  • KUBELET_KUBEADM_ARGSを含む動的な環境ファイルは/var/lib/kubelet/kubeadm-flags.envから取得します。
  • KUBELET_EXTRA_ARGSによるユーザー定義のフラグの上書きを格納できるファイルは/etc/default/kubelet(DEBの場合)、または/etc/sysconfig/kubelet(RPMの場合)から取得します。KUBELET_EXTRA_ARGSはフラグの連なりの最後に位置し、優先度が最も高いです。

Kubernetesバイナリとパッケージの内容

Kubernetesに同梱されるDEB、RPMのパッケージは以下の通りです。

パッケージ名説明
kubeadm/usr/bin/kubeadmCLIツールと、kubelet用のsystemdファイルをインストールします。
kubeletkubeletバイナリを/usr/binに、CNIバイナリを/opt/cni/binにインストールします。
kubectl/usr/bin/kubectlバイナリをインストールします。
cri-tools/usr/bin/crictlバイナリをcri-tools gitリポジトリからインストールします。

2.2.1.9 - kubeadmによるデュアルスタックのサポート

FEATURE STATE: Kubernetes v1.23 [stable]

Kubernetesクラスターにはデュアルスタックネットワークが含まれています。つまりクラスターネットワークではいずれかのアドレスファミリーを使用することができます。 クラスターでは、コントロールプレーンはIPv4アドレスとIPv6アドレスの両方を、単一のPodまたはServiceに割り当てることができます。

始める前に

kubeadmのインストールの手順に従って、kubeadmツールをインストールしておく必要があります。

ノードとして使用したいサーバーごとに、IPv6フォワーディングが許可されていることを確認してください。 Linuxでは、各サーバーでrootユーザーとしてsysctl -w net.ipv6.conf.all.forwarding=1を実行することで設定できます。

使用するにはIPv4およびIPv6アドレス範囲が必要です。 クラスター運用者は、通常はIPv4にはプライベートアドレス範囲を使用します。 IPv6では、通常は運用者が割り当てたアドレス範囲を使用して、2000::/3の範囲内からグローバルユニキャストアドレスブロックを選択します。 クラスターのIPアドレス範囲をパブリックインターネットにルーティングする必要はありません。

IPアドレス割り当てのサイズは、実行する予定のPodとServiceの数に適している必要があります。

備考:

kubeadm upgradeコマンドを使用して既存のクラスターをアップグレードする場合、kubeadmはPodのIPアドレス範囲("クラスターCIDR")やクラスターのServiceのアドレス範囲("Service CIDR")の変更をサポートしません。

デュアルスタッククラスターの作成

kubeadm initを使用してデュアルスタッククラスターを作成するには、以下の例のようにコマンドライン引数を渡します:

# これらのアドレス範囲は例です
kubeadm init --pod-network-cidr=10.244.0.0/16,2001:db8:42:0::/56 --service-cidr=10.96.0.0/16,2001:db8:42:1::/112

わかりやすいように、主要なデュアルスタックコントロールプレーンノードのkubeadm構成ファイルkubeadm-config.yamlの例を示します。

---
apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
networking:
  podSubnet: 10.244.0.0/16,2001:db8:42:0::/56
  serviceSubnet: 10.96.0.0/16,2001:db8:42:1::/112
---
apiVersion: kubeadm.k8s.io/v1beta4
kind: InitConfiguration
localAPIEndpoint:
  advertiseAddress: "10.100.0.1"
  bindPort: 6443
nodeRegistration:
  kubeletExtraArgs:
  - name: "node-ip"
    value: "10.100.0.2,fd00:1:2:3::2

InitConfigurationのadvertiseAddressは、APIサーバーがリッスンしていることをアドバタイズするIPアドレスを指定します。 advertiseAddressの値はkubeadm init--apiserver-advertise-addressフラグに相当します。

kubeadmを実行してデュアルスタックコントロールプレーンノードを初期化します:

kubeadm init --config=kubeadm-config.yaml

kube-controller-managerフラグ--node-cidr-mask-size-ipv4|--node-cidr-mask-size-ipv6はデフォルト値で設定されます。 IPv4/IPv6デュアルスタックの設定を参照してください。

備考:

--apiserver-advertise-addressフラグはデュアルスタックをサポートしません。

デュアルスタッククラスターへのノード参加

ノードを参加させる前に、そのノードにIPv6ルーティングが可能なネットワークインターフェースがあり、IPv6フォワーディングが許可されていることを確認してください。

以下は、ワーカーノードをクラスターに参加させるためのkubeadm構成ファイルkubeadm-config.yamlの例です。

apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
discovery:
  bootstrapToken:
    apiServerEndpoint: 10.100.0.1:6443
    token: "clvldh.vjjwg16ucnhp94qr"
    caCertHashes:
    - "sha256:a4863cde706cfc580a439f842cc65d5ef112b7b2be31628513a9881cf0d9fe0e"
    # 上記の認証情報をクラスターの実際のトークンとCA証明書に一致するように変更
nodeRegistration:
  kubeletExtraArgs:
  - name: "node-ip"
    value: "10.100.0.2,fd00:1:2:3::3"

また以下は、別のコントロールプレーンノードをクラスターに参加させるためのkubeadm構成ファイルkubeadm-config.yamlの例です。

apiVersion: kubeadm.k8s.io/v1beta4
kind: JoinConfiguration
controlPlane:
  localAPIEndpoint:
    advertiseAddress: "10.100.0.2"
    bindPort: 6443
discovery:
  bootstrapToken:
    apiServerEndpoint: 10.100.0.1:6443
    token: "clvldh.vjjwg16ucnhp94qr"
    caCertHashes:
    - "sha256:a4863cde706cfc580a439f842cc65d5ef112b7b2be31628513a9881cf0d9fe0e"
    # 上記の認証情報をクラスターの実際のトークンとCA証明書に一致するように変更
nodeRegistration:
  kubeletExtraArgs:
  - name: "node-ip"
    value: "10.100.0.2,fd00:1:2:3::4"

JoinConfiguration.controlPlaneのadvertiseAddressは、APIサーバーがリッスンしていることをアドバタイズするIPアドレスを指定します。 advertiseAddressの値はkubeadm join--apiserver-advertise-addressフラグに相当します。

kubeadm join --config=kubeadm-config.yaml

シングルスタッククラスターの作成

備考:

デュアルスタックのサポートは、デュアルスタックアドレスを使用する必要があるという意味ではありません。 デュアルスタックネットワーク機能が有効になっているシングルスタッククラスターをデプロイすることができます。

よりわかりやすいように、シングルスタックコントロールプレーンノードのkubeadm構成ファイルkubeadm-config.yamlの例を示します。

apiVersion: kubeadm.k8s.io/v1beta4
kind: ClusterConfiguration
networking:
  podSubnet: 10.244.0.0/16
  serviceSubnet: 10.96.0.0/16

次の項目

2.2.1.10 - コントロールプレーンをセルフホストするようにkubernetesクラスターを構成する

コントロールプレーンのセルフホスティング

kubeadmを使用すると、セルフホスト型のKubernetesコントロールプレーンを実験的に作成できます。これはAPIサーバー、コントローラーマネージャー、スケジューラーなどの主要コンポーネントは、静的ファイルを介してkubeletで構成されたstatic podsではなく、Kubernetes APIを介して構成されたDaemonSet podsとして実行されることを意味します。

セルフホスト型クラスターを作成する場合はkubeadm alpha selfhosting pivotを参照してください。

警告

注意:

この機能により、クラスターがサポートされていない状態になり、kubeadmがクラスターを管理できなくなります。これにはkubeadm upgradeが含まれます。
  1. 1.8以降のセルフホスティングには、いくつかの重要な制限があります。特に、セルフホスト型クラスターは、手動の介入なしにコントロールプレーンのNode再起動から回復することはできません。

  2. デフォルトでは、セルフホスト型のコントロールプレーンのPodは、hostPathボリュームからロードされた資格情報に依存しています。最初の作成を除いて、これらの資格情報はkubeadmによって管理されません。

  3. コントロールプレーンのセルフホストされた部分にはetcdが含まれていませんが、etcdは静的Podとして実行されます。

プロセス

セルフホスティングのブートストラッププロセスは、kubeadm design documentに記載されています。

要約すると、kubeadm alpha selfhostingは次のように機能します。

  1. 静的コントロールプレーンのブートストラップが起動し、正常になるのを待ちます。これはkubeadm initのセルフホスティングを使用しないプロセスと同じです。

  2. 静的コントロールプレーンのPodのマニフェストを使用して、セルフホスト型コントロールプレーンを実行する一連のDaemonSetのマニフェストを構築します。また、必要に応じてこれらのマニフェストを変更します。たとえば、シークレット用の新しいボリュームを追加します。

  3. kube-systemのネームスペースにDaemonSetを作成し、Podの結果が起動されるのを待ちます。

  4. セルフホスト型のPodが操作可能になると、関連する静的Podが削除され、kubeadmは次のコンポーネントのインストールに進みます。これによりkubeletがトリガーされて静的Podが停止します。

  5. 元の静的なコントロールプレーンが停止すると、新しいセルフホスト型コントロールプレーンはリスニングポートにバインドしてアクティブになります。

2.3 - ターンキークラウドソリューション

このページは、Kubernetes認定ソリューションプロバイダーのリストを提供します。 各プロバイダーのページから、本番環境でも利用可能なクラスターのインストール方法やセットアップ方法を学ぶことができます。

3 - ベストプラクティス

3.1 - 大規模クラスターの構築

クラスターはKubernetesのエージェントが動作する(物理もしくは仮想の)ノードの集合で、コントロールプレーンによって管理されます。 Kubernetes v1.36 では、最大5000ノードから構成されるクラスターをサポートします。 具体的には、Kubernetesは次の基準を 全て 満たす構成に対して適用できるように設計されています。

  • 1ノードにつきPodが110個以上存在しない
  • 5000ノード以上存在しない
  • Podの総数が150000個以上存在しない
  • コンテナの総数が300000個以上存在しない

ノードを追加したり削除したりすることによって、クラスターをスケールできます。 これを行う方法は、クラスターがどのようにデプロイされたかに依存します。

クラウドプロバイダーのリソースクォータ

クラウドプロバイダーのクォータの問題に遭遇することを避けるため、多数のノードを使ったクラスターを作成するときには次のようなことを考慮してください。

  • 次のようなクラウドリソースの増加をリクエストする
    • コンピューターインスタンス
    • CPU
    • ストレージボリューム
    • 使用中のIPアドレス
    • パケットフィルタリングのルールセット
    • ロードバランサーの数
    • ネットワークサブネット
    • ログストリーム
  • クラウドプロバイダーによる新しいインスタンスの作成に対するレート制限のため、バッチで新しいノードを立ち上げるようなクラスターのスケーリング操作を通すためには、バッチ間ですこし休止を入れます。

コントロールプレーンのコンポーネント

大きなクラスターでは、十分な計算とその他のリソースを持ったコントロールプレーンが必要になります。

特に故障ゾーンあたり1つまたは2つのコントロールプレーンインスタンスを動かす場合、最初に垂直方向にインスタンスをスケールし、垂直方向のスケーリングの効果が低下するポイントに達したら水平方向にスケールします。

フォールトトレランスを備えるために、1つの故障ゾーンに対して最低1インスタンスを動かすべきです。 Kubernetesノードは、同一故障ゾーン内のコントロールプレーンエンドポイントに対して自動的にトラフィックが向かないようにします。 しかし、クラウドプロバイダーはこれを実現するための独自の機構を持っているかもしれません。

例えばマネージドなロードバランサーを使うと、故障ゾーン A にあるkubeletやPodから発生したトラフィックを、同じく故障ゾーン A にあるコントロールプレーンホストに対してのみ送るように設定します。もし1つのコントロールプレーンホストまたは故障ゾーン A のエンドポイントがオフラインになった場合、ゾーン A にあるノードについてすべてのコントロールプレーンのトラフィックはゾーンを跨いで送信されます。それぞれのゾーンで複数のコントロールプレーンホストを動作させることは、結果としてほとんどありません。

etcdストレージ

大きなクラスターの性能を向上させるために、他の専用のetcdインスタンスにイベントオブジェクトを保存できます。

クラスターを作るときに、(カスタムツールを使って)以下のようなことができます。

  • 追加のetcdインスタンスを起動または設定する
  • イベントを保存するためにAPIサーバを設定する

大きなクラスターのためにetcdを設定・管理する詳細については、Operating etcd clusters for Kubernetesまたはkubeadmを使用した高可用性etcdクラスターの作成を見てください。

アドオンのリソース

Kubernetesのリソース制限は、メモリリークの影響やPodやコンテナが他のコンポーネントに与える他の影響を最小化することに役立ちます。 これらのリソース制限は、アプリケーションのワークロードに適用するのと同様に、アドオンのリソースにも適用されます。

例えば、ロギングコンポーネントに対してCPUやメモリ制限を設定できます。

  ...
  containers:
  - name: fluentd-cloud-logging
    image: fluent/fluentd-kubernetes-daemonset:v1
    resources:
      limits:
        cpu: 100m
        memory: 200Mi

アドオンのデフォルト制限は、アドオンを小~中規模のKubernetesクラスターで動作させたときの経験から得られたデータに基づきます。 大規模のクラスターで動作させる場合は、アドオンはデフォルト制限よりも多くのリソースを消費することが多いです。 これらの値を調整せずに大規模のクラスターをデプロイした場合、メモリー制限に達し続けるため、アドオンが継続的に停止されるかもしれません。 あるいは、CPUのタイムスライス制限により性能がでない状態で動作するかもしれません。

クラスターのアドオンのリソース制限に遭遇しないために、多くのノードで構成されるクラスターを構築する場合は次のことを考慮します。

  • いくつかのアドオンは垂直方向にスケールします - クラスターに1つのレプリカ、もしくは故障ゾーン全体にサービングされるものがあります。このようなアドオンでは、クラスターをスケールアウトしたときにリクエストと制限を増やす必要があります。
  • 数多くのアドオンは、水平方向にスケールします - より多くのPod数を動作させることで性能を向上できます - ただし、とても大きなクラスターではCPUやメモリの制限も少し引き上げる必要があるかもしれません。VerticalPodAutoscalerは、提案されたリクエストや制限の数値を提供する _recommender_ モードで動作可能です。
  • いくつかのアドオンはDaemonSetによって制御され、1ノードに1つ複製される形で動作します: 例えばノードレベルのログアグリゲーターです。水平方向にスケールするアドオンの場合と同様に、CPUやメモリ制限を少し引き上げる必要があるかもしれません。

次の項目

VerticalPodAutoscaler は、リソースのリクエストやPodの制限についての管理を手助けするためにクラスターへデプロイ可能なカスタムリソースです。 VerticalPodAutoscaler やクラスターで致命的なアドオンを含むクラスターコンポーネントをスケールする方法についてさらに知りたい場合はVertical Pod Autoscalerをご覧ください。

cluster autoscalerは、クラスターで要求されるリソース水準を満たす正確なノード数で動作できるよう、いくつかのクラウドプロバイダーと統合されています。

addon resizerは、クラスターのスケールが変化したときにアドオンの自動的なリサイズをお手伝いします。

3.2 - 複数のゾーンで動かす

このページでは、複数のゾーンにまたがるKubernetesクラスターの実行について説明します。

背景

Kubernetesは、1つのKubernetesクラスターが複数のゾーンにまたがって実行できるように設計されており、通常これらのゾーンは リージョン と呼ばれる論理的なグループ内に収まります。主要なクラウドプロバイダーは、一貫した機能を提供するゾーン( アベイラビリティゾーン とも呼ばれる)の集合をリージョンと定義しており、リージョン内では各ゾーンが同じAPIとサービスを提供しています。

一般的なクラウドアーキテクチャは、あるゾーンでの障害が別のゾーンのサービスにも影響を与える可能性を最小限に抑えることを目的としています。

コントロールプレーンの動作

すべてのコントロールプレーンコンポーネントは、交換可能なリソースのプールとして実行され、コンポーネントごとに複製されることをサポートします。

クラスターコントロールプレーンをデプロイする場合は、複数のゾーンに渡ってコントロールプレーンコンポーネントのレプリカを配置します。可用性を重視する場合は、少なくとも3つのゾーンを選択し、個々のコントロールプレーンコンポーネント(APIサーバー、スケジューラー、etcd、クラスターコントローラーマネージャー)を少なくとも3つのゾーンに渡って複製します。クラウドコントローラーマネージャーを実行している場合は、選択したすべてのゾーンにまたがって複製する必要があります。

備考:

KubernetesはAPIサーバーのエンドポイントに対してゾーンを跨いだ回復力を提供しません。クラスター内のAPIサーバーの可用性を向上させるためにDNSラウンドロビン、SRVレコード、またはヘルスチェックを備えたサードパーティの負荷分散ソリューションなど、さまざまな技術を使用できます。

ノードの動作

Kubernetesは、(DeploymentStatefulSetのような)ワークロードリソース用のPodをクラスター内の異なるノードに自動的に分散します。この分散は、障害の影響を軽減するのに役立ちます。

ノードが起動すると、各ノードのkubeletは、Kubernetes APIで特定のkubeletを表すNodeオブジェクトにラベルを自動的に追加します。これらのラベルにはゾーン情報を含めることができます。

クラスターが複数のゾーンまたはリージョンにまたがっている場合、ノードラベルとPod Topology Spread Constraintsを組み合わせて使用することで、リージョン、ゾーン、さらには特定のノードといった障害ドメイン間でクラスター全体にPodをどのように分散させるかを制御できます。これらのヒントにより、スケジューラーは期待される可用性を高めてPodを配置し、関連する障害がワークロード全体に影響するリスクを低減できます

例えば、StatefulSetの3つのレプリカがすべて互いに異なるゾーンで実行されるように制約を設定できます。ワークロードごとにどのアベイラビリティゾーンを使用するかを明示的に定義しなくても、宣言的に定義できます。

ノードをゾーンに分散させる

Kubernetesのコアがノードを作成してくれるわけではないため、自分で行うか、Cluster APIなどのツールを使ってノードの管理を代行する必要があります。

Cluster APIなどのツールを使用すると、複数の障害ドメインにわたってクラスターのワーカーノードとして実行するマシンのセットを定義したり、ゾーン全体のサービスが中断した場合にクラスターを自動的に復旧するルールを定義できます。

Podの手動ゾーン割り当て

nodeSelectorの制約は、作成したPodだけでなく、Deployment、StatefulSet、Jobなどのワークロードリソース内のPodテンプレートにも適用できます。

ゾーンのストレージアクセス

Persistent Volumeが作成されると、Kubernetesは特定のゾーンにリンクされているすべてのPersistent Volumeにゾーンラベルを自動的に追加します。その後、スケジューラーは、NoVolumeZoneConflict条件を通じて、指定されたPersistent Volumeを要求するPodがそのボリュームと同じゾーンにのみ配置されるようにします。

ゾーンラベルの追加方法は、クラウドプロバイダーと使用しているストレージプロビジョナーによって異なる可能性があることに注意してください。正しい設定を行うために、常に利用している環境のドキュメントを参照してください。

Persistent Volume Claimには、そのクラス内のストレージが使用する障害ドメイン(ゾーン)を指定するStorageClassを指定できます。障害ドメインまたはゾーンを認識するStorageClassの構成については、許可されたトポロジーを参照してください。

ネットワーキング

Kubernetes自体にはゾーンを意識したネットワーキングは含まれていません。ネットワークプラグインを使用してクラスターネットワーキングを設定できますが、そのネットワークソリューションにはゾーン固有の要素があるかもしれません。例えば、クラウドプロバイダーがtype=LoadBalancerのServiceをサポートしている場合、ロードバランサーは与えられた接続を処理するロードバランサーのコンポーネントと同じゾーンで動作しているPodにのみトラフィックを送信する可能性があります。詳しくはクラウドプロバイダーのドキュメントを確認してください。

カスタムまたはオンプレミスのデプロイメントの場合、同様の考慮事項が適用されます。ServiceおよびIngressの動作は、異なるゾーンの処理を含め、クラスターのセットアップ方法によって異なります。

障害回復

クラスターをセットアップする際には、リージョン内のすべてのゾーンが同時にオフラインになった場合にセットアップがサービスを復旧できるかどうか、またどのように復旧させるかを考慮しておく必要があるかもしれません。例えば、ゾーン内にPodを実行できるノードが少なくとも1つあることに依存していますか?クラスタークリティカルな修復作業が、クラスター内に少なくとも1つの健全なノードがあることに依存していないことを確認してください。例えば、全てのノードが不健全な場合、少なくとも1つのノードを使用できるよう修復が完了するように、特別なtolerationで修復Jobを実行する必要があるかもしれません。

Kubernetesにはこの課題に対する答えはありませんが、検討すべきことです。

次の項目

設定された制約を守りつつ、スケジューラーがクラスターにPodを配置する方法については、スケジューリング、プリエンプションと退避を参照してください。

3.3 - ノードのセットアップの検証

ノード適合テスト

ノード適合テスト は、システムの検証とノードに対する機能テストを提供するコンテナ型のテストフレームワークです。このテストは、ノードがKubernetesの最小要件を満たしているかどうかを検証するもので、テストに合格したノードはKubernetesクラスターに参加する資格があることになります。

ノードの前提条件

適合テストを実行するにはノードは通常のKubernetesノードと同じ前提条件を満たしている必要があります。 最低でもノードに以下のデーモンがインストールされている必要があります:

  • コンテナランタイム (Docker)
  • Kubelet

ノード適合テストの実行

ノード適合テストを実行するには、以下の手順に従います:

  1. kubeletの--kubeconfigオプションの値を調べます。例:--kubeconfig=/var/lib/kubelet/config.yaml。 このテストフレームワークはKubeletのテスト用にローカルコントロールプレーンを起動するため、APIサーバーのURLとしてhttp://localhost:8080を使用します。 他にも使用できるkubeletコマンドラインパラメーターがいくつかあります:

    • --cloud-provider: --cloud-provider=gceを指定している場合は、テストを実行する前にこのフラグを取り除いてください。
  2. 以下のコマンドでノード適合テストを実行します:

# $CONFIG_DIRはKubeletのPodのマニフェストパスです。
# $LOG_DIRはテスト出力のパスです。
sudo docker run -it --rm --privileged --net=host \
  -v /:/rootfs -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
  registry.k8s.io/node-test:0.2

他アーキテクチャ向けのノード適合テストの実行

Kubernetesは他のアーキテクチャ用のノード適合テストのdockerイメージを提供しています:

ArchImage
amd64node-test-amd64
armnode-test-arm
arm64node-test-arm64

選択したテストの実行

特定のテストを実行するには、環境変数FOCUSを実行したいテストの正規表現で上書きします。

sudo docker run -it --rm --privileged --net=host \
  -v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
  -e FOCUS=MirrorPod \ # MirrorPodテストのみを実行します
  registry.k8s.io/node-test:0.2

特定のテストをスキップするには、環境変数SKIPをスキップしたいテストの正規表現で上書きします。

sudo docker run -it --rm --privileged --net=host \
  -v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
  -e SKIP=MirrorPod \ # MirrorPodテスト以外のすべてのノード適合テストを実行します
  registry.k8s.io/node-test:0.2

ノード適合テストは、node e2e testのコンテナ化されたバージョンです。 デフォルトでは、すべての適合テストが実行されます。

理論的には、コンテナを構成し必要なボリュームを適切にマウントすれば、どのノードのe2eテストも実行できます。しかし、不適合テストを実行するためにはより複雑な設定が必要となるため、適合テストのみを実行することを強く推奨します

注意事項

  • このテストでは、ノード適合テストイメージや機能テストで使用されるコンテナのイメージなど、いくつかのdockerイメージがノード上に残ります。
  • このテストでは、ノード上にデッドコンテナが残ります。これらのコンテナは機能テスト中に作成されます。

3.4 - Podセキュリティ標準の強制

このページでは、Podセキュリティの標準を強制する際のベストプラクティスの概要を説明します。

ビルトインPodセキュリティアドミッションコントローラーの使用

FEATURE STATE: Kubernetes v1.25 [stable]

Podセキュリティアドミッションコントローラーは、非推奨のPodSecurityPolicyを置き換えます。

すべてのNamespaceに設定する

設定が全く無いNamespaceは、クラスターのセキュリティモデルにおいて重大な弱点とみなすべきです。 各Namespaceで発生するワークロードのタイプを時間をかけて分析し、Podセキュリティ標準を参照しながら、それぞれに適切なレベルを決定することを推奨します。 また、ラベルのないNamespaceは、まだ評価されていないことだけを示すべきです。

すべてのNamespaceのワークロードが同じセキュリティ要件を持つというシナリオでは、PodSecurityラベルを一括適用する方法をで説明しています。

最小特権の原則を採用する

理想的な世界では、すべてのNamespaceのPodがrestrictedポリシーの要件を満たすでしょう。 しかし、ワークロードの中には正当な理由で昇格した特権を必要とするものもあるため、それは不可能であり、現実的でもありません。

  • privilegedワークロードを許可するNamespaceは、適切なアクセス制御を確立し、実施すべきである。
  • 最小権限のNamespaceで実行されるワークロードについては、そのワークロードのセキュリティ要件に関するドキュメントを整備する。可能であれば、それらの要件がどのように制約される可能性があるのかを考慮する。

マルチモード戦略の採用

Podセキュリティアドミッションコントローラーのauditwarnモードを使用すると、既存のワークロードを破壊することなく、Podに関する重要なセキュリティインサイトを簡単に収集できます。

すべてのNamespaceでこれらのモードを有効にし、最終的にenforceしたいレベルやバージョンに設定するのがよい方法です。 このフェーズで生成される警告と監査注釈は、その状態への指針となります。 ワークロード作成者が希望のレベルに収まるように変更することを期待している場合は、warnモードを有効にしてください。 監査ログを使用して、希望のレベルに収まるように変更を監視/推進することを期待している場合は、auditモードを有効にしてください。

enforceモードが希望通りの値に設定されている場合でも、これらのモードはいくつかの異なる方法で役立ちます。

  • warnenforceと同じレベルに設定すると、バリデーションを通過しないPod(またはPodテンプレートを持つリソース)を作成しようとしたときに、クライアントが警告を受け取るようになります。これにより、対象のリソースを更新して準拠させることができます。
  • enforceを特定の最新バージョンではないに固定するNamespaceでは、auditwarnモードをenforceと同じレベルに設定するが、最新バージョンに対して設定することで、以前のバージョンでは許可されていたが、現在のベストプラクティスでは許可されていない設定を可視化することができます。

サードパーティによる代替案

備考: このセクションでは、Kubernetesが必要とする機能を提供するサードパーティプロジェクトにリンクしています。これらのプロジェクトはアルファベット順に記載されていて、Kubernetesプロジェクトの作者は責任を持ちません。このリストにプロジェクトを追加するには、変更を提出する前にコンテンツガイドをお読みください。詳細はこちら。

Kubernetesエコシステムでは、セキュリティプロファイルを強制するための他の選択肢も開発されています。

ビルトインソリューション(PodSecurityアドミッションコントローラーなど)とサードパーティツールのどちらを選ぶかは、あなたの状況次第です。 どのようなソリューションを評価する場合でも、サプライチェーンの信頼が非常に重要です。最終的には、前述のアプローチのどれを使っても、何もしないよりはましでしょう。

3.5 - PKI証明書とその要件

Kubernetesでは、TLS認証のためにPKI証明書が必要です。 kubeadmでKubernetesをインストールする場合、必要な証明書は自動で生成されます。 自身で証明書を作成することも可能です。例えば、秘密鍵をAPIサーバーに保持しないことで、管理をよりセキュアにする場合が挙げられます。 本ページでは、クラスターに必要な証明書について説明します。

クラスターではどのように証明書が使われているのか

Kubernetesは下記の用途でPKIを必要とします:

  • kubeletがAPIサーバーの認証をするためのクライアント証明書
  • APIサーバーがkubeletと通信するためのkubeletのサーバー証明書
  • APIサーバーのエンドポイント用サーバー証明書
  • クラスターの管理者がAPIサーバーの認証を行うためのクライアント証明書
  • APIサーバーがkubeletと通信するためのクライアント証明書
  • APIサーバーがetcdと通信するためのクライアント証明書
  • controller managerがAPIサーバーと通信するためのクライアント証明書およびkubeconfig
  • スケジューラーがAPIサーバーと通信するためのクライアント証明書およびkubeconfig
  • front-proxy用のクライアント証明書およびサーバー証明書

備考:

front-proxy証明書は、Kubernetes APIの拡張をサポートするためにkube-proxyを実行する場合のみ必要です。

さらに、etcdはクライアントおよびピア間の認証に相互TLS通信を実装しています。

証明書の保存場所

kubeadmを使用してKubernetesをインストールする場合、ほとんどの証明書は/etc/kubernetes/pkiに保存されます。このドキュメントの全てのパスは、そのディレクトリの相対パスを表します。 ただしユーザーアカウントの証明書に関しては、kubeadmは/etc/kubernetesに配置します。

手動で証明書を設定する

もしkubeadmに必要な証明書の生成を望まない場合、それらを単一ルート認証局を使って作成するか、全ての証明書を提供することで作成できます。 自身の認証局を作成する詳細については、証明書を手動で生成するを参照してください。 証明書の管理についての詳細は、kubeadmによる証明書管理を参照してください。

単一ルート認証局

管理者によりコントロールされた、単一ルート認証局の作成が可能です。このルート認証局は複数の中間認証局を作る事が可能で、作成はKubernetes自身に委ねます。

必要な認証局:

パスデフォルトCN説明
ca.crt,keykubernetes-caKubernetes全体の認証局
etcd/ca.crt,keyetcd-caetcd用
front-proxy-ca.crt,keykubernetes-front-proxy-cafront-end proxy

上記の認証局に加えて、サービスアカウント管理用に公開鍵/秘密鍵のペア(sa.keysa.pub)を取得する事が必要です。 次の例は、前の表で示されたCAのキーと証明書を示しています:

/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-ca.key

全ての証明書

CAの秘密鍵をクラスターにコピーしたくない場合、自身で全ての証明書を作成できます。

必要な証明書:

デフォルトCN親認証局組織種類ホスト名 (SAN)
kube-etcdetcd-caserver, client<hostname>, <Host_IP>, localhost, 127.0.0.1
kube-etcd-peeretcd-caserver, client<hostname>, <Host_IP>, localhost, 127.0.0.1
kube-etcd-healthcheck-clientetcd-caclient
kube-apiserver-etcd-clientetcd-caclient
kube-apiserverkubernetes-caserver<hostname>, <Host_IP>, <advertise_IP>, [1]
kube-apiserver-kubelet-clientkubernetes-casystem:mastersclient
front-proxy-clientkubernetes-front-proxy-caclient

備考:

kube-apiserver-kubelet-clientにスーパーユーザーグループsystem:mastersを使用する代わりに、より権限の低いグループを使用することができます。 そのために、kubeadmはkubeadm:cluster-adminsグループを使用します。

[1]: クラスターに接続するIPおよびDNS名( kubeadmを使用する場合と同様、ロードバランサーのIPおよびDNS名、kuberneteskubernetes.defaultkubernetes.default.svckubernetes.default.svc.clusterkubernetes.default.svc.cluster.local)

ここで種類は、一つまたは複数のx509の鍵用途にマッピングされており、これはCertificateSigningRequest.spec.usagesにも記載されています:

種類鍵の用途
serverdigital signature, key encipherment, server auth
clientdigital signature, key encipherment, client auth

備考:

上記に挙げられたホスト名(SAN)は、クラスターを動作させるために推奨されるものです。 特別なセットアップが求められる場合、全てのサーバー証明書にSANを追加する事ができます。

備考:

kubeadm利用者のみ:

  • 秘密鍵なしでCA証明書をクラスターにコピーするシナリオは、kubeadmドキュメントの外部認証局の項目で言及されています。
  • kubeadmでPKIを生成すると、kube-etcdkube-etcd-peerおよび kube-etcd-healthcheck-client証明書は外部etcdを利用するケースでは生成されない事に留意してください。

証明書のパス

証明書は推奨パスに配置するべきです(kubeadmを使用する場合と同様)。 パスは場所に関係なく与えられた引数で特定されます。

デフォルトCN鍵の推奨パス証明書の推奨パスコマンド鍵を指定する引数証明書を指定する引数
etcd-caetcd/ca.keyetcd/ca.crtkube-apiserver--etcd-cafile
kube-apiserver-etcd-clientapiserver-etcd-client.keyapiserver-etcd-client.crtkube-apiserver--etcd-keyfile--etcd-certfile
kubernetes-caca.keyca.crtkube-apiserver--client-ca-file
kubernetes-caca.keyca.crtkube-controller-manager--cluster-signing-key-file--client-ca-file, --root-ca-file, --cluster-signing-cert-file
kube-apiserverapiserver.keyapiserver.crtkube-apiserver--tls-private-key-file--tls-cert-file
kube-apiserver-kubelet-clientapiserver-kubelet-client.keyapiserver-kubelet-client.crtkube-apiserver--kubelet-client-key--kubelet-client-certificate
front-proxy-cafront-proxy-ca.keyfront-proxy-ca.crtkube-apiserver--requestheader-client-ca-file
front-proxy-cafront-proxy-ca.keyfront-proxy-ca.crtkube-controller-manager--requestheader-client-ca-file
front-proxy-clientfront-proxy-client.keyfront-proxy-client.crtkube-apiserver--proxy-client-key-file--proxy-client-cert-file
etcd-caetcd/ca.keyetcd/ca.crtetcd--trusted-ca-file, --peer-trusted-ca-file
kube-etcdetcd/server.keyetcd/server.crtetcd--key-file--cert-file
kube-etcd-peeretcd/peer.keyetcd/peer.crtetcd--peer-key-file--peer-cert-file
etcd-caetcd/ca.crtetcdctl--cacert
kube-etcd-healthcheck-clientetcd/healthcheck-client.keyetcd/healthcheck-client.crtetcdctl--key--cert

サービスアカウント用の鍵ペアについても同様です。

秘密鍵のパス公開鍵のパスコマンド引数
sa.keykube-controller-managerservice-account-private
sa.pubkube-apiserverservice-account-key

次の例は、自分自身で全てのキーと証明書を生成している場合に提供する必要があるファイルパスを前の表から示しています:

/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/apiserver-etcd-client.key
/etc/kubernetes/pki/apiserver-etcd-client.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/apiserver.key
/etc/kubernetes/pki/apiserver.crt
/etc/kubernetes/pki/apiserver-kubelet-client.key
/etc/kubernetes/pki/apiserver-kubelet-client.crt
/etc/kubernetes/pki/front-proxy-ca.key
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-client.key
/etc/kubernetes/pki/front-proxy-client.crt
/etc/kubernetes/pki/etcd/server.key
/etc/kubernetes/pki/etcd/server.crt
/etc/kubernetes/pki/etcd/peer.key
/etc/kubernetes/pki/etcd/peer.crt
/etc/kubernetes/pki/etcd/healthcheck-client.key
/etc/kubernetes/pki/etcd/healthcheck-client.crt
/etc/kubernetes/pki/sa.key
/etc/kubernetes/pki/sa.pub

ユーザーアカウント用に証明書を設定する

管理者アカウントおよびサービスアカウントは手動で設定しなければなりません。

ファイル名クレデンシャル名デフォルトCNO (in Subject)
admin.confdefault-adminkubernetes-admin<admin-group>
super-admin.confdefault-super-adminkubernetes-super-adminsystem:masters
kubelet.confdefault-authsystem:node:<nodeName> (備考を参照)system:nodes
controller-manager.confdefault-controller-managersystem:kube-controller-manager
scheduler.confdefault-schedulersystem:kube-scheduler

備考:

kubelet.confにおける<nodeName>の値は必ずAPIサーバーに登録されたkubeletのノード名と一致しなければなりません。詳細は、Node Authorizationを参照してください。

備考:

上記の例での<admin-group>は実装に依存します。 一部のツールはデフォルトのadmin.conf内の証明書にsystem:mastersグループの一部として署名します。 system:mastersは緊急用のスーパーユーザーグループであり、RBACのようなKubernetesの認証レイヤーをバイパスすることができます。 また、一部のツールはこのスーパーユーザーグループに紐づけられた証明書を含むsuper-admin.confを生成しません。

kubeadmはkubeconfigファイル内に2つの別々の管理者証明書を生成します。 一つはadmin.conf内にあり、Subject: O = kubeadm:cluster-admins, CN = kubernetes-adminとなっています。 kubeadm:cluster-adminscluster-admin ClusterRoleに紐づけられたカスタムグループです。 このファイルは、kubeadmが管理する全てのコントロールプレーンマシン上で生成されます。

もう一つはsuper-admin.conf内にあり、Subject: O = system:masters, CN = kubernetes-super-adminとなっています。 このファイルはkubeadm initが呼び出されたノード上でのみ生成されます。

  1. 各コンフィグ毎に、CN名と組織を指定してx509証明書と鍵ペアを生成してください。

  2. 以下のように、各コンフィグでkubectlを実行してください。

KUBECONFIG=<filename> kubectl config set-cluster default-cluster --server=https://<host ip>:6443 --certificate-authority <path-to-kubernetes-ca> --embed-certs
KUBECONFIG=<filename> kubectl config set-credentials <credential-name> --client-key <path-to-key>.pem --client-certificate <path-to-cert>.pem --embed-certs
KUBECONFIG=<filename> kubectl config set-context default-system --cluster default-cluster --user <credential-name>
KUBECONFIG=<filename> kubectl config use-context default-system

これらのファイルは以下のように利用されます:

ファイル名コマンドコメント
admin.confkubectlクラスターの管理者設定用
kubelet.confkubeletクラスターの各ノードに1つ必要です。
controller-manager.confkube-controller-managermanifests/kube-controller-manager.yamlのマニフェストファイルに追記する必要があります。
scheduler.confkube-schedulermanifests/kube-scheduler.yamlのマニフェストファイルに追記する必要があります。

以下のファイルは、前の表に挙げたファイルへの絶対パスを示しています:

/etc/kubernetes/admin.conf
/etc/kubernetes/super-admin.conf
/etc/kubernetes/kubelet.conf
/etc/kubernetes/controller-manager.conf
/etc/kubernetes/scheduler.conf