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

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

ドキュメント

1 - Kubernetesドキュメント

Kubernetesは、コンテナ化されたアプリケーションの展開、スケーリング、また管理を自動化するためのオープンソースコンテナプラットフォームです。このオープンソースプロジェクトは、Cloud Native Computing Foundationによってホストされています。

1.1 - 利用可能なドキュメントバージョン

本ウェブサイトには、現行版とその直前4バージョンのKubernetesドキュメントがあります。

2 - はじめに

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

Kubernetesクラスタはローカルマシン、クラウド、オンプレのデータセンターにデプロイすることもできますし、マネージドのKubernetesクラスターを選択することもできます。複数のクラウドプロバイダーやベアメタルの環境に跨ったカスタムソリューションもあります。

環境について学ぶ

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

本番環境

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

Certified Kubernetesプロバイダーの一覧については、Kubernetes パートナーを参照してください。

2.1 - リリースノートおよびバージョンスキュー

2.1.1 - Kubernetesバージョンとバージョンスキューサポートポリシー

このドキュメントでは、さまざまなKubernetesコンポーネント間でサポートされる最大のバージョンの差異(バージョンスキュー)について説明します。特定のクラスターデプロイツールは、バージョンの差異に追加の制限を加える場合があります。

サポートされるバージョン

Kubernetesのバージョンはx.y.zの形式で表現され、xはメジャーバージョン、yはマイナーバージョン、zはパッチバージョンを指します。これはセマンティック バージョニングに従っています。詳細は、Kubernetesのリリースバージョニングを参照してください。

Kubernetesプロジェクトでは、最新の3つのマイナーリリースについてリリースブランチを管理しています (1.24, 1.23, 1.22)。

セキュリティフィックスを含む適用可能な修正は、重大度や実行可能性によってはこれら3つのリリースブランチにバックポートされることもあります。パッチリリースは、これらのブランチから 定期的に 切り出され、必要に応じて追加の緊急リリースも行われます。

リリースマネージャーグループがこれを決定しています。

詳細は、Kubernetesパッチリリースページを参照してください。

サポートされるバージョンの差異

kube-apiserver

高可用性 (HA) クラスターでは、最新および最古のkube-apiserverインスタンスがそれぞれ1つのマイナーバージョン内でなければなりません。

例:

  • 最新のkube-apiserver1.24であるとします
  • ほかのkube-apiserverインスタンスは1.24および1.23がサポートされます

kubelet

kubeletkube-apiserverより新しいものであってはならず、2つの古いマイナーバージョンまで有効です。

例:

  • kube-apiserver1.24であるとします
  • kubelet1.241.23および1.22がサポートされます

例:

  • kube-apiserverインスタンスが1.24および1.12であるとします
  • kubelet1.23および1.22がサポートされます(1.24はバージョン1.23kube-apiserverよりも新しくなるためサポートされません)

kube-controller-manager、kube-scheduler、およびcloud-controller-manager

kube-controller-managerkube-schedulerおよびcloud-controller-managerは、通信するkube-apiserverインスタンスよりも新しいバージョンであってはなりません。kube-apiserverのマイナーバージョンと一致することが期待されますが、1つ古いマイナーバージョンでも可能です(ライブアップグレードを可能にするため)。

例:

  • kube-apiserver1.24であるとします
  • kube-controller-managerkube-schedulerおよびcloud-controller-manager1.24および1.23がサポートされます

例:

  • kube-apiserverインスタンスが1.24および1.23であるとします
  • いずれかのkube-apiserverインスタンスへ配信するロードバランサーと通信するkube-controller-managerkube-schedulerおよびcloud-controller-manager1.23がサポートされます(1.24はバージョン1.23kube-apiserverよりも新しくなるためサポートされません)

kubectl

kubectlkube-apiserverの1つ以内のバージョン(古い、または新しいもの)をサポートします。

例:

  • kube-apiserver1.24であるとします
  • kubectl1.251.24および1.23がサポートされます

例:

  • kube-apiserverインスタンスが1.24および1.23であるとします
  • kubectl1.24および1.23がサポートされます(ほかのバージョンでは、あるkube-apiserverコンポーネントからマイナーバージョンが2つ以上離れる可能性があります)

サポートされるコンポーネントのアップグレード順序

コンポーネント間でサポートされるバージョンの差異は、コンポーネントをアップグレードする順序に影響されます。このセクションでは、既存のクラスターをバージョン1.23から1.24 へ移行するために、コンポーネントをアップグレードする順序を説明します。

kube-apiserver

前提条件:

  • シングルインスタンスのクラスターにおいて、既存のkube-apiserverインスタンスは1.23とします
  • HAクラスターにおいて、既存のkube-apiserver1.23または1.24 とします(最新と最古の間で、最大で1つのマイナーバージョンの差異となります)
  • サーバーと通信するkube-controller-managerkube-schedulerおよびcloud-controller-managerはバージョン1.23とします(必ず既存のAPIサーバーのバージョンよりも新しいものでなく、かつ新しいAPIサーバーのバージョンの1つ以内のマイナーバージョンとなります)
  • すべてのノードのkubeletインスタンスはバージョン1.23または1.22 とします(必ず既存のAPIサーバーよりも新しいバージョンでなく、かつ新しいAPIサーバーのバージョンの2つ以内のマイナーバージョンとなります)
  • 登録されたAdmission webhookは、新しいkube-apiserverインスタンスが送信するこれらのデータを扱うことができます:
    • ValidatingWebhookConfigurationおよびMutatingWebhookConfigurationオブジェクトは、1.24 で追加されたRESTリソースの新しいバージョンを含んで更新されます(または、v1.15から利用可能なmatchPolicy: Equivalentオプションを使用してください)
    • Webhookは送信されたRESTリソースの新しいバージョン、および1.24 のバージョンで追加された新しいフィールドを扱うことができます

kube-apiserver1.24 にアップグレードしてください。

kube-controller-manager、kube-scheduler、およびcloud-controller-manager

前提条件:

  • これらのコンポーネントと通信するkube-apiserverインスタンスが1.24 であること(これらのコントロールプレーンコンポーネントが、クラスター内のkube-apiserverインスタンスと通信できるHAクラスターでは、これらのコンポーネントをアップグレードする前にすべてのkube-apiserverインスタンスをアップグレードしなければなりません)

kube-controller-managerkube-schedulerおよびcloud-controller-manager1.24 にアップグレードしてください。

kubelet

前提条件:

  • kubeletと通信するkube-apiserver1.24 であること

必要に応じて、kubeletインスタンスを1.24 にアップグレードしてください(1.231.22 のままにすることもできます)。

kube-proxy

  • kube-proxyのマイナーバージョンはノード上のkubeletと同じマイナーバージョンでなければなりません
  • kube-proxykube-apiserverよりも新しいものであってはなりません
  • kube-proxyのマイナーバージョンはkube-apiserverのマイナーバージョンよりも2つ以上古いものでなければなりません

例:

kube-proxyのバージョンが1.22の場合:

  • kubeletのバージョンは1.22でなければなりません
  • kube-apiserverのバージョンは1.221.24の間でなければなりません

2.2 - 学習環境

2.2.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=k8s.gcr.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の特定のバージョンを指定することができます。 例えば、v1.24.0のバージョンを実行するには以下を実行します:

minikube start --kubernetes-version v1.24.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: " をつけてください。

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

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

インストール

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

2.3 - プロダクション環境

2.3.1 - CRIのインストール

FEATURE STATE: Kubernetes v1.6 [stable]
Podのコンテナを実行するために、Kubernetesはコンテナランタイムを使用します。 様々なランタイムのインストール手順は次のとおりです。

適用性

このガイドでは全てのコマンドを root で実行します。 例として、コマンドに sudo を付けたり、 root になってそのユーザーでコマンドを実行します。

Cgroupドライバー

systemdがLinuxのディストリビューションのinitシステムとして選択されている場合、 initプロセスが作成され、rootコントロールグループ(cgroup)を使い、cgroupマネージャーとして行動します。 systemdはcgroupと密接に統合されており、プロセスごとにcgroupを割り当てます。 cgroupfs を使うように、あなたのコンテナランライムとkubeletを設定することができます。 systemdと一緒に cgroupfs を使用するということは、2つの異なるcgroupマネージャーがあることを意味します。

コントロールグループはプロセスに割り当てられるリソースを制御するために使用されます。 単一のcgroupマネージャーは、割り当てられているリソースのビューを単純化し、 デフォルトでは使用可能なリソースと使用中のリソースについてより一貫性のあるビューになります。 2つのマネージャーがある場合、それらのリソースについて2つのビューが得られます。 kubeletとDockerに cgroupfs を使用し、ノード上で実行されている残りのプロセスに systemd を使用するように設定されたノードが、 リソース圧迫下で不安定になる場合があります。

コンテナランタイムとkubeletがcgroupドライバーとしてsystemdを使用するように設定を変更することでシステムは安定します。 以下のDocker設定の native.cgroupdriver=systemd オプションに注意してください。

Docker

それぞれのマシンに対してDockerをインストールします。 バージョン19.03.11が推奨されていますが、1.13.1、17.03、17.06、17.09、18.06、18.09についても動作が確認されています。 Kubernetesのリリースノートにある、Dockerの動作確認済み最新バージョンについてもご確認ください。

システムへDockerをインストールするには、次のコマンドを実行します。

# (Install Docker CE)
## リポジトリをセットアップ
### HTTPS越しのリポジトリの使用をaptに許可するために、パッケージをインストール
apt-get update && apt-get install -y \
  apt-transport-https ca-certificates curl software-properties-common gnupg2
# Docker公式のGPG鍵を追加:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
# Dockerのaptレポジトリを追加:
add-apt-repository \
  "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) \
  stable"
# Docker CEのインストール
apt-get update && apt-get install -y \
containerd.io=1.2.13-2 \
docker-ce=5:19.03.11~3-0~ubuntu-$(lsb_release -cs) \
docker-ce-cli=5:19.03.11~3-0~ubuntu-$(lsb_release -cs)
# デーモンをセットアップ
cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
# dockerを再起動
systemctl daemon-reload
systemctl restart docker

# (Docker CEのインストール)
## リポジトリをセットアップ
### 必要なパッケージのインストール
yum install -y yum-utils device-mapper-persistent-data lvm2
## Dockerリポジトリの追加
yum-config-manager --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo
## Docker CEのインストール
yum update -y && yum install -y \
  containerd.io-1.2.13 \
  docker-ce-19.03.11 \
  docker-ce-cli-19.03.11
## /etc/docker ディレクトリを作成
mkdir /etc/docker
# デーモンをセットアップ
cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
# dockerを再起動
systemctl daemon-reload
systemctl restart docker

ブート時にDockerサービスを開始させたい場合は、以下のコマンドを入力してください:

sudo systemctl enable docker

詳細については、Dockerの公式インストールガイドを参照してください。

CRI-O

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

システムへCRI-Oをインストールするためには以下のコマンドを利用します:

事前準備

modprobe overlay
modprobe br_netfilter

# 必要なカーネルパラメータの設定をします。これらの設定値は再起動後も永続化されます。
cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sysctl --system

CRI-Oを以下のOSにインストールするには、環境変数$OSを以下の表の適切なフィールドに設定します。

Operating system$OS
Debian UnstableDebian_Unstable
Debian TestingDebian_Testing

そして、`$VERSION`にKubernetesのバージョンに合わせたCRI-Oのバージョンを設定します。例えば、CRI-O 1.18をインストールしたい場合は、`VERSION=1.18` を設定します。インストールを特定のリリースに固定することができます。バージョン 1.18.3をインストールするには、`VERSION=1.18:1.18.3` を設定します。

以下を実行します。

echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | apt-key add -
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key add -

apt-get update
apt-get install cri-o cri-o-runc

CRI-Oを以下のOSにインストールするには、環境変数$OSを以下の表の適切なフィールドに設定します。

Operating system$OS
Ubuntu 20.04xUbuntu_20.04
Ubuntu 19.10xUbuntu_19.10
Ubuntu 19.04xUbuntu_19.04
Ubuntu 18.04xUbuntu_18.04

次に、`$VERSION`をKubernetesのバージョンと一致するCRI-Oのバージョンに設定します。例えば、CRI-O 1.18をインストールしたい場合は、`VERSION=1.18` を設定します。インストールを特定のリリースに固定することができます。バージョン 1.18.3 をインストールするには、`VERSION=1.18:1.18.3` を設定します。

以下を実行します。

echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable:/cri-o:/$VERSION/$OS/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.list

curl -L https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/Release.key | apt-key add -
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/Release.key | apt-key add -

apt-get update
apt-get install cri-o cri-o-runc

CRI-Oを以下のOSにインストールするには、環境変数$OSを以下の表の適切なフィールドに設定します。

Operating system$OS
Centos 8CentOS_8
Centos 8 StreamCentOS_8_Stream
Centos 7CentOS_7

次に、`$VERSION`をKubernetesのバージョンと一致するCRI-Oのバージョンに設定します。例えば、CRI-O 1.18 をインストールしたい場合は、`VERSION=1.18` を設定します。インストールを特定のリリースに固定することができます。バージョン 1.18.3 をインストールするには、`VERSION=1.18:1.18.3` を設定します。

以下を実行します。

curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/$OS/devel:kubic:libcontainers:stable.repo
curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/$OS/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
yum install cri-o

 sudo zypper install cri-o

$VERSIONには、Kubernetesのバージョンと一致するCRI-Oのバージョンを設定します。例えば、CRI-O 1.18をインストールしたい場合は、$VERSION=1.18を設定します。 以下のコマンドで、利用可能なバージョンを見つけることができます。

dnf module list cri-o

CRI-OはFedoraの特定のリリースにピン留めすることをサポートしていません。

以下を実行します。

dnf module enable cri-o:$VERSION
dnf install cri-o

CRI-Oの起動

systemctl daemon-reload
systemctl start crio

詳細については、CRI-Oインストールガイドを参照してください。

Containerd

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

システムへContainerdをインストールするためには次のコマンドを実行します。

必要な設定の追加

cat > /etc/modules-load.d/containerd.conf <<EOF
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

# 必要なカーネルパラメータの設定をします。これらの設定値は再起動後も永続化されます。
cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF

sysctl --system

containerdのインストール

# (containerdのインストール)
## リポジトリの設定
### HTTPS越しのリポジトリの使用をaptに許可するために、パッケージをインストール
apt-get update && apt-get install -y apt-transport-https ca-certificates curl software-properties-common
## Docker公式のGPG鍵を追加
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
## Dockerのaptリポジトリの追加
add-apt-repository \
    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
    $(lsb_release -cs) \
    stable"
## containerdのインストール
apt-get update && apt-get install -y containerd.io
# containerdの設定
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# containerdの再起動
systemctl restart containerd

# (containerdのインストール)
## リポジトリの設定
### 必要なパッケージのインストール
yum install -y yum-utils device-mapper-persistent-data lvm2
## Dockerのリポジトリの追加
yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo
## containerdのインストール
yum update -y && yum install -y containerd.io
## containerdの設定
mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# containerdの再起動
systemctl restart containerd

systemd

systemdのcgroupドライバーを使うには、/etc/containerd/config.toml内でplugins.cri.systemd_cgroup = trueを設定してください。 kubeadmを使う場合はkubeletのためのcgroupドライバーを手動で設定してください。

その他のCRIランタイム: frakti

詳細についてはFraktiのクイックスタートガイドを参照してください。

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

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

2.3.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クラスターのアドレスが適切なアダプターを経由するように設定することをお勧めします。

iptablesがブリッジを通過するトラフィックを処理できるようにする

Linuxノードのiptablesがブリッジを通過するトラフィックを正確に処理する要件として、net.bridge.bridge-nf-call-iptablessysctlの設定ファイルで1に設定してください。例えば以下のようにします。

cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

この手順の前にbr_netfilterモジュールがロードされていることを確認してください。lsmod | grep br_netfilterを実行することで確認できます。明示的にロードするにはmodprobe br_netfilterを実行してください。

詳細はネットワークプラグインの要件を参照してください。

iptablesがnftablesバックエンドを使用しないようにする

Linuxでは、カーネルのiptablesサブシステムの最新の代替品としてnftablesが利用できます。iptablesツールは互換性レイヤーとして機能し、iptablesのように動作しますが、実際にはnftablesを設定します。このnftablesバックエンドは現在のkubeadmパッケージと互換性がありません。(ファイアウォールルールが重複し、kube-proxyを破壊するためです。)

もしあなたのシステムのiptablesツールがnftablesバックエンドを使用している場合、これらの問題を避けるためにiptablesツールをレガシーモードに切り替える必要があります。これは、少なくともDebian 10(Buster)、Ubuntu 19.04、Fedora 29、およびこれらのディストリビューションの新しいリリースでのデフォルトです。RHEL 8はレガシーモードへの切り替えをサポートしていないため、現在のkubeadmパッケージと互換性がありません。

# レガシーバイナリがインストールされていることを確認してください
sudo apt-get install -y iptables arptables ebtables

# レガシーバージョンに切り替えてください。
sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo update-alternatives --set arptables /usr/sbin/arptables-legacy
sudo update-alternatives --set ebtables /usr/sbin/ebtables-legacy

update-alternatives --set iptables /usr/sbin/iptables-legacy

必須ポートの確認

コントロールプレーンノード

プロトコル通信の向きポート範囲目的使用者
TCPInbound6443*Kubernetes API server全て
TCPInbound2379-2380etcd server client APIkube-apiserver、etcd
TCPInbound10250Kubelet API自身、コントロールプレーン
TCPInbound10251kube-scheduler自身
TCPInbound10252kube-controller-manager自身

ワーカーノード

プロトコル通信の向きポート範囲目的使用者
TCPInbound10250Kubelet API自身、コントロールプレーン
TCPInbound30000-32767NodePort Service†全て

NodePort Serviceのデフォルトのポートの範囲

*の項目は書き換え可能です。そのため、あなたが指定したカスタムポートも開いていることを確認する必要があります。

etcdポートはコントロールプレーンノードに含まれていますが、独自のetcdクラスターを外部またはカスタムポートでホストすることもできます。

使用する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)に関しては下記を参照してください。

sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
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/yum-key.gpg 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://storage.googleapis.com/kubernetes-release/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.3.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.3.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.24向けに書かれています。

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.24のkubeadmツールは、バージョンv1.24またはv1.23のコントロールプレーンを持つクラスターをデプロイできます。また、バージョンv1.24のkubeadmは、バージョンv1.23のkubeadmで構築されたクラスターをアップグレートできます。

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

例: 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.3.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.3.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.3.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.3.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 (k8s.gcr.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 k8s.gcr.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.3.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.3.2.1.9 - コントロールプレーンをセルフホストするように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.3.2.2 - kopsを使ったAWS上でのKubernetesのインストール

This quickstart shows you how to easily install a Kubernetes cluster on AWS. It uses a tool called kops.

kops is an automated provisioning system:

  • Fully automated installation
  • Uses DNS to identify clusters
  • Self-healing: everything runs in Auto-Scaling Groups
  • Multiple OS support (Debian, Ubuntu 16.04 supported, CentOS & RHEL, Amazon Linux and CoreOS) - see the images.md
  • High-Availability support - see the high_availability.md
  • Can directly provision, or generate terraform manifests - see the terraform.md

始める前に

クラスタの作成

(1/5) kopsのインストール

インストール

Download kops from the releases page (it is also easy to build from source):

Download the latest release with the command:

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-darwin-amd64

To download a specific version, replace the following portion of the command with the specific kops version.

$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)

For example, to download kops version v1.20.0 type:

curl -LO https://github.com/kubernetes/kops/releases/download/v1.20.0/kops-darwin-amd64

Make the kops binary executable.

chmod +x kops-darwin-amd64

Move the kops binary in to your PATH.

sudo mv kops-darwin-amd64 /usr/local/bin/kops

You can also install kops using Homebrew.

brew update && brew install kops

Download the latest release with the command:

curl -LO https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64

To download a specific version of kops, replace the following portion of the command with the specific kops version.

$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)

For example, to download kops version v1.20.0 type:

curl -LO https://github.com/kubernetes/kops/releases/download/v1.20.0/kops-linux-amd64

Make the kops binary executable

chmod +x kops-linux-amd64

Move the kops binary in to your PATH.

sudo mv kops-linux-amd64 /usr/local/bin/kops

You can also install kops using Homebrew.

brew update && brew install kops

(2/5) クラスタ用のroute53ドメインの作成

kops uses DNS for discovery, both inside the cluster and outside, so that you can reach the kubernetes API server from clients.

kops has a strong opinion on the cluster name: it should be a valid DNS name. By doing so you will no longer get your clusters confused, you can share clusters with your colleagues unambiguously, and you can reach them without relying on remembering an IP address.

You can, and probably should, use subdomains to divide your clusters. As our example we will use useast1.dev.example.com. The API server endpoint will then be api.useast1.dev.example.com.

A Route53 hosted zone can serve subdomains. Your hosted zone could be useast1.dev.example.com, but also dev.example.com or even example.com. kops works with any of these, so typically you choose for organization reasons (e.g. you are allowed to create records under dev.example.com, but not under example.com).

Let's assume you're using dev.example.com as your hosted zone. You create that hosted zone using the normal process, or with a command such as aws route53 create-hosted-zone --name dev.example.com --caller-reference 1.

You must then set up your NS records in the parent domain, so that records in the domain will resolve. Here, you would create NS records in example.com for dev. If it is a root domain name you would configure the NS records at your domain registrar (e.g. example.com would need to be configured where you bought example.com).

