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

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

はじめに

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

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

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

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

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

環境について学ぶ

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

プロダクション環境

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

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

次の項目

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

1 - 学習環境

1.1 - Minikubeを使用してローカル環境でKubernetesを動かす

Minikubeはローカル環境でKubernetesを簡単に実行するためのツールです。Kubernetesを試したり日々の開発への使用を検討するユーザー向けに、PC上のVM内でシングルノードのKubernetesクラスターを実行することができます。

Minikubeの機能

MinikubeのサポートするKubernetesの機能:

  • DNS
  • NodePort
  • ConfigMapとSecret
  • ダッシュボード
  • コンテナランタイム: Docker、CRI-Oおよびcontainerd
  • CNI (Container Network Interface) の有効化
  • Ingress

インストール

ツールのインストールについて知りたい場合は、公式のGet Started!のガイドに従ってください。

クイックスタート

これはMinikubeの起動、使用、削除をローカルで実施する簡単なデモです。下記の手順に従って、Minikubeを起動し試してください。

  1. Minikubeを起動し、クラスターを作成します:

    minikube start
    

    出力はこのようになります:

    Starting local Kubernetes cluster...
    Running pre-create checks...
    Creating machine...
    Starting local Kubernetes cluster...
    

    特定のKubernetesのバージョン、VM、コンテナランタイム上でクラスターを起動するための詳細は、クラスターの起動を参照してください。

  2. kubectlを使用してクラスターと対話できるようになります。詳細はクラスターに触れてみようを参照してください。

    単純なHTTPサーバーであるechoserverという既存のイメージを使用して、Kubernetes Deploymentを作りましょう。そして--portを使用して8080番ポートで公開しましょう。

    kubectl create deployment hello-minikube --image=registry.k8s.io/echoserver:1.10
    

    出力はこのようになります:

    deployment.apps/hello-minikube created
    
  3. hello-minikubeDeploymentに接続するために、Serviceとして公開します:

    kubectl expose deployment hello-minikube --type=NodePort --port=8080
    

    --type=NodePortオプションで、Serviceのタイプを指定します。

    出力はこのようになります:

    service/hello-minikube exposed
    
  4. hello-minikubePodが起動開始されましたが、公開したService経由で接続する前にPodが起動完了になるまで待つ必要があります。

    Podが稼働しているか確認します:

    kubectl get pod
    

    STATUSContainerCreatingと表示されている場合、Podはまだ作成中です:

    NAME                              READY     STATUS              RESTARTS   AGE
    hello-minikube-3383150820-vctvh   0/1       ContainerCreating   0          3s
    

    STATUSRunningと表示されている場合、Podは稼働中です:

    NAME                              READY     STATUS    RESTARTS   AGE
    hello-minikube-3383150820-vctvh   1/1       Running   0          13s
    
  5. Serviceの詳細を確認するため、公開したServiceのURLを取得します:

    minikube service hello-minikube --url
    
  6. ローカル環境のクラスターについて詳細を確認するには、出力から得たURLをブラウザー上でコピーアンドペーストしてください。

    出力はこのようになります:

    Hostname: hello-minikube-7c77b68cff-8wdzq
    
    Pod Information:
     -no pod information available-
    
    Server values:
     server_version=nginx: 1.13.3 - lua: 10008
    
    Request Information:
     client_address=172.17.0.1
     method=GET
     real path=/
     query=
     request_version=1.1
     request_scheme=http
     request_uri=http://192.168.99.100:8080/
    
    Request Headers:
    	accept=*/*
    	host=192.168.99.100:30674
    	user-agent=curl/7.47.0
    
    Request Body:
    	-no body in request-
    

    Serviceやクラスターをこれ以上稼働させない場合、削除する事ができます。

  7. hello-minikubeServiceを削除します:

    kubectl delete services hello-minikube
    

    出力はこのようになります:

    service "hello-minikube" deleted
    
  8. hello-minikubeDeploymentを削除します:

    kubectl delete deployment hello-minikube
    

    出力はこのようになります:

    deployment.extensions "hello-minikube" deleted
    
  9. ローカル環境のMinikubeクラスターを停止します:

    minikube stop
    

    出力はこのようになります:

    Stopping "minikube"...
    "minikube" stopped.
    

    詳細はクラスターの停止を参照ください。

  10. ローカルのMinikubeクラスターを削除します:

    minikube delete
    

    出力はこのようになります:

    Deleting "minikube" ...
    The "minikube" cluster has been deleted.
    

    詳細はクラスターの削除を参照ください。

クラスターの管理

クラスターの起動

minikube startコマンドを使用してクラスターを起動することができます。 このコマンドはシングルノードのKubernetesクラスターを実行する仮想マシンを作成・設定します。 また、このクラスターと通信するkubectlのインストールも設定します。

Kubernetesバージョンの指定

minikube startコマンドに--kubernetes-version文字列を追加することで、 MinikubeにKubernetesの特定のバージョンを指定することができます。 例えば、1.32.0のバージョンを実行するには以下を実行します:

minikube start --kubernetes-version 1.32.0

VMドライバーの指定

もしVMドライバーを変更したい場合は、--driver=<enter_driver_name>フラグをminikube startに設定してください。例えば、コマンドは以下のようになります。

minikube start --driver=<driver_name>

Minikubeは以下のドライバーをサポートしています:

コンテナランタイムの代替

下記のコンテナランタイム上でMinikubeを起動できます。

containerd をコンテナランタイムとして使用するには以下を実行してください:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --container-runtime=containerd \
    --bootstrapper=kubeadm

もしくは拡張バージョンを使用することもできます:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --extra-config=kubelet.container-runtime=remote \
    --extra-config=kubelet.container-runtime-endpoint=unix:///run/containerd/containerd.sock \
    --extra-config=kubelet.image-service-endpoint=unix:///run/containerd/containerd.sock \
    --bootstrapper=kubeadm

CRI-Oをコンテナランタイムとして使用するには以下を実行してください:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --container-runtime=cri-o \
    --bootstrapper=kubeadm

もしくは拡張バージョンを使用することもできます:

minikube start \
    --network-plugin=cni \
    --enable-default-cni \
    --extra-config=kubelet.container-runtime=remote \
    --extra-config=kubelet.container-runtime-endpoint=/var/run/crio.sock \
    --extra-config=kubelet.image-service-endpoint=/var/run/crio.sock \
    --bootstrapper=kubeadm

Dockerデーモンの再利用によるローカルイメージの使用

Kubernetesの単一のVMを使用する場合、Minikube組み込みのDockerデーモンの再利用がおすすめです。ホストマシン上にDockerレジストリを構築してイメージをプッシュする必要がなく、ローカルでの実験を加速させるMinikubeと同じDockerデーモンの中に構築することができます。

Mac/LinuxのホストでDockerデーモンを操作できるようにするには、minikube docker-envを実行します。

これにより、MinikubeのVM内のDockerデーモンと通信しているホストのMac/LinuxマシンのコマンドラインでDockerを使用できるようになります:

docker ps

Kubernetesの設定

Minikubeにはユーザーが任意の値でKubernetesコンポーネントを設定することを可能にする "configurator" 機能があります。 この機能を使うには、minikube start コマンドに --extra-config フラグを使うことができます。

このフラグは繰り返されるので、複数のオプションを設定するためにいくつかの異なる値を使って何度も渡すことができます。

このフラグは component.key=value 形式の文字列を取ります。component は下記のリストの文字列の1つです。 keyは設定構造体上の値で、 value は設定する値です。

各コンポーネントのKubernetes componentconfigs のドキュメントを調べることで有効なキーを見つけることができます。 サポートされている各設定のドキュメントは次のとおりです:

Kubeletの MaxPods 設定を5に変更するには、このフラグを渡します: --extra-config=kubelet.MaxPods=5

この機能はネストした構造体もサポートします。スケジューラーの LeaderElection.LeaderElecttrue に設定するには、このフラグを渡します: --extra-config=scheduler.LeaderElection.LeaderElect=true

apiserverAuthorizationModeRABC に設定するには、このフラグを使います: --extra-config=apiserver.authorization-mode=RBAC.

クラスターの停止

minikube stop コマンドを使ってクラスターを停止することができます。 このコマンドはMinikube仮想マシンをシャットダウンしますが、すべてのクラスターの状態とデータを保存します。 クラスターを再起動すると、以前の状態に復元されます。

クラスターの削除

minikube delete コマンドを使ってクラスターを削除することができます。 このコマンドはMinikube仮想マシンをシャットダウンして削除します。データや状態は保存されません。

minikubeのアップグレード

macOSを使用しBrew Package Managerがインストールされている場合、以下を実行します:

brew update
brew upgrade minikube

クラスターに触れてみよう

Kubectl

minikube start コマンドは "minikube" というkubectl contextを作成します。 このコンテキストはMinikubeクラスターと通信するための設定が含まれています。

Minikubeはこのコンテキストを自動的にデフォルトに設定しますが、将来的に設定を切り戻す場合には次のコマンドを実行してください:

kubectl config use-context minikube

もしくは各コマンドにコンテキストを次のように渡します:

kubectl get pods --context=minikube

ダッシュボード

Kubernetes Dashboardにアクセスするには、Minikubeを起動してアドレスを取得した後、シェルでこのコマンドを実行してください:

minikube dashboard

サービス

ノードポート経由で公開されているサービスにアクセスするには、Minikubeを起動してアドレスを取得した後、シェルでこのコマンドを実行してください:

minikube service [-n NAMESPACE] [--url] NAME

ネットワーク

MinikubeのVMは minikube ipコマンドで取得できるホストオンリーIPアドレスを介してホストシステムに公開されます。 NodePort上では、 NodePort タイプのどのサービスもそのIPアドレスを介してアクセスできます。

サービスのNodePortを決定するには、kubectl コマンドを次のように使用します:

kubectl get service $SERVICE --output='jsonpath="{.spec.ports[0].nodePort}"'

永続ボリューム

Minikubeは hostPath タイプのPersistentVolumesをサポートします。 このPersistentVolumesはMinikubeのVM内のディレクトリーにマッピングされます。

MinikubeのVMはtmpfsで起動するため、ほとんどのディレクトリーは再起動しても持続しません (minikube stop)。 しかし、Minikubeは以下のホストディレクトリーに保存されているファイルを保持するように設定されています:

  • /data
  • /var/lib/minikube
  • /var/lib/docker

以下は /data ディレクトリのデータを永続化するPersistentVolumeの設定例です:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0001
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 5Gi
  hostPath:
    path: /data/pv0001/

ホストフォルダーのマウント

一部のドライバーはVM内にホストフォルダーをマウントするため、VMとホストの間でファイルを簡単に共有できます。これらは現時点では設定可能ではなく、使用しているドライバーとOSによって異なります。

DriverOSHostFolderVM
VirtualBoxLinux/home/hosthome
VirtualBoxmacOS/Users/Users
VirtualBoxWindowsC://Users/c/Users
VMware FusionmacOS/Users/mnt/hgfs/Users
XhyvemacOS/Users/Users

プライベートコンテナレジストリ

プライベートコンテナレジストリにアクセスするには、このページの手順に従ってください。

ImagePullSecrets を使用することをおすすめしますが、MinikubeのVM内でアクセス設定したい場合には、/home/docker ディレクトリに .dockercfg を置くか、または /home/docker/.docker ディレクトリに config.json を置いてください。

アドオン

カスタムアドオンを正しく起動または再起動させるには、 Minikubeで起動したいアドオンを ~/.minikube/addons ディレクトリに置きます。 このフォルダ内のアドオンはMinikubeのVMに移動され、Minikubeが起動または再起動されるたびにアドオンが起動されます。

HTTPプロキシ経由のMinikube利用

MinikubeはKubernetesとDockerデーモンを含む仮想マシンを作成します。 KubernetesがDockerを使用してコンテナをスケジュールしようとする際、Dockerデーモンはコンテナをプルするために外部ネットワークを必要とする場合があります。

HTTPプロキシを通している場合には、プロキシ設定をDockerに提供する必要があります。 これを行うには、minikube start に必要な環境変数をフラグとして渡します。

例:

minikube start --docker-env http_proxy=http://$YOURPROXY:PORT \
               --docker-env https_proxy=https://$YOURPROXY:PORT

仮想マシンのアドレスが192.168.99.100の場合、プロキシの設定により kubectl が直接アクセスできない可能性があります。 このIPアドレスのプロキシ設定を迂回するには、以下のようにno_proxy設定を変更する必要があります。

export no_proxy=$no_proxy,$(minikube ip)

既知の問題

複数ノードを必要とする機能はMinikubeでは動作しません。

設計

MinikubeはVMのプロビジョニングにlibmachineを使用し、kubeadmをKubernetesクラスターのプロビジョニングに使用します。

Minikubeの詳細については、proposalを参照してください。

追加リンク集

  • 目標と非目標: Minikubeプロジェクトの目標と非目標については、ロードマップを参照してください。
  • 開発ガイド: プルリクエストを送る方法の概要については、コントリビュートするを参照してください。
  • Minikubeのビルド: Minikubeをソースからビルド/テストする方法については、ビルドガイドを参照してください。
  • 新しい依存性の追加: Minikubeに新しい依存性を追加する方法については、依存性追加ガイドを参照してください。
  • 新しいアドオンの追加: Minikubeに新しいアドオンを追加する方法については、アドオン追加ガイドを参照してください。
  • MicroK8s: 仮想マシンを実行したくないLinuxユーザーは代わりにMicroK8sを検討してみてください。

コミュニティ

コントリビューションや質問、コメントは歓迎・奨励されています! Minikubeの開発者はSlack#minikubeチャンネルにいます(Slackへの招待状はこちら)。dev@kubernetes Google Groupsメーリングリストもあります。メーリングリストに投稿する際は件名の最初に "minikube: " をつけてください。

1.2 - Kindを使用してKubernetesをインストールする

Kindは、Dockerコンテナをノードとして使用して、ローカルのKubernetesクラスターを実行するためのツールです。

インストール

Kindをインストールするを参照してください。

2 - プロダクション環境

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

次の項目

2.1 - コンテナランタイム

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

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

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

このページではいくつかの一般的なコンテナランタイムを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_netfilteroverlayモジュールが読み込まれていることを確認してください。

lsmod | grep br_netfilter
lsmod | grep overlay

以下のコマンドを実行して、net.bridge.bridge-nf-call-iptablesnet.bridge.bridge-nf-call-ip6tablesnet.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を設定するには、以下のようにKubeletConfigurationcgroupDriverオプションを編集してsystemdを設定します。

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

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

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

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

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

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

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

コンテナランタイム

containerd

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

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

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

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

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

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

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

/etc/containerd/config.toml内でruncsystemd cgroupドライバーを使うようにするには、次のように設定します。

[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ドライバーの利用を推奨します。

この変更を適用した場合、必ず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

  1. 各ノードに、使用しているLinuxディストリビューション用のDockerをDocker Engineのインストールに従ってインストールします。

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

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

Mirantis Container Runtime

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

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

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

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

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

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

次の項目

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

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

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

2.2.1.1 - kubeadmのインストール

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

始める前に

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

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

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

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

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

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

必須ポートの確認

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

nc 127.0.0.1 6443 -v

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # `/etc/apt/keyrings`フォルダーが存在しない場合は、curlコマンドの前に作成する必要があります。下記の備考を参照してください。
    # sudo mkdir -p -m 755 /etc/apt/keyrings
    curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
    
  1. 適切なKubernetes aptリポジトリーを追加します。このリポジトリーには、Kubernetes 1.32用のパッケージのみがあることに注意してください。他の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.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
    
  2. aptのパッケージ一覧を更新し、kubelet、kubeadm、kubectlをインストールします。そしてバージョンを固定します:

    sudo apt-get update
    sudo apt-get install -y kubelet kubeadm kubectl
    sudo apt-mark hold kubelet kubeadm kubectl
    

cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF

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

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

systemctl enable --now kubelet

Note:

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

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

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

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

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

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

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

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

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

systemctl enable --now kubelet

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

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

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

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

KUBELET_EXTRA_ARGS=--cgroup-driver=<value>

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

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

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

systemctl daemon-reload
systemctl restart kubelet

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

トラブルシュート

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

次の項目

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

sudo systemctl restart docker.service
sudo kubeadm reset

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

journalctl -u docker

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

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

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

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

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

HostPortサービスが動かない

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

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

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

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

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

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

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

TLS証明書のエラー

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

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

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

    unset KUBECONFIG
    

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    systemctl daemon-reload
    systemctl restart kubelet
    

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

始める前に

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

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

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

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

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

目的

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

手順

ホストへのkubeadmのインストール

kubeadmのインストール」を読んでください。

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

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

  1. (推奨)シングルコントロールプレーンのkubeadmクラスターを高可用性クラスターにアップグレードする予定がある場合、--control-plane-endpointを指定して、すべてのコントロールプレーンノードとエンドポイントを共有する必要があります。エンドポイントにはDNSネームやロードバランサーのIPアドレスが使用できます。
  2. Podネットワークアドオンを選んで、kubeadm initに引数を渡す必要があるかどうか確認してください。選んだサードパーティーのプロバイダーによっては、--pod-network-cidrをプロバイダー固有の値に設定する必要がある場合があります。詳しくは、Podネットワークアドオンのインストールを参照してください。
  3. (オプション)バージョン1.14から、kubeadmはよく知られたドメインソケットのパスリストを用いて、Linux上のコンテナランタイムの検出を試みます。異なるコンテナランタイムを使用する場合やプロビジョニングするノードに2つ以上のランタイムがインストールされている場合、kubeadm init--cri-socket引数を指定してください。詳しくは、ランタイムのインストールを読んでください。
  4. (オプション)明示的に指定しない限り、kubeadmはデフォルトゲートウェイに関連付けられたネットワークインターフェースを使用して、この特定のコントロールプレーンノードのAPIサーバーのadvertise addressを設定します。異なるネットワークインターフェースを使用するには、kubeadm init--apiserver-advertise-address=<ip-address>引数を指定してください。IPv6アドレスを使用するIPv6 Kubernetesクラスターをデプロイするには、たとえば--apiserver-advertise-address=fd00::101のように、IPv6アドレスを指定する必要があります。
  5. (オプション)kubeadm initを実行する前にkubeadm config images pullを実行して、gcr.ioコンテナイメージレジストリに接続できるかどうかを確認します。

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

kubeadm init <args>

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-endpointkubeadm 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ネットワークアドオンのインストール

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/mastertaintを削除します。その結果、スケジューラーはどこにでも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>

トークンがわからない場合は、コントロールプレーンノードで次のコマンドを実行すると取得できます。

kubeadm token list

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

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時間後に有効期限が切れます。もし現在のトークンの有効期限が切れた後にクラスターにノードを参加させたい場合は、コントロールプレーンノードで次のコマンドを実行することで、新しいトークンを生成できます。

kubeadm token create

このコマンドの出力は次のようになります。

5didvk.d09sbcov8ph2amjw

もし--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

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

[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

(オプション)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によってインストールされた状態をリセットします。

kubeadm reset

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

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

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

ipvsadm -C

ノードを削除します。

kubectl delete node <node name>

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

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

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

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

次の手順

フィードバック

バージョン互換ポリシー

バージョンv1.32のkubeadmツールは、バージョンv1.32またはv1.31のコントロールプレーンを持つクラスターをデプロイできます。また、バージョンv1.32のkubeadmは、バージョンv1.31のkubeadmで構築されたクラスターをアップグレートできます。

未来を見ることはできないため、kubeadm CLI v1.32はv1.33をデプロイできないかもしれません。

例: 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.2.1.4 - kubeadmを使ったコントロールプレーンの設定のカスタマイズ

FEATURE STATE: Kubernetes 1.12 [stable]

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

  • apiServer
  • controllerManager
  • scheduler

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

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

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

APIServerフラグ

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

使用例:

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

ControllerManagerフラグ

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

使用例:

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

Schedulerフラグ

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

使用例:

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

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

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

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

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

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

積層etcdトポロジー

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

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

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

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

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

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

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

積層etcdトポロジー

外部のetcdトポロジー

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

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

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

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

外部のetcdトポロジー

次の項目

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

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

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

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

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

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

始める前に

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

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

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

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

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

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

  1. DNSで解決される名前で、kube-apiserver用ロードバランサーを作成する。

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

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

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

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

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

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

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

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

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

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

    sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
    
    • --kubernetes-versionフラグで使用するKubernetesのバージョンを設定できます。kubeadm、kubelet、kubectl、Kubernetesのバージョンを一致させることが推奨されます。
    • --control-plane-endpointフラグは、ロードバランサーのIPアドレスまたはDNS名と、ポートが設定される必要があります。
    • --upload-certsフラグは全てのコントロールプレーンノードで共有する必要がある証明書をクラスターにアップロードするために使用されます。代わりに、コントロールプレーンノード間で手動あるいは自動化ツールを使用して証明書をコピーしたい場合は、このフラグを削除し、以下の証明書の手動配布のセクションを参照してください。
    • このような出力がされます:
    ...
    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
    
  2. 使用するCNIプラグインを適用します:
    こちらの手順に従いCNIプロバイダーをインストールします。該当する場合は、kubeadmの設定で指定されたPodのCIDRに対応していることを確認してください。

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

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

    kubectl get pod -n kube-system -w
    

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

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

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

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

外部のetcdノード

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

etcdクラスターの構築

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

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

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

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

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

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

    apiVersion: kubeadm.k8s.io/v1beta2
    kind: ClusterConfiguration
    kubernetesVersion: stable
    controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT"
    etcd:
        external:
            endpoints:
            - https://ETCD_0_IP:2379
            - https://ETCD_1_IP:2379
            - https://ETCD_2_IP:2379
            caFile: /etc/kubernetes/pki/etcd/ca.crt
            certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt
            keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
    
    • テンプレート内の以下の変数を、クラスターに合わせて適切な値に置き換えます:

      • LOAD_BALANCER_DNS
      • LOAD_BALANCER_PORT
      • ETCD_0_IP
      • ETCD_1_IP
      • ETCD_2_IP

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

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

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

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

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

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

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

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

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

workerのインストール

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

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

証明書の手動配布

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

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

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

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

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

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

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

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

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

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

    USER=ubuntu # 環境に合わせる
    CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8"
    for host in ${CONTROL_PLANE_IPS}; do
        scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
        scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
        scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
        scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
        scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
        scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
        scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
        # 外部のetcdノード使用時はこちらのコマンドを実行
        scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
    done
    
  5. 次に、クラスターに参加させる残りの各コントロールプレーンノードでkubeadm joinを実行する前に次のスクリプトを実行する必要があります。このスクリプトは、前の手順でコピーした証明書をホームディレクトリから/etc/kubernetes/pkiへ移動します:

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

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

Kubeadm 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.

  1. 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
    
  2. 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
    
  3. 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
  4. 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
    
  5. 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/
    
  6. 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
    
  7. 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
    
  8. 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.2.1.8 - kubeadmを使用したクラスター内の各kubeletの設定

FEATURE STATE: Kubernetes 1.11 [stable]

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

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

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

Kubeletの設定パターン

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

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

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

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

kubeadm init --service-cidr 10.96.0.0/12

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

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

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

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

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

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

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

kubeadmを使用したkubeletの設定

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

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

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

kubeadm init実行時の流れ

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

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

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

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

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

systemctl daemon-reload && systemctl restart kubelet

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

kubeadm join実行時の流れ

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

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

systemctl daemon-reload && systemctl restart kubelet

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

kubelet用のsystemdファイル

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

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

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

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

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

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

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

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

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

FEATURE STATE: Kubernetes v1.23 [stable]

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

始める前に

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

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

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

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

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

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

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

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

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

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

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

kubeadm init --config=kubeadm-config.yaml

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

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

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

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

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

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

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

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

kubeadm join --config=kubeadm-config.yaml

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

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

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

次の項目

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

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

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

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

警告

  1. 1.8以降のセルフホスティングには、いくつかの重要な制限があります。特に、セルフホスト型クラスターは、手動の介入なしにコントロールプレーンのNode再起動から回復することはできません。

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

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

プロセス

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

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

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

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

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

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

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

2.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.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
  • 継続的インテグレーションテスト。

あなたのユースケースに最適なツールの選択には、kubeadmkops比較したドキュメントを参照してください。

クラスターの作成

(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はクラスターを管理する追加のプレイブックを提供します: scaleupgrade

クラスターのスケール

scaleプレイブックを実行することで、クラスターにワーカーノードを追加することができます。詳細については、"ノードの追加"を参照してください。 remove-nodeプレイブックを実行することで、クラスターからワーカーノードを削除することができます。詳細については、"ノードの削除"を参照してください。

クラスターのアップグレード

upgrade-clusterプレイブックを実行することで、クラスターのアップグレードができます。詳細については、"アップグレード"を参照してください。

クリーンアップ

resetプレイブックを使用して、ノードをリセットし、Kubesprayでインストールした全てのコンポーネントを消すことができます。

フィードバック

次の項目

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

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

2.4 - Windows in Kubernetes

2.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のドキュメントを参照してください。

サポートされている機能と制限

サポートされている機能

コンピュート

APIとkubectlの観点から見ると、WindowsコンテナはLinuxベースのコンテナとほとんど同じように動作します。ただし、制限セクションで概説されている主要な機能には、いくつかの顕著な違いがあります。

オペレーティングシステムのバージョンから始めましょう。KubernetesのWindowsオペレーティングシステムのサポートについては、次の表を参照してください。単一の混成Kubernetesクラスターは、WindowsとLinuxの両方のワーカーノードを持つことができます。WindowsコンテナはWindowsノードで、LinuxコンテナはLinuxノードでスケジュールする必要があります。

Kubernetes バージョンホストOS バージョン (Kubernetes ノード)
Windows Server 1709Windows Server 1803Windows Server 1809/Windows Server 2019
Kubernetes v1.14サポートされていませんサポートされていませんWindows Server containers Builds 17763.* と Docker EE-basic 18.09 がサポートされています

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ボリュームを使用すると、データの永続性と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-bridgeAzure-CNI、Flannelホストゲートウェイは、win-bridgeを使用します。win-bridgeはL2bridgeネットワークモードを使用して、コンテナをホストのアンダーレイに接続して、最高のパフォーマンスを提供します。ノード間接続にはユーザー定義ルート(UDR)が必要です。
L2Tunnelこれはl2bridgeの特殊なケースですが、Azureでのみ使用されます。すべてのパケットは、SDNポリシーが適用されている仮想化ホストに送信されます。MACが書き換えられ、IPがアンダーレイネットワークで表示されます。Azure-CNIAzure-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-kubernetesansible経由でデプロイします。分散ACLは、Kubernetesポリシーを介して適用できます。 IPAMをサポートします。負荷分散は、kube-proxyなしで実現できます。 NATは、ip​​tables/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オプションがサポートされています。

  • ホストローカル
  • HNS IPAM (受信トレイプラットフォームIPAM、これはIPAMが設定されていない場合のフォールバック)
  • Azure-vnet-ipam(azure-cniのみ)

制限

コントロールプレーン

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で追加されました。

  • kubectl port-forward
CNIプラグイン
  • Windowsリファレンスネットワークプラグインのwin-bridgeとwin-overlayは、CNI仕様v0.4.0において「CHECK」実装がないため、今のところ実装されていません。
  • Flannel VXLAN CNIについては、Windowsで次の制限があります。:
  1. Node-podの直接間接続は設計上不可能です。FlannelPR 1096を使用するローカルPodでのみ可能です
  2. 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.localkubernetesの両方を名前解決できますが、kubernetes.defaultkubernetes.default.svcのような中間での名前解決はできません。
  • Windowsでは、複数のDNSリゾルバーを使用できます。これらには少し異なる動作が付属しているため、ネームクエリの解決にはResolve-DNSNameユーティリティを使用することをお勧めします。
セキュリティ

Secretはノードのボリュームに平文テキストで書き込まれます(Linuxのtmpfs/in-memoryの比較として)。これはカスタマーが2つのことを行う必要があります

  1. ファイルACLを使用してSecretファイルの場所を保護する
  2. 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ログ収集に関するコントリビュートガイドの指示に従ってください。

  1. start.ps1が正常に完了したことをどのように確認できますか?

    ノード上でkubelet、kube-proxy、および(ネットワーキングソリューションとしてFlannelを選択した場合)flanneldホストエージェントプロセスが実行され、実行ログが個別のPowerShellウィンドウに表示されます。これに加えて、WindowsノードがKubernetesクラスターで「Ready」として表示されているはずです。

  2. Kubernetesノードのプロセスをサービスとしてバックグラウンドで実行するように構成できますか?

    Kubeletとkube-proxyは、ネイティブのWindowsサービスとして実行するように既に構成されています、障害(例えば、プロセスのクラッシュ)が発生した場合にサービスを自動的に再起動することにより、復元性を提供します。これらのノードコンポーネントをサービスとして構成するには、2つのオプションがあります。

    1. ネイティブ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
      
    2. 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の使用法のドキュメントを参照してください。

  3. Windows Podにネットワーク接続がありません

    仮想マシンを使用している場合は、すべてのVMネットワークアダプターでMACスプーフィングが有効になっていることを確認してください。

  4. 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" # 管理 (ホスト) のサブネット
                ]
    
  5. WindowsノードがNodePort Serviceにアクセスできません

    ノード自体からのローカルNodePortアクセスは失敗します。これは既知の制限です。NodePortアクセスは、他のノードまたは外部クライアントから行えます。

  6. コンテナのvNICとHNSエンドポイントが削除されています

    この問題は、hostname-overrideパラメーターがkube-proxyに渡されない場合に発生する可能性があります。これを解決するには、ユーザーは次のようにホスト名をkube-proxyに渡す必要があります。:

    C:\k\kube-proxy.exe --hostname-override=$(hostname)
    
  7. flannelを使用すると、クラスターに再参加した後、ノードに問題が発生します

    以前に削除されたノードがクラスターに再参加するときはいつも、flannelDは新しいPodサブネットをノードに割り当てようとします。ユーザーは、次のパスにある古いPodサブネット構成ファイルを削除する必要があります。:

    Remove-Item C:\k\SourceVip.json
    Remove-Item C:\k\SourceVipRequest.json
    
  8. 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
    
  9. /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
    
  10. WindowsノードがService IPを使用してServiceにアクセスできない

    これは、Windows上の現在のネットワークスタックの既知の制限です。ただし、Windows PodはService IPにアクセスできます。

  11. kubeletの起動時にネットワークアダプターが見つかりません

    WindowsネットワーキングスタックがKubernetesネットワーキングを動かすには、仮想アダプターが必要です。次のコマンドを実行しても結果が返されない場合(管理シェルで)、仮想ネットワークの作成(Kubeletが機能するために必要な前提条件)に失敗したことになります。:

    Get-HnsNetwork | ? Name -ieq "cbr0"
    Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"
    

    ホストのネットワークアダプターが「イーサネット」ではない場合、多くの場合、start.ps1スクリプトのInterfaceNameパラメーターを修正する価値があります。そうでない場合はstart-kubelet.ps1スクリプトの出力結果を調べて、仮想ネットワークの作成中にエラーがないか確認します。

  12. 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でリリースしています。

  13. DNS名前解決が正しく機能していない

    このセクションでDNSの制限を確認してください。

  14. kubectl port-forwardが「ポート転送を実行できません:wincatが見つかりません」で失敗します

    これはKubernetes 1.15、およびPauseインフラストラクチャコンテナmcr.microsoft.com/k8s/core/pause:1.2.0で実装されました。必ずこれらのバージョン以降を使用してください。 独自のPauseインフラストラクチャコンテナを構築する場合は、必ずwincatを含めてください。

  15. 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)
    
  16. 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
  • その他のストレージプラグイン

2.4.2 - KubernetesでWindowsコンテナをスケジュールするためのガイド

Windowsアプリケーションは、多くの組織で実行されるサービスとアプリケーションの大部分を占めます。このガイドでは、KubernetesでWindowsコンテナを構成してデプロイする手順について説明します。

目的

  • WindowsノードでWindowsコンテナを実行するサンプルのDeploymentを構成します
  • (オプション)Group Managed Service Accounts(GMSA)を使用してPodのActive Directory IDを構成します

始める前に

  • Windows Serverを実行するマスターノードとワーカーノードを含むKubernetesクラスターを作成します
  • Kubernetes上にServiceとワークロードを作成してデプロイすることは、LinuxコンテナとWindowsコンテナ共に、ほぼ同じように動作することに注意してください。クラスターとのインターフェースとなるKubectlコマンドも同じです。Windowsコンテナをすぐに体験できる例を以下セクションに用意しています。

はじめに: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
  1. すべてのノードが正常であることを確認します。:

    kubectl get nodes
    
  2. Serviceをデプロイして、Podの更新を確認します。:

    kubectl apply -f win-webserver.yaml
    kubectl get pods -o wide -w
    

    Serviceが正しくデプロイされると、両方のPodがReadyとして表示されます。watch状態のコマンドを終了するには、Ctrl + Cを押します。

  3. デプロイが成功したことを確認します。検証するために行うこと:

    • 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コンテナ内のワークロードの動作は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 201910.0.17763
Windows Server version 180910.0.17763
Windows Server version 190310.0.18362

RuntimeClassによる簡素化

RuntimeClassは、TaintsとTolerationsを使用するプロセスを簡略化するために使用できます。クラスター管理者は、これらのTaintsとTolerationsをカプセル化するために使用するRuntimeClassオブジェクトを作成できます。

  1. このファイルを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"
  1. クラスター管理者として使用するkubectl create -f runtimeClasses.ymlを実行します
  2. 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

3 - ベストプラクティス

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

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

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

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

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

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

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

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

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

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

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

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

etcdストレージ

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

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

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

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

アドオンのリソース

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

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

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

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

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

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

次の項目

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

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

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

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

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

背景

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

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

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

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

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

ノードの動作

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

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

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

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

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

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

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

Podの手動ゾーン割り当て

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

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

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

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

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

ネットワーキング

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

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

障害回復

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

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

次の項目

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

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

ノード適合テスト

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

ノードの前提条件

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

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

ノード適合テストの実行

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

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

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

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

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

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

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

選択したテストの実行

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

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

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

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

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

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

注意事項

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

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

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

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

FEATURE STATE: Kubernetes v1.25 [stable]

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

すべてのNamespaceに設定する

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

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

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

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

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

マルチモード戦略の採用

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

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

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

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

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

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

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

3.5 - PKI証明書とその要件

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

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

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

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

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

証明書の保存場所

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

手動で証明書を設定する

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

単一ルート認証局

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

必要な認証局:

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

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

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

全ての証明書

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

必要な証明書:

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

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

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

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

証明書のパス

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

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

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

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

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

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

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

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

ファイル名クレデンシャル名デフォルトCNO (in Subject)
admin.confdefault-adminkubernetes-admin<admin-group>
super-admin.confdefault-super-adminkubernetes-super-adminsystem:masters
kubelet.confdefault-authsystem:node:<nodeName> (備考を参照)system:nodes
controller-manager.confdefault-controller-managersystem:kube-controller-manager
scheduler.confdefault-schedulersystem:kube-scheduler
  1. 各コンフィグ毎に、CN名と組織を指定してx509証明書と鍵ペアを生成してください。

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

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

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

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

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

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