プロダクション環境
プロダクション品質の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-apiserver、kube-controller-manager、kube-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クラスターの認証認可をセットアップするにあたって、いくつかの考慮事項があります。
- 認証モードの設定: Kubermetes 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は名前空間のデフォルトのサービスアカウントを引き受けます。新規のサービスアカウントの作成についての情報はサービスアカウントの管理をご覧ください。例えば、以下のようなことが考えられます:
次の項目
1 - コンテナランタイム
クラスター内の各ノードがPodを実行できるようにするため、コンテナランタイムをインストールする必要があります。
このページでは、ノードをセットアップするための概要と関連する作業について説明します。
Kubernetes 1.30においては、Container Runtime Interface (CRI)に準拠したランタイムを使用する必要があります。
詳しくはサポートするCRIのバージョンをご覧ください。
このページではいくつかの一般的なコンテナランタイムをKubernetesで使用する方法の概要を説明します。
備考:
v1.24以前のKubernetesリリースでは、 dockershim という名前のコンポーネントを使用したDocker Engineとの直接の統合が含まれていました。
この特別な直接統合は、もはやKubernetesの一部ではありません(この削除はv1.20リリースの一部として発表されています)。
dockershimの廃止がどのような影響を与えるかについては、dockershim削除の影響範囲を確認する をご覧ください。
dockershimからの移行について知りたい場合、dockershimからの移行を参照してください。
v1.30以外のバージョンのKubernetesを実行している場合、そのバージョンのドキュメントを確認してください。
インストールと設定の必須要件
以下の手順では、全コンテナランタイムに共通の設定をLinux上のKubernetesノードに適用します。
特定の設定が不要であることが分かっている場合、手順をスキップして頂いて構いません。
詳細については、Network Plugin Requirementsまたは、特定のコンテナランタイムのドキュメントを参照してください。
IPv4フォワーディングを有効化し、iptablesからブリッジされたトラフィックを見えるようにする
以下のコマンドを実行します。
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# この構成に必要なカーネルパラメーター、再起動しても値は永続します
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 再起動せずにカーネルパラメーターを適用
sudo sysctl --system
以下のコマンドを実行してbr_netfilter
とoverlay
モジュールが読み込まれていることを確認してください。
lsmod | grep br_netfilter
lsmod | grep overlay
以下のコマンドを実行して、net.bridge.bridge-nf-call-iptables
、net.bridge.bridge-nf-call-ip6tables
、net.ipv4.ip_forward
カーネルパラメーターが1に設定されていることを確認します。
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables 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
を設定するには、以下のようにKubeletConfiguration
のcgroupDriver
オプションを編集して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.30は、デフォルトでCRI APIのv1を使用します。
コンテナランタイムがv1 APIをサポートしていない場合、kubeletは代わりに(非推奨の)v1alpha2 APIにフォールバックします。
コンテナランタイム
備考: このセクションでは、Kubernetesが必要とする機能を提供するサードパーティープロジェクトにリンクしています。これらのプロジェクトはアルファベット順に記載されていて、Kubernetesプロジェクトの作者は責任を持ちません。このリストにプロジェクトを追加するには、変更を提出する前に
content guideをお読みください。
詳細はこちら。
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
内でrunc
がsystemd
cgroupドライバーを使うようにするには、次のように設定します。
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".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
アダプターを使用することを想定しています。
-
各ノードに、使用しているLinuxディストリビューション用のDockerをDocker Engineのインストールに従ってインストールします。
-
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 - Kubernetesをデプロイツールでインストールする
2.1 - kubeadmを使ってクラスターを構築する
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などのツールを使用することで、下記のようにポートが開いているかどうかを確認することが可能です。
使用する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は、組み込まれたdockershim
CRIを通してDockerと連携します。
詳細は、コンテナランタイムを参照してください。
デフォルトでは、kubeadmはDockerをコンテナランタイムとして使用します。
kubeletは、組み込まれたdockershim
CRIを通してDockerと連携します。
詳細は、コンテナランタイムを参照してください。
kubeadm、kubelet、kubectlのインストール
以下のパッケージをマシン上にインストールしてください
-
kubeadm
: クラスターを起動するコマンドです。
-
kubelet
: クラスター内のすべてのマシンで実行されるコンポーネントです。
Podやコンテナの起動などを行います。
-
kubectl
: クラスターにアクセスするためのコマンドラインツールです。
kubeadmはkubelet
やkubectl
をインストールまたは管理しないため、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)に関しては下記を参照してください。
-
apt
のパッケージ一覧を更新し、Kubernetesのapt
リポジトリーを利用するのに必要なパッケージをインストールします:
sudo apt-get update
# apt-transport-httpsはダミーパッケージの可能性があります。その場合、そのパッケージはスキップできます
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
-
Kubernetesパッケージリポジトリーの公開署名キーをダウンロードします。すべてのリポジトリーに同じ署名キーが使用されるため、URL内のバージョンは無視できます:
# `/etc/apt/keyrings`フォルダーが存在しない場合は、curlコマンドの前に作成する必要があります。下記の備考を参照してください。
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
備考:
Debian 12とUbuntu 22.04より古いリリースでは、/etc/apt/keyrings
フォルダーはデフォルトでは存在しないため、curlコマンドの前に作成する必要があります。
-
適切なKubernetes apt
リポジトリーを追加します。このリポジトリーには、Kubernetes 1.30用のパッケージのみがあることに注意してください。他の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.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
-
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
kubeadm
、kubelet
、kubectl
をインストールし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.1.2 - kubeadmのトラブルシューティング
どのプログラムでもそうですが、kubeadmのインストールや実行でエラーが発生することがあります。このページでは、一般的な失敗例をいくつか挙げ、問題を理解して解決するための手順を示しています。
本ページに問題が記載されていない場合は、以下の手順を行ってください:
RBACがないため、v1.18ノードをv1.17クラスターに結合できない
v1.18では、同名のノードが既に存在する場合にクラスター内のノードに参加しないようにする機能を追加しました。これには、ブートストラップトークンユーザがNodeオブジェクトをGETできるようにRBACを追加する必要がありました。
しかし、これによりv1.18のkubeadm join
がkubeadm v1.17で作成したクラスターに参加できないという問題が発生します。
この問題を回避するには、次の2つの方法があります。
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つの方法があります:
-
ここの指示に従ってDockerを再度インストールします。
-
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のログを調べるのも有効な場合があります:
Podの状態がRunContainerError
、CrashLoopBackOff
、またはError
となる
kubeadm init
の直後には、これらの状態ではPodは存在しないはずです。
kubeadm init
の 直後 にこれらの状態のいずれかにPodがある場合は、kubeadmのリポジトリにIssueを立ててください。ネットワークソリューションをデプロイするまではcoredns
(またはkube-dns
)はPending
状態でなければなりません。
- ネットワークソリューションをデプロイしても
coredns
(またはkube-dns
)に何も起こらない場合にRunContainerError、
CrashLoopBackOff、
Error`の状態でPodが表示された場合は、インストールしたPodネットワークソリューションが壊れている可能性が高いです。より多くのRBACの特権を付与するか、新しいバージョンを使用する必要があるかもしれません。PodネットワークプロバイダのイシュートラッカーにIssueを出して、そこで問題をトリアージしてください。
- 1.12.1よりも古いバージョンのDockerをインストールした場合は、
systemd
でdockerd
を起動する際に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
サービスが動かない
HostPort
とHostIP
の機能は、ご使用のPodネットワークプロバイダによって利用可能です。Podネットワークソリューションの作者に連絡して、HostPort
とHostIP
機能が利用可能かどうかを確認してください。
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
の設定を解除するには以下のコマンドを実行するか:
設定をデフォルトの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 logs
やkubectl 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を無効にするかallowPrivilegeEscalation
をtrue
に設定すると、クラスターのセキュリティが損なわれる可能性があります。
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
のような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-plugins
はNamespaceExists
の値しか持ちません。既知の回避策としては、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つの回避策があります:
-
空のスライスの代わりにnode-role.kubernetes.io/master:PreferNoSchedule
テイントを使用します。他のノードに容量がない限り、Podsはマスター上でスケジュールされます。
-
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 plan
がcontext deadline exceeded
エラーメッセージを表示する
このエラーメッセージは、外部etcdを実行している場合にkubeadm
でKubernetesクラスターをアップグレードする際に表示されます。これは致命的なバグではなく、古いバージョンのkubeadmが外部etcdクラスターのバージョンチェックを行うために発生します。kubeadm upgrade apply ...
で進めることができます。
この問題はバージョン1.19で修正されます。
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.30向けに書かれています。
kubeadmツールの全体の機能の状態は、一般利用可能(GA)です。一部のサブ機能はまだ活発に開発が行われています。クラスター作成の実装は、ツールの進化に伴ってわずかに変わるかもしれませんが、全体の実装は非常に安定しているはずです。
備考:
kubeadm alpha
以下のすべてのコマンドは、定義通り、アルファレベルでサポートされています。
目的
- シングルコントロールプレーンのKubernetesクラスターをインストールする
- クラスター上にPodネットワークをインストールして、Podがお互いに通信できるようにする
手順
ホストへのkubeadmのインストール
「kubeadmのインストール」を読んでください。
備考:
すでにkubeadmがインストール済みである場合は、最新バージョンのkubeadmを取得するためにapt-get update && apt-get upgrade
やyum update
を実行してください。
アップグレード中、kubeletが数秒ごとに再起動します。これは、kubeadmがkubeletにするべきことを伝えるまで、crashloopの状態で待機するためです。このcrashloopは期待通りの通常の動作です。コントロールプレーンの初期化が完了すれば、kubeletは正常に動作します。
コントロールプレーンノードの初期化
コントロールプレーンノードとは、etcd(クラスターのデータベース)やAPIサーバー(kubectlコマンドラインツールが通信する相手)などのコントロールプレーンのコンポーネントが実行されるマシンです。
- (推奨)シングルコントロールプレーンの
kubeadm
クラスターを高可用性クラスターにアップグレードする予定がある場合、--control-plane-endpoint
を指定して、すべてのコントロールプレーンノードとエンドポイントを共有する必要があります。エンドポイントにはDNSネームやロードバランサーのIPアドレスが使用できます。
- Podネットワークアドオンを選んで、
kubeadm init
に引数を渡す必要があるかどうか確認してください。選んだサードパーティーのプロバイダーによっては、--pod-network-cidr
をプロバイダー固有の値に設定する必要がある場合があります。詳しくは、Podネットワークアドオンのインストールを参照してください。
- (オプション)バージョン1.14から、
kubeadm
はよく知られたドメインソケットのパスリストを用いて、Linux上のコンテナランタイムの検出を試みます。異なるコンテナランタイムを使用する場合やプロビジョニングするノードに2つ以上のランタイムがインストールされている場合、kubeadm init
に--cri-socket
引数を指定してください。詳しくは、ランタイムのインストールを読んでください。
- (オプション)明示的に指定しない限り、
kubeadm
はデフォルトゲートウェイに関連付けられたネットワークインターフェースを使用して、この特定のコントロールプレーンノードのAPIサーバーのadvertise addressを設定します。異なるネットワークインターフェースを使用するには、kubeadm init
に--apiserver-advertise-address=<ip-address>
引数を指定してください。IPv6アドレスを使用するIPv6 Kubernetesクラスターをデプロイするには、たとえば--apiserver-advertise-address=fd00::101
のように、IPv6アドレスを指定する必要があります。
- (オプション)
kubeadm init
を実行する前にkubeadm config images pull
を実行して、gcr.ioコンテナイメージレジストリに接続できるかどうかを確認します。
コントロールプレーンノードを初期化するには、次のコマンドを実行します。
apiserver-advertise-addressとControlPlaneEndpointに関する検討
--apiserver-advertise-address
は、この特定のコントロールプレーンノードのAPIサーバーへのadvertise addressを設定するために使えますが、--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-endpoint
をkubeadm init
に渡せるようになり、kubeadm join
にも同じDNSネームを渡せます。後でcluster-endpoint
を修正して、高可用性が必要なシナリオでロードバランサーのアドレスを指すようにすることができます。
kubeadmでは、--control-plane-endpoint
を渡さずに構築したシングルコントロールプレーンのクラスターを高可用性クラスターに切り替えることはサポートされていません。
詳細な情報
kubeadm init
の引数のより詳細な情報は、kubeadmリファレンスガイドを参照してください。
設定オプションの全リストは、設定ファイルのドキュメントで確認できます。
コントロールプレーンコンポーネントやetcdサーバーのliveness probeへのオプションのIPv6の割り当てなど、コントロールプレーンのコンポーネントをカスタマイズしたい場合は、カスタムの引数に示されている方法で各コンポーネントに追加の引数を与えてください。
kubeadm init
を再び実行する場合は、初めにクラスターの破壊を行う必要があります。
もし異なるアーキテクチャのノードをクラスターにjoinさせたい場合は、デプロイしたDaemonSetがそのアーキテクチャ向けのコンテナイメージをサポートしているか確認してください。
初めにkubeadm init
は、マシンがKubernetesを実行する準備ができているかを確認する、一連の事前チェックを行います。これらの事前チェックはエラー発生時には警告を表示して終了します。次に、kubeadm init
はクラスターのコントロールプレーンのコンポーネントをダウンロードしてインストールします。これには数分掛かるかもしれません。出力は次のようになります。
[init] Using Kubernetes version: vX.Y.Z
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1]
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubeadm-cp kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.138.0.4]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 31.501735 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-X.Y" in namespace kube-system with the configuration for the kubelets in the cluster
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "kubeadm-cp" as an annotation
[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: <token>
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
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:
/ja/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以外のユーザーでも実行できるようにするには、次のコマンドを実行します。これらのコマンドは、kubectl 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
が出力した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を使用してください)
-
デフォルトでは、kubeadm
はRBAC(role based access control)の使用を強制します。PodネットワークプラグインがRBACをサポートしていて、またそのデプロイに使用するマニフェストもRBACをサポートしていることを確認してください。
-
クラスターでIPv6を使用したい場合、デュアルスタック、IPv6のみのシングルスタックのネットワークのいずれであっても、PodネットワークプラグインがIPv6をサポートしていることを確認してください。IPv6のサポートは、CNIのv0.6.0で追加されました。
備考:
現在、Calicoはkubeadmプロジェクトがe2eテストを実施している唯一のCNIプラグインです。
もしCNIプラグインに関する問題を見つけた場合、kubeadmやkubernetesではなく、そのCNIプラグインの課題管理システムへ問題を報告してください。
CNIを使用するKubernetes Podネットワークを提供する外部のプロジェクトがいくつかあります。一部のプロジェクトでは、ネットワークポリシーもサポートしています。
Kubernetesのネットワークモデルを実装したアドオンの一覧も確認してください。
Podネットワークアドオンをインストールするには、コントロールプレーンノード上またはkubeconfigクレデンシャルを持っているノード上で、次のコマンドを実行します。
kubectl apply -f <add-on.yaml>
インストールできるPodネットワークは、クラスターごとに1つだけです。
Podネットワークがインストールされたら、kubectl get pods --all-namespaces
の出力結果でCoreDNS PodがRunning
状態であることをチェックすることで、ネットワークが動作していることを確認できます。そして、一度CoreDNS Podが動作すれば、続けてノードを追加できます。
もしネットワークやCoreDNSがRunning
状態にならない場合は、kubeadm
のトラブルシューティングガイドをチェックしてください。
コントロールプレーンノードの隔離
デフォルトでは、セキュリティ上の理由により、クラスターはコントロールプレーンノードにPodをスケジューリングしません。たとえば、開発用のKubernetesシングルマシンのクラスターなどで、Podをコントロールプレーンノードにスケジューリングしたい場合は、次のコマンドを実行します。
kubectl taint nodes --all node-role.kubernetes.io/master-
出力は次のようになります。
node "test-01" untainted
taint "node-role.kubernetes.io/master:" not found
taint "node-role.kubernetes.io/master:" not found
このコマンドは、コントロールプレーンノードを含むすべてのノードからnode-role.kubernetes.io/master
taintを削除します。その結果、スケジューラーはどこにでもPodをスケジューリングできるようになります。
ノードの追加
ノードは、ワークロード(コンテナやPodなど)が実行される場所です。新しいノードをクラスターに追加するためには、各マシンに対して、以下の手順を実行してください。
- マシンへSSHする
- rootになる(例:
sudo su -
)
kubeadm init
実行時に出力されたコマンドを実行する。たとえば、次のようなコマンドです。
kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
トークンがわからない場合は、コントロールプレーンノードで次のコマンドを実行すると取得できます。
出力は次のようになります。
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
8ewj1p.9r9hcjoqgajrj4gi 23h 2018-06-12T02:51:28Z authentication, The default bootstrap system:
signing token generated by bootstrappers:
'kubeadm init'. kubeadm:
default-node-token
デフォルトでは、トークンは24時間後に有効期限が切れます。もし現在のトークンの有効期限が切れた後にクラスターにノードを参加させたい場合は、コントロールプレーンノードで次のコマンドを実行することで、新しいトークンを生成できます。
このコマンドの出力は次のようになります。
もし--discovery-token-ca-cert-hash
の値がわからない場合は、コントロールプレーンノード上で次のコマンドチェーンを実行することで取得できます。
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
出力は次のようになります。
8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78
備考:
IPv6タプルを<control-plane-host>:<control-plane-port>
と指定するためには、IPv6アドレスを角括弧で囲みます。たとえば、[fd00::101]:2073
のように書きます。
出力は次のようになります。
[preflight] Running pre-flight checks
... (joinワークフローのログ出力) ...
Node join complete:
* Certificate signing request sent to control-plane and response
received.
* Kubelet informed of new secure connection details.
Run 'kubectl get nodes' on control-plane to see this machine join.
数秒後、コントロールプレーンノード上でkubectl get nodes
を実行すると、出力内にこのノードが表示されるはずです。
(オプション)コントロールプレーンノード以外のマシンからのクラスター操作
他のコンピューター(例: ラップトップ)上のkubectlがクラスターと通信できるようにするためには、次のようにして、administratorの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-local-data --force --ignore-daemonsets
ノードが削除される前に、kubeadm
によってインストールされた状態をリセットします。
リセットプロセスでは、iptablesのルールやIPVS tablesのリセットやクリーンアップは行われません。iptablesをリセットしたい場合は、次のように手動でコマンドを実行する必要があります。
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
IPVS tablesをリセットしたい場合は、次のコマンドを実行する必要があります。
ノードを削除します。
kubectl delete node <node name>
クラスターのセットアップを最初から始めたいときは、kubeadm init
やkubeadm join
を適切な引数を付けて実行すればいいだけです。
コントロールプレーンのクリーンアップ
コントロールホスト上でkubeadm reset
を実行すると、ベストエフォートでのクリーンアップが実行できます。
このサブコマンドとオプションに関するより詳しい情報は、kubeadm reset
リファレンスドキュメントを読んでください。
次の手順
フィードバック
バージョン互換ポリシー
バージョンv1.31のkubeadm
ツールは、バージョンv1.31またはv1.30のコントロールプレーンを持つクラスターをデプロイできます。また、バージョンv1.31のkubeadm
は、バージョンv1.30のkubeadmで構築されたクラスターをアップグレートできます。
未来を見ることはできないため、kubeadm CLI v1.31はv1.32をデプロイできないかもしれません。
例: kubeadm
v1.8は、v1.7とv1.8のクラスターをデプロイでき、v1.7のkubeadmで構築されたクラスターをv1.8にアップグレートできます。
kubeletとコントロールプレーンの間や、他のKubernetesコンポーネント間のバージョンの差異に関する詳しい情報は、以下の資料を確認してください。
制限事項
クラスターのレジリエンス
ここで作られたクラスターは、1つのコントロールプレーンノードと、その上で動作する1つのetcdデータベースしか持ちません。つまり、コントロールプレーンノードが故障した場合、クラスターのデータは失われ、クラスターを最初から作り直す必要があるかもしれないということです。
対処方法:
kubeadmのdeb/rpmパッケージおよびバイナリは、multi-platform proposalに従い、amd64、arm(32ビット)、arm64、ppc64le、およびs390x向けにビルドされています。
マルチプラットフォームのコントロールプレーンおよびアドオン用のコンテナイメージも、v1.12からサポートされています。
すべてのプラットフォーム向けのソリューションを提供しているネットワークプロバイダーは一部のみです。それぞれのプロバイダーが選択したプラットフォームをサポートしているかどうかを確認するには、前述のネットワークプロバイダーのリストを参照してください。
トラブルシューティング
kubeadmに関する問題が起きたときは、トラブルシューティングドキュメントを確認してください。
2.1.4 - kubeadmを使ったコントロールプレーンの設定のカスタマイズ
FEATURE STATE: Kubernetes 1.12 [stable]
kubeadmのClusterConfiguration
オブジェクトはAPIServer、ControllerManager、およびSchedulerのようなコントロールプレーンの構成要素に渡されたデフォルトのフラグを上書きすることができる extraArgs
の項目があります。
その構成要素は次の項目で定義されています。
apiServer
controllerManager
scheduler
extraArgs
の項目は キー: 値
のペアです。コントロールプレーンの構成要素のフラグを上書きするには:
- 設定内容に適切な項目を追加
- フラグを追加して項目を上書き
--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.1.5 - 高可用性トポロジーのためのオプション
このページでは、高可用性(HA)Kubernetesクラスターのトポロジーを設定するための2つのオプションについて説明します。
HAクラスターは次の方法で設定できます。
- 積層コントロールプレーンノードを使用する方法。こちらの場合、etcdノードはコントロールプレーンノードと同じ場所で動作します。
- 外部のetcdノードを使用する方法。こちらの場合、etcdがコントロールプレーンとは分離されたノードで動作します。
HAクラスターをセットアップする前に、各トポロジーの利点と欠点について注意深く考慮する必要があります。
備考:
kubeadmは、etcdクラスターを静的にブートストラップします。
詳細については、etcd
クラスタリングガイドをご覧ください。
積層etcdトポロジー
積層HAクラスターは、コントロールプレーンのコンポーネントを実行する、kubeadmで管理されたノードで構成されるクラスターの上に、etcdにより提供される分散データストレージクラスターがあるようなトポロジーです。
各コントロールプレーンノードは、kube-apiserver
、kube-scheduler
、およびkube-controller-manager
を実行します。kube-apiserver
はロードバランサーを用いてワーカーノードに公開されます。
各コントロールプレーンノードはローカルのetcdメンバーを作り、このetcdメンバーはそのノードのkube-apiserver
とだけ通信します。ローカルのkube-controller-manager
とkube-scheduler
のインスタンスも同様です。
このトポロジーは、同じノード上のコントロールプレーンとetcdのメンバーを結合します。外部のetcdノードを使用するクラスターよりはセットアップがシンプルで、レプリケーションの管理もシンプルです。
しかし、積層クラスターには、結合による故障のリスクがあります。1つのノードがダウンすると、etcdメンバーとコントロールプレーンのインスタンスの両方が失われ、冗長性が損なわれます。より多くのコントロールプレーンノードを追加することで、このリスクは緩和できます。
そのため、HAクラスターのためには、最低でも3台の積層コントロールプレーンノードを実行しなければなりません。
これがkubeadmのデフォルトのトポロジーです。kubeadm init
やkubeadm join --control-place
を実行すると、ローカルのetcdメンバーがコントロールプレーンノード上に自動的に作成されます。
外部のetcdトポロジー
外部のetcdを持つHAクラスターは、コントロールプレーンコンポーネントを実行するノードで構成されるクラスターの外部に、etcdにより提供される分散データストレージクラスターがあるようなトポロジーです。
積層etcdトポロジーと同様に、外部のetcdトポロジーにおける各コントロールプレーンノードは、kube-apiserver
、kube-scheduler
、およびkube-controller-manager
のインスタンスを実行します。そして、kube-apiserver
は、ロードバランサーを使用してワーカーノードに公開されます。しかし、etcdメンバーは異なるホスト上で動作しており、各etcdホストは各コントロールプレーンノードのkube-api-server
と通信します。
このトポロジーは、コントロールプレーンとetcdメンバーを疎結合にします。そのため、コントロールプレーンインスタンスまたはetcdメンバーを失うことによる影響は少なく、積層HAトポロジーほどクラスターの冗長性に影響しないHAセットアップが実現します。
しかし、このトポロジーでは積層HAトポロジーの2倍の数のホストを必要とします。このトポロジーのHAクラスターのためには、最低でもコントロールプレーンのために3台のホストが、etcdノードのために3台のホストがそれぞれ必要です。
次の項目
2.1.6 - kubeadmを使用した高可用性クラスターの作成
このページでは、kubeadmを使用して、高可用性クラスターを作成する、2つの異なるアプローチを説明します:
- 積層コントロールプレーンノードを使う方法。こちらのアプローチは、必要なインフラストラクチャーが少ないです。etcdのメンバーと、コントロールプレーンノードは同じ場所に置かれます。
- 外部のetcdクラスターを使う方法。こちらのアプローチには、より多くのインフラストラクチャーが必要です。コントロールプレーンノードと、etcdのメンバーは分離されます。
先へ進む前に、どちらのアプローチがアプリケーションの要件と、環境に適合するか、慎重に検討してください。こちらの比較が、それぞれの利点/欠点について概説しています。
高可用性クラスターの作成で問題が発生した場合は、kueadmのissue trackerでフィードバックを提供してください。
高可用性クラスターのアップグレードも参照してください。
注意:
このページはクラウド上でクラスターを構築することには対応していません。ここで説明されているどちらのアプローチも、クラウド上で、LoadBalancerタイプのServiceオブジェクトや、動的なPersistentVolumeを利用して動かすことはできません。
始める前に
どちらの方法でも、以下のインフラストラクチャーが必要です:
- master用に、kubeadmの最小要件を満たす3台のマシン
- worker用に、kubeadmの最小要件を満たす3台のマシン
- クラスター内のすべてのマシン間がフルにネットワーク接続可能であること(パブリック、もしくはプライベートネットワーク)
- すべてのマシンにおいて、sudo権限
- あるデバイスから、システム内のすべてのノードに対しSSH接続できること
kubeadm
とkubelet
がすべてのマシンにインストールされていること。 kubectl
は任意です。
外部etcdクラスターには、以下も必要です:
両手順における最初のステップ
kube-apiserver用にロードバランサーを作成
備考:
ロードバランサーには多くの設定項目があります。以下の例は、一選択肢に過ぎません。あなたのクラスター要件には、異なった設定が必要かもしれません。
-
DNSで解決される名前で、kube-apiserver用ロードバランサーを作成する。
-
クラウド環境では、コントロールプレーンノードをTCPフォワーディングロードバランサーの後ろに置かなければなりません。このロードバランサーはターゲットリストに含まれる、すべての健全なコントロールプレーンノードにトラフィックを分配します。apiserverへのヘルスチェックはkube-apiserverがリッスンするポート(デフォルト値: :6443
)に対する、TCPチェックです。
-
クラウド環境では、IPアドレスを直接使うことは推奨されません。
-
ロードバランサーは、apiserverポートで、全てのコントロールプレーンノードと通信できなければなりません。また、リスニングポートに対する流入トラフィックも許可されていなければなりません。
-
ロードバランサーのアドレスは、常にkubeadmのControlPlaneEndpoint
のアドレスと一致することを確認してください。
-
詳細はOptions for Software Load Balancingをご覧ください。
-
ロードバランサーに、最初のコントロールプレーンノードを追加し、接続をテストする:
nc -v LOAD_BALANCER_IP PORT
- apiserverはまだ動いていないので、接続の拒否は想定通りです。しかし、タイムアウトしたのであれば、ロードバランサーはコントロールプレーンノードと通信できなかったことを意味します。もし、タイムアウトが起きたら、コントロールプレーンノードと通信できるように、ロードバランサーを再設定してください。
-
残りのコントロールプレーンノードを、ロードバランサーのターゲットグループに追加します。
積層コントロールプレーンとetcdノード
最初のコントロールプレーンノードの手順
-
最初のコントロールプレーンノードを初期化します:
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
フィールドを適切な場所に追加する必要があります(
InitConfiguration
と
JoinConfiguration: controlPlane
の配下)。
備考:
いくつかのCNIネットワークプラグインはPodのIPのCIDRの指定など追加の設定を必要としますが、必要としないプラグインもあります。
CNIネットワークドキュメントを参照してください。PodにCIDRを設定するには、
ClusterConfiguration
の
networking
オブジェクトに
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時間で期限切れとなります。
注意:
コマンド出力に記載されているように、証明書キーはクラスターの機密データへのアクセスを提供します。秘密にしてください!
-
使用するCNIプラグインを適用します:
こちらの手順に従いCNIプロバイダーをインストールします。該当する場合は、kubeadmの設定で指定されたPodのCIDRに対応していることを確認してください。
Weave Netを使用する場合の例:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
-
以下のコマンドを入力し、コンポーネントのPodが起動するのを確認します:
kubectl get pod -n kube-system -w
残りのコントロールプレーンノードの手順
備考:
kubeadmバージョン1.15以降、複数のコントロールプレーンノードを並行してクラスターに参加させることができます。
このバージョンの前は、最初のノードの初期化が完了した後でのみ、新しいコントロールプレーンノードを順番にクラスターに参加させる必要があります。
追加のコントロールプレーンノード毎に、以下の手順を行います。
-
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クラスターの構築
-
こちらの手順にしたがって、etcdクラスターを構築してください。
-
こちらの手順にしたがって、SSHを構築してください。
-
以下のファイルをクラスター内の任意の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
で置き換えます。
最初のコントロールプレーンノードの構築
-
以下の内容で、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トポロジーの場合、これは自動で管理されます。
以下の手順は、積層etcdの構築と同様です。
-
sudo kubeadm init --config kubeadm-config.yaml --upload-certs
をこのノードで実行します。
-
表示されたjoinコマンドを、あとで使うためにテキストファイルに書き込みます。
-
使用する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
を実行しない場合、プライマリコントロールプレーンノードから他のコントロールプレーンノードへ証明書を手動でコピーする必要があります。
コピーを行うには多くの方法があります。次の例ではssh
とscp
を使用しています。
1台のマシンから全てのノードをコントロールしたいのであれば、SSHが必要です。
-
システム内の全ての他のノードにアクセスできるメインデバイスで、ssh-agentを有効にします
eval $(ssh-agent)
-
SSHの秘密鍵を、セッションに追加します:
ssh-add ~/.ssh/path_to_private_key
-
正常に接続できることを確認するために、ノード間でSSHします。
-
全てのノードで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がないため、追加ノードの作成は失敗するかもしれません。
-
次に、クラスターに参加させる残りの各コントロールプレーンノードで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.1.7 - kubeadmを使用した高可用性etcdクラスターの作成
備考:
While kubeadm is being used as the management tool for external etcd nodes
in this guide, please note that kubeadm does not plan to support certificate rotation
or upgrades for such nodes. The long term plan is to empower the tool
etcdadm to manage these
aspects.
Kubeadm defaults to running a single member etcd cluster in a static pod managed
by the kubelet on the control plane node. This is not a high availability setup
as the etcd cluster contains only one member and cannot sustain any members
becoming unavailable. This task walks through the process of creating a high
availability etcd cluster of three members that can be used as an external etcd
when using kubeadm to set up a kubernetes cluster.
始める前に
- Three hosts that can talk to each other over ports 2379 and 2380. This
document assumes these default ports. However, they are configurable through
the kubeadm config file.
- Each host must have docker, kubelet, and kubeadm installed.
- Each host should have access to the Kubernetes container image registry (
registry.k8s.io
) or list/pull the required etcd image using kubeadm config images list/pull
. This guide will setup etcd instances as static pods managed by a kubelet.
- Some infrastructure to copy files between hosts. For example
ssh
and scp
can satisfy this requirement.
クラスターの構築
The general approach is to generate all certs on one node and only distribute
the necessary files to the other nodes.
備考:
kubeadm contains all the necessary cryptographic machinery to generate
the certificates described below; no other cryptographic tooling is required for
this example.
-
Configure the kubelet to be a service manager for etcd.
Since etcd was created first, you must override the service priority by creating a new unit file
that has higher precedence than the kubeadm-provided kubelet unit file.
cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
# Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs".
ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd
Restart=always
EOF
systemctl daemon-reload
systemctl restart kubelet
-
Create configuration files for kubeadm.
Generate one kubeadm configuration file for each host that will have an etcd
member running on it using the following script.
# Update HOST0, HOST1, and HOST2 with the IPs or resolvable names of your hosts
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8
# Create temp directories to store files that will end up on other hosts.
mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/
ETCDHOSTS=(${HOST0} ${HOST1} ${HOST2})
NAMES=("infra0" "infra1" "infra2")
for i in "${!ETCDHOSTS[@]}"; do
HOST=${ETCDHOSTS[$i]}
NAME=${NAMES[$i]}
cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
apiVersion: "kubeadm.k8s.io/v1beta2"
kind: ClusterConfiguration
etcd:
local:
serverCertSANs:
- "${HOST}"
peerCertSANs:
- "${HOST}"
extraArgs:
initial-cluster: ${NAMES[0]}=https://${ETCDHOSTS[0]}:2380,${NAMES[1]}=https://${ETCDHOSTS[1]}:2380,${NAMES[2]}=https://${ETCDHOSTS[2]}:2380
initial-cluster-state: new
name: ${NAME}
listen-peer-urls: https://${HOST}:2380
listen-client-urls: https://${HOST}:2379
advertise-client-urls: https://${HOST}:2379
initial-advertise-peer-urls: https://${HOST}:2380
EOF
done
-
Generate the certificate authority
If you already have a CA then the only action that is copying the CA's crt
and
key
file to /etc/kubernetes/pki/etcd/ca.crt
and
/etc/kubernetes/pki/etcd/ca.key
. After those files have been copied,
proceed to the next step, "Create certificates for each member".
If you do not already have a CA then run this command on $HOST0
(where you
generated the configuration files for kubeadm).
kubeadm init phase certs etcd-ca
This creates two files
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
-
Create certificates for each member
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}/
# cleanup non-reusable certificates
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
# No need to move the certs because they are for HOST0
# clean up certs that should not be copied off this host
find /tmp/${HOST2} -name ca.key -type f -delete
find /tmp/${HOST1} -name ca.key -type f -delete
-
Copy certificates and kubeadm configs
The certificates have been generated and now they must be moved to their
respective hosts.
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/
-
Ensure all expected files exist
The complete list of required files on $HOST0
is:
/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
On $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
On $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
-
Create the static pod manifests
Now that the certificates and configs are in place it's time to create the
manifests. On each host run the kubeadm
command to generate a static manifest
for etcd.
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
-
Optional: Check the cluster health
docker run --rm -it \
--net host \
-v /etc/kubernetes:/etc/kubernetes registry.k8s.io/etcd:${ETCD_TAG} 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 --cluster
...
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
- Set
${ETCD_TAG}
to the version tag of your etcd image. For example 3.4.3-0
. To see the etcd image and tag that kubeadm uses execute kubeadm config images list --kubernetes-version ${K8S_VERSION}
, where ${K8S_VERSION}
is for example v1.17.0
- Set
${HOST0}
to the IP address of the host you are testing.
次の項目
Once you have a working 3 member etcd cluster, you can continue setting up a
highly available control plane using the external etcd method with
kubeadm.
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は一元的な設定管理のためのKubeletConfiguration
APIを提供しています。
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 ... --config some-config-file.yaml
のように、カスタムのKubeletConfiguration
APIオブジェクトを設定ファイルを介して渡すことで、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/kubeadm CLIツールと、kubelet用のsystemdファイルをインストールします。 |
kubelet |
kubeletバイナリを/usr/bin に、CNIバイナリを/opt/cni/bin にインストールします。 |
kubectl |
/usr/bin/kubectl バイナリをインストールします。 |
cri-tools |
/usr/bin/crictl バイナリをcri-tools gitリポジトリからインストールします。 |
2.1.9 - コントロールプレーンをセルフホストするようにkubernetesクラスターを構成する
コントロールプレーンのセルフホスティング
kubeadmを使用すると、セルフホスト型のKubernetesコントロールプレーンを実験的に作成できます。これはAPIサーバー、コントローラーマネージャー、スケジューラーなどの主要コンポーネントは、静的ファイルを介してkubeletで構成されたstatic podsではなく、Kubernetes APIを介して構成されたDaemonSet podsとして実行されることを意味します。
セルフホスト型クラスターを作成する場合はkubeadm alpha selfhosting pivotを参照してください。
警告
注意:
この機能により、クラスターがサポートされていない状態になり、kubeadmがクラスターを管理できなくなります。これにはkubeadm upgrade
が含まれます。
-
1.8以降のセルフホスティングには、いくつかの重要な制限があります。特に、セルフホスト型クラスターは、手動の介入なしにコントロールプレーンのNode再起動から回復することはできません。
-
デフォルトでは、セルフホスト型のコントロールプレーンのPodは、hostPath
ボリュームからロードされた資格情報に依存しています。最初の作成を除いて、これらの資格情報はkubeadmによって管理されません。
-
コントロールプレーンのセルフホストされた部分にはetcdが含まれていませんが、etcdは静的Podとして実行されます。
プロセス
セルフホスティングのブートストラッププロセスは、kubeadm design
documentに記載されています。
要約すると、kubeadm alpha selfhosting
は次のように機能します。
-
静的コントロールプレーンのブートストラップが起動し、正常になるのを待ちます。これはkubeadm init
のセルフホスティングを使用しないプロセスと同じです。
-
静的コントロールプレーンのPodのマニフェストを使用して、セルフホスト型コントロールプレーンを実行する一連のDaemonSetのマニフェストを構築します。また、必要に応じてこれらのマニフェストを変更します。たとえば、シークレット用の新しいボリュームを追加します。
-
kube-system
のネームスペースにDaemonSetを作成し、Podの結果が起動されるのを待ちます。
-
セルフホスト型のPodが操作可能になると、関連する静的Podが削除され、kubeadmは次のコンポーネントのインストールに進みます。これによりkubeletがトリガーされて静的Podが停止します。
-
元の静的なコントロールプレーンが停止すると、新しいセルフホスト型コントロールプレーンはリスニングポートにバインドしてアクティブになります。
2.2 - kopsを使ったAWS上でのKubernetesのインストール
This quickstart shows you how to easily install a Kubernetes cluster on AWS.
It uses a tool called kops
.
kops is an automated provisioning system:
- Fully automated installation
- Uses DNS to identify clusters
- Self-healing: everything runs in Auto-Scaling Groups
- Multiple OS support (Debian, Ubuntu 16.04 supported, CentOS & RHEL, Amazon Linux and CoreOS) - see the images.md
- High-Availability support - see the high_availability.md
- Can directly provision, or generate terraform manifests - see the terraform.md
始める前に
クラスターの作成
(1/5) kopsのインストール
インストール
Download kops from the releases page (it is also easy to build from source):
Download the latest release with the command:
curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-darwin-amd64
To download a specific version, replace the following portion of the command with the specific kops version.
$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)
For example, to download kops version v1.20.0 type:
curl -LO https://github.com/kubernetes/kops/releases/download/v1.20.0/kops-darwin-amd64
Make the kops binary executable.
chmod +x kops-darwin-amd64
Move the kops binary in to your PATH.
sudo mv kops-darwin-amd64 /usr/local/bin/kops
You can also install kops using Homebrew.
brew update && brew install kops
Download the latest release with the command:
curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
To download a specific version of kops, replace the following portion of the command with the specific kops version.
$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)
For example, to download kops version v1.20.0 type:
curl -LO https://github.com/kubernetes/kops/releases/download/v1.20.0/kops-linux-amd64
Make the kops binary executable
chmod +x kops-linux-amd64
Move the kops binary in to your PATH.
sudo mv kops-linux-amd64 /usr/local/bin/kops
You can also install kops using Homebrew.
brew update && brew install kops
(2/5) クラスター用のroute53ドメインの作成
kops uses DNS for discovery, both inside the cluster and outside, so that you can reach the kubernetes API server
from clients.
kops has a strong opinion on the cluster name: it should be a valid DNS name. By doing so you will
no longer get your clusters confused, you can share clusters with your colleagues unambiguously,
and you can reach them without relying on remembering an IP address.
You can, and probably should, use subdomains to divide your clusters. As our example we will use
useast1.dev.example.com
. The API server endpoint will then be api.useast1.dev.example.com
.
A Route53 hosted zone can serve subdomains. Your hosted zone could be useast1.dev.example.com
,
but also dev.example.com
or even example.com
. kops works with any of these, so typically
you choose for organization reasons (e.g. you are allowed to create records under dev.example.com
,
but not under example.com
).
Let's assume you're using dev.example.com
as your hosted zone. You create that hosted zone using
the normal process, or
with a command such as aws route53 create-hosted-zone --name dev.example.com --caller-reference 1
.
You must then set up your NS records in the parent domain, so that records in the domain will resolve. Here,
you would create NS records in example.com
for dev
. If it is a root domain name you would configure the NS
records at your domain registrar (e.g. example.com
would need to be configured where you bought example.com
).
This step is easy to mess up (it is the #1 cause of problems!) You can double-check that
your cluster is configured correctly if you have the dig tool by running:
dig NS dev.example.com
You should see the 4 NS records that Route53 assigned your hosted zone.
(3/5) クラスターの状態を保存するS3バケットの作成
kops lets you manage your clusters even after installation. To do this, it must keep track of the clusters
that you have created, along with their configuration, the keys they are using etc. This information is stored
in an S3 bucket. S3 permissions are used to control access to the bucket.
Multiple clusters can use the same S3 bucket, and you can share an S3 bucket between your colleagues that
administer the same clusters - this is much easier than passing around kubecfg files. But anyone with access
to the S3 bucket will have administrative access to all your clusters, so you don't want to share it beyond
the operations team.
So typically you have one S3 bucket for each ops team (and often the name will correspond
to the name of the hosted zone above!)
In our example, we chose dev.example.com
as our hosted zone, so let's pick clusters.dev.example.com
as
the S3 bucket name.
-
Export AWS_PROFILE
(if you need to select a profile for the AWS CLI to work)
-
Create the S3 bucket using aws s3 mb s3://clusters.dev.example.com
-
You can export KOPS_STATE_STORE=s3://clusters.dev.example.com
and then kops will use this location by default.
We suggest putting this in your bash profile or similar.
(4/5) クラスター設定の構築
Run kops create cluster
to create your cluster configuration:
kops create cluster --zones=us-east-1c useast1.dev.example.com
kops will create the configuration for your cluster. Note that it only creates the configuration, it does
not actually create the cloud resources - you'll do that in the next step with a kops update cluster
. This
give you an opportunity to review the configuration or change it.
It prints commands you can use to explore further:
- List your clusters with:
kops get cluster
- Edit this cluster with:
kops edit cluster useast1.dev.example.com
- Edit your node instance group:
kops edit ig --name=useast1.dev.example.com nodes
- Edit your master instance group:
kops edit ig --name=useast1.dev.example.com master-us-east-1c
If this is your first time using kops, do spend a few minutes to try those out! An instance group is a
set of instances, which will be registered as kubernetes nodes. On AWS this is implemented via auto-scaling-groups.
You can have several instance groups, for example if you wanted nodes that are a mix of spot and on-demand instances, or
GPU and non-GPU instances.
(5/5) AWSにクラスターを作成
Run "kops update cluster" to create your cluster in AWS:
kops update cluster useast1.dev.example.com --yes
That takes a few seconds to run, but then your cluster will likely take a few minutes to actually be ready.
kops update cluster
will be the tool you'll use whenever you change the configuration of your cluster; it
applies the changes you have made to the configuration to your cluster - reconfiguring AWS or kubernetes as needed.
For example, after you kops edit ig nodes
, then kops update cluster --yes
to apply your configuration, and
sometimes you will also have to kops rolling-update cluster
to roll out the configuration immediately.
Without --yes
, kops update cluster
will show you a preview of what it is going to do. This is handy
for production clusters!
他のアドオンの参照
See the list of add-ons to explore other add-ons, including tools for logging, monitoring, network policy, visualization, and control of your Kubernetes cluster.
クリーンアップ
- To delete your cluster:
kops delete cluster useast1.dev.example.com --yes
次の項目
2.3 - kubesprayを使ったKubernetesのインストール
このクイックスタートは、Kubesprayを使用して、GCE、Azure、OpenStack、AWS、vSphere、Equinix Metal(以前のPacket)、Oracle Cloud Infrastructure(実験的)またはベアメタルにホストされたKubernetesクラスターをインストールするためのものです。
Kubesprayは、汎用的なOSやKubernetesクラスターの構成管理タスクのためのAnsibleプレイブック、インベントリー、プロビジョニングツール、ドメインナレッジをまとめたものです。
Kubesprayは次を提供します:
- 高可用性クラスター。
- 構成可能(例えばネットワークプラグインの選択)。
- 最もポピュラーなLinuxディストリビューションのサポート:
- Flatcar Container Linux by Kinvolk
- Debian Bullseye, Buster, Jessie, Stretch
- Ubuntu 16.04, 18.04, 20.04, 22.04
- CentOS/RHEL 7, 8, 9
- Fedora 35, 36
- Fedora CoreOS
- openSUSE Leap 15.x/Tumbleweed
- Oracle Linux 7, 8, 9
- Alma Linux 8, 9
- Rocky Linux 8, 9
- Kylin Linux Advanced Server V10
- Amazon Linux 2
- 継続的インテグレーションテスト。
あなたのユースケースに最適なツールの選択には、kubeadmやkopsと比較したドキュメントを参照してください。
クラスターの作成
(1/5) 下地の要件の確認
次の要件に従ってサーバーをプロビジョニングします:
- Kubernetesの最低必要バージョンはv1.22
- Ansibleのコマンドを実行するマシン上にAnsible v2.11+、Jinja 2.11+とpython-netaddrがインストールされていること
- ターゲットサーバーはdockerイメージをpullするためにインターネットにアクセスできる必要があります。そうでは無い場合は追加の構成が必要です(オフライン環境を参照)
- ターゲットのサーバーはIPv4フォワーディングができるように構成されていること。
- PodとServiceにIPv6を使用している場合は、ターゲットサーバーはIPv6フォワーディングができるように構成されていること。
- ファイアウォールは管理されないため、従来のように独自のルールを実装しなければなりません。デプロイ中の問題を避けるためには、ファイアウォールを無効にすべきです
- root以外のユーザーアカウントでkubesprayを実行する場合は、ターゲットサーバー上で特権昇格の方法を正しく構成されている必要があります。そして、
ansible_become
フラグ、またはコマンドパラメーター--become
、-b
を指定する必要があります
Kubesprayは環境のプロビジョニングを支援するために次のユーティリティを提供します:
(2/5) インベントリーファイルの用意
サーバーをプロビジョニングした後、Ansibleのインベントリーファイルを作成します。これは手動またはダイナミックインベントリースクリプトによって行うことができます。詳細については、"独自のインベントリーを構築する"を参照してください。
(3/5) クラスター作成の計画
Kubesprayは多くの点でデプロイメントをカスタマイズする機能を提供します:
- デプロイメントモードの選択: kubeadmまたはnon-kubeadm
- CNI(ネットワーク)プラグイン
- DNS設定
- コントロールプレーンの選択: ネイティブ/バイナリまたはコンテナ化
- コンポーネントバージョン
- Calicoルートリフレクター
- コンポーネントランタイムオプション
- 証明書の生成方法
Kubesprayはvariableファイルによってカスタマイズできます。Kubesprayを使い始めたばかりであれば、Kubesprayのデフォルト設定を使用してクラスターをデプロイし、Kubernetesを探索することを検討してください。
(4/5) クラスターのデプロイ
次にクラスターをデプロイします:
クラスターのデプロイメントにはansible-playbookを使用します。
ansible-playbook -i your/inventory/inventory.ini cluster.yml -b -v \
--private-key=~/.ssh/private_key
大規模なデプロイメント(100以上のノード)では、最適な結果を得るために個別の調整が必要な場合があります。
(5/5) デプロイの確認
Kubesprayは、NetcheckerによるPod間の接続とDNSの解決の検証を行う機能を提供します。Netcheckerは、netchecker-agents Podがdefault名前空間内でDNSリクエストを解決し、互いにpingを送信できることを確かめます。これらのPodは他のワークロードと同様の動作を再現し、クラスターの健全性を示す指標として機能します。
クラスターの操作
Kubesprayはクラスターを管理する追加のプレイブックを提供します: scale と upgrade。
クラスターのスケール
scaleプレイブックを実行することで、クラスターにワーカーノードを追加することができます。詳細については、"ノードの追加"を参照してください。
remove-nodeプレイブックを実行することで、クラスターからワーカーノードを削除することができます。詳細については、"ノードの削除"を参照してください。
クラスターのアップグレード
upgrade-clusterプレイブックを実行することで、クラスターのアップグレードができます。詳細については、"アップグレード"を参照してください。
クリーンアップ
resetプレイブックを使用して、ノードをリセットし、Kubesprayでインストールした全てのコンポーネントを消すことができます。
注意:
resetプレイブックを実行する際は、誤ってプロダクションのクラスターを対象にしないように気をつけること!
フィードバック
次の項目
3 - ターンキークラウドソリューション
このページは、Kubernetes認定ソリューションプロバイダーのリストを提供します。
各プロバイダーのページから、本番環境でも利用可能なクラスターのインストール方法やセットアップ方法を学ぶことができます。
4 - Windows in Kubernetes
4.1 - KubernetesのWindowsサポート概要
Windowsアプリケーションは、多くの組織で実行されているサービスやアプリケーションの大部分を占めています。Windowsコンテナは、プロセスとパッケージの依存関係を一つにまとめる最新の方法を提供し、DevOpsプラクティスの使用とWindowsアプリケーションのクラウドネイティブパターンの追求を容易にします。Kubernetesは事実上、標準的なコンテナオーケストレータになりました。Kubernetes 1.14のリリースでは、Kubernetesクラスター内のWindowsノードでWindowsコンテナをスケジューリングする本番環境サポートが含まれたので、Windowsアプリケーションの広大なエコシステムにおいて、Kubernetesを有効的に活用できます。WindowsベースのアプリケーションとLinuxベースのアプリケーションに投資している組織は、ワークロードを管理する個別のオーケストレーターが不要となるため、オペレーティングシステムに関係なくアプリケーション全体の運用効率が向上します。
KubernetesのWindowsコンテナ
KubernetesでWindowsコンテナのオーケストレーションを有効にする方法は、既存のLinuxクラスターにWindowsノードを含めるだけです。KubernetesのPodでWindowsコンテナをスケジュールすることは、Linuxベースのコンテナをスケジュールするのと同じくらいシンプルで簡単です。
Windowsコンテナを実行するには、Kubernetesクラスターに複数のオペレーティングシステムを含める必要があります。コントロールプレーンノードはLinux、ワーカーノードはワークロードのニーズに応じてWindowsまたはLinuxで実行します。Windows Server 2019は、サポートされている唯一のWindowsオペレーティングシステムであり、Windows (kubelet、コンテナランタイム、kube-proxyを含む)でKubernetesノードを有効にします。Windowsディストリビューションチャンネルの詳細については、Microsoftのドキュメントを参照してください。
備考:
マスターコンポーネントを含むKubernetesコントロールプレーンは、Linuxで実行し続けます。WindowsのみのKubernetesクラスターを導入する計画はありません。
備考:
このドキュメントでは、Windowsコンテナについて説明する場合、プロセス分離のWindowsコンテナを意味します。
Hyper-V分離のWindowsコンテナは、将来リリースが計画されています。
サポートされている機能と制限
サポートされている機能
コンピュート
APIとkubectlの観点から見ると、WindowsコンテナはLinuxベースのコンテナとほとんど同じように動作します。ただし、制限セクションで概説されている主要な機能には、いくつかの顕著な違いがあります。
オペレーティングシステムのバージョンから始めましょう。KubernetesのWindowsオペレーティングシステムのサポートについては、次の表を参照してください。単一の混成Kubernetesクラスターは、WindowsとLinuxの両方のワーカーノードを持つことができます。WindowsコンテナはWindowsノードで、LinuxコンテナはLinuxノードでスケジュールする必要があります。
Kubernetes バージョン |
ホストOS バージョン (Kubernetes ノード) |
|
|
|
Windows Server 1709 |
Windows Server 1803 |
Windows Server 1809/Windows Server 2019 |
Kubernetes v1.14 |
サポートされていません |
サポートされていません |
Windows Server containers Builds 17763.* と Docker EE-basic 18.09 がサポートされています |
備考:
すべてのWindowsユーザーがアプリのオペレーティングシステムを頻繁に更新することは望んでいません。アプリケーションのアップグレードは、クラスターに新しいノードをアップグレードまたは導入することを要求する必要があります。Kubernetesで実行されているコンテナのオペレーティングシステムをアップグレードすることを選択したユーザーには、新しいオペレーティングシステムバージョンのサポート追加時に、ガイダンスと段階的な指示を提供します。このガイダンスには、クラスターノードと共にアプリケーションをアップグレードするための推奨アップグレード手順が含まれます。Windowsノードは、現在のLinuxノードと同じように、Kubernetes
バージョンスキューポリシー(ノードからコントロールプレーンのバージョン管理)に準拠しています。
Kubernetesの主要な要素は、WindowsでもLinuxと同じように機能します。このセクションでは、主要なワークロードイネーブラーのいくつかと、それらがWindowsにどのようにマップされるかについて説明します。
-
Pods
Podは、Kubernetesにおける最も基本的な構成要素です。人間が作成またはデプロイするKubernetesオブジェクトモデルの中で最小かつ最もシンプルな単位です。WindowsとLinuxのコンテナを同じPodにデプロイすることはできません。Pod内のすべてのコンテナは、各ノードが特定のプラットフォームとアーキテクチャを表す単一のノードにスケジュールされます。次のPod機能、プロパティ、およびイベントがWindowsコンテナでサポートされています。:
- プロセス分離とボリューム共有を備えたPodごとの単一または複数のコンテナ
- Podステータスフィールド
- ReadinessとLiveness Probe
- postStartとpreStopコンテナのライフサイクルイベント
- 環境変数またはボリュームとしてのConfigMap、 Secrets
- EmptyDir
- 名前付きパイプホストマウント
- リソース制限
-
Controllers
Kubernetesコントローラーは、Podの望ましい状態を処理します。次のワークロードコントローラーは、Windowsコンテナでサポートされています。:
- ReplicaSet
- ReplicationController
- Deployments
- StatefulSets
- DaemonSet
- Job
- CronJob
-
Services
Kubernetes Serviceは、Podの論理セットとPodにアクセスするためのポリシーを定義する抽象概念です。マイクロサービスと呼ばれることもあります。オペレーティングシステム間の接続にServiceを使用できます。WindowsでのServiceは、次のタイプ、プロパティと機能を利用できます。:
- サービス環境変数
- NodePort
- ClusterIP
- LoadBalancer
- ExternalName
- Headless services
Pod、Controller、Serviceは、KubernetesでWindowsワークロードを管理するための重要な要素です。ただし、それだけでは、動的なクラウドネイティブ環境でWindowsワークロードの適切なライフサイクル管理を可能にするのに十分ではありません。次の機能のサポートを追加しました:
- Podとコンテナのメトリクス
- Horizontal Pod Autoscalerサポート
- kubectl Exec
- リソースクォータ
- Schedulerのプリエンプション
コンテナランタイム
Docker EE
FEATURE STATE: Kubernetes v1.14 [stable]
Docker EE-basic 18.09+は、Kubernetesを実行しているWindows Server 2019 / 1809ノードに推奨されるコンテナランタイムです。kubeletに含まれるdockershimコードで動作します。
CRI-ContainerD
FEATURE STATE: Kubernetes v1.18 [alpha]
ContainerDはLinux上のKubernetesで動作するOCI準拠のランタイムです。Kubernetes v1.18では、Windows上でのContainerDのサポートが追加されています。Windows上でのContainerDの進捗状況はenhancements#1001で確認できます。
注意:
Kubernetes v1.18におけるWindows上でのContainerDは以下の既知の欠点があります:
- ContainerDは公式リリースではWindowsをサポートしていません。すなわち、Kubernetesでのすべての開発はアクティブなContainerD開発ブランチに対して行われています。本番環境へのデプロイは常に、完全にテストされセキュリティ修正をサポートした公式リリースを利用するべきです。
- ContainerDを利用した場合、Group Managed Service Accountsは実装されていません。詳細はcontainerd/cri#1276を参照してください。
永続ストレージ
Kubernetesボリュームを使用すると、データの永続性とPodボリュームの共有要件を備えた複雑なアプリケーションをKubernetesにデプロイできます。特定のストレージバックエンドまたはプロトコルに関連付けられた永続ボリュームの管理には、ボリュームのプロビジョニング/プロビジョニング解除/サイズ変更、Kubernetesノードへのボリュームのアタッチ/デタッチ、およびデータを永続化する必要があるPod内の個別のコンテナへのボリュームのマウント/マウント解除などのアクションが含まれます。特定のストレージバックエンドまたはプロトコルに対してこれらのボリューム管理アクションを実装するコードは、Kubernetesボリュームプラグインの形式で出荷されます。次の幅広いクラスのKubernetesボリュームプラグインがWindowsでサポートされています。:
In-treeボリュームプラグイン
In-treeボリュームプラグインに関連付けられたコードは、コアKubernetesコードベースの一部として提供されます。In-treeボリュームプラグインのデプロイでは、追加のスクリプトをインストールしたり、個別のコンテナ化されたプラグインコンポーネントをデプロイしたりする必要はありません。これらのプラグインは、ストレージバックエンドでのボリュームのプロビジョニング/プロビジョニング解除とサイズ変更、Kubernetesノードへのボリュームのアタッチ/アタッチ解除、Pod内の個々のコンテナへのボリュームのマウント/マウント解除を処理できます。次のIn-treeプラグインは、Windowsノードをサポートしています。:
FlexVolume Plugins
FlexVolumeプラグインに関連付けられたコードは、ホストに直接デプロイする必要があるout-of-treeのスクリプトまたはバイナリとして出荷されます。FlexVolumeプラグインは、Kubernetesノードとの間のボリュームのアタッチ/デタッチ、およびPod内の個々のコンテナとの間のボリュームのマウント/マウント解除を処理します。FlexVolumeプラグインに関連付けられた永続ボリュームのプロビジョニング/プロビジョニング解除は、通常FlexVolumeプラグインとは別の外部プロビジョニング担当者を通じて処理できます。次のFlexVolumeプラグインは、Powershellスクリプトとしてホストにデプロイされ、Windowsノードをサポートします:
CSIプラグイン
FEATURE STATE: Kubernetes v1.16 [alpha]
CSIプラグインに関連付けられたコードは、通常、コンテナイメージとして配布され、DaemonSetやStatefulSetなどの標準のKubernetesコンポーネントを使用してデプロイされるout-of-treeのスクリプトおよびバイナリとして出荷されます。CSIプラグインは、ボリュームのプロビジョニング/プロビジョニング解除/サイズ変更、Kubernetesノードへのボリュームのアタッチ/ボリュームからのデタッチ、Pod内の個々のコンテナへのボリュームのマウント/マウント解除、バックアップ/スナップショットとクローニングを使用した永続データのバックアップ/リストアといった、Kubernetesの幅広いボリューム管理アクションを処理します。CSIプラグインは通常、ノードプラグイン(各ノードでDaemonSetとして実行される)とコントローラープラグインで構成されます。
CSIノードプラグイン(特に、ブロックデバイスまたは共有ファイルシステムとして公開された永続ボリュームに関連付けられているプラグイン)は、ディスクデバイスのスキャン、ファイルシステムのマウントなど、さまざまな特権操作を実行する必要があります。これらの操作は、ホストオペレーティングシステムごとに異なります。Linuxワーカーノードの場合、コンテナ化されたCSIノードプラグインは通常、特権コンテナとしてデプロイされます。Windowsワーカーノードの場合、コンテナ化されたCSIノードプラグインの特権操作は、csi-proxyを使用してサポートされます。各Windowsノードにプリインストールされている。詳細については、展開するCSIプラグインの展開ガイドを参照してください。
ネットワーキング
Windowsコンテナのネットワークは、CNIプラグインを通じて公開されます。Windowsコンテナは、ネットワークに関して仮想マシンと同様に機能します。各コンテナには、Hyper-V仮想スイッチ(vSwitch)に接続されている仮想ネットワークアダプター(vNIC)があります。Host Network Service(HNS)とHost Compute Service(HCS)は連携してコンテナを作成し、コンテナvNICをネットワークに接続します。HCSはコンテナの管理を担当するのに対し、HNSは次のようなネットワークリソースの管理を担当します。:
- 仮想ネットワーク(vSwitchの作成を含む)
- エンドポイント/vNIC
- 名前空間
- ポリシー(パケットのカプセル化、負荷分散ルール、ACL、NATルールなど)
次のServiceタイプがサポートされています。:
- NodePort
- ClusterIP
- LoadBalancer
- ExternalName
Windowsは、L2bridge、L2tunnel、Overlay、Transparent、NATの5つの異なるネットワークドライバー/モードをサポートしています。WindowsとLinuxのワーカーノードを持つ異種クラスターでは、WindowsとLinuxの両方で互換性のあるネットワークソリューションを選択する必要があります。以下のツリー外プラグインがWindowsでサポートされており、各CNIをいつ使用するかに関する推奨事項があります。:
ネットワークドライバー |
説明 |
コンテナパケットの変更 |
ネットワークプラグイン |
ネットワークプラグインの特性 |
L2bridge |
コンテナは外部のvSwitchに接続されます。コンテナはアンダーレイネットワークに接続されますが、物理ネットワークはコンテナのMACを上り/下りで書き換えるため、MACを学習する必要はありません。コンテナ間トラフィックは、コンテナホスト内でブリッジされます。 |
MACはホストのMACに書き換えられ、IPは変わりません。 |
win-bridge、Azure-CNI、Flannelホストゲートウェイは、win-bridgeを使用します。 |
win-bridgeはL2bridgeネットワークモードを使用して、コンテナをホストのアンダーレイに接続して、最高のパフォーマンスを提供します。ノード間接続にはユーザー定義ルート(UDR)が必要です。 |
L2Tunnel |
これはl2bridgeの特殊なケースですが、Azureでのみ使用されます。すべてのパケットは、SDNポリシーが適用されている仮想化ホストに送信されます。 |
MACが書き換えられ、IPがアンダーレイネットワークで表示されます。 |
Azure-CNI |
Azure-CNIを使用すると、コンテナをAzure vNETと統合し、Azure Virtual Networkが提供する一連の機能を活用できます。たとえば、Azureサービスに安全に接続するか、Azure NSGを使用します。azure-cniのいくつかの例を参照してください。 |
オーバーレイ(KubernetesのWindows用のオーバーレイネットワークは アルファ 段階です) |
コンテナには、外部のvSwitchに接続されたvNICが付与されます。各オーバーレイネットワークは、カスタムIPプレフィックスで定義された独自のIPサブネットを取得します。オーバーレイネットワークドライバーは、VXLANを使用してカプセル化します。 |
外部ヘッダーでカプセル化されます。 |
Win-overlay、Flannel VXLAN (win-overlayを使用) |
win-overlayは、仮想コンテナネットワークをホストのアンダーレイから分離する必要がある場合に使用する必要があります(セキュリティ上の理由など)。データセンター内のIPが制限されている場合に、(異なるVNIDタグを持つ)異なるオーバーレイネットワークでIPを再利用できるようにします。このオプションには、Windows Server 2019でKB4489899が必要です。 |
透過的(ovn-kubernetesの特別な使用例) |
外部のvSwitchが必要です。コンテナは外部のvSwitchに接続され、論理ネットワーク(論理スイッチおよびルーター)を介したPod内通信を可能にします。 |
パケットは、GENEVEまたはSTTトンネリングを介してカプセル化され、同じホスト上にないポッドに到達します。パケットは、ovnネットワークコントローラーによって提供されるトンネルメタデータ情報を介して転送またはドロップされます。NATは南北通信のために行われます。 |
ovn-kubernetes |
ansible経由でデプロイします。分散ACLは、Kubernetesポリシーを介して適用できます。 IPAMをサポートします。負荷分散は、kube-proxyなしで実現できます。 NATは、iptables/netshを使用せずに行われます。 |
NAT(Kubernetesでは使用されません) |
コンテナには、内部のvSwitchに接続されたvNICが付与されます。DNS/DHCPは、WinNATと呼ばれる内部コンポーネントを使用して提供されます。 |
MACおよびIPはホストMAC/IPに書き換えられます。 |
nat |
完全を期すためにここに含まれています。 |
上で概説したように、Flannel CNIメタプラグインは、VXLANネットワークバックエンド(アルファサポート、win-overlayへのデリゲート)およびホストゲートウェイネットワークバックエンド(安定したサポート、win-bridgeへのデリゲート)を介してWindowsでもサポートされます。このプラグインは、参照CNIプラグイン(win-overlay、win-bridge)の1つへの委任をサポートし、WindowsのFlannelデーモン(Flanneld)と連携して、ノードのサブネットリースの自動割り当てとHNSネットワークの作成を行います。このプラグインは、独自の構成ファイル(cni.conf)を読み取り、FlannelDで生成されたsubnet.envファイルからの環境変数と統合します。次に、ネットワークプラミング用の参照CNIプラグインの1つに委任し、ノード割り当てサブネットを含む正しい構成をIPAMプラグイン(ホストローカルなど)に送信します。
Node、Pod、およびServiceオブジェクトの場合、TCP/UDPトラフィックに対して次のネットワークフローがサポートされます。:
- Pod -> Pod (IP)
- Pod -> Pod (Name)
- Pod -> Service (Cluster IP)
- Pod -> Service (PQDN、ただし、「.」がない場合のみ)
- Pod -> Service (FQDN)
- Pod -> External (IP)
- Pod -> External (DNS)
- Node -> Pod
- Pod -> Node
Windowsでは、次のIPAMオプションがサポートされています。
制限
コントロールプレーン
Windowsは、Kubernetesアーキテクチャとコンポーネントマトリックスのワーカーノードとしてのみサポートされています。つまり、Kubernetesクラスターには常にLinuxマスターノード、0以上のLinuxワーカーノード、0以上のWindowsワーカーノードが含まれている必要があります。
コンピュート
リソース管理とプロセス分離
Linux cgroupsは、Linuxのリソースを制御するPodの境界として使用されます。コンテナは、ネットワーク、プロセス、およびファイルシステムを分離するのために、その境界内に作成されます。cgroups APIを使用して、cpu/io/memoryの統計を収集できます。対照的に、Windowsはシステムネームスペースフィルターを備えたコンテナごとのジョブオブジェクトを使用して、コンテナ内のすべてのプロセスを格納し、ホストからの論理的な分離を提供します。ネームスペースフィルタリングを行わずにWindowsコンテナを実行する方法はありません。これは、ホストの環境ではシステム特権を主張できないため、Windowsでは特権コンテナを使用できないことを意味します。セキュリティアカウントマネージャー(SAM)が独立しているため、コンテナはホストからIDを引き受けることができません。
オペレーティングシステムの制限
Windowsには厳密な互換性ルールがあり、ホストOSのバージョンとコンテナのベースイメージOSのバージョンは、一致する必要があります。Windows Server 2019のコンテナオペレーティングシステムを備えたWindowsコンテナのみがサポートされます。Hyper-V分離のコンテナは、Windowsコンテナのイメージバージョンに下位互換性を持たせることは、将来のリリースで計画されています。
機能制限
- TerminationGracePeriod:実装されていません
- 単一ファイルのマッピング:CRI-ContainerDで実装されます
- 終了メッセージ:CRI-ContainerDで実装されます
- 特権コンテナ:現在Windowsコンテナではサポートされていません
- HugePages:現在Windowsコンテナではサポートされていません
- 既存のノード問題を検出する機能はLinux専用であり、特権コンテナが必要です。一般的に、特権コンテナはサポートされていないため、これがWindowsで使用されることは想定していません。
- ネームスペース共有については、すべての機能がサポートされているわけではありません(詳細については、APIセクションを参照してください)
メモリ予約と処理
Windowsには、Linuxのようなメモリ不足のプロセスキラーはありません。Windowsは常に全ユーザーモードのメモリ割り当てを仮想として扱い、ページファイルは必須です。正味の効果は、WindowsはLinuxのようなメモリ不足の状態にはならず、メモリ不足(OOM)終了の影響を受ける代わりにページをディスクに処理します。メモリが過剰にプロビジョニングされ、物理メモリのすべてが使い果たされると、ページングによってパフォーマンスが低下する可能性があります。
2ステップのプロセスで、メモリ使用量を妥当な範囲内に保つことが可能です。まず、kubeletパラメーター--kubelet-reserve
や--system-reserve
を使用して、ノード(コンテナ外)でのメモリ使用量を明確にします。これにより、NodeAllocatable)が削減されます。ワークロードをデプロイするときは、コンテナにリソース制限をかけます(制限のみを設定するか、制限が要求と等しくなければなりません)。これにより、NodeAllocatableも差し引かれ、ノードのリソースがフルな状態になるとSchedulerがPodを追加できなくなります。
過剰なプロビジョニングを回避するためのベストプラクティスは、Windows、Docker、およびKubernetesのプロセスに対応するために、最低2GBのメモリを予約したシステムでkubeletを構成することです。
フラグの振舞いについては、次のような異なる動作をします。:
--kubelet-reserve
、--system-reserve
、および--eviction-hard
フラグはノードの割り当て可能数を更新します
--enforce-node-allocable
を使用した排除は実装されていません
--eviction-hard
および--eviction-soft
を使用した排除は実装されていません
- MemoryPressureの制約は実装されていません
- kubeletによって実行されるOOMを排除することはありません
- Windowsノードで実行されているKubeletにはメモリ制限がありません。
--kubelet-reserve
と--system-reserve
は、ホストで実行されているkubeletまたはプロセスに制限を設定しません。これは、ホスト上のkubeletまたはプロセスが、NodeAllocatableとSchedulerの外でメモリリソース不足を引き起こす可能性があることを意味します。
ストレージ
Windowsには、コンテナレイヤーをマウントして、NTFSに基づいて複製されたファイルシステムを作るためのレイヤー構造のファイルシステムドライバーがあります。コンテナ内のすべてのファイルパスは、そのコンテナの環境内だけで決められます。
- ボリュームマウントは、コンテナ内のディレクトリのみを対象にすることができ、個別のファイルは対象にできません
- ボリュームマウントは、ファイルまたはディレクトリをホストファイルシステムに投影することはできません
- WindowsレジストリとSAMデータベースには常に書き込みアクセスが必要であるため、読み取り専用ファイルシステムはサポートされていません。ただし、読み取り専用ボリュームはサポートされています
- ボリュームのユーザーマスクと権限は使用できません。SAMはホストとコンテナ間で共有されないため、それらの間のマッピングはありません。すべての権限はコンテナの環境内で決められます
その結果、次のストレージ機能はWindowsノードではサポートされません。
- ボリュームサブパスのマウント。Windowsコンテナにマウントできるのはボリューム全体だけです。
- シークレットのサブパスボリュームのマウント
- ホストマウントプロジェクション
- DefaultMode(UID/GID依存関係による)
- 読み取り専用のルートファイルシステム。マップされたボリュームは引き続き読み取り専用をサポートします
- ブロックデバイスマッピング
- 記憶媒体としてのメモリ
- uui/guid、ユーザーごとのLinuxファイルシステム権限などのファイルシステム機能
- NFSベースのストレージ/ボリュームのサポート
- マウントされたボリュームの拡張(resizefs)
ネットワーキング
Windowsコンテナネットワーキングは、Linuxネットワーキングとはいくつかの重要な実装方法の違いがあります。Microsoft documentation for Windows Container Networkingには、追加の詳細と背景があります。
Windowsホストネットワーキングサービスと仮想スイッチはネームスペースを実装して、Podまたはコンテナの必要に応じて仮想NICを作成できます。ただし、DNS、ルート、メトリックなどの多くの構成は、Linuxのような/etc/...ファイルではなく、Windowsレジストリデータベースに保存されます。コンテナのWindowsレジストリはホストのレジストリとは別であるため、ホストからコンテナへの/etc/resolv.confのマッピングなどの概念は、Linuxの場合と同じ効果をもたらしません。これらは、そのコンテナの環境で実行されるWindows APIを使用して構成する必要があります。したがって、CNIの実装は、ファイルマッピングに依存する代わりにHNSを呼び出して、ネットワークの詳細をPodまたはコンテナに渡す必要があります。
次のネットワーク機能はWindowsノードではサポートされていません
- ホストネットワーキングモードはWindows Podでは使用できません
- ノード自体からのローカルNodePortアクセスは失敗します(他のノードまたは外部クライアントで機能)
- ノードからのService VIPへのアクセスは、Windows Serverの将来のリリースで利用可能になる予定です
- kube-proxyのオーバーレイネットワーキングサポートはアルファリリースです。さらに、KB4482887がWindows Server 2019にインストールされている必要があります
- ローカルトラフィックポリシーとDSRモード
- l2bridge、l2tunnel、またはオーバーレイネットワークに接続されたWindowsコンテナは、IPv6スタックを介した通信をサポートしていません。これらのネットワークドライバーがIPv6アドレスを使用できるようにするために必要な機能として、優れたWindowsプラットフォームの機能があり、それに続いて、kubelet、kube-proxy、およびCNIプラグインといったKubernetesの機能があります。
- win-overlay、win-bridge、およびAzure-CNIプラグインを介したICMPプロトコルを使用したアウトバウンド通信。具体的には、Windowsデータプレーン(VFP)は、ICMPパケットの置き換えをサポートしていません。これの意味は:
- 同じネットワーク内の宛先に向けられたICMPパケット(pingを介したPod間通信など)は期待どおりに機能し、制限はありません
- TCP/UDPパケットは期待どおりに機能し、制限はありません
- リモートネットワーク(Podからping経由の外部インターネット通信など)を通過するように指示されたICMPパケットは置き換えできないため、ソースにルーティングされません。
- TCP/UDPパケットは引き続き置き換えできるため、
ping <destination>
をcurl <destination>
に置き換えることで、外部への接続をデバッグできます。
これらの機能はKubernetes v1.15で追加されました。
CNIプラグイン
- Windowsリファレンスネットワークプラグインのwin-bridgeとwin-overlayは、CNI仕様v0.4.0において「CHECK」実装がないため、今のところ実装されていません。
- Flannel VXLAN CNIについては、Windowsで次の制限があります。:
- Node-podの直接間接続は設計上不可能です。FlannelPR 1096を使用するローカルPodでのみ可能です
- VNI 4096とUDPポート4789の使用に制限されています。VNIの制限は現在取り組んでおり、将来のリリースで解決される予定です(オープンソースのflannelの変更)。これらのパラメーターの詳細については、公式のFlannel VXLANバックエンドのドキュメントをご覧ください。
DNS
- ClusterFirstWithHostNetは、DNSでサポートされていません。Windowsでは、FQDNとしてすべての名前を「.」で扱い、PQDNでの名前解決はスキップします。
- Linuxでは、PQDNで名前解決しようとするときに使用するDNSサフィックスリストがあります。Windowsでは、1つのDNSサフィックスしかありません。これは、そのPodのNamespaceに関連付けられているDNSサフィックスです(たとえば、mydns.svc.cluster.local)。Windowsでは、そのサフィックスだけで名前解決可能なFQDNおよびServiceまたはNameでの名前解決ができます。たとえば、defaultのNamespaceで生成されたPodには、DNSサフィックスdefault.svc.cluster.localが付けられます。WindowsのPodでは、kubernetes.default.svc.cluster.localとkubernetesの両方を名前解決できますが、kubernetes.defaultやkubernetes.default.svcのような中間での名前解決はできません。
- Windowsでは、複数のDNSリゾルバーを使用できます。これらには少し異なる動作が付属しているため、ネームクエリの解決には
Resolve-DNSName
ユーティリティを使用することをお勧めします。
セキュリティ
Secretはノードのボリュームに平文テキストで書き込まれます(Linuxのtmpfs/in-memoryの比較として)。これはカスタマーが2つのことを行う必要があります
- ファイルACLを使用してSecretファイルの場所を保護する
- BitLockerを使って、ボリュームレベルの暗号化を使用する
RunAsUserは、現在Windowsではサポートされていません。回避策は、コンテナをパッケージ化する前にローカルアカウントを作成することです。RunAsUsername機能は、将来のリリースで追加される可能性があります。
SELinux、AppArmor、Seccomp、特性(POSIX機能)のような、Linux固有のPodセキュリティ環境の権限はサポートされていません。
さらに、既に述べたように特権付きコンテナは、Windowsにおいてサポートされていません。
API
ほとんどのKubernetes APIがWindowsでも機能することに違いはありません。そのわずかな違いはOSとコンテナランタイムの違いによるものです。特定の状況では、PodやコンテナなどのワークロードAPIの一部のプロパティが、Linuxで実装されているが、Windowsでは実行できないことを前提に設計されています。
高いレベルで、これらOSのコンセプトに違いがります。:
- ID - Linuxでは、Integer型として表されるuserID(UID)とgroupID(GID)を使用します。ユーザー名とグループ名は正規ではありません - それらは、UID+GIDの背後にある
/etc/groups
または/etc/passwd
の単なるエイリアスです。Windowsは、Windows Security Access Manager(SAM)データベースに格納されているより大きなバイナリセキュリティ識別子(SID)を使用します。このデータベースは、ホストとコンテナ間、またはコンテナ間で共有されません。
- ファイル権限 - Windowsは、権限とUID+GIDのビットマスクではなく、SIDに基づくアクセス制御リストを使用します
- ファイルパス - Windowsの規則では、
/
ではなく\
を使用します。Go IOライブラリは通常両方を受け入れ、それを機能させるだけですが、コンテナ内で解釈されるパスまたはコマンドラインを設定する場合、\
が必要になる場合があります。
- シグナル - Windowsのインタラクティブなアプリは終了を異なる方法で処理し、次の1つ以上を実装できます。:
- UIスレッドは、WM_CLOSEを含む明確に定義されたメッセージを処理します
- コンソールアプリは、コントロールハンドラーを使用してctrl-cまたはctrl-breakを処理します
- サービスは、SERVICE_CONTROL_STOP制御コードを受け入れることができるサービスコントロールハンドラー関数を登録します。
終了コードは、0が成功、0以外が失敗の場合と同じ規則に従います。特定のエラーコードは、WindowsとLinuxで異なる場合があります。ただし、Kubernetesのコンポーネント(kubelet、kube-proxy)から渡される終了コードは変更されていません。
V1.Container
- V1.Container.ResourceRequirements.limits.cpuおよびV1.Container.ResourceRequirements.limits.memory - Windowsは、CPU割り当てにハード制限を使用しません。代わりに、共有システムが使用されます。ミリコアに基づく既存のフィールドは、Windowsスケジューラーによって追従される相対共有にスケーリングされます。参照: kuberuntime/helpers_windows.go、参照: resource controls in Microsoft docs
- Huge Pagesは、Windowsコンテナランタイムには実装されてないので、使用できません。コンテナに対して設定できないユーザー特権を主張する必要があります。
- V1.Container.ResourceRequirements.requests.cpuおよびV1.Container.ResourceRequirements.requests.memory - リクエストはノードの利用可能なリソースから差し引かれるので、ノードのオーバープロビジョニングを回避するために使用できます。ただし、過剰にプロビジョニングされたノードのリソースを保証するために使用することはできません。オペレーターが完全にプロビジョニングし過ぎないようにする場合は、ベストプラクティスとしてこれらをすべてのコンテナに適用する必要があります。
- V1.Container.SecurityContext.allowPrivilegeEscalation - Windowsでは使用できません、接続されている機能はありません
- V1.Container.SecurityContext.Capabilities - POSIX機能はWindowsでは実装されていません
- V1.Container.SecurityContext.privileged - Windowsでは特権コンテナをサポートしていません
- V1.Container.SecurityContext.procMount - Windowsでは/procファイルシステムがありません
- V1.Container.SecurityContext.readOnlyRootFilesystem - Windowsでは使用できません、レジストリおよびシステムプロセスがコンテナ内で実行するには、書き込みアクセスが必要です
- V1.Container.SecurityContext.runAsGroup - Windowsでは使用できません、GIDのサポートもありません
- V1.Container.SecurityContext.runAsNonRoot - Windowsではrootユーザーが存在しません。最も近いものは、ノードに存在しないIDであるContainerAdministratorです。
- V1.Container.SecurityContext.runAsUser - Windowsでは使用できません。intとしてのUIDはサポートされていません。
- V1.Container.SecurityContext.seLinuxOptions - Windowsでは使用できません、SELinuxがありません
- V1.Container.terminationMessagePath - これは、Windowsが単一ファイルのマッピングをサポートしないという点でいくつかの制限があります。デフォルト値は/dev/termination-logであり、デフォルトではWindowsに存在しないため動作します。
V1.Pod
- V1.Pod.hostIPC、v1.pod.hostpid - Windowsではホストのネームスペースを共有することはできません
- V1.Pod.hostNetwork - ホストのネットワークを共有するためのWindows OSサポートはありません
- V1.Pod.dnsPolicy - ClusterFirstWithHostNet - Windowsではホストネットワーキングがサポートされていないため、サポートされていません。
- V1.Pod.podSecurityContext - 以下のV1.PodSecurityContextを参照
- V1.Pod.shareProcessNamespace - これはベータ版の機能であり、Windowsに実装されていないLinuxのNamespace機能に依存しています。Windowsでは、プロセスのネームスペースまたはコンテナのルートファイルシステムを共有できません。共有できるのはネットワークだけです。
- V1.Pod.terminationGracePeriodSeconds - これはWindowsのDockerに完全には実装されていません。リファレンスを参照してください。今日の動作では、ENTRYPOINTプロセスにCTRL_SHUTDOWN_EVENTが送信され、Windowsではデフォルトで5秒待機し、最後に通常のWindowsシャットダウン動作を使用してすべてのプロセスをシャットダウンします。5秒のデフォルトは、実際にはWindowsレジストリーコンテナ内にあるため、コンテナ作成時にオーバーライドできます。
- V1.Pod.volumeDevices - これはベータ機能であり、Windowsには実装されていません。Windowsでは、rawブロックデバイスをPodに接続できません。
- V1.Pod.volumes-EmptyDir、Secret、ConfigMap、HostPath - すべて動作し、TestGridにテストがあります
- V1.emptyDirVolumeSource - ノードのデフォルトのメディアはWindowsのディスクです。Windowsでは、RAMディスクが組み込まれていないため、メモリはサポートされていません。
- V1.VolumeMount.mountPropagation - mount propagationは、Windowsではサポートされていません。
V1.PodSecurityContext
Windowsでは、PodSecurityContextフィールドはどれも機能しません。これらは参照用にここにリストされています。
- V1.PodSecurityContext.SELinuxOptions - SELinuxは、Windowsでは使用できません
- V1.PodSecurityContext.RunAsUser - UIDを提供しますが、Windowsでは使用できません
- V1.PodSecurityContext.RunAsGroup - GIDを提供しますが、Windowsでは使用できません
- V1.PodSecurityContext.RunAsNonRoot - Windowsにはrootユーザーがありません。最も近いものは、ノードに存在しないIDであるContainerAdministratorです。
- V1.PodSecurityContext.SupplementalGroups - GIDを提供しますが、Windowsでは使用できません
- V1.PodSecurityContext.Sysctls - これらはLinuxのsysctlインターフェースの一部です。Windowsには同等のものはありません。
ヘルプとトラブルシューティングを学ぶ
Kubernetesクラスターのトラブルシューティングの主なヘルプソースは、トラブルシューティングページから始める必要があります。このセクションには、いくつか追加的な、Windows固有のトラブルシューティングヘルプが含まれています。ログは、Kubernetesにおけるトラブルシューティング問題の重要な要素です。他のコントリビューターからトラブルシューティングの支援を求めるときは、必ずそれらを含めてください。SIG-Windowsログ収集に関するコントリビュートガイドの指示に従ってください。
-
start.ps1が正常に完了したことをどのように確認できますか?
ノード上でkubelet、kube-proxy、および(ネットワーキングソリューションとしてFlannelを選択した場合)flanneldホストエージェントプロセスが実行され、実行ログが個別のPowerShellウィンドウに表示されます。これに加えて、WindowsノードがKubernetesクラスターで「Ready」として表示されているはずです。
-
Kubernetesノードのプロセスをサービスとしてバックグラウンドで実行するように構成できますか?
Kubeletとkube-proxyは、ネイティブのWindowsサービスとして実行するように既に構成されています、障害(例えば、プロセスのクラッシュ)が発生した場合にサービスを自動的に再起動することにより、復元性を提供します。これらのノードコンポーネントをサービスとして構成するには、2つのオプションがあります。
-
ネイティブWindowsサービスとして
Kubeletとkube-proxyは、sc.exe
を使用してネイティブのWindowsサービスとして実行できます。
# 2つの個別のコマンドでkubeletおよびkube-proxyのサービスを作成する
sc.exe create <component_name> binPath= "<path_to_binary> --service <other_args>"
# 引数にスペースが含まれている場合は、エスケープする必要があることに注意してください。
sc.exe create kubelet binPath= "C:\kubelet.exe --service --hostname-override 'minion' <other_args>"
# サービスを開始する
Start-Service kubelet
Start-Service kube-proxy
# サービスを停止する
Stop-Service kubelet (-Force)
Stop-Service kube-proxy (-Force)
# サービスの状態を問い合わせる
Get-Service kubelet
Get-Service kube-proxy
-
nssm.exeの使用
また、nssm.exeなどの代替サービスマネージャーを使用して、これらのプロセス(flanneld、kubelet、kube-proxy)をバックグラウンドで実行することもできます。このサンプルスクリプトを使用すると、nssm.exeを利用してkubelet、kube-proxy、flanneld.exeを登録し、Windowsサービスとしてバックグラウンドで実行できます。
register-svc.ps1 -NetworkMode <Network mode> -ManagementIP <Windows Node IP> -ClusterCIDR <Cluster subnet> -KubeDnsServiceIP <Kube-dns Service IP> -LogDir <Directory to place logs>
# NetworkMode = ネットワークソリューションとして選択されたネットワークモードl2bridge(flannel host-gw、これもデフォルト値)またはoverlay(flannel vxlan)
# ManagementIP = Windowsノードに割り当てられたIPアドレス。 ipconfigを使用してこれを見つけることができます
# ClusterCIDR = クラスターのサブネット範囲。(デフォルト値 10.244.0.0/16)
# KubeDnsServiceIP = Kubernetes DNSサービスIP(デフォルト値 10.96.0.10)
# LogDir = kubeletおよびkube-proxyログがそれぞれの出力ファイルにリダイレクトされるディレクトリ(デフォルト値 C:\k)
上記のスクリプトが適切でない場合は、次の例を使用してnssm.exeを手動で構成できます。
# flanneld.exeを登録する
nssm install flanneld C:\flannel\flanneld.exe
nssm set flanneld AppParameters --kubeconfig-file=c:\k\config --iface=<ManagementIP> --ip-masq=1 --kube-subnet-mgr=1
nssm set flanneld AppEnvironmentExtra NODE_NAME=<hostname>
nssm set flanneld AppDirectory C:\flannel
nssm start flanneld
# kubelet.exeを登録
# マイクロソフトは、mcr.microsoft.com/k8s/core/pause:1.2.0としてポーズインフラストラクチャコンテナをリリース
nssm install kubelet C:\k\kubelet.exe
nssm set kubelet AppParameters --hostname-override=<hostname> --v=6 --pod-infra-container-image=mcr.microsoft.com/k8s/core/pause:1.2.0 --resolv-conf="" --allow-privileged=true --enable-debugging-handlers --cluster-dns=<DNS-service-IP> --cluster-domain=cluster.local --kubeconfig=c:\k\config --hairpin-mode=promiscuous-bridge --image-pull-progress-deadline=20m --cgroups-per-qos=false --log-dir=<log directory> --logtostderr=false --enforce-node-allocatable="" --network-plugin=cni --cni-bin-dir=c:\k\cni --cni-conf-dir=c:\k\cni\config
nssm set kubelet AppDirectory C:\k
nssm start kubelet
# kube-proxy.exeを登録する (l2bridge / host-gw)
nssm install kube-proxy C:\k\kube-proxy.exe
nssm set kube-proxy AppDirectory c:\k
nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --hostname-override=<hostname>--kubeconfig=c:\k\config --enable-dsr=false --log-dir=<log directory> --logtostderr=false
nssm.exe set kube-proxy AppEnvironmentExtra KUBE_NETWORK=cbr0
nssm set kube-proxy DependOnService kubelet
nssm start kube-proxy
# kube-proxy.exeを登録する (overlay / vxlan)
nssm install kube-proxy C:\k\kube-proxy.exe
nssm set kube-proxy AppDirectory c:\k
nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --feature-gates="WinOverlay=true" --hostname-override=<hostname> --kubeconfig=c:\k\config --network-name=vxlan0 --source-vip=<source-vip> --enable-dsr=false --log-dir=<log directory> --logtostderr=false
nssm set kube-proxy DependOnService kubelet
nssm start kube-proxy
最初のトラブルシューティングでは、nssm.exeで次のフラグを使用して、stdoutおよびstderrを出力ファイルにリダイレクトできます。:
nssm set <Service Name> AppStdout C:\k\mysvc.log
nssm set <Service Name> AppStderr C:\k\mysvc.log
詳細については、公式のnssmの使用法のドキュメントを参照してください。
-
Windows Podにネットワーク接続がありません
仮想マシンを使用している場合は、すべてのVMネットワークアダプターでMACスプーフィングが有効になっていることを確認してください。
-
Windows Podが外部リソースにpingできません
現在、Windows Podには、ICMPプロトコル用にプログラムされた送信ルールはありません。ただし、TCP/UDPはサポートされています。クラスター外のリソースへの接続を実証する場合は、ping <IP>
に対応するcurl <IP>
コマンドに置き換えてください。
それでも問題が解決しない場合は、cni.confのネットワーク構成に値する可能性があるので、いくつかの特別な注意が必要です。この静的ファイルはいつでも編集できます。構成の更新は、新しく作成されたすべてのKubernetesリソースに適用されます。
Kubernetesのネットワーキング要件の1つ(参照Kubernetesモデル)は、内部でNATを使用せずにクラスター通信を行うためのものです。この要件を遵守するために、すべての通信にExceptionListがあり、アウトバウンドNATが発生しないようにします。ただし、これは、クエリしようとしている外部IPをExceptionListから除外する必要があることも意味します。そうして初めて、Windows PodからのトラフィックがSNAT処理され、外部からの応答を受信できるようになります。この点で、cni.conf
のExceptionListは次のようになります。:
"ExceptionList": [
"10.244.0.0/16", # クラスターのサブネット
"10.96.0.0/12", # Serviceのサブネット
"10.127.130.0/24" # 管理 (ホスト) のサブネット
]
-
WindowsノードがNodePort Serviceにアクセスできません
ノード自体からのローカルNodePortアクセスは失敗します。これは既知の制限です。NodePortアクセスは、他のノードまたは外部クライアントから行えます。
-
コンテナのvNICとHNSエンドポイントが削除されています
この問題は、hostname-override
パラメーターがkube-proxyに渡されない場合に発生する可能性があります。これを解決するには、ユーザーは次のようにホスト名をkube-proxyに渡す必要があります。:
C:\k\kube-proxy.exe --hostname-override=$(hostname)
-
flannelを使用すると、クラスターに再参加した後、ノードに問題が発生します
以前に削除されたノードがクラスターに再参加するときはいつも、flannelDは新しいPodサブネットをノードに割り当てようとします。ユーザーは、次のパスにある古いPodサブネット構成ファイルを削除する必要があります。:
Remove-Item C:\k\SourceVip.json
Remove-Item C:\k\SourceVipRequest.json
-
start.ps1
を起動した後、flanneldが「ネットワークが作成されるのを待っています」と表示されたままになります
この調査中の問題に関する多数の報告があります。最も可能性が高いのは、flannelネットワークの管理IPが設定されるタイミングの問題です。回避策は、単純にstart.ps1を再起動するか、次のように手動で再起動することです。:
PS C:> [Environment]::SetEnvironmentVariable("NODE_NAME", "<Windows_Worker_Hostname>")
PS C:> C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface=<Windows_Worker_Node_IP> --ip-masq=1 --kube-subnet-mgr=1
-
/run/flannel/subnet.env
がないため、Windows Podを起動できません
これは、Flannelが正しく起動しなかったことを示しています。 flanneld.exeの再起動を試みるか、Kubernetesマスターの/run/flannel/subnet.env
からWindowsワーカーノードのC:\run\flannel\subnet.env
に手動でファイルをコピーすることができます。「FLANNEL_SUBNET」行を別の番号に変更します。たとえば、ノードサブネット10.244.4.1/24が必要な場合は以下となります。:
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.4.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=true
-
WindowsノードがService IPを使用してServiceにアクセスできない
これは、Windows上の現在のネットワークスタックの既知の制限です。ただし、Windows PodはService IPにアクセスできます。
-
kubeletの起動時にネットワークアダプターが見つかりません
WindowsネットワーキングスタックがKubernetesネットワーキングを動かすには、仮想アダプターが必要です。次のコマンドを実行しても結果が返されない場合(管理シェルで)、仮想ネットワークの作成(Kubeletが機能するために必要な前提条件)に失敗したことになります。:
Get-HnsNetwork | ? Name -ieq "cbr0"
Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"
ホストのネットワークアダプターが「イーサネット」ではない場合、多くの場合、start.ps1スクリプトのInterfaceNameパラメーターを修正する価値があります。そうでない場合はstart-kubelet.ps1
スクリプトの出力結果を調べて、仮想ネットワークの作成中にエラーがないか確認します。
-
Podが「Container Creating」と表示されたまま動かなくなったり、何度も再起動を繰り返します
PauseイメージがOSバージョンと互換性があることを確認してください。説明では、OSとコンテナの両方がバージョン1803であると想定しています。それ以降のバージョンのWindowsを使用している場合は、Insiderビルドなどでは、それに応じてイメージを調整する必要があります。イメージについては、MicrosoftのDockerレジストリを参照してください。いずれにしても、PauseイメージのDockerfileとサンプルサービスの両方で、イメージに:latestのタグが付けられていると想定しています。
Kubernetes v1.14以降、MicrosoftはPauseインフラストラクチャコンテナをmcr.microsoft.com/k8s/core/pause:1.2.0
でリリースしています。
-
DNS名前解決が正しく機能していない
このセクションでDNSの制限を確認してください。
-
kubectl port-forward
が「ポート転送を実行できません:wincatが見つかりません」で失敗します
これはKubernetes 1.15、およびPauseインフラストラクチャコンテナmcr.microsoft.com/k8s/core/pause:1.2.0
で実装されました。必ずこれらのバージョン以降を使用してください。
独自のPauseインフラストラクチャコンテナを構築する場合は、必ずwincatを含めてください。
-
Windows Serverノードがプロキシの背後にあるため、Kubernetesのインストールが失敗します
プロキシの背後にある場合は、次のPowerShell環境変数を定義する必要があります。:
[Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine)
[Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine)
-
pause
コンテナとは何ですか
Kubernetes Podでは、インフラストラクチャまたは「pause」コンテナが最初に作成され、コンテナエンドポイントをホストします。インフラストラクチャやワーカーコンテナなど、同じPodに属するコンテナは、共通のネットワークネームスペースとエンドポイント(同じIPとポートスペース)を共有します。Pauseコンテナは、ネットワーク構成を失うことなくクラッシュまたは再起動するワーカーコンテナに対応するために必要です。
「pause」(インフラストラクチャ)イメージは、Microsoft Container Registry(MCR)でホストされています。docker pull mcr.microsoft.com/k8s/core/pause:1.2.0
を使用してアクセスできます。詳細については、DOCKERFILEをご覧ください。
さらなる調査
これらの手順で問題が解決しない場合は、次の方法で、KubernetesのWindowsノードでWindowsコンテナを実行する際のヘルプを利用できます。:
IssueとFeatureリクエストの報告
バグのようなものがある場合、またはFeatureリクエストを行う場合は、GitHubのIssueシステムを使用してください。GitHubでIssueを開いて、SIG-Windowsに割り当てることができます。以前に報告された場合は、まずIssueリストを検索し、Issueについての経験をコメントして、追加のログを加える必要があります。SIG-Windows Slackは、チケットを作成する前に、初期サポートとトラブルシューティングのアイデアを得るための素晴らしい手段でもあります。
バグを報告する場合は、問題の再現方法に関する次のような詳細情報を含めてください。:
- Kubernetesのバージョン: kubectlのバージョン
- 環境の詳細: クラウドプロバイダー、OSのディストリビューション、選択したネットワーキングと構成、およびDockerのバージョン
- 問題を再現するための詳細な手順
- 関連するログ
/sig windows
でIssueにコメントして、Issueにsig/windowsのタグを付けて、SIG-Windowsメンバーが気付くようにします
次の項目
ロードマップには多くの機能があります。高レベルの簡略リストを以下に示しますが、ロードマッププロジェクトを見て、貢献することによってWindowsサポートを改善することをお勧めします。
Hyper-V分離
Hyper-V分離はKubernetesで以下のWindowsコンテナのユースケースを実現するために必要です。
- Pod間のハイパーバイザーベースの分離により、セキュリティを強化
- 下位互換性により、コンテナの再構築を必要とせずにノードで新しいWindows Serverバージョンを実行
- Podの特定のCPU/NUMA設定
- メモリの分離と予約
既存のHyper-V分離サポートは、v1.10の試験的な機能であり、上記のCRI-ContainerD機能とRuntimeClass機能を優先して将来廃止される予定です。現在の機能を使用してHyper-V分離コンテナを作成するには、kubeletのフィーチャーゲートをHyperVContainer=true
で開始し、Podにアノテーションexperimental.windows.kubernetes.io/isolation-type=hyperv
を含める必要があります。実験的リリースでは、この機能はPodごとに1つのコンテナに制限されています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: iis
spec:
selector:
matchLabels:
app: iis
replicas: 3
template:
metadata:
labels:
app: iis
annotations:
experimental.windows.kubernetes.io/isolation-type: hyperv
spec:
containers:
- name: iis
image: microsoft/iis
ports:
- containerPort: 80
kubeadmとクラスターAPIを使用したデプロイ
Kubeadmは、ユーザーがKubernetesクラスターをデプロイするための事実上の標準になりつつあります。kubeadmのWindowsノードのサポートは進行中ですが、ガイドはすでにここで利用可能です。Windowsノードが適切にプロビジョニングされるように、クラスターAPIにも投資しています。
その他の主な機能
- グループ管理サービスアカウントのベータサポート
- その他のCNI
- その他のストレージプラグイン
4.2 - KubernetesでWindowsコンテナをスケジュールするためのガイド
Windowsアプリケーションは、多くの組織で実行されるサービスとアプリケーションの大部分を占めます。このガイドでは、KubernetesでWindowsコンテナを構成してデプロイする手順について説明します。
目的
- WindowsノードでWindowsコンテナを実行するサンプルのDeploymentを構成します
- (オプション)Group Managed Service Accounts(GMSA)を使用してPodのActive Directory IDを構成します
始める前に
はじめに:Windowsコンテナのデプロイ
WindowsコンテナをKubernetesにデプロイするには、最初にサンプルアプリケーションを作成する必要があります。以下のYAMLファイルの例では、簡単なウェブサーバーアプリケーションを作成しています。以下の内容でwin-webserver.yaml
という名前のサービススペックを作成します。:
apiVersion: v1
kind: Service
metadata:
name: win-webserver
labels:
app: win-webserver
spec:
ports:
# このサービスが提供するポート
- port: 80
targetPort: 80
selector:
app: win-webserver
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: win-webserver
name: win-webserver
spec:
replicas: 2
selector:
matchLabels:
app: win-webserver
template:
metadata:
labels:
app: win-webserver
name: win-webserver
spec:
containers:
- name: windowswebserver
image: mcr.microsoft.com/windows/servercore:ltsc2019
command:
- powershell.exe
- -command
- "<#code used from https://gist.github.com/19WAS85/5424431#> ; $$listener = New-Object System.Net.HttpListener ; $$listener.Prefixes.Add('http://*:80/') ; $$listener.Start() ; $$callerCounts = @{} ; Write-Host('Listening at http://*:80/') ; while ($$listener.IsListening) { ;$$context = $$listener.GetContext() ;$$requestUrl = $$context.Request.Url ;$$clientIP = $$context.Request.RemoteEndPoint.Address ;$$response = $$context.Response ;Write-Host '' ;Write-Host('> {0}' -f $$requestUrl) ; ;$$count = 1 ;$$k=$$callerCounts.Get_Item($$clientIP) ;if ($$k -ne $$null) { $$count = $$k } ;$$callerCounts.Set_Item($$clientIP, $$count) ;$$ip=(Get-NetAdapter | Get-NetIpAddress); $$header='<html><body><H1>Windows Container Web Server</H1>' ;$$callerCountsString='' ;$$callerCounts.Keys | % { $$callerCountsString='<p>IP {0} callerCount {1} ' -f $$ip[1].IPAddress,$$callerCounts.Item($$_) } ;$$footer='</body></html>' ;$$content='{0}{1}{2}' -f $$header,$$callerCountsString,$$footer ;Write-Output $$content ;$$buffer = [System.Text.Encoding]::UTF8.GetBytes($$content) ;$$response.ContentLength64 = $$buffer.Length ;$$response.OutputStream.Write($$buffer, 0, $$buffer.Length) ;$$response.Close() ;$$responseStatus = $$response.StatusCode ;Write-Host('< {0}' -f $$responseStatus) } ; "
nodeSelector:
kubernetes.io/os: windows
備考:
ポートマッピングもサポートされていますが、この例では簡単にするために、コンテナポート80がサービスに直接公開されています。
-
すべてのノードが正常であることを確認します。:
-
Serviceをデプロイして、Podの更新を確認します。:
kubectl apply -f win-webserver.yaml
kubectl get pods -o wide -w
Serviceが正しくデプロイされると、両方のPodがReadyとして表示されます。watch状態のコマンドを終了するには、Ctrl + Cを押します。
-
デプロイが成功したことを確認します。検証するために行うこと:
- WindowsノードのPodごとの2つのコンテナに
docker ps
します
- Linuxマスターからリストされた2つのPodに
kubectl get pods
します
- ネットワークを介したノードとPod間通信、LinuxマスターからのPod IPのポート80に向けて
curl
して、ウェブサーバーの応答をチェックします
- docker execまたはkubectl execを使用したPod間通信、Pod間(および複数のWindowsノードがある場合はホスト間)へのpingします
- ServiceからPodへの通信、Linuxマスターおよび個々のPodからの仮想Service IP(
kubectl get services
で表示される)にcurl
します
- サービスディスカバリ、Kubernetesのdefault DNS suffixと共にService名に
curl
します
- Inbound connectivity,
curl
the NodePort from the Linux master or machines outside of the cluster
- インバウンド接続、Linuxマスターまたはクラスター外のマシンからNodePortに
curl
します
- アウトバウンド接続、kubectl execを使用したPod内からの外部IPに
curl
します
備考:
今のところ、Windowsネットワークスタックのプラットフォーム制限のため、Windowsコンテナホストは、ホストされているサービスのIPにアクセスできません。Service IPにアクセスできるのは、Windows Podだけです。
可観測性
ワークロードからのログキャプチャ
ログは可観測性の重要な要素です。これにより、ユーザーはワークロードの運用面に関する洞察を得ることができ、問題のトラブルシューティングの主要な要素になります。WindowsコンテナとWindowsコンテナ内のワークロードの動作はLinuxコンテナとは異なるため、ユーザーはログの収集に苦労し、運用の可視性が制限されていました。たとえば、Windowsワークロードは通常、ETW(Windowsのイベントトレース)にログを記録するか、アプリケーションイベントログにエントリをプッシュするように構成されます。MicrosoftのオープンソースツールであるLogMonitorは、Windowsコンテナ内の構成されたログソースを監視するための推奨方法です。LogMonitorは、イベントログ、ETWプロバイダー、カスタムアプリケーションログのモニタリングをサポートしており、それらをSTDOUTにパイプして、kubectl logs <pod>
で使用できます。
LogMonitor GitHubページの指示に従って、バイナリと構成ファイルをすべてのコンテナにコピーして、LogMonitorがログをSTDOUTにプッシュするために必要なエントリーポイントを追加します。
構成可能なコンテナのユーザー名の使用
Kubernetes v1.16以降、Windowsコンテナは、イメージのデフォルトとは異なるユーザー名でエントリーポイントとプロセスを実行するように構成できます。これが達成される方法は、Linuxコンテナで行われる方法とは少し異なります。詳しくはこちら.
Group Managed Service AccountsによるワークロードIDの管理
Kubernetes v1.14以降、Windowsコンテナワークロードは、Group Managed Service Accounts(GMSA)を使用するように構成できます。Group Managed Service Accountsは、自動パスワード管理、簡略化されたサービスプリンシパル名(SPN)管理、および複数のサーバー間で他の管理者に管理を委任する機能を提供する特定の種類のActive Directoryアカウントです。GMSAで構成されたコンテナは、GMSAで構成されたIDを保持しながら、外部Active Directoryドメインリソースにアクセスできます。Windowsコンテナ用のGMSAの構成と使用の詳細はこちら。
TaintsとTolerations
今日のユーザーは、LinuxとWindowsのワークロードをそれぞれのOS固有のノードで維持するために、Taintsとノードセレクターのいくつかの組み合わせを使用する必要があります。これはおそらくWindowsユーザーにのみ負担をかけます。推奨されるアプローチの概要を以下に示します。主な目標の1つは、このアプローチによって既存のLinuxワークロードの互換性が損なわれないようにすることです。
OS固有のワークロードが適切なコンテナホストに確実に到達するようにする
ユーザーは、TaintsとTolerationsを使用して、Windowsコンテナを適切なホストでスケジュールできるようにすることができます。現在、すべてのKubernetesノードには次のデフォルトラベルがあります。:
- kubernetes.io/os = [windows|linux]
- kubernetes.io/arch = [amd64|arm64|...]
Podの仕様で"kubernetes.io/os": windows
のようなnodeSelectorが指定されていない場合、PodをWindowsまたはLinuxの任意のホストでスケジュールすることができます。WindowsコンテナはWindowsでのみ実行でき、LinuxコンテナはLinuxでのみ実行できるため、これは問題になる可能性があります。ベストプラクティスは、nodeSelectorを使用することです。
ただし、多くの場合、ユーザーには既存の多数のLinuxコンテナのdeployment、およびコミュニティHelmチャートのような既成構成のエコシステムやOperatorのようなプログラム的にPodを生成するケースがあることを理解しています。このような状況では、nodeSelectorsを追加するための構成変更をためらう可能性があります。代替策は、Taintsを使用することです。kubeletは登録中にTaintsを設定できるため、Windowsだけで実行する時に自動的にTaintを追加するように簡単に変更できます。
例:--register-with-taints='os=windows:NoSchedule'
すべてのWindowsノードにTaintを追加することにより、それらには何もスケジュールされません(既存のLinuxPodを含む)。Windows PodがWindowsノードでスケジュールされるためには、nodeSelectorがWindowsを選択することと、適切にマッチするTolerationが必要です。
nodeSelector:
kubernetes.io/os: windows
node.kubernetes.io/windows-build: '10.0.17763'
tolerations:
- key: "os"
operator: "Equal"
value: "windows"
effect: "NoSchedule"
同じクラスター内の複数Windowsバージョンの管理
各Podで使用されるWindows Serverのバージョンは、ノードのバージョンと一致している必要があります。
同じクラスター内で複数のWindows Serverバージョンを使用したい場合は、追加のノードラベルとnodeSelectorsを設定する必要があります。
Kubernetes 1.17では、これを簡単するために新しいラベルnode.kubernetes.io/windows-build
が自動的に追加されます。古いバージョンを実行している場合は、このラベルをWindowsノードに手動で追加することをお勧めします。
このラベルは、互換性のために一致する必要があるWindowsのメジャー、マイナー、およびビルド番号を反映しています。以下は、Windows Serverの各バージョンで現在使用されている値です。
製品番号 |
ビルド番号 |
Windows Server 2019 |
10.0.17763 |
Windows Server version 1809 |
10.0.17763 |
Windows Server version 1903 |
10.0.18362 |
RuntimeClassによる簡素化
RuntimeClassは、TaintsとTolerationsを使用するプロセスを簡略化するために使用できます。クラスター管理者は、これらのTaintsとTolerationsをカプセル化するために使用するRuntimeClass
オブジェクトを作成できます。
- このファイルを
runtimeClasses.yml
に保存します。これには、Windows OS、アーキテクチャ、およびバージョンに適切なnodeSelector
が含まれています。
apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
name: windows-2019
handler: 'docker'
scheduling:
nodeSelector:
kubernetes.io/os: 'windows'
kubernetes.io/arch: 'amd64'
node.kubernetes.io/windows-build: '10.0.17763'
tolerations:
- effect: NoSchedule
key: os
operator: Equal
value: "windows"
- クラスター管理者として使用する
kubectl create -f runtimeClasses.yml
を実行します
- Podの仕様に応じて
runtimeClassName: windows-2019
を追加します
例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: iis-2019
labels:
app: iis-2019
spec:
replicas: 1
template:
metadata:
name: iis-2019
labels:
app: iis-2019
spec:
runtimeClassName: windows-2019
containers:
- name: iis
image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
resources:
limits:
cpu: 1
memory: 800Mi
requests:
cpu: .1
memory: 300Mi
ports:
- containerPort: 80
selector:
matchLabels:
app: iis-2019
---
apiVersion: v1
kind: Service
metadata:
name: iis
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 80
selector:
app: iis-2019