This step is easy to mess up (it is the #1 cause of problems!) You can double-check that your cluster is configured correctly if you have the dig tool by running:

dig NS dev.example.com

You should see the 4 NS records that Route53 assigned your hosted zone.

(3/5) クラスタの状態を保存するS3バケットの作成

kops lets you manage your clusters even after installation. To do this, it must keep track of the clusters that you have created, along with their configuration, the keys they are using etc. This information is stored in an S3 bucket. S3 permissions are used to control access to the bucket.

Multiple clusters can use the same S3 bucket, and you can share an S3 bucket between your colleagues that administer the same clusters - this is much easier than passing around kubecfg files. But anyone with access to the S3 bucket will have administrative access to all your clusters, so you don't want to share it beyond the operations team.

So typically you have one S3 bucket for each ops team (and often the name will correspond to the name of the hosted zone above!)

In our example, we chose dev.example.com as our hosted zone, so let's pick clusters.dev.example.com as the S3 bucket name.

  • Export AWS_PROFILE (if you need to select a profile for the AWS CLI to work)

  • Create the S3 bucket using aws s3 mb s3://clusters.dev.example.com

  • You can export KOPS_STATE_STORE=s3://clusters.dev.example.com and then kops will use this location by default. We suggest putting this in your bash profile or similar.

(4/5) クラスタ設定の構築

Run kops create cluster to create your cluster configuration:

kops create cluster --zones=us-east-1c useast1.dev.example.com

kops will create the configuration for your cluster. Note that it only creates the configuration, it does not actually create the cloud resources - you'll do that in the next step with a kops update cluster. This give you an opportunity to review the configuration or change it.

It prints commands you can use to explore further:

  • List your clusters with: kops get cluster
  • Edit this cluster with: kops edit cluster useast1.dev.example.com
  • Edit your node instance group: kops edit ig --name=useast1.dev.example.com nodes
  • Edit your master instance group: kops edit ig --name=useast1.dev.example.com master-us-east-1c

If this is your first time using kops, do spend a few minutes to try those out! An instance group is a set of instances, which will be registered as kubernetes nodes. On AWS this is implemented via auto-scaling-groups. You can have several instance groups, for example if you wanted nodes that are a mix of spot and on-demand instances, or GPU and non-GPU instances.

(5/5) AWSにクラスタを作成

Run "kops update cluster" to create your cluster in AWS:

kops update cluster useast1.dev.example.com --yes

That takes a few seconds to run, but then your cluster will likely take a few minutes to actually be ready. kops update cluster will be the tool you'll use whenever you change the configuration of your cluster; it applies the changes you have made to the configuration to your cluster - reconfiguring AWS or kubernetes as needed.

For example, after you kops edit ig nodes, then kops update cluster --yes to apply your configuration, and sometimes you will also have to kops rolling-update cluster to roll out the configuration immediately.

Without --yes, kops update cluster will show you a preview of what it is going to do. This is handy for production clusters!

他のアドオンの参照

See the list of add-ons to explore other add-ons, including tools for logging, monitoring, network policy, visualization, and control of your Kubernetes cluster.

クリーンアップ

  • To delete your cluster: kops delete cluster useast1.dev.example.com --yes

次の項目

2.3.2.3 - kubesprayを使ったオンプレミス/クラウドプロバイダへのKubernetesのインストール

This quickstart helps to install a Kubernetes cluster hosted on GCE, Azure, OpenStack, AWS, vSphere, Equinix Metal (formerly Packet), Oracle Cloud Infrastructure (Experimental) or Baremetal with Kubespray.

Kubespray is a composition of Ansible playbooks, inventory, provisioning tools, and domain knowledge for generic OS/Kubernetes clusters configuration management tasks. Kubespray provides:

  • a highly available cluster
  • composable attributes
  • support for most popular Linux distributions
    • Ubuntu 16.04, 18.04, 20.04, 22.04
    • CentOS/RHEL/Oracle Linux 7, 8
    • Debian Buster, Jessie, Stretch, Wheezy
    • Fedora 34, 35
    • Fedora CoreOS
    • openSUSE Leap 15
    • Flatcar Container Linux by Kinvolk
  • continuous integration tests

To choose a tool which best fits your use case, read this comparison to kubeadm and kops.

クラスタの作成

(1/5) 下地の要件の確認

Provision servers with the following requirements:

  • Ansible v2.11 and python-netaddr are installed on the machine that will run Ansible commands
  • Jinja 2.11 (or newer) is required to run the Ansible Playbooks
  • The target servers must have access to the Internet in order to pull docker images. Otherwise, additional configuration is required (See Offline Environment)
  • The target servers are configured to allow IPv4 forwarding
  • Your ssh key must be copied to all the servers in your inventory
  • Firewalls are not managed by kubespray. You'll need to implement appropriate rules as needed. You should disable your firewall in order to avoid any issues during deployment
  • If kubespray is run from a non-root user account, correct privilege escalation method should be configured in the target servers and the ansible_become flag or command parameters --become or -b should be specified

Kubespray provides the following utilities to help provision your environment:

(2/5) インベントリファイルの用意

After you provision your servers, create an inventory file for Ansible. You can do this manually or via a dynamic inventory script. For more information, see "Building your own inventory".

(3/5) クラスタ作成の計画

Kubespray provides the ability to customize many aspects of the deployment:

  • Choice deployment mode: kubeadm or non-kubeadm
  • CNI (networking) plugins
  • DNS configuration
  • Choice of control plane: native/binary or containerized
  • Component versions
  • Calico route reflectors
  • Component runtime options
  • Certificate generation methods

Kubespray customizations can be made to a variable file. If you are just getting started with Kubespray, consider using the Kubespray defaults to deploy your cluster and explore Kubernetes.

(4/5) クラスタのデプロイ

Next, deploy your cluster:

Cluster deployment using ansible-playbook.

ansible-playbook -i your/inventory/inventory.ini cluster.yml -b -v \
  --private-key=~/.ssh/private_key

Large deployments (100+ nodes) may require specific adjustments for best results.

(5/5) デプロイの確認

Kubespray provides a way to verify inter-pod connectivity and DNS resolve with Netchecker. Netchecker ensures the netchecker-agents pods can resolve DNS requests and ping each over within the default namespace. Those pods mimic similar behavior of the rest of the workloads and serve as cluster health indicators.

クラスタの操作

Kubespray provides additional playbooks to manage your cluster: scale and upgrade.

クラスタのスケール

You can add worker nodes from your cluster by running the scale playbook. For more information, see "Adding nodes". You can remove worker nodes from your cluster by running the remove-node playbook. For more information, see "Remove nodes".

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

You can upgrade your cluster by running the upgrade-cluster playbook. For more information, see "Upgrades".

クリーンアップ

You can reset your nodes and wipe out all components installed with Kubespray via the reset playbook.

フィードバック

次の項目

Check out planned work on Kubespray's roadmap.

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

2.3.3.1 - Alibaba CloudでKubernetesを動かす

Alibaba Cloud Container Service

Alibaba Cloud Container ServiceはAlibaba Cloud ECSインスタンスのクラスター上もしくはサーバーレスの形態でDockerアプリケーションを起動して管理します。著名なオープンソースのコンテナオーケストレーターであるDocker SwarmおよびKubernetesをサポートしています。

クラスターの構築と管理を簡素化するために、Alibaba Cloud Container ServiceのためのKubernetesサポートを使用します。Kubernetes walk-throughに従ってすぐに始めることができ、中国語のAlibaba CloudにおけるKubernetesサポートのためのチュートリアルもあります。

カスタムバイナリもしくはオープンソースKubernetesを使用する場合は、以下の手順に従って下さい。

構築のカスタム

Alibaba Cloudプロバイダーが実装されたKubernetesのソースコードはオープンソースであり、GitHubから入手可能です。

さらなる情報は英語のKubernetesのクイックデプロイメント - Alibaba CloudのVPC環境をご覧下さい。

2.3.3.2 - AWS EC2上でKubernetesを動かす

このページでは、AWS上でKubernetesクラスターをインストールする方法について説明します。

始める前に

AWS上でKubernetesクラスターを作成するには、AWSからアクセスキーIDおよびシークレットアクセスキーを入手する必要があります。

サポートされているプロダクショングレードのツール

  • conjure-upはUbuntu上でネイティブなAWSインテグレーションを用いてKubernetesクラスターを作成するオープンソースのインストーラーです。

  • Kubernetes Operations - プロダクショングレードなKubernetesのインストール、アップグレード、管理が可能です。AWS上のDebian、Ubuntu、CentOS、RHELをサポートしています。

  • kube-aws EC2、CloudFormation、Auto Scalingを使用して、Flatcar LinuxノードでKubernetesクラスターを作成および管理します。

  • KubeOneは可用性の高いKubernetesクラスターを作成、アップグレード、管理するための、オープンソースのライフサイクル管理ツールです。

クラスターの始まり

コマンドライン管理ツール: kubectl

クラスターの起動スクリプトによってワークステーション上にkubernetesディレクトリが作成されます。もしくは、Kubernetesの最新リリースをこちらからダウンロードすることも可能です。

次に、kubectlにアクセスするために適切なバイナリフォルダーをPATHへ追加します:

# macOS
export PATH=<path/to/kubernetes-directory>/platforms/darwin/amd64:$PATH

# Linux
export PATH=<path/to/kubernetes-directory>/platforms/linux/amd64:$PATH

ツールに関する最新のドキュメントページはこちらです: kubectl manual

デフォルトでは、kubectlはクラスターの起動中に生成されたkubeconfigファイルをAPIに対する認証に使用します。 詳細な情報は、kubeconfig filesを参照してください。

新しいクラスターを試すには、簡単なnginxの例を参照してください。

"Guestbook"アプリケーションは、Kubernetesを始めるもう一つのポピュラーな例です: guestbookの例

より完全なアプリケーションについては、examplesディレクトリを参照してください。

クラスターのスケーリング

kubectlを使用したノードの追加および削除はサポートしていません。インストール中に作成されたAuto Scaling Group内の'Desired'および'Max'プロパティを手動で調整することで、ノード数をスケールさせることができます。

クラスターの解体

クラスターのプロビジョニングに使用した環境変数がexportされていることを確認してから、kubernetesディレクトリ内で以下のスクリプトを実行してください:

cluster/kube-down.sh

サポートレベル

IaaS プロバイダー構成管理OSネットワークドキュメント適合サポートレベル
AWSkopsDebiank8s (VPC)docsCommunity (@justinsb)
AWSCoreOSCoreOSflannel-Community
AWSJujuUbuntuflannel, calico, canal-100%Commercial, Community
AWSKubeOneUbuntu, CoreOS, CentOScanal, weavenetdocs100%Commercial, Community

2.3.3.3 - Azure 上で Kubernetes を動かす

Azure Kubernetes Service (AKS)

Azure Kubernetes Serviceは、Kubernetesクラスターのためのシンプルなデプロイ機能を提供します。

Azure Kubernetes Serviceを利用してAzure上にKubernetesクラスターをデプロイする例:

Microsoft Azure Kubernetes Service

デプロイのカスタマイズ: AKS-Engine

Azure Kubernetes Serviceのコア部分はオープンソースであり、コミュニティのためにGitHub上で公開され、利用およびコントリビュートすることができます: AKS-Engine。レガシーな ACS-Engine のコードベースはAKS-engineのために廃止となりました。

AKS-Engineは、Azure Kubernetes Serviceが公式にサポートしている機能を超えてデプロイをカスタマイズしたい場合に適した選択肢です。 既存の仮想ネットワークへのデプロイや、複数のagent poolを利用するなどのカスタマイズをすることができます。 コミュニティによるAKS-Engineへのコントリビュートが、Azure Kubernetes Serviceに組み込まれる場合もあります。

AKS-Engineへの入力は、Kubernetesクラスターを記述するapimodelのJSONファイルです。これはAzure Kubernetes Serviceを使用してクラスターを直接デプロイするために使用されるAzure Resource Manager (ARM) のテンプレート構文と似ています。 処理結果はARMテンプレートとして出力され、ソース管理に組み込んだり、AzureにKubernetesクラスターをデプロイするために使うことができます。

AKS-Engine Kubernetes Tutorial を参照して始めることができます。

Azure上でCoreOS Tectonicを動かす

Azureで利用できるCoreOS Tectonic Installerはオープンソースであり、コミュニティのためにGitHub上で公開され、利用およびコントリビュートすることができます: Tectonic Installer.

Tectonic Installerは、 Hashicorp が提供する TerraformのAzure Resource Manager(ARM)プロバイダーを用いてクラスターをカスタマイズしたい場合に適した選択肢です。 これを利用することにより、Terraformと親和性の高いツールを使用してカスタマイズしたり連携したりすることができます。

Tectonic Installer for Azure Guideを参照して、すぐに始めることができます。

2.3.3.4 - Google Compute Engine上でKubernetesを動かす

The example below creates a Kubernetes cluster with 3 worker node Virtual Machines and a master Virtual Machine (i.e. 4 VMs in your cluster). This cluster is set up and controlled from your workstation (or wherever you find convenient).

始める前に

If you want a simplified getting started experience and GUI for managing clusters, please consider trying Google Kubernetes Engine for hosted cluster installation and management.

For an easy way to experiment with the Kubernetes development environment, click the button below to open a Google Cloud Shell with an auto-cloned copy of the Kubernetes source repo.

Open in Cloud Shell

If you want to use custom binaries or pure open source Kubernetes, please continue with the instructions below.

前提条件

  1. You need a Google Cloud Platform account with billing enabled. Visit the Google Developers Console for more details.
  2. Install gcloud as necessary. gcloud can be installed as a part of the Google Cloud SDK.
  3. Enable the Compute Engine Instance Group Manager API in the Google Cloud developers console.
  4. Make sure that gcloud is set to use the Google Cloud Platform project you want. You can check the current project using gcloud config list project and change it via gcloud config set project <project-id>.
  5. Make sure you have credentials for GCloud by running gcloud auth login.
  6. (Optional) In order to make API calls against GCE, you must also run gcloud auth application-default login.
  7. Make sure you can start up a GCE VM from the command line. At least make sure you can do the Create an instance part of the GCE Quickstart.
  8. Make sure you can SSH into the VM without interactive prompts. See the Log in to the instance part of the GCE Quickstart.

クラスターの起動

You can install a client and start a cluster with either one of these commands (we list both in case only one is installed on your machine):

curl -sS https://get.k8s.io | bash

or

wget -q -O - https://get.k8s.io | bash

Once this command completes, you will have a master VM and four worker VMs, running as a Kubernetes cluster.

By default, some containers will already be running on your cluster. Containers like fluentd provide logging, while heapster provides monitoring services.

The script run by the commands above creates a cluster with the name/prefix "kubernetes". It defines one specific cluster config, so you can't run it more than once.

Alternately, you can download and install the latest Kubernetes release from this page, then run the <kubernetes>/cluster/kube-up.sh script to start the cluster:

cd kubernetes
cluster/kube-up.sh

If you want more than one cluster running in your project, want to use a different name, or want a different number of worker nodes, see the <kubernetes>/cluster/gce/config-default.sh file for more fine-grained configuration before you start up your cluster.

If you run into trouble, please see the section on troubleshooting, post to the Kubernetes Forum, or come ask questions on #gke Slack channel.

The next few steps will show you:

  1. How to set up the command line client on your workstation to manage the cluster
  2. Examples of how to use the cluster
  3. How to delete the cluster
  4. How to start clusters with non-default options (like larger clusters)

ワークステーション上でのKubernetesコマンドラインツールのインストール

The cluster startup script will leave you with a running cluster and a kubernetes directory on your workstation.

The kubectl tool controls the Kubernetes cluster manager. It lets you inspect your cluster resources, create, delete, and update components, and much more. You will use it to look at your new cluster and bring up example apps.

You can use gcloud to install the kubectl command-line tool on your workstation:

gcloud components install kubectl

クラスターの始まり

クラスターの様子を見る

Once kubectl is in your path, you can use it to look at your cluster. E.g., running:

kubectl get --all-namespaces services

should show a set of services that look something like this:

NAMESPACE     NAME          TYPE             CLUSTER_IP       EXTERNAL_IP       PORT(S)        AGE
default       kubernetes    ClusterIP        10.0.0.1         <none>            443/TCP        1d
kube-system   kube-dns      ClusterIP        10.0.0.2         <none>            53/TCP,53/UDP  1d
kube-system   kube-ui       ClusterIP        10.0.0.3         <none>            80/TCP         1d
...

Similarly, you can take a look at the set of pods that were created during cluster startup. You can do this via the

kubectl get --all-namespaces pods

command.

You'll see a list of pods that looks something like this (the name specifics will be different):

NAMESPACE     NAME                                           READY     STATUS    RESTARTS   AGE
kube-system   coredns-5f4fbb68df-mc8z8                       1/1       Running   0          15m
kube-system   fluentd-cloud-logging-kubernetes-minion-63uo   1/1       Running   0          14m
kube-system   fluentd-cloud-logging-kubernetes-minion-c1n9   1/1       Running   0          14m
kube-system   fluentd-cloud-logging-kubernetes-minion-c4og   1/1       Running   0          14m
kube-system   fluentd-cloud-logging-kubernetes-minion-ngua   1/1       Running   0          14m
kube-system   kube-ui-v1-curt1                               1/1       Running   0          15m
kube-system   monitoring-heapster-v5-ex4u3                   1/1       Running   1          15m
kube-system   monitoring-influx-grafana-v1-piled             2/2       Running   0          15m

Some of the pods may take a few seconds to start up (during this time they'll show Pending), but check that they all show as Running after a short period.

いくつかの例の実行

Then, see a simple nginx example to try out your new cluster.

For more complete applications, please look in the examples directory. The guestbook example is a good "getting started" walkthrough.

クラスターの解体

To remove/delete/teardown the cluster, use the kube-down.sh script.

cd kubernetes
cluster/kube-down.sh

Likewise, the kube-up.sh in the same directory will bring it back up. You do not need to rerun the curl or wget command: everything needed to setup the Kubernetes cluster is now on your workstation.

カスタマイズ

The script above relies on Google Storage to stage the Kubernetes release. It then will start (by default) a single master VM along with 3 worker VMs. You can tweak some of these parameters by editing kubernetes/cluster/gce/config-default.sh You can view a transcript of a successful cluster creation here.

トラブルシューティング

プロジェクトの設定

You need to have the Google Cloud Storage API, and the Google Cloud Storage JSON API enabled. It is activated by default for new projects. Otherwise, it can be done in the Google Cloud Console. See the Google Cloud Storage JSON API Overview for more details.

Also ensure that-- as listed in the Prerequisites section-- you've enabled the Compute Engine Instance Group Manager API, and can start up a GCE VM from the command line as in the GCE Quickstart instructions.

クラスター初期化のハング

If the Kubernetes startup script hangs waiting for the API to be reachable, you can troubleshoot by SSHing into the master and node VMs and looking at logs such as /var/log/startupscript.log.

Once you fix the issue, you should run kube-down.sh to cleanup after the partial cluster creation, before running kube-up.sh to try again.

SSH

If you're having trouble SSHing into your instances, ensure the GCE firewall isn't blocking port 22 to your VMs. By default, this should work but if you have edited firewall rules or created a new non-default network, you'll need to expose it: gcloud compute firewall-rules create default-ssh --network=<network-name> --description "SSH allowed from anywhere" --allow tcp:22

Additionally, your GCE SSH key must either have no passcode or you need to be using ssh-agent.

ネットワーク

The instances must be able to connect to each other using their private IP. The script uses the "default" network which should have a firewall rule called "default-allow-internal" which allows traffic on any port on the private IPs. If this rule is missing from the default network or if you change the network being used in cluster/config-default.sh create a new rule with the following field values:

  • Source Ranges: 10.0.0.0/8
  • Allowed Protocols and Port: tcp:1-65535;udp:1-65535;icmp

サポートレベル

IaaS ProviderConfig. MgmtOSNetworkingDocsConformsSupport Level
GCESaltstackDebianGCEdocsProject

2.3.3.5 - IBM Cloud Privateを使ってマルチクラウドでKubernetesを動かす

IBM® Cloud Private is a turnkey cloud solution and an on-premises turnkey cloud solution. IBM Cloud Private delivers pure upstream Kubernetes with the typical management components that are required to run real enterprise workloads. These workloads include health management, log management, audit trails, and metering for tracking usage of workloads on the platform.

IBM Cloud Private is available in a community edition and a fully supported enterprise edition. The community edition is available at no charge from Docker Hub. The enterprise edition supports high availability topologies and includes commercial support from IBM for Kubernetes and the IBM Cloud Private management platform. If you want to try IBM Cloud Private, you can use either the hosted trial, the tutorial, or the self-guided demo. You can also try the free community edition. For details, see Get started with IBM Cloud Private.

For more information, explore the following resources:

IBM Cloud PrivateとTerraform

The following modules are available where you can deploy IBM Cloud Private by using Terraform:

AWS上でのIBM Cloud Private

You can deploy an IBM Cloud Private cluster on Amazon Web Services (AWS) using Terraform.

IBM Cloud Private can also run on the AWS cloud platform by using Terraform. To deploy IBM Cloud Private in an AWS EC2 environment, see Installing IBM Cloud Private on AWS.

Azure上でのIBM Cloud Private

You can enable Microsoft Azure as a cloud provider for IBM Cloud Private deployment and take advantage of all the IBM Cloud Private features on the Azure public cloud. For more information, see IBM Cloud Private on Azure.

Red Hat OpenShiftを用いたIBM Cloud Private

You can deploy IBM certified software containers that are running on IBM Cloud Private onto Red Hat OpenShift.

Integration capabilities:

  • Supports Linux® 64-bit platform in offline-only installation mode
  • Single-master configuration
  • Integrated IBM Cloud Private cluster management console and catalog
  • Integrated core platform services, such as monitoring, metering, and logging
  • IBM Cloud Private uses the OpenShift image registry

For more information see, IBM Cloud Private on OpenShift.

VirtualBox上でのIBM Cloud Private

To install IBM Cloud Private to a VirtualBox environment, see Installing IBM Cloud Private on VirtualBox.

VMware上でのIBM Cloud Private

You can install IBM Cloud Private on VMware with either Ubuntu or RHEL images. For details, see the following projects:

The IBM Cloud Private Hosted service automatically deploys IBM Cloud Private Hosted on your VMware vCenter Server instances. This service brings the power of microservices and containers to your VMware environment on IBM Cloud. With this service, you can extend the same familiar VMware and IBM Cloud Private operational model and tools from on-premises into the IBM Cloud.

For more information, see IBM Cloud Private Hosted service.

2.3.4 - オンプレミスVM

2.3.4.1 - Cloudstack

CloudStack is a software to build public and private clouds based on hardware virtualization principles (traditional IaaS). To deploy Kubernetes on CloudStack there are several possibilities depending on the Cloud being used and what images are made available. CloudStack also has a vagrant plugin available, hence Vagrant could be used to deploy Kubernetes either using the existing shell provisioner or using new Salt based recipes.

CoreOS templates for CloudStack are built nightly. CloudStack operators need to register this template in their cloud before proceeding with these Kubernetes deployment instructions.

This guide uses a single Ansible playbook, which is completely automated and can deploy Kubernetes on a CloudStack based Cloud using CoreOS images. The playbook, creates an ssh key pair, creates a security group and associated rules and finally starts coreOS instances configured via cloud-init.

前提条件

sudo apt-get install -y python-pip libssl-dev
sudo pip install cs
sudo pip install sshpubkeys
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible

On CloudStack server you also have to install libselinux-python :

yum install libselinux-python

cs is a python module for the CloudStack API.

Set your CloudStack endpoint, API keys and HTTP method used.

You can define them as environment variables: CLOUDSTACK_ENDPOINT, CLOUDSTACK_KEY, CLOUDSTACK_SECRET and CLOUDSTACK_METHOD.

Or create a ~/.cloudstack.ini file:

[cloudstack]
endpoint = <your cloudstack api endpoint>
key = <your api access key>
secret = <your api secret key>
method = post

We need to use the http POST method to pass the large userdata to the coreOS instances.

playbookのクローン

git clone https://github.com/apachecloudstack/k8s
cd kubernetes-cloudstack

Kubernetesクラスターの作成

You simply need to run the playbook.

ansible-playbook k8s.yml

Some variables can be edited in the k8s.yml file.

vars:
  ssh_key: k8s
  k8s_num_nodes: 2
  k8s_security_group_name: k8s
  k8s_node_prefix: k8s2
  k8s_template: <templatename>
  k8s_instance_type: <serviceofferingname>

This will start a Kubernetes master node and a number of compute nodes (by default 2). The instance_type and template are specific, edit them to specify your CloudStack cloud specific template and instance type (i.e. service offering).

Check the tasks and templates in roles/k8s if you want to modify anything.

Once the playbook as finished, it will print out the IP of the Kubernetes master:

TASK: [k8s | debug msg='k8s master IP is {{ k8s_master.default_ip }}'] ********

SSH to it using the key that was created and using the core user.

ssh -i ~/.ssh/id_rsa_k8s core@<master IP>

And you can list the machines in your cluster:

fleetctl list-machines
MACHINE        IP             METADATA
a017c422...    <node #1 IP>   role=node
ad13bf84...    <master IP>    role=master
e9af8293...    <node #2 IP>   role=node

サポートレベル

IaaS ProviderConfig. MgmtOSNetworkingDocsConformsSupport Level
CloudStackAnsibleCoreOSflanneldocsCommunity (@Guiques)

2.3.4.2 - DC/OS上のKubernetes

MesosphereはDC/OS上にKubernetesを構築するための簡単な選択肢を提供します。それは

  • 純粋なアップストリームのKubernetes
  • シングルクリッククラスター構築
  • デフォルトで高可用であり安全
  • Kubernetesが高速なデータプラットフォーム(例えばAkka、Cassandra、Kafka、Spark)と共に稼働

です。

公式Mesosphereガイド

DC/OS入門の正規のソースはクイックスタートリポジトリにあります。

2.3.4.3 - oVirt

oVirt is a virtual datacenter manager that delivers powerful management of multiple virtual machines on multiple hosts. Using KVM and libvirt, oVirt can be installed on Fedora, CentOS, or Red Hat Enterprise Linux hosts to set up and manage your virtual data center.

oVirtクラウドプロバイダーによる構築

The oVirt cloud provider allows to easily discover and automatically add new VM instances as nodes to your Kubernetes cluster. At the moment there are no community-supported or pre-loaded VM images including Kubernetes but it is possible to import or install Project Atomic (or Fedora) in a VM to generate a template. Any other distribution that includes Kubernetes may work as well.

It is mandatory to install the ovirt-guest-agent in the guests for the VM ip address and hostname to be reported to ovirt-engine and ultimately to Kubernetes.

Once the Kubernetes template is available it is possible to start instantiating VMs that can be discovered by the cloud provider.

oVirtクラウドプロバイダーの使用

The oVirt Cloud Provider requires access to the oVirt REST-API to gather the proper information, the required credential should be specified in the ovirt-cloud.conf file:

[connection]
uri = https://localhost:8443/ovirt-engine/api
username = admin@internal
password = admin

In the same file it is possible to specify (using the filters section) what search query to use to identify the VMs to be reported to Kubernetes:

[filters]
# Search query used to find nodes
vms = tag=kubernetes

In the above example all the VMs tagged with the kubernetes label will be reported as nodes to Kubernetes.

The ovirt-cloud.conf file then must be specified in kube-controller-manager:

kube-controller-manager ... --cloud-provider=ovirt --cloud-config=/path/to/ovirt-cloud.conf ...

oVirtクラウドプロバイダーのスクリーンキャスト

This short screencast demonstrates how the oVirt Cloud Provider can be used to dynamically add VMs to your Kubernetes cluster.

Screencast

サポートレベル

IaaS ProviderConfig. MgmtOSNetworkingDocsConformsSupport Level
oVirtdocsCommunity (@simon3z)

2.3.5 - Windows in Kubernetes

2.3.5.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.3.5.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

2.4 - ベストプラクティス

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

This page describes how to run a cluster in multiple zones.

始めに

Kubernetes 1.2より、複数のゾーンにおいて単一のクラスターを運用するサポートが追加されました(GCEでは単純に"ゾーン",AWSは"アベイラビリティゾーン"と呼びますが、ここでは"ゾーン"とします)。 これは、より範囲の広いCluster Federationの軽量バージョンです(以前は"Ubernetes"の愛称で言及されていました)。 完全なCluster Federationでは、異なるリージョンやクラウドプロバイダー(あるいはオンプレミスデータセンター)内の独立したKubernetesクラスターをまとめることが可能になります。しかしながら、多くのユーザーは単に1つのクラウドプロバイダーの複数のゾーンでより可用性の高いKubernetesクラスターを運用したいと考えており、バージョン1.2におけるマルチゾーンサポート(以前は"Ubernetes Lite"の愛称で使用されていました)ではこれが可能になります。

マルチゾーンサポートは故意に限定されています: 1つのKubernetesクラスターは複数のゾーンで運用することができますが、同じリージョン(あるいはクラウドプロバイダー)のみです。現在はGCEとAWSのみが自動的にサポートされています(他のクラウドプロバイダーやベアメタル環境においても、単にノードやボリュームに追加する適切なラベルを用意して同様のサポートを追加することは容易ではありますが)。

機能性

ノードが開始された時、kubeletは自動的にそれらにゾーン情報を付したラベルを追加します。

Kubernetesはレプリケーションコントローラーやサービス内のPodをシングルゾーンクラスターにおけるノードにデプロイします(障害の影響を減らすため)。マルチゾーンクラスターでは、このデプロイの挙動はゾーンを跨いで拡張されます(障害の影響を減らすため)(これはSelectorSpreadPriorityによって可能になります)。これはベストエフォートな配置であり、つまりもしクラスターのゾーンが異種である(例:異なる数のノード,異なるタイプのノードや異なるPodのリソース要件)場合、これはゾーンを跨いだPodのデプロイを完璧に防ぐことができます。必要であれば、同種のゾーン(同一の数及びタイプのノード)を利用して不平等なデプロイの可能性を減らすことができます。

永続ボリュームが作成されると、PersistentVolumeLabelアドミッションコントローラーがそれらにゾーンラベルを付与します。スケジューラーはVolumeZonePredicateを通じて与えられたボリュームを請求するPodがそのボリュームと同じゾーンにのみ配置されることを保証します、これはボリュームはゾーンを跨いでアタッチすることができないためです。

制限

マルチゾーンサポートにはいくつか重要な制限があります:

  • 異なるゾーンはネットワーク内においてお互いに近接して位置していることが想定されているため、いかなるzone-aware routingも行われません。特に、トラフィックはゾーンを跨いだサービスを通じて行き来するため(サービスをサポートするいくつかのPodがクライアントと同じゾーンに存在していても)、これは追加のレイテンシやコストを生むかもしれません。

  • Volume zone-affinityはPersistentVolumeと共に動作し、例えばPodのスペックにおいてEBSボリュームを直接指定しても動作しません。

  • クラスターはクラウドやリージョンを跨げません(この機能はフルフェデレーションサポートが必要です)。

*ノードは複数のゾーンに存在しますが、kube-upは現在デフォルトではシングルマスターノードでビルドします。サービスは高可用性でありゾーンの障害に耐えることができますが、コントロールプレーンは単一のゾーンに配置されます。高可用性コントロールプレーンを必要とするユーザーは高可用性の説明を参照してください。

ボリュームの制限

以下の制限はtopology-aware volume bindingに記載されています。

  • 動的なプロビジョニングを使用する際のStatefulSetボリュームゾーンのデプロイは、現在Podのアフィニティあるいはアンチアフィニティと互換性がありません。

  • StatefulSetの名前がダッシュ("-")を含む場合、ボリュームゾーンのデプロイはゾーンを跨いだストレージの均一な分配を提供しない可能性があります。

  • DeploymentやPodのスペックにおいて複数のPVCを指定すると、StorageClassは特定の1つのゾーンに割り当てる必要があります、あるいはPVは特定のゾーンに静的にプロビジョンされる必要があります。もう一つの解決方法として、StatefulSetを使用すると、レプリカに対する全てのボリュームが同じゾーンにプロビジョンされます。

全体の流れ

GCEとAWSの両方にマルチゾーンのクラスターをセットアップし使用する手順について説明します。そのために、フルクラスターを用意し(MULTIZONE=trueと指定する)、kube-upを再び実行して追加のゾーンにノードを追加します(KUBE_USE_EXISTING_MASTER=trueと指定する)。

クラスターの立ち上げ

通常と同様にクラスターを作成します、しかし複数のゾーンを管理するためにMULTIZONEをクラスターに設定します。ノードをus-central1-aに作成します。

GCE:

curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a NUM_NODES=3 bash

AWS:

curl -sS https://get.k8s.io | MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a NUM_NODES=3 bash

このステップは通常と同様にクラスターを立ち上げ、1つのゾーンで動作しています(しかし、MULTIZONE=trueによりマルチゾーン能力は有効になっています)。

ノードはラベルが付与される

ノードを見てください。それらがゾーン情報と共にラベルされているのが分かります。 それら全ては今のところus-central1-a (GCE)あるいはus-west-2a (AWS)にあります。ラベルはtopology.kubernetes.io/regionがリージョンに、topology.kubernetes.io/zoneはゾーンに付けられています:

kubectl get nodes --show-labels

結果は以下のようになります:

NAME                     STATUS                     ROLES    AGE   VERSION          LABELS
kubernetes-master        Ready,SchedulingDisabled   <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-1,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-87j9   Ready                      <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv   Ready                      <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q   Ready                      <none>   6m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q

2つ目のゾーンにさらにノードを追加

それでは、現存のマスターを再利用し、現存のクラスターの異なるゾーン(us-central1-bかus-west-2b)にもう1つのノードのセットを追加しましょう。 kube-upを再び実行します.しかしKUBE_USE_EXISTING_MASTER=trueを指定することでkube-upは新しいマスターを作成せず、代わりに以前作成したものを再利用します。

GCE:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-b NUM_NODES=3 kubernetes/cluster/kube-up.sh

AWSではマスターの内部IPアドレスに加えて追加のサブネット用のネットワークCIDRを指定する必要があります:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2b NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.1.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh

ノードをもう1度見てください。更なる3つのノードがus-central1-bに起動し、タグ付けられているはずです:

kubectl get nodes --show-labels

結果は以下のようになります:

NAME                     STATUS                     ROLES    AGE   VERSION           LABELS
kubernetes-master        Ready,SchedulingDisabled   <none>   16m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-1,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-master
kubernetes-minion-281d   Ready                      <none>   2m    v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-87j9   Ready                      <none>   16m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-87j9
kubernetes-minion-9vlv   Ready                      <none>   16m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-a12q   Ready                      <none>   17m   v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-a12q
kubernetes-minion-pp2f   Ready                      <none>   2m    v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-pp2f
kubernetes-minion-wf8i   Ready                      <none>   2m    v1.13.0           beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-wf8i

ボリュームのアフィニティ

動的ボリュームを使用してボリュームを作成します(PersistentVolumeのみがゾーンアフィニティに対してサポートされています):

kubectl apply -f - <<EOF
{
  "apiVersion": "v1",
  "kind": "PersistentVolumeClaim",
  "metadata": {
    "name": "claim1",
    "annotations": {
        "volume.alpha.kubernetes.io/storage-class": "foo"
    }
  },
  "spec": {
    "accessModes": [
      "ReadWriteOnce"
    ],
    "resources": {
      "requests": {
        "storage": "5Gi"
      }
    }
  }
}
EOF

それでは、KubernetesがPVが作成されたゾーン及びリージョンを自動的にラベルしているか確認しましょう。

kubectl get pv --show-labels

結果は以下のようになります:

NAME           CAPACITY   ACCESSMODES   RECLAIM POLICY   STATUS    CLAIM            STORAGECLASS    REASON    AGE       LABELS
pv-gce-mj4gm   5Gi        RWO           Retain           Bound     default/claim1   manual                    46s       topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a

では永続ボリュームクレームを使用するPodを作成します。 GCE PD / AWS EBSボリュームはゾーンを跨いでアタッチできないため、これはこのPodがボリュームと同じゾーンにのみ作成されることを意味します:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: claim1
EOF

一般的にゾーンを跨いだアタッチはクラウドプロバイダーによって許可されていないため、Podは自動的にボリュームと同じゾーンに作成されることに注意してください:

kubectl describe pod mypod | grep Node
Node:        kubernetes-minion-9vlv/10.240.0.5

ノードのラベルをチェックします:

kubectl get node kubernetes-minion-9vlv --show-labels
NAME                     STATUS    AGE    VERSION          LABELS
kubernetes-minion-9vlv   Ready     22m    v1.6.0+fff5156   beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv

Podがゾーンをまたがって配置される

レプリケーションコントローラーやサービス内のPodは自動的にゾーンに跨いでデプロイされます。まず、3つ目のゾーンに更なるノードを立ち上げましょう:

GCE:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-f NUM_NODES=3 kubernetes/cluster/kube-up.sh

AWS:

KUBE_USE_EXISTING_MASTER=true MULTIZONE=true KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2c NUM_NODES=3 KUBE_SUBNET_CIDR=172.20.2.0/24 MASTER_INTERNAL_IP=172.20.0.9 kubernetes/cluster/kube-up.sh

3つのゾーンにノードがあることを確認します:

kubectl get nodes --show-labels

シンプルなWebアプリケーションを動作する、3つのRCを持つguestbook-goの例を作成します:

find kubernetes/examples/guestbook-go/ -name '*.json' | xargs -I {} kubectl apply -f {}

Podは3つの全てのゾーンにデプロイされているはずです:

kubectl describe pod -l app=guestbook | grep Node
Node:        kubernetes-minion-9vlv/10.240.0.5
Node:        kubernetes-minion-281d/10.240.0.8
Node:        kubernetes-minion-olsh/10.240.0.11
kubectl get node kubernetes-minion-9vlv kubernetes-minion-281d kubernetes-minion-olsh --show-labels
NAME                     STATUS    ROLES    AGE    VERSION          LABELS
kubernetes-minion-9vlv   Ready     <none>   34m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-a,kubernetes.io/hostname=kubernetes-minion-9vlv
kubernetes-minion-281d   Ready     <none>   20m    v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-b,kubernetes.io/hostname=kubernetes-minion-281d
kubernetes-minion-olsh   Ready     <none>   3m     v1.13.0          beta.kubernetes.io/instance-type=n1-standard-2,topology.kubernetes.io/region=us-central1,topology.kubernetes.io/zone=us-central1-f,kubernetes.io/hostname=kubernetes-minion-olsh

ロードバランサーはクラスター内の全てのゾーンにデプロイされています; guestbook-goの例は負荷分散サービスのサンプルを含みます:

kubectl describe service guestbook | grep LoadBalancer.Ingress

結果は以下のようになります:

LoadBalancer Ingress:   130.211.126.21

IPの上に設定します:

export IP=130.211.126.21

IPをcurlを通じて探索します:

curl -s http://${IP}:3000/env | grep HOSTNAME

結果は以下のようになります:

  "HOSTNAME": "guestbook-44sep",

再び、複数回探索します:

(for i in `seq 20`; do curl -s http://${IP}:3000/env | grep HOSTNAME; done)  | sort | uniq

結果は以下のようになります:

  "HOSTNAME": "guestbook-44sep",
  "HOSTNAME": "guestbook-hum5n",
  "HOSTNAME": "guestbook-ppm40",

ロードバランサーは、たとえPodが複数のゾーンに存在していても、全てのPodをターゲットします。

クラスターの停止

終了したら、クリーンアップします:

GCE:

KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-f kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_USE_EXISTING_MASTER=true KUBE_GCE_ZONE=us-central1-b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=gce KUBE_GCE_ZONE=us-central1-a kubernetes/cluster/kube-down.sh

AWS:

KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2c kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_USE_EXISTING_MASTER=true KUBE_AWS_ZONE=us-west-2b kubernetes/cluster/kube-down.sh
KUBERNETES_PROVIDER=aws KUBE_AWS_ZONE=us-west-2a kubernetes/cluster/kube-down.sh

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

クラスターはKubernetesのエージェントが動作する(物理もしくは仮想の)ノードの集合で、コントロールプレーンによって管理されます。 Kubernetes v1.24 では、最大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は、クラスターのスケールが変化したときにアドオンの自動的なリサイズをお手伝いします。

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

ノード適合テスト

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

制約

Kubernetesのバージョン1.5ではノード適合テストには以下の制約があります:

  • ノード適合テストはコンテナのランタイムとしてDockerのみをサポートします。

ノードの前提条件

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

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

ノード適合テストの実行

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

  1. Kubeletをlocalhostに指定します(--api-servers="http://localhost:8080")、 このテストフレームワークはKubeletのテストにローカルマスターを起動するため、Kubeletをローカルホストに設定します(--api-servers="http://localhost:8080")。他にも配慮するべきKubeletフラグがいくつかあります:
  • --pod-cidr: kubenetを利用している場合は、Kubeletに任意のCIDR(例: --pod-cidr=10.180.0.0/24)を指定する必要があります。
  • --cloud-provider: --cloud-provider=gceを指定している場合は、テストを実行する前にこのフラグを取り除いてください。
  1. 以下のコマンドでノード適合テストを実行します:
# $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 \
  k8s.gcr.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テストのみを実行します
  k8s.gcr.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テスト以外のすべてのノード適合テストを実行します
  k8s.gcr.io/node-test:0.2

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

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

注意事項

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

2.4.4 - PKI証明書とその要件

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

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

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

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

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

証明書の保存場所

kubeadmを使用してKubernetesをインストールする場合、証明書は/etc/kubernetes/pkiに保存されます。このドキュメントの全てのパスは、そのディレクトリの相対パスを表します。

手動で証明書を設定する

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の秘密鍵をクラスターにコピーしたくない場合、自身で全ての証明書を作成できます。

必要な証明書:

デフォルト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-casystem:mastersclient
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)

kindは下記のx509の鍵用途のタイプにマッピングされます:

種類鍵の用途    
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

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

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

ファイル名クレデンシャル名デフォルトCN組織      
admin.confdefault-adminkubernetes-adminsystem:masters
kubelet.confdefault-authsystem:node:<nodeName> (see note)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のマニフェストファイルに追記する必要があります。

3 - コンセプト

本セクションは、Kubernetesシステムの各パートと、クラスターを表現するためにKubernetesが使用する抽象概念について学習し、Kubernetesの仕組みをより深く理解するのに役立ちます。

概要

Kubernetesを機能させるには、Kubernetes API オブジェクト を使用して、実行したいアプリケーションやその他のワークロード、使用するコンテナイメージ、レプリカ(複製)の数、どんなネットワークやディスクリソースを利用可能にするかなど、クラスターの desired state (望ましい状態)を記述します。desired state (望ましい状態)をセットするには、Kubernetes APIを使用してオブジェクトを作成します。通常はコマンドラインインターフェイス kubectl を用いてKubernetes APIを操作しますが、Kubernetes APIを直接使用してクラスターと対話し、desired state (望ましい状態)を設定、または変更することもできます。

一旦desired state (望ましい状態)を設定すると、Pod Lifecycle Event Generator(PLEG)を使用したKubernetes コントロールプレーンが機能し、クラスターの現在の状態をdesired state (望ましい状態)に一致させます。そのためにKubernetesはさまざまなタスク(たとえば、コンテナの起動または再起動、特定アプリケーションのレプリカ数のスケーリング等)を自動的に実行します。Kubernetesコントロールプレーンは、クラスターで実行されている以下のプロセスで構成されています。

  • Kubernetes Master: kube-apiserverkube-controller-managerkube-scheduler の3プロセスの集合です。これらのプロセスはクラスター内の一つのノード上で実行されます。実行ノードはマスターノードとして指定します。
  • クラスター内の個々の非マスターノードは、それぞれ2つのプロセスを実行します。
    • kubelet: Kubernetes Masterと通信します。
    • kube-proxy: 各ノードのKubernetesネットワークサービスを反映するネットワークプロキシです。

Kubernetesオブジェクト

Kubernetesには、デプロイ済みのコンテナ化されたアプリケーションやワークロード、関連するネットワークとディスクリソース、クラスターが何をしているかに関するその他の情報といった、システムの状態を表現する抽象が含まれています。これらの抽象は、Kubernetes APIのオブジェクトによって表現されます。詳細については、Kubernetesオブジェクトについて知るをご覧ください。

基本的なKubernetesのオブジェクトは次のとおりです。

Kubernetesには、コントローラーに依存して基本オブジェクトを構築し、追加の機能と便利な機能を提供する高レベルの抽象化も含まれています。これらには以下のものを含みます:

Kubernetesコントロールプレーン

Kubernetesマスターや kubeletプロセスといったKubernetesコントロールプレーンのさまざまなパーツは、Kubernetesがクラスターとどのように通信するかを統制します。コントロールプレーンはシステム内のすべてのKubernetesオブジェクトの記録を保持し、それらのオブジェクトの状態を管理するために継続的制御ループを実行します。コントロールプレーンの制御ループは常にクラスターの変更に反応し、システム内のすべてのオブジェクトの実際の状態が、指定した状態に一致するように動作します。

たとえば、Kubernetes APIを使用してDeploymentを作成する場合、システムには新しいdesired state (望ましい状態)が提供されます。Kubernetesコントロールプレーンは、そのオブジェクトの作成を記録します。そして、要求されたアプリケーションの開始、およびクラスターノードへのスケジューリングにより指示を完遂します。このようにしてクラスターの実際の状態を望ましい状態に一致させます。

Kubernetesマスター

Kubernetesのマスターは、クラスターの望ましい状態を維持する責務を持ちます。kubectl コマンドラインインターフェイスを使用するなどしてKubernetesとやり取りするとき、ユーザーは実際にはクラスターにあるKubernetesのマスターと通信しています。

「マスター」とは、クラスター状態を管理するプロセスの集合を指します。通常これらのプロセスは、すべてクラスター内の単一ノードで実行されます。このノードはマスターとも呼ばれます。マスターは、可用性と冗長性のために複製することもできます。

Kubernetesノード

クラスターのノードは、アプリケーションとクラウドワークフローを実行するマシン(VM、物理サーバーなど)です。Kubernetesのマスターは各ノードを制御します。運用者自身がノードと直接対話することはほとんどありません。

次の項目

コンセプトページを追加したい場合は、 ページテンプレートの使用 のコンセプトページタイプとコンセプトテンプレートに関する情報を確認してください。

3.1 - 概要

3.1.1 - Kubernetesとは何か?

Kubernetesは、宣言的な構成管理と自動化を促進し、コンテナ化されたワークロードやサービスを管理するための、ポータブルで拡張性のあるオープンソースのプラットフォームです。Kubernetesは巨大で急速に成長しているエコシステムを備えており、それらのサービス、サポート、ツールは幅広い形で利用可能です。

このページでは、Kubernetesの概要について説明します。

Kubernetesは、宣言的な構成管理と自動化を促進し、コンテナ化されたワークロードやサービスを管理するための、ポータブルで拡張性のあるオープンソースのプラットフォームです。Kubernetesは巨大で急速に成長しているエコシステムを備えており、それらのサービス、サポート、ツールは幅広い形で利用可能です。

Kubernetesの名称は、ギリシャ語に由来し、操舵手やパイロットを意味しています。Googleは2014年にKubernetesプロジェクトをオープンソース化しました。Kubernetesは、本番環境で大規模なワークロードを稼働させたGoogleの15年以上の経験と、コミュニティからの最高のアイディアや実践を組み合わせています。

過去を振り返ってみると

過去を振り返って、Kubernetesがなぜこんなに便利なのかを見てみましょう。

Deployment evolution

仮想化ができる前の時代におけるデプロイ (Traditional deployment): 初期の頃は、組織は物理サーバー上にアプリケーションを実行させていました。物理サーバー上でアプリケーションのリソース制限を設定する方法がなかったため、リソースの割当問題が発生していました。例えば、複数のアプリケーションを実行させた場合、ひとつのアプリケーションがリソースの大半を消費してしまうと、他のアプリケーションのパフォーマンスが低下してしまうことがありました。この解決方法は、それぞれのアプリケーションを別々の物理サーバーで動かすことでした。しかし、リソースが十分に活用できなかったため、拡大しませんでした。また組織にとって多くの物理サーバーを維持することは費用がかかりました。

仮想化を使ったデプロイ (Virtualized deployment): ひとつの解決方法として、仮想化が導入されました。1台の物理サーバーのCPU上で、複数の仮想マシン(VM)を実行させることができるようになりました。仮想化によりアプリケーションをVM毎に隔離する事ができ、ひとつのアプリケーションの情報が他のアプリケーションから自由にアクセスさせないといったセキュリティレベルを提供することができます。

仮想化により、物理サーバー内のリソース使用率が向上し、アプリケーションの追加や更新が容易になり、ハードウェアコストの削減などスケーラビリティが向上します。仮想化を利用すると、物理リソースのセットを使い捨て可能な仮想マシンのクラスターとして提示することができます。

各VMは、仮想ハードウェア上で各自のOSを含んだ全コンポーネントを実行する完全なマシンです。

コンテナを使ったデプロイ (Container deployment): コンテナはVMと似ていますが、アプリケーション間でオペレーティング・システム(OS)を共有できる緩和された分離特性を持っています。そのため、コンテナは軽量だといわれます。VMと同じように、コンテナは各自のファイルシステム、CPUの共有、メモリー、プロセス空間等を持っています。基盤のインフラストラクチャから分離されているため、クラウドやOSディストリビューションを越えて移動することが可能です。

コンテナは、その他にも次のようなメリットを提供するため、人気が高まっています。

  • アジャイルアプリケーションの作成とデプロイ: VMイメージの利用時と比較して、コンテナイメージ作成の容易さと効率性が向上します。
  • 継続的な開発、インテグレーションとデプロイ: 信頼できる頻繁なコンテナイメージのビルドと、素早く簡単にロールバックすることが可能なデプロイを提供します。(イメージが不変であれば)
  • 開発者と運用者の関心を分離: アプリケーションコンテナイメージの作成は、デプロイ時ではなく、ビルド/リリース時に行います。それによって、インフラストラクチャとアプリケーションを分離します。
  • 可観測性はOSレベルの情報とメトリクスだけではなく、アプリケーションの稼働状態やその他の警告も表示します。
  • 開発、テスト、本番環境を越えた環境の一貫性: クラウドで実行させるのと同じようにノートPCでも実行させる事ができます。
  • クラウドとOSディストリビューションの可搬性: Ubuntu、RHEL、CoreOS上でも、オンプレミスも、主要なパブリッククラウドでも、それ以外のどんな環境でも、実行できます。
  • アプリケーション中心の管理: 仮想マシン上でOSを実行するから、論理リソースを使用してOS上でアプリケーションを実行するへと抽象度のレベルを向上させます。
  • 疎結合、分散化、拡張性、柔軟性のあるマイクロサービス: アプリケーションを小さく、同時にデプロイと管理が可能な独立した部品に分割されます。1台の大きな単一目的のマシン上に実行するモノリシックなスタックではありません。
  • リソースの分割: アプリケーションのパフォーマンスが予測可能です。
  • リソースの効率的な利用: 高い効率性と集約性が可能です。

Kubernetesが必要な理由と提供する機能

コンテナは、アプリケーションを集約して実行する良い方法です。本番環境では、アプリケーションを実行しダウンタイムが発生しないように、コンテナを管理する必要があります。例えば、コンテナがダウンした場合、他のコンテナを起動する必要があります。このような動作がシステムに組込まれていると、管理が簡単になるのではないでしょうか?

そこを助けてくれるのがKubernetesです! Kubernetesは分散システムを弾力的に実行するフレームワークを提供してくれます。あなたのアプリケーションのためにスケーリングとフェイルオーバーの面倒を見てくれて、デプロイのパターンなどを提供します。例えば、Kubernetesはシステムにカナリアデプロイを簡単に管理することができます。

Kubernetesは以下を提供します。

  • サービスディスカバリーと負荷分散 Kubernetesは、DNS名または独自のIPアドレスを使ってコンテナを公開することができます。コンテナへのトラフィックが多い場合は、Kubernetesは負荷分散し、ネットワークトラフィックを振り分けることができるため、デプロイが安定します。
  • ストレージ オーケストレーション Kubernetesは、ローカルストレージやパブリッククラウドプロバイダーなど、選択したストレージシステムを自動でマウントすることができます。
  • 自動化されたロールアウトとロールバック Kubernetesを使うとデプロイしたコンテナのあるべき状態を記述することができ、制御されたスピードで実際の状態をあるべき状態に変更することができます。例えば、アプリケーションのデプロイのために、新しいコンテナの作成や既存コンテナの削除、新しいコンテナにあらゆるリソースを適用する作業を、Kubernetesで自動化できます。
  • 自動ビンパッキング コンテナ化されたタスクを実行するノードのクラスターをKubernetesへ提供します。各コンテナがどれくらいCPUやメモリー(RAM)を必要とするのかをKubernetesに宣言することができます。Kubernetesはコンテナをノードにあわせて調整することができ、リソースを最大限に活用してくれます。
  • 自己修復 Kubernetesは、処理が失敗したコンテナを再起動し、コンテナを入れ替え、定義したヘルスチェックに応答しないコンテナを強制終了します。処理の準備ができるまでは、クライアントに通知しません。
  • 機密情報と構成管理 Kubernetesは、パスワードやOAuthトークン、SSHキーのよう機密の情報を保持し、管理することができます。機密情報をデプロイし、コンテナイメージを再作成することなくアプリケーションの構成情報を更新することができます。スタック構成の中で機密情報を晒してしまうこともありません。

Kubernetesにないもの

Kubernetesは、従来型の全部入りなPaaS(Platform as a Service)のシステムではありません。Kubernetesはハードウェアレベルではなく、コンテナレベルで動作するため、デプロイ、スケーリング、負荷分散といったPaaSが提供するのと共通の機能をいくつか提供し、またユーザーはロギングやモニタリング及びアラートを行うソリューションを統合できます。また一方、Kubernetesはモノリシックでなく、標準のソリューションは選択が自由で、追加と削除が容易な構成になっています。Kubernetesは開発プラットフォーム構築のためにビルディングブロックを提供しますが、重要な部分はユーザーの選択と柔軟性を維持しています。

Kubernetesは...

  • サポートするアプリケーションの種類を制限しません。Kubernetesは、ステートレス、ステートフルやデータ処理のワークロードなど、非常に多様なワークロードをサポートすることを目的としています。アプリケーションがコンテナで実行できるのであれば、Kubernetes上で問題なく実行できるはずです。
  • ソースコードのデプロイやアプリケーションのビルドは行いません。継続的なインテグレーション、デリバリー、デプロイ(CI/CD)のワークフローは、技術的な要件だけでなく組織の文化や好みで決められます。
  • ミドルウェア(例:メッセージバス)、データ処理フレームワーク(例:Spark)、データベース(例:MySQL)、キャッシュ、クラスターストレージシステム(例:Ceph)といったアプリケーションレベルの機能を組み込んで提供しません。それらのコンポーネントは、Kubernetes上で実行することもできますし、Open Service Brokerのようなポータブルメカニズムを経由してKubernetes上で実行されるアプリケーションからアクセスすることも可能です。
  • ロギング、モニタリングやアラートを行うソリューションは指定しません。PoCとしていくつかのインテグレーションとメトリクスを収集し出力するメカニズムを提供します。
  • 構成言語/システム(例:Jsonnet)の提供も指示もしません。任意の形式の宣言型仕様の対象となる可能性のある宣言型APIを提供します。
  • 統合的なマシンの構成、メンテナンス、管理、または自己修復を行うシステムは提供も採用も行いません。
  • さらに、Kubernetesは単なるオーケストレーションシステムではありません。実際には、オーケストレーションの必要性はありません。オーケストレーションの技術的な定義は、「最初にAを実行し、次にB、その次にCを実行」のような定義されたワークフローの実行です。対照的にKubernetesは、現在の状態から提示されたあるべき状態にあわせて継続的に維持するといった、独立していて構成可能な制御プロセスのセットを提供します。AからCへどのように移行するかは問題ではありません。集中管理も必要ありません。これにより、使いやすく、より強力で、堅牢で、弾力性と拡張性があるシステムが実現します。

次の項目

3.1.2 - Kubernetesのコンポーネント

Kubernetesクラスターはコントロールプレーンやノードと呼ばれるマシン群といったコンポーネントからなります。

Kubernetesをデプロイすると、クラスターが展開されます。

Kubernetesクラスターは、 コンテナ化されたアプリケーションを実行する、ノードと呼ばれるワーカーマシンの集合です。すべてのクラスターには少なくとも1つのワーカーノードがあります。

ワーカーノードは、アプリケーションのコンポーネントであるPodをホストします。マスターノードは、クラスター内のワーカーノードとPodを管理します。複数のマスターノードを使用して、クラスターにフェイルオーバーと高可用性を提供します。 ワーカーノードは、アプリケーションワークロードのコンポーネントであるPodをホストします。コントロールプレーンは、クラスター内のワーカーノードとPodを管理します。本番環境では、コントロールプレーンは複数のコンピューターを使用し、クラスターは複数のノードを使用し、耐障害性や高可用性を提供します。

このドキュメントでは、Kubernetesクラスターが機能するために必要となるさまざまなコンポーネントの概要を説明します。

すべてのコンポーネントが結び付けられたKubernetesクラスターの図を次に示します。

Kubernetesのコンポーネント

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

コントロールプレーンコンポーネントは、クラスターに関する全体的な決定(スケジューリングなど)を行います。また、クラスターイベントの検出および応答を行います(たとえば、deploymentのreplicasフィールドが満たされていない場合に、新しい Pod を起動する等)。

コントロールプレーンコンポーネントはクラスター内のどのマシンでも実行できますが、シンプルにするため、セットアップスクリプトは通常、すべてのコントロールプレーンコンポーネントを同じマシンで起動し、そのマシンではユーザーコンテナを実行しません。 マルチマスター VMセットアップの例については、高可用性クラスターの構築 を参照してください。

kube-apiserver

APIサーバーは、Kubernetes APIを外部に提供するKubernetesコントロールプレーンのコンポーネントです。 APIサーバーはKubernetesコントロールプレーンのフロントエンドになります。

Kubernetes APIサーバーの主な実装はkube-apiserverです。 kube-apiserverは水平方向にスケールするように設計されています—つまり、インスタンスを追加することでスケールが可能です。 複数のkube-apiserverインスタンスを実行することで、インスタンス間でトラフィックを分散させることが可能です。

etcd

一貫性、高可用性を持ったキーバリューストアで、Kubernetesの全てのクラスター情報の保存場所として利用されています。

etcdをKubernetesのデータストアとして使用する場合、必ずデータのバックアッププランを作成して下さい。

公式ドキュメントでetcdに関する詳細な情報を見つけることができます。

kube-scheduler

コントロールプレーン上で動作するコンポーネントで、新しく作られたPodノードが割り当てられているか監視し、割り当てられていなかった場合にそのPodを実行するノードを選択します。

スケジューリングの決定は、PodあるいはPod群のリソース要求量、ハードウェア/ソフトウェア/ポリシーによる制約、アフィニティおよびアンチアフィニティの指定、データの局所性、ワークロード間の干渉、有効期限などを考慮して行われます。

kube-controller-manager

コントロールプレーン上で動作するコンポーネントで、複数のコントローラープロセスを実行します。

論理的には、各コントローラーは個別のプロセスですが、複雑さを減らすために一つの実行ファイルにまとめてコンパイルされ、単一のプロセスとして動きます。

コントローラーには以下が含まれます。

  • ノードコントローラー:ノードがダウンした場合の通知と対応を担当します。
  • レプリケーションコントローラー:システム内の全レプリケーションコントローラーオブジェクトについて、Podの数を正しく保つ役割を持ちます。
  • エンドポイントコントローラー:エンドポイントオブジェクトを注入します(つまり、ServiceとPodを紐付けます)。
  • サービスアカウントとトークンコントローラー:新規の名前空間に対して、デフォルトアカウントとAPIアクセストークンを作成します。

cloud-controller-manager

クラウド特有の制御ロジックを組み込むKubernetesのcontrol planeコンポーネントです。クラウドコントロールマネージャーは、クラスターをクラウドプロバイダーAPIをリンクし、クラスタのみで相互作用するコンポーネントからクラウドプラットフォームで相互作用するコンポーネントを分離します。

cloud-controller-managerは、クラウドプロバイダー固有のコントローラーのみを実行します。 KubernetesをオンプレミスあるいはPC内での学習環境で動かす際には、クラスターにcloud container managerはありません。

kube-controller-managerを使用すると、cloud-controller-managerは複数の論理的に独立したコントロールループをシングルバイナリにまとめ、これが一つのプロセスとして動作します。パフォーマンスを向上させるあるいは障害に耐えるために水平方向にスケールする(一つ以上のコピーを動かす)ことができます。

次のコントローラーには、クラウドプロバイダーへの依存関係を持つ可能性があります。

  • ノードコントローラー:ノードが応答を停止した後、クラウドで削除されたかどうかを判断するため、クラウドプロバイダーをチェックします。
  • ルーティングコントローラー:基盤であるクラウドインフラでルーティングを設定します。
  • サービスコントローラー:クラウドプロバイダーのロードバランサーの作成、更新、削除を行います。

ノードコンポーネント

ノードコンポーネントはすべてのノードで実行され、稼働中のPodの管理やKubernetesの実行環境を提供します。

kubelet

クラスター内の各ノードで実行されるエージェントです。各コンテナPodで実行されていることを保証します。

kubeletは、さまざまなメカニズムを通じて提供されるPodSpecのセットを取得し、それらのPodSpecに記述されているコンテナが正常に実行されている状態を保証します。kubeletは、Kubernetesが作成したものではないコンテナは管理しません。

kube-proxy

kube-proxyはクラスター内の各nodeで動作しているネットワークプロキシで、KubernetesのServiceコンセプトの一部を実装しています。

kube-proxyは、Nodeのネットワークルールをメンテナンスします。これらのネットワークルールにより、クラスターの内部または外部のネットワークセッションからPodへのネットワーク通信が可能になります。

kube-proxyは、オペレーティングシステムにパケットフィルタリング層があり、かつ使用可能な場合、パケットフィルタリング層を使用します。それ以外の場合は自身でトラフィックを転送します。

コンテナランタイム

コンテナランタイムは、コンテナの実行を担当するソフトウェアです。

Kubernetesは次の複数のコンテナランタイムをサポートします。 DockercontainerdCRI-O、 および全ての Kubernetes CRI (Container Runtime Interface) 実装です。

アドオン

アドオンはクラスター機能を実装するためにKubernetesリソース(DaemonSetDeploymentなど)を使用します。 アドオンはクラスターレベルの機能を提供しているため、アドオンのリソースで名前空間が必要なものはkube-system名前空間に属します。

いくつかのアドオンについて以下で説明します。より多くの利用可能なアドオンのリストは、アドオン をご覧ください。

DNS

クラスターDNS以外のアドオンは必須ではありませんが、すべてのKubernetesクラスターはクラスターDNSを持つべきです。多くの使用例がクラスターDNSを前提としています。

クラスターDNSは、環境内の他のDNSサーバーに加えて、KubernetesサービスのDNSレコードを提供するDNSサーバーです。

Kubernetesによって開始されたコンテナは、DNS検索にこのDNSサーバーを自動的に含めます。

Web UI (ダッシュボード)

ダッシュボードは、Kubernetesクラスター用の汎用WebベースUIです。これによりユーザーはクラスターおよびクラスター内で実行されているアプリケーションについて、管理およびトラブルシューティングを行うことができます。

コンテナリソース監視

コンテナリソース監視は、コンテナに関する一般的な時系列メトリックを中央データベースに記録します。また、そのデータを閲覧するためのUIを提供します。

クラスターレベルログ

クラスターレベルログメカニズムは、コンテナのログを、検索/参照インターフェイスを備えた中央ログストアに保存します。

次の項目

3.1.3 - Kubernetes API

Kubernetes APIを使用すると、Kubernetes内のオブジェクトの状態をクエリで操作できます。 Kubernetesのコントロールプレーンの中核は、APIサーバーとそれが公開するHTTP APIです。ユーザー、クラスターのさまざまな部分、および外部コンポーネントはすべて、APIサーバーを介して互いに通信します。

Kubernetesの中核である control planeAPI server です。 APIサーバーは、エンドユーザー、クラスターのさまざまな部分、および外部コンポーネントが相互に通信できるようにするHTTP APIを公開します。

Kubernetes APIを使用すると、Kubernetes API内のオブジェクトの状態をクエリで操作できます(例:Pod、Namespace、ConfigMap、Events)。

ほとんどの操作は、APIを使用しているkubectlコマンドラインインターフェースもしくはkubeadmのような別のコマンドラインツールを通して実行できます。 RESTコールを利用して直接APIにアクセスすることも可能です。

Kubernetes APIを利用してアプリケーションを書いているのであれば、client librariesの利用を考えてみてください。

OpenAPI 仕様

完全なAPIの詳細は、OpenAPIを使用して文書化されています。

Kubernetes APIサーバーは、/openapi/v2エンドポイントを介してOpenAPI仕様を提供します。 次のように要求ヘッダーを使用して、応答フォーマットを要求できます。

OpenAPI v2クエリの有効なリクエストヘッダー値
HeaderPossible valuesNotes
Accept-Encodinggzipこのヘッダーを使わないことも可能
Acceptapplication/com.github.proto-openapi.spec.v2@v1.0+protobuf主にクラスター内での使用
application/jsonデフォルト
*application/jsonを提供

Kubernetesは、他の手段として主にクラスター間の連携用途向けのAPIに、Protocol buffersをベースにしたシリアライズフォーマットを実装しています。このフォーマットに関しては、Kubernetes Protobuf serializationデザイン提案を参照してください。また、各スキーマのInterface Definition Language(IDL)ファイルは、APIオブジェクトを定義しているGoパッケージ内に配置されています。

永続性

KubernetesはAPIリソースの観点からシリアル化された状態をetcdに書き込むことで保存します。

APIグループとバージョニング

フィールドの削除やリソース表現の再構成を簡単に行えるようにするため、Kubernetesは複数のAPIバージョンをサポートしており、/api/v1/apis/rbac.authorization.k8s.io/v1alpha1のように、それぞれ異なるAPIのパスが割り当てられています。

APIが、システムリソースと動作について明確かつ一貫したビューを提供し、サポート終了、実験的なAPIへのアクセス制御を有効にするために、リソースまたはフィールドレベルではなく、APIレベルでバージョンが行われます。

APIの発展や拡張を簡易に行えるようにするため、Kubernetesは有効もしくは無効を行えるAPIグループを実装しました。

APIリソースは、APIグループ、リソースタイプ、ネームスペース(namespacedリソースのための)、名前によって区別されます。APIサーバーは、APIバージョン間の変換を透過的に処理します。すべてのバージョンの違いは、実際のところ同じ永続データとして表現されます。APIサーバーは、同じ基本的なデータを複数のAPIバージョンで提供することができます。

例えば、同じリソースでv1v1beta1の2つのバージョンが有ることを考えてみます。v1beta1バージョンのAPIを利用しオブジェクトを最初に作成したとして、v1beta1もしくはv1どちらのAPIバージョンを利用してもオブジェクトのread、update、deleteができます。

APIの変更

成功を収めているシステムはすべて、新しいユースケースの出現や既存の変化に応じて成長し、変化する必要があります。 したがって、Kubernetesには、Kubernetes APIを継続的に変更および拡張できる設計機能があります。 Kubernetesプロジェクトは、既存のクライアントとの互換性を破壊 しないこと 、およびその互換性を一定期間維持して、他のプロジェクトが適応する機会を提供することを目的としています。

基本的に、新しいAPIリソースと新しいリソースフィールドは追加することができます。 リソースまたはフィールドを削除するには、API非推奨ポリシーに従ってください。

Kubernetesは、公式のKubernetes APIが一度一般提供(GA)に達した場合、通常はv1APIバージョンです、互換性を維持することを強い責任があります。さらに、Kubernetesは beta についても可能な限り互換性を維持し続けます。ベータAPIを採用した場合、その機能が安定版になったあとでも、APIを利用してクラスタを操作し続けることができます。

APIバージョンレベルの定義に関する詳細はAPIバージョンのリファレンスを参照してください。

APIの拡張

Kubernetes APIは2つの方法で拡張できます。

  1. カスタムリソースは、APIサーバーが選択したリソースAPIをどのように提供するかを宣言的に定義します。
  2. アグリゲーションレイヤーを実装することでKubernetes APIを拡張することもできます。

次の項目

  • 自分自身でカスタムリソース定義を追加してKubernetes APIを拡張する方法について学んでください。
  • Kubernetes APIのアクセス制御では、クラスターがAPIアクセスの認証と承認を管理する方法を説明しています。
  • APIリファレンスを読んで、APIエンドポイント、リソースタイプやサンプルについて学んでください。
  • APIの変更から、互換性のある変更とは何か, どのようにAPIを変更するかについて学んでください。

3.1.4 - Kubernetesオブジェクトを利用する

Kubernetesオブジェクトは、Kubernetes上で永続的なエンティティです。Kubernetesはこれらのエンティティを使い、クラスターの状態を表現します。 Kubernetesオブジェクトモデルと、これらのオブジェクトの利用方法について学びます。

3.1.4.1 - Kubernetesオブジェクトを理解する

このページでは、KubernetesオブジェクトがKubernetes APIでどのように表現されているか、またそれらを.yamlフォーマットでどのように表現するかを説明します。

Kubernetesオブジェクトを理解する

Kubernetesオブジェクト は、Kubernetes上で永続的なエンティティです。Kubernetesはこれらのエンティティを使い、クラスターの状態を表現します。具体的に言うと、下記のような内容が表現できます:

  • どのようなコンテナ化されたアプリケーションが稼働しているか(またそれらはどのノード上で動いているか)
  • それらのアプリケーションから利用可能なリソース
  • アプリケーションがどのように振る舞うかのポリシー、例えば再起動、アップグレード、耐障害性ポリシーなど

Kubernetesオブジェクトは「意図の記録」です。一度オブジェクトを作成すると、Kubernetesは常にそのオブジェクトが存在し続けるように動きます。オブジェクトを作成することで、Kubernetesに対し効果的にあなたのクラスターのワークロードがこのようになっていて欲しいと伝えているのです。これが、あなたのクラスターの望ましい状態です。

Kubernetesオブジェクトを操作するには、作成、変更、または削除に関わらずKubernetes APIを使う必要があるでしょう。例えばkubectlコマンドラインインターフェースを使った場合、このCLIが処理に必要なKubernetes API命令を、あなたに代わり発行します。あなたのプログラムからクライアントライブラリを利用し、直接Kubernetes APIを利用することも可能です。

オブジェクトのspec(仕様)とstatus(状態)

ほとんどのKubernetesオブジェクトは、オブジェクトの設定を管理する2つの入れ子になったオブジェクトのフィールドを持っています。それはオブジェクト spec とオブジェクト status です。specを持っているオブジェクトに関しては、オブジェクト作成時にspecを設定する必要があり、望ましい状態としてオブジェクトに持たせたい特徴を記述する必要があります。

status オブジェクトはオブジェクトの 現在の状態 を示し、その情報はKubernetesシステムとそのコンポーネントにより提供、更新されます。Kubernetesコントロールプレーンは、あなたから指定された望ましい状態と現在の状態が一致するよう常にかつ積極的に管理をします。

例えば、KubernetesのDeploymentはクラスター上で稼働するアプリケーションを表現するオブジェクトです。Deploymentを作成するとき、アプリケーションの複製を3つ稼働させるようDeploymentのspecで指定するかもしれません。KubernetesはDeploymentのspecを読み取り、指定されたアプリケーションを3つ起動し、現在の状態がspecに一致するようにします。もしこれらのインスタンスでどれかが落ちた場合(statusが変わる)、Kubernetesはspecと、statusの違いに反応し、修正しようとします。この場合は、落ちたインスタンスの代わりのインスタンスを立ち上げます。

spec、status、metadataに関するさらなる情報は、Kubernetes API Conventionsをご確認ください。

Kubernetesオブジェクトを記述する

Kubernetesでオブジェクトを作成する場合、オブジェクトの基本的な情報(例えば名前)と共に、望ましい状態を記述したオブジェクトのspecを渡さなければいけません。KubernetesAPIを利用しオブジェクトを作成する場合(直接APIを呼ぶか、kubectlを利用するかに関わらず)、APIリクエストはそれらの情報をJSON形式でリクエストのBody部に含んでいなければなりません。

ここで、KubernetesのDeploymentに必要なフィールドとオブジェクトのspecを記載した.yamlファイルの例を示します:

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

上に示した.yamlファイルを利用してDeploymentを作成するには、kubectlコマンドラインインターフェースに含まれているkubectl applyコマンドに.yamlファイルを引数に指定し、実行します。ここで例を示します:

kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record

出力結果は、下記に似た形になります:

deployment.apps/nginx-deployment created

必須フィールド

Kubernetesオブジェクトを.yamlファイルに記載して作成する場合、下記に示すフィールドに値をセットしておく必要があります:

  • apiVersion - どのバージョンのKubernetesAPIを利用してオブジェクトを作成するか
  • kind - どの種類のオブジェクトを作成するか
  • metadata - オブジェクトを一意に特定するための情報、文字列のnameUID、また任意のnamespaceが該当する
  • spec - オブジェクトの望ましい状態

specの正確なフォーマットは、Kubernetesオブジェクトごとに異なり、オブジェクトごとに特有な入れ子のフィールドを持っています。Kubernetes API リファレンスが、Kubernetesで作成できる全てのオブジェクトに関するspecのフォーマットを探すのに役立ちます。 例えば、Podオブジェクトに関するspecのフォーマットはPodSpec v1 coreを、またDeploymentオブジェクトに関するspecのフォーマットはDeploymentSpec v1 appsをご確認ください。

次の項目

  • 最も重要、かつ基本的なKubernetesオブジェクト群を学びましょう、例えば、Podです。
  • Kubernetesのコントローラーを学びましょう。
  • Using the Kubernetes APIはこのページでは取り上げていない他のAPIについて説明します。

3.1.4.2 - Kubernetesオブジェクト管理

kubectlコマンドラインツールは、Kubernetesオブジェクトを作成、管理するためにいくつかの異なる方法をサポートしています。 このドキュメントでは、それらの異なるアプローチごとの概要を提供します。 Kubectlを使ったオブジェクト管理の詳細は、Kubectl bookを参照してください。

管理手法

管理手法何を対象にするか推奨環境サポートライター学習曲線
命令型コマンド現行のオブジェクト開発用プロジェクト1+緩やか
命令型オブジェクト設定個々のファイル本番用プロジェクト1中程度
宣言型オブジェクト設定ファイルのディレクトリ本番用プロジェクト1+

命令型コマンド

命令型コマンドを使う場合、ユーザーはクラスター内の現行のオブジェクトに対して処理を行います。 ユーザーはkubectlコマンドに処理内容を引数、もしくはフラグで指定します。

これはKubernetesの使い始め、またはクラスターに対して一度限りのタスクを行う際の最も簡単な手法です。 なぜなら、この手法は現行のオブジェクトに対して直接操作ができ、以前の設定履歴は提供されないからです。

Deploymentオブジェクトを作成し、nginxコンテナの単一インスタンスを起動します:

kubectl run nginx --image nginx

同じことを異なる構文で行います:

kubectl create deployment nginx --image nginx

トレードオフ

オブジェクト設定手法に対する長所:

  • コマンドは簡潔、簡単に学ぶことができ、そして覚えやすいです
  • コマンドではクラスタの設定を変えるのに、わずか1ステップしか必要としません

オブジェクト設定手法に対する短所:

  • コマンドは変更レビュープロセスと連携しません
  • コマンドは変更に伴う監査証跡を提供しません
  • コマンドは現行がどうなっているかという情報を除き、レコードのソースを提供しません
  • コマンドはオブジェクトを作成するためのテンプレートを提供しません

命令型オブジェクト設定

命令型オブジェクト設定では、kubectlコマンドに処理内容(create、replaceなど)、任意のフラグ、そして最低1つのファイル名を指定します。 指定されたファイルは、YAMLまたはJSON形式でオブジェクトの全ての定義情報を含んでいなければいけません。

オブジェクト定義の詳細は、APIリファレンスを参照してください。

設定ファイルに定義されたオブジェクトを作成します:

kubectl create -f nginx.yaml

設定ファイルに定義されたオブジェクトを削除します:

kubectl delete -f nginx.yaml -f redis.yaml

設定ファイルに定義された情報で、現行の設定を上書き更新します:

kubectl replace -f nginx.yaml

トレードオフ

命令型コマンド手法に対する長所:

  • オブジェクト設定をGitのような、ソースコード管理システムに格納することができます
  • オブジェクト設定の変更内容をプッシュする前にレビュー、監査証跡を残すようなプロセスと連携することができます
  • オブジェクト設定は新しいオブジェクトを作る際のテンプレートを提供します

命令型コマンド手法に対する短所:

  • オブジェクト設定ではオブジェクトスキーマの基礎的な理解が必要です
  • オブジェクト設定ではYAMLファイルを書くという、追加のステップが必要です

宣言型オブジェクト設定手法に対する長所:

  • 命令型オブジェクト設定の振る舞いは、よりシンプルで簡単に理解ができます
  • Kubernetesバージョン1.5においては、命令型オブジェクト設定の方がより成熟しています

宣言型オブジェクト設定手法に対する短所:

  • 命令型オブジェクト設定は各ファイルごとに設定を書くには最も適していますが、ディレクトリには適していません
  • 現行オブジェクトの更新は設定ファイルに対して反映しなければなりません。反映されない場合、次の置き換え時に更新内容が失われてしまいます

宣言型オブジェクト設定

宣言型オブジェクト設定を利用する場合、ユーザーはローカルに置かれている設定ファイルを操作します。 しかし、ユーザーはファイルに対する操作内容を指定しません。作成、更新、そして削除といった操作はオブジェクトごとにkubectlが検出します。 この仕組みが、異なるオブジェクトごとに異なる操作をディレクトリに対して行うことを可能にしています。

configディレクトリ配下にある全てのオブジェクト設定ファイルを処理し、作成、または現行オブジェクトへのパッチを行います。 まず、diffでどのような変更が行われるかを確認した後に適用します:

kubectl diff -f configs/
kubectl apply -f configs/

再帰的にディレクトリを処理します:

kubectl diff -R -f configs/
kubectl apply -R -f configs/

トレードオフ

命令型オブジェクト設定手法に対する長所:

  • 現行オブジェクトに直接行われた変更が、それらが設定ファイルに反映されていなかったとしても、保持されます
  • 宣言型オブジェクト設定は、ディレクトリごとの処理をより良くサポートしており、自動的にオブジェクトごとに操作のタイプ(作成、パッチ、削除)を検出します

命令型オブジェクト設定手法に対する短所:

  • 宣言型オブジェクト設定は、デバッグ、そして想定外の結果が出たときに理解するのが困難です
  • 差分を利用した一部のみの更新は、複雑なマージ、パッチの操作が必要です

次の項目

3.1.4.3 - オブジェクトの名前とID

クラスター内の各オブジェクトには、そのタイプのリソースに固有の名前があります。すべてのKubernetesオブジェクトには、クラスター全体で一意のUIDもあります。

たとえば、同じ名前空間内にmyapp-1234という名前のPodは1つしか含められませんが、myapp-1234という名前の1つのPodと1つのDeploymentを含めることができます。

ユーザーが一意ではない属性を付与するために、Kubernetesはラベルアノテーションを提供しています。

名前

クライアントから提供され、リソースURL内のオブジェクトを参照する文字列です。例えば/api/v1/pods/何らかの名前のようになります。

同じ種類のオブジェクトは、同じ名前を同時に持つことはできません。しかし、オブジェクトを削除することで、旧オブジェクトと同じ名前で新しいオブジェクトを作成できます。

次の3つの命名規則がよく使われます。

DNSサブドメイン名

ほとんどのリソースタイプには、RFC 1123で定義されているDNSサブドメイン名として使用できる名前が必要です。 つまり、名前は次のとおりでなければなりません:

  • 253文字以内
  • 英小文字、数字、「-」または「.」のみを含む
  • 英数字で始まる
  • 英数字で終わる

DNSラベル名

一部のリソースタイプでは、RFC 1123で定義されているDNSラベル標準に従う名前が必要です。 つまり、名前は次のとおりでなければなりません:

  • 63文字以内
  • 英小文字、数字または「-」のみを含む
  • 英数字で始まる
  • 英数字で終わる

パスセグメント名

一部のリソースタイプでは、名前をパスセグメントとして安全にエンコードできるようにする必要があります。 つまり、名前を「.」や「..」にすることはできず、名前に「/」または「%」を含めることはできません。

以下は、nginx-demoという名前のPodのマニフェストの例です。

apiVersion: v1
kind: Pod
metadata:
  name: nginx-demo
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

UID

オブジェクトを一意に識別するためのKubernetesが生成する文字列です。

Kubernetesクラスターの生存期間中にわたって生成された全てのオブジェクトは、異なるUIDを持っています。これは類似のエンティティの、同一時間軸での存在を区別するのが目的です。

Kubernetes UIDは、UUIDのことを指します。 UUIDは、ISO/IEC 9834-8およびITU-T X.667として標準化されています。

次の項目

3.1.4.4 - Namespace(名前空間)

Kubernetesは、同一の物理クラスター上で複数の仮想クラスターの動作をサポートします。 この仮想クラスターをNamespaceと呼びます。

複数のNamespaceを使う時

Namespaceは、複数のチーム・プロジェクトにまたがる多くのユーザーがいる環境での使用を目的としています。 数人から数十人しかユーザーのいないクラスターに対して、あなたはNamespaceを作成したり、考える必要は全くありません。 Kubernetesが提供するNamespaceの機能が必要となった時に、Namespaceの使用を始めてください。

Namespaceは名前空間のスコープを提供します。リソース名は単一のNamespace内ではユニークである必要がありますが、Namespace全体ではその必要はありません。Namespaceは相互にネストすることはできず、各Kubernetesリソースは1つのNamespaceにのみ存在できます。

Namespaceは、複数のユーザーの間でクラスターリソースを分割する方法です。(これはリソースクォータを介して分割します。)

同じアプリケーションの異なるバージョンなど、少し違うリソースをただ分割するだけに、複数のNamespaceを使う必要はありません。 同一のNamespace内でリソースを区別するためにはラベルを使用してください。

Namespaceを利用する

Namespaceの作成と削除方法はNamespaceの管理ガイドドキュメントに記載されています。

Namespaceの表示

ユーザーは、以下の方法で単一クラスター内の現在のNamespaceの一覧を表示できます。

kubectl get namespace
NAME              STATUS   AGE
default           Active   1d
kube-node-lease   Active   1d
kube-system       Active   1d
kube-public       Active   1d

Kubernetesの起動時には4つの初期Namespaceが作成されています。

  • default 他にNamespaceを持っていないオブジェクトのためのデフォルトNamespace
  • kube-system Kubernetesシステムによって作成されたオブジェクトのためのNamespace
  • kube-public このNamespaceは自動的に作成され、全てのユーザーから読み取り可能です。(認証されていないユーザーも含みます。) このNamespaceは、リソースをクラスター全体を通じてパブリックに表示・読み取り可能にするため、ほとんどクラスターによって使用される用途で予約されます。 このNamespaceのパブリックな側面は単なる慣例であり、要件ではありません。
  • kube-node-lease クラスターのスケールに応じたノードハートビートのパフォーマンスを向上させる各ノードに関連したLeaseオブジェクトのためのNamespace。

Namespaceの設定

現在のリクエストのNamespaceを設定するには、--namespaceフラグを使用します。

例:

kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>

Namespace設定の永続化

ユーザーはあるコンテキストのその後のコマンドで使うために、コンテキスト内で永続的にNamespaceを保存できます。

kubectl config set-context --current --namespace=<insert-namespace-name-here>
# Validate it
kubectl config view --minify | grep namespace:

NamespaceとDNS

ユーザーがServiceを作成するとき、Serviceは対応するDNSエントリを作成します。 このエントリは<service-name>.<namespace-name>.svc.cluster.localという形式になり、これはもしあるコンテナがただ<service-name>を指定していた場合、Namespace内のローカルのServiceに対して名前解決されます。 これはデベロップメント、ステージング、プロダクションといった複数のNamespaceをまたいで同じ設定を使う時に効果的です。 もしユーザーがNamespaceをまたいでアクセスしたい時、 完全修飾ドメイン名(FQDN)を指定する必要があります。

すべてのオブジェクトはNamespaceに属しているとは限らない

ほとんどのKubernetesリソース(例えば、Pod、Service、ReplicationControllerなど)はいくつかのNamespaceにあります。 しかしNamespaceのリソースそれ自体は単一のNamespace内にありません。 そしてNodeやPersistentVolumeのような低レベルのリソースはどのNamespaceにも属していません。

どのKubernetesリソースがNamespaceに属しているか、属していないかを見るためには、以下のコマンドで確認できます。

# Namespaceに属しているもの
kubectl api-resources --namespaced=true

# Namespaceに属していないもの
kubectl api-resources --namespaced=false

次の項目

3.1.4.5 - ラベル(Labels)とセレクター(Selectors)

ラベル(Labels) はPodなどのオブジェクトに割り当てられたキーとバリューのペアです。
ラベルはユーザーに関連した意味のあるオブジェクトの属性を指定するために使われることを目的としています。しかしKubernetesのコアシステムに対して直接的にその意味を暗示するものではありません。
ラベルはオブジェクトのサブセットを選択し、グルーピングするために使うことができます。また、ラベルはオブジェクトの作成時に割り当てられ、その後いつでも追加、修正ができます。
各オブジェクトはキーとバリューのラベルのセットを定義できます。各キーは、単一のオブジェクトに対してはユニークである必要があります。

"metadata": {
  "labels": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

ラベルは効率的な検索・閲覧を可能にし、UIやCLI上での利用に最適です。 識別用途でない情報は、アノテーションを用いて記録されるべきです。

ラベルを使う動機

ラベルは、クライアントにそのマッピング情報を保存することを要求することなく、ユーザー独自の組織構造をシステムオブジェクト上で疎結合にマッピングできます。

サービスデプロイメントとバッチ処理のパイプラインは多くの場合、多次元のエンティティとなります(例: 複数のパーティション、Deployment、リリーストラック、ティアー、ティアー毎のマイクロサービスなど)
管理は分野横断的な操作が必要になることが多く、それによって厳密な階層表現、特にユーザーによるものでなく、インフラストラクチャーによって定義された厳格な階層のカプセル化が破られます。

ラベルの例:

  • "release" : "stable", "release" : "canary"
  • "environment" : "dev", "environment" : "qa", "environment" : "production"
  • "tier" : "frontend", "tier" : "backend", "tier" : "cache"
  • "partition" : "customerA", "partition" : "customerB"
  • "track" : "daily", "track" : "weekly"

これらは単によく使われるラベルの例です。ユーザーは自由に規約を決めることができます。 ラベルのキーは、ある1つのオブジェクトに対してユニークである必要があることは覚えておかなくてはなりません。

構文と文字セット

ラベルは、キーとバリューのベアです。正しいラベルキーは2つのセグメントを持ちます。
それは/によって分割されたオプショナルなプレフィックスと名前です。
名前セグメントは必須で、63文字以下である必要があり、文字列の最初と最後は英数字([a-z0-9A-Z])で、文字列の間ではこれに加えてダッシュ(-)、アンダースコア(_)、ドット(.)を使うことができます。
プレフィックスはオプションです。もしプレフィックスが指定されていた場合、プレフィックスはDNSサブドメイン形式である必要があり、それはドット(.)で区切られたDNSラベルのセットで、253文字以下である必要があり、最後にスラッシュ(/)が続きます。

もしプレフィックスが省略された場合、ラベルキーはそのユーザーに対してプライベートであると推定されます。
エンドユーザーのオブジェクトにラベルを追加するような自動化されたシステムコンポーネント(例: kube-scheduler kube-controller-manager kube-apiserver kubectlやその他のサードパーティツール)は、プレフィックスを指定しなくてはなりません。

kubernetes.io/k8s.io/プレフィックスは、Kubernetesコアコンポーネントのために予約されています。

正しいラベル値は63文字以下の長さで、空文字か、もしくは開始と終了が英数字([a-z0-9A-Z])で、文字列の間がダッシュ(-)、アンダースコア(_)、ドット(.)と英数字である文字列を使うことができます。

例えば、environment: productionapp: nginxの2つのラベルを持つPodの設定ファイルは下記のようになります。


apiVersion: v1
kind: Pod
metadata:
  name: label-demo
  labels:
    environment: production
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

ラベルセレクター

名前とUIDとは異なり、ラベルはユニーク性を提供しません。通常、多くのオブジェクトが同じラベルを保持することを想定します。

ラベルセレクター を介して、クライアントとユーザーはオブジェクトのセットを指定できます。ラベルセレクターはKubernetesにおいてコアなグルーピング機能となります。

Kubernetes APIは現在2タイプのセレクターをサポートしています。
それは等価ベース(equality-based)集合ベース(set-based) です。
単一のラベルセレクターは、コンマ区切りの複数の要件(requirements) で構成されています。
複数の要件がある場合、コンマセパレーターは論理積 AND(&&)オペレーターと同様にふるまい、全ての要件を満たす必要があります。

空文字の場合や、指定なしのセレクターに関するセマンティクスは、コンテキストに依存します。 そしてセレクターを使うAPIタイプは、それらのセレクターの妥当性とそれらが示す意味をドキュメントに記載するべきです。

等価ベース(Equality-based) の要件(requirement)

等価ベース(Equality-based) もしくは不等ベース(Inequality-based) の要件は、ラベルキーとラベル値によるフィルタリングを可能にします。
要件に一致したオブジェクトは、指定されたラベルの全てを満たさなくてはいけませんが、それらのオブジェクトはさらに追加のラベルも持つことができます。
そして等価ベースの要件においては、3つの種類のオペレーターの利用が許可されています。===!=となります。
最初の2つのオペレーター(===)は等価(Equality) を表現し(この2つは単なる同義語)、最後の1つ(!=)は不等(Inequality) を意味します。
例えば

environment = production
tier != frontend

最初の例は、キーがenvironmentで、値がproductionである全てのリソースを対象にします。
次の例は、キーがtierで、値がfrontendとは異なるリソースと、tierという名前のキーを持たない全てのリソースを対象にします。
コンマセパレーター,を使って、productionの中から、frontendのものを除外するようにフィルターすることもできます。
environment=production,tier!=frontend

等価ベースのラベル要件の1つの使用シナリオとして、PodにおけるNodeの選択要件を指定するケースがあります。
例えば、下記のサンプルPodは、ラベルaccelerator=nvidia-tesla-p100をもったNodeを選択します。

apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "k8s.gcr.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100

集合ベース(Set-based) の要件(requirement)

集合ベース(Set-based) のラベルの要件は値のセットによってキーをフィルタリングします。
innotinexistsの3つのオペレーターをサポートしています(キーを特定するのみ)。

例えば:

environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
  • 最初の例では、キーがenvironmentで、値がproductionqaに等しいリソースを全て選択します。
  • 第2の例では、キーがtierで、値がfrontendbackend以外のもの、そしてtierキーを持たないリソースを全て選択します。
  • 第3の例では、partitionというキーをもつラベルを全て選択し、値はチェックしません。
  • 第4の例では、partitionというキーを持たないラベルを全て選択し、値はチェックしません。

同様に、コンマセパレーターは、AND オペレーターと同様にふるまいます。そのため、partitionenvironmentキーの値がともにqaでないラベルを選択するには、partition,environment notin (qa)と記述することで可能です。
集合ベース のラベルセレクターは、environment=productionという記述がenvironment in (production)と等しいため、一般的な等価形式となります。 !=notinも同様に等価となります。

集合ベース の要件は、等価ベース の要件と混在できます。
例えば:
partition in (customerA, customerB),environment!=qa.

API

LISTとWATCHによるフィルタリング

LISTとWATCHオペレーションは、単一のクエリパラメータを使うことによって返されるオブジェクトのセットをフィルターするためのラベルセレクターを指定できます。
集合ベース等価ベース のどちらの要件も許可されています(ここでは、URLクエリストリング内で出現します)。

  • 等価ベース での要件: ?labelSelector=environment%3Dproduction,tier%3Dfrontend
  • 集合ベース での要件: ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29

上記の2つの形式のラベルセレクターはRESTクライアントを介してリストにしたり、もしくは確認するために使われます。
例えば、kubectlによってapiserverをターゲットにし、等価ベース の要件でフィルターすると以下のように書けます。

kubectl get pods -l environment=production,tier=frontend

もしくは、集合ベース の要件を指定すると以下のようになります。

kubectl get pods -l 'environment in (production),tier in (frontend)'

すでに言及したように、集合ベース の要件は、等価ベース の要件より表現力があります。
例えば、値に対する OR オペレーターを実装して以下のように書けます。

kubectl get pods -l 'environment in (production, qa)'

もしくは、exists オペレーターを介して、否定マッチングによる制限もできます。

kubectl get pods -l 'environment,environment notin (frontend)'

APIオブジェクトに参照を設定する

ServiceReplicationControllerのような、いくつかのKubernetesオブジェクトでは、ラベルセレクターをPodのような他のリソースのセットを指定するのにも使われます。

ServiceとReplicationController

Serviceが対象とするPodの集合は、ラベルセレクターによって定義されます。
同様に、ReplicationControllerが管理するべきPod数についてもラベルセレクターを使って定義されます。

それぞれのオブジェクトに対するラベルセレクターはマップを使ってjsonもしくはyaml形式のファイルで定義され、等価ベース のセレクターのみサポートされています。

"selector": {
    "component" : "redis",
}

もしくは

selector:
    component: redis

このセレクター(それぞれjsonまたはyaml形式)は、component=redisまたはcomponent in (redis)と等価です。

集合ベース の要件指定をサポートするリソース

JobDeploymentReplicaSetDaemonSetなどの比較的新しいリソースは、集合ベース での要件指定もサポートしています。

selector:
  matchLabels:
    component: redis
  matchExpressions:
    - {key: tier, operator: In, values: [cache]}
    - {key: environment, operator: NotIn, values: [dev]}

matchLabelsは、{key,value}ペアのマップです。matchLabels内の単一の{key,value}は、matchExpressionsの要素と等しく、それは、keyフィールドがキー名で、operatorが"In"で、values配列は単に"値"を保持します。
matchExpressionsはPodセレクター要件のリストです。対応しているオペレーターはInNotInExistsDoesNotExistです。valuesのセットは、InNotInオペレーターにおいては空文字を許容しません。
matchLabelsmatchExpressionsの両方によって指定された全ての要件指定はANDで判定されます。つまり要件にマッチするには指定された全ての要件を満たす必要があります。

Nodeのセットを選択する

ラベルを選択するための1つのユースケースはPodがスケジュールできるNodeのセットを制限することです。
さらなる情報に関しては、Node選定 のドキュメントを参照してください。

3.1.4.6 - アノテーション(Annotations)

ユーザーは、識別用途でない任意のメタデータをオブジェクトに割り当てるためにアノテーションを使用できます。ツールやライブラリなどのクライアントは、このメタデータを取得できます。

オブジェクトにメタデータを割り当てる

ユーザーは、Kubernetesオブジェクトに対してラベルやアノテーションの両方またはどちらか一方を割り当てることができます。 ラベルはオブジェクトの選択や、特定の条件を満たしたオブジェクトの集合を探すことに使うことができます。 それと対照的に、アノテーションはオブジェクトを識別、または選択するために使用されません。 アノテーション内のメタデータは大小様々で、構造化されているものや、そうでないものも設定でき、ラベルでは許可されていない文字も含むことができます。

アノテーションは、ラベルと同様に、キーとバリューのマップとなります。

"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

下記は、アノテーション内で記録できる情報の例です。

  • 宣言的設定レイヤによって管理されているフィールド。これらのフィールドをアノテーションとして割り当てることで、クライアントもしくはサーバによってセットされたデフォルト値、オートサイジングやオートスケーリングシステムによってセットされたフィールドや、自動生成のフィールドなどと区別することができます。

  • ビルド、リリースやタイムスタンプのようなイメージの情報、リリースID、gitのブランチ、PR番号、イメージハッシュ、レジストリアドレスなど

  • ロギング、監視、分析用のポインタ、もしくは監査用リポジトリ

  • デバッグ目的で使用されるためのクライアントライブラリやツールの情報。例えば、名前、バージョン、ビルド情報など。

  • 他のエコシステムのコンポーネントからの関連オブジェクトのURLなど、ユーザーやツール、システムの出所情報。

  • 軽量ロールアウトツールのメタデータ。 例えば設定やチェックポイントなど。

  • 情報をどこで確認できるかを示すためのもの。例えばチームのウェブサイト、責任者の電話番号や、ページャー番号やディレクトリエンティティなど。

  • システムのふるまいの変更や、標準ではない機能を利用可能にするために、エンドユーザーがシステムに対して指定する値

アノテーションを使用するかわりに、ユーザーはこのようなタイプの情報を外部のデータベースやディレクトリに保存することもできます。しかし、それによりデプロイ、管理、イントロスペクションを行うためのクライアンライブラリやツールの生成が非常に難しくなります。

構文と文字セット

アノテーション はキーとバリューのペアです。有効なアノテーションのキーの形式は2つのセグメントがあります。 プレフィックス(オプション)と名前で、それらはスラッシュ/で区切られます。 名前セグメントは必須で、63文字以下である必要があり、文字列の最初と最後は英数字([a-z0-9A-Z])と、文字列の間にダッシュ(-)、アンダースコア(_)、ドット(.)を使うことができます。 プレフィックスはオプションです。もしプレフィックスが指定されていた場合、プレフィックスはDNSサブドメイン形式である必要があり、それはドット(.)で区切られたDNSラベルのセットで、253文字以下である必要があり、最後にスラッシュ(/)が続きます。

もしプレフィックスが除外された場合、アノテーションキーはそのユーザーに対してプライベートであると推定されます。 エンドユーザーのオブジェクトにアノテーションを追加するような自動化されたシステムコンポーネント(例: kube-scheduler kube-controller-manager kube-apiserver kubectlやその他のサードパーティツール)は、プレフィックスを指定しなくてはなりません。

kubernetes.io/k8s.io/プレフィックスは、Kubernetesコアコンポーネントのために予約されています。

たとえば、imageregistry: https://hub.docker.com/というアノテーションが付いたPodの構成ファイルは次のとおりです:

apiVersion: v1
kind: Pod
metadata:
  name: annotations-demo
  annotations:
    imageregistry: "https://hub.docker.com/"
spec:
  containers:
  - name: nginx
    image: nginx:1.14.2
    ports:
    - containerPort: 80

次の項目

ラベルとセレクターについて学習してください。

3.1.4.7 - フィールドセレクター(Field Selectors)

フィールドセレクター(Field Selectors) は、1つかそれ以上のリソースフィールドの値を元にKubernetesリソースを選択するためのものです。
フィールドセレクタークエリの例は以下の通りです。

  • metadata.name=my-service
  • metadata.namespace!=default
  • status.phase=Pending

下記のkubectlコマンドは、status.phaseフィールドの値がRunningである全てのPodを選択します。

kubectl get pods --field-selector status.phase=Running

サポートされているフィールド

サポートされているフィールドセレクターはKubernetesリソースタイプによって異なります。全てのリソースタイプはmetadata.namemetadata.namespaceフィールドをサポートしています。サポートされていないフィールドセレクターの使用をするとエラーとなります。
例えば以下の通りです。

kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"

サポートされているオペレーター

ユーザーは、===!=といったオペレーターをフィールドセレクターと組み合わせて使用できます。(===は同義)
例として、下記のkubectlコマンドはdefaultネームスペースに属していない全てのKubernetes Serviceを選択します。

kubectl get services  --all-namespaces --field-selector metadata.namespace!=default

連結されたセレクター

ラベルや他のセレクターと同様に、フィールドセレクターはコンマ区切りのリストとして連結することができます。
下記のkubectlコマンドは、status.phaseRunnningでなく、かつspec.restartPolicyフィールドがAlwaysに等しいような全てのPodを選択します。

kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always

複数のリソースタイプ

ユーザーは複数のリソースタイプにまたがったフィールドセレクターを利用できます。
下記のkubectlコマンドは、defaultネームスペースに属していない全てのStatefulSetとServiceを選択します。

kubectl get statefulsets,services --field-selector metadata.namespace!=default

3.1.4.8 - 推奨ラベル(Recommended Labels)

ユーザーはkubectlやダッシュボード以外に、多くのツールでKubernetesオブジェクトの管理と可視化ができます。共通のラベルセットにより、全てのツールにおいて解釈可能な共通のマナーに沿ってオブジェクトを表現することで、ツールの相互運用を可能にします。

ツール化に対するサポートに加えて、推奨ラベルはクエリ可能な方法でアプリケーションを表現します。

メタデータは、アプリケーション のコンセプトを中心に構成されています。KubernetesはPaaS(Platform as a Service)でなく、アプリケーションの公式な概念を持たず、またそれを強制することはありません。 そのかわり、アプリケーションは、非公式で、メタデータによって表現されています。単一のアプリケーションが有する項目に対する定義は厳密に決められていません。

共有されたラベルとアノテーションは、app.kubernetes.ioという共通のプレフィックスを持ちます。プレフィックスの無いラベルはユーザーに対してプライベートなものになります。その共有されたプレフィックスは、共有ラベルがユーザーのカスタムラベルに干渉しないことを保証します。

ラベル

これらの推奨ラベルの利点を最大限得るためには、全てのリソースオブジェクトに対して推奨ラベルが適用されるべきです。

キー説明
app.kubernetes.io/nameアプリケーション名mysql文字列
app.kubernetes.io/instanceアプリケーションのインスタンスを特定するための固有名mysql-abcxzy文字列
app.kubernetes.io/versionアプリケーションの現在のバージョン (例: セマンティックバージョン、リビジョンのハッシュなど)5.7.21文字列
app.kubernetes.io/componentアーキテクチャ内のコンポーネントdatabase文字列
app.kubernetes.io/part-ofこのアプリケーションによって構成される上位レベルのアプリケーションwordpress文字列
app.kubernetes.io/managed-byこのアプリケーションの操作を管理するために使われているツールhelm文字列

これらのラベルが実際にどう使われているかを表すために、下記のStatefulSetのオブジェクトを考えましょう。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: mysql-abcxzy
    app.kubernetes.io/version: "5.7.21"
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
    app.kubernetes.io/managed-by: helm

アプリケーションとアプリケーションのインスタンス

単一のアプリケーションは、Kubernetesクラスタ内で、いくつかのケースでは同一の名前空間に対して1回または複数回インストールされることがあります。 例えば、WordPressは複数のウェブサイトがあれば、それぞれ別のWordPressが複数回インストールされることがあります。

アプリケーション名と、アプリケーションのインスタンス名はそれぞれ別に記録されます。 例えば、WordPressはapp.kubernetes.io/namewordpressと記述され、インスタンス名に関してはapp.kubernetes.io/instancewordpress-abcxzyと記述されます。この仕組みはアプリケーションと、アプリケーションのインスタンスを特定可能にします。全てのアプリケーションインスタンスは固有の名前を持たなければなりません。

ラベルの使用例

ここでは、ラベルの異なる使用例を示します。これらの例はそれぞれシステムの複雑さが異なります。

シンプルなステートレスサービス

DeploymentServiceオブジェクトを使って、シンプルなステートレスサービスをデプロイするケースを考えます。下記の2つのスニペットはラベルが最もシンプルな形式においてどのように使われるかをあらわします。

下記のDeploymentは、アプリケーションを稼働させるポッドを管理するのに使われます。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...

下記のServiceは、アプリケーションを公開するために使われます。

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...

データベースを使ったウェブアプリケーション

次にもう少し複雑なアプリケーションについて考えます。データベース(MySQL)を使ったウェブアプリケーション(WordPress)で、Helmを使ってインストールします。 下記のスニペットは、このアプリケーションをデプロイするために使うオブジェクト設定の出だし部分です。

はじめに下記のDeploymentは、WordPressのために使われます。

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: wordpress
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "4.9.4"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: server
    app.kubernetes.io/part-of: wordpress
...

下記のServiceは、WordPressを公開するために使われます。

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: wordpress
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "4.9.4"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: server
    app.kubernetes.io/part-of: wordpress
...

MySQLはStatefulSetとして公開され、MySQL自身と、MySQLが属する親アプリケーションのメタデータを持ちます。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: mysql-abcxzy
    app.kubernetes.io/version: "5.7.21"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
...

このServiceはMySQLをWordPressアプリケーションの一部として公開します。

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: mysql-abcxzy
    app.kubernetes.io/version: "5.7.21"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
...

MySQLのStatefulSetServiceにより、MySQLとWordPressに関するより広範な情報が含まれていることに気づくでしょう。

3.2 - クラスターのアーキテクチャ

3.2.1 - ノード

Kubernetesはコンテナを Node 上で実行されるPodに配置することで、ワークロードを実行します。 ノードはクラスターによりますが、1つのVMまたは物理的なマシンです。 各ノードはPodやそれを制御するコントロールプレーンを実行するのに必要なサービスを含んでいます。

通常、1つのクラスターで複数のノードを持ちます。学習用途やリソースの制限がある環境では、1ノードかもしれません。

1つのノード上のコンポーネントには、kubeletコンテナランタイムkube-proxyが含まれます。

管理

ノードをAPIサーバーに加えるには2つの方法があります:

  1. ノード上のkubeletが、コントロールプレーンに自己登録する。
  2. あなた、もしくは他のユーザーが手動でNodeオブジェクトを追加する。

Nodeオブジェクトの作成、もしくはノード上のkubeketによる自己登録の後、コントロールプレーンはNodeオブジェクトが有効かチェックします。例えば、下記のjsonマニフェストでノードを作成してみましょう:

{
  "kind": "Node",
  "apiVersion": "v1",
  "metadata": {
    "name": "10.240.79.157",
    "labels": {
      "name": "my-first-k8s-node"
    }
  }
}

Kubernetesは内部的にNodeオブジェクトを作成します。 APIサーバーに登録したkubeletがノードのmetadata.nameフィールドが一致しているか検証します。ノードが有効な場合、つまり必要なサービスがすべて実行されている場合は、Podを実行する資格があります。それ以外の場合、該当ノードが有効になるまではいかなるクラスターの活動に対しても無視されます。

Nodeオブジェクトの名前は有効なDNSサブドメイン名である必要があります。

ノードの自己登録

kubeletのフラグ --register-nodeがtrue(デフォルト)のとき、kubeletは自分自身をAPIサーバーに登録しようとします。これはほとんどのディストリビューションで使用されている推奨パターンです。

自己登録については、kubeletは以下のオプションを伴って起動されます:

  • --kubeconfig - 自分自身をAPIサーバーに対して認証するための資格情報へのパス
  • --cloud-provider - 自身に関するメタデータを読むためにクラウドプロバイダーと会話する方法
  • --register-node - 自身をAPIサーバーに自動的に登録
  • --register-with-taints - 与えられたtaintのリストでノードを登録します (カンマ区切りの <key>=<value>:<effect>)。

register-nodeがfalseの場合、このオプションは機能しません

  • --node-ip - ノードのIPアドレス
  • --node-labels - ノードをクラスターに登録するときに追加するLabelNodeRestriction許可プラグインによって適用されるラベルの制限を参照)
  • --node-status-update-frequency - kubeletがノードのステータスをマスターにPOSTする頻度の指定

ノード認証モードおよびNodeRestriction許可プラグインが有効になっている場合、kubeletは自分自身のノードリソースを作成/変更することのみ許可されています。

手動によるノード管理

クラスター管理者はkubectlを使用してNodeオブジェクトを作成および変更できます。

管理者が手動でNodeオブジェクトを作成したい場合は、kubeletフラグ --register-node = falseを設定してください。

管理者は--register-nodeの設定に関係なくNodeオブジェクトを変更することができます。 例えば、ノードにラベルを設定し、それをunschedulableとしてマークすることが含まれます。

ノード上のラベルは、スケジューリングを制御するためにPod上のノードセレクターと組み合わせて使用できます。 例えば、Podをノードのサブセットでのみ実行する資格があるように制限します。

ノードをunschedulableとしてマークすると、新しいPodがそのノードにスケジュールされるのを防ぎますが、ノード上の既存のPodには影響しません。 これは、ノードの再起動などの前の準備ステップとして役立ちます。

ノードにスケジュール不可能のマークを付けるには、次のコマンドを実行します:

kubectl cordon $ノード名

ノードのステータス

ノードのステータスは以下の情報を含みます:

kubectlを使用し、ノードのステータスや詳細を確認できます:

kubectl describe node <ノード名をここに挿入>

出力情報の各箇所について、以下で説明します。

Addresses

これらのフィールドの使い方は、お使いのクラウドプロバイダーやベアメタルの設定内容によって異なります。

  • HostName: ノードのカーネルによって伝えられたホスト名です。kubeletの--hostname-overrideパラメーターによって上書きすることができます。
  • ExternalIP: 通常は、外部にルーティング可能(クラスターの外からアクセス可能)なノードのIPアドレスです。
  • InternalIP: 通常は、クラスター内でのみルーティング可能なノードのIPアドレスです。

Conditions

conditionsフィールドは全てのRunningなノードのステータスを表します。例として、以下のような状態を含みます:

ノードのConditionと、各condition適用時の概要
ノードのCondition概要
Readyノードの状態が有効でPodを配置可能な場合にTrueになります。ノードの状態に問題があり、Podが配置できない場合にFalseになります。ノードコントローラーが、node-monitor-grace-periodで設定された時間内(デフォルトでは40秒)に該当ノードと疎通できない場合、Unknownになります。
DiskPressureノードのディスク容量が圧迫されているときにTrueになります。圧迫とは、ディスクの空き容量が少ないことを指します。それ以外のときはFalseです。
MemoryPressureノードのメモリが圧迫されているときにTrueになります。圧迫とは、メモリの空き容量が少ないことを指します。それ以外のときはFalseです。
PIDPressureプロセスが圧迫されているときにTrueになります。圧迫とは、プロセス数が多すぎることを指します。それ以外のときはFalseです。
NetworkUnavailableノードのネットワークが適切に設定されていない場合にTrueになります。それ以外のときはFalseです。

Nodeの状態は、Nodeリソースの.statusの一部として表現されます。例えば、正常なノードの場合は以下のようなjson構造が表示されます。

"conditions": [
  {
    "type": "Ready",
    "status": "True",
    "reason": "KubeletReady",
    "message": "kubelet is posting ready status",
    "lastHeartbeatTime": "2019-06-05T18:38:35Z",
    "lastTransitionTime": "2019-06-05T11:41:27Z"
  }
]

Ready conditionがpod-eviction-timeout(kube-controller-managerに渡された引数)に設定された時間を超えてもUnknownFalseのままになっている場合、該当ノード上にあるPodはノードコントローラーによって削除がスケジュールされます。デフォルトの退役のタイムアウトの時間は5分です。ノードが到達不能ないくつかの場合においては、APIサーバーが該当ノードのkubeletと疎通できない状態になっています。その場合、APIサーバーがkubeletと再び通信を確立するまでの間、Podの削除を行うことはできません。削除がスケジュールされるまでの間、削除対象のPodは切り離されたノードの上で稼働を続けることになります。

ノードコントローラーはクラスター内でPodが停止するのを確認するまでは強制的に削除しないようになりました。到達不能なノード上で動いているPodはTerminatingまたはUnknownのステータスになります。Kubernetesが基盤となるインフラストラクチャーを推定できない場合、クラスター管理者は手動でNodeオブジェクトを削除する必要があります。KubernetesからNodeオブジェクトを削除すると、そのノードで実行されているすべてのPodオブジェクトがAPIサーバーから削除され、それらの名前が解放されます。

ノードのライフサイクルコントローラーがconditionを表したtaintを自動的に生成します。 スケジューラーがPodをノードに割り当てる際、ノードのtaintを考慮します。Podが許容するtaintは例外です。

詳細は条件によるtaintの付与を参照してください。

CapacityとAllocatable

ノードで利用可能なリソース(CPU、メモリ、およびノードでスケジュールできる最大Pod数)について説明します。

capacityブロック内のフィールドは、ノードが持っているリソースの合計量を示します。 allocatableブロックは、通常のPodによって消費されるノード上のリソースの量を示します。

CapacityとAllocatableについて深く知りたい場合は、ノード上でどのようにコンピュートリソースが予約されるかを読みながら学ぶことができます。

Info

カーネルのバージョン、Kubernetesのバージョン(kubeletおよびkube-proxyのバージョン)、(使用されている場合)Dockerのバージョン、OS名など、ノードに関する一般的な情報です。 この情報はノードからkubeletを通じて取得され、Kubernetes APIに公開されます。

ハートビート

ハートビートは、Kubernetesノードから送信され、ノードが利用可能か判断するのに役立ちます。 以下の2つのハートビートがあります:

  • Nodeの.statusの更新
  • Lease objectです。 各ノードはkube-node-leaseというnamespaceに関連したLeaseオブジェクトを持ちます。 Leaseは軽量なリソースで、クラスターのスケールに応じてノードのハートビートにおけるパフォーマンスを改善します。

kubeletがNodeStatusとLeaseオブジェクトの作成および更新を担当します。

  • kubeletは、ステータスに変化があったり、設定した間隔の間に更新がない時にNodeStatusを更新します。NodeStatus更新のデフォルト間隔は5分です。(到達不能の場合のデフォルトタイムアウトである40秒よりもはるかに長いです)
  • kubeletは10秒間隔(デフォルトの更新間隔)でLeaseオブジェクトの生成と更新を実施します。Leaseの更新はNodeStatusの更新とは独立されて行われます。Leaseの更新が失敗した場合、kubeletは200ミリ秒から始まり7秒を上限とした指数バックオフでリトライします。

ノードコントローラー

ノードコントローラーは、ノードのさまざまな側面を管理するKubernetesのコントロールプレーンコンポーネントです。

ノードコントローラーは、ノードの存続期間中に複数の役割を果たします。1つ目は、ノードが登録されたときにCIDRブロックをノードに割り当てることです(CIDR割り当てがオンになっている場合)。

2つ目は、ノードコントローラーの内部ノードリストをクラウドの利用可能なマシンのリストと一致させることです。 クラウド環境で実行している場合、ノードに異常があると、ノードコントローラーはクラウドプロバイダーにそのNodeのVMがまだ使用可能かどうかを問い合わせます。 使用可能でない場合、ノードコントローラーはノードのリストから該当ノードを削除します。

3つ目は、ノードの状態を監視することです。 ノードが到達不能(例えば、ノードがダウンしているなどので理由で、ノードコントローラーがハートビートの受信を停止した場合)になると、ノードコントローラーは、NodeStatusのNodeReady conditionをConditionUnknownに変更する役割があります。その後も該当ノードが到達不能のままであった場合、Graceful Terminationを使って全てのPodを退役させます。デフォルトのタイムアウトは、ConditionUnknownの報告を開始するまで40秒、その後Podの追い出しを開始するまで5分に設定されています。 ノードコントローラーは、--node-monitor-periodに設定された秒数ごとに各ノードの状態をチェックします。

信頼性

ほとんどの場合、排除の速度は1秒あたり--node-eviction-rateに設定された数値(デフォルトは秒間0.1)です。つまり、10秒間に1つ以上のPodをノードから追い出すことはありません。

特定のアベイラビリティーゾーン内のノードのステータスが異常になると、ノード排除の挙動が変わります。ノードコントローラーは、ゾーン内のノードの何%が異常(NodeReady条件がConditionUnknownまたはConditionFalseである)であるかを同時に確認します。 異常なノードの割合が少なくとも --healthy-zone-thresholdに設定した値を下回る場合(デフォルトは0.55)であれば、退役率は低下します。クラスターが小さい場合(すなわち、 --large-cluster-size-thresholdの設定値よりもノード数が少ない場合。デフォルトは50)、退役は停止し、そうでない場合、退役率は秒間で--secondary-node-eviction-rateの設定値(デフォルトは0.01)に減少します。 これらのポリシーがアベイラビリティーゾーンごとに実装されているのは、1つのアベイラビリティーゾーンがマスターから分割される一方、他のアベイラビリティーゾーンは接続されたままになる可能性があるためです。 クラスターが複数のクラウドプロバイダーのアベイラビリティーゾーンにまたがっていない場合、アベイラビリティーゾーンは1つだけです(クラスター全体)。

ノードを複数のアベイラビリティゾーンに分散させる主な理由は、1つのゾーン全体が停止したときにワークロードを正常なゾーンに移動できることです。 したがって、ゾーン内のすべてのノードが異常である場合、ノードコントローラーは通常のレート --node-eviction-rateで退役します。 コーナーケースは、すべてのゾーンが完全にUnhealthyである(すなわち、クラスタ内にHealthyなノードがない)場合です。 このような場合、ノードコントローラーはマスター接続に問題があると見なし、接続が回復するまですべての退役を停止します。

ノードコントローラーは、Podがtaintを許容しない場合、 NoExecuteのtaintを持つノード上で実行されているPodを排除する責務もあります。 さらに、ノードコントローラーはノードに到達できない、または準備ができていないなどのノードの問題に対応するtaintを追加する責務があります。これはスケジューラーが、問題のあるノードにPodを配置しない事を意味しています。

ノードのキャパシティ

Nodeオブジェクトはノードのリソースキャパシティ(CPUの数とメモリの量)を監視します。 自己登録したノードは、Nodeオブジェクトを作成するときにキャパシティを報告します。 手動によるノード管理を実行している場合は、ノードを追加するときにキャパシティを設定する必要があります。

Kubernetesスケジューラーは、ノード上のすべてのPodに十分なリソースがあることを確認します。スケジューラーは、ノード上のコンテナが要求するリソースの合計がノードキャパシティ以下であることを確認します。 これは、kubeletによって管理されたすべてのコンテナを含みますが、コンテナランタイムによって直接開始されたコンテナやkubeletの制御外で実行されているプロセスは含みません。

ノードのトポロジー

FEATURE STATE: Kubernetes v1.16 [alpha]
TopologyManagerフィーチャーゲートを有効にすると、 kubeletはリソースの割当を決定する際にトポロジーのヒントを利用できます。 詳細は、ノードのトポロジー管理ポリシーを制御するを参照してください。

ノードの正常終了

FEATURE STATE: Kubernetes v1.21 [beta]

kubeletは、ノードのシステムシャットダウンを検出すると、ノード上で動作しているPodを終了させます。

Kubelet は、ノードのシャットダウン時に、ポッドが通常の通常のポッド終了プロセスに従うようにします。

Graceful Node Shutdownはsystemdに依存しているため、systemd inhibitor locksを 利用してノードのシャットダウンを一定時間遅らせることができます。

Graceful Node Shutdownは、v1.21でデフォルトで有効になっているGracefulNodeShutdown フィーチャーゲートで制御されます。

なお、デフォルトでは、後述の設定オプションShutdownGracePeriodおよびShutdownGracePeriodCriticalPodsの両方がゼロに設定されているため、Graceful node shutdownは有効になりません。この機能を有効にするには、この2つのkubeletの設定を適切に設定し、ゼロ以外の値を設定する必要があります。

Graceful shutdownでは、kubeletは以下の2段階でPodを終了させます。

  1. そのノード上で動作している通常のPodを終了させます。
  2. そのノード上で動作しているcritical podsを終了させます。

Graceful Node Shutdownには、2つのKubeletConfigurationオプションを設定します。:

  • ShutdownGracePeriod:
    • ノードがシャットダウンを遅らせるべき合計期間を指定します。これは、通常のPodとcritical podsの両方のPod終了の合計猶予期間です。
  • ShutdownGracePeriodCriticalPods:
    • ノードのシャットダウン時にcritical podsを終了させるために使用する期間を指定します。この値は、ShutdownGracePeriodよりも小さくする必要があります。

例えば、ShutdownGracePeriod=30sShutdownGracePeriodCriticalPods=10sとすると、 kubeletはノードのシャットダウンを30秒遅らせます。シャットダウンの間、最初の20(30-10)秒は通常のポッドを優雅に終了させるために確保され、 残りの10秒は重要なポッドを終了させるために確保されることになります。

スワップメモリの管理

FEATURE STATE: Kubernetes v1.22 [alpha]

Kubernetes 1.22以前では、ノードはスワップメモリの使用をサポートしておらず、ノード上でスワップが検出された場合、 kubeletはデフォルトで起動に失敗していました。1.22以降では、スワップメモリのサポートをノードごとに有効にすることができます。

ノードでスワップを有効にするには、kubeletの NodeSwap フィーチャーゲートを有効にし、 --fail-swap-onコマンドラインフラグまたはfailSwapOnKubeletConfigurationを false に設定する必要があります。

ユーザーはオプションで、ノードがスワップメモリをどのように使用するかを指定するために、memorySwap.swapBehaviorを設定することもできます。ノードがスワップメモリをどのように使用するかを指定します。例えば、以下のようになります。

memorySwap:
  swapBehavior: LimitedSwap

swapBehaviorで使用できる設定オプションは以下の通りです。:

  • LimitedSwap: Kubernetesのワークロードが、使用できるスワップ量に制限を設けます。Kubernetesが管理していないノード上のワークロードは、依然としてスワップを使用できます。
  • UnlimitedSwap: Kubernetesのワークロードが使用できるスワップ量に制限を設けません。システムの限界まで、要求されただけのスワップメモリを使用することができます。

memorySwapの設定が指定されておらず、フィーチャーゲートが有効な場合、デフォルトのkubeletはLimitedSwapの設定と同じ動作を適用します。

LimitedSwap設定の動作は、ノードがコントロールグループ(「cgroups」とも呼ばれる)のv1とv2のどちらで動作しているかによって異なります。

Kubernetesのワークロードでは、メモリとスワップを組み合わせて使用することができ、ポッドのメモリ制限が設定されている場合はその制限まで使用できます。

  • cgroupsv1: Kubernetesのワークロードは、メモリとスワップを組み合わせて使用することができ、ポッドのメモリ制限が設定されている場合はその制限まで使用できます。
  • cgroupsv2: Kubernetesのワークロードは、スワップメモリを使用できません。

詳しくは、KEP-2400design proposalをご覧いただき、テストにご協力、ご意見をお聞かせください。

次の項目

3.2.2 - マスターとノード間の通信

本ドキュメントでは、KubernetesにおけるMaster(実態はAPIサーバー)およびクラスター間のコミュニケーション経路についてまとめます。 この文書の目的は、信頼できないネットワーク上(またはクラウドプロバイダ上の完全にパブリックなIP上)でクラスタを実行できるように、ユーザーがインストールをカスタマイズしてネットワーク構成を強化できるようにすることです。

クラスターからマスターへの通信

クラスターからマスターへのすべての通信経路は、APIサーバーで終端します(他のマスターコンポーネントはどれもリモートサービスを公開するように設計されていません)。 一般的には、1つ以上の形式のクライアント認証が有効になっている状態で、APIサーバーはセキュアなHTTPSポート(443)でリモート接続をlistenするように構成されています。 特に匿名のリクエストまたはサービスアカウントトークンが許可されている場合は、1つまたは複数の認証を有効にする必要があります。

ノードには、有効なクライアント認証情報を使って安全にAPIサーバーに接続できるように、クラスターのパブリックなルート証明書をプロビジョニングする必要があります。 たとえば、GKEのデフォルト設定では、kubeletに提供されるクライアント認証情報はクライアント証明書の形式です。 kubeletのクライアント証明書を自動プロビジョニングする方法については、kubelet TLSブートストラッピングを参照してください。

APIサーバーに接続したいPodは、サービスアカウントを利用することで接続を安全にすることができます。そうすることで、Podが作成されたときにKubernetesがパブリックなルート証明書と有効なBearer TokenをPodに自動的に挿入します。

kubernetesサービスには(すべてのネームスペースで)、APIサーバー上のHTTPSエンドポイントに(kube-proxy経由で)リダイレクトされる仮想IPアドレスが設定されています。

マスターコンポーネントは、セキュアなポートを介してクラスターAPIサーバーとも通信します。

その結果、クラスター(ノードとそのノードで実行されているPod)からマスターへの接続はデフォルトで保護され、信頼できないネットワークやパブリックネットワークを介して実行できます。

マスターからクラスターへの通信

マスター(APIサーバー)からクラスターへの通信には、2つの主要な通信経路があります。 1つ目は、APIサーバーからクラスター内の各ノードで実行されるkubeletプロセスへの通信です。 2つ目は、APIサーバーのプロキシ機能を介した、APIサーバーから任意のノード、Pod、またはサービスへのアクセスです。

APIサーバーからkubeletへの通信

APIサーバーからkubeletへの接続は以下の目的で使用されます:

  • Podのログを取得する
  • 実行中のPodに(kubectlを通して)接続する
  • kubeletのポート転送機能を提供する

これらの接続は、kubeletのHTTPSエンドポイントで終了します。 デフォルトでは、APIサーバーはkubeletが提供する証明書を検証しないため、接続は中間者攻撃を受けやすく、安全でない信頼できないネットワークやパブリックなネットワークを介して実行されることになります。

この接続を検証するには、--kubelet-certificate-authorityフラグを使用して、kubeletが提供する証明書を確認するために使用するルート証明書バンドルをAPIサーバーに提供します。

それができない場合は、信頼できないネットワークやパブリックなネットワークを介した接続を回避するために、必要に応じてAPIサーバーとkubeletの間でSSHトンネリングを使用してください。

最後に、kubeletのAPIを保護するためにkubeletの認証認可を有効にする必要があります。

APIサーバーからノード、Pod、サービスへの通信

APIサーバーからノード、Pod、またはサービスへの接続はデフォルトで平文のHTTP接続になるため、認証も暗号化もされません。 API URL内のノード、Pod、またはサービス名にhttps:を付けることで安全なHTTPS接続で実行できますが、HTTPSエンドポイントから提供される証明書を検証したりクライアントの資格情報を提供したりすることはありませんし、暗号化されているという完全性を保証するものでもありません。 これらの接続を信頼できないネットワークや公衆ネットワークを介して実行するのは、現時点において安全ではありません。

SSHトンネル

Kubernetesはマスターからクラスターへの通信経路を保護するためにSSHトンネルをサポートしています。 この設定では、APIサーバーはクラスター内の各ノード(ポート22でlistenしているsshサーバーに接続)へのSSHトンネルを開始し、トンネルを介してkubelet、ノード、Pod、またはサービス宛てのすべてのトラフィックを渡します。 このトンネルにより、ノードが実行されているネットワークの外部にトラフィックが公開されないようにします。

SSHトンネルは現在非推奨なので、自分がしていることが分からない限り、使用しないでください。この通信チャネルに代わるものが設計されています。

3.2.3 - コントローラー

ロボット工学やオートメーションの分野において、 制御ループ とは、あるシステムの状態を制御する終了状態のないループのことです。

ここでは、制御ループの一例として、部屋の中にあるサーモスタットを挙げます。

あなたが温度を設定すると、それはサーモスタットに 目的の状態(desired state) を伝えることになります。実際の部屋の温度は 現在の状態 です。サーモスタットは、装置をオンまたはオフにすることによって、現在の状態を目的の状態に近づけるように動作します。

Kubernetesにおいて、コントローラーはクラスターの状態を監視し、必要に応じて変更を加えたり要求したりする制御ループです。それぞれのコントローラーは現在のクラスターの状態を望ましい状態に近づけるように動作します。

コントローラーパターン

コントローラーは少なくとも1種類のKubernetesのリソースを監視します。これらのオブジェクトには目的の状態を表すspecフィールドがあります。リソースのコントローラーは、現在の状態を目的の状態に近づける責務を持ちます。

コントローラーは自分自身でアクションを実行する場合もありますが、KubernetesではコントローラーがAPIサーバーに意味のある副作用を持つメッセージを送信することが一般的です。以下では、このような例を見ていきます。

APIサーバー経由でコントロールする

JobコントローラーはKubernetesのビルトインのコントローラーの一例です。ビルトインのコントローラーは、クラスターのAPIサーバーとやりとりをして状態を管理します。

Jobは、1つ以上のPodを起動して、タスクを実行した後に停止する、Kubernetesのリソースです。

(1度スケジュールされると、Podオブジェクトはkubeletに対する目的の状態の一部になります。)

Jobコントローラーが新しいタスクを見つけると、その処理が完了するように、クラスター上のどこかで、一連のNode上のkubeletが正しい数のPodを実行することを保証します。ただし、Jobコントローラーは、自分自身でPodやコンテナを実行することはありません。代わりに、APIサーバーに対してPodの作成や削除を依頼します。コントロールプレーン上の他のコンポーネントが(スケジュールして実行するべき新しいPodが存在するという)新しい情報を基に動作することによって、最終的に目的の処理が完了します。

新しいJobが作成されたとき、目的の状態は、そのJobが完了することです。JobコントローラーはそのJobに対する現在の状態を目的の状態に近づけるようにします。つまり、そのJobが行ってほしい処理を実行するPodを作成し、Jobが完了に近づくようにします。

コントローラーは、コントローラーを設定するオブジェクトも更新します。たとえば、あるJobが完了した場合、Jobコントローラーは、JobオブジェクトにFinishedというマークを付けます。

(これは、部屋が設定温度になったことを示すために、サーモスタットがランプを消灯するのに少し似ています。)

直接的なコントロール

Jobとは対照的に、クラスターの外部に変更を加える必要があるコントローラーもあります。

たとえば、クラスターに十分な数のNodeが存在することを保証する制御ループの場合、そのコントローラーは、必要に応じて新しいNodeをセットアップするために、現在のクラスターの外部とやりとりをする必要があります。

外部の状態とやりとりをするコントローラーは、目的の状態をAPIサーバーから取得した後、外部のシステムと直接通信し、現在の状態を目的の状態に近づけます。

(クラスター内のノードを水平にスケールさせるコントローラーが実際に存在します。)

ここで重要な点は、コントローラーが目的の状態を実現するために変更を加えてから、現在の状態をクラスターのAPIサーバーに報告することです。他の制御ループは、その報告されたデータを監視し、独自のアクションを実行できます。

サーモスタットの例では、部屋が非常に寒い場合、別のコントローラーが霜防止ヒーターをオンにすることもあります。Kubernetesクラスターを使用すると、コントロールプレーンは、Kubernetesを拡張して実装することにより、IPアドレス管理ツールやストレージサービス、クラウドプロバイダーAPI、およびその他のサービスと間接的に連携します。

目的の状態 vs 現在の状態

Kubernetesはシステムに対してクラウドネイティブな見方をするため、常に変化し続けるような状態を扱えるように設計されています。

処理を実行したり、制御ループが故障を自動的に修正したりしているどの時点でも、クラスターは変化中である可能性があります。つまり、クラスターは決して安定した状態にならない可能性があるということです。

コントローラーがクラスターのために実行されていて、有用な変更が行われるのであれば、全体的な状態が安定しているかどうかは問題にはなりません。

設計

設計理念として、Kubernetesは多数のコントローラーを使用しており、各コントローラーはクラスターの状態の特定の側面をそれぞれ管理しています。最もよくあるパターンは、特定の制御ループ(コントローラー)が目的の状態として1種類のリソースを使用し、目的の状態を実現することを管理するために別の種類のリソースを用意するというものです。たとえば、Jobのコントローラーは、Jobオブジェクト(新しい処理を見つけるため)およびPodオブジェクト(Jobを実行し、処理が完了したか確認するため)を監視します。この場合、なにか別のものがJobを作成し、JobコントローラーはPodを作成します。

相互にリンクされた単一のモノリシックな制御ループよりは、複数の単純なコントローラーが存在する方が役に立ちます。コントローラーは故障することがあるため、Kubernetesは故障を許容するように設計されています。

コントローラーを実行する方法

Kubernetesには、kube-controller-manager内部で動作する一組のビルトインのコントローラーが用意されています。これらビルトインのコントローラーは、コアとなる重要な振る舞いを提供します。

DeploymentコントローラーとJobコントローラーは、Kubernetes自体の一部として同梱されているコントローラーの例です(それゆえ「ビルトイン」のコントローラーと呼ばれます)。Kubernetesは回復性のあるコントロールプレーンを実行できるようにしているため、ビルトインのコントローラーの一部が故障しても、コントロールプレーンの別の部分が作業を引き継いでくれます。

Kubernetesを拡張するためにコントロールプレーンの外で動作するコントローラーもあります。もし望むなら、新しいコントローラーを自分で書くこともできます。自作のコントローラーをPodセットとして動作させたり、Kubernetesの外部で動作させることもできます。どのような動作方法が最も適しているかは、そのコントローラーがどのようなことを行うのかに依存します。

次の項目

3.2.4 - クラウドコントローラーマネージャー

FEATURE STATE: Kubernetes v1.11 [beta]

クラウドインフラストラクチャー技術により、パブリック、プライベート、ハイブリッドクラウド上でKubernetesを動かすことができます。Kubernetesは、コンポーネント間の密なつながりが不要な自動化されたAPI駆動インフラストラクチャーを信条としています。

cloud-controller-managerは クラウド特有の制御ロジックを組み込むKubernetesのcontrol planeコンポーネントです。クラウドコントロールマネージャーは、クラスターをクラウドプロバイダーAPIをリンクし、クラスタのみで相互作用するコンポーネントからクラウドプラットフォームで相互作用するコンポーネントを分離します。

Kubernetesと下のクラウドインフラストラクチャー間の相互運用ロジックを分離することで、cloud-controller-managerコンポーネントはクラウドプロバイダを主なKubernetesプロジェクトと比較し異なるペースで機能をリリース可能にします。

cloud-controller-managerは、プラグイン機構を用い、異なるクラウドプロバイダーに対してそれぞれのプラットフォームとKubernetesの結合を可能にする構成になっています。

設計

Kubernetesのコンポーネント

クラウドコントローラーマネージャーは、複製されたプロセスの集合としてコントロールプレーンで実行されます。(通常、Pod内のコンテナとなります)各cloud-controller-managerは、シングルプロセスで複数のcontrollersを実装します。

クラウドコントローラーマネージャーの機能

クラウドコントローラーマネージャーのコントローラーは以下を含んでいます。

ノードコントローラー

ノードコントローラーは、クラウドインフラストラクチャーで新しいサーバーが作成された際に、Nodeオブジェクトを作成する責務を持ちます。ノードコントローラーは、クラウドプロバイダーのテナント内で動作しているホストの情報を取得します。ノードコントローラーは下記に示す機能を実行します:

  1. Nodeオブジェクトを、コントローラーがクラウドプロバイダーAPIを通じて見つけた各サーバーで初期化する
  2. Nodeオブジェクトに、ノードがデプロイされているリージョンや利用可能なリソース(CPU、メモリなど)のようなクラウド特有な情報を注釈付けやラベル付けをする
  3. ノードのホスト名とネットワークアドレスを取得する
  4. ノードの正常性を検証する。ノードが応答しなくなった場合、クラウドプロバイダーのAPIを利用しサーバーがdeactivated / deleted / terminatedであるかを確認する。クラウドからノードが削除されていた場合、KubernetesクラスターからNodeオブジェクトを削除する

いくつかのクラウドプロバイダーは、これをノードコントローラーと個別のノードライフサイクルコントローラーに分けて実装しています。

ルートコントローラー

ルートコントローラーは、クラスタ内の異なるノード上で稼働しているコンテナが相互に通信できるように、クラウド内のルートを適切に設定する責務を持ちます。

クラウドプロバイダーによっては、ルートコントローラーはPodネットワークのIPアドレスのブロックを割り当てることもあります。

サービスコントローラー

Servicesは、マネージドロードバランサー、IPアドレスネットワークパケットフィルタや対象のヘルスチェックのようなクラウドインフラストラクチャーコンポーネントのインテグレーションを行います。サービスコントローラーは、ロードバランサーや他のインフラストラクチャーコンポーネントを必要とするServiceリソースを宣言する際にそれらのコンポーネントを設定するため、クラウドプロバイダーのAPIと対話します。

認可

このセクションでは、クラウドコントローラーマネージャーが操作を行うために様々なAPIオブジェクトに必要な権限を分類します。

ノードコントローラー

ノードコントローラーはNodeオブジェクトのみに対して働きます。Nodeオブジェクトに対して、readとmodifyの全権限が必要です。

v1/Node:

  • Get
  • List
  • Create
  • Update
  • Patch
  • Watch
  • Delete

ルートコントローラー

ルートコントローラーは、Nodeオブジェクトの作成を待ち受け、ルートを適切に設定します。Nodeオブジェクトについて、get権限が必要です。

v1/Node:

  • Get

サービスコントローラー

サービスコントローラーは、Serviceオブジェクトの作成、更新、削除イベントを待ち受け、その後、サービスのEndpointを適切に設定します。

サービスにアクセスするため、list、watchの権限が必要です。サービスを更新するため、patch、updateの権限が必要です。

サービスのEndpointリソースを設定するため、create、list、get、watchそしてupdateの権限が必要です。

v1/Service:

  • List
  • Get
  • Watch
  • Patch
  • Update

その他

クラウドコントローラーマネージャーのコア機能の実装は、Eventオブジェクトのcreate権限と、セキュアな処理を保証するため、ServiceAccountのcreate権限が必要です。

v1/Event:

  • Create
  • Patch
  • Update

v1/ServiceAccount:

  • Create

クラウドコントローラーマネージャーのRBAC ClusterRoleはこのようになります:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cloud-controller-manager
rules:
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - create
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - nodes
  verbs:
  - '*'
- apiGroups:
  - ""
  resources:
  - nodes/status
  verbs:
  - patch
- apiGroups:
  - ""
  resources:
  - services
  verbs:
  - list
  - patch
  - update
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - create
- apiGroups:
  - ""
  resources:
  - persistentvolumes
  verbs:
  - get
  - list
  - update
  - watch
- apiGroups:
  - ""
  resources:
  - endpoints
  verbs:
  - create
  - get
  - list
  - watch
  - update

次の項目

Cloud Controller Manager Administration はクラウドコントラーマネージャーの実行と管理を説明しています。

どのようにあなた自身のクラウドコントローラーマネージャーが実装されるのか、もしくは既存プロジェクトの拡張について知りたいですか?

クラウドコントローラーマネージャーは、いかなるクラウドからもプラグインとしての実装を許可するためにGoインターフェースを使います。具体的には、kubernetes/cloud-providercloud.goで定義されているCloudProviderを使います。

本ドキュメントでハイライトした共有コントローラー(Node、Route、Service)の実装と共有クラウドプロバイダーインターフェースに沿ったいくつかの足場は、Kubernetesコアの一部です。クラウドプロバイダに特化した実装は、Kubernetesのコアの外部として、またCloudProviderインターフェースを実装します。

プラグイン開発ついての詳細な情報は、Developing Cloud Controller Managerを見てください。

3.2.5 - ガベージコレクション

ガベージコレクションは、Kubernetesがクラスターリソースをクリーンアップするために使用するさまざまなメカニズムの総称です。これにより、次のようなリソースのクリーンアップが可能になります:

オーナーの依存関係

Kubernetesの多くのオブジェクトは、owner referenceを介して相互にリンクしています。 owner referenceは、どのオブジェクトが他のオブジェクトに依存しているかをコントロールプレーンに通知します。 Kubernetesは、owner referenceを使用して、コントロールプレーンやその他のAPIクライアントに、オブジェクトを削除する前に関連するリソースをクリーンアップする機会を提供します。 ほとんどの場合、Kubernetesはowner referenceを自動的に管理します。

Ownershipは、一部のリソースでも使用されるラベルおよびセレクターメカニズムとは異なります。 たとえば、EndpointSliceオブジェクトを作成するServiceを考えます。 Serviceはラベルを使用して、コントロールプレーンがServiceに使用されているEndpointSliceオブジェクトを判別できるようにします。 ラベルに加えて、Serviceに代わって管理される各EndpointSliceには、owner referenceがあります。 owner referenceは、Kubernetesのさまざまな部分が制御していないオブジェクトへの干渉を回避するのに役立ちます。

カスケード削除

Kubernetesは、ReplicaSetを削除したときに残されたPodなど、owner referenceがなくなったオブジェクトをチェックして削除します。 オブジェクトを削除する場合、カスケード削除と呼ばれるプロセスで、Kubernetesがオブジェクトの依存関係を自動的に削除するかどうかを制御できます。 カスケード削除には、次の2つのタイプがあります。

  • フォアグラウンドカスケード削除
  • バックグラウンドカスケード削除

また、Kubernetes finalizerを使用して、ガベージコレクションがowner referenceを持つリソースを削除する方法とタイミングを制御することもできます。

フォアグラウンドカスケード削除

フォアグラウンドカスケード削除では、削除するオーナーオブジェクトは最初に削除進行中の状態になります。 この状態では、オーナーオブジェクトに次のことが起こります。

  • Kubernetes APIサーバーは、オブジェクトのmetadata.deletionTimestampフィールドを、オブジェクトに削除のマークが付けられた時刻に設定します。
  • Kubernetes APIサーバーは、metadata.finalizersフィールドをforegroundDeletionに設定します。
  • オブジェクトは、削除プロセスが完了するまで、KubernetesAPIを介して表示されたままになります。

オーナーオブジェクトが削除進行中の状態に入ると、コントローラーは依存関係を削除します。 すべての依存関係オブジェクトを削除した後、コントローラーはオーナーオブジェクトを削除します。 この時点で、オブジェクトはKubernetesAPIに表示されなくなります。

フォアグラウンドカスケード削除中に、オーナーの削除をブロックする依存関係は、ownerReference.blockOwnerDeletion=trueフィールドを持つ依存関係のみです。 詳細については、フォアグラウンドカスケード削除の使用を参照してください。

バックグラウンドカスケード削除

バックグラウンドカスケード削除では、Kubernetes APIサーバーがオーナーオブジェクトをすぐに削除し、コントローラーがバックグラウンドで依存オブジェクトをクリーンアップします。 デフォルトでは、フォアグラウンド削除を手動で使用するか、依存オブジェクトを孤立させることを選択しない限り、Kubernetesはバックグラウンドカスケード削除を使用します。

詳細については、バックグラウンドカスケード削除の使用を参照してください。

孤立した依存関係

Kubernetesがオーナーオブジェクトを削除すると、残された依存関係はorphanオブジェクトと呼ばれます。 デフォルトでは、Kubernetesは依存関係オブジェクトを削除します。この動作をオーバーライドする方法については、オーナーオブジェクトと孤立した依存関係の削除を参照してください。

未使用のコンテナとイメージのガベージコレクション

kubeletは未使用のイメージに対して5分ごとに、未使用のコンテナーに対して1分ごとにガベージコレクションを実行します。 外部のガベージコレクションツールは、kubeletの動作を壊し、存在するはずのコンテナを削除する可能性があるため、使用しないでください。

未使用のコンテナーとイメージのガベージコレクションのオプションを設定するには、設定ファイルを使用してkubeletを調整し、KubeletConfigurationリソースタイプを使用してガベージコレクションに関連するパラメーターを変更します。

コンテナイメージのライフサイクル

Kubernetesは、kubeletの一部であるイメージマネージャーを通じて、cadvisorの協力を得て、すべてのイメージのライフサイクルを管理します。kubeletは、ガベージコレクションを決定する際に、次のディスク使用制限を考慮します。

  • HighThresholdPercent
  • LowThresholdPercent

設定されたHighThresholdPercent値を超えるディスク使用量はガベージコレクションをトリガーします。 ガベージコレクションは、最後に使用された時間に基づいて、最も古いものから順にイメージを削除します。 kubeletは、ディスク使用量がLowThresholdPercent値に達するまでイメージを削除します。

コンテナイメージのガベージコレクション

kubeletは、次の変数に基づいて未使用のコンテナをガベージコレクションします。

  • MinAge: kubeletがガベージコレクションできるコンテナの最低期間。0を設定すると無効化されます。
  • MaxPerPodContainer: 各Podのペアが持つことができるデッドコンテナの最大数。0未満に設定すると無効化されます。
  • MaxContainers: クラスターが持つことができるデッドコンテナーの最大数。0未満に設定すると無効化されます。

これらの変数に加えて、kubeletは、通常、最も古いものから順に、定義されていない削除されたコンテナをガベージコレクションします。

MaxPerPodContainerMaxContainerは、Podごとのコンテナーの最大数(MaxPerPodContainer)を保持すると、グローバルなデッドコンテナの許容合計(MaxContainers)を超える状況で、互いに競合する可能性があります。 この状況では、kubeletはMaxPodPerContainerを調整して競合に対処します。最悪のシナリオは、MaxPerPodContainerを1にダウングレードし、最も古いコンテナーを削除することです。 さらに、削除されたPodが所有するコンテナは、MinAgeより古くなると削除されます。

ガベージコレクションの設定

これらのリソースを管理するコントローラーに固有のオプションを設定することにより、リソースのガベージコレクションを調整できます。次のページは、ガベージコレクションを設定する方法を示しています。

次の項目

3.2.6 - コンテナランタイムインターフェイス(CRI)

CRIは、クラスターコンポーネントを再コンパイルすることなく、kubeletがさまざまなコンテナランタイムを使用できるようにするプラグインインターフェイスです。

kubeletPodとそのコンテナを起動できるように、クラスター内の各ノードで動作するcontainer runtimeが必要です。

kubeletとContainerRuntime間の通信のメインプロトコルです。

Kubernetes Container Runtime Interface(CRI)は、クラスターコンポーネントkubeletcontainer runtime間の通信用のメインgRPCプロトコルを定義します。

API

FEATURE STATE: Kubernetes v1.23 [stable]

kubeletは、gRPCを介してコンテナランタイムに接続するときにクライアントとして機能します。ランタイムおよびイメージサービスエンドポイントは、コンテナランタイムで使用可能である必要があります。コンテナランタイムは、--image-service-endpointおよび--container-runtime-endpointコマンドラインフラグを使用して、kubelet内で個別に設定できます。

Kubernetes v1.24の場合、kubeletはCRI v1の使用を優先します。 コンテナランタイムがCRIのv1をサポートしていない場合、kubeletはサポートされている古いバージョンのネゴシエーションを試みます。 kubelet v1.24はCRI v1alpha2をネゴシエートすることもできますが、このバージョンは非推奨と見なされます。 kubeletがサポートされているCRIバージョンをネゴシエートできない場合、kubeletはあきらめて、ノードとして登録されません。

アップグレード

Kubernetesをアップグレードする場合、kubeletはコンポーネントの再起動時に最新のCRIバージョンを自動的に選択しようとします。 それが失敗した場合、フォールバックは上記のように行われます。 コンテナランタイムがアップグレードされたためにgRPCリダイヤルが必要な場合は、コンテナランタイムも最初に選択されたバージョンをサポートする必要があります。 そうでない場合、リダイヤルは失敗することが予想されます。これには、kubeletの再起動が必要です。

次の項目

3.3 - コンテナ

アプリケーションとランタイムの依存関係を一緒にパッケージ化するための技術

実行するそれぞれのコンテナは繰り返し使用可能です。依存関係を含めて標準化されており、どこで実行しても同じ動作が得られることを意味しています。

コンテナは基盤となるホストインフラからアプリケーションを切り離します。これにより、さまざまなクラウドやOS環境下でのデプロイが容易になります。

コンテナイメージ

コンテナイメージはすぐに実行可能なソフトウェアパッケージで、アプリケーションの実行に必要なものをすべて含んています。コードと必要なランタイム、アプリケーションとシステムのライブラリ、そして必須な設定項目のデフォルト値を含みます。

設計上、コンテナは不変で、既に実行中のコンテナのコードを変更することはできません。コンテナ化されたアプリケーションがあり変更したい場合は、変更を含んだ新しいイメージをビルドし、コンテナを再作成して、更新されたイメージから起動する必要があります。

コンテナランタイム

コンテナランタイムは、コンテナの実行を担当するソフトウェアです。

Kubernetesは次の複数のコンテナランタイムをサポートします。 DockercontainerdCRI-O、 および全ての Kubernetes CRI (Container Runtime Interface) 実装です。

次の項目

3.3.1 - コンテナの概要

コンテナは、アプリケーションの(コンパイルされた)コードと、実行時に必要な依存関係をパッケージ化するための技術です。実行する各コンテナは再現性があります。依存関係を含めることによる標準化は、どこで実行しても同じ動作が得られることを意味します。

コンテナは、基礎となるホストインフラストラクチャからアプリケーションを切り離します。これにより、さまざまなクラウド環境やOS環境でのデプロイが容易になります。

コンテナイメージ

コンテナイメージは、アプリケーションを実行するために必要なすべてのものを含んだ、すぐに実行可能なソフトウェアパッケージです。コードとそれが必要とする任意のランタイム、アプリケーションとシステムのライブラリ、および必須の設定のデフォルト値が含まれています。

設計上、コンテナは不変であるため、すでに実行中のコンテナのコードを変更することはできません。コンテナ化されたアプリケーションがあり、変更を加えたい場合は、変更を含む新しいコンテナをビルドし、コンテナを再作成して更新されたイメージから起動する必要があります。

コンテナランタイム

コンテナランタイムは、コンテナの実行を担当するソフトウェアです。

Kubernetesは次の複数のコンテナランタイムをサポートします。 DockercontainerdCRI-O、 および全ての Kubernetes CRI (Container Runtime Interface) 実装です。

次の項目

3.3.2 - イメージ

コンテナイメージはアプリケーションと依存関係のあるすべてソフトウェアをカプセル化したバイナリデータを表します。コンテナイメージはスタンドアロンで実行可能なソフトウェアをひとつにまとめ、ランタイム環境に関する想定を明確に定義しています。

アプリケーションのコンテナイメージを作成し、一般的にはPodで参照する前にレジストリへPushします。

このページではコンテナイメージの概要を説明します。

イメージの名称

コンテナイメージは、pauseexample/mycontainer、またはkube-apiserverのような名前が通常つけられます。 イメージにはレジストリのホスト名も含めることができ(例:fictional.registry.example/imagename)、さらにポート番号も含めることが可能です(例:fictional.registry.example:10443/imagename)。

レジストリのホスト名を指定しない場合は、KubernetesはDockerパブリックレジストリを意味していると見なします。

イメージ名の後に、タグ を追加することができます(dockerpodmanのようなコマンドを利用した場合と同様)。 タグによって同じイメージの異なるバージョンを識別できます。

イメージタグは大文字と小文字、数値、アンダースコア(_)、ピリオド(.)とマイナス(-)で構成されます。 イメージタグでは区切り記号(_-.)を指定できる追加ルールがあります。 タグを指定しない場合は、Kubernetesはlatestタグを指定したと見なします。

イメージの更新

デフォルトのpull policyでは、kubeletはイメージを既に取得済みの場合、イメージのPullをスキップさせるIfNotPresentが設定されています。 常にPullを強制させたい場合は、次のいずれかの方法で実行できます。

  • コンテナのimagePullPolicyAlwaysを設定する
  • imagePullPolicyを省略し、使用するイメージに:latestタグを使用する
  • imagePullPolicyと使用するイメージのタグを省略する
  • AlwaysPullImagesアドミッションコントローラーを有効にする

imagePullPolicyが値なしで定義された場合、この場合もAlwaysが設定されます。

イメージインデックスを使ったマルチアーキテクチャイメージ

コンテナレジストリはバイナリイメージの提供だけでなく、コンテナイメージインデックスも提供する事ができます。イメージインデックスはコンテナのアーキテクチャ固有バージョンに関する複数のイメージマニフェストを指すことができます。イメージインデックスの目的はイメージの名前(例:pauseexample/mycontainerkube-apiserver)をもたせ、様々なシステムが使用しているマシンアーキテクチャにあう適切なバイナリイメージを取得できることです。

Kubernetes自身は、通常コンテナイメージに-$(ARCH)のサフィックスを持つ名前をつけます。下位互換の為にサフィックス付きの古い仕様のイメージを生成してください。その目的は、pauseのようなすべてのアーキテクチャのマニフェストを持つイメージと、サフィックスのあるイメージをハードコードしていた可能性のある古い仕様の設定やYAMLファイルと下位互換があるpause-amd64のようなイメージを生成することです。

プライベートレジストリを使用する方法

プライベートレジストリではイメージを読み込む為にキーが必要になる場合があります。
認証情報はいくつかの方法で提供できます。

  • プライベートレジストリへの認証をNodeに設定する
    • すべてのPodがプライベートレジストリを読み取ることができる
    • クラスター管理者によるNodeの設定が必要
  • 事前にPullされたイメージ
    • すべてのPodがNode上にキャッシュされたイメージを利用できる
    • セットアップするためにはすべてのNodeに対するrootアクセスが必要
  • PodでImagePullSecretsを指定する
    • キーを提供したPodのみがプライベートレジストリへアクセスできる
  • ベンダー固有またはローカルエクステンション
    • カスタムNode構成を使っている場合、あなた(または、あなたのクラウドプロバイダー)はコンテナレジストリへの認証の仕組みを組み込むことができる

これらのオプションについて、以下で詳しく説明します。

プライベートレジストリへの認証をNodeに設定する

Node上でDockerを実行している場合、プライベートコンテナレジストリへの認証をDockerコンテナランタイムに設定できます。

Node構成を制御できる場合は、この方法が適しています。

Dockerは、$HOME/.dockercfgまたは$HOME/.docker/config.jsonファイルの中に、プライベートレジストリのキーを保持します。 下記リストの検索パスに同じファイルを配置した場合、kubeletはイメージをPullする時に認証情報プロバイダーとして利用します。

  • {--root-dir:-/var/lib/kubelet}/config.json
  • {cwd of kubelet}/config.json
  • ${HOME}/.docker/config.json
  • /.docker/config.json
  • {--root-dir:-/var/lib/kubelet}/.dockercfg
  • {cwd of kubelet}/.dockercfg
  • ${HOME}/.dockercfg
  • /.dockercfg

以下は、プライベートレジストリを使用する為にNodeを構成する推奨の手順です。この例では、デスクトップ/ノートPC上で実行します。

  1. 使用したい認証情報のセット毎に docker login [server]を実行する。これであなたのPC上の$HOME/.docker/config.jsonが更新される
  2. 使用したい認証情報が含まれているかを確認するため、エディターで$HOME/.docker/config.jsonを見る
  3. Nodeの一覧を取得 例:
    • 名称が必要な場合: nodes=$( kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}' )
    • IPアドレスを取得したい場合: nodes=$( kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}' )
  4. ローカルの.docker/config.jsonを上記の検索パスのいずれかにコピーする
    • 例えば、これでテストを実施する: for n in $nodes; do scp ~/.docker/config.json root@"$n":/var/lib/kubelet/config.json; done

プライベートイメージを使用するPodを作成し確認します。 例:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: private-image-test-1
spec:
  containers:
    - name: uses-private-image
      image: $PRIVATE_IMAGE_NAME
      imagePullPolicy: Always
      command: [ "echo", "SUCCESS" ]
EOF
pod/private-image-test-1 created

すべてが機能している場合は、しばらくしてから以下のコマンドを実行します。

kubectl logs private-image-test-1

コマンドの結果を確認してください。

SUCCESS

コマンドが失敗したと思われる場合には、以下を実行します。

kubectl describe pods/private-image-test-1 | grep 'Failed'

失敗している場合、結果が次のようになります。

  Fri, 26 Jun 2015 15:36:13 -0700    Fri, 26 Jun 2015 15:39:13 -0700    19    {kubelet node-i2hq}    spec.containers{uses-private-image}    failed        Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found

クラスターのすべてのNodeが同じ.docker/config.jsonになっているかを確認する必要があります。 そうでない場合、Podは一部のNodeで実行できますが他のNodeでは実行に失敗します。 例えば、Nodeのオートスケールを使用している場合、各インスタンスのテンプレートに.docker/config.jsonが含まれている、またはこのファイルが含まれているドライブをマウントする必要があります。

プライベートレジストリキーを.docker/config.jsonに追加した時点で、すべてのPodがプライベートレジストリのイメージに読み取りアクセス権も持つようになります。

事前にPullしたイメージ

デフォルトでは、kubeletは指定されたレジストリからそれぞれのイメージをPullしようとします。 また一方では、コンテナのimagePullPolicyプロパティにIfNotPresentNeverが設定されている場合、ローカルのイメージが使用されます。(それぞれに対して、優先的またはか排他的に)

レジストリ認証の代替として事前にPullしたイメージを利用したい場合、クラスターのすべてのNodeが同じ事前にPullしたイメージを持っていることを確認する必要があります。

特定のイメージをあらかじめロードしておくことは高速化やプライベートレジストリへの認証の代替として利用することができます。

すべてのPodは事前にPullしたイメージへの読み取りアクセス権をもちます。

PodでimagePullSecretsを指定する

KubernetesはPodでのコンテナイメージレジストリキーの指定をサポートしています。

Dockerの設定を利用してSecretを作成する。

適切な大文字の値を置き換えて、次のコマンドを実行します。

kubectl create secret docker-registry <name> --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

既にDocker認証情報ファイルを持っている場合は、上記のコマンドの代わりに、認証情報ファイルをKubernetes Secretsとしてインポートすることができます。 既存のDocker認証情報に基づいてSecretを作成する で、この設定方法を説明します.

これは複数のプライベートコンテナレジストリを使用している場合に特に有効です。kubectl create secret docker-registryはひとつのプライベートレジストリにのみ機能するSecretを作成するからです。

PodのimagePullSecretsを参照する方法

これで、imagePullSecretsセクションをPod定義へ追加することでSecretを参照するPodを作成できます。

例:

cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: awesomeapps
spec:
  containers:
    - name: foo
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey
EOF

cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF

これは、プライベートレジストリを使用する各Podで行う必要があります。

ただし、この項目の設定はServiceAccountリソースの中でimagePullSecretsを指定することで自動化することができます。

詳細の手順は、ImagePullSecretsをService Accountに追加するをクリックしてください。

これを各Nodeの.docker/config.jsonに組み合わせて利用できます。認証情報はマージされます。

ユースケース

プライベートレジストリを設定するためのソリューションはいくつかあります。ここでは、いくつかの一般的なユースケースと推奨される解決方法を示します。

  1. クラスターに独自仕様でない(例えば、オープンソース)イメージだけを実行する。イメージを非公開にする必要がない
    • Docker hubのパブリックイメージを利用する
      • 設定は必要ない
      • クラウドプロバイダーによっては、可用性の向上とイメージをPullする時間を短くする為に、自動的にキャッシュやミラーされたパプリックイメージが提供される
  2. 社外には非公開の必要があるが、すべてのクラスター利用者には見せてよい独自仕様のイメージをクラスターで実行している
    • ホストされたプライペートな Dockerレジストリを使用
      • Docker Hubまたは他の場所の上でホストされている場合がある
      • 上記のように各Node上のdocker/config.jsonを手動で構成する
    • または、オープンな読み取りアクセスを許可したファイヤーウォールの背後で内部向けプライベートレジストリを実行する
      • Kubernetesの設定は必要ない
    • イメージへのアクセスを制御できるホストされたコンテナイメージレジストリサービスを利用する
      • Nodeを手動設定するよりもクラスターのオートスケーリングのほうがうまく機能する
    • また、Node設定変更を自由にできないクラスターではimagePullSecretsを使用する
  3. 独自仕様のイメージを含むクラスターで、いくつかは厳格なアクセス制御が必要である
    • AlwaysPullImagesアドミッションコントローラーが有効化かを確認する必要がある。さもないと、全部のPodがすべてのイメージへのアクセスができてしまう可能性がある
    • 機密データはイメージに含めてしまうのではなく、"Secret"リソースに移行する
  4. それぞれのテナントが独自のプライベートレジストリを必要とするマルチテナントのクラスターである
    • AlwaysPullImagesアドミッションコントローラーが有効化を確認する必要がある。さもないと、すべてのテナントの全Podが全部のイメージにアクセスできてしまう可能性がある
    • 認証が必要なプライベートレジストリを実行する
    • それぞれのテナントでレジストリ認証を生成し、Secretへ設定し、各テナントのNamespaceに追加する
    • テナントは、Secretを各NamespaceのimagePullSecretsへ追加する

複数のレジストリへのアクセスが必要な場合、それぞれのレジストリ毎にひとつのSecretを作成する事ができます。 Kubeletは複数のimagePullSecretsを単一の仮想的な.docker/config.jsonにマージします。

次の項目

3.3.3 - コンテナ環境

このページでは、コンテナ環境で利用可能なリソースについて説明します。

コンテナ環境

Kubernetesはコンテナにいくつかの重要なリソースを提供します。

  • イメージと1つ以上のボリュームの組み合わせのファイルシステム
  • コンテナ自体に関する情報
  • クラスター内の他のオブジェクトに関する情報

コンテナ情報

コンテナの ホスト名 は、コンテナが実行されているPodの名前です。 ホスト名はhostnameコマンドまたはlibcのgethostname関数呼び出しにより利用可能です。

Podの名前と名前空間はdownward APIを通じて環境変数として利用可能です。

Pod定義からのユーザー定義の環境変数もコンテナで利用できます。 Dockerイメージで静的に指定されている環境変数も同様です。

クラスター情報

コンテナの作成時に実行されていたすべてのサービスのリストは、環境変数として使用できます。 これらの環境変数はDockerリンクの構文と一致します。

bar という名前のコンテナに対応する foo という名前のサービスの場合、以下の変数が定義されています。

FOO_SERVICE_HOST=<サービスが実行されているホスト>
FOO_SERVICE_PORT=<サービスが実行されているポート>

サービスは専用のIPアドレスを持ち、DNSアドオンが有効の場合、DNSを介してコンテナで利用可能です。

次の項目

3.3.4 - ランタイムクラス(Runtime Class)

FEATURE STATE: Kubernetes v1.14 [beta]

このページではRuntimeClassリソースと、runtimeセクションのメカニズムについて説明します。

RuntimeClassはコンテナランタイムの設定を選択するための機能です。そのコンテナランタイム設定はPodのコンテナを稼働させるために使われます。

RuntimeClassを使う動機

異なるPodに異なるRuntimeClassを設定することで、パフォーマンスとセキュリティのバランスをとることができます。例えば、ワークロードの一部に高レベルの情報セキュリティ保証が必要な場合、ハードウェア仮想化を使用するコンテナランタイムで実行されるようにそれらのPodをスケジュールすることを選択できます。その後、追加のオーバーヘッドを犠牲にして、代替ランタイムをさらに分離することでメリットが得られます。

RuntimeClassを使用して、コンテナランタイムは同じで設定が異なるPodを実行することもできます。

セットアップ

RuntimeClass機能のフィーチャーゲートが有効になっていることを確認してください(デフォルトで有効です)。フィーチャーゲートを有効にする方法については、フィーチャーゲートを参照してください。 そのRuntimeClassのフィーチャーゲートはApiServerとkubeletのどちらも有効になっていなければなりません。

  1. ノード上でCRI実装を設定する。(ランタイムに依存)
  2. 対応するRuntimeClassリソースを作成する。

1. ノード上でCRI実装を設定する

RuntimeClassを通じて利用可能な設定はContainer Runtime Interface (CRI)の実装依存となります。 ユーザーの環境のCRI実装の設定方法は、対応するドキュメント(下記)を参照ください。

RuntimeClassの設定は、RuntimeClassによって参照されるハンドラー名を持ちます。そのハンドラーは正式なDNS-1123に準拠する形式のラベルでなくてはなりません(英数字 + -の文字で構成されます)。

2. 対応するRuntimeClassリソースを作成する

ステップ1にて設定する各項目は、関連するハンドラー 名を持ちます。それはどの設定かを指定するものです。各ハンドラーにおいて、対応するRuntimeClassオブジェクトが作成されます。

そのRuntimeClassリソースは現時点で2つの重要なフィールドを持ちます。それはRuntimeClassの名前(metadata.name)とハンドラー(handler)です。そのオブジェクトの定義は下記のようになります。

apiVersion: node.k8s.io/v1beta1  # RuntimeClassはnode.k8s.ioというAPIグループで定義されます。
kind: RuntimeClass
metadata:
  name: myclass  # RuntimeClass名
  # RuntimeClassはネームスペースなしのリソースです。
handler: myconfiguration  # 対応するCRI設定

RuntimeClassオブジェクトの名前はDNSサブドメイン名に従う必要があります。

使用例

一度RuntimeClassがクラスターに対して設定されると、それを使用するのは非常に簡単です。PodSpecのruntimeClassNameを指定してください。
例えば

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  runtimeClassName: myclass
  # ...

これは、Kubeletに対してPodを稼働させるためのRuntimeClassを使うように指示します。もし設定されたRuntimeClassが存在しない場合や、CRIが対応するハンドラーを実行できない場合、そのPodはFailedというフェーズになります。 エラーメッセージに関しては対応するイベントを参照して下さい。

もしruntimeClassNameが指定されていない場合、デフォルトのRuntimeHandlerが使用され、これはRuntimeClassの機能が無効であるときのふるまいと同じものとなります。

CRIの設定

CRIランタイムのセットアップに関するさらなる詳細は、CRIのインストールを参照してください。

dockershim

Kubernetesのビルトインのdockershim CRIは、ランタイムハンドラーをサポートしていません。

containerd

ランタイムハンドラーは、/etc/containerd/config.tomlにあるcontainerdの設定ファイルにより設定されます。 正しいハンドラーは、そのruntimeセクションで設定されます。

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${HANDLER_NAME}]

containerdの設定に関する詳細なドキュメントは下記を参照してください。
https://github.com/containerd/cri/blob/master/docs/config.md

CRI-O

ランタイムハンドラーは、/etc/crio/crio.confにあるCRI-Oの設定ファイルにより設定されます。 正しいハンドラーはcrio.runtime tableで設定されます。

[crio.runtime.runtimes.${HANDLER_NAME}]
  runtime_path = "${PATH_TO_BINARY}"

詳細はCRI-Oの設定に関するドキュメントを参照してください。

スケジューリング

FEATURE STATE: Kubernetes v1.16 [beta]

Kubernetes 1.16では、RuntimeClassはschedulingフィールドを使ったクラスター内での異なる設定をサポートしています。 このフィールドによって、設定されたRuntimeClassをサポートするノードに対してPodがスケジュールされることを保証できます。 スケジューリングをサポートするためにはRuntimeClass アドミッションコントローラーを有効にしなければなりません。(1.16ではデフォルトです)

特定のRuntimeClassをサポートしているノードへPodが配置されることを保証するために、各ノードはruntimeclass.scheduling.nodeSelectorフィールドによって選択される共通のラベルを持つべきです。 RuntimeClassのnodeSelectorはアドミッション機能によりPodのnodeSelectorに統合され、効率よくノードを選択します。 もし設定が衝突した場合は、Pod作成は拒否されるでしょう。

もしサポートされているノードが他のRuntimeClassのPodが稼働しないようにtaint付与されていた場合、RuntimeClassに対してtolerationsを付与することができます。 nodeSelectorと同様に、tolerationsはPodのtolerationsにアドミッション機能によって統合され、効率よく許容されたノードを選択します。

ノードの選択とtolerationsについての詳細はノード上へのPodのスケジューリングを参照してください。

Podオーバーヘッド

FEATURE STATE: Kubernetes v1.18 [beta]

Podが稼働する時に関連する オーバーヘッド リソースを指定できます。オーバーヘッドを宣言すると、クラスター(スケジューラーを含む)がPodとリソースに関する決定を行うときにオーバーヘッドを考慮することができます。 Podオーバーヘッドを使うためには、PodOverheadフィーチャーゲートを有効にしなければなりません。(デフォルトではonです)

PodのオーバーヘッドはRuntimeClass内のoverheadフィールドによって定義されます。 このフィールドを使用することで、RuntimeClassを使用して稼働するPodのオーバーヘッドを指定することができ、Kubernetes内部で使用されるオーバーヘッドを確保することができます。

次の項目

3.3.5 - コンテナライフサイクルフック

このページでは、kubeletにより管理されるコンテナがコンテナライフサイクルフックフレームワークを使用して、管理ライフサイクル中にイベントによって引き起こされたコードを実行する方法について説明します。

概要

Angularなどのコンポーネントライフサイクルフックを持つ多くのプログラミング言語フレームワークと同様に、Kubernetesはコンテナにライフサイクルフックを提供します。 フックにより、コンテナは管理ライフサイクル内のイベントを認識し、対応するライフサイクルフックが実行されたときにハンドラーに実装されたコードを実行できます。

コンテナフック

コンテナに公開されている2つのフックがあります。

PostStart

このフックはコンテナが作成された直後に実行されます。 しかし、フックがコンテナのENTRYPOINTの前に実行されるという保証はありません。 ハンドラーにパラメーターは渡されません。

PreStop

このフックは、APIからの要求、またはliveness probeの失敗、プリエンプション、リソース競合などの管理イベントが原因でコンテナが終了する直前に呼び出されます。コンテナがすでに終了状態または完了状態にある場合、preStopフックの呼び出しは失敗します。 これはブロッキング、つまり同期的であるため、コンテナを停止する信号が送信される前に完了する必要があります。 ハンドラーにパラメーターは渡されません。

終了動作の詳細な説明は、Termination of Podsにあります。

フックハンドラーの実装

コンテナは、フックのハンドラーを実装して登録することでそのフックにアクセスできます。 コンテナに実装できるフックハンドラーは2種類あります。

  • Exec - コンテナのcgroupsと名前空間の中で、 pre-stop.shのような特定のコマンドを実行します。 コマンドによって消費されたリソースはコンテナに対してカウントされます。
  • HTTP - コンテナ上の特定のエンドポイントに対してHTTP要求を実行します。

フックハンドラーの実行

コンテナライフサイクル管理フックが呼び出されると、Kubernetes管理システムはフックアクションにしたがってハンドラーを実行します。 exectcpSocketはコンテナの中で実行され、httpGetはkubeletプロセスによって実行されます。

フックハンドラーの呼び出しは、コンテナを含むPodのコンテキスト内で同期しています。 これは、PostStartフックの場合、コンテナのENTRYPOINTとフックは非同期に起動することを意味します。 しかし、フックの実行に時間がかかりすぎたりハングしたりすると、コンテナはrunning状態になることができません。

PreStopフックはコンテナを停止する信号から非同期で実行されるのではなく、信号が送られる前に実行を完了する必要があります。 もしPreStopフックが実行中にハングした場合、PodはTerminating状態になり、 terminationGracePeriodSecondsの時間切れで強制終了されるまで続きます。 この猶予時間は、PreStopフックが実行され正常にコンテナを停止できるまでの合計時間に適用されます。 例えばterminationGracePeriodSecondsが60で、フックの終了に55秒かかり、シグナルを受信した後にコンテナを正常に停止させるのに10秒かかる場合、コンテナは正常に停止する前に終了されてしまいます。terminationGracePeriodSecondsが、これら2つの実行にかかる合計時間(55+10)よりも短いからです。

PostStartまたはPreStopフックが失敗した場合、コンテナは強制終了します。

ユーザーはフックハンドラーをできるだけ軽量にするべきです。 ただし、コンテナを停止する前に状態を保存するなどの場合は、長時間のコマンド実行が必要なケースもあります。

フック配信保証

フックの配信は 少なくとも1回 を意図しています。これはフックがPostStartPreStopのような任意のイベントに対して複数回呼ばれることがあることを意味します。 これを正しく処理するのはフックの実装次第です。

通常、1回の配信のみが行われます。 たとえば、HTTPフックレシーバーがダウンしていてトラフィックを受け取れない場合、再送信は試みられません。 ただし、まれに二重配信が発生することがあります。 たとえば、フックの送信中にkubeletが再起動した場合、kubeletが起動した後にフックが再送信される可能性があります。

フックハンドラーのデバッグ

フックハンドラーのログは、Podのイベントには表示されません。 ハンドラーが何らかの理由で失敗した場合は、イベントをブロードキャストします。 PostStartの場合、これはFailedPostStartHookイベントで、PreStopの場合、これはFailedPreStopHookイベントです。 これらのイベントは kubectl describe pod <pod_name>を実行することで見ることができます。 このコマンドの実行によるイベントの出力例をいくつか示します。

Events:
  FirstSeen  LastSeen  Count  From                                                   SubObjectPath          Type      Reason               Message
  ---------  --------  -----  ----                                                   -------------          --------  ------               -------
  1m         1m        1      {default-scheduler }                                                          Normal    Scheduled            Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
  1m         1m        1      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}  spec.containers{main}  Normal    Pulling              pulling image "test:1.0"
  1m         1m        1      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}  spec.containers{main}  Normal    Created              Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
  1m         1m        1      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}  spec.containers{main}  Normal    Pulled               Successfully pulled image "test:1.0"
  1m         1m        1      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}  spec.containers{main}  Normal    Started              Started container with docker id 5c6a256a2567
  38s        38s       1      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}  spec.containers{main}  Normal    Killing              Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
  37s        37s       1      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}  spec.containers{main}  Normal    Killing              Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
  38s        37s       2      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}                         Warning   FailedSync           Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
  1m         22s       2      {kubelet gke-test-cluster-default-pool-a07e5d30-siqd}  spec.containers{main}  Warning   FailedPostStartHook

