はじめに
このセクションではKubernetesをセットアップして動かすための複数のやり方について説明します。
Kubernetesをインストールする際には、メンテナンスの容易さ、セキュリティ、制御、利用可能なリソース、クラスターの運用および管理に必要な専門知識に基づいてインストレーションタイプを選んでください。
Kuerbetesクラスターをローカルマシン、クラウド、データセンターにデプロイするために、Kubernetesをダウンロードできます。
kube-apiserverやkube-proxyのようないくつかのKubernetesのコンポーネントも、コンテナイメージとしてクラスター内にデプロイできます。
可能であればコンテナイメージとしてKubernetesのコンポーネントを実行し、それらのコンポーネントをKubernetesで管理するようにすることを推奨します。
コンテナを実行するコンポーネント(特にkubelet)は、このカテゴリーには含まれません。
Kubernetesクラスターを自分で管理するのを望まないなら、認定プラットフォームをはじめとする、マネージドのサービスを選択することもできます。
複数のクラウドやベアメタル環境にまたがった、その他の標準あるいはカスタムのソリューションもあります。
環境について学ぶ
Kubernetesについて学んでいる場合、Kubernetesコミュニティにサポートされているツールや、Kubernetesクラスターをローカルマシンにセットアップするエコシステム内のツールを使いましょう。
ツールのインストールを参照してください。
プロダクション環境
プロダクション環境用のソリューションを評価する際には、Kubernetesクラスター(または抽象概念)の運用においてどの部分を自分で管理し、どの部分をプロバイダーに任せるのかを考慮してください。
自分で管理するクラスターであれば、Kubernetesをデプロイするための公式にサポートされているツールはkubeadmです。
次の項目
Kubernetesは、そのコントロールプレーンがLinux上で実行されるよう設計されています。
クラスター内では、Linux上でも、Windowsを含めた別のオペレーティングシステム上でも、アプリケーションを実行できます。
1 - リリースノートおよびバージョンスキュー
1.1 - Kubernetesバージョンとバージョンスキューサポートポリシー
このドキュメントでは、さまざまなKubernetesコンポーネント間でサポートされる最大のバージョンの差異(バージョンスキュー)について説明します。特定のクラスターデプロイツールは、バージョンの差異に追加の制限を加える場合があります。
サポートされるバージョン
Kubernetesのバージョンはx.y.zの形式で表現され、xはメジャーバージョン、yはマイナーバージョン、zはパッチバージョンを指します。これはセマンティック バージョニングに従っています。詳細は、Kubernetesのリリースバージョニングを参照してください。
Kubernetesプロジェクトでは、最新の3つのマイナーリリースについてリリースブランチを管理しています (1.29, 1.28, 1.27)。
セキュリティフィックスを含む適用可能な修正は、重大度や実行可能性によってはこれら3つのリリースブランチにバックポートされることもあります。パッチリリースは、これらのブランチから 定期的に 切り出され、必要に応じて追加の緊急リリースも行われます。
リリースマネージャーグループがこれを決定しています。
詳細は、Kubernetesパッチリリースページを参照してください。
サポートされるバージョンの差異
kube-apiserver
高可用性 (HA) クラスターでは、最新および最古のkube-apiserver
インスタンスがそれぞれ1つのマイナーバージョン内でなければなりません。
例:
- 最新の
kube-apiserver
が1.29であるとします
- ほかの
kube-apiserver
インスタンスは1.29および1.28がサポートされます
kubelet
kubelet
はkube-apiserver
より新しいものであってはならず、2つの古いマイナーバージョンまで有効です。
例:
kube-apiserver
が1.29であるとします
kubelet
は1.29、1.28および1.27がサポートされます
備考: HAクラスター内のkube-apiserver
間にバージョンの差異がある場合、有効なkubelet
のバージョンは少なくなります。
例:
kube-apiserver
インスタンスが1.29および1.12であるとします
kubelet
は1.28および1.27がサポートされます(1.29はバージョン1.28のkube-apiserver
よりも新しくなるためサポートされません)
kube-controller-manager、kube-scheduler、およびcloud-controller-manager
kube-controller-manager
、kube-scheduler
およびcloud-controller-manager
は、通信するkube-apiserver
インスタンスよりも新しいバージョンであってはなりません。kube-apiserver
のマイナーバージョンと一致することが期待されますが、1つ古いマイナーバージョンでも可能です(ライブアップグレードを可能にするため)。
例:
kube-apiserver
が1.29であるとします
kube-controller-manager
、kube-scheduler
およびcloud-controller-manager
は1.29および1.28がサポートされます
備考: HAクラスター内のkube-apiserver
間にバージョンの差異があり、これらのコンポーネントがクラスター内のいずれかのkube-apiserver
と通信する場合(たとえばロードバランサーを経由して)、コンポーネントの有効なバージョンは少なくなります。
例:
kube-apiserver
インスタンスが1.29および1.28であるとします
- いずれかの
kube-apiserver
インスタンスへ配信するロードバランサーと通信するkube-controller-manager
、kube-scheduler
およびcloud-controller-manager
は1.28がサポートされます(1.29はバージョン1.28のkube-apiserver
よりも新しくなるためサポートされません)
kubectl
kubectl
はkube-apiserver
の1つ以内のバージョン(古い、または新しいもの)をサポートします。
例:
kube-apiserver
が1.29であるとします
kubectl
は1.30、1.29および1.28がサポートされます
備考: HAクラスター内のkube-apiserver
間にバージョンの差異がある場合、有効なkubectl
バージョンは少なくなります。
例:
kube-apiserver
インスタンスが1.29および1.28であるとします
kubectl
は1.29および1.28がサポートされます(ほかのバージョンでは、あるkube-apiserver
コンポーネントからマイナーバージョンが2つ以上離れる可能性があります)
サポートされるコンポーネントのアップグレード順序
コンポーネント間でサポートされるバージョンの差異は、コンポーネントをアップグレードする順序に影響されます。このセクションでは、既存のクラスターをバージョン1.28から1.29 へ移行するために、コンポーネントをアップグレードする順序を説明します。
kube-apiserver
前提条件:
- シングルインスタンスのクラスターにおいて、既存の
kube-apiserver
インスタンスは1.28とします
- HAクラスターにおいて、既存の
kube-apiserver
は1.28または1.29 とします(最新と最古の間で、最大で1つのマイナーバージョンの差異となります)
- サーバーと通信する
kube-controller-manager
、kube-scheduler
およびcloud-controller-manager
はバージョン1.28とします(必ず既存のAPIサーバーのバージョンよりも新しいものでなく、かつ新しいAPIサーバーのバージョンの1つ以内のマイナーバージョンとなります)
- すべてのノードの
kubelet
インスタンスはバージョン1.28または1.27 とします(必ず既存のAPIサーバーよりも新しいバージョンでなく、かつ新しいAPIサーバーのバージョンの2つ以内のマイナーバージョンとなります)
- 登録されたAdmission webhookは、新しい
kube-apiserver
インスタンスが送信するこれらのデータを扱うことができます:
ValidatingWebhookConfiguration
およびMutatingWebhookConfiguration
オブジェクトは、1.29 で追加されたRESTリソースの新しいバージョンを含んで更新されます(または、v1.15から利用可能なmatchPolicy: Equivalent
オプションを使用してください)
- Webhookは送信されたRESTリソースの新しいバージョン、および1.29 のバージョンで追加された新しいフィールドを扱うことができます
kube-apiserver
を1.29 にアップグレードしてください。
備考: 非推奨APIおよび
APIの変更ガイドラインのプロジェクトポリシーにおいては、シングルインスタンスの場合でも
kube-apiserver
のアップグレードの際にマイナーバージョンをスキップしてはなりません。
kube-controller-manager、kube-scheduler、およびcloud-controller-manager
前提条件:
- これらのコンポーネントと通信する
kube-apiserver
インスタンスが1.29 であること(これらのコントロールプレーンコンポーネントが、クラスター内のkube-apiserver
インスタンスと通信できるHAクラスターでは、これらのコンポーネントをアップグレードする前にすべてのkube-apiserver
インスタンスをアップグレードしなければなりません)
kube-controller-manager
、kube-scheduler
およびcloud-controller-manager
を1.29 にアップグレードしてください。
kubelet
前提条件:
kubelet
と通信するkube-apiserver
が1.29 であること
必要に応じて、kubelet
インスタンスを1.29 にアップグレードしてください(1.28や1.27 のままにすることもできます)。
警告: kube-apiserver
と2つのマイナーバージョンのkubelet
インスタンスを使用してクラスターを実行させることは推奨されません:
- コントロールプレーンをアップグレードする前に、インスタンスを
kube-apiserver
の1つのマイナーバージョン内にアップグレードさせる必要があります
- メンテナンスされている3つのマイナーリリースよりも古いバージョンの
kubelet
を実行する可能性が高まります
kube-proxy
kube-proxy
のマイナーバージョンはノード上のkubelet
と同じマイナーバージョンでなければなりません
kube-proxy
はkube-apiserver
よりも新しいものであってはなりません
kube-proxy
のマイナーバージョンはkube-apiserver
のマイナーバージョンよりも2つ以上古いものでなければなりません
例:
kube-proxy
のバージョンが1.27の場合:
kubelet
のバージョンは1.27でなければなりません
kube-apiserver
のバージョンは1.27と1.29の間でなければなりません
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を起動し試してください。
-
Minikubeを起動し、クラスターを作成します:
出力はこのようになります:
Starting local Kubernetes cluster...
Running pre-create checks...
Creating machine...
Starting local Kubernetes cluster...
特定のKubernetesのバージョン、VM、コンテナランタイム上でクラスターを起動するための詳細は、クラスターの起動を参照してください。
-
kubectlを使用してクラスターと対話できるようになります。詳細はクラスターに触れてみようを参照してください。
単純なHTTPサーバーであるechoserver
という既存のイメージを使用して、Kubernetes Deploymentを作りましょう。そして--port
を使用して8080番ポートで公開しましょう。
kubectl create deployment hello-minikube --image=registry.k8s.io/echoserver:1.10
出力はこのようになります:
deployment.apps/hello-minikube created
-
hello-minikube
Deploymentに接続するために、Serviceとして公開します:
kubectl expose deployment hello-minikube --type=NodePort --port=8080
--type=NodePort
オプションで、Serviceのタイプを指定します。
出力はこのようになります:
service/hello-minikube exposed
-
hello-minikube
Podが起動開始されましたが、公開したService経由で接続する前にPodが起動完了になるまで待つ必要があります。
Podが稼働しているか確認します:
STATUS
にContainerCreating
と表示されている場合、Podはまだ作成中です:
NAME READY STATUS RESTARTS AGE
hello-minikube-3383150820-vctvh 0/1 ContainerCreating 0 3s
STATUS
にRunning
と表示されている場合、Podは稼働中です:
NAME READY STATUS RESTARTS AGE
hello-minikube-3383150820-vctvh 1/1 Running 0 13s
-
Serviceの詳細を確認するため、公開したServiceのURLを取得します:
minikube service hello-minikube --url
-
ローカル環境のクラスターについて詳細を確認するには、出力から得た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やクラスターをこれ以上稼働させない場合、削除する事ができます。
-
hello-minikube
Serviceを削除します:
kubectl delete services hello-minikube
出力はこのようになります:
service "hello-minikube" deleted
-
hello-minikube
Deploymentを削除します:
kubectl delete deployment hello-minikube
出力はこのようになります:
deployment.extensions "hello-minikube" deleted
-
ローカル環境のMinikubeクラスターを停止します:
出力はこのようになります:
Stopping "minikube"...
"minikube" stopped.
詳細はクラスターの停止を参照ください。
-
ローカルのMinikubeクラスターを削除します:
出力はこのようになります:
Deleting "minikube" ...
The "minikube" cluster has been deleted.
詳細はクラスターの削除を参照ください。
クラスターの管理
クラスターの起動
minikube start
コマンドを使用してクラスターを起動することができます。
このコマンドはシングルノードのKubernetesクラスターを実行する仮想マシンを作成・設定します。
また、このクラスターと通信するkubectlのインストールも設定します。
備考: もしWebプロキシーを通している場合、そのプロキシー情報をminikube start
コマンドに渡す必要があります:
https_proxy=<my proxy> minikube start --docker-env http_proxy=<my proxy> --docker-env https_proxy=<my proxy> --docker-env no_proxy=192.168.99.0/24
残念なことに、ただ環境変数を設定するだけではうまく動作しません。
Minikubeは"minikube"コンテキストも作成し、そのコンテキストをデフォルト設定としてkubectlに設定します。
あとでコンテキストを切り戻すには、このコマンドを実行してください: kubectl config use-context minikube
Kubernetesバージョンの指定
minikube start
コマンドに--kubernetes-version
文字列を追加することで、
MinikubeにKubernetesの特定のバージョンを指定することができます。
例えば、1.29.0のバージョンを実行するには以下を実行します:
minikube start --kubernetes-version 1.29.0
VMドライバーの指定
もしVMドライバーを変更したい場合は、--driver=<enter_driver_name>
フラグをminikube start
に設定してください。例えば、コマンドは以下のようになります。
minikube start --driver=<driver_name>
Minikubeは以下のドライバーをサポートしています:
備考: サポートされているドライバーとプラグインのインストールの詳細については
DRIVERSを参照してください。
注意: none
ドライバーを使用する場合、一部のKubernetesのコンポーネントは特権付きのコンテナとして稼働するため、Minikube環境外に副作用をもたらします。
この副作用から、none
ドライバーは、個人の作業環境では推奨されません。
コンテナランタイムの代替
下記のコンテナランタイム上で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デーモンの中に構築することができます。
備考: Dockerイメージに'latest'以外のタグを付け、そのタグを使用してイメージをプルしてください。イメージのバージョンを指定しなければAlways
のプルイメージポリシーにより:latest
と仮定され、もしデフォルトのDockerレジストリ(通常はDockerHub)にどのバージョンのDockerイメージもまだ存在しない場合には、ErrImagePull
になる恐れがあります。
Mac/LinuxのホストでDockerデーモンを操作できるようにするには、minikube docker-env
を実行します。
これにより、MinikubeのVM内のDockerデーモンと通信しているホストのMac/LinuxマシンのコマンドラインでDockerを使用できるようになります:
備考: CentOS 7では、Dockerが以下のエラーを出力することがあります:
Could not read CA certificate "/etc/docker/ca.pem": open /etc/docker/ca.pem: no such file or directory
修正方法としては、/etc/sysconfig/dockerを更新してMinikube環境の変更が確実に反映されるようにすることです:
< DOCKER_CERT_PATH=/etc/docker
---
> if [ -z "${DOCKER_CERT_PATH}" ]; then
> DOCKER_CERT_PATH=/etc/docker
> fi
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.LeaderElect
を true
に設定するには、このフラグを渡します: --extra-config=scheduler.LeaderElection.LeaderElect=true
apiserver
の AuthorizationMode
を RABC
に設定するには、このフラグを使います: --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を起動してアドレスを取得した後、シェルでこのコマンドを実行してください:
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によって異なります。
備考: ホストフォルダーの共有はKVMドライバーにはまだ実装されていません。
Driver |
OS |
HostFolder |
VM |
VirtualBox |
Linux |
/home |
/hosthome |
VirtualBox |
macOS |
/Users |
/Users |
VirtualBox |
Windows |
C://Users |
/c/Users |
VMware Fusion |
macOS |
/Users |
/mnt/hgfs/Users |
Xhyve |
macOS |
/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 - Kindを使用してKubernetesをインストールする
Kindは、Dockerコンテナをノードとして使用して、ローカルのKubernetesクラスターを実行するためのツールです。
インストール
Kindをインストールするを参照してください。
3 - プロダクション環境
3.1 - コンテナランタイム
クラスター内の各ノードがPodを実行できるようにするため、コンテナランタイムをインストールする必要があります。
このページでは、ノードをセットアップするための概要と関連する作業について説明します。
Kubernetes 1.29においては、Container Runtime Interface (CRI)に準拠したランタイムを使用する必要があります。
詳しくはサポートするCRIのバージョンをご覧ください。
このページではいくつかの一般的なコンテナランタイムをKubernetesで使用する方法の概要を説明します。
備考: v1.24以前のKubernetesリリースでは、 dockershim という名前のコンポーネントを使用したDocker Engineとの直接の統合が含まれていました。
この特別な直接統合は、もはやKubernetesの一部ではありません(この削除はv1.20リリースの一部として発表されています)。
dockershimの廃止がどのような影響を与えるかについては、dockershim削除の影響範囲を確認する をご覧ください。
dockershimからの移行について知りたい場合、dockershimからの移行を参照してください。
v1.29以外のバージョンのKubernetesを実行している場合、そのバージョンのドキュメントを確認してください。
インストールと設定の必須要件
以下の手順では、全コンテナランタイムに共通の設定をLinux上のKubernetesノードに適用します。
特定の設定が不要であることが分かっている場合、手順をスキップして頂いて構いません。
詳細については、Network Plugin Requirementsまたは、特定のコンテナランタイムのドキュメントを参照してください。
IPv4フォワーディングを有効化し、iptablesからブリッジされたトラフィックを見えるようにする
以下のコマンドを実行します。
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# この構成に必要なカーネルパラメーター、再起動しても値は永続します
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# 再起動せずにカーネルパラメーターを適用
sudo sysctl --system
以下のコマンドを実行してbr_netfilter
とoverlay
モジュールが読み込まれていることを確認してください。
lsmod | grep br_netfilter
lsmod | grep overlay
以下のコマンドを実行して、net.bridge.bridge-nf-call-iptables
、net.bridge.bridge-nf-call-ip6tables
、net.ipv4.ip_forward
カーネルパラメーターが1に設定されていることを確認します。
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
cgroupドライバー
Linuxでは、プロセスに割り当てられるリソースを制約するためにcgroupが使用されます。
kubeletと基盤となるコンテナランタイムは、コンテナのリソース管理を実施し、CPU/メモリーの要求や制限などのリソースを設定するため、cgroupとインターフェースする必要があります。
cgroupとインターフェースするために、kubeletおよびコンテナランタイムはcgroupドライバーを使用する必要があります。
この際、kubeletとコンテナランタイムが同一のcgroupドライバーを使用し、同一の設定を適用することが不可欠となります。
利用可能なcgroupドライバーは以下の2つです。
cgroupfsドライバー
cgroupfs
ドライバーは、kubeletのデフォルトのcgroupドライバーです。
cgroupfs
ドライバーを使用すると、kubeletとコンテナランタイムはcgroupファイルシステムと直接インターフェイスし、cgroupを設定します。
systemdがinitシステムである場合、cgroupfs
ドライバーは推奨されません。
なぜなら、systemdはシステム上のcgroupマネージャーが単一であると想定しているからです。
また、cgroup v2を使用している場合は、cgroupfs
の代わりにsystemd
cgroupドライバーを使用してください。
systemd cgroupドライバー
Linuxディストリビューションのinitシステムにsystemdが選択されている場合、
initプロセスはルートcgroupを生成・消費し、cgroupマネージャーとして動作します。
systemdはcgroupと密接に連携しており、systemdユニットごとにcgroupを割り当てます。
その結果、initシステムにsystemd
を使用した状態でcgroupfs
ドライバーを使用すると、
システムには2つの異なるcgroupマネージャーが存在することになります。
2つのcgroupマネージャーが存在することで、システムで利用可能なリソースおよび使用中のリソースに、2つの異なる見え方が与えられることになります。
特定の場合において、kubeletとコンテナランタイムにcgroupfs
を、残りのプロセスにsystemd
を使用するように設定されたノードが高負荷時に不安定になることがあります。
このような不安定性を緩和するためのアプローチは、systemdがinitシステムに採用されている場合にkubeletとコンテナランタイムのcgroupドライバーとしてsystemd
を使用することです。
cgroupドライバーにsystemd
を設定するには、以下のようにKubeletConfiguration
のcgroupDriver
オプションを編集してsystemd
を設定します。
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
...
cgroupDriver: systemd
kubelet用のcgroupドライバーとしてsystemd
を設定する場合、コンテナランタイムのcgroupドライバーにもsystemd
を設定する必要があります。
具体的な手順については、以下のリンクなどの、お使いのコンテナランタイムのドキュメントを参照してください。
注意: クラスターに参加したノードのcgroupドライバーを変更するのはデリケートな操作です。
kubeletが特定のcgroupドライバーのセマンティクスを使用してPodを作成していた場合、
コンテナランタイムを別のcgroupドライバーに変更すると、そのような既存のPodに対してPodサンドボックスを再作成しようとしたときにエラーが発生することがあります。
kubeletを再起動してもこのようなエラーは解決しない可能性があります。
もしあなたが適切な自動化の手段を持っているのであれば、更新された設定を使用してノードを別のノードに置き換えるか、自動化を使用して再インストールを行ってください。
kubeadmで管理されたクラスターでのsystemd
ドライバーへの移行
既存のkubeadm管理クラスターでsystemd
cgroupドライバーに移行したい場合は、cgroupドライバーの設定に従ってください。
サポートするCRIのバージョン
コンテナランタイムは、Container Runtime Interfaceのv1alpha2以上をサポートする必要があります。
Kubernetes 1.29は、デフォルトでCRI APIのv1を使用します。
コンテナランタイムがv1 APIをサポートしていない場合、kubeletは代わりに(非推奨の)v1alpha2 APIにフォールバックします。
コンテナランタイム
備考:
このセクションでは、Kubernetesが必要とする機能を提供するサードパーティープロジェクトにリンクしています。これらのプロジェクトはアルファベット順に記載されていて、Kubernetesプロジェクトの作者は責任を持ちません。このリストにプロジェクトを追加するには、変更を提出する前に
content guideをお読みください。
詳細はこちら。
containerd
このセクションでは、CRIランタイムとしてcontainerdを使用するために必要な手順の概要を説明します。
以下のコマンドを使用して、システムにcontainerdをインストールします:
まずはcontainerdの使用を開始するの指示に従ってください。有効なconfig.toml
設定ファイルを作成したら、このステップに戻ります。
このファイルはパス/etc/containerd/config.toml
にあります。
このファイルはC:\Program Files\containerd\config.toml
にあります。
Linuxでは、containerd用のデフォルトのCRIソケットは/run/containerd/containerd.sock
です。
Windowsでは、デフォルトのCRIエンドポイントはnpipe://./pipe/containerd-containerd
です。
systemd
cgroupドライバーを構成する
/etc/containerd/config.toml
内でrunc
がsystemd
cgroupドライバーを使うようにするには、次のように設定します。
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
...
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
cgroup v2を使用する場合はsystemd
cgroupドライバーの利用を推奨します。
備考: パッケージ(RPMや.deb
など)からcontainerdをインストールした場合、
CRI統合プラグインがデフォルトで無効になっていることがあります。
Kubernetesでcontainerdを使用するには、CRIサポートを有効にする必要があります。
/etc/containerd/config.toml
内のdisabled_plugins
リストにcri
が含まれていないことを確認してください。
このファイルを変更した場合、containerd
も再起動してください。
クラスターの初回構築後、またはCNIをインストールした後にコンテナのクラッシュループが発生した場合、
パッケージと共に提供されるcontainerdの設定に互換性のないパラメーターが含まれている可能性があります。
get-started.mdにあるように、
containerd config default > /etc/containerd/config.toml
でcontainerdの設定をリセットした上で、
上記の設定パラメーターを使用することを検討してください。
この変更を適用した場合、必ずcontainerdを再起動してください。
sudo systemctl restart containerd
kubeadmを使用している場合、手動でkubelet cgroupドライバーの設定を行ってください。
サンドボックス(pause)イメージの上書き
containerdの設定で以下の設定をすることで、サンドボックスのイメージを上書きすることができます。
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.k8s.io/pause:3.2"
この場合も、設定ファイルの更新後にsystemctl restart containerd
を実行してcontainerd
も再起動する必要があるでしょう。
CRI-O
本セクションでは、コンテナランタイムとしてCRI-Oをインストールするために必要な手順を説明します。
CRI-Oをインストールするには、CRI-Oのインストール手順に従ってください。
cgroupドライバー
CRI-Oはデフォルトでsystemd cgroupドライバーを使用し、おそらく問題なく動作します。
cgroupfs
cgroupドライバーに切り替えるには、/etc/crio/crio.conf
を編集するか、
/etc/crio/crio.conf.d/02-cgroup-manager.conf
にドロップイン設定ファイルを置いて、以下のような設定を記述してください。
[crio.runtime]
conmon_cgroup = "pod"
cgroup_manager = "cgroupfs"
上記でconmon_cgroup
も変更されていることに注意してください。
CRI-Oでcgroupfs
を使用する場合、ここにはpod
という値を設定する必要があります。
一般に、kubeletのcgroupドライバーの設定(通常はkubeadmによって行われます)とCRI-Oの設定は一致させる必要があります。
CRI-Oの場合、CRIソケットはデフォルトで/var/run/crio/crio.sock
となります。
サンドボックス(pause)イメージの上書き
CRI-Oの設定において、以下の値を設定することができます。
[crio.image]
pause_image="registry.k8s.io/pause:3.6"
このオプションはライブ設定リロードによる変更の適用に対応しています。
systemctl reload crio
またはcrio
プロセスにSIGHUP
を送信することで変更を適用できます。
Docker Engine
備考: この手順では、Docker EngineとKubernetesを統合するために
cri-dockerd
アダプターを使用することを想定しています。
-
各ノードに、使用しているLinuxディストリビューション用のDockerをDocker Engineのインストールに従ってインストールします。
-
cri-dockerd
をリポジトリ内の指示に従ってインストールします。
cri-dockerd
の場合、CRIソケットはデフォルトで/run/cri-dockerd.sock
になります。
Mirantis Container Runtime
Mirantis Container Runtime(MCR)は、
以前はDocker Enterprise Editionとして知られていた、商業的に利用可能なコンテナランタイムです。
MCRに含まれるオープンソースのcri-dockerd
コンポーネントを使用することで、
Mirantis Container RuntimeをKubernetesで使用することができます。
Mirantis Container Runtimeのインストール方法について知るには、MCRデプロイガイドを参照してください。
CRIソケットのパスを見つけるには、systemdのcri-docker.socket
という名前のユニットを確認してください。
サンドボックス(pause)イメージを上書きする
cri-dockerd
アダプターは、Podインフラコンテナ("pause image")として使用するコンテナイメージを指定するためのコマンドライン引数を受け付けます。
使用するコマンドライン引数は --pod-infra-container-image
です。
次の項目
コンテナランタイムに加えて、クラスターには動作するネットワークプラグインが必要です。
3.2 - Kubernetesをデプロイツールでインストールする
3.2.1 - kubeadmを使ってクラスターを構築する
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クラスターのアドレスが適切なアダプターを経由するように設定することをお勧めします。
必須ポートの確認
Kubernetesのコンポーネントが互いに通信するためには、これらの必要なポートが開いている必要があります。
netcatなどのツールを使用することで、下記のようにポートが開いているかどうかを確認することが可能です。
使用するPodネットワークプラグインによっては、特定のポートを開く必要がある場合もあります。
これらは各Podネットワークプラグインによって異なるため、どのようなポートが必要かについては、プラグインのドキュメントを参照してください。
ランタイムのインストール
Podのコンテナを実行するために、Kubernetesはコンテナランタイムを使用します。
デフォルトでは、Kubernetesは選択されたコンテナランタイムと通信するためにContainer Runtime Interface (CRI)を使用します。
ランタイムを指定しない場合、kubeadmはよく知られたUnixドメインソケットのリストをスキャンすることで、インストールされたコンテナランタイムの検出を試みます。
次の表がコンテナランタイムと関連するソケットのパスリストです。
コンテナランタイムとソケットパス
ランタイム |
Unixドメインソケットのパス |
Docker |
/var/run/docker.sock |
containerd |
/run/containerd/containerd.sock |
CRI-O |
/var/run/crio/crio.sock |
Dockerとcontainerdの両方が同時に検出された場合、Dockerが優先されます。Docker 18.09にはcontainerdが同梱されており、両方が検出可能であるため、この仕様が必要です。他の2つ以上のランタイムが検出された場合、kubeadmは適切なエラーメッセージで終了します。
kubeletは、組み込まれたdockershim
CRIを通してDockerと連携します。
詳細は、コンテナランタイムを参照してください。
デフォルトでは、kubeadmはDockerをコンテナランタイムとして使用します。
kubeletは、組み込まれたdockershim
CRIを通してDockerと連携します。
詳細は、コンテナランタイムを参照してください。
kubeadm、kubelet、kubectlのインストール
以下のパッケージをマシン上にインストールしてください
-
kubeadm
: クラスターを起動するコマンドです。
-
kubelet
: クラスター内のすべてのマシンで実行されるコンポーネントです。
Podやコンテナの起動などを行います。
-
kubectl
: クラスターにアクセスするためのコマンドラインツールです。
kubeadmはkubelet
やkubectl
をインストールまたは管理しないため、kubeadmにインストールするKubernetesコントロールプレーンのバージョンと一致させる必要があります。そうしないと、予期しないバグのある動作につながる可能性のあるバージョン差異(version skew)が発生するリスクがあります。ただし、kubeletとコントロールプレーン間のマイナーバージョン差異(minor version skew)は_1つ_サポートされていますが、kubeletバージョンがAPIサーバーのバージョンを超えることはできません。たとえば、1.7.0を実行するkubeletは1.8.0 APIサーバーと完全に互換性がありますが、その逆はできません。
kubectl
のインストールに関する詳細情報は、kubectlのインストールおよびセットアップを参照してください。
警告: これらの手順はシステムアップグレードによるすべてのKubernetesパッケージの更新を除きます。これはkubeadmとKubernetesが
アップグレードにおける特別な注意を必要とするからです。
バージョン差異(version skew)に関しては下記を参照してください。
-
apt
のパッケージ一覧を更新し、Kubernetesのapt
リポジトリを利用するのに必要なパッケージをインストールします:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
-
Google Cloudの公開鍵をダウンロードします:
curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
-
Kubernetesのapt
リポジトリを追加します:
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
-
apt
のパッケージ一覧を更新し、kubelet、kubeadm、kubectlをインストールします。そしてバージョンを固定します:
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
備考: Debian 12やUbuntu 22.04より古いリリースでは、/etc/apt/keyrings
はデフォルトでは存在しません。
必要に応じてこのディレクトリを作成し、誰でも読み取り可能で、管理者のみ書き込み可能にすることができます。
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
# SELinuxをpermissiveモードに設定する(効果的に無効化する)
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable --now kubelet
Note:
setenforce 0
およびsed ...
を実行することによりSELinuxをpermissiveモードに設定し、効果的に無効化できます。
これはコンテナがホストのファイルシステムにアクセスするために必要です。例えば、Podのネットワークに必要とされます。
kubeletにおけるSELinuxのサポートが改善されるまでは、これを実行しなければなりません。
CNIプラグインをインストールする(ほとんどのPodのネットワークに必要です):
CNI_VERSION="v0.8.2"
ARCH="amd64"
mkdir -p /opt/cni/bin
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz
crictlをインストールする (kubeadm / Kubelet Container Runtime Interface (CRI)に必要です)
CRICTL_VERSION="v1.22.0"
ARCH="amd64"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz
kubeadm
、kubelet
、kubectl
をインストールしkubelet
をsystemd serviceに登録します:
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
ARCH="amd64"
mkdir -p /opt/bin
cd /opt/bin
curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet,kubectl}
chmod +x {kubeadm,kubelet,kubectl}
curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/kubelet.service" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service
mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/kubernetes/${RELEASE}/build/debs/10-kubeadm.conf" | sed "s:/usr/bin:/opt/bin:g" > /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
kubelet
を有効化し起動します:
systemctl enable --now kubelet
kubeadmが何をすべきか指示するまで、kubeletはクラッシュループで数秒ごとに再起動します。
コントロールプレーンノードのkubeletによって使用されるcgroupドライバーの設定
Dockerを使用した場合、kubeadmは自動的にkubelet向けのcgroupドライバーを検出し、それを実行時に/var/lib/kubelet/kubeadm-flags.env
ファイルに設定します。
もしあなたが異なるCRIを使用している場合、/etc/default/kubelet
(CentOS、RHEL、Fedoraでは/etc/sysconfig/kubelet
)ファイル内のcgroup-driver
の値を以下のように変更する必要があります。
KUBELET_EXTRA_ARGS=--cgroup-driver=<value>
このファイルは、kubeletの追加のユーザー定義引数を取得するために、kubeadm init
およびkubeadm join
によって使用されます。
CRIのcgroupドライバーがcgroupfs
でない場合にのみそれを行う必要があることに注意してください。なぜなら、これはすでにkubeletのデフォルト値であるためです。
kubeletをリスタートする方法:
systemctl daemon-reload
systemctl restart kubelet
CRI-Oやcontainerdといった他のコンテナランタイムのcgroup driverは実行中に自動的に検出されます。
トラブルシュート
kubeadmで問題が発生した場合は、トラブルシューティングを参照してください。
次の項目
3.2.1.2 - kubeadmのトラブルシューティング
どのプログラムでもそうですが、kubeadmのインストールや実行でエラーが発生することがあります。このページでは、一般的な失敗例をいくつか挙げ、問題を理解して解決するための手順を示しています。
本ページに問題が記載されていない場合は、以下の手順を行ってください:
RBACがないため、v1.18ノードをv1.17クラスターに結合できない
v1.18では、同名のノードが既に存在する場合にクラスター内のノードに参加しないようにする機能を追加しました。これには、ブートストラップトークンユーザがNodeオブジェクトをGETできるようにRBACを追加する必要がありました。
しかし、これによりv1.18のkubeadm join
がkubeadm v1.17で作成したクラスターに参加できないという問題が発生します。
この問題を回避するには、次の2つの方法があります。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubeadm:get-nodes
rules:
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeadm:get-nodes
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: kubeadm:get-nodes
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:bootstrappers:kubeadm:default-node-token
インストール中にebtables
もしくは他の似たような実行プログラムが見つからない
kubeadm init
の実行中に以下のような警告が表示された場合は、以降に記載するやり方を行ってください。
[preflight] WARNING: ebtables not found in system path
[preflight] WARNING: ethtool not found in system path
このような場合、ノード上にebtables
, ethtool
などの実行ファイルがない可能性があります。これらをインストールするには、以下のコマンドを実行します。
- Ubuntu/Debianユーザーは、
apt install ebtables ethtool
を実行してください。
- CentOS/Fedoraユーザーは、
yum install ebtables ethtool
を実行してください。
インストール中にkubeadmがコントロールプレーンを待ち続けて止まる
以下のを出力した後にkubeadm init
が止まる場合は、kubeadm init
を実行してください:
[apiclient] Created API client, waiting for the control plane to become ready
これはいくつかの問題が原因となっている可能性があります。最も一般的なのは:
-
ネットワーク接続の問題が挙げられます。続行する前に、お使いのマシンがネットワークに完全に接続されていることを確認してください。
-
kubeletのデフォルトのcgroupドライバの設定がDockerで使用されているものとは異なっている場合も考えられます。
システムログファイル(例: /var/log/message
)をチェックするか、journalctl -u kubelet
の出力を調べてください:
error: failed to run Kubelet: failed to create kubelet:
misconfiguration: kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"
以上のようなエラーが現れていた場合、cgroupドライバの問題を解決するには、以下の2つの方法があります:
-
ここの指示に従ってDockerを再度インストールします。
-
Dockerのcgroupドライバに合わせてkubeletの設定を手動で変更します。その際は、マスターノード上でkubeletが使用するcgroupドライバを設定するを参照してください。
- control plane Dockerコンテナがクラッシュループしたり、ハングしたりしています。これは
docker ps
を実行し、docker logs
を実行して各コンテナを調査することで確認できます。
管理コンテナを削除する時にkubeadmが止まる
Dockerが停止して、Kubernetesで管理されているコンテナを削除しないと、以下のようなことが起こる可能性があります:
sudo kubeadm reset
[preflight] Running pre-flight checks
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Removing kubernetes-managed containers
(block)
考えられる解決策は、Dockerサービスを再起動してからkubeadm reset
を再実行することです:
sudo systemctl restart docker.service
sudo kubeadm reset
dockerのログを調べるのも有効な場合があります:
Podの状態がRunContainerError
、CrashLoopBackOff
、またはError
となる
kubeadm init
の直後には、これらの状態ではPodは存在しないはずです。
kubeadm init
の 直後 にこれらの状態のいずれかにPodがある場合は、kubeadmのリポジトリにIssueを立ててください。ネットワークソリューションをデプロイするまではcoredns
(またはkube-dns
)はPending
状態でなければなりません。
- ネットワークソリューションをデプロイしても
coredns
(またはkube-dns
)に何も起こらない場合にRunContainerError、
CrashLoopBackOff、
Error`の状態でPodが表示された場合は、インストールしたPodネットワークソリューションが壊れている可能性が高いです。より多くのRBACの特権を付与するか、新しいバージョンを使用する必要があるかもしれません。PodネットワークプロバイダのイシュートラッカーにIssueを出して、そこで問題をトリアージしてください。
- 1.12.1よりも古いバージョンのDockerをインストールした場合は、
systemd
でdockerd
を起動する際にMountFlags=slave
オプションを削除してdocker
を再起動してください。マウントフラグは/usr/lib/systemd/system/docker.service
で確認できます。MountFlagsはKubernetesがマウントしたボリュームに干渉し、PodsをCrashLoopBackOff
状態にすることがあります。このエラーは、Kubernetesがvar/run/secrets/kubernetes.io/serviceaccount
ファイルを見つけられない場合に発生します。
coredns
(もしくはkube-dns
)がPending
状態でスタックする
kubeadmはネットワークプロバイダに依存しないため、管理者は選択したPodネットワークソリューションをインストールをする必要があります。CoreDNSを完全にデプロイする前にPodネットワークをインストールする必要があります。したがって、ネットワークがセットアップされる前の Pending
状態になります。
HostPort
サービスが動かない
HostPort
とHostIP
の機能は、ご使用のPodネットワークプロバイダによって利用可能です。Podネットワークソリューションの作者に連絡して、HostPort
とHostIP
機能が利用可能かどうかを確認してください。
Calico、Canal、FlannelのCNIプロバイダは、HostPortをサポートしていることが確認されています。
詳細については、[CNI portmap documentation] (https://github.com/containernetworking/plugins/blob/master/plugins/meta/portmap/README.md) を参照してください。
ネットワークプロバイダが portmap CNI プラグインをサポートしていない場合は、NodePortサービスを使用するか、HostNetwork=true
を使用してください。
サービスIP経由でPodにアクセスすることができない
-
多くのネットワークアドオンは、PodがサービスIPを介して自分自身にアクセスできるようにするヘアピンモードを有効にしていません。これはCNIに関連する問題です。ヘアピンモードのサポート状況については、ネットワークアドオンプロバイダにお問い合わせください。
-
VirtualBoxを使用している場合(直接またはVagrant経由)は、hostname -i
がルーティング可能なIPアドレスを返すことを確認する必要があります。デフォルトでは、最初のインターフェースはルーティング可能でないホスト専用のネットワークに接続されています。これを回避するには/etc/hosts
を修正する必要があります。例としてはこのVagrantfileを参照してください。
TLS証明書のエラー
以下のエラーは、証明書の不一致の可能性を示しています。
# kubectl get pods
Unable to connect to the server: x509: certificate signed by unknown authority (possibly because of "crypto/rsa: verification error" while trying to verify candidate authority certificate "kubernetes")
-
HOME/.kube/config
ファイルに有効な証明書が含まれていることを確認し、必要に応じて証明書を再生成します。kubeconfigファイル内の証明書はbase64でエンコードされています。証明書をデコードするにはbase64 --decode
コマンドを、証明書情報を表示するにはopenssl x509 -text -noout
コマンドを用いてください。
-
環境変数KUBECONFIG
の設定を解除するには以下のコマンドを実行するか:
設定をデフォルトのKUBECONFIG
の場所に設定します:
export KUBECONFIG=/etc/kubernetes/admin.conf
-
もう一つの回避策は、既存のkubeconfig
を"admin"ユーザに上書きすることです:
mv $HOME/.kube $HOME/.kube.bak
mkdir $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Vagrant内でPodネットワークとしてflannelを使用する時のデフォルトNIC
以下のエラーは、Podネットワークに何か問題があったことを示している可能性を示しています:
Error from server (NotFound): the server could not find the requested resource
-
Vagrant内のPodネットワークとしてflannelを使用している場合は、flannelのデフォルトのインターフェース名を指定する必要があります。
Vagrantは通常、2つのインターフェースを全てのVMに割り当てます。1つ目は全てのホストにIPアドレス10.0.2.15
が割り当てられており、NATされる外部トラフィックのためのものです。
これは、ホストの最初のインターフェイスをデフォルトにしているflannelの問題につながるかもしれません。これは、すべてのホストが同じパブリックIPアドレスを持っていると考えます。これを防ぐには、2番目のインターフェイスが選択されるように --iface eth1
フラグをflannelに渡してください。
公開されていないIPがコンテナに使われている
状況によっては、kubectl logs
やkubectl run
コマンドが以下のようなエラーを返すことがあります:
Error from server: Get https://10.19.0.41:10250/containerLogs/default/mysql-ddc65b868-glc5m/mysql: dial tcp 10.19.0.41:10250: getsockopt: no route to host
-
これには、おそらくマシンプロバイダのポリシーによって、一見同じサブネット上の他のIPと通信できないIPをKubernetesが使用している可能性があります。
-
DigitalOceanはパブリックIPとプライベートIPをeth0
に割り当てていますが、kubelet
はパブリックIPではなく、ノードのInternalIP
として後者を選択します。
ifconfig
ではエイリアスIPアドレスが表示されないため、ifconfig
の代わりにip addr show
を使用してこのシナリオをチェックしてください。あるいは、DigitalOcean専用のAPIエンドポイントを使用して、ドロップレットからアンカーIPを取得することもできます:
curl http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address
回避策としては、--node-ip
を使ってどのIPを使うかをkubelet
に伝えることです。DigitalOceanを使用する場合、オプションのプライベートネットワークを使用したい場合は、パブリックIP(eth0
に割り当てられている)かプライベートIP(eth1
に割り当てられている)のどちらかを指定します。これにはkubeadm NodeRegistrationOptions
構造体の KubeletExtraArgs
セクション が利用できます。
kubelet
を再起動してください:
systemctl daemon-reload
systemctl restart kubelet
coredns
のPodがCrashLoopBackOff
もしくはError
状態になる
SELinuxを実行しているノードで古いバージョンのDockerを使用している場合、coredns
Podが起動しないということが起きるかもしれません。この問題を解決するには、以下のオプションのいずれかを試してみてください:
kubectl -n kube-system get deployment coredns -o yaml | \
sed 's/allowPrivilegeEscalation: false/allowPrivilegeEscalation: true/g' | \
kubectl apply -f -
CoreDNSにCrashLoopBackOff
が発生する別の原因は、KubernetesにデプロイされたCoreDNS Podがループを検出したときに発生します。CoreDNSがループを検出して終了するたびに、KubernetesがCoreDNS Podを再起動しようとするのを避けるために、いくつかの回避策が用意されています。
警告: SELinuxを無効にするかallowPrivilegeEscalation
をtrue
に設定すると、クラスターのセキュリティが損なわれる可能性があります。
etcdのpodが継続的に再起動する
以下のエラーが発生した場合は:
rpc error: code = 2 desc = oci runtime error: exec failed: container_linux.go:247: starting container process caused "process_linux.go:110: decoding init error from pipe caused \"read parent: connection reset by peer\""
この問題は、CentOS 7をDocker 1.13.1.84で実行した場合に表示されます。このバージョンのDockerでは、kubeletがetcdコンテナに実行されないようにすることができます。
この問題を回避するには、以下のいずれかのオプションを選択します:
- 1.13.1-75のような以前のバージョンのDockerにロールバックする
yum downgrade docker-1.13.1-75.git8633870.el7.centos.x86_64 docker-client-1.13.1-75.git8633870.el7.centos.x86_64 docker-common-1.13.1-75.git8633870.el7.centos.x86_64
- 18.06のような最新の推奨バージョンをインストールする:
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install docker-ce-18.06.1.ce-3.el7.x86_64
-component-extra-args
のようなkubeadm init
フラグを使うと、kube-apiserverのようなコントロールプレーンコンポーネントにカスタム引数を渡すことができます。しかし、このメカニズムは値の解析に使われる基本的な型 (mapStringString
) のために制限されています。
もし、--apiserver-extra-args "enable-admission plugins=LimitRanger,NamespaceExists"
のようにカンマで区切られた複数の値をサポートする引数を渡した場合、このフラグはflag: malformed pair, expect string=string
で失敗します。これは--apiserver-extra-args
の引数リストがkey=value
のペアを期待しており、この場合NamespacesExists
は値を欠いたキーとみなされるためです。
別の方法として、key=value
のペアを以下のように分離してみることもできます:
--apiserver-extra-args "enable-admission-plugins=LimitRanger,enable-admission-plugins=NamespaceExists"
しかし、この場合は、キーenable-admission-plugins
はNamespaceExists
の値しか持ちません。既知の回避策としては、kubeadm設定ファイルを使用することが挙げられます。
cloud-controller-managerによってノードが初期化される前にkube-proxyがスケジューリングされる
クラウドプロバイダのシナリオでは、クラウドコントローラーマネージャがノードアドレスを初期化する前に、kube-proxyが新しいワーカーノードでスケジューリングされてしまうことがあります。これにより、kube-proxyがノードのIPアドレスを正しく拾えず、ロードバランサを管理するプロキシ機能に悪影響を及ぼします。
kube-proxy Podsでは以下のようなエラーが発生します:
server.go:610] Failed to retrieve node IP: host IP unknown; known addresses: []
proxier.go:340] invalid nodeIP, initializing kube-proxy with 127.0.0.1 as nodeIP
既知の解決策は、初期のガード条件が緩和されるまで他のノードから離しておき、条件に関係なくコントロールプレーンノード上でスケジューリングできるように、キューブプロキシDaemonSetにパッチを当てることです:
kubectl -n kube-system patch ds kube-proxy -p='{ "spec": { "template": { "spec": { "tolerations": [ { "key": "CriticalAddonsOnly", "operator": "Exists" }, { "effect": "NoSchedule", "key": "node-role.kubernetes.io/master" } ] } } } }'
Tこの問題のトラッキング問題はこちら。
kubeadmの設定をマーシャリングする際、NodeRegistration.Taintsフィールドが省略される
注意: このIssueは、kubeadmタイプをマーシャルするツール(YAML設定ファイルなど)にのみ適用されます。これはkubeadm API v1beta2で修正される予定です。
デフォルトでは、kubeadmはコントロールプレーンノードにnode-role.kubernetes.io/master:NoSchedule
のテイントを適用します。kubeadmがコントロールプレーンノードに影響を与えないようにし、InitConfiguration.NodeRegistration.Taints
を空のスライスに設定すると、マーシャリング時にこのフィールドは省略されます。フィールドが省略された場合、kubeadmはデフォルトのテイントを適用します。
少なくとも2つの回避策があります:
-
空のスライスの代わりにnode-role.kubernetes.io/master:PreferNoSchedule
テイントを使用します。他のノードに容量がない限り、Podsはマスター上でスケジュールされます。
-
kubeadm init終了後のテイントの除去:
kubectl taint nodes NODE_NAME node-role.kubernetes.io/master:NoSchedule-
ノード{#usr-mounted-read-only}に/usr
が読み取り専用でマウントされる
Fedora CoreOSなどのLinuxディストリビューションでは、ディレクトリ/usr
が読み取り専用のファイルシステムとしてマウントされます。 flex-volumeサポートでは、kubeletやkube-controller-managerのようなKubernetesコンポーネントはデフォルトで/usr/libexec/kubernetes/kubelet-plugins/volume/exec/
のパスを使用していますが、この機能を動作させるためにはflex-volumeディレクトリは 書き込み可能 な状態でなければなりません。
この問題を回避するには、kubeadm設定ファイルを使用してflex-volumeディレクトリを設定します。
プライマリコントロールプレーンノード(kubeadm init
で作成されたもの)上で、--config
で以下のファイルを渡します:
apiVersion: kubeadm.k8s.io/v1beta2
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
---
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
controllerManager:
extraArgs:
flex-volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
ノードをジョインするには:
apiVersion: kubeadm.k8s.io/v1beta2
kind: JoinConfiguration
nodeRegistration:
kubeletExtraArgs:
volume-plugin-dir: "/opt/libexec/kubernetes/kubelet-plugins/volume/exec/"
あるいは、/usr
マウントを書き込み可能にするために /etc/fstab
を変更することもできますが、これはLinuxディストリビューションの設計原理を変更していることに注意してください。
kubeadm upgrade plan
がcontext deadline exceeded
エラーメッセージを表示する
このエラーメッセージは、外部etcdを実行している場合にkubeadm
でKubernetesクラスターをアップグレードする際に表示されます。これは致命的なバグではなく、古いバージョンのkubeadmが外部etcdクラスターのバージョンチェックを行うために発生します。kubeadm upgrade apply ...
で進めることができます。
この問題はバージョン1.19で修正されます。
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.29向けに書かれています。
kubeadmツールの全体の機能の状態は、一般利用可能(GA)です。一部のサブ機能はまだ活発に開発が行われています。クラスター作成の実装は、ツールの進化に伴ってわずかに変わるかもしれませんが、全体の実装は非常に安定しているはずです。
備考: kubeadm alpha
以下のすべてのコマンドは、定義通り、アルファレベルでサポートされています。
目的
- シングルコントロールプレーンのKubernetesクラスターをインストールする
- クラスター上にPodネットワークをインストールして、Podがお互いに通信できるようにする
手順
ホストへのkubeadmのインストール
「kubeadmのインストール」を読んでください。
備考: すでにkubeadmがインストール済みである場合は、最新バージョンのkubeadmを取得するためにapt-get update && apt-get upgrade
やyum update
を実行してください。
アップグレード中、kubeletが数秒ごとに再起動します。これは、kubeadmがkubeletにするべきことを伝えるまで、crashloopの状態で待機するためです。このcrashloopは期待通りの通常の動作です。コントロールプレーンの初期化が完了すれば、kubeletは正常に動作します。
コントロールプレーンノードの初期化
コントロールプレーンノードとは、etcd(クラスターのデータベース)やAPIサーバー(kubectlコマンドラインツールが通信する相手)などのコントロールプレーンのコンポーネントが実行されるマシンです。
- (推奨)シングルコントロールプレーンの
kubeadm
クラスターを高可用性クラスターにアップグレードする予定がある場合、--control-plane-endpoint
を指定して、すべてのコントロールプレーンノードとエンドポイントを共有する必要があります。エンドポイントにはDNSネームやロードバランサーのIPアドレスが使用できます。
- Podネットワークアドオンを選んで、
kubeadm init
に引数を渡す必要があるかどうか確認してください。選んだサードパーティーのプロバイダーによっては、--pod-network-cidr
をプロバイダー固有の値に設定する必要がある場合があります。詳しくは、Podネットワークアドオンのインストールを参照してください。
- (オプション)バージョン1.14から、
kubeadm
はよく知られたドメインソケットのパスリストを用いて、Linux上のコンテナランタイムの検出を試みます。異なるコンテナランタイムを使用する場合やプロビジョニングするノードに2つ以上のランタイムがインストールされている場合、kubeadm init
に--cri-socket
引数を指定してください。詳しくは、ランタイムのインストールを読んでください。
- (オプション)明示的に指定しない限り、
kubeadm
はデフォルトゲートウェイに関連付けられたネットワークインターフェイスを使用して、この特定のコントロールプレーンノードのAPIサーバーのadvertise addressを設定します。異なるネットワークインターフェイスを使用するには、kubeadm init
に--apiserver-advertise-address=<ip-address>
引数を指定してください。IPv6アドレスを使用するIPv6 Kubernetesクラスターをデプロイするには、たとえば--apiserver-advertise-address=fd00::101
のように、IPv6アドレスを指定する必要があります。
- (オプション)
kubeadm init
を実行する前にkubeadm config images pull
を実行して、gcr.ioコンテナイメージレジストリに接続できるかどうかを確認します。
コントロールプレーンノードを初期化するには、次のコマンドを実行します。
apiserver-advertise-addressとControlPlaneEndpointに関する検討
--apiserver-advertise-address
は、この特定のコントロールプレーンノードのAPIサーバーへのadvertise addressを設定するために使えますが、--control-plane-endpoint
は、すべてのコントロールプレーンノード共有のエンドポイントを設定するために使えます。
--control-plane-endpoint
はIPアドレスと、IPアドレスへマッピングできるDNS名を使用できます。利用可能なソリューションをそうしたマッピングの観点から評価するには、ネットワーク管理者に相談してください。
以下にマッピングの例を示します。
192.168.0.102 cluster-endpoint
ここでは、192.168.0.102
がこのノードのIPアドレスであり、cluster-endpoint
がこのIPアドレスへとマッピングされるカスタムDNSネームです。このように設定することで、--control-plane-endpoint=cluster-endpoint
をkubeadm init
に渡せるようになり、kubeadm join
にも同じDNSネームを渡せます。後でcluster-endpoint
を修正して、高可用性が必要なシナリオでロードバランサーのアドレスを指すようにすることができます。
kubeadmでは、--control-plane-endpoint
を渡さずに構築したシングルコントロールプレーンのクラスターを高可用性クラスターに切り替えることはサポートされていません。
詳細な情報
kubeadm init
の引数のより詳細な情報は、kubeadmリファレンスガイドを参照してください。
設定オプションの全リストは、設定ファイルのドキュメントで確認できます。
コントロールプレーンコンポーネントやetcdサーバーのliveness probeへのオプションのIPv6の割り当てなど、コントロールプレーンのコンポーネントをカスタマイズしたい場合は、カスタムの引数に示されている方法で各コンポーネントに追加の引数を与えてください。
kubeadm init
を再び実行する場合は、初めにクラスターの破壊を行う必要があります。
もし異なるアーキテクチャのノードをクラスターにjoinさせたい場合は、デプロイしたDaemonSetがそのアーキテクチャ向けのコンテナイメージをサポートしているか確認してください。
初めにkubeadm init
は、マシンがKubernetesを実行する準備ができているかを確認する、一連の事前チェックを行います。これらの事前チェックはエラー発生時には警告を表示して終了します。次に、kubeadm init
はクラスターのコントロールプレーンのコンポーネントをダウンロードしてインストールします。これには数分掛かるかもしれません。出力は次のようになります。
[init] Using Kubernetes version: vX.Y.Z
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Activating the kubelet service
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/ca" certificate and key
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1]
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [kubeadm-cp localhost] and IPs [10.138.0.4 127.0.0.1 ::1]
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "ca" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubeadm-cp kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 10.138.0.4]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Generating "front-proxy-ca" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "sa" key and public key
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "kubelet.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[etcd] Creating static Pod manifest for local etcd in "/etc/kubernetes/manifests"
[wait-control-plane] Waiting for the kubelet to boot up the control plane as static Pods from directory "/etc/kubernetes/manifests". This can take up to 4m0s
[apiclient] All control plane components are healthy after 31.501735 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-X.Y" in namespace kube-system with the configuration for the kubelets in the cluster
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object "kubeadm-cp" as an annotation
[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the label "node-role.kubernetes.io/master=''"
[mark-control-plane] Marking the node kubeadm-cp as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: <token>
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
/ja/docs/concepts/cluster-administration/addons/
You can now join any number of machines by running the following on each node
as root:
kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>
kubectlをroot以外のユーザーでも実行できるようにするには、次のコマンドを実行します。これらのコマンドは、kubectl init
の出力の中にも書かれています。
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
あなたがroot
ユーザーである場合は、代わりに次のコマンドを実行します。
export KUBECONFIG=/etc/kubernetes/admin.conf
kubeadm init
が出力したkubeadm join
コマンドをメモしておいてください。クラスターにノードを追加するために、このコマンドが必要になります。
トークンは、コントロールプレーンノードと追加ノードの間の相互認証に使用します。ここに含まれるトークンには秘密の情報が含まれます。このトークンを知っていれば、誰でもクラスターに認証済みノードを追加できてしまうため、取り扱いには注意してください。kubeadm token
コマンドを使用すると、これらのトークンの一覧、作成、削除ができます。詳しくはkubeadmリファレンスガイドを読んでください。
Podネットワークアドオンのインストール
注意: このセクションには、ネットワークのセットアップとデプロイの順序に関する重要な情報が書かれています。先に進む前に以下のすべてのアドバイスを熟読してください。
Pod同士が通信できるようにするには、Container Network Interface(CNI)をベースとするPodネットワークアドオンをデプロイしなければなりません。ネットワークアドオンをインストールする前には、Cluster DNS(CoreDNS)は起動しません。
-
Podネットワークがホストネットワークと決して重ならないように気をつけてください。もし重なると、様々な問題が起こってしまう可能性があります。(ネットワークプラグインが優先するPodネットワークとホストのネットワークの一部が衝突することが分かった場合、適切な代わりのCIDRを考える必要があります。そして、kubeadm init
の実行時に--pod-network-cidr
にそのCIDRを指定し、ネットワークプラグインのYAMLでは代わりにそのCIDRを使用してください)
-
デフォルトでは、kubeadm
はRBAC(role based access control)の使用を強制します。PodネットワークプラグインがRBACをサポートしていて、またそのデプロイに使用するマニフェストもRBACをサポートしていることを確認してください。
-
クラスターでIPv6を使用したい場合、デュアルスタック、IPv6のみのシングルスタックのネットワークのいずれであっても、PodネットワークプラグインがIPv6をサポートしていることを確認してください。IPv6のサポートは、CNIのv0.6.0で追加されました。
備考: 現在、Calicoはkubeadmプロジェクトがe2eテストを実施している唯一のCNIプラグインです。
もしCNIプラグインに関する問題を見つけた場合、kubeadmやkubernetesではなく、そのCNIプラグインの課題管理システムへ問題を報告してください。
CNIを使用するKubernetes Podネットワークを提供する外部のプロジェクトがいくつかあります。一部のプロジェクトでは、ネットワークポリシーもサポートしています。
Kubernetesのネットワークモデルを実装したアドオンの一覧も確認してください。
Podネットワークアドオンをインストールするには、コントロールプレーンノード上またはkubeconfigクレデンシャルを持っているノード上で、次のコマンドを実行します。
kubectl apply -f <add-on.yaml>
インストールできるPodネットワークは、クラスターごとに1つだけです。
Podネットワークがインストールされたら、kubectl get pods --all-namespaces
の出力結果でCoreDNS PodがRunning
状態であることをチェックすることで、ネットワークが動作していることを確認できます。そして、一度CoreDNS Podが動作すれば、続けてノードを追加できます。
もしネットワークやCoreDNSがRunning
状態にならない場合は、kubeadm
のトラブルシューティングガイドをチェックしてください。
コントロールプレーンノードの隔離
デフォルトでは、セキュリティ上の理由により、クラスターはコントロールプレーンノードにPodをスケジューリングしません。たとえば、開発用のKubernetesシングルマシンのクラスターなどで、Podをコントロールプレーンノードにスケジューリングしたい場合は、次のコマンドを実行します。
kubectl taint nodes --all node-role.kubernetes.io/master-
出力は次のようになります。
node "test-01" untainted
taint "node-role.kubernetes.io/master:" not found
taint "node-role.kubernetes.io/master:" not found
このコマンドは、コントロールプレーンノードを含むすべてのノードからnode-role.kubernetes.io/master
taintを削除します。その結果、スケジューラーはどこにでもPodをスケジューリングできるようになります。
ノードの追加
ノードは、ワークロード(コンテナやPodなど)が実行される場所です。新しいノードをクラスターに追加するためには、各マシンに対して、以下の手順を実行してください。
- マシンへSSHする
- rootになる(例:
sudo su -
)
kubeadm init
実行時に出力されたコマンドを実行する。たとえば、次のようなコマンドです。
kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
トークンがわからない場合は、コントロールプレーンノードで次のコマンドを実行すると取得できます。
出力は次のようになります。
TOKEN TTL EXPIRES USAGES DESCRIPTION EXTRA GROUPS
8ewj1p.9r9hcjoqgajrj4gi 23h 2018-06-12T02:51:28Z authentication, The default bootstrap system:
signing token generated by bootstrappers:
'kubeadm init'. kubeadm:
default-node-token
デフォルトでは、トークンは24時間後に有効期限が切れます。もし現在のトークンの有効期限が切れた後にクラスターにノードを参加させたい場合は、コントロールプレーンノードで次のコマンドを実行することで、新しいトークンを生成できます。
このコマンドの出力は次のようになります。
もし--discovery-token-ca-cert-hash
の値がわからない場合は、コントロールプレーンノード上で次のコマンドチェーンを実行することで取得できます。
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | \
openssl dgst -sha256 -hex | sed 's/^.* //'
出力は次のようになります。
8cb2de97839780a412b93877f8507ad6c94f73add17d5d7058e91741c9d5ec78
備考: IPv6タプルを<control-plane-host>:<control-plane-port>
と指定するためには、IPv6アドレスを角括弧で囲みます。たとえば、[fd00::101]:2073
のように書きます。
出力は次のようになります。
[preflight] Running pre-flight checks
... (joinワークフローのログ出力) ...
Node join complete:
* Certificate signing request sent to control-plane and response
received.
* Kubelet informed of new secure connection details.
Run 'kubectl get nodes' on control-plane to see this machine join.
数秒後、コントロールプレーンノード上でkubectl get nodes
を実行すると、出力内にこのノードが表示されるはずです。
(オプション)コントロールプレーンノード以外のマシンからのクラスター操作
他のコンピューター(例: ラップトップ)上のkubectlがクラスターと通信できるようにするためには、次のようにして、administratorのkubeconfigファイルをコントロールプレーンノードからそのコンピューター上にコピーする必要があります。
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf get nodes
備考: 上の例では、rootユーザーに対するSSH接続が有効であることを仮定しています。もしそうでない場合は、admin.conf
ファイルを誰か他のユーザーからアクセスできるようにコピーした上で、代わりにそのユーザーを使ってscp
してください。
admin.conf
ファイルはユーザーにクラスターに対する 特権ユーザー の権限を与えます。そのため、このファイルを使うのは控えめにしなければなりません。通常のユーザーには、明示的に許可した権限を持つユニークなクレデンシャルを生成することを推奨します。これには、kubeadm kubeconfig user --client-name <CN>
コマンドが使えます。このコマンドを実行すると、KubeConfigファイルがSTDOUTに出力されるので、ファイルに保存してユーザーに配布します。その後、kubectl create (cluster)rolebinding
コマンドを使って権限を付与します。
(オプション)APIサーバーをlocalhostへプロキシする
クラスターの外部からAPIサーバーに接続したいときは、次のようにkubectl proxy
コマンドが使えます。
scp root@<control-plane-host>:/etc/kubernetes/admin.conf .
kubectl --kubeconfig ./admin.conf proxy
これで、ローカルのhttp://localhost:8001/api/v1
からAPIサーバーにアクセスできるようになります。
クリーンアップ
テストのためにクラスターに破棄可能なサーバーを使用した場合、サーバーのスイッチをオフにすれば、以降のクリーンアップの作業は必要ありません。クラスターのローカルの設定を削除するには、kubectl config delete-cluster
を実行します。
しかし、もしよりきれいにクラスターのプロビジョンをもとに戻したい場合は、初めにノードのdrainを行い、ノードが空になっていることを確認した後、ノードの設定を削除する必要があります。
ノードの削除
適切なクレデンシャルを使用してコントロールプレーンノードに削除することを伝えます。次のコマンドを実行してください。
kubectl drain <node name> --delete-local-data --force --ignore-daemonsets
ノードが削除される前に、kubeadm
によってインストールされた状態をリセットします。
リセットプロセスでは、iptablesのルールやIPVS tablesのリセットやクリーンアップは行われません。iptablesをリセットしたい場合は、次のように手動でコマンドを実行する必要があります。
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
IPVS tablesをリセットしたい場合は、次のコマンドを実行する必要があります。
ノードを削除します。
kubectl delete node <node name>
クラスターのセットアップを最初から始めたいときは、kubeadm init
やkubeadm join
を適切な引数を付けて実行すればいいだけです。
コントロールプレーンのクリーンアップ
コントロールホスト上でkubeadm reset
を実行すると、ベストエフォートでのクリーンアップが実行できます。
このサブコマンドとオプションに関するより詳しい情報は、kubeadm reset
リファレンスドキュメントを読んでください。
次の手順
フィードバック
バージョン互換ポリシー
バージョンv1.29のkubeadm
ツールは、バージョンv1.29またはv1.28のコントロールプレーンを持つクラスターをデプロイできます。また、バージョンv1.29のkubeadm
は、バージョンv1.28のkubeadmで構築されたクラスターをアップグレートできます。
未来を見ることはできないため、kubeadm CLI v1.29はv1.30をデプロイできないかもしれません。
例: 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に関する問題が起きたときは、トラブルシューティングドキュメントを確認してください。
3.2.1.4 - kubeadmを使ったコントロールプレーンの設定のカスタマイズ
FEATURE STATE: Kubernetes 1.12 [stable]
kubeadmのClusterConfiguration
オブジェクトはAPIServer、ControllerManager、およびSchedulerのようなコントロールプレーンの構成要素に渡されたデフォルトのフラグを上書きすることができる extraArgs
の項目があります。
その構成要素は次の項目で定義されています。
apiServer
controllerManager
scheduler
extraArgs
の項目は キー: 値
のペアです。コントロールプレーンの構成要素のフラグを上書きするには:
- 設定内容に適切な項目を追加
- フラグを追加して項目を上書き
--config <任意の設定YAMLファイル>
でkubeadm init
を実行
各設定項目のより詳細な情報はAPIリファレンスのページを参照してください。
備考: kubeadm config print init-defaults
を実行し、選択したファイルに出力を保存することで、デフォルト値でClusterConfiguration
オブジェクトを生成できます。
APIServerフラグ
詳細はkube-apiserverのリファレンスドキュメントを参照してください。
使用例:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
apiServer:
extraArgs:
advertise-address: 192.168.0.103
anonymous-auth: "false"
enable-admission-plugins: AlwaysPullImages,DefaultStorageClass
audit-log-path: /home/johndoe/audit.log
ControllerManagerフラグ
詳細はkube-controller-managerのリファレンスドキュメントを参照してください。
使用例:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
controllerManager:
extraArgs:
cluster-signing-key-file: /home/johndoe/keys/ca.key
bind-address: 0.0.0.0
deployment-controller-sync-period: "50"
Schedulerフラグ
詳細はkube-schedulerのリファレンスドキュメントを参照してください。
使用例:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.16.0
scheduler:
extraArgs:
bind-address: 0.0.0.0
config: /home/johndoe/schedconfig.yaml
kubeconfig: /home/johndoe/kubeconfig.yaml
3.2.1.5 - 高可用性トポロジーのためのオプション
このページでは、高可用性(HA)Kubernetesクラスターのトポロジーを設定するための2つのオプションについて説明します。
HAクラスターは次の方法で設定できます。
- 積層コントロールプレーンノードを使用する方法。こちらの場合、etcdノードはコントロールプレーンノードと同じ場所で動作します。
- 外部のetcdノードを使用する方法。こちらの場合、etcdがコントロールプレーンとは分離されたノードで動作します。
HAクラスターをセットアップする前に、各トポロジーの利点と欠点について注意深く考慮する必要があります。
備考: kubeadmは、etcdクラスターを静的にブートストラップします。
詳細については、etcd
クラスタリングガイドをご覧ください。
積層etcdトポロジー
積層HAクラスターは、コントロールプレーンのコンポーネントを実行する、kubeadmで管理されたノードで構成されるクラスターの上に、etcdにより提供される分散データストレージクラスターがあるようなトポロジーです。
各コントロールプレーンノードは、kube-apiserver
、kube-scheduler
、およびkube-controller-manager
を実行します。kube-apiserver
はロードバランサーを用いてワーカーノードに公開されます。
各コントロールプレーンノードはローカルのetcdメンバーを作り、このetcdメンバーはそのノードのkube-apiserver
とだけ通信します。ローカルのkube-controller-manager
とkube-scheduler
のインスタンスも同様です。
このトポロジーは、同じノード上のコントロールプレーンとetcdのメンバーを結合します。外部のetcdノードを使用するクラスターよりはセットアップがシンプルで、レプリケーションの管理もシンプルです。
しかし、積層クラスターには、結合による故障のリスクがあります。1つのノードがダウンすると、etcdメンバーとコントロールプレーンのインスタンスの両方が失われ、冗長性が損なわれます。より多くのコントロールプレーンノードを追加することで、このリスクは緩和できます。
そのため、HAクラスターのためには、最低でも3台の積層コントロールプレーンノードを実行しなければなりません。
これがkubeadmのデフォルトのトポロジーです。kubeadm init
やkubeadm join --control-place
を実行すると、ローカルのetcdメンバーがコントロールプレーンノード上に自動的に作成されます。
外部のetcdトポロジー
外部のetcdを持つHAクラスターは、コントロールプレーンコンポーネントを実行するノードで構成されるクラスターの外部に、etcdにより提供される分散データストレージクラスターがあるようなトポロジーです。
積層etcdトポロジーと同様に、外部のetcdトポロジーにおける各コントロールプレーンノードは、kube-apiserver
、kube-scheduler
、およびkube-controller-manager
のインスタンスを実行します。そして、kube-apiserver
は、ロードバランサーを使用してワーカーノードに公開されます。しかし、etcdメンバーは異なるホスト上で動作しており、各etcdホストは各コントロールプレーンノードのkube-api-server
と通信します。
このトポロジーは、コントロールプレーンとetcdメンバーを疎結合にします。そのため、コントロールプレーンインスタンスまたはetcdメンバーを失うことによる影響は少なく、積層HAトポロジーほどクラスターの冗長性に影響しないHAセットアップが実現します。
しかし、このトポロジーでは積層HAトポロジーの2倍の数のホストを必要とします。このトポロジーのHAクラスターのためには、最低でもコントロールプレーンのために3台のホストが、etcdノードのために3台のホストがそれぞれ必要です。
次の項目
3.2.1.6 - kubeadmを使用した高可用性クラスターの作成
このページでは、kubeadmを使用して、高可用性クラスターを作成する、2つの異なるアプローチを説明します:
- 積層コントロールプレーンノードを使う方法。こちらのアプローチは、必要なインフラストラクチャーが少ないです。etcdのメンバーと、コントロールプレーンノードは同じ場所に置かれます。
- 外部のetcdクラスターを使う方法。こちらのアプローチには、より多くのインフラストラクチャーが必要です。コントロールプレーンノードと、etcdのメンバーは分離されます。
先へ進む前に、どちらのアプローチがアプリケーションの要件と、環境に適合するか、慎重に検討してください。こちらの比較が、それぞれの利点/欠点について概説しています。
高可用性クラスターの作成で問題が発生した場合は、kueadmのissue trackerでフィードバックを提供してください。
高可用性クラスターのアップグレードも参照してください。
注意: このページはクラウド上でクラスターを構築することには対応していません。ここで説明されているどちらのアプローチも、クラウド上で、LoadBalancerタイプのServiceオブジェクトや、動的なPersistentVolumeを利用して動かすことはできません。
始める前に
どちらの方法でも、以下のインフラストラクチャーが必要です:
- master用に、kubeadmの最小要件を満たす3台のマシン
- worker用に、kubeadmの最小要件を満たす3台のマシン
- クラスター内のすべてのマシン間がフルにネットワーク接続可能であること(パブリック、もしくはプライベートネットワーク)
- すべてのマシンにおいて、sudo権限
- あるデバイスから、システム内のすべてのノードに対しSSH接続できること
kubeadm
とkubelet
がすべてのマシンにインストールされていること。 kubectl
は任意です。
外部etcdクラスターには、以下も必要です:
両手順における最初のステップ
kube-apiserver用にロードバランサーを作成
備考: ロードバランサーには多くの設定項目があります。以下の例は、一選択肢に過ぎません。あなたのクラスター要件には、異なった設定が必要かもしれません。
-
DNSで解決される名前で、kube-apiserver用ロードバランサーを作成する。
-
クラウド環境では、コントロールプレーンノードをTCPフォワーディングロードバランサーの後ろに置かなければなりません。このロードバランサーはターゲットリストに含まれる、すべての健全なコントロールプレーンノードにトラフィックを分配します。apiserverへのヘルスチェックはkube-apiserverがリッスンするポート(デフォルト値: :6443
)に対する、TCPチェックです。
-
クラウド環境では、IPアドレスを直接使うことは推奨されません。
-
ロードバランサーは、apiserverポートで、全てのコントロールプレーンノードと通信できなければなりません。また、リスニングポートに対する流入トラフィックも許可されていなければなりません。
-
ロードバランサーのアドレスは、常にkubeadmのControlPlaneEndpoint
のアドレスと一致することを確認してください。
-
詳細はOptions for Software Load Balancingをご覧ください。
-
ロードバランサーに、最初のコントロールプレーンノードを追加し、接続をテストする:
nc -v LOAD_BALANCER_IP PORT
- apiserverはまだ動いていないので、接続の拒否は想定通りです。しかし、タイムアウトしたのであれば、ロードバランサーはコントロールプレーンノードと通信できなかったことを意味します。もし、タイムアウトが起きたら、コントロールプレーンノードと通信できるように、ロードバランサーを再設定してください。
-
残りのコントロールプレーンノードを、ロードバランサーのターゲットグループに追加します。
積層コントロールプレーンとetcdノード
最初のコントロールプレーンノードの手順
-
最初のコントロールプレーンノードを初期化します:
sudo kubeadm init --control-plane-endpoint "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT" --upload-certs
--kubernetes-version
フラグで使用するKubernetesのバージョンを設定できます。kubeadm、kubelet、kubectl、Kubernetesのバージョンを一致させることが推奨されます。
--control-plane-endpoint
フラグは、ロードバランサーのIPアドレスまたはDNS名と、ポートが設定される必要があります。
--upload-certs
フラグは全てのコントロールプレーンノードで共有する必要がある証明書をクラスターにアップロードするために使用されます。代わりに、コントロールプレーンノード間で手動あるいは自動化ツールを使用して証明書をコピーしたい場合は、このフラグを削除し、以下の証明書の手動配布のセクションを参照してください。
備考: kubeadm init
の
--config
フラグと
--certificate-key
フラグは混在させることはできないため、
kubeadm configurationを使用する場合は
certificateKey
フィールドを適切な場所に追加する必要があります(
InitConfiguration
と
JoinConfiguration: controlPlane
の配下)。
備考: いくつかのCNIネットワークプラグインはPodのIPのCIDRの指定など追加の設定を必要としますが、必要としないプラグインもあります。
CNIネットワークドキュメントを参照してください。PodにCIDRを設定するには、
ClusterConfiguration
の
networking
オブジェクトに
podSubnet: 192.168.0.0/16
フィールドを設定してください。
...
You can now join any number of control-plane node by running the following command on each as a root:
kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use kubeadm init phase upload-certs to reload certs afterward.
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
-
この出力をテキストファイルにコピーします。あとで、他のコントロールプレーンノードとワーカーノードをクラスターに参加させる際に必要です。
-
--upload-certs
フラグをkubeadm init
で使用すると、プライマリコントロールプレーンの証明書が暗号化されて、kubeadm-certs
Secretにアップロードされます。
-
証明書を再アップロードして新しい復号キーを生成するには、すでにクラスターに参加しているコントロールプレーンノードで次のコマンドを使用します:
sudo kubeadm init phase upload-certs --upload-certs
- また、後で
join
で使用できるように、init
中にカスタムした--certificate-key
を指定することもできます。このようなキーを生成するには、次のコマンドを使用します:
kubeadm alpha certs certificate-key
備考: kubeadm-certs
のSecretと復号キーは2時間で期限切れとなります。
注意: コマンド出力に記載されているように、証明書キーはクラスターの機密データへのアクセスを提供します。秘密にしてください!
-
使用するCNIプラグインを適用します:
こちらの手順に従いCNIプロバイダーをインストールします。該当する場合は、kubeadmの設定で指定されたPodのCIDRに対応していることを確認してください。
Weave Netを使用する場合の例:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
-
以下のコマンドを入力し、コンポーネントのPodが起動するのを確認します:
kubectl get pod -n kube-system -w
残りのコントロールプレーンノードの手順
備考: kubeadmバージョン1.15以降、複数のコントロールプレーンノードを並行してクラスターに参加させることができます。
このバージョンの前は、最初のノードの初期化が完了した後でのみ、新しいコントロールプレーンノードを順番にクラスターに参加させる必要があります。
追加のコントロールプレーンノード毎に、以下の手順を行います。
-
kubeadm init
を最初のノードで実行した際に取得したjoinコマンドを使って、新しく追加するコントロールプレーンノードでkubeadm join
を開始します。このようなコマンドになるはずです:
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866 --control-plane --certificate-key f8902e114ef118304e561c3ecd4d0b543adc226b7a07f675f56564185ffe0c07
--control-plane
フラグによって、kubeadm join
の実行は新しいコントロールプレーンを作成します。
-certificate-key ...
を指定したキーを使って、クラスターのkubeadm-certs
Secretからダウンロードされたコントロールプレーンの証明書が復号されます。
外部のetcdノード
外部のetcdノードを使ったクラスターの設定は、積層etcdの場合と似ていますが、最初にetcdを設定し、kubeadmの設定ファイルにetcdの情報を渡す必要があります。
etcdクラスターの構築
-
こちらの手順にしたがって、etcdクラスターを構築してください。
-
こちらの手順にしたがって、SSHを構築してください。
-
以下のファイルをクラスター内の任意のetcdノードから最初のコントロールプレーンノードにコピーしてください:
export CONTROL_PLANE="ubuntu@10.0.0.7"
scp /etc/kubernetes/pki/etcd/ca.crt "${CONTROL_PLANE}":
scp /etc/kubernetes/pki/apiserver-etcd-client.crt "${CONTROL_PLANE}":
scp /etc/kubernetes/pki/apiserver-etcd-client.key "${CONTROL_PLANE}":
CONTROL_PLANE
の値を、最初のコントロールプレーンノードのuser@host
で置き換えます。
最初のコントロールプレーンノードの構築
-
以下の内容で、kubeadm-config.yaml
という名前の設定ファイルを作成します:
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: stable
controlPlaneEndpoint: "LOAD_BALANCER_DNS:LOAD_BALANCER_PORT"
etcd:
external:
endpoints:
- https://ETCD_0_IP:2379
- https://ETCD_1_IP:2379
- https://ETCD_2_IP:2379
caFile: /etc/kubernetes/pki/etcd/ca.crt
certFile: /etc/kubernetes/pki/apiserver-etcd-client.crt
keyFile: /etc/kubernetes/pki/apiserver-etcd-client.key
備考: ここで、積層etcdと外部etcdの違いは、外部etcdの構成ではetcd
のexternal
オブジェクトにetcdのエンドポイントが記述された設定ファイルが必要です。積層etcdトポロジーの場合、これは自動で管理されます。
以下の手順は、積層etcdの構築と同様です。
-
sudo kubeadm init --config kubeadm-config.yaml --upload-certs
をこのノードで実行します。
-
表示されたjoinコマンドを、あとで使うためにテキストファイルに書き込みます。
-
使用するCNIプラグインを適用します。以下はWeave CNIの場合です:
kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
残りのコントロールプレーンノードの手順
手順は、積層etcd構築の場合と同じです:
- 最初のコントロールプレーンノードが完全に初期化されているのを確認します。
- テキストファイルに保存したjoinコマンドを使って、それぞれのコントロールプレーンノードをクラスターへ参加させます。コントロールプレーンノードは1台ずつクラスターへ参加させるのを推奨します。
--certificate-key
で指定する復号キーは、デフォルトで2時間で期限切れになることを忘れないでください。
コントロールプレーン起動後の共通タスク
workerのインストール
kubeadm init
コマンドから返されたコマンドを利用して、workerノードをクラスターに参加させることが可能です。
sudo kubeadm join 192.168.0.200:6443 --token 9vr73a.a8uxyaju799qwdjv --discovery-token-ca-cert-hash sha256:7c2e69131a36ae2a042a339b33381c6d0d43887e2de83720eff5359e26aec866
証明書の手動配布
--upload-certs
フラグを指定してkubeadm init
を実行しない場合、プライマリコントロールプレーンノードから他のコントロールプレーンノードへ証明書を手動でコピーする必要があります。
コピーを行うには多くの方法があります。次の例ではssh
とscp
を使用しています。
1台のマシンから全てのノードをコントロールしたいのであれば、SSHが必要です。
-
システム内の全ての他のノードにアクセスできるメインデバイスで、ssh-agentを有効にします
eval $(ssh-agent)
-
SSHの秘密鍵を、セッションに追加します:
ssh-add ~/.ssh/path_to_private_key
-
正常に接続できることを確認するために、ノード間でSSHします。
-
全てのノードでSSHを設定したら、kubeadm init
を実行した後、最初のコントロールノードプレーンノードで次のスクリプトを実行します。このスクリプトは、最初のコントロールプレーンノードから残りのコントロールプレーンノードへ証明書ファイルをコピーします:
次の例の、CONTROL_PLANE_IPS
を他のコントロールプレーンノードのIPアドレスに置き換えます。
USER=ubuntu # 環境に合わせる
CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8"
for host in ${CONTROL_PLANE_IPS}; do
scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
# 外部のetcdノード使用時はこちらのコマンドを実行
scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
done
注意: 上のリストにある証明書だけをコピーしてください。kubeadmが、参加するコントロールプレーンノード用に、残りの証明書と必要なSANの生成を行います。間違って全ての証明書をコピーしてしまったら、必要なSANがないため、追加ノードの作成は失敗するかもしれません。
-
次に、クラスターに参加させる残りの各コントロールプレーンノードでkubeadm join
を実行する前に次のスクリプトを実行する必要があります。このスクリプトは、前の手順でコピーした証明書をホームディレクトリから/etc/kubernetes/pki
へ移動します:
USER=ubuntu # 環境に合わせる
mkdir -p /etc/kubernetes/pki/etcd
mv /home/${USER}/ca.crt /etc/kubernetes/pki/
mv /home/${USER}/ca.key /etc/kubernetes/pki/
mv /home/${USER}/sa.pub /etc/kubernetes/pki/
mv /home/${USER}/sa.key /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/
mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
# 外部のetcdノード使用時はこちらのコマンドを実行
mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
3.2.1.7 - kubeadmを使用した高可用性etcdクラスターの作成
備考: While kubeadm is being used as the management tool for external etcd nodes
in this guide, please note that kubeadm does not plan to support certificate rotation
or upgrades for such nodes. The long term plan is to empower the tool
etcdadm to manage these
aspects.
Kubeadm defaults to running a single member etcd cluster in a static pod managed
by the kubelet on the control plane node. This is not a high availability setup
as the etcd cluster contains only one member and cannot sustain any members
becoming unavailable. This task walks through the process of creating a high
availability etcd cluster of three members that can be used as an external etcd
when using kubeadm to set up a kubernetes cluster.
始める前に
- Three hosts that can talk to each other over ports 2379 and 2380. This
document assumes these default ports. However, they are configurable through
the kubeadm config file.
- Each host must have docker, kubelet, and kubeadm installed.
- Each host should have access to the Kubernetes container image registry (
registry.k8s.io
) or list/pull the required etcd image using kubeadm config images list/pull
. This guide will setup etcd instances as static pods managed by a kubelet.
- Some infrastructure to copy files between hosts. For example
ssh
and scp
can satisfy this requirement.
クラスターの構築
The general approach is to generate all certs on one node and only distribute
the necessary files to the other nodes.
備考: kubeadm contains all the necessary cryptographic machinery to generate
the certificates described below; no other cryptographic tooling is required for
this example.
-
Configure the kubelet to be a service manager for etcd.
Since etcd was created first, you must override the service priority by creating a new unit file
that has higher precedence than the kubeadm-provided kubelet unit file.
cat << EOF > /etc/systemd/system/kubelet.service.d/20-etcd-service-manager.conf
[Service]
ExecStart=
# Replace "systemd" with the cgroup driver of your container runtime. The default value in the kubelet is "cgroupfs".
ExecStart=/usr/bin/kubelet --address=127.0.0.1 --pod-manifest-path=/etc/kubernetes/manifests --cgroup-driver=systemd
Restart=always
EOF
systemctl daemon-reload
systemctl restart kubelet
-
Create configuration files for kubeadm.
Generate one kubeadm configuration file for each host that will have an etcd
member running on it using the following script.
# Update HOST0, HOST1, and HOST2 with the IPs or resolvable names of your hosts
export HOST0=10.0.0.6
export HOST1=10.0.0.7
export HOST2=10.0.0.8
# Create temp directories to store files that will end up on other hosts.
mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/
ETCDHOSTS=(${HOST0} ${HOST1} ${HOST2})
NAMES=("infra0" "infra1" "infra2")
for i in "${!ETCDHOSTS[@]}"; do
HOST=${ETCDHOSTS[$i]}
NAME=${NAMES[$i]}
cat << EOF > /tmp/${HOST}/kubeadmcfg.yaml
apiVersion: "kubeadm.k8s.io/v1beta2"
kind: ClusterConfiguration
etcd:
local:
serverCertSANs:
- "${HOST}"
peerCertSANs:
- "${HOST}"
extraArgs:
initial-cluster: ${NAMES[0]}=https://${ETCDHOSTS[0]}:2380,${NAMES[1]}=https://${ETCDHOSTS[1]}:2380,${NAMES[2]}=https://${ETCDHOSTS[2]}:2380
initial-cluster-state: new
name: ${NAME}
listen-peer-urls: https://${HOST}:2380
listen-client-urls: https://${HOST}:2379
advertise-client-urls: https://${HOST}:2379
initial-advertise-peer-urls: https://${HOST}:2380
EOF
done
-
Generate the certificate authority
If you already have a CA then the only action that is copying the CA's crt
and
key
file to /etc/kubernetes/pki/etcd/ca.crt
and
/etc/kubernetes/pki/etcd/ca.key
. After those files have been copied,
proceed to the next step, "Create certificates for each member".
If you do not already have a CA then run this command on $HOST0
(where you
generated the configuration files for kubeadm).
kubeadm init phase certs etcd-ca
This creates two files
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
-
Create certificates for each member
kubeadm init phase certs etcd-server --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST2}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST2}/
# cleanup non-reusable certificates
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
kubeadm init phase certs etcd-server --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST1}/kubeadmcfg.yaml
cp -R /etc/kubernetes/pki /tmp/${HOST1}/
find /etc/kubernetes/pki -not -name ca.crt -not -name ca.key -type f -delete
kubeadm init phase certs etcd-server --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-peer --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs etcd-healthcheck-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
kubeadm init phase certs apiserver-etcd-client --config=/tmp/${HOST0}/kubeadmcfg.yaml
# No need to move the certs because they are for HOST0
# clean up certs that should not be copied off this host
find /tmp/${HOST2} -name ca.key -type f -delete
find /tmp/${HOST1} -name ca.key -type f -delete
-
Copy certificates and kubeadm configs
The certificates have been generated and now they must be moved to their
respective hosts.
USER=ubuntu
HOST=${HOST1}
scp -r /tmp/${HOST}/* ${USER}@${HOST}:
ssh ${USER}@${HOST}
USER@HOST $ sudo -Es
root@HOST $ chown -R root:root pki
root@HOST $ mv pki /etc/kubernetes/
-
Ensure all expected files exist
The complete list of required files on $HOST0
is:
/tmp/${HOST0}
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── ca.key
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
On $HOST1
:
$HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
On $HOST2
$HOME
└── kubeadmcfg.yaml
---
/etc/kubernetes/pki
├── apiserver-etcd-client.crt
├── apiserver-etcd-client.key
└── etcd
├── ca.crt
├── healthcheck-client.crt
├── healthcheck-client.key
├── peer.crt
├── peer.key
├── server.crt
└── server.key
-
Create the static pod manifests
Now that the certificates and configs are in place it's time to create the
manifests. On each host run the kubeadm
command to generate a static manifest
for etcd.
root@HOST0 $ kubeadm init phase etcd local --config=/tmp/${HOST0}/kubeadmcfg.yaml
root@HOST1 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
root@HOST2 $ kubeadm init phase etcd local --config=$HOME/kubeadmcfg.yaml
-
Optional: Check the cluster health
docker run --rm -it \
--net host \
-v /etc/kubernetes:/etc/kubernetes registry.k8s.io/etcd:${ETCD_TAG} etcdctl \
--cert /etc/kubernetes/pki/etcd/peer.crt \
--key /etc/kubernetes/pki/etcd/peer.key \
--cacert /etc/kubernetes/pki/etcd/ca.crt \
--endpoints https://${HOST0}:2379 endpoint health --cluster
...
https://[HOST0 IP]:2379 is healthy: successfully committed proposal: took = 16.283339ms
https://[HOST1 IP]:2379 is healthy: successfully committed proposal: took = 19.44402ms
https://[HOST2 IP]:2379 is healthy: successfully committed proposal: took = 35.926451ms
- Set
${ETCD_TAG}
to the version tag of your etcd image. For example 3.4.3-0
. To see the etcd image and tag that kubeadm uses execute kubeadm config images list --kubernetes-version ${K8S_VERSION}
, where ${K8S_VERSION}
is for example v1.17.0
- Set
${HOST0}
to the IP address of the host you are testing.
次の項目
Once you have a working 3 member etcd cluster, you can continue setting up a
highly available control plane using the external etcd method with
kubeadm.
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は一元的な設定管理のためのKubeletConfiguration
APIを提供しています。
Kubeletの設定パターン
以下のセクションでは、kubeadmを使用したkubeletの設定パターンについて説明します。これは手動で各Nodeの設定を管理するよりも簡易に行うことができます。
各kubeletにクラスターレベルの設定を配布
kubeadm init
およびkubeadm join
コマンドを使用すると、kubeletにデフォルト値を設定することができます。興味深い例として、異なるCRIランタイムを使用したり、Serviceが使用するデフォルトのサブネットを設定したりすることができます。
Serviceが使用するデフォルトのサブネットとして10.96.0.0/12
を設定する必要がある場合は、--service-cidr
パラメーターを渡します。
kubeadm init --service-cidr 10.96.0.0/12
これによってServiceの仮想IPはこのサブネットから割り当てられるようになりました。また、--cluster-dns
フラグを使用し、kubeletが用いるDNSアドレスを設定する必要もあります。この設定はクラスター内の全てのマネージャーとNode上で同一である必要があります。kubeletは、kubeletのComponentConfigと呼ばれる、バージョン管理と構造化されたAPIオブジェクトを提供します。これはkubelet内のほとんどのパラメーターを設定し、その設定をクラスター内で稼働中の各kubeletへ適用することを可能にします。以下の例のように、キャメルケースのキーに値のリストとしてクラスターDNS IPアドレスなどのフラグを指定することができます。
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
clusterDNS:
- 10.96.0.10
ComponentConfigの詳細については、このセクションをご覧ください
インスタンス固有の設定内容を適用
いくつかのホストでは、ハードウェア、オペレーティングシステム、ネットワーク、その他ホスト固有のパラメーターの違いのため、特定のkubeletの設定を必要とします。以下にいくつかの例を示します。
- DNS解決ファイルへのパスは
--resolv-conf
フラグで指定することができますが、オペレーティングシステムやsystemd-resolved
を使用するかどうかによって異なる場合があります。このパスに誤りがある場合、そのNode上でのDNS解決は失敗します。
- クラウドプロバイダーを使用していない場合、Node APIオブジェクト
.metadata.name
はデフォルトでマシンのホスト名に設定されます。異なるNode名を指定する必要がある場合には、--hostname-override
フラグによってこの挙動を書き換えることができます。
- 現在のところ、kubletはCRIランタイムが使用するcgroupドライバを自動で検知することができませんが、kubeletの稼働を保証するためには、
--cgroup-driver
の値はCRIランタイムが使用するcgroupドライバに一致していなければなりません。
- クラスターが使用するCRIランタイムによっては、異なるフラグを指定する必要があるかもしれません。例えば、Dockerを使用している場合には、
--network-plugin=cni
のようなフラグを指定する必要があります。外部のランタイムを使用している場合には、--container-runtime=remote
と指定し、--container-runtime-endpoint=<path>
のようにCRIエンドポイントを指定する必要があります。
これらのフラグは、systemdなどのサービスマネージャー内のkubeletの設定によって指定することができます。
kubeadm ... --config some-config-file.yaml
のように、カスタムのKubeletConfiguration
APIオブジェクトを設定ファイルを介して渡すことで、kubeadmによって起動されるkubeletに設定を反映することができます。
kubeadm config print init-defaults --component-configs KubeletConfiguration
を実行することによって、この構造体の全てのデフォルト値を確認することができます。
また、各フィールドの詳細については、kubelet ComponentConfigに関するAPIリファレンスを参照してください。
kubeadm init
実行時の流れ
kubeadm init
を実行した場合、kubeletの設定は/var/lib/kubelet/config.yaml
に格納され、クラスターのConfigMapにもアップロードされます。ConfigMapはkubelet-config-1.X
という名前で、X
は初期化するKubernetesのマイナーバージョンを表します。またこの設定ファイルは、クラスター内の全てのkubeletのために、クラスター全体設定の基準と共に/etc/kubernetes/kubelet.conf
にも書き込まれます。この設定ファイルは、kubeletがAPIサーバと通信するためのクライアント証明書を指し示します。これは、各kubeletにクラスターレベルの設定を配布することの必要性を示しています。
二つ目のパターンである、インスタンス固有の設定内容を適用するために、kubeadmは環境ファイルを/var/lib/kubelet/kubeadm-flags.env
へ書き出します。このファイルは以下のように、kubelet起動時に渡されるフラグのリストを含んでいます。
KUBELET_KUBEADM_ARGS="--flag1=value1 --flag2=value2 ..."
kubelet起動時に渡されるフラグに加えて、このファイルはcgroupドライバーや異なるCRIランタイムソケットを使用するかどうか(--cri-socket
)といった動的なパラメーターも含みます。
これら二つのファイルがディスク上に格納されると、systemdを使用している場合、kubeadmは以下の二つのコマンドを実行します。
systemctl daemon-reload && systemctl restart kubelet
リロードと再起動に成功すると、通常のkubeadm init
のワークフローが続きます。
kubeadm join
実行時の流れ
kubeadm join
を実行した場合、kubeadmはBootstrap Token証明書を使用してTLS bootstrapを行い、ConfigMapkubelet-config-1.X
をダウンロードするために必要なクレデンシャルを取得し、/var/lib/kubelet/config.yaml
へ書き込みます。動的な環境ファイルは、kubeadm init
の場合と全く同様の方法で生成されます。
次に、kubeadm
は、kubeletに新たな設定を読み込むために、以下の二つのコマンドを実行します。
systemctl daemon-reload && systemctl restart kubelet
kubeletが新たな設定を読み込むと、kubeadmは、KubeConfigファイル/etc/kubernetes/bootstrap-kubelet.conf
を書き込みます。これは、CA証明書とBootstrap Tokenを含みます。これらはkubeletがTLS Bootstrapを行い/etc/kubernetes/kubelet.conf
に格納されるユニークなクレデンシャルを取得するために使用されます。ファイルが書き込まれると、kubeletはTLS Bootstrapを終了します。
kubelet用のsystemdファイル
kubeadm
には、systemdがどのようにkubeletを実行するかを指定した設定ファイルが同梱されています。
kubeadm CLIコマンドは決してこのsystemdファイルには触れないことに注意してください。
kubeadmのDEBパッケージまたはRPMパッケージによってインストールされたこの設定ファイルは、/etc/systemd/system/kubelet.service.d/10-kubeadm.conf
に書き込まれ、systemdで使用されます。基本的なkubelet.service
(RPM用または、 DEB用)を拡張します。
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf
--kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"
# This is a file that "kubeadm init" and "kubeadm join" generate at runtime, populating
the KUBELET_KUBEADM_ARGS variable dynamically
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
# This is a file that the user can use for overrides of the kubelet args as a last resort. Preferably,
# the user should use the .NodeRegistration.KubeletExtraArgs object in the configuration files instead.
# KUBELET_EXTRA_ARGS should be sourced from this file.
EnvironmentFile=-/etc/default/kubelet
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
このファイルは、kubeadmがkubelet用に管理する全ファイルが置かれるデフォルトの場所を指定します。
- TLS Bootstrapに使用するKubeConfigファイルは
/etc/kubernetes/bootstrap-kubelet.conf
ですが、/etc/kubernetes/kubelet.conf
が存在しない場合にのみ使用します。
- ユニークなkublet識別子を含むKubeConfigファイルは
/etc/kubernetes/kubelet.conf
です。
- kubeletのComponentConfigを含むファイルは
/var/lib/kubelet/config.yaml
です。
KUBELET_KUBEADM_ARGS
を含む動的な環境ファイルは/var/lib/kubelet/kubeadm-flags.env
から取得します。
KUBELET_EXTRA_ARGS
によるユーザー定義のフラグの上書きを格納できるファイルは/etc/default/kubelet
(DEBの場合)、または/etc/sysconfig/kubelet
(RPMの場合)から取得します。KUBELET_EXTRA_ARGS
はフラグの連なりの最後に位置し、優先度が最も高いです。
Kubernetesバイナリとパッケージの内容
Kubernetesに同梱されるDEB、RPMのパッケージは以下の通りです。
パッケージ名 |
説明 |
kubeadm |
/usr/bin/kubeadm CLIツールと、kubelet用のsystemdファイルをインストールします。 |
kubelet |
kubeletバイナリを/usr/bin に、CNIバイナリを/opt/cni/bin にインストールします。 |
kubectl |
/usr/bin/kubectl バイナリをインストールします。 |
cri-tools |
/usr/bin/crictl バイナリをcri-tools gitリポジトリからインストールします。 |
3.2.1.9 - コントロールプレーンをセルフホストするようにkubernetesクラスターを構成する
コントロールプレーンのセルフホスティング
kubeadmを使用すると、セルフホスト型のKubernetesコントロールプレーンを実験的に作成できます。これはAPIサーバー、コントローラーマネージャー、スケジューラーなどの主要コンポーネントは、静的ファイルを介してkubeletで構成されたstatic podsではなく、Kubernetes APIを介して構成されたDaemonSet podsとして実行されることを意味します。
セルフホスト型クラスターを作成する場合はkubeadm alpha selfhosting pivotを参照してください。
警告
注意: この機能により、クラスターがサポートされていない状態になり、kubeadmがクラスターを管理できなくなります。これにはkubeadm upgrade
が含まれます。
-
1.8以降のセルフホスティングには、いくつかの重要な制限があります。特に、セルフホスト型クラスターは、手動の介入なしにコントロールプレーンのNode再起動から回復することはできません。
-
デフォルトでは、セルフホスト型のコントロールプレーンのPodは、hostPath
ボリュームからロードされた資格情報に依存しています。最初の作成を除いて、これらの資格情報はkubeadmによって管理されません。
-
コントロールプレーンのセルフホストされた部分にはetcdが含まれていませんが、etcdは静的Podとして実行されます。
プロセス
セルフホスティングのブートストラッププロセスは、kubeadm design
documentに記載されています。
要約すると、kubeadm alpha selfhosting
は次のように機能します。
-
静的コントロールプレーンのブートストラップが起動し、正常になるのを待ちます。これはkubeadm init
のセルフホスティングを使用しないプロセスと同じです。
-
静的コントロールプレーンのPodのマニフェストを使用して、セルフホスト型コントロールプレーンを実行する一連のDaemonSetのマニフェストを構築します。また、必要に応じてこれらのマニフェストを変更します。たとえば、シークレット用の新しいボリュームを追加します。
-
kube-system
のネームスペースにDaemonSetを作成し、Podの結果が起動されるのを待ちます。
-
セルフホスト型のPodが操作可能になると、関連する静的Podが削除され、kubeadmは次のコンポーネントのインストールに進みます。これによりkubeletがトリガーされて静的Podが停止します。
-
元の静的なコントロールプレーンが停止すると、新しいセルフホスト型コントロールプレーンはリスニングポートにバインドしてアクティブになります。
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
次の項目
3.2.3 - kubesprayを使ったKubernetesのインストール
このクイックスタートは、Kubesprayを使用して、GCE、Azure、OpenStack、AWS、vSphere、Equinix Metal(以前のPacket)、Oracle Cloud Infrastructure(実験的)またはベアメタルにホストされたKubernetesクラスターをインストールするためのものです。
Kubesprayは、汎用的なOSやKubernetesクラスターの構成管理タスクのためのAnsibleプレイブック、インベントリー、プロビジョニングツール、ドメインナレッジをまとめたものです。
Kubesprayは次を提供します:
- 高可用性クラスター。
- 構成可能(例えばネットワークプラグインの選択)。
- 最もポピュラーなLinuxディストリビューションのサポート:
- Flatcar Container Linux by Kinvolk
- Debian Bullseye, Buster, Jessie, Stretch
- Ubuntu 16.04, 18.04, 20.04, 22.04
- CentOS/RHEL 7, 8, 9
- Fedora 35, 36
- Fedora CoreOS
- openSUSE Leap 15.x/Tumbleweed
- Oracle Linux 7, 8, 9
- Alma Linux 8, 9
- Rocky Linux 8, 9
- Kylin Linux Advanced Server V10
- Amazon Linux 2
- 継続的インテグレーションテスト。
あなたのユースケースに最適なツールの選択には、kubeadmやkopsと比較したドキュメントを参照してください。
クラスターの作成
(1/5) 下地の要件の確認
次の要件に従ってサーバーをプロビジョニングします:
- Kubernetesの最低必要バージョンはv1.22
- Ansibleのコマンドを実行するマシン上にAnsible v2.11+、Jinja 2.11+とpython-netaddrがインストールされていること
- ターゲットサーバーはdockerイメージをpullするためにインターネットにアクセスできる必要があります。そうでは無い場合は追加の構成が必要です(オフライン環境を参照)
- ターゲットのサーバーはIPv4フォワーディングができるように構成されていること。
- PodとServiceにIPv6を使用している場合は、ターゲットサーバーはIPv6フォワーディングができるように構成されていること。
- ファイアウォールは管理されないため、従来のように独自のルールを実装しなければなりません。デプロイ中の問題を避けるためには、ファイアウォールを無効にすべきです
- root以外のユーザーアカウントでkubesprayを実行する場合は、ターゲットサーバー上で特権昇格の方法を正しく構成されている必要があります。そして、
ansible_become
フラグ、またはコマンドパラメーター--become
、-b
を指定する必要があります
Kubesprayは環境のプロビジョニングを支援するために次のユーティリティを提供します:
(2/5) インベントリーファイルの用意
サーバーをプロビジョニングした後、Ansibleのインベントリーファイルを作成します。これは手動またはダイナミックインベントリースクリプトによって行うことができます。詳細については、"独自のインベントリーを構築する"を参照してください。
(3/5) クラスター作成の計画
Kubesprayは多くの点でデプロイメントをカスタマイズする機能を提供します:
- デプロイメントモードの選択: kubeadmまたはnon-kubeadm
- CNI(ネットワーク)プラグイン
- DNS設定
- コントロールプレーンの選択: ネイティブ/バイナリまたはコンテナ化
- コンポーネントバージョン
- Calicoルートリフレクター
- コンポーネントランタイムオプション
- 証明書の生成方法
Kubesprayはvariableファイルによってカスタマイズできます。Kubesprayを使い始めたばかりであれば、Kubesprayのデフォルト設定を使用してクラスターをデプロイし、Kubernetesを探索することを検討してください。
(4/5) クラスターのデプロイ
次にクラスターをデプロイします:
クラスターのデプロイメントにはansible-playbookを使用します。
ansible-playbook -i your/inventory/inventory.ini cluster.yml -b -v \
--private-key=~/.ssh/private_key
大規模なデプロイメント(100以上のノード)では、最適な結果を得るために個別の調整が必要な場合があります。
(5/5) デプロイの確認
Kubesprayは、NetcheckerによるPod間の接続とDNSの解決の検証を行う機能を提供します。Netcheckerは、netchecker-agents Podがdefault名前空間内でDNSリクエストを解決し、互いにpingを送信できることを確かめます。これらのPodは他のワークロードと同様の動作を再現し、クラスターの健全性を示す指標として機能します。
クラスターの操作
Kubesprayはクラスターを管理する追加のプレイブックを提供します: scale と upgrade。
クラスターのスケール
scaleプレイブックを実行することで、クラスターにワーカーノードを追加することができます。詳細については、"ノードの追加"を参照してください。
remove-nodeプレイブックを実行することで、クラスターからワーカーノードを削除することができます。詳細については、"ノードの削除"を参照してください。
クラスターのアップグレード
upgrade-clusterプレイブックを実行することで、クラスターのアップグレードができます。詳細については、"アップグレード"を参照してください。
クリーンアップ
resetプレイブックを使用して、ノードをリセットし、Kubesprayでインストールした全てのコンポーネントを消すことができます。
注意: resetプレイブックを実行する際は、誤ってプロダクションのクラスターを対象にしないように気をつけること!
フィードバック
次の項目
3.3 - ターンキークラウドソリューション
このページは、Kubernetes認定ソリューションプロバイダーのリストを提供します。
各プロバイダーのページから、本番環境でも利用可能なクラスターのインストール方法やセットアップ方法を学ぶことができます。
3.4 - Windows in Kubernetes
3.4.1 - KubernetesのWindowsサポート概要
Windowsアプリケーションは、多くの組織で実行されているサービスやアプリケーションの大部分を占めています。Windowsコンテナは、プロセスとパッケージの依存関係を一つにまとめる最新の方法を提供し、DevOpsプラクティスの使用とWindowsアプリケーションのクラウドネイティブパターンの追求を容易にします。Kubernetesは事実上、標準的なコンテナオーケストレータになりました。Kubernetes 1.14のリリースでは、Kubernetesクラスター内のWindowsノードでWindowsコンテナをスケジューリングする本番環境サポートが含まれたので、Windowsアプリケーションの広大なエコシステムにおいて、Kubernetesを有効的に活用できます。WindowsベースのアプリケーションとLinuxベースのアプリケーションに投資している組織は、ワークロードを管理する個別のオーケストレーターが不要となるため、オペレーティングシステムに関係なくアプリケーション全体の運用効率が向上します。
KubernetesのWindowsコンテナ
KubernetesでWindowsコンテナのオーケストレーションを有効にする方法は、既存のLinuxクラスターにWindowsノードを含めるだけです。KubernetesのPodでWindowsコンテナをスケジュールすることは、Linuxベースのコンテナをスケジュールするのと同じくらいシンプルで簡単です。
Windowsコンテナを実行するには、Kubernetesクラスターに複数のオペレーティングシステムを含める必要があります。コントロールプレーンノードはLinux、ワーカーノードはワークロードのニーズに応じてWindowsまたはLinuxで実行します。Windows Server 2019は、サポートされている唯一のWindowsオペレーティングシステムであり、Windows (kubelet、コンテナランタイム、kube-proxyを含む)でKubernetesノードを有効にします。Windowsディストリビューションチャンネルの詳細については、Microsoftのドキュメントを参照してください。
備考: マスターコンポーネントを含むKubernetesコントロールプレーンは、Linuxで実行し続けます。WindowsのみのKubernetesクラスターを導入する計画はありません。
備考: このドキュメントでは、Windowsコンテナについて説明する場合、プロセス分離のWindowsコンテナを意味します。
Hyper-V分離のWindowsコンテナは、将来リリースが計画されています。
サポートされている機能と制限
サポートされている機能
コンピュート
APIとkubectlの観点から見ると、WindowsコンテナはLinuxベースのコンテナとほとんど同じように動作します。ただし、制限セクションで概説されている主要な機能には、いくつかの顕著な違いがあります。
オペレーティングシステムのバージョンから始めましょう。KubernetesのWindowsオペレーティングシステムのサポートについては、次の表を参照してください。単一の混成Kubernetesクラスターは、WindowsとLinuxの両方のワーカーノードを持つことができます。WindowsコンテナはWindowsノードで、LinuxコンテナはLinuxノードでスケジュールする必要があります。
Kubernetes バージョン |
ホストOS バージョン (Kubernetes ノード) |
|
|
|
Windows Server 1709 |
Windows Server 1803 |
Windows Server 1809/Windows Server 2019 |
Kubernetes v1.14 |
サポートされていません |
サポートされていません |
Windows Server containers Builds 17763.* と Docker EE-basic 18.09 がサポートされています |
備考: すべてのWindowsユーザーがアプリのオペレーティングシステムを頻繁に更新することは望んでいません。アプリケーションのアップグレードは、クラスターに新しいノードをアップグレードまたは導入することを要求する必要があります。Kubernetesで実行されているコンテナのオペレーティングシステムをアップグレードすることを選択したユーザーには、新しいオペレーティングシステムバージョンのサポート追加時に、ガイダンスと段階的な指示を提供します。このガイダンスには、クラスターノードと共にアプリケーションをアップグレードするための推奨アップグレード手順が含まれます。Windowsノードは、現在のLinuxノードと同じように、Kubernetes
バージョンスキューポリシー(ノードからコントロールプレーンのバージョン管理)に準拠しています。
Kubernetesの主要な要素は、WindowsでもLinuxと同じように機能します。このセクションでは、主要なワークロードイネーブラーのいくつかと、それらがWindowsにどのようにマップされるかについて説明します。
-
Pods
Podは、Kubernetesにおける最も基本的な構成要素です。人間が作成またはデプロイするKubernetesオブジェクトモデルの中で最小かつ最もシンプルな単位です。WindowsとLinuxのコンテナを同じPodにデプロイすることはできません。Pod内のすべてのコンテナは、各ノードが特定のプラットフォームとアーキテクチャを表す単一のノードにスケジュールされます。次のPod機能、プロパティ、およびイベントがWindowsコンテナでサポートされています。:
- プロセス分離とボリューム共有を備えたPodごとの単一または複数のコンテナ
- Podステータスフィールド
- ReadinessとLiveness Probe
- postStartとpreStopコンテナのライフサイクルイベント
- 環境変数またはボリュームとしてのConfigMap、 Secrets
- EmptyDir
- 名前付きパイプホストマウント
- リソース制限
-
Controllers
Kubernetesコントローラーは、Podの望ましい状態を処理します。次のワークロードコントローラーは、Windowsコンテナでサポートされています。:
- ReplicaSet
- ReplicationController
- Deployments
- StatefulSets
- DaemonSet
- Job
- CronJob
-
Services
Kubernetes Serviceは、Podの論理セットとPodにアクセスするためのポリシーを定義する抽象概念です。マイクロサービスと呼ばれることもあります。オペレーティングシステム間の接続にServiceを使用できます。WindowsでのServiceは、次のタイプ、プロパティと機能を利用できます。:
- サービス環境変数
- NodePort
- ClusterIP
- LoadBalancer
- ExternalName
- Headless services
Pod、Controller、Serviceは、KubernetesでWindowsワークロードを管理するための重要な要素です。ただし、それだけでは、動的なクラウドネイティブ環境でWindowsワークロードの適切なライフサイクル管理を可能にするのに十分ではありません。次の機能のサポートを追加しました:
- Podとコンテナのメトリクス
- Horizontal Pod Autoscalerサポート
- kubectl Exec
- リソースクォータ
- Schedulerのプリエンプション
コンテナランタイム
Docker EE
FEATURE STATE: Kubernetes v1.14 [stable]
Docker EE-basic 18.09+は、Kubernetesを実行しているWindows Server 2019 / 1809ノードに推奨されるコンテナランタイムです。kubeletに含まれるdockershimコードで動作します。
CRI-ContainerD
FEATURE STATE: Kubernetes v1.18 [alpha]
ContainerDはLinux上のKubernetesで動作するOCI準拠のランタイムです。Kubernetes v1.18では、Windows上でのContainerDのサポートが追加されています。Windows上でのContainerDの進捗状況はenhancements#1001で確認できます。
注意: Kubernetes v1.18におけるWindows上でのContainerDは以下の既知の欠点があります:
- ContainerDは公式リリースではWindowsをサポートしていません。すなわち、Kubernetesでのすべての開発はアクティブなContainerD開発ブランチに対して行われています。本番環境へのデプロイは常に、完全にテストされセキュリティ修正をサポートした公式リリースを利用するべきです。
- ContainerDを利用した場合、Group Managed Service Accountsは実装されていません。詳細はcontainerd/cri#1276を参照してください。
永続ストレージ
Kubernetesボリュームを使用すると、データの永続性とPodボリュームの共有要件を備えた複雑なアプリケーションをKubernetesにデプロイできます。特定のストレージバックエンドまたはプロトコルに関連付けられた永続ボリュームの管理には、ボリュームのプロビジョニング/プロビジョニング解除/サイズ変更、Kubernetesノードへのボリュームのアタッチ/デタッチ、およびデータを永続化する必要があるPod内の個別のコンテナへのボリュームのマウント/マウント解除などのアクションが含まれます。特定のストレージバックエンドまたはプロトコルに対してこれらのボリューム管理アクションを実装するコードは、Kubernetesボリュームプラグインの形式で出荷されます。次の幅広いクラスのKubernetesボリュームプラグインがWindowsでサポートされています。:
In-treeボリュームプラグイン
In-treeボリュームプラグインに関連付けられたコードは、コアKubernetesコードベースの一部として提供されます。In-treeボリュームプラグインのデプロイでは、追加のスクリプトをインストールしたり、個別のコンテナ化されたプラグインコンポーネントをデプロイしたりする必要はありません。これらのプラグインは、ストレージバックエンドでのボリュームのプロビジョニング/プロビジョニング解除とサイズ変更、Kubernetesノードへのボリュームのアタッチ/アタッチ解除、Pod内の個々のコンテナへのボリュームのマウント/マウント解除を処理できます。次のIn-treeプラグインは、Windowsノードをサポートしています。:
FlexVolume Plugins
FlexVolumeプラグインに関連付けられたコードは、ホストに直接デプロイする必要があるout-of-treeのスクリプトまたはバイナリとして出荷されます。FlexVolumeプラグインは、Kubernetesノードとの間のボリュームのアタッチ/デタッチ、およびPod内の個々のコンテナとの間のボリュームのマウント/マウント解除を処理します。FlexVolumeプラグインに関連付けられた永続ボリュームのプロビジョニング/プロビジョニング解除は、通常FlexVolumeプラグインとは別の外部プロビジョニング担当者を通じて処理できます。次のFlexVolumeプラグインは、Powershellスクリプトとしてホストにデプロイされ、Windowsノードをサポートします:
CSIプラグイン
FEATURE STATE: Kubernetes v1.16 [alpha]
CSIプラグインに関連付けられたコードは、通常、コンテナイメージとして配布され、DaemonSetやStatefulSetなどの標準のKubernetesコンポーネントを使用してデプロイされるout-of-treeのスクリプトおよびバイナリとして出荷されます。CSIプラグインは、ボリュームのプロビジョニング/プロビジョニング解除/サイズ変更、Kubernetesノードへのボリュームのアタッチ/ボリュームからのデタッチ、Pod内の個々のコンテナへのボリュームのマウント/マウント解除、バックアップ/スナップショットとクローニングを使用した永続データのバックアップ/リストアといった、Kubernetesの幅広いボリューム管理アクションを処理します。CSIプラグインは通常、ノードプラグイン(各ノードでDaemonSetとして実行される)とコントローラープラグインで構成されます。
CSIノードプラグイン(特に、ブロックデバイスまたは共有ファイルシステムとして公開された永続ボリュームに関連付けられているプラグイン)は、ディスクデバイスのスキャン、ファイルシステムのマウントなど、さまざまな特権操作を実行する必要があります。これらの操作は、ホストオペレーティングシステムごとに異なります。Linuxワーカーノードの場合、コンテナ化されたCSIノードプラグインは通常、特権コンテナとしてデプロイされます。Windowsワーカーノードの場合、コンテナ化されたCSIノードプラグインの特権操作は、csi-proxyを使用してサポートされます。各Windowsノードにプリインストールされている。詳細については、展開するCSIプラグインの展開ガイドを参照してください。
ネットワーキング
Windowsコンテナのネットワークは、CNIプラグインを通じて公開されます。Windowsコンテナは、ネットワークに関して仮想マシンと同様に機能します。各コンテナには、Hyper-V仮想スイッチ(vSwitch)に接続されている仮想ネットワークアダプター(vNIC)があります。Host Network Service(HNS)とHost Compute Service(HCS)は連携してコンテナを作成し、コンテナvNICをネットワークに接続します。HCSはコンテナの管理を担当するのに対し、HNSは次のようなネットワークリソースの管理を担当します。:
- 仮想ネットワーク(vSwitchの作成を含む)
- エンドポイント/vNIC
- 名前空間
- ポリシー(パケットのカプセル化、負荷分散ルール、ACL、NATルールなど)
次のServiceタイプがサポートされています。:
- NodePort
- ClusterIP
- LoadBalancer
- ExternalName
Windowsは、L2bridge、L2tunnel、Overlay、Transparent、NATの5つの異なるネットワークドライバー/モードをサポートしています。WindowsとLinuxのワーカーノードを持つ異種クラスターでは、WindowsとLinuxの両方で互換性のあるネットワークソリューションを選択する必要があります。以下のツリー外プラグインがWindowsでサポートされており、各CNIをいつ使用するかに関する推奨事項があります。:
ネットワークドライバー |
説明 |
コンテナパケットの変更 |
ネットワークプラグイン |
ネットワークプラグインの特性 |
L2bridge |
コンテナは外部のvSwitchに接続されます。コンテナはアンダーレイネットワークに接続されますが、物理ネットワークはコンテナのMACを上り/下りで書き換えるため、MACを学習する必要はありません。コンテナ間トラフィックは、コンテナホスト内でブリッジされます。 |
MACはホストのMACに書き換えられ、IPは変わりません。 |
win-bridge、Azure-CNI、Flannelホストゲートウェイは、win-bridgeを使用します。 |
win-bridgeはL2bridgeネットワークモードを使用して、コンテナをホストのアンダーレイに接続して、最高のパフォーマンスを提供します。ノード間接続にはユーザー定義ルート(UDR)が必要です。 |
L2Tunnel |
これはl2bridgeの特殊なケースですが、Azureでのみ使用されます。すべてのパケットは、SDNポリシーが適用されている仮想化ホストに送信されます。 |
MACが書き換えられ、IPがアンダーレイネットワークで表示されます。 |
Azure-CNI |
Azure-CNIを使用すると、コンテナをAzure vNETと統合し、Azure Virtual Networkが提供する一連の機能を活用できます。たとえば、Azureサービスに安全に接続するか、Azure NSGを使用します。azure-cniのいくつかの例を参照してください。 |
オーバーレイ(KubernetesのWindows用のオーバーレイネットワークは アルファ 段階です) |
コンテナには、外部のvSwitchに接続されたvNICが付与されます。各オーバーレイネットワークは、カスタムIPプレフィックスで定義された独自のIPサブネットを取得します。オーバーレイネットワークドライバーは、VXLANを使用してカプセル化します。 |
外部ヘッダーでカプセル化されます。 |
Win-overlay、Flannel VXLAN (win-overlayを使用) |
win-overlayは、仮想コンテナネットワークをホストのアンダーレイから分離する必要がある場合に使用する必要があります(セキュリティ上の理由など)。データセンター内のIPが制限されている場合に、(異なるVNIDタグを持つ)異なるオーバーレイネットワークでIPを再利用できるようにします。このオプションには、Windows Server 2019でKB4489899が必要です。 |
透過的(ovn-kubernetesの特別な使用例) |
外部のvSwitchが必要です。コンテナは外部のvSwitchに接続され、論理ネットワーク(論理スイッチおよびルーター)を介したPod内通信を可能にします。 |
パケットは、GENEVEまたはSTTトンネリングを介してカプセル化され、同じホスト上にないポッドに到達します。パケットは、ovnネットワークコントローラーによって提供されるトンネルメタデータ情報を介して転送またはドロップされます。NATは南北通信のために行われます。 |
ovn-kubernetes |
ansible経由でデプロイします。分散ACLは、Kubernetesポリシーを介して適用できます。 IPAMをサポートします。負荷分散は、kube-proxyなしで実現できます。 NATは、iptables/netshを使用せずに行われます。 |
NAT(Kubernetesでは使用されません) |
コンテナには、内部のvSwitchに接続されたvNICが付与されます。DNS/DHCPは、WinNATと呼ばれる内部コンポーネントを使用して提供されます。 |
MACおよびIPはホストMAC/IPに書き換えられます。 |
nat |
完全を期すためにここに含まれています。 |
上で概説したように、Flannel CNIメタプラグインは、VXLANネットワークバックエンド(アルファサポート、win-overlayへのデリゲート)およびホストゲートウェイネットワークバックエンド(安定したサポート、win-bridgeへのデリゲート)を介してWindowsでもサポートされます。このプラグインは、参照CNIプラグイン(win-overlay、win-bridge)の1つへの委任をサポートし、WindowsのFlannelデーモン(Flanneld)と連携して、ノードのサブネットリースの自動割り当てとHNSネットワークの作成を行います。このプラグインは、独自の構成ファイル(cni.conf)を読み取り、FlannelDで生成されたsubnet.envファイルからの環境変数と統合します。次に、ネットワークプラミング用の参照CNIプラグインの1つに委任し、ノード割り当てサブネットを含む正しい構成をIPAMプラグイン(ホストローカルなど)に送信します。
Node、Pod、およびServiceオブジェクトの場合、TCP/UDPトラフィックに対して次のネットワークフローがサポートされます。:
- Pod -> Pod (IP)
- Pod -> Pod (Name)
- Pod -> Service (Cluster IP)
- Pod -> Service (PQDN、ただし、「.」がない場合のみ)
- Pod -> Service (FQDN)
- Pod -> External (IP)
- Pod -> External (DNS)
- Node -> Pod
- Pod -> Node
Windowsでは、次のIPAMオプションがサポートされています。
制限
コントロールプレーン
Windowsは、Kubernetesアーキテクチャとコンポーネントマトリックスのワーカーノードとしてのみサポートされています。つまり、Kubernetesクラスターには常にLinuxマスターノード、0以上のLinuxワーカーノード、0以上のWindowsワーカーノードが含まれている必要があります。
コンピュート
リソース管理とプロセス分離
Linux cgroupsは、Linuxのリソースを制御するPodの境界として使用されます。コンテナは、ネットワーク、プロセス、およびファイルシステムを分離するのために、その境界内に作成されます。cgroups APIを使用して、cpu/io/memoryの統計を収集できます。対照的に、Windowsはシステムネームスペースフィルターを備えたコンテナごとのジョブオブジェクトを使用して、コンテナ内のすべてのプロセスを格納し、ホストからの論理的な分離を提供します。ネームスペースフィルタリングを行わずにWindowsコンテナを実行する方法はありません。これは、ホストの環境ではシステム特権を主張できないため、Windowsでは特権コンテナを使用できないことを意味します。セキュリティアカウントマネージャー(SAM)が独立しているため、コンテナはホストからIDを引き受けることができません。
オペレーティングシステムの制限
Windowsには厳密な互換性ルールがあり、ホストOSのバージョンとコンテナのベースイメージOSのバージョンは、一致する必要があります。Windows Server 2019のコンテナオペレーティングシステムを備えたWindowsコンテナのみがサポートされます。Hyper-V分離のコンテナは、Windowsコンテナのイメージバージョンに下位互換性を持たせることは、将来のリリースで計画されています。
機能制限
- TerminationGracePeriod:実装されていません
- 単一ファイルのマッピング:CRI-ContainerDで実装されます
- 終了メッセージ:CRI-ContainerDで実装されます
- 特権コンテナ:現在Windowsコンテナではサポートされていません
- HugePages:現在Windowsコンテナではサポートされていません
- 既存のノード問題を検出する機能はLinux専用であり、特権コンテナが必要です。一般的に、特権コンテナはサポートされていないため、これがWindowsで使用されることは想定していません。
- ネームスペース共有については、すべての機能がサポートされているわけではありません(詳細については、APIセクションを参照してください)
メモリ予約と処理
Windowsには、Linuxのようなメモリ不足のプロセスキラーはありません。Windowsは常に全ユーザーモードのメモリ割り当てを仮想として扱い、ページファイルは必須です。正味の効果は、WindowsはLinuxのようなメモリ不足の状態にはならず、メモリ不足(OOM)終了の影響を受ける代わりにページをディスクに処理します。メモリが過剰にプロビジョニングされ、物理メモリのすべてが使い果たされると、ページングによってパフォーマンスが低下する可能性があります。
2ステップのプロセスで、メモリ使用量を妥当な範囲内に保つことが可能です。まず、kubeletパラメーター--kubelet-reserve
や--system-reserve
を使用して、ノード(コンテナ外)でのメモリ使用量を明確にします。これにより、NodeAllocatable)が削減されます。ワークロードをデプロイするときは、コンテナにリソース制限をかけます(制限のみを設定するか、制限が要求と等しくなければなりません)。これにより、NodeAllocatableも差し引かれ、ノードのリソースがフルな状態になるとSchedulerがPodを追加できなくなります。
過剰なプロビジョニングを回避するためのベストプラクティスは、Windows、Docker、およびKubernetesのプロセスに対応するために、最低2GBのメモリを予約したシステムでkubeletを構成することです。
フラグの振舞いについては、次のような異なる動作をします。:
--kubelet-reserve
、--system-reserve
、および--eviction-hard
フラグはノードの割り当て可能数を更新します
--enforce-node-allocable
を使用した排除は実装されていません
--eviction-hard
および--eviction-soft
を使用した排除は実装されていません
- MemoryPressureの制約は実装されていません
- kubeletによって実行されるOOMを排除することはありません
- Windowsノードで実行されているKubeletにはメモリ制限がありません。
--kubelet-reserve
と--system-reserve
は、ホストで実行されているkubeletまたはプロセスに制限を設定しません。これは、ホスト上のkubeletまたはプロセスが、NodeAllocatableとSchedulerの外でメモリリソース不足を引き起こす可能性があることを意味します。
ストレージ
Windowsには、コンテナレイヤーをマウントして、NTFSに基づいて複製されたファイルシステムを作るためのレイヤー構造のファイルシステムドライバーがあります。コンテナ内のすべてのファイルパスは、そのコンテナの環境内だけで決められます。
- ボリュームマウントは、コンテナ内のディレクトリのみを対象にすることができ、個別のファイルは対象にできません
- ボリュームマウントは、ファイルまたはディレクトリをホストファイルシステムに投影することはできません
- WindowsレジストリとSAMデータベースには常に書き込みアクセスが必要であるため、読み取り専用ファイルシステムはサポートされていません。ただし、読み取り専用ボリュームはサポートされています
- ボリュームのユーザーマスクと権限は使用できません。SAMはホストとコンテナ間で共有されないため、それらの間のマッピングはありません。すべての権限はコンテナの環境内で決められます
その結果、次のストレージ機能はWindowsノードではサポートされません。
- ボリュームサブパスのマウント。Windowsコンテナにマウントできるのはボリューム全体だけです。
- シークレットのサブパスボリュームのマウント
- ホストマウントプロジェクション
- DefaultMode(UID/GID依存関係による)
- 読み取り専用のルートファイルシステム。マップされたボリュームは引き続き読み取り専用をサポートします
- ブロックデバイスマッピング
- 記憶媒体としてのメモリ
- uui/guid、ユーザーごとのLinuxファイルシステム権限などのファイルシステム機能
- NFSベースのストレージ/ボリュームのサポート
- マウントされたボリュームの拡張(resizefs)
ネットワーキング
Windowsコンテナネットワーキングは、Linuxネットワーキングとはいくつかの重要な実装方法の違いがあります。Microsoft documentation for Windows Container Networkingには、追加の詳細と背景があります。
Windowsホストネットワーキングサービスと仮想スイッチはネームスペースを実装して、Podまたはコンテナの必要に応じて仮想NICを作成できます。ただし、DNS、ルート、メトリックなどの多くの構成は、Linuxのような/etc/...ファイルではなく、Windowsレジストリデータベースに保存されます。コンテナのWindowsレジストリはホストのレジストリとは別であるため、ホストからコンテナへの/etc/resolv.confのマッピングなどの概念は、Linuxの場合と同じ効果をもたらしません。これらは、そのコンテナの環境で実行されるWindows APIを使用して構成する必要があります。したがって、CNIの実装は、ファイルマッピングに依存する代わりにHNSを呼び出して、ネットワークの詳細をPodまたはコンテナに渡す必要があります。
次のネットワーク機能はWindowsノードではサポートされていません
- ホストネットワーキングモードはWindows Podでは使用できません
- ノード自体からのローカルNodePortアクセスは失敗します(他のノードまたは外部クライアントで機能)
- ノードからのService VIPへのアクセスは、Windows Serverの将来のリリースで利用可能になる予定です
- kube-proxyのオーバーレイネットワーキングサポートはアルファリリースです。さらに、KB4482887がWindows Server 2019にインストールされている必要があります
- ローカルトラフィックポリシーとDSRモード
- l2bridge、l2tunnel、またはオーバーレイネットワークに接続されたWindowsコンテナは、IPv6スタックを介した通信をサポートしていません。これらのネットワークドライバーがIPv6アドレスを使用できるようにするために必要な機能として、優れたWindowsプラットフォームの機能があり、それに続いて、kubelet、kube-proxy、およびCNIプラグインといったKubernetesの機能があります。
- win-overlay、win-bridge、およびAzure-CNIプラグインを介したICMPプロトコルを使用したアウトバウンド通信。具体的には、Windowsデータプレーン(VFP)は、ICMPパケットの置き換えをサポートしていません。これの意味は:
- 同じネットワーク内の宛先に向けられたICMPパケット(pingを介したPod間通信など)は期待どおりに機能し、制限はありません
- TCP/UDPパケットは期待どおりに機能し、制限はありません
- リモートネットワーク(Podからping経由の外部インターネット通信など)を通過するように指示されたICMPパケットは置き換えできないため、ソースにルーティングされません。
- TCP/UDPパケットは引き続き置き換えできるため、
ping <destination>
をcurl <destination>
に置き換えることで、外部への接続をデバッグできます。
これらの機能はKubernetes v1.15で追加されました。
CNIプラグイン
- Windowsリファレンスネットワークプラグインのwin-bridgeとwin-overlayは、CNI仕様v0.4.0において「CHECK」実装がないため、今のところ実装されていません。
- Flannel VXLAN CNIについては、Windowsで次の制限があります。:
- Node-podの直接間接続は設計上不可能です。FlannelPR 1096を使用するローカルPodでのみ可能です
- VNI 4096とUDPポート4789の使用に制限されています。VNIの制限は現在取り組んでおり、将来のリリースで解決される予定です(オープンソースのflannelの変更)。これらのパラメーターの詳細については、公式のFlannel VXLANバックエンドのドキュメントをご覧ください。
DNS
- ClusterFirstWithHostNetは、DNSでサポートされていません。Windowsでは、FQDNとしてすべての名前を「.」で扱い、PQDNでの名前解決はスキップします。
- Linuxでは、PQDNで名前解決しようとするときに使用するDNSサフィックスリストがあります。Windowsでは、1つのDNSサフィックスしかありません。これは、そのPodのNamespaceに関連付けられているDNSサフィックスです(たとえば、mydns.svc.cluster.local)。Windowsでは、そのサフィックスだけで名前解決可能なFQDNおよびServiceまたはNameでの名前解決ができます。たとえば、defaultのNamespaceで生成されたPodには、DNSサフィックスdefault.svc.cluster.localが付けられます。WindowsのPodでは、kubernetes.default.svc.cluster.localとkubernetesの両方を名前解決できますが、kubernetes.defaultやkubernetes.default.svcのような中間での名前解決はできません。
- Windowsでは、複数のDNSリゾルバーを使用できます。これらには少し異なる動作が付属しているため、ネームクエリの解決には
Resolve-DNSName
ユーティリティを使用することをお勧めします。
セキュリティ
Secretはノードのボリュームに平文テキストで書き込まれます(Linuxのtmpfs/in-memoryの比較として)。これはカスタマーが2つのことを行う必要があります
- ファイルACLを使用してSecretファイルの場所を保護する
- BitLockerを使って、ボリュームレベルの暗号化を使用する
RunAsUserは、現在Windowsではサポートされていません。回避策は、コンテナをパッケージ化する前にローカルアカウントを作成することです。RunAsUsername機能は、将来のリリースで追加される可能性があります。
SELinux、AppArmor、Seccomp、特性(POSIX機能)のような、Linux固有のPodセキュリティ環境の権限はサポートされていません。
さらに、既に述べたように特権付きコンテナは、Windowsにおいてサポートされていません。
API
ほとんどのKubernetes APIがWindowsでも機能することに違いはありません。そのわずかな違いはOSとコンテナランタイムの違いによるものです。特定の状況では、PodやコンテナなどのワークロードAPIの一部のプロパティが、Linuxで実装されているが、Windowsでは実行できないことを前提に設計されています。
高いレベルで、これらOSのコンセプトに違いがります。:
- ID - Linuxでは、Integer型として表されるuserID(UID)とgroupID(GID)を使用します。ユーザー名とグループ名は正規ではありません - それらは、UID+GIDの背後にある
/etc/groups
または/etc/passwd
の単なるエイリアスです。Windowsは、Windows Security Access Manager(SAM)データベースに格納されているより大きなバイナリセキュリティ識別子(SID)を使用します。このデータベースは、ホストとコンテナ間、またはコンテナ間で共有されません。
- ファイル権限 - Windowsは、権限とUID+GIDのビットマスクではなく、SIDに基づくアクセス制御リストを使用します
- ファイルパス - Windowsの規則では、
/
ではなく\
を使用します。Go IOライブラリは通常両方を受け入れ、それを機能させるだけですが、コンテナ内で解釈されるパスまたはコマンドラインを設定する場合、\
が必要になる場合があります。
- シグナル - Windowsのインタラクティブなアプリは終了を異なる方法で処理し、次の1つ以上を実装できます。:
- UIスレッドは、WM_CLOSEを含む明確に定義されたメッセージを処理します
- コンソールアプリは、コントロールハンドラーを使用してctrl-cまたはctrl-breakを処理します
- サービスは、SERVICE_CONTROL_STOP制御コードを受け入れることができるサービスコントロールハンドラー関数を登録します。
終了コードは、0が成功、0以外が失敗の場合と同じ規則に従います。特定のエラーコードは、WindowsとLinuxで異なる場合があります。ただし、Kubernetesのコンポーネント(kubelet、kube-proxy)から渡される終了コードは変更されていません。
V1.Container
- V1.Container.ResourceRequirements.limits.cpuおよびV1.Container.ResourceRequirements.limits.memory - Windowsは、CPU割り当てにハード制限を使用しません。代わりに、共有システムが使用されます。ミリコアに基づく既存のフィールドは、Windowsスケジューラーによって追従される相対共有にスケーリングされます。参照: kuberuntime/helpers_windows.go、参照: resource controls in Microsoft docs
- Huge Pagesは、Windowsコンテナランタイムには実装されてないので、使用できません。コンテナに対して設定できないユーザー特権を主張する必要があります。
- V1.Container.ResourceRequirements.requests.cpuおよびV1.Container.ResourceRequirements.requests.memory - リクエストはノードの利用可能なリソースから差し引かれるので、ノードのオーバープロビジョニングを回避するために使用できます。ただし、過剰にプロビジョニングされたノードのリソースを保証するために使用することはできません。オペレーターが完全にプロビジョニングし過ぎないようにする場合は、ベストプラクティスとしてこれらをすべてのコンテナに適用する必要があります。
- V1.Container.SecurityContext.allowPrivilegeEscalation - Windowsでは使用できません、接続されている機能はありません
- V1.Container.SecurityContext.Capabilities - POSIX機能はWindowsでは実装されていません
- V1.Container.SecurityContext.privileged - Windowsでは特権コンテナをサポートしていません
- V1.Container.SecurityContext.procMount - Windowsでは/procファイルシステムがありません
- V1.Container.SecurityContext.readOnlyRootFilesystem - Windowsでは使用できません、レジストリおよびシステムプロセスがコンテナ内で実行するには、書き込みアクセスが必要です
- V1.Container.SecurityContext.runAsGroup - Windowsでは使用できません、GIDのサポートもありません
- V1.Container.SecurityContext.runAsNonRoot - Windowsではrootユーザーが存在しません。最も近いものは、ノードに存在しないIDであるContainerAdministratorです。
- V1.Container.SecurityContext.runAsUser - Windowsでは使用できません。intとしてのUIDはサポートされていません。
- V1.Container.SecurityContext.seLinuxOptions - Windowsでは使用できません、SELinuxがありません
- V1.Container.terminationMessagePath - これは、Windowsが単一ファイルのマッピングをサポートしないという点でいくつかの制限があります。デフォルト値は/dev/termination-logであり、デフォルトではWindowsに存在しないため動作します。
V1.Pod
- V1.Pod.hostIPC、v1.pod.hostpid - Windowsではホストのネームスペースを共有することはできません
- V1.Pod.hostNetwork - ホストのネットワークを共有するためのWindows OSサポートはありません
- V1.Pod.dnsPolicy - ClusterFirstWithHostNet - Windowsではホストネットワーキングがサポートされていないため、サポートされていません。
- V1.Pod.podSecurityContext - 以下のV1.PodSecurityContextを参照
- V1.Pod.shareProcessNamespace - これはベータ版の機能であり、Windowsに実装されていないLinuxのNamespace機能に依存しています。Windowsでは、プロセスのネームスペースまたはコンテナのルートファイルシステムを共有できません。共有できるのはネットワークだけです。
- V1.Pod.terminationGracePeriodSeconds - これはWindowsのDockerに完全には実装されていません。リファレンスを参照してください。今日の動作では、ENTRYPOINTプロセスにCTRL_SHUTDOWN_EVENTが送信され、Windowsではデフォルトで5秒待機し、最後に通常のWindowsシャットダウン動作を使用してすべてのプロセスをシャットダウンします。5秒のデフォルトは、実際にはWindowsレジストリーコンテナ内にあるため、コンテナ作成時にオーバーライドできます。
- V1.Pod.volumeDevices - これはベータ機能であり、Windowsには実装されていません。Windowsでは、rawブロックデバイスをPodに接続できません。
- V1.Pod.volumes-EmptyDir、Secret、ConfigMap、HostPath - すべて動作し、TestGridにテストがあります
- V1.emptyDirVolumeSource - ノードのデフォルトのメディアはWindowsのディスクです。Windowsでは、RAMディスクが組み込まれていないため、メモリはサポートされていません。
- V1.VolumeMount.mountPropagation - mount propagationは、Windowsではサポートされていません。
V1.PodSecurityContext
Windowsでは、PodSecurityContextフィールドはどれも機能しません。これらは参照用にここにリストされています。
- V1.PodSecurityContext.SELinuxOptions - SELinuxは、Windowsでは使用できません
- V1.PodSecurityContext.RunAsUser - UIDを提供しますが、Windowsでは使用できません
- V1.PodSecurityContext.RunAsGroup - GIDを提供しますが、Windowsでは使用できません
- V1.PodSecurityContext.RunAsNonRoot - Windowsにはrootユーザーがありません。最も近いものは、ノードに存在しないIDであるContainerAdministratorです。
- V1.PodSecurityContext.SupplementalGroups - GIDを提供しますが、Windowsでは使用できません
- V1.PodSecurityContext.Sysctls - これらはLinuxのsysctlインターフェースの一部です。Windowsには同等のものはありません。
ヘルプとトラブルシューティングを学ぶ
Kubernetesクラスターのトラブルシューティングの主なヘルプソースは、トラブルシューティングページから始める必要があります。このセクションには、いくつか追加的な、Windows固有のトラブルシューティングヘルプが含まれています。ログは、Kubernetesにおけるトラブルシューティング問題の重要な要素です。他のコントリビューターからトラブルシューティングの支援を求めるときは、必ずそれらを含めてください。SIG-Windowsログ収集に関するコントリビュートガイドの指示に従ってください。
-
start.ps1が正常に完了したことをどのように確認できますか?
ノード上でkubelet、kube-proxy、および(ネットワーキングソリューションとしてFlannelを選択した場合)flanneldホストエージェントプロセスが実行され、実行ログが個別のPowerShellウィンドウに表示されます。これに加えて、WindowsノードがKubernetesクラスターで「Ready」として表示されているはずです。
-
Kubernetesノードのプロセスをサービスとしてバックグラウンドで実行するように構成できますか?
Kubeletとkube-proxyは、ネイティブのWindowsサービスとして実行するように既に構成されています、障害(例えば、プロセスのクラッシュ)が発生した場合にサービスを自動的に再起動することにより、復元性を提供します。これらのノードコンポーネントをサービスとして構成するには、2つのオプションがあります。
-
ネイティブWindowsサービスとして
Kubeletとkube-proxyは、sc.exe
を使用してネイティブのWindowsサービスとして実行できます。
# 2つの個別のコマンドでkubeletおよびkube-proxyのサービスを作成する
sc.exe create <component_name> binPath= "<path_to_binary> --service <other_args>"
# 引数にスペースが含まれている場合は、エスケープする必要があることに注意してください。
sc.exe create kubelet binPath= "C:\kubelet.exe --service --hostname-override 'minion' <other_args>"
# サービスを開始する
Start-Service kubelet
Start-Service kube-proxy
# サービスを停止する
Stop-Service kubelet (-Force)
Stop-Service kube-proxy (-Force)
# サービスの状態を問い合わせる
Get-Service kubelet
Get-Service kube-proxy
-
nssm.exeの使用
また、nssm.exeなどの代替サービスマネージャーを使用して、これらのプロセス(flanneld、kubelet、kube-proxy)をバックグラウンドで実行することもできます。このサンプルスクリプトを使用すると、nssm.exeを利用してkubelet、kube-proxy、flanneld.exeを登録し、Windowsサービスとしてバックグラウンドで実行できます。
register-svc.ps1 -NetworkMode <Network mode> -ManagementIP <Windows Node IP> -ClusterCIDR <Cluster subnet> -KubeDnsServiceIP <Kube-dns Service IP> -LogDir <Directory to place logs>
# NetworkMode = ネットワークソリューションとして選択されたネットワークモードl2bridge(flannel host-gw、これもデフォルト値)またはoverlay(flannel vxlan)
# ManagementIP = Windowsノードに割り当てられたIPアドレス。 ipconfigを使用してこれを見つけることができます
# ClusterCIDR = クラスターのサブネット範囲。(デフォルト値 10.244.0.0/16)
# KubeDnsServiceIP = Kubernetes DNSサービスIP(デフォルト値 10.96.0.10)
# LogDir = kubeletおよびkube-proxyログがそれぞれの出力ファイルにリダイレクトされるディレクトリ(デフォルト値 C:\k)
上記のスクリプトが適切でない場合は、次の例を使用してnssm.exeを手動で構成できます。
# flanneld.exeを登録する
nssm install flanneld C:\flannel\flanneld.exe
nssm set flanneld AppParameters --kubeconfig-file=c:\k\config --iface=<ManagementIP> --ip-masq=1 --kube-subnet-mgr=1
nssm set flanneld AppEnvironmentExtra NODE_NAME=<hostname>
nssm set flanneld AppDirectory C:\flannel
nssm start flanneld
# kubelet.exeを登録
# マイクロソフトは、mcr.microsoft.com/k8s/core/pause:1.2.0としてポーズインフラストラクチャコンテナをリリース
nssm install kubelet C:\k\kubelet.exe
nssm set kubelet AppParameters --hostname-override=<hostname> --v=6 --pod-infra-container-image=mcr.microsoft.com/k8s/core/pause:1.2.0 --resolv-conf="" --allow-privileged=true --enable-debugging-handlers --cluster-dns=<DNS-service-IP> --cluster-domain=cluster.local --kubeconfig=c:\k\config --hairpin-mode=promiscuous-bridge --image-pull-progress-deadline=20m --cgroups-per-qos=false --log-dir=<log directory> --logtostderr=false --enforce-node-allocatable="" --network-plugin=cni --cni-bin-dir=c:\k\cni --cni-conf-dir=c:\k\cni\config
nssm set kubelet AppDirectory C:\k
nssm start kubelet
# kube-proxy.exeを登録する (l2bridge / host-gw)
nssm install kube-proxy C:\k\kube-proxy.exe
nssm set kube-proxy AppDirectory c:\k
nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --hostname-override=<hostname>--kubeconfig=c:\k\config --enable-dsr=false --log-dir=<log directory> --logtostderr=false
nssm.exe set kube-proxy AppEnvironmentExtra KUBE_NETWORK=cbr0
nssm set kube-proxy DependOnService kubelet
nssm start kube-proxy
# kube-proxy.exeを登録する (overlay / vxlan)
nssm install kube-proxy C:\k\kube-proxy.exe
nssm set kube-proxy AppDirectory c:\k
nssm set kube-proxy AppParameters --v=4 --proxy-mode=kernelspace --feature-gates="WinOverlay=true" --hostname-override=<hostname> --kubeconfig=c:\k\config --network-name=vxlan0 --source-vip=<source-vip> --enable-dsr=false --log-dir=<log directory> --logtostderr=false
nssm set kube-proxy DependOnService kubelet
nssm start kube-proxy
最初のトラブルシューティングでは、nssm.exeで次のフラグを使用して、stdoutおよびstderrを出力ファイルにリダイレクトできます。:
nssm set <Service Name> AppStdout C:\k\mysvc.log
nssm set <Service Name> AppStderr C:\k\mysvc.log
詳細については、公式のnssmの使用法のドキュメントを参照してください。
-
Windows Podにネットワーク接続がありません
仮想マシンを使用している場合は、すべてのVMネットワークアダプターでMACスプーフィングが有効になっていることを確認してください。
-
Windows Podが外部リソースにpingできません
現在、Windows Podには、ICMPプロトコル用にプログラムされた送信ルールはありません。ただし、TCP/UDPはサポートされています。クラスター外のリソースへの接続を実証する場合は、ping <IP>
に対応するcurl <IP>
コマンドに置き換えてください。
それでも問題が解決しない場合は、cni.confのネットワーク構成に値する可能性があるので、いくつかの特別な注意が必要です。この静的ファイルはいつでも編集できます。構成の更新は、新しく作成されたすべてのKubernetesリソースに適用されます。
Kubernetesのネットワーキング要件の1つ(参照Kubernetesモデル)は、内部でNATを使用せずにクラスター通信を行うためのものです。この要件を遵守するために、すべての通信にExceptionListがあり、アウトバウンドNATが発生しないようにします。ただし、これは、クエリしようとしている外部IPをExceptionListから除外する必要があることも意味します。そうして初めて、Windows PodからのトラフィックがSNAT処理され、外部からの応答を受信できるようになります。この点で、cni.conf
のExceptionListは次のようになります。:
"ExceptionList": [
"10.244.0.0/16", # クラスターのサブネット
"10.96.0.0/12", # Serviceのサブネット
"10.127.130.0/24" # 管理 (ホスト) のサブネット
]
-
WindowsノードがNodePort Serviceにアクセスできません
ノード自体からのローカルNodePortアクセスは失敗します。これは既知の制限です。NodePortアクセスは、他のノードまたは外部クライアントから行えます。
-
コンテナのvNICとHNSエンドポイントが削除されています
この問題は、hostname-override
パラメーターがkube-proxyに渡されない場合に発生する可能性があります。これを解決するには、ユーザーは次のようにホスト名をkube-proxyに渡す必要があります。:
C:\k\kube-proxy.exe --hostname-override=$(hostname)
-
flannelを使用すると、クラスターに再参加した後、ノードに問題が発生します
以前に削除されたノードがクラスターに再参加するときはいつも、flannelDは新しいPodサブネットをノードに割り当てようとします。ユーザーは、次のパスにある古いPodサブネット構成ファイルを削除する必要があります。:
Remove-Item C:\k\SourceVip.json
Remove-Item C:\k\SourceVipRequest.json
-
start.ps1
を起動した後、flanneldが「ネットワークが作成されるのを待っています」と表示されたままになります
この調査中の問題に関する多数の報告があります。最も可能性が高いのは、flannelネットワークの管理IPが設定されるタイミングの問題です。回避策は、単純にstart.ps1を再起動するか、次のように手動で再起動することです。:
PS C:> [Environment]::SetEnvironmentVariable("NODE_NAME", "<Windows_Worker_Hostname>")
PS C:> C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface=<Windows_Worker_Node_IP> --ip-masq=1 --kube-subnet-mgr=1
-
/run/flannel/subnet.env
がないため、Windows Podを起動できません
これは、Flannelが正しく起動しなかったことを示しています。 flanneld.exeの再起動を試みるか、Kubernetesマスターの/run/flannel/subnet.env
からWindowsワーカーノードのC:\run\flannel\subnet.env
に手動でファイルをコピーすることができます。「FLANNEL_SUBNET」行を別の番号に変更します。たとえば、ノードサブネット10.244.4.1/24が必要な場合は以下となります。:
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.4.1/24
FLANNEL_MTU=1500
FLANNEL_IPMASQ=true
-
WindowsノードがService IPを使用してServiceにアクセスできない
これは、Windows上の現在のネットワークスタックの既知の制限です。ただし、Windows PodはService IPにアクセスできます。
-
kubeletの起動時にネットワークアダプターが見つかりません
WindowsネットワーキングスタックがKubernetesネットワーキングを動かすには、仮想アダプターが必要です。次のコマンドを実行しても結果が返されない場合(管理シェルで)、仮想ネットワークの作成(Kubeletが機能するために必要な前提条件)に失敗したことになります。:
Get-HnsNetwork | ? Name -ieq "cbr0"
Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*"
ホストのネットワークアダプターが「イーサネット」ではない場合、多くの場合、start.ps1スクリプトのInterfaceNameパラメーターを修正する価値があります。そうでない場合はstart-kubelet.ps1
スクリプトの出力結果を調べて、仮想ネットワークの作成中にエラーがないか確認します。
-
Podが「Container Creating」と表示されたまま動かなくなったり、何度も再起動を繰り返します
PauseイメージがOSバージョンと互換性があることを確認してください。説明では、OSとコンテナの両方がバージョン1803であると想定しています。それ以降のバージョンのWindowsを使用している場合は、Insiderビルドなどでは、それに応じてイメージを調整する必要があります。イメージについては、MicrosoftのDockerレジストリを参照してください。いずれにしても、PauseイメージのDockerfileとサンプルサービスの両方で、イメージに:latestのタグが付けられていると想定しています。
Kubernetes v1.14以降、MicrosoftはPauseインフラストラクチャコンテナをmcr.microsoft.com/k8s/core/pause:1.2.0
でリリースしています。
-
DNS名前解決が正しく機能していない
このセクションでDNSの制限を確認してください。
-
kubectl port-forward
が「ポート転送を実行できません:wincatが見つかりません」で失敗します
これはKubernetes 1.15、およびPauseインフラストラクチャコンテナmcr.microsoft.com/k8s/core/pause:1.2.0
で実装されました。必ずこれらのバージョン以降を使用してください。
独自のPauseインフラストラクチャコンテナを構築する場合は、必ずwincatを含めてください。
-
Windows Serverノードがプロキシの背後にあるため、Kubernetesのインストールが失敗します
プロキシの背後にある場合は、次のPowerShell環境変数を定義する必要があります。:
[Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine)
[Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine)
-
pause
コンテナとは何ですか
Kubernetes Podでは、インフラストラクチャまたは「pause」コンテナが最初に作成され、コンテナエンドポイントをホストします。インフラストラクチャやワーカーコンテナなど、同じPodに属するコンテナは、共通のネットワークネームスペースとエンドポイント(同じIPとポートスペース)を共有します。Pauseコンテナは、ネットワーク構成を失うことなくクラッシュまたは再起動するワーカーコンテナに対応するために必要です。
「pause」(インフラストラクチャ)イメージは、Microsoft Container Registry(MCR)でホストされています。docker pull mcr.microsoft.com/k8s/core/pause:1.2.0
を使用してアクセスできます。詳細については、DOCKERFILEをご覧ください。
さらなる調査
これらの手順で問題が解決しない場合は、次の方法で、KubernetesのWindowsノードでWindowsコンテナを実行する際のヘルプを利用できます。:
IssueとFeatureリクエストの報告
バグのようなものがある場合、またはFeatureリクエストを行う場合は、GitHubのIssueシステムを使用してください。GitHubでIssueを開いて、SIG-Windowsに割り当てることができます。以前に報告された場合は、まずIssueリストを検索し、Issueについての経験をコメントして、追加のログを加える必要があります。SIG-Windows Slackは、チケットを作成する前に、初期サポートとトラブルシューティングのアイデアを得るための素晴らしい手段でもあります。
バグを報告する場合は、問題の再現方法に関する次のような詳細情報を含めてください。:
- Kubernetesのバージョン: kubectlのバージョン
- 環境の詳細: クラウドプロバイダー、OSのディストリビューション、選択したネットワーキングと構成、およびDockerのバージョン
- 問題を再現するための詳細な手順
- 関連するログ
/sig windows
でIssueにコメントして、Issueにsig/windowsのタグを付けて、SIG-Windowsメンバーが気付くようにします
次の項目
ロードマップには多くの機能があります。高レベルの簡略リストを以下に示しますが、ロードマッププロジェクトを見て、貢献することによってWindowsサポートを改善することをお勧めします。
Hyper-V分離
Hyper-V分離はKubernetesで以下のWindowsコンテナのユースケースを実現するために必要です。
- Pod間のハイパーバイザーベースの分離により、セキュリティを強化
- 下位互換性により、コンテナの再構築を必要とせずにノードで新しいWindows Serverバージョンを実行
- Podの特定のCPU/NUMA設定
- メモリの分離と予約
既存のHyper-V分離サポートは、v1.10の試験的な機能であり、上記のCRI-ContainerD機能とRuntimeClass機能を優先して将来廃止される予定です。現在の機能を使用してHyper-V分離コンテナを作成するには、kubeletのフィーチャーゲートをHyperVContainer=true
で開始し、Podにアノテーションexperimental.windows.kubernetes.io/isolation-type=hyperv
を含める必要があります。実験的リリースでは、この機能はPodごとに1つのコンテナに制限されています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: iis
spec:
selector:
matchLabels:
app: iis
replicas: 3
template:
metadata:
labels:
app: iis
annotations:
experimental.windows.kubernetes.io/isolation-type: hyperv
spec:
containers:
- name: iis
image: microsoft/iis
ports:
- containerPort: 80
kubeadmとクラスターAPIを使用したデプロイ
Kubeadmは、ユーザーがKubernetesクラスターをデプロイするための事実上の標準になりつつあります。kubeadmのWindowsノードのサポートは進行中ですが、ガイドはすでにここで利用可能です。Windowsノードが適切にプロビジョニングされるように、クラスターAPIにも投資しています。
その他の主な機能
- グループ管理サービスアカウントのベータサポート
- その他のCNI
- その他のストレージプラグイン
3.4.2 - KubernetesでWindowsコンテナをスケジュールするためのガイド
Windowsアプリケーションは、多くの組織で実行されるサービスとアプリケーションの大部分を占めます。このガイドでは、KubernetesでWindowsコンテナを構成してデプロイする手順について説明します。
目的
- WindowsノードでWindowsコンテナを実行するサンプルのDeploymentを構成します
- (オプション)Group Managed Service Accounts(GMSA)を使用してPodのActive Directory IDを構成します
始める前に
はじめに:Windowsコンテナのデプロイ
WindowsコンテナをKubernetesにデプロイするには、最初にサンプルアプリケーションを作成する必要があります。以下のYAMLファイルの例では、簡単なウェブサーバーアプリケーションを作成しています。以下の内容でwin-webserver.yaml
という名前のサービススペックを作成します。:
apiVersion: v1
kind: Service
metadata:
name: win-webserver
labels:
app: win-webserver
spec:
ports:
# このサービスが提供するポート
- port: 80
targetPort: 80
selector:
app: win-webserver
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: win-webserver
name: win-webserver
spec:
replicas: 2
selector:
matchLabels:
app: win-webserver
template:
metadata:
labels:
app: win-webserver
name: win-webserver
spec:
containers:
- name: windowswebserver
image: mcr.microsoft.com/windows/servercore:ltsc2019
command:
- powershell.exe
- -command
- "<#code used from https://gist.github.com/19WAS85/5424431#> ; $$listener = New-Object System.Net.HttpListener ; $$listener.Prefixes.Add('http://*:80/') ; $$listener.Start() ; $$callerCounts = @{} ; Write-Host('Listening at http://*:80/') ; while ($$listener.IsListening) { ;$$context = $$listener.GetContext() ;$$requestUrl = $$context.Request.Url ;$$clientIP = $$context.Request.RemoteEndPoint.Address ;$$response = $$context.Response ;Write-Host '' ;Write-Host('> {0}' -f $$requestUrl) ; ;$$count = 1 ;$$k=$$callerCounts.Get_Item($$clientIP) ;if ($$k -ne $$null) { $$count = $$k } ;$$callerCounts.Set_Item($$clientIP, $$count) ;$$ip=(Get-NetAdapter | Get-NetIpAddress); $$header='<html><body><H1>Windows Container Web Server</H1>' ;$$callerCountsString='' ;$$callerCounts.Keys | % { $$callerCountsString='<p>IP {0} callerCount {1} ' -f $$ip[1].IPAddress,$$callerCounts.Item($$_) } ;$$footer='</body></html>' ;$$content='{0}{1}{2}' -f $$header,$$callerCountsString,$$footer ;Write-Output $$content ;$$buffer = [System.Text.Encoding]::UTF8.GetBytes($$content) ;$$response.ContentLength64 = $$buffer.Length ;$$response.OutputStream.Write($$buffer, 0, $$buffer.Length) ;$$response.Close() ;$$responseStatus = $$response.StatusCode ;Write-Host('< {0}' -f $$responseStatus) } ; "
nodeSelector:
kubernetes.io/os: windows
備考: ポートマッピングもサポートされていますが、この例では簡単にするために、コンテナポート80がサービスに直接公開されています。
-
すべてのノードが正常であることを確認します。:
-
Serviceをデプロイして、Podの更新を確認します。:
kubectl apply -f win-webserver.yaml
kubectl get pods -o wide -w
Serviceが正しくデプロイされると、両方のPodがReadyとして表示されます。watch状態のコマンドを終了するには、Ctrl + Cを押します。
-
デプロイが成功したことを確認します。検証するために行うこと:
- WindowsノードのPodごとの2つのコンテナに
docker ps
します
- Linuxマスターからリストされた2つのPodに
kubectl get pods
します
- ネットワークを介したノードとPod間通信、LinuxマスターからのPod IPのポート80に向けて
curl
して、ウェブサーバーの応答をチェックします
- docker execまたはkubectl execを使用したPod間通信、Pod間(および複数のWindowsノードがある場合はホスト間)へのpingします
- ServiceからPodへの通信、Linuxマスターおよび個々のPodからの仮想Service IP(
kubectl get services
で表示される)にcurl
します
- サービスディスカバリ、Kubernetesのdefault DNS suffixと共にService名に
curl
します
- Inbound connectivity,
curl
the NodePort from the Linux master or machines outside of the cluster
- インバウンド接続、Linuxマスターまたはクラスター外のマシンからNodePortに
curl
します
- アウトバウンド接続、kubectl execを使用したPod内からの外部IPに
curl
します
備考: 今のところ、Windowsネットワークスタックのプラットフォーム制限のため、Windowsコンテナホストは、ホストされているサービスのIPにアクセスできません。Service IPにアクセスできるのは、Windows Podだけです。
可観測性
ワークロードからのログキャプチャ
ログは可観測性の重要な要素です。これにより、ユーザーはワークロードの運用面に関する洞察を得ることができ、問題のトラブルシューティングの主要な要素になります。WindowsコンテナとWindowsコンテナ内のワークロードの動作はLinuxコンテナとは異なるため、ユーザーはログの収集に苦労し、運用の可視性が制限されていました。たとえば、Windowsワークロードは通常、ETW(Windowsのイベントトレース)にログを記録するか、アプリケーションイベントログにエントリをプッシュするように構成されます。MicrosoftのオープンソースツールであるLogMonitorは、Windowsコンテナ内の構成されたログソースを監視するための推奨方法です。LogMonitorは、イベントログ、ETWプロバイダー、カスタムアプリケーションログのモニタリングをサポートしており、それらをSTDOUTにパイプして、kubectl logs <pod>
で使用できます。
LogMonitor GitHubページの指示に従って、バイナリと構成ファイルをすべてのコンテナにコピーして、LogMonitorがログをSTDOUTにプッシュするために必要なエントリーポイントを追加します。
構成可能なコンテナのユーザー名の使用
Kubernetes v1.16以降、Windowsコンテナは、イメージのデフォルトとは異なるユーザー名でエントリーポイントとプロセスを実行するように構成できます。これが達成される方法は、Linuxコンテナで行われる方法とは少し異なります。詳しくはこちら.
Group Managed Service AccountsによるワークロードIDの管理
Kubernetes v1.14以降、Windowsコンテナワークロードは、Group Managed Service Accounts(GMSA)を使用するように構成できます。Group Managed Service Accountsは、自動パスワード管理、簡略化されたサービスプリンシパル名(SPN)管理、および複数のサーバー間で他の管理者に管理を委任する機能を提供する特定の種類のActive Directoryアカウントです。GMSAで構成されたコンテナは、GMSAで構成されたIDを保持しながら、外部Active Directoryドメインリソースにアクセスできます。Windowsコンテナ用のGMSAの構成と使用の詳細はこちら。
TaintsとTolerations
今日のユーザーは、LinuxとWindowsのワークロードをそれぞれのOS固有のノードで維持するために、Taintsとノードセレクターのいくつかの組み合わせを使用する必要があります。これはおそらくWindowsユーザーにのみ負担をかけます。推奨されるアプローチの概要を以下に示します。主な目標の1つは、このアプローチによって既存のLinuxワークロードの互換性が損なわれないようにすることです。
OS固有のワークロードが適切なコンテナホストに確実に到達するようにする
ユーザーは、TaintsとTolerationsを使用して、Windowsコンテナを適切なホストでスケジュールできるようにすることができます。現在、すべてのKubernetesノードには次のデフォルトラベルがあります。:
- kubernetes.io/os = [windows|linux]
- kubernetes.io/arch = [amd64|arm64|...]
Podの仕様で"kubernetes.io/os": windows
のようなnodeSelectorが指定されていない場合、PodをWindowsまたはLinuxの任意のホストでスケジュールすることができます。WindowsコンテナはWindowsでのみ実行でき、LinuxコンテナはLinuxでのみ実行できるため、これは問題になる可能性があります。ベストプラクティスは、nodeSelectorを使用することです。
ただし、多くの場合、ユーザーには既存の多数のLinuxコンテナのdeployment、およびコミュニティHelmチャートのような既成構成のエコシステムやOperatorのようなプログラム的にPodを生成するケースがあることを理解しています。このような状況では、nodeSelectorsを追加するための構成変更をためらう可能性があります。代替策は、Taintsを使用することです。kubeletは登録中にTaintsを設定できるため、Windowsだけで実行する時に自動的にTaintを追加するように簡単に変更できます。
例:--register-with-taints='os=windows:NoSchedule'
すべてのWindowsノードにTaintを追加することにより、それらには何もスケジュールされません(既存のLinuxPodを含む)。Windows PodがWindowsノードでスケジュールされるためには、nodeSelectorがWindowsを選択することと、適切にマッチするTolerationが必要です。
nodeSelector:
kubernetes.io/os: windows
node.kubernetes.io/windows-build: '10.0.17763'
tolerations:
- key: "os"
operator: "Equal"
value: "windows"
effect: "NoSchedule"
同じクラスター内の複数Windowsバージョンの管理
各Podで使用されるWindows Serverのバージョンは、ノードのバージョンと一致している必要があります。
同じクラスター内で複数のWindows Serverバージョンを使用したい場合は、追加のノードラベルとnodeSelectorsを設定する必要があります。
Kubernetes 1.17では、これを簡単するために新しいラベルnode.kubernetes.io/windows-build
が自動的に追加されます。古いバージョンを実行している場合は、このラベルをWindowsノードに手動で追加することをお勧めします。
このラベルは、互換性のために一致する必要があるWindowsのメジャー、マイナー、およびビルド番号を反映しています。以下は、Windows Serverの各バージョンで現在使用されている値です。
製品番号 |
ビルド番号 |
Windows Server 2019 |
10.0.17763 |
Windows Server version 1809 |
10.0.17763 |
Windows Server version 1903 |
10.0.18362 |
RuntimeClassによる簡素化
RuntimeClassは、TaintsとTolerationsを使用するプロセスを簡略化するために使用できます。クラスター管理者は、これらのTaintsとTolerationsをカプセル化するために使用するRuntimeClass
オブジェクトを作成できます。
- このファイルを
runtimeClasses.yml
に保存します。これには、Windows OS、アーキテクチャ、およびバージョンに適切なnodeSelector
が含まれています。
apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
name: windows-2019
handler: 'docker'
scheduling:
nodeSelector:
kubernetes.io/os: 'windows'
kubernetes.io/arch: 'amd64'
node.kubernetes.io/windows-build: '10.0.17763'
tolerations:
- effect: NoSchedule
key: os
operator: Equal
value: "windows"
- クラスター管理者として使用する
kubectl create -f runtimeClasses.yml
を実行します
- Podの仕様に応じて
runtimeClassName: windows-2019
を追加します
例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: iis-2019
labels:
app: iis-2019
spec:
replicas: 1
template:
metadata:
name: iis-2019
labels:
app: iis-2019
spec:
runtimeClassName: windows-2019
containers:
- name: iis
image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
resources:
limits:
cpu: 1
memory: 800Mi
requests:
cpu: .1
memory: 300Mi
ports:
- containerPort: 80
selector:
matchLabels:
app: iis-2019
---
apiVersion: v1
kind: Service
metadata:
name: iis
spec:
type: LoadBalancer
ports:
- protocol: TCP
port: 80
selector:
app: iis-2019
4 - ベストプラクティス
4.1 - 大規模クラスターの構築
クラスターはKubernetesのエージェントが動作する(物理もしくは仮想の)ノードの集合で、コントロールプレーンによって管理されます。
Kubernetes v1.29 では、最大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は、クラスターのスケールが変化したときにアドオンの自動的なリサイズをお手伝いします。
4.2 - 複数のゾーンで動かす
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
備考: バージョン1.3以降のKubernetesは設定したゾーンを跨いでPVクレームを分配します。
バージョン1.2では動的永続ボリュームは常にクラスターのマスターがあるゾーンに作成されます。
(ここではus-central1-a / us-west-2a); このイシューは
(
#23330)
にバージョン1.3以降で記載されています。
それでは、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の上に設定します:
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
4.3 - ノードのセットアップの検証
ノード適合テスト
ノード適合テスト は、システムの検証とノードに対する機能テストを提供するコンテナ型のテストフレームワークです。このテストは、ノードがKubernetesの最小要件を満たしているかどうかを検証するもので、テストに合格したノードはKubernetesクラスターに参加する資格があることになります。
ノードの前提条件
適合テストを実行するにはノードは通常のKubernetesノードと同じ前提条件を満たしている必要があります。 最低でもノードに以下のデーモンがインストールされている必要があります:
- コンテナランタイム (Docker)
- Kubelet
ノード適合テストの実行
ノード適合テストを実行するには、以下の手順に従います:
-
kubeletの--kubeconfig
オプションの値を調べます。例:--kubeconfig=/var/lib/kubelet/config.yaml
。
このテストフレームワークはKubeletのテスト用にローカルコントロールプレーンを起動するため、APIサーバーのURLとしてhttp://localhost:8080
を使用します。
他にも使用できるkubeletコマンドラインパラメーターがいくつかあります:
--cloud-provider
: --cloud-provider=gce
を指定している場合は、テストを実行する前にこのフラグを取り除いてください。
-
以下のコマンドでノード適合テストを実行します:
# $CONFIG_DIRはKubeletのPodのマニフェストパスです。
# $LOG_DIRはテスト出力のパスです。
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
registry.k8s.io/node-test:0.2
他アーキテクチャ向けのノード適合テストの実行
Kubernetesは他のアーキテクチャ用のノード適合テストのdockerイメージを提供しています:
Arch |
Image |
amd64 |
node-test-amd64 |
arm |
node-test-arm |
arm64 |
node-test-arm64 |
選択したテストの実行
特定のテストを実行するには、環境変数FOCUS
を実行したいテストの正規表現で上書きします。
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
-e FOCUS=MirrorPod \ # MirrorPodテストのみを実行します
registry.k8s.io/node-test:0.2
特定のテストをスキップするには、環境変数SKIP
をスキップしたいテストの正規表現で上書きします。
sudo docker run -it --rm --privileged --net=host \
-v /:/rootfs:ro -v $CONFIG_DIR:$CONFIG_DIR -v $LOG_DIR:/var/result \
-e SKIP=MirrorPod \ # MirrorPodテスト以外のすべてのノード適合テストを実行します
registry.k8s.io/node-test:0.2
ノード適合テストは、node e2e testのコンテナ化されたバージョンです。
デフォルトでは、すべての適合テストが実行されます。
理論的には、コンテナを構成し必要なボリュームを適切にマウントすれば、どのノードのe2eテストも実行できます。しかし、不適合テストを実行するためにはより複雑な設定が必要となるため、適合テストのみを実行することを強く推奨します。
注意事項
- このテストでは、ノード適合テストイメージや機能テストで使用されるコンテナのイメージなど、いくつかのdockerイメージがノード上に残ります。
- このテストでは、ノード上にデッドコンテナが残ります。これらのコンテナは機能テスト中に作成されます。
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,key |
kubernetes-ca |
Kubernetes全体の認証局 |
etcd/ca.crt,key |
etcd-ca |
etcd用 |
front-proxy-ca.crt,key |
kubernetes-front-proxy-ca |
front-end proxy用 |
上記の認証局に加えて、サービスアカウント管理用に公開鍵/秘密鍵のペア(sa.key
とsa.pub
)を取得する事が必要です。
全ての証明書
CAの秘密鍵をクラスターにコピーしたくない場合、自身で全ての証明書を作成できます。
必要な証明書:
デフォルトCN |
親認証局 |
組織 |
種類 |
ホスト名 (SAN) |
kube-etcd |
etcd-ca |
|
server, client |
<hostname> , <Host_IP> , localhost , 127.0.0.1 |
kube-etcd-peer |
etcd-ca |
|
server, client |
<hostname> , <Host_IP> , localhost , 127.0.0.1 |
kube-etcd-healthcheck-client |
etcd-ca |
|
client |
|
kube-apiserver-etcd-client |
etcd-ca |
|
client |
|
kube-apiserver |
kubernetes-ca |
|
server |
<hostname> , <Host_IP> , <advertise_IP> , [1] |
kube-apiserver-kubelet-client |
kubernetes-ca |
system:masters |
client |
|
front-proxy-client |
kubernetes-front-proxy-ca |
|
client |
|
[1]: クラスターに接続するIPおよびDNS名( kubeadmを使用する場合と同様、ロードバランサーのIPおよびDNS名、kubernetes
、kubernetes.default
、kubernetes.default.svc
、kubernetes.default.svc.cluster
、kubernetes.default.svc.cluster.local
)
kind
は下記のx509の鍵用途のタイプにマッピングされます:
種類 |
鍵の用途 |
server |
digital signature, key encipherment, server auth |
client |
digital signature, key encipherment, client auth |
備考: 上記に挙げられたホスト名(SAN)は、クラスターを動作させるために推奨されるものです。
特別なセットアップが求められる場合、全てのサーバー証明書にSANを追加する事ができます。
備考: kubeadm利用者のみ:
- 秘密鍵なしでCA証明書をクラスターにコピーするシナリオは、kubeadmドキュメントの外部認証局の項目で言及されています。
- kubeadmでPKIを生成すると、
kube-etcd
、kube-etcd-peer
および kube-etcd-healthcheck-client
証明書は外部etcdを利用するケースでは生成されない事に留意してください。
証明書のパス
証明書は推奨パスに配置するべきです(kubeadmを使用する場合と同様)。
パスは場所に関係なく与えられた引数で特定されます。
デフォルトCN |
鍵の推奨パス |
証明書の推奨パス |
コマンド |
鍵を指定する引数 |
証明書を指定する引数 |
etcd-ca |
etcd/ca.key |
etcd/ca.crt |
kube-apiserver |
|
--etcd-cafile |
kube-apiserver-etcd-client |
apiserver-etcd-client.key |
apiserver-etcd-client.crt |
kube-apiserver |
--etcd-keyfile |
--etcd-certfile |
kubernetes-ca |
ca.key |
ca.crt |
kube-apiserver |
|
--client-ca-file |
kubernetes-ca |
ca.key |
ca.crt |
kube-controller-manager |
--cluster-signing-key-file |
--client-ca-file, --root-ca-file, --cluster-signing-cert-file |
kube-apiserver |
apiserver.key |
apiserver.crt |
kube-apiserver |
--tls-private-key-file |
--tls-cert-file |
kube-apiserver-kubelet-client |
apiserver-kubelet-client.key |
apiserver-kubelet-client.crt |
kube-apiserver |
--kubelet-client-key |
--kubelet-client-certificate |
front-proxy-ca |
front-proxy-ca.key |
front-proxy-ca.crt |
kube-apiserver |
|
--requestheader-client-ca-file |
front-proxy-ca |
front-proxy-ca.key |
front-proxy-ca.crt |
kube-controller-manager |
|
--requestheader-client-ca-file |
front-proxy-client |
front-proxy-client.key |
front-proxy-client.crt |
kube-apiserver |
--proxy-client-key-file |
--proxy-client-cert-file |
etcd-ca |
etcd/ca.key |
etcd/ca.crt |
etcd |
|
--trusted-ca-file, --peer-trusted-ca-file |
kube-etcd |
etcd/server.key |
etcd/server.crt |
etcd |
--key-file |
--cert-file |
kube-etcd-peer |
etcd/peer.key |
etcd/peer.crt |
etcd |
--peer-key-file |
--peer-cert-file |
etcd-ca |
|
etcd/ca.crt |
etcdctl |
|
--cacert |
kube-etcd-healthcheck-client |
etcd/healthcheck-client.key |
etcd/healthcheck-client.crt |
etcdctl |
--key |
--cert |
サービスアカウント用の鍵ペアについても同様です。
秘密鍵のパス |
公開鍵のパス |
コマンド |
引数 |
sa.key |
|
kube-controller-manager |
service-account-private |
|
sa.pub |
kube-apiserver |
service-account-key |
ユーザアカウント用に証明書を設定する
管理者アカウントおよびサービスアカウントは手動で設定しなければなりません。
ファイル名 |
クレデンシャル名 |
デフォルトCN |
組織 |
admin.conf |
default-admin |
kubernetes-admin |
system:masters |
kubelet.conf |
default-auth |
system:node:<nodeName> (see note) |
system:nodes |
controller-manager.conf |
default-controller-manager |
system:kube-controller-manager |
|
scheduler.conf |
default-scheduler |
system:kube-scheduler |
|
備考: kubelet.conf
における
<nodeName>
の値は
必ずAPIサーバーに登録されたkubeletのノード名と一致しなければなりません。詳細は、
Node Authorizationを参照してください。
-
各コンフィグ毎に、CN名と組織を指定してx509証明書と鍵ペアを生成してください。
-
以下のように、各コンフィグで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.conf |
kubectl |
クラスターの管理者設定用 |
kubelet.conf |
kubelet |
クラスターの各ノードに1つ必要です。 |
controller-manager.conf |
kube-controller-manager |
manifests/kube-controller-manager.yaml のマニフェストファイルに追記する必要があります。 |
scheduler.conf |
kube-scheduler |
manifests/kube-scheduler.yaml のマニフェストファイルに追記する必要があります。 |