次の項目

3.4 - ワークロード

Kubernetesにおけるデプロイ可能な最小のオブジェクトであるPodと、高レベルな抽象化がPodの実行を助けることを理解します。

ワークロードとは、Kubernetes上で実行中のアプリケーションです。 ワークロードが1つのコンポーネントからなる場合でも、複数のコンポーネントが協調して動作する場合でも、KubernetesではそれらはPodの集合として実行されます。Kubernetesでは、Podはクラスター上で実行中のコンテナの集合として表されます。

Podには定義されたライフサイクルがあります。たとえば、一度Podがクラスター上で実行中になると、そのPodが実行中のノード上で深刻な障害が起こったとき、そのノード上のすべてのPodは停止してしまうことになります。Kubernetesではそのようなレベルの障害を最終的なものとして扱うため、たとえノードが後で復元したとしても、ユーザーは新しいPodを作成し直す必要があります。

しかし、生活をかなり楽にするためには、それぞれのPodを直接管理する必要はありません。ワークロードリソース を利用すれば、あなたの代わりにPodの集合の管理を行ってもらえます。これらのリソースはあなたが指定した状態に一致するようにコントローラーを設定し、正しい種類のPodが正しい数だけ実行中になることを保証してくれます。

ワークロードリソースには、次のような種類があります。

  • DeploymentReplicaSet(レガシーなリソースReplicationControllerを置き換えるものです)
  • StatefulSet
  • DaemonSet(ストレージドライバやネットワークプラグインなど、ノードローカルな機能を提供するためのPodを実行するために使われます)
  • JobCronJob(実行後に完了するようなタスクのために使われます)

多少関連のある2種類の補助的な概念もあります。

次の項目

各リソースについて読む以外にも、以下のページでそれぞれのワークロードに関連する特定のタスクについて学ぶことができます。

アプリケーションが実行できるようになったら、インターネット上で公開したくなるかもしれません。その場合には、Serviceとして公開したり、ウェブアプリケーションだけの場合、Ingressを使用することができます。

コードを設定から分離するKubernetesのしくみについて学ぶには、設定を読んでください。

3.4.1 - Pod

Podは、Kubernetes内で作成・管理できるコンピューティングの最小のデプロイ可能なユニットです(Podという名前は、たとえばクジラの群れ(pod of whales)やえんどう豆のさや(pea pod)などの表現と同じような意味です)。

Podは、1つまたは複数のコンテナのグループであり、ストレージやネットワークの共有リソースを持ち、コンテナの実行方法に関する仕様を持っています。同じPodに含まれるリソースは、常に同じ場所で同時にスケジューリングされ、共有されたコンテキストの中で実行されます。Podはアプリケーションに特化した「論理的なホスト」をモデル化します。つまり、1つのPod内には、1つまたは複数の比較的密に結合されたアプリケーションコンテナが含まれます。クラウド外の文脈で説明すると、アプリケーションが同じ物理ホストや同じバーチャルマシンで実行されることが、クラウドアプリケーションの場合には同じ論理ホスト上で実行されることに相当します。

アプリケーションコンテナと同様に、Podでも、Podのスタートアップ時に実行されるinitコンテナを含めることができます。また、クラスターで利用できる場合には、エフェメラルコンテナを注入してデバッグすることもできます。

Podとは何か?

Podの共有コンテキストは、Dockerコンテナを隔離するのに使われているのと同じ、Linuxのnamespaces、cgroups、場合によっては他の隔離技術の集合を用いて作られます。Podのコンテキスト内では、各アプリケーションが追加の準隔離技術を適用することもあります。

Dockerの概念を使って説明すると、Podは共有の名前空間と共有ファイルシステムのボリュームを持つDockerコンテナのグループに似ています。

Podを使用する

通常、たとえ単一のコンテナしか持たないシングルトンのPodだとしても、自分でPodを直接作成する必要はありません。その代わりに、DeploymentJobなどのワークロードリソースを使用してPodを作成します。もしPodが状態を保持する必要がある場合は、StatefulSetリソースを使用することを検討してください。

Kubernetesクラスター内のPodは、主に次の2種類の方法で使われます。

  • 単一のコンテナを稼働させるPod。「1Pod1コンテナ」構成のモデルは、Kubernetesでは最も一般的なユースケースです。このケースでは、ユーザーはPodを単一のコンテナのラッパーとして考えることができます。Kubernetesはコンテナを直接管理するのではなく、Podを管理します。

  • 協調して稼働させる必要がある複数のコンテナを稼働させるPod。単一のPodは、密に結合してリソースを共有する必要があるような、同じ場所で稼働する複数のコンテナからなるアプリケーションをカプセル化することもできます。これらの同じ場所で稼働するコンテナ群は、単一のまとまりのあるサービスのユニットを構成します。たとえば、1つのコンテナが共有ボリュームからファイルをパブリックに配信し、別のサイドカーコンテナがそれらのファイルを更新するという構成が考えられます。Podはこれらの複数のコンテナ、ストレージリソース、一時的なネットワークIDなどを、単一のユニットとしてまとめます。

各Podは、与えられたアプリケーションの単一のインスタンスを稼働するためのものです。もしユーザーのアプリケーションを水平にスケールさせたい場合(例: 複数インスタンスを稼働させる)、複数のPodを使うべきです。1つのPodは各インスタンスに対応しています。Kubernetesでは、これは一般的にレプリケーションと呼ばれます。レプリケーションされたPodは、通常ワークロードリソースと、それに対応するコントローラーによって、作成・管理されます。

Kubernetesがワークロードリソースとそのコントローラーを活用して、スケーラブルで自動回復するアプリケーションを実装する方法については、詳しくはPodとコントローラーを参照してください。

Podが複数のコンテナを管理する方法

Podは、まとまりの強いサービスのユニットを構成する、複数の協調する(コンテナとして実行される)プロセスをサポートするために設計されました。単一のPod内の複数のコンテナは、クラスター内の同じ物理または仮想マシン上で、自動的に同じ場所に配置・スケジューリングされます。コンテナ間では、リソースや依存関係を共有したり、お互いに通信したり、停止するときにはタイミングや方法を協調して実行できます。

たとえば、あるコンテナが共有ボリューム内のファイルを配信するウェブサーバーとして動作し、別の「サイドカー」コンテナがリモートのリソースからファイルをアップデートするような構成が考えられます。この構成を以下のダイアグラムに示します。

Podのダイアグラムの例

Podによっては、appコンテナに加えてinitコンテナを持っている場合があります。initコンテナはappコンテナが起動する前に実行・完了するコンテナです。

Podは、Podを構成する複数のコンテナに対して、ネットワークストレージの2種類の共有リソースを提供します。

Podを利用する

通常Kubernetesでは、たとえ単一のコンテナしか持たないシングルトンのPodだとしても、個別のPodを直接作成することはめったにありません。その理由は、Podがある程度一時的で使い捨てできる存在として設計されているためです。Podが作成されると(あなたが直接作成した場合でも、コントローラーが間接的に作成した場合でも)、新しいPodはクラスター内のノード上で実行されるようにスケジューリングされます。Podは、実行が完了するか、Podオブジェクトが削除されるか、リソース不足によって強制退去されるか、ノードが停止するまで、そのノード上にとどまります。

Podオブジェクトのためのマニフェストを作成したときは、指定したPodの名前が有効なDNSサブドメイン名であることを確認してください。

Podとコンテナコントローラー

ワークロードリソースは、複数のPodを作成・管理するために利用できます。リソースに対応するコントローラーが、複製やロールアウトを扱い、Podの障害時には自動回復を行います。たとえば、あるノードに障害が発生した場合、コントローラーはそのノードの動作が停止したことを検知し、代わりのPodを作成します。そして、スケジューラーが代わりのPodを健全なノード上に配置します。

以下に、1つ以上のPodを管理するワークロードリソースの一例をあげます。

Podテンプレート

workloadリソース向けのコントローラーは、PodをPodテンプレートを元に作成し、あなたの代わりにPodを管理してくれます。

PodTemplateはPodを作成するための仕様で、DeploymentJobDaemonSetなどのワークロードリソースの中に含まれています。

ワークロードリソースに対応する各コントローラーは、ワークロードオブジェクト内にあるPodTemplateを使用して実際のPodを作成します。PodTemplateは、アプリを実行するために使われるワークロードリソースがどんな種類のものであれ、その目的の状態の一部を構成するものです。

以下は、単純なJobのマニフェストの一例で、1つのコンテナを実行するtemplateがあります。Pod内のコンテナはメッセージを出力した後、一時停止します。

apiVersion: batch/v1
kind: Job
metadata:
  name: hello
spec:
  template:
    # これがPodテンプレートです
    spec:
      containers:
      - name: hello
        image: busybox
        command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
      restartPolicy: OnFailure
    # Podテンプレートはここまでです

Podテンプレートを修正するか新しいPodに切り替えたとしても、すでに存在するPodには直接の影響はありません。ワークロードリソース内のPodテンプレートを変更すると、そのリソースは更新されたテンプレートを使用して代わりとなるPodを作成する必要があります。

たとえば、StatefulSetコントローラーは、各StatefulSetごとに、実行中のPodが現在のPodテンプレートに一致することを保証します。Podテンプレートを変更するためにStatefulSetを編集すると、StatefulSetは更新されたテンプレートを元にした新しいPodを作成するようになります。最終的に、すべての古いPodが新しいPodで置き換えられ、更新は完了します。

各ワークロードリソースは、Podテンプレートへの変更を処理するための独自のルールを実装しています。特にStatefulSetについて更に詳しく知りたい場合は、StatefulSetの基本チュートリアル内のアップデート戦略を読んでください。

ノード上では、kubeletはPodテンプレートに関する詳細について監視や管理を直接行うわけではありません。こうした詳細は抽象化されています。こうした抽象化や関心の分離のおかげでシステムのセマンティクスが単純化され、既存のコードを変更せずにクラスターの動作を容易に拡張できるようになっているのです。

リソースの共有と通信

Podは、データの共有と構成するコンテナ間での通信を可能にします。

Pod内のストレージ

Podでは、共有ストレージであるボリュームの集合を指定できます。Pod内のすべてのコンテナは共有ボリュームにアクセスできるため、それら複数のコンテナでデータを共有できるようになります。また、ボリュームを利用すれば、Pod内のコンテナの1つに再起動が必要になった場合にも、Pod内の永続化データを保持し続けられるようにできます。Kubernetesの共有ストレージの実装方法とPodで利用できるようにする方法に関するさらに詳しい情報は、ストレージを読んでください。

Podネットワーク

各Podには、各アドレスファミリーごとにユニークなIPアドレスが割り当てられます。Pod内のすべてのコンテナは、IPアドレスとネットワークポートを含むネットワーク名前空間を共有します。Podの中では(かつその場合にのみ)、そのPod内のコンテナはlocalhostを使用して他のコンテナと通信できます。Podの内部にあるコンテナがPodの外部にあるエンティティと通信する場合、(ポートなどの)共有ネットワークリソースの使い方をコンテナ間で調整しなければなりません。Pod内では、コンテナはIPアドレスとポートの空間を共有するため、localhostで他のコンテナにアクセスできます。また、Pod内のコンテナは、SystemVのセマフォやPOSIXの共有メモリなど、標準のプロセス間通信を使って他のコンテナと通信することもできます。異なるPod内のコンテナは異なるIPアドレスを持つため、特別な設定をしない限りIPCで通信することはできません。異なるPod上で実行中のコンテナ間でやり取りをしたい場合は、IPネットワークを使用して通信できます。

Pod内のコンテナは、システムのhostnameがPodに設定したnameと同一であると考えます。ネットワークについての詳しい情報は、ネットワークで説明しています。

コンテナの特権モード

Pod内のどんなコンテナも、privilegedフラグをコンテナのspecのsecurity contextに設定することで、特権モード(privileged mode)を有効にできます。これは、ネットワークスタックの操作やハードウェアデバイスへのアクセスなど、オペレーティングシステムの管理者の権限が必要なコンテナの場合に役に立ちます。特権コンテナ内のプロセスはコンテナ外のプロセスが利用できるのとほぼ同等の権限を取得します。

static Pod

static Podは、APIサーバーには管理されない、特定のノード上でkubeletデーモンによって直接管理されるPodのことです。大部分のPodはコントロープレーン(たとえばDeployment)によって管理されますが、static Podの場合はkubeletが各static Podを直接管理します(障害時には再起動します)。

static Podは常に特定のノード上の1つのKubeletに紐付けられます。static Podの主な用途は、セルフホストのコントロールプレーンを実行すること、言い換えると、kubeletを使用して個別のコントロールプレーンコンポーネントを管理することです。

kubeletは自動的にKubernetes APIサーバー上に各static Podに対応するミラーPodの作成を試みます。つまり、ノード上で実行中のPodはAPIサーバー上でも見えるようになるけれども、APIサーバー上から制御はできないということです。

次の項目

Kubernetesが共通のPod APIを他のリソース内(たとえばStatefulSetDeploymentなど)にラッピングしている理由の文脈を理解するためには、Kubernetes以前から存在する以下のような既存技術について読むのが助けになります。

3.4.1.1 - Podの概観

このページでは、Kubernetesのオブジェクトモデルにおいて、デプロイ可能な最小単位のオブジェクトであるPodに関して説明します。

Podについて理解する

Pod は、Kubernetesアプリケーションの基本的な実行単位です。これは、作成またはデプロイするKubernetesオブジェクトモデルの中で最小かつ最も単純な単位です。Podは、クラスターで実行されているプロセスを表します。

Podは、アプリケーションのコンテナ(いくつかの場合においては複数のコンテナ)、ストレージリソース、ユニークなネットワークIP、およびコンテナの実行方法を管理するオプションをカプセル化します。Podはデプロイメントの単位、すなわちKubernetesのアプリケーションの単一インスタンス で、単一のコンテナまたは密結合なリソースを共有する少数のコンテナで構成される場合があります。

DockerはKubernetesのPod内で使われる最も一般的なコンテナランタイムですが、Podは他のコンテナランタイムも同様にサポートしています。

Kubernetesクラスター内でのPodは2つの主な方法で使うことができます。

  • 単一のコンテナを稼働させるPod : いわゆる*「1Pod1コンテナ」* 構成のモデルは、最も一般的なKubernetesのユースケースです。 このケースでは、ユーザーはPodを単一のコンテナのラッパーとして考えることができ、Kubernetesはコンテナを直接扱うというよりは、Podを管理することになります。
  • 協調して稼働させる必要がある複数のコンテナを稼働させるPod : 単一のPodは、リソースを共有する必要があるような、密接に連携した複数の同じ環境にあるコンテナからなるアプリケーションをカプセル化することもできます。 これらの同じ環境にあるコンテナ群は、サービスの結合力の強いユニットを構成することができます。 -- 1つのコンテナが、共有されたボリュームからファイルをパブリックな場所に送信し、一方では分割されたサイドカー コンテナがそれらのファイルを更新します。そのPodはそれらのコンテナとストレージリソースを、単一の管理可能なエンティティとしてまとめます。

Kubernetes Blogにて、Podのユースケースに関するいくつかの追加情報を見ることができます。さらなる情報を得たい場合は、下記のページを参照ください。

各Podは、与えられたアプリケーションの単一のインスタンスを稼働するためのものです。もしユーザーのアプリケーションを水平にスケールさせたい場合(例: 複数インスタンスを稼働させる)、複数のPodを使うべきです。1つのPodは各インスタンスに対応しています。 Kubernetesにおいて、これは一般的に レプリケーション と呼ばれます。 レプリケーションされたPodは、通常コントローラーと呼ばれる抽象概念によって単一のグループとして作成、管理されます。 さらなる情報に関してはPodとコントローラーを参照して下さい。

Podがどのように複数のコンテナを管理しているか

Podは凝集性の高いサービスのユニットを構成するような複数の協調プロセス(コンテナ)をサポートするためにデザインされました。 単一のPod内のコンテナ群は、クラスター内において同一の物理マシンもしくは仮想マシン上において自動で同じ環境に配備され、スケジュールされます。コンテナはリソースや依存関係を共有し、お互いにコミュニケートし、それらがいつ、どのように削除されるかを調整できます。

注意点として、単一のPod内で同じ環境に配備され、同時管理される複数のコンテナをグルーピングするのは、比較的に発展的なユースケースとなります。 ユーザーは、コンテナ群が密接に連携するような、特定のインスタンスにおいてのみこのパターンを使用するべきです。 例えば、ユーザーが共有ボリューム内にあるファイル用のWebサーバとして稼働するコンテナと、下記のダイアグラムにあるような、リモートのソースからファイルを更新するような分離されたサイドカー コンテナを持っているような場合です。

Podのダイアグラム

Podは、Podによって構成されたコンテナ群のために2種類の共有リソースを提供します。 ネットワーキングストレージ です。

ネットワーキング

各Podは固有のIPアドレスを割り当てられます。単一のPod内の各コンテナは、IPアドレスやネットワークポートを含む、そのネットワークの名前空間を共有します。Pod内の コンテナはlocalhostを使用してお互いに疎通できます。単一のPod内のコンテナがPod外 のエンティティと疎通する場合、共有されたネットワークリソース(ポートなど)をどのように使うかに関して調整しなければなりません。

ストレージ

単一のPodは共有されたストレージボリュームのセットを指定できます。Pod内の全てのコンテナは、その共有されたボリュームにアクセスでき、コンテナ間でデータを共有することを可能にします。ボリュームもまた、もしPod内のコンテナの1つが再起動が必要になった場合に備えて、データを永続化できます。 単一のPod内での共有ストレージをKubernetesがどう実装しているかについてのさらなる情報については、Volumesを参照してください。

Podを利用する

ユーザーはまれに、Kubernetes内で独立したPodを直接作成する場合があります(シングルトンPodなど)。 これはPodが比較的、一時的な使い捨てエンティティとしてデザインされているためです。Podが作成された時(ユーザーによって直接的、またはコントローラーによって間接的に作成された場合)、ユーザーのクラスター内の単一のノード上で稼働するようにスケジューリングされます。そのPodはプロセスが停止されたり、Podオブジェクトが削除されたり、Podがリソースの欠如のために追い出され たり、ノードが故障するまでノード上に残り続けます。

Podは、Podそれ自体によって自己修復しません。もし、稼働されていないノード上にPodがスケジュールされた場合や、スケジューリング操作自体が失敗した場合、Podが削除されます。同様に、Podはリソースの欠如や、ノードのメンテナンスによる追い出しがあった場合はそこで停止します。Kubernetesはコントローラー と呼ばれる高レベルの抽象概念を使用し、それは比較的使い捨て可能なPodインスタンスの管理を行います。 このように、Podを直接使うのは可能ですが、コントローラーを使用したPodを管理する方がより一般的です。KubernetesがPodのスケーリングと修復機能を実現するためにコントローラーをどのように使うかに関する情報はPodとコントローラーを参照してください。

Podとコントローラー

単一のコントローラーは、ユーザーのために複数のPodを作成・管理し、レプリケーションやロールアウト、クラスターのスコープ内で自己修復の機能をハンドリングします。例えば、もしノードが故障した場合、コントローラーは異なるノード上にPodを置き換えるようにスケジューリングすることで、自動的にリプレース可能となります。

1つまたはそれ以上のPodを含むコントローラーの例は下記の通りです。

通常は、コントローラーはユーザーが作成したPodテンプレートを使用して、担当するPodを作成します。

Podテンプレート

Podテンプレートは、ReplicationControllerJobや、 DaemonSetのような他のオブジェクト内で含まれるPodの仕様となります。 コントローラーは実際のPodを作成するためにPodテンプレートを使用します。 下記のサンプルは、メッセージを表示する単一のコンテナを含んだ、シンプルなPodのマニフェストとなります。

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 3600']

全てのレプリカの現在の理想的な状態を指定するというよりも、Podテンプレートはクッキーの抜き型のようなものです。一度クッキーがカットされると、そのクッキーは抜き型から離れて関係が無くなります。そこにはいわゆる”量子もつれ”といったものはありません。テンプレートに対するその後の変更や新しいテンプレートへの切り替えは、すでに作成されたPod上には直接的な影響はありません。 同様に、ReplicationControllerによって作成されたPodは、変更後に直接更新されます。これはPodとの意図的な違いとなり、そのPodに属する全てのコンテナの現在の理想的な状態を指定します。このアプローチは根本的にシステムのセマンティクスを単純化し、機能の柔軟性を高めます。

次の項目

3.4.1.2 - Podのライフサイクル

このページではPodのライフサイクルについて説明します。Podは定義されたライフサイクルに従い Pendingフェーズから始まり、少なくとも1つのプライマリーコンテナが正常に開始した場合はRunningを経由し、次に失敗により終了したコンテナの有無に応じて、SucceededまたはFailedフェーズを経由します。

Podの実行中、kubeletはコンテナを再起動して、ある種の障害を処理できます。Pod内で、Kubernetesはさまざまなコンテナのステータスを追跡して、回復させるためのアクションを決定します。

Kubernetes APIでは、Podには仕様と実際のステータスの両方があります。Podオブジェクトのステータスは、PodのConditionのセットで構成されます。カスタムのReadiness情報をPodのConditionデータに挿入することもできます。

Podはその生存期間に1回だけスケジューリングされます。PodがNodeにスケジュール(割り当て)されると、Podは停止または終了するまでそのNode上で実行されます。

Podのライフタイム

個々のアプリケーションコンテナと同様に、Podは(永続的ではなく)比較的短期間の存在と捉えられます。Podが作成されると、一意のID(UID)が割り当てられ、(再起動ポリシーに従って)終了または削除されるまでNodeで実行されるようにスケジュールされます。
ノードが停止した場合、そのNodeにスケジュールされたPodは、タイムアウト時間の経過後に削除されます。

Pod自体は、自己修復しません。Podがnodeにスケジュールされ、その後に失敗、またはスケジュール操作自体が失敗した場合、Podは削除されます。同様に、リソースの不足またはNodeのメンテナンスによりPodはNodeから立ち退きます。Kubernetesは、比較的使い捨てのPodインスタンスの管理作業を処理する、controllerと呼ばれる上位レベルの抽象化を使用します。

特定のPod(UIDで定義)は新しいNodeに"再スケジュール"されません。代わりに、必要に応じて同じ名前で、新しいUIDを持つ同一のPodに置き換えることができます。

volumeなど、Podと同じ存続期間を持つものがあると言われる場合、それは(そのUIDを持つ)Podが存在する限り存在することを意味します。そのPodが何らかの理由で削除された場合、たとえ同じ代替物が作成されたとしても、関連するもの(例えばボリューム)も同様に破壊されて再作成されます。

Podの図

file puller(ファイル取得コンテナ)とWebサーバーを含むマルチコンテナのPod。コンテナ間の共有ストレージとして永続ボリュームを使用しています。

Podのフェーズ

Podのstatus項目はPodStatusオブジェクトで、それはphaseのフィールドがあります。

Podのフェーズは、そのPodがライフサイクルのどの状態にあるかを、簡単かつ高レベルにまとめたものです。このフェーズはコンテナやPodの状態を包括的にまとめることを目的としたものではなく、また包括的なステートマシンでもありません。

Podの各フェーズの値と意味は厳重に守られています。ここに記載されているもの以外にphaseの値は存在しないと思ってください。

これらがphaseの取りうる値です。

概要
PendingPodがKubernetesクラスターによって承認されましたが、1つ以上のコンテナがセットアップされて稼働する準備ができていません。これには、スケジュールされるまでの時間と、ネットワーク経由でイメージをダウンロードするための時間などが含まれます。
RunningPodがNodeにバインドされ、すべてのコンテナが作成されました。少なくとも1つのコンテナがまだ実行されているか、開始または再起動中です。
SucceededPod内のすべてのコンテナが正常に終了し、再起動されません。
FailedPod内のすべてのコンテナが終了し、少なくとも1つのコンテナが異常終了しました。つまり、コンテナはゼロ以外のステータスで終了したか、システムによって終了されました。
Unknown何らかの理由によりPodの状態を取得できませんでした。このフェーズは通常はPodのホストとの通信エラーにより発生します。

Nodeが停止するか、クラスタの残りの部分から切断された場合、Kubernetesは失われたNode上のすべてのPodのPhaseをFailedに設定するためのポリシーを適用します。

コンテナのステータス

Pod全体のフェーズと同様に、KubernetesはPod内の各コンテナの状態を追跡します。container lifecycle hooksを使用して、コンテナのライフサイクルの特定のポイントで実行するイベントをトリガーできます。

PodがschedulerによってNodeに割り当てられると、kubeletはcontainer runtimeを使用してコンテナの作成を開始します。コンテナの状態はWaitingRunningまたはTerminatedの3ついずれかです。

Podのコンテナの状態を確認するにはkubectl describe pod [POD_NAME]のコマンドを使用します。Pod内のコンテナごとにStateの項目として表示されます。

各状態の意味は次のとおりです。

Waiting

コンテナがRunningまたはTerminatedのいずれの状態でもない場合コンテナはWaitingの状態になります。Waiting状態のコンテナは引き続きコンテナイメージレジストリからイメージを取得したりSecretを適用したりするなど必要な操作を実行します。Waiting状態のコンテナを持つPodに対してkubectlコマンドを使用すると、そのコンテナがWaitingの状態である理由の要約が表示されます。

Running

Running状態はコンテナが問題なく実行されていることを示します。postStartフックが構成されていた場合、それはすでに実行が完了しています。Running状態のコンテナを持つPodに対してkubectlコマンドを使用すると、そのコンテナがRunning状態になった時刻が表示されます。

Terminated

Terminated状態のコンテナは実行されて、完了したときまたは何らかの理由で失敗したことを示します。Terminated状態のコンテナを持つPodに対してkubectlコマンドを使用すると、いずれにせよ理由と終了コード、コンテナの開始時刻と終了時刻が表示されます。

コンテナがTerminatedに入る前にpreStopフックがあれば実行されます。

コンテナの再起動ポリシー

Podのspecには、Always、OnFailure、またはNeverのいずれかの値を持つrestartPolicyフィールドがあります。デフォルト値はAlwaysです。

restartPolicyは、Pod内のすべてのコンテナに適用されます。restartPolicyは、同じNode上のkubeletによるコンテナの再起動のみを参照します。Pod内のコンテナが終了した後、kubeletは5分を上限とする指数バックオフ遅延(10秒、20秒、40秒...)でコンテナを再起動します。コンテナが10分間実行されると、kubeletはコンテナの再起動バックオフタイマーをリセットします。

PodのCondition

PodにはPodStatusがあります。それはPodが成功したかどうかの情報を持つPodConditionsの配列です。

  • PodScheduled: PodがNodeにスケジュールされました。
  • ContainersReady: Pod内のすべてのコンテナが準備できた状態です。
  • Initialized: すべてのInitコンテナが正常に実行されました。
  • Ready: Podはリクエストを処理でき、一致するすべてのサービスの負荷分散プールに追加されます。
フィールド名内容
typeこのPodの状態の名前です。
statusその状態が適用可能かどうか示します。可能な値は"True"と"False"、"Unknown"のうちのいずれかです。
lastProbeTimePod Conditionが最後に確認されたときのタイムスタンプが表示されます。
lastTransitionTime最後にPodのステータスの遷移があった際のタイムスタンプが表示されます。
reason最後の状態遷移の理由を示す、機械可読のアッパーキャメルケースのテキストです。
messageステータスの遷移に関する詳細を示す人間向けのメッセージです。

PodのReadiness

FEATURE STATE: Kubernetes v1.14 [stable]

追加のフィードバックやシグナルをPodStatus:_Pod readiness_に注入できるようにします。これを使用するには、PodのspecreadinessGatesを設定して、kubeletがPodのReadinessを評価する追加の状態のリストを指定します。

ReadinessゲートはPodのstatus.conditionsフィールドの現在の状態によって決まります。KubernetesがPodのstatus.conditionsフィールドでそのような状態を発見できない場合、ステータスはデフォルトでFalseになります。

以下はその例です。

Kind: Pod
...
spec:
  readinessGates:
    - conditionType: "www.example.com/feature-1"
status:
  conditions:
    - type: Ready  # これはビルトインのPodCondition
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
    - type: "www.example.com/feature-1"   # 追加のPodCondition
      status: "False"
      lastProbeTime: null
      lastTransitionTime: 2018-01-01T00:00:00Z
  containerStatuses:
    - containerID: docker://abcd...
      ready: true
...

PodのConditionは、Kubernetesのlabel key formatに準拠している必要があります。

PodのReadinessの状態

kubectl patchコマンドはオブジェクトステータスのパッチ適用をまだサポートしていません。Podにこれらのstatus.conditionsを設定するには、アプリケーションとoperatorsPATCHアクションを使用する必要があります。Kubernetes client libraryを使用して、PodのReadinessのためにカスタムのPodのConditionを設定するコードを記述できます。

カスタムのPodのConditionが導入されるとPodは次の両方の条件に当てはまる場合のみ準備できていると評価されます:

  • Pod内のすべてのコンテナが準備完了している。
  • ReadinessGatesで指定された条件が全てTrueである。

Podのコンテナは準備完了ですが、少なくとも1つのカスタムのConditionが欠落しているか「False」の場合、kubeletはPodのConditionContainersReadyに設定します。

コンテナのProbe

Probekubelet により定期的に実行されるコンテナの診断です。診断を行うために、kubeletはコンテナに実装された Handlerを呼びます。Handlerには次の3つの種類があります:

  • ExecAction: コンテナ内で特定のコマンドを実行します。コマンドがステータス0で終了した場合に診断を成功と見まします。

  • TCPSocketAction: PodのIPの特定のポートにTCPチェックを行います。 そのポートが空いていれば診断を成功とみなします。

  • HTTPGetAction: PodのIPの特定のポートとパスに対して、HTTP GETのリクエストを送信します。 レスポンスのステータスコードが200以上400未満の際に診断を成功とみなします。

各Probe 次の3つのうちの一つの結果を持ちます:

  • Success: コンテナの診断が成功しました。
  • Failure: コンテナの診断が失敗しました。
  • Unknown: コンテナの診断が失敗し、取れるアクションがありません。

Kubeletは3種類のProbeを実行中のコンテナで行い、また反応することができます:

  • livenessProbe: コンテナが動いているかを示します。 livenessProbe に失敗すると、kubeletはコンテナを殺します、そしてコンテナはrestart policyに従います。 コンテナにlivenessProbeが設定されていない場合、デフォルトの状態はSuccessです。

  • readinessProbe: コンテナがリクエスト応答する準備ができているかを示します。 readinessProbeに失敗すると、エンドポイントコントローラーにより、ServiceからそのPodのIPアドレスが削除されます。 initial delay前のデフォルトのreadinessProbeの初期値はFailureです。 コンテナにreadinessProbeが設定されていない場合、デフォルトの状態はSuccessです。

  • startupProbe: コンテナ内のアプリケーションが起動したかどうかを示します。 startupProbeが設定された場合、完了するまでその他のすべてのProbeは無効になります。 startupProbeに失敗すると、kubeletはコンテナを殺します、そしてコンテナはrestart policyに従います。 コンテナにstartupProbeが設定されていない場合、デフォルトの状態はSuccessです。

livenessProbe、readinessProbeまたはstartupProbeを設定する方法の詳細については、Liveness Probe、Readiness ProbeおよびStartup Probeを使用するを参照してください。

livenessProbeをいつ使うべきか?

FEATURE STATE: Kubernetes v1.0 [stable]

コンテナ自体に問題が発生した場合や状態が悪くなった際にクラッシュすることができればlivenessProbeは不要です. この場合kubeletが自動でPodのrestartPolicyに基づいたアクションを実行します。

Probeに失敗したときにコンテナを殺したり再起動させたりするには、livenessProbeを設定しrestartPolicyをAlwaysまたはOnFailureにします。

readinessProbeをいつ使うべきか?

FEATURE STATE: Kubernetes v1.0 [stable]

Probeが成功したときにのみPodにトラフィックを送信したい場合は、readinessProbeを指定します。 この場合readinessProbeはlivenessProbeと同じになる可能性がありますが、readinessProbeが存在するということは、Podがトラフィックを受けずに開始され、Probe成功が開始した後でトラフィックを受け始めることになります。コンテナが起動時に大きなデータ、構成ファイル、またはマイグレーションを読み込む必要がある場合は、readinessProbeを指定します。

コンテナがメンテナンスのために停止できるようにするには、livenessProbeとは異なる、特定のエンドポイントを確認するreadinessProbeを指定することができます。

startupProbeをいつ使うべきか?

FEATURE STATE: Kubernetes v1.18 [beta]

startupProbeは、サービスの開始に時間がかかるコンテナを持つPodに役立ちます。livenessProbeの間隔を長く設定するのではなく、コンテナの起動時に別のProbeを構成して、livenessProbeの間隔よりも長い時間を許可できます。 コンテナの起動時間が、initialDelaySeconds + failureThreshold x periodSecondsよりも長い場合は、livenessProbeと同じエンドポイントをチェックするためにstartupProbeを指定します。periodSecondsのデフォルトは30秒です。次に、failureThresholdをlivenessProbeのデフォルト値を変更せずにコンテナが起動できるように、十分に高い値を設定します。これによりデッドロックを防ぐことができます。

Podの終了

Podは、クラスター内のNodeで実行中のプロセスを表すため、不要になったときにそれらのプロセスを正常に終了できるようにすることが重要です(対照的なケースは、KILLシグナルで強制終了され、クリーンアップする機会がない場合)。

ユーザーは削除を要求可能であるべきで、プロセスがいつ終了するかを知ることができなければなりませんが、削除が最終的に完了することも保証できるべきです。ユーザーがPodの削除を要求すると、システムはPodが強制終了される前に意図された猶予期間を記録および追跡します。強制削除までの猶予期間がある場合、kubelet正常な終了を試みます。

通常、コンテナランタイムは各コンテナのメインプロセスにTERMシグナルを送信します。多くのコンテナランタイムは、コンテナイメージで定義されたSTOPSIGNAL値を尊重し、TERMシグナルの代わりにこれを送信します。猶予期間が終了すると、プロセスにKILLシグナルが送信され、PodはAPI serverから削除されます。プロセスの終了を待っている間にkubeletかコンテナランタイムの管理サービスが再起動されると、クラスターは元の猶予期間を含めて、最初からリトライされます。

フローの例は下のようになります。

  1. ユーザーがデフォルトの猶予期間(30秒)でPodを削除するためにkubectlコマンドを送信する。
  2. API server内のPodは、猶予期間を越えるとPodが「死んでいる」と見なされるように更新される。
    削除中のPodに対してkubectl describeコマンドを使用すると、Podは「終了中」と表示される。
    Podが実行されているNode上で、Podが終了しているとマークされている(正常な終了期間が設定されている)とkubeletが認識するとすぐに、kubeletはローカルでPodの終了プロセスを開始します。
    1. Pod内のコンテナの1つがpreStopフックを定義している場合は、コンテナの内側で呼び出される。猶予期間が終了した後も preStopフックがまだ実行されている場合は、一度だけ猶予期間を延長される(2秒)。
    2. kubeletはコンテナランタイムをトリガーして、コンテナ内のプロセス番号1にTERMシグナルを送信する。
  3. kubeletが正常な終了を開始すると同時に、コントロールプレーンは、終了中のPodをEndpoints(および有効な場合はEndpointSlice)オブジェクトから削除します。これらのオブジェクトは、selectorが設定されたServiceを表します。ReplicaSetsとその他のワークロードリソースは、終了中のPodを有効なサービス中のReplicaSetとして扱いません。ゆっくりと終了するPodは、(サービスプロキシーのような)ロードバランサーが終了猶予期間が_始まる_とエンドポイントからそれらのPodを削除するので、トラフィックを継続して処理できません。
  4. 猶予期間が終了すると、kubeletは強制削除を開始する。コンテナランタイムは、Pod内でまだ実行中のプロセスにSIGKILLを送信する。kubeletは、コンテナランタイムが非表示のpauseコンテナを使用している場合、そのコンテナをクリーンアップします。
  5. kubeletは猶予期間を0(即時削除)に設定することでAPI server上のPodの削除を終了する。
  6. API serverはPodのAPIオブジェクトを削除し、クライアントからは見えなくなります。

Podの強制削除

デフォルトでは、すべての削除は30秒以内に正常に行われます。kubectl delete コマンドは、ユーザーがデフォルト値を上書きして独自の値を指定できるようにする --grace-period=<seconds> オプションをサポートします。

--grace-period0に設定した場合、PodはAPI serverから即座に強制的に削除されます。PodがNode上でまだ実行されている場合、その強制削除によりkubeletがトリガーされ、すぐにクリーンアップが開始されます。

強制削除が実行されると、API serverは、Podが実行されていたNode上でPodが停止されたというkubeletからの確認を待ちません。API内のPodは直ちに削除されるため、新しいPodを同じ名前で作成できるようになります。Node上では、すぐに終了するように設定されるPodは、強制終了される前にわずかな猶予期間が与えられます。

StatefulSetのPodについては、StatefulSetからPodを削除するためのタスクのドキュメントを参照してください。

失敗したPodのガベージコレクション

失敗したPodは人間またはcontrollerが明示的に削除するまで存在します。

コントロールプレーンは終了状態のPod(SucceededまたはFailedのphaseを持つ)の数が設定された閾値(kube-controller-manager内のterminated-pod-gc-thresholdによって定義される)を超えたとき、それらのPodを削除します。これはPodが作成されて時間とともに終了するため、リソースリークを避けます。

次の項目

3.4.1.3 - Initコンテナ

このページでは、Initコンテナについて概観します。Initコンテナとは、Pod内でアプリケーションコンテナの前に実行される特別なコンテナです。 Initコンテナにはアプリケーションコンテナのイメージに存在しないセットアップスクリプトやユーティリティーを含めることができます。

Initコンテナは、Podの仕様のうちcontainersという配列(これがアプリケーションコンテナを示します)と並べて指定します。

Initコンテナを理解する

単一のPodは、Pod内にアプリケーションを実行している複数のコンテナを持つことができますが、同様に、アプリケーションコンテナが起動する前に実行されるInitコンテナも1つ以上持つことができます。

Initコンテナは下記の項目をのぞいて、通常のコンテナと全く同じものとなります。

  • Initコンテナは常に完了するまで稼働します。
  • 各Initコンテナは、次のInitコンテナが稼働する前に正常に完了しなくてはなりません。

もしあるPodの単一のInitコンテナが失敗した場合、Kubeletは成功するまで何度もそのInitコンテナを再起動します。しかし、もしそのPodのrestartPolicyがNeverで、そのPodの起動時にInitコンテナが失敗した場合、KubernetesはそのPod全体を失敗として扱います。

PodにInitコンテナを指定するためには、Podの仕様にそのアプリケーションのcontainers配列と並べて、initContainersフィールドをContainer型のオブジェクトの配列として指定してください。 Initコンテナのステータスは、.status.initContainerStatusesフィールドにコンテナのステータスの配列として返されます(.status.containerStatusesと同様)。

通常のコンテナとの違い

Initコンテナは、リソースリミット、ボリューム、セキュリティ設定などのアプリケーションコンテナの全てのフィールドと機能をサポートしています。しかし、Initコンテナに対するリソースリクエストやリソースリミットの扱いは異なります。リソースにて説明します。

また、InitコンテナはそのPodの準備ができる前に完了しなくてはならないため、lifecyclelivenessProbereadinessProbeおよびstartupProbeをサポートしていません。

複数のInitコンテナを単一のPodに対して指定した場合、KubeletはそれらのInitコンテナを1つずつ順番に実行します。各Initコンテナは、次のInitコンテナが稼働する前に正常終了しなくてはなりません。全てのInitコンテナの実行が完了すると、KubeletはPodのアプリケーションコンテナを初期化し、通常通り実行します。

Initコンテナを使用する

Initコンテナはアプリケーションコンテナのイメージとは分離されているため、コンテナの起動に関連したコードにおいていくつかの利点があります。

  • Initコンテナはアプリケーションのイメージに存在しないセットアップ用のユーティリティーやカスタムコードを含むことができます。例えば、セットアップ中にsedawkpythonや、digのようなツールを使うためだけに、別のイメージを元にしてアプリケーションイメージを作る必要がなくなります。
  • アプリケーションイメージをビルドする役割とデプロイする役割は、共同で単一のアプリケーションイメージをビルドする必要がないため、それぞれ独立して実施することができます。
  • Initコンテナは同一Pod内のアプリケーションコンテナと別のファイルシステムビューで稼働することができます。その結果、アプリケーションコンテナがアクセスできないSecretに対するアクセス権限を得ることができます。
  • Initコンテナはアプリケーションコンテナが開始する前に完了するまで実行されるため、Initコンテナを使用することで、特定の前提条件が満たされるまでアプリケーションコンテナの起動をブロックしたり遅らせることができます。前提条件が満たされると、Pod内の全てのアプリケーションコンテナを並行して起動することができます。
  • Initコンテナはアプリケーションコンテナイメージの安全性を低下させるようなユーティリティーやカスタムコードを安全に実行することができます。不必要なツールを分離しておくことで、アプリケーションコンテナイメージのアタックサーフィスを制限することができます。

Initコンテナを活用する方法について、いくつかのアイデアを次に示します。

  • シェルコマンドを使って単一のServiceが作成されるのを待機する。

    for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
    
  • 以下のようなコマンドを使って下位のAPIからPodの情報をリモートサーバに登録する。

    curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
    
  • 以下のようなコマンドを使ってアプリケーションコンテナの起動を待機する。

    sleep 60
    
  • gitリポジトリをVolumeにクローンする。

  • いくつかの値を設定ファイルに配置し、メインのアプリケーションコンテナのための設定ファイルを動的に生成するためのテンプレートツールを実行する。例えば、そのPodのPOD_IPの値を設定ファイルに配置し、Jinjaを使ってメインのアプリケーションコンテナの設定ファイルを生成する。

Initコンテナの具体的な使用方法

下記の例は2つのInitコンテナを含むシンプルなPodを定義しています。 1つ目のInitコンテナはmyserviesの起動を、2つ目のInitコンテナはmydbの起動をそれぞれ待ちます。両方のInitコンテナの実行が完了すると、Podはspecセクションにあるアプリケーションコンテナを実行します。

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]

次のコマンドを実行して、このPodを開始できます。

kubectl apply -f myapp.yaml
pod/myapp-pod created

そして次のコマンドでステータスを確認します。

kubectl get -f myapp.yaml
NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

より詳細な情報は次のコマンドで確認します。

kubectl describe -f myapp.yaml
Name:          myapp-pod
Namespace:     default
[...]
Labels:        app=myapp
Status:        Pending
[...]
Init Containers:
  init-myservice:
[...]
    State:         Running
[...]
  init-mydb:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Containers:
  myapp-container:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
Events:
  FirstSeen    LastSeen    Count    From                      SubObjectPath                           Type          Reason        Message
  ---------    --------    -----    ----                      -------------                           --------      ------        -------
  16s          16s         1        {default-scheduler }                                              Normal        Scheduled     Successfully assigned myapp-pod to 172.17.4.201
  16s          16s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Pulling       pulling image "busybox"
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Pulled        Successfully pulled image "busybox"
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Created       Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
  13s          13s         1        {kubelet 172.17.4.201}    spec.initContainers{init-myservice}     Normal        Started       Started container with docker id 5ced34a04634

このPod内のInitコンテナのログを確認するためには、次のコマンドを実行します。

kubectl logs myapp-pod -c init-myservice # 1つ目のInitコンテナを調査する
kubectl logs myapp-pod -c init-mydb      # 2つ目のInitコンテナを調査する

この時点で、これらのInitコンテナはmydbmyserviceという名前のServiceの検出を待機しています。

これらのServiceを検出させるための構成は以下の通りです。

---
apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376
---
apiVersion: v1
kind: Service
metadata:
  name: mydb
spec:
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9377

mydbおよびmyserviceというServiceを作成するために、以下のコマンドを実行します。

kubectl apply -f services.yaml
service/myservice created
service/mydb created

Initコンテナが完了し、myapp-podというPodがRunning状態に移行したことが確認できます。

kubectl get -f myapp.yaml
NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

このシンプルな例を独自のInitコンテナを作成する際の参考にしてください。次の項目にさらに詳細な使用例に関するリンクがあります。

Initコンテナのふるまいに関する詳細

Podの起動時は各Initコンテナが起動状態となるまで、kubeletはネットワーキングおよびストレージを利用可能な状態にしません。また、kubeletはPodのspecに定義された順番に従ってPodのInitコンテナを起動します。各Initコンテナは次のInitコンテナが起動する前に正常に終了しなくてはなりません。もしあるInitコンテナがランタイムもしくはエラーにより起動失敗した場合、そのPodのrestartPolicyの値に従ってリトライされます。しかし、もしPodのrestartPolicyAlwaysに設定されていた場合、InitコンテナのrestartPolicyOnFailureが適用されます。

Podは全てのInitコンテナが完了するまでReady状態となりません。Initコンテナ上のポートはServiceによって集約されません。初期化中のPodのステータスはPendingとなりますが、Initializedという値はtrueとなります。

もしそのPodが再起動されたとき、全てのInitコンテナは必ず再度実行されます。

Initコンテナの仕様の変更は、コンテナイメージのフィールドのみに制限されています。 Initコンテナのイメージフィールド値を変更すると、そのPodは再起動されます。

Initコンテナは何度も再起動およびリトライ可能なため、べき等(Idempotent)である必要があります。特に、EmptyDirsにファイルを書き込むコードは、書き込み先のファイルがすでに存在している可能性を考慮に入れる必要があります。

Initコンテナはアプリケーションコンテナの全てのフィールドを持っています。しかしKubernetesは、Initコンテナが完了と異なる状態を定義できないためreadinessProbeが使用されることを禁止しています。これはバリデーションの際に適用されます。

Initコンテナがずっと失敗し続けたままの状態を防ぐために、PodにactiveDeadlineSecondsを、コンテナにlivenessProbeをそれぞれ設定してください。activeDeadlineSecondsの設定はInitコンテナが実行中の時間にも適用されます。

Pod内の各アプリケーションコンテナとInitコンテナの名前はユニークである必要があります。他のコンテナと同じ名前を共有していた場合、バリデーションエラーが返されます。

リソース

Initコンテナの順序と実行を考えるとき、リソースの使用に関して下記のルールが適用されます。

  • 全てのInitコンテナの中で定義された最も高いリソースリクエストとリソースリミットが、有効なinitリクエスト/リミット になります。
  • Podのリソースの有効なリクエスト/リミット は、下記の2つの中のどちらか高い方となります。
    • リソースに対する全てのアプリケーションコンテナのリクエスト/リミットの合計
    • リソースに対する有効なinitリクエスト/リミット
  • スケジューリングは有効なリクエスト/リミットに基づいて実行されます。つまり、InitコンテナはPodの生存中には使用されない初期化用のリソースを確保することができます。
  • Podの有効なQoS(quality of service)ティアー は、Initコンテナとアプリケーションコンテナで同様です。

クォータとリミットは有効なPodリクエストとリミットに基づいて適用されます。

Podレベルのコントロールグループ(cgroups)は、スケジューラーと同様に、有効なPodリクエストとリミットに基づいています。

Podの再起動の理由

以下の理由によりPodは再起動し、Initコンテナの再実行も引き起こす可能性があります。

  • ユーザーが、そのPodのInitコンテナのイメージを変更するようにPodの仕様を更新する場合。アプリケーションコンテナのイメージの変更はそのアプリケーションコンテナの再起動のみ行われます。
  • そのPodのインフラストラクチャーコンテナが再起動された場合。これはあまり起きるものでなく、Nodeに対するルート権限を持ったユーザーにより行われることがあります。
  • restartPolicyAlwaysと設定されているPod内の全てのコンテナが停止され、再起動が行われた場合。およびガーベージコレクションによりInitコンテナの完了記録が失われた場合。

次の項目

3.4.1.4 - Pod Preset

FEATURE STATE: Kubernetes v1.6 [alpha]

このページではPodPresetについて概観します。PodPresetは、Podの作成時にそのPodに対して、Secret、Volume、VolumeMountや環境変数など、特定の情報を注入するためのオブジェクトです。

PodPresetを理解する

PodPresetはPodの作成時に追加のランタイム要求を注入するためのAPIリソースです。ユーザーはPodPresetを適用する対象のPodを指定するために、ラベルセレクターを使用します。

PodPresetの使用により、Podテンプレートの作者はPodにおいて、全ての情報を明示的に指定する必要がなくなります。この方法により、特定のServiceを使っているPodテンプレートの作者は、そのServiceについて全ての詳細を知る必要がなくなります。

クラスターでPodPresetを有効にする

ユーザーのクラスター内でPodPresetを使うためには、クラスター内の以下の項目をご確認ください。

  1. settings.k8s.io/v1alpha1/podpresetというAPIを有効にします。例えば、これはAPI Serverの --runtime-configオプションにsettings.k8s.io/v1alpha1=trueを含むことで可能になります。Minikubeにおいては、クラスターの起動時に--extra-config=apiserver.runtime-config=settings.k8s.io/v1alpha1=trueをつけることで可能です。
  2. PodPresetに対する管理コントローラーを有効にします。これを行うための1つの方法として、API Serverの--enable-admission-pluginsオプションの値にPodPresetを含む方法があります。例えば、Minikubeにおいては、クラスターの起動時に
--extra-config=apiserver.enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodPreset

を追加することで可能になります。

PodPresetはどのように動くか

KubernetesはPodPresetに対する管理用コントローラーを提供し、これが有効になっている時、コントローラーはリクエストされたPod作成要求に対してPodPresetを適用します。Pod作成要求が発生した時、Kubernetesシステムは下記の処理を行います。

  1. 使用可能な全てのPodPresetを取得する。
  2. それらのPodPresetのラベルセレクターが、作成されたPod上のラベルと一致するかチェックする。
  3. PodPresetによって定義された様々なリソースを、作成されたPodにマージしようと試みる。
  4. エラーが起きた時、そのPod上でマージエラーが起きたことを説明するイベントをスローし、PodPresetからリソースを1つも注入されていないPodを作成します。
  5. PodPresetによって修正されたことを示すために、マージ後の修正されたPodにアノテーションをつけます。そのアノテーションはpodpreset.admission.kubernetes.io/podpreset-<PodPreset名>: "<リソースのバージョン>"という形式になります。

各Podは0以上のPodPresetにマッチすることができます。そして各PodPresetは0以上のPodに適用されます。単一のPodPresetが1以上のPodに適用された時、KubernetesはそのPodのSpecを修正します。envenvFromvolumeMountsへの変更があると、KubernetesはそのPod内の全てのコンテナのSpecを修正します。volumesへの変更があった場合、KubernetesはそのPodのSpecを修正します。

特定のPodに対するPodPresetを無効にする

PodPresetによるPodの変更を受け付けたくないようなインスタンスがある場合があります。このようなケースでは、ユーザーはそのPodの.spec内に次のような形式のアノテーションを追加できます。
podpreset.admission.kubernetes.io/exclude: "true"

次の項目

PodPresetを使ったPodへのデータの注入

PodPresetの内部についてのさらなる情報は、PodPresetのデザインプロポーザルを参照してください。

3.4.1.5 - エフェメラルコンテナ

FEATURE STATE: Kubernetes v1.16 [alpha]

このページでは、特別な種類のコンテナであるエフェメラルコンテナの概要を説明します。エフェメラルコンテナは、トラブルシューティングなどのユーザーが開始するアクションを実行するために、すでに存在するPod内で一時的に実行するコンテナです。エフェメラルコンテナは、アプリケーションの構築ではなく、serviceの調査のために利用します。

エフェメラルコンテナを理解する

Podは、Kubernetesのアプリケーションの基本的なビルディングブロックです。Podは破棄可能かつ置き換え可能であることが想定されているため、一度Podが作成されると新しいコンテナを追加することはできません。その代わりに、通常はDeploymentを使用してPodを削除して置き換えます。

たとえば、再現困難なバグのトラブルシューティングなどのために、すでに存在するPodの状態を調査する必要が出てくることがあります。このような場合、既存のPod内でエフェメラルコンテナを実行することで、Podの状態を調査したり、任意のコマンドを実行したりできます。

エフェメラルコンテナとは何か?

エフェメラルコンテナは、他のコンテナと異なり、リソースや実行が保証されず、自動的に再起動されることも決してないため、アプリケーションを構築する目的には適しません。エフェメラルコンテナは、通常のコンテナと同じContainerSpecで記述されますが、多くのフィールドに互換性がなかったり、使用できなくなっています。

  • エフェメラルコンテナはポートを持つことができないため、portslivenessProbereadinessProbeなどは使えなくなっています。
  • Podリソースの割り当てはイミュータブルであるため、resourcesの設定が禁止されています。
  • 利用が許可されているフィールドの一覧については、EphemeralContainerのリファレンスドキュメントを参照してください。

エフェメラルコンテナは、直接pod.specに追加するのではなく、API内の特別なephemeralcontainersハンドラを使用して作成します。そのため、エフェメラルコンテナをkubectl editを使用して追加することはできません。

エフェメラルコンテナをPodに追加した後は、通常のコンテナのようにエフェメラルコンテナを変更または削除することはできません。

エフェメラルコンテナの用途

エフェメラルコンテナは、コンテナがクラッシュしてしまったり、コンテナイメージにデバッグ用ユーティリティが同梱されていない場合など、kubectl execでは不十分なときにインタラクティブなトラブルシューティングを行うために役立ちます。

特に、distrolessイメージを利用すると、攻撃対象領域を減らし、バグや脆弱性を露出する可能性を減らせる最小のコンテナイメージをデプロイできるようになります。distrolessイメージにはシェルもデバッグ用のユーティリティも含まれないため、kubectl execのみを使用してdistrolessイメージのトラブルシューティングを行うのは困難です。

エフェメラルコンテナを利用する場合には、他のコンテナ内のプロセスにアクセスできるように、プロセス名前空間の共有を有効にすると便利です。

エフェメラルコンテナを利用してトラブルシューティングを行う例については、デバッグ用のエフェメラルコンテナを使用してデバッグするを参照してください。

Ephemeral containers API

このセクションの例では、API内でエフェメラルコンテナを表示する方法を示します。通常は、APIを直接呼び出すのではなく、kubectl alpha debugやその他のkubectlプラグインを使用して、これらのステップを自動化します。

エフェメラルコンテナは、Podのephemeralcontainersサブリソースを使用して作成されます。このサブリソースは、kubectl --rawを使用して確認できます。まずはじめに、以下にEphemeralContainersリストとして追加するためのエフェメラルコンテナを示します。

{
    "apiVersion": "v1",
    "kind": "EphemeralContainers",
    "metadata": {
        "name": "example-pod"
    },
    "ephemeralContainers": [{
        "command": [
            "sh"
        ],
        "image": "busybox",
        "imagePullPolicy": "IfNotPresent",
        "name": "debugger",
        "stdin": true,
        "tty": true,
        "terminationMessagePolicy": "File"
    }]
}

すでに実行中のexample-podのエフェメラルコンテナを更新するには、次のコマンドを実行します。

kubectl replace --raw /api/v1/namespaces/default/pods/example-pod/ephemeralcontainers -f ec.json

このコマンドを実行すると、新しいエフェメラルコンテナのリストが返されます。

{
   "kind":"EphemeralContainers",
   "apiVersion":"v1",
   "metadata":{
      "name":"example-pod",
      "namespace":"default",
      "selfLink":"/api/v1/namespaces/default/pods/example-pod/ephemeralcontainers",
      "uid":"a14a6d9b-62f2-4119-9d8e-e2ed6bc3a47c",
      "resourceVersion":"15886",
      "creationTimestamp":"2019-08-29T06:41:42Z"
   },
   "ephemeralContainers":[
      {
         "name":"debugger",
         "image":"busybox",
         "command":[
            "sh"
         ],
         "resources":{

         },
         "terminationMessagePolicy":"File",
         "imagePullPolicy":"IfNotPresent",
         "stdin":true,
         "tty":true
      }
   ]
}

新しく作成されたエフェメラルコンテナの状態を確認するには、kubectl describeを使用します。

kubectl describe pod example-pod
...
Ephemeral Containers:
  debugger:
    Container ID:  docker://cf81908f149e7e9213d3c3644eda55c72efaff67652a2685c1146f0ce151e80f
    Image:         busybox
    Image ID:      docker-pullable://busybox@sha256:9f1003c480699be56815db0f8146ad2e22efea85129b5b5983d0e0fb52d9ab70
    Port:          <none>
    Host Port:     <none>
    Command:
      sh
    State:          Running
      Started:      Thu, 29 Aug 2019 06:42:21 +0000
    Ready:          False
    Restart Count:  0
    Environment:    <none>
    Mounts:         <none>
...

新しいエフェメラルコンテナとやりとりをするには、他のコンテナと同じように、kubectl attachkubectl execkubectl logsなどのコマンドが利用できます。例えば、次のようなコマンドが実行できます。

kubectl attach -it example-pod -c debugger

3.4.2 - ワークロードリソース

3.4.2.1 - Deployment

DeploymentPodReplicaSetの宣言的なアップデート機能を提供します。

Deploymentにおいて 理想的な状態 を記述すると、Deploymentコントローラーは指定された頻度で現在の状態を理想的な状態に変更します。Deploymentを定義することによって、新しいReplicaSetを作成したり、既存のDeploymentを削除して新しいDeploymentで全てのリソースを適用できます。

ユースケース

以下の項目はDeploymentの典型的なユースケースです。

  • ReplicaSetをロールアウトするためにDeploymentの作成を行う: ReplicaSetはバックグラウンドでPodを作成します。Podの作成が完了したかどうかは、ロールアウトのステータスを確認してください。
  • DeploymentのPodTemplateSpecを更新することによりPodの新しい状態を宣言する: 新しいReplicaSetが作成され、Deploymentは指定された頻度で古いReplicaSetから新しいReplicaSetへのPodの移行を管理します。新しいReplicaSetはDeploymentのリビジョンを更新します。
  • Deploymentの現在の状態が不安定な場合、Deploymentのロールバックをする: ロールバックによる各更新作業は、Deploymentのリビジョンを更新します。
  • より多くの負荷をさばけるように、Deploymentをスケールアップする。
  • PodTemplateSpecに対する複数の修正を適用するためにDeploymentを停止(Pause)し、それを再開して新しいロールアウトを開始します。
  • Deploymentのステータス をロールアウトが失敗したサインとして利用する。
  • 今後必要としない古いReplicaSetのクリーンアップ

Deploymentの作成

以下はDeploymentの例です。これはnginxPodのレプリカを3つ持つReplicaSetを作成します。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

この例では、

  • .metadata.nameフィールドで指定されたnginx-deploymentという名前のDeploymentが作成されます。

  • このDeploymentは.spec.replicasフィールドで指定された通り、3つのレプリカPodを作成します。

  • .spec.selectorフィールドは、Deploymentが管理するPodのラベルを定義します。ここでは、Podテンプレートにて定義されたラベル(app: nginx)を選択しています。しかし、PodTemplate自体がそのルールを満たす限り、さらに洗練された方法でセレクターを指定することができます。

  • templateフィールドは、以下のサブフィールドを持ちます。:

    • Podは.metadata.labelsフィールドによって指定されたapp: nginxというラベルがつけられます。
    • PodTemplate、または.template.specフィールドは、Podがnginxという名前でDocker Hubにあるnginxのバージョン1.14.2が動くコンテナを1つ動かすことを示します。
    • 1つのコンテナを作成し、.spec.template.spec.containers[0].nameフィールドを使ってnginxという名前をつけます。

作成を始める前に、Kubernetesクラスターが稼働していることを確認してください。 上記のDeploymentを作成するためには以下のステップにしたがってください:

  1. 以下のコマンドを実行してDeploymentを作成してください。
kubectl apply -f https://k8s.io/examples/controllers/nginx-deployment.yaml
  1. Deploymentが作成されたことを確認するために、kubectl get deploymentsを実行してください。

Deploymentがまだ作成中の場合、コマンドの実行結果は以下のとおりです。

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   0/3     0            0           1s

クラスターにてDeploymentを調査するとき、以下のフィールドが出力されます。

  • NAMEは、クラスター内にあるDeploymentの名前一覧です。
  • READYは、ユーザーが使用できるアプリケーションのレプリカの数です。使用可能な数/理想的な数の形式で表示されます。
  • UP-TO-DATEは、理想的な状態を満たすためにアップデートが完了したレプリカの数です。
  • AVAILABLEは、ユーザーが利用可能なレプリカの数です。
  • AGEは、アプリケーションが稼働してからの時間です。

.spec.replicasフィールドの値によると、理想的なレプリカ数は3であることがわかります。

  1. Deploymentのロールアウトステータスを確認するために、kubectl rollout status deployment.v1.apps/nginx-deploymentを実行してください。

コマンドの