Kubernetesドキュメントのこのセクションには、個々のタスクの実行方法を示すページが含まれています。タスクページは、通常、短い手順を実行することにより、1つのことを行う方法を示します。
タスクページを作成したい場合は、ドキュメントのPull Requestの作成を参照してください。
これは、このセクションの複数ページの印刷可能なビューです。 印刷するには、ここをクリックしてください.
Kubernetesドキュメントのこのセクションには、個々のタスクの実行方法を示すページが含まれています。タスクページは、通常、短い手順を実行することにより、1つのことを行う方法を示します。
タスクページを作成したい場合は、ドキュメントのPull Requestの作成を参照してください。
Kubernetesのコマンドラインツールkubectl
を使用すると、Kubernetesクラスターに対してコマンドを実行できるようになります。
kubectlは、アプリケーションのデプロイ、クラスターリソースの調査と管理、ログの表示などに使用できます。
kubectlの操作の完全なリストを含む詳細については、kubectl
のリファレンスドキュメントを参照してください。
kubectlはさまざまなLinuxプラットフォーム、macOS、Windows上にインストールできます。 下記の中から好きなオペレーティングシステムを選んでください。
kind
を使うと、ローカルのコンピューター上でKubernetesを実行することができます。
このツールはDockerとPodmanのどちらかのインストールが必要です。
Quick Startに、kindの起動と実行に必要なことが書かれています。
kind
と同じように、minikubeは、Kubernetesをローカルで実行するツールです。
minikube
はオールインワンまたはマルチノードのローカルKubernetesクラスターをパーソナルコンピューター上(Windows、macOS、Linux PCを含む)で実行することで、Kubernetesを試したり、日常的な開発作業のために利用できます。
ツールのインストールについて知りたい場合は、公式のGet Started!のガイドに従ってください。
minikubeが起動したら、サンプルアプリケーションの実行を試すことができます。
Kubernetesクラスターの作成、管理をするためにkubeadmツールを使用することができます。
最低限実行可能でセキュアなクラスタを、ユーザーフレンドリーな方法で稼働させるために必要なアクションを実行します。
kubeadmのインストールでは、kubeadmをインストールする方法を示しています。 一度インストールすれば、クラスターを作成するために使用できます。
kubectlのバージョンは、クラスターのマイナーバージョンとの差分が1つ以内でなければなりません。 たとえば、クライアントがv1.32であれば、v1.31、v1.32、v1.33のコントロールプレーンと通信できます。 最新の互換性のあるバージョンのkubectlを使うことで、不測の事態を避けることができるでしょう。
Linuxへkubectlをインストールするには、次の方法があります:
次のコマンドにより、最新リリースをダウンロードしてください:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl"
特定のバージョンをダウンロードする場合、コマンドの$(curl -L -s https://dl.k8s.io/release/stable.txt)
の部分を特定のバージョンに書き換えてください。
たとえば、Linux x86-64へ1.32.0のバージョンをダウンロードするには、次のコマンドを入力します:
curl -LO https://dl.k8s.io/release/v1.32.0/bin/linux/amd64/kubectl
そして、Linux ARM64に対しては、次のコマンドを入力します:
curl -LO https://dl.k8s.io/release/v1.32.0/bin/linux/arm64/kubectl
バイナリを検証してください(オプション)
kubectlのチェックサムファイルをダウンロードします:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl.sha256"
チェックサムファイルに対してkubectlバイナリを検証します:
echo "$(cat kubectl.sha256) kubectl" | sha256sum --check
正しければ、出力は次のようになります:
kubectl: OK
チェックに失敗すると、sha256
は0以外のステータスで終了し、次のような出力を表示します:
kubectl: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
kubectlをインストールしてください
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
ターゲットシステムにルートアクセスを持っていない場合でも、~/.local/bin
ディレクトリにkubectlをインストールできます:
chmod +x kubectl
mkdir -p ~/.local/bin
mv ./kubectl ~/.local/bin/kubectl
# そして ~/.local/bin を $PATH の末尾 (または先頭) に追加します
インストールしたバージョンが最新であることを確認してください:
kubectl version --client
または、バージョンの詳細を表示するために次を使用します:
kubectl version --client --output=yaml
apt
のパッケージ一覧を更新し、Kubernetesのapt
リポジトリを利用するのに必要なパッケージをインストールしてください:
sudo apt-get update
# apt-transport-httpsはダミーパッケージの可能性があります。その場合、そのパッケージはスキップできます
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
Kubernetesパッケージリポジトリの公開署名キーをダウンロードしてください。 すべてのリポジトリに同じ署名キーが使用されるため、URL内のバージョンは無視できます:
# `/etc/apt/keyrings`フォルダーが存在しない場合は、curlコマンドの前に作成する必要があります。下記の備考を参照してください。
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg # 特権のないAPTプログラムがこのkeyringを読めるようにします
/etc/apt/keyrings
フォルダーは既定では存在しないため、curlコマンドの前に作成する必要があります。適切なKubernetesのapt
リポジトリを追加してください。
v1.32とは異なるKubernetesバージョンを利用したい場合は、以下のコマンドのv1.32を目的のマイナーバージョンに置き換えてください:
# これにより、/etc/apt/sources.list.d/kubernetes.listにある既存の設定が上書きされます
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list # command-not-foundのようなツールが正しく動作するようにします
apt-get update
とapt-get upgrade
を実行する前に、/etc/apt/sources.list.d/kubernetes.list
の中のバージョンを上げる必要があります。
この手順についてはChanging The Kubernetes Package Repositoryに詳細が記載されています。apt
のパッケージインデックスを更新し、kubectlをインストールしてください:
sudo apt-get update
sudo apt-get install -y kubectl
Kubernetesのyum
リポジトリを追加してください。
v1.32とは異なるKubernetesバージョンを利用したい場合は、以下のコマンドのv1.32を目的のマイナーバージョンに置き換えてください:
# これにより、/etc/yum.repos.d/kubernetes.repoにある既存の設定が上書きされます
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/repodata/repomd.xml.key
EOF
yum update
を実行する前に、/etc/yum.repos.d/kubernetes.repo
の中のバージョンを上げる必要があります。
この手順についてはChanging The Kubernetes Package Repositoryに詳細が記載されています。yum
を使用してkubectlをインストールしてください:
sudo yum install -y kubectl
Kubernetesのzypper
リポジトリを追加してください。
v1.32とは異なるKubernetesバージョンを利用したい場合は、以下のコマンドのv1.32を目的のマイナーバージョンに置き換えてください。
# これにより、/etc/zypp/repos.d/kubernetes.repoにある既存の設定が上書きされます
cat <<EOF | sudo tee /etc/zypp/repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.32/rpm/repodata/repomd.xml.key
EOF
zypper update
を実行する前に、/etc/zypp/repos.d/kubernetes.repo
の中のバージョンを上げる必要があります。
この手順についてはChanging The Kubernetes Package Repositoryに詳細が記載されています。zypper
を使用してkubectlをインストールしてください:
sudo zypper install -y kubectl
kubectlがKubernetesクラスターを探索し接続するために、kubeconfigファイルが必要です。
これは、kube-up.shによりクラスターを作成した際や、Minikubeクラスターを正常にデプロイした際に自動生成されます。
デフォルトでは、kubectlの設定は~/.kube/config
に格納されています。
クラスターの状態を取得し、kubectlが適切に設定されていることを確認してください:
kubectl cluster-info
URLのレスポンスが表示されている場合は、kubectlはクラスターに接続するよう正しく設定されています。
以下のようなメッセージが表示されている場合は、kubectlは正しく設定されていないか、Kubernetesクラスターに接続できていません。
The connection to the server <server-name:port> was refused - did you specify the right host or port?
たとえば、ラップトップ上(ローカル環境)でKubernetesクラスターを起動するような場合、Minikubeなどのツールを最初にインストールしてから、上記のコマンドを再実行する必要があります。
kubectl cluster-info
がURLレスポンスを返したにもかかわらずクラスターにアクセスできない場合は、次のコマンドで設定が正しいことを確認してください:
kubectl cluster-info dump
Kubernetes 1.26にて、kubectlは以下のクラウドプロバイダーが提供するマネージドKubernetesのビルトイン認証を削除しました。 これらのプロバイダーは、クラウド固有の認証を提供するkubectlプラグインをリリースしています。 手順については以下のプロバイダーのドキュメントを参照してください:
(この変更とは関係なく、他の理由で同じエラーメッセージが表示される可能性もあります。)
kubectlはBash、Zsh、Fish、PowerShellの自動補完を提供しています。 これにより、入力を大幅に削減することができます。
以下にBash、Fish、Zshの自動補完の設定手順を示します。
Bashにおけるkubectlの補完スクリプトはkubectl completion bash
コマンドで生成できます。
補完スクリプトをシェル内に読み込ませることでkubectlの自動補完が有効になります。
ただし、補完スクリプトはbash-completionに依存しているため、事前にインストールしておく必要があります(type _init_completion
を実行することで、bash-completionがすでにインストールされていることを確認できます)。
bash-completionは多くのパッケージマネージャーから提供されています(こちらを参照してください)。
apt-get install bash-completion
またはyum install bash-completion
などでインストールできます。
上記のコマンドでbash-completionの主要スクリプトである/usr/share/bash-completion/bash_completion
が作成されます。
パッケージマネージャーによっては、このファイルを~/.bashrc
にて手動で読み込ませる必要があります。
これを調べるには、シェルをリロードしてからtype _init_completion
を実行してください。
コマンドが成功していればすでに設定済みです。そうでなければ、~/.bashrc
ファイルに以下を追記してください:
source /usr/share/bash-completion/bash_completion
シェルをリロードし、type _init_completion
を実行してbash-completionが正しくインストールされていることを検証してください。
次に、kubectl補完スクリプトがすべてのシェルセッションで読み込まれるように設定する必要があります。 これを行うには2つの方法があります:
echo 'source <(kubectl completion bash)' >>~/.bashrc
kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
sudo chmod a+r /etc/bash_completion.d/kubectl
kubectlにエイリアスを張っている場合は、エイリアスでも動作するようにシェルの補完を拡張することができます:
echo 'alias k=kubectl' >>~/.bashrc
echo 'complete -o default -F __start_kubectl k' >>~/.bashrc
/etc/bash_completion.d
内のすべての補完スクリプトを読み込みます。どちらも同様の手法です。 シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。 シェルの現在のセッションでbashの自動補完を有効にするには、~/.bashrcを読み込みます:
source ~/.bashrc
Fishにおけるkubectlの補完スクリプトはkubectl completion fish
コマンドで生成できます。
補完スクリプトをシェル内に読み込ませることでkubectlの自動補完が有効になります。
すべてのシェルセッションで使用するには、~/.config/fish/config.fish
に以下を追記してください:
kubectl completion fish | source
シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。
Zshにおけるkubectlの補完スクリプトはkubectl completion zsh
コマンドで生成できます。
補完スクリプトをシェル内に読み込ませることでkubectlの自動補完が有効になります。
すべてのシェルセッションで使用するには、~/.zshrc
に以下を追記してください:
source <(kubectl completion zsh)
kubectlにエイリアスを張っている場合でも、kubectlの自動補完は自動的に機能します。
シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。
2: command not found: compdef
のようなエラーが出力された場合は、以下を~/.zshrc
の先頭に追記してください:
autoload -Uz compinit
compinit
kubectl convert
プラグインをインストールする異なるAPIバージョン間でマニフェストを変換できる、Kubernetesコマンドラインツールkubectl
のプラグインです。
これは特に、新しいKubernetesのリリースで、非推奨ではないAPIバージョンにマニフェストを移行する場合に役に立ちます。
詳細については非推奨ではないAPIへの移行を参照してください。
次のコマンドを使用して最新リリースをダウンロードしてください:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl-convert"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl-convert"
バイナリを検証してください(オプション)
kubectl-convertのチェックサムファイルをダウンロードします:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl-convert.sha256"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl-convert.sha256"
チェックサムファイルに対してkubectl-convertバイナリを検証します:
echo "$(cat kubectl-convert.sha256) kubectl-convert" | sha256sum --check
正しければ、出力は次のようになります:
kubectl-convert: OK
チェックに失敗すると、sha256
は0以外のステータスで終了し、次のような出力を表示します:
kubectl-convert: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
kubectl-convertをインストールしてください
sudo install -o root -g root -m 0755 kubectl-convert /usr/local/bin/kubectl-convert
プラグインが正常にインストールできたことを確認してください
kubectl convert --help
何もエラーが表示されない場合は、プラグインが正常にインストールされたことを示しています。
プラグインのインストール後、インストールファイルを削除してください:
rm kubectl-convert kubectl-convert.sha256
kubectlのバージョンは、クラスターのマイナーバージョンとの差分が1つ以内でなければなりません。 たとえば、クライアントがv1.32であれば、v1.31、v1.32、v1.33のコントロールプレーンと通信できます。 最新の互換性のあるバージョンのkubectlを使うことで、不測の事態を避けることができるでしょう。
macOSへkubectlをインストールするには、次の方法があります:
最新リリースをダウンロードしてください:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
特定のバージョンをダウンロードする場合、コマンドの$(curl -L -s https://dl.k8s.io/release/stable.txt)
の部分を特定のバージョンに置き換えてください。
例えば、Intel macOSへ1.32.0のバージョンをダウンロードするには、次のコマンドを入力します:
curl -LO "https://dl.k8s.io/release/v1.32.0/bin/darwin/amd64/kubectl"
Appleシリコン上のmacOSに対しては、次を入力します:
curl -LO "https://dl.k8s.io/release/v1.32.0/bin/darwin/arm64/kubectl"
バイナリを検証してください(オプション)
kubectlのチェックサムファイルをダウンロードします:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl.sha256"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl.sha256"
チェックサムファイルに対してkubectlバイナリを検証します:
echo "$(cat kubectl.sha256) kubectl" | shasum -a 256 --check
正しければ、出力は次のようになります:
kubectl: OK
チェックに失敗すると、shasum
は0以外のステータスで終了し、次のような出力を表示します:
kubectl: FAILED
shasum: WARNING: 1 computed checksum did NOT match
kubectlバイナリを実行可能にしてください。
chmod +x ./kubectl
kubectlバイナリをPATH
の中に移動させてください。
sudo mv ./kubectl /usr/local/bin/kubectl
sudo chown root: /usr/local/bin/kubectl
/usr/local/bin
がPATH環境変数の中に含まれるようにしてください。インストールしたバージョンが最新であることを確認してください:
kubectl version --client
または、バージョンの詳細を表示するために次を使用します:
kubectl version --client --output=yaml
kubectlをインストールし、検証した後は、チェックサムファイルを削除してください:
rm kubectl.sha256
macOSでHomebrewパッケージマネージャーを使用していれば、Homebrewでkubectlをインストールできます。
インストールコマンドを実行してください:
brew install kubectl
または
brew install kubernetes-cli
インストールしたバージョンが最新であることを確認してください:
kubectl version --client
macOSでMacPortsパッケージマネージャーを使用していれば、MacPortsでkubectlをインストールできます。
インストールコマンドを実行してください:
sudo port selfupdate
sudo port install kubectl
インストールしたバージョンが最新であることを確認してください:
kubectl version --client
kubectlがKubernetesクラスターを探索し接続するために、kubeconfigファイルが必要です。
これは、kube-up.shによりクラスターを作成した際や、Minikubeクラスターを正常にデプロイした際に自動生成されます。
デフォルトでは、kubectlの設定は~/.kube/config
に格納されています。
クラスターの状態を取得し、kubectlが適切に設定されていることを確認してください:
kubectl cluster-info
URLのレスポンスが表示されている場合は、kubectlはクラスターに接続するよう正しく設定されています。
以下のようなメッセージが表示されている場合は、kubectlは正しく設定されていないか、Kubernetesクラスターに接続できていません。
The connection to the server <server-name:port> was refused - did you specify the right host or port?
たとえば、ラップトップ上(ローカル環境)でKubernetesクラスターを起動するような場合、Minikubeなどのツールを最初にインストールしてから、上記のコマンドを再実行する必要があります。
kubectl cluster-info
がURLレスポンスを返したにもかかわらずクラスターにアクセスできない場合は、次のコマンドで設定が正しいことを確認してください:
kubectl cluster-info dump
Kubernetes 1.26にて、kubectlは以下のクラウドプロバイダーが提供するマネージドKubernetesのビルトイン認証を削除しました。 これらのプロバイダーは、クラウド固有の認証を提供するkubectlプラグインをリリースしています。 手順については以下のプロバイダーのドキュメントを参照してください:
(この変更とは関係なく、他の理由で同じエラーメッセージが表示される可能性もあります。)
kubectlはBash、Zsh、Fish、PowerShellの自動補完を提供しています。 これにより、入力を大幅に削減することができます。
以下にBash、Fish、Zshの自動補完の設定手順を示します。
Bashにおけるkubectlの補完スクリプトはkubectl completion bash
コマンドで生成できます。
補完スクリプトをシェル内に読み込ませることでkubectlの自動補完が有効になります。
ただし、補完スクリプトはbash-completionに依存しているため、事前にインストールしておく必要があります。
ここではBash 4.1以降の使用を前提としています。 Bashのバージョンは下記のコマンドで調べることができます:
echo $BASH_VERSION
バージョンが古い場合、Homebrewを使用してインストールもしくはアップグレードできます:
brew install bash
シェルをリロードし、希望するバージョンを使用していることを確認してください:
echo $BASH_VERSION $SHELL
Homebrewは通常、/usr/local/bin/bash
にインストールします。
type _init_completion
を実行することで、bash-completionがすでにインストールされていることを確認できます。
ない場合は、Homebrewを使用してインストールすることができます:
brew install bash-completion@2
このコマンドの出力で示されたように、~/.bash_profile
に以下を追記してください:
brew_etc="$(brew --prefix)/etc" && [[ -r "${brew_etc}/profile.d/bash_completion.sh" ]] && . "${brew_etc}/profile.d/bash_completion.sh"
シェルをリロードし、type _init_completion
を実行してbash-completion v2が正しくインストールされていることを検証してください。
次に、kubectl補完スクリプトがすべてのシェルセッションで読み込まれるように設定する必要があります。 これを行うには複数の方法があります:
補完スクリプトを~/.bash_profile
内で読み込ませる:
echo 'source <(kubectl completion bash)' >>~/.bash_profile
補完スクリプトを/usr/local/etc/bash_completion.d
ディレクトリに追加する:
kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl
kubectlにエイリアスを張っている場合は、エイリアスでも動作するようにシェルの補完を拡張することができます:
echo 'alias k=kubectl' >>~/.bash_profile
echo 'complete -o default -F __start_kubectl k' >>~/.bash_profile
kubectlをHomebrewでインストールした場合(前述の通り)、kubectlの補完スクリプトはすでに/usr/local/etc/bash_completion.d/kubectl
に格納されているでしょうか。
この場合、なにも操作する必要はありません。
BASH_COMPLETION_COMPAT_DIR
ディレクトリ内のすべてのファイルを読み込むため、後者の2つの方法が機能します。どの場合でも、シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。
Fishにおけるkubectlの補完スクリプトはkubectl completion fish
コマンドで生成できます。
補完スクリプトをシェル内に読み込ませることでkubectlの自動補完が有効になります。
すべてのシェルセッションで使用するには、~/.config/fish/config.fish
に以下を追記してください:
kubectl completion fish | source
シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。
Zshにおけるkubectlの補完スクリプトはkubectl completion zsh
コマンドで生成できます。
補完スクリプトをシェル内に読み込ませることでkubectlの自動補完が有効になります。
すべてのシェルセッションで使用するには、~/.zshrc
に以下を追記してください:
source <(kubectl completion zsh)
kubectlにエイリアスを張っている場合でも、kubectlの自動補完は自動的に機能します。
シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。
2: command not found: compdef
のようなエラーが出力された場合は、以下を~/.zshrc
の先頭に追記してください:
autoload -Uz compinit
compinit
kubectl convert
プラグインをインストールする異なるAPIバージョン間でマニフェストを変換できる、Kubernetesコマンドラインツールkubectl
のプラグインです。
これは特に、新しいKubernetesのリリースで、非推奨ではないAPIバージョンにマニフェストを移行する場合に役に立ちます。
詳細については非推奨ではないAPIへの移行を参照してください。
次のコマンドを使用して最新リリースをダウンロードしてください:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl-convert"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl-convert"
バイナリを検証してください(オプション)
kubectl-convertのチェックサムファイルをダウンロードします:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl-convert.sha256"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl-convert.sha256"
チェックサムファイルに対してkubectl-convertバイナリを検証します:
echo "$(cat kubectl-convert.sha256) kubectl-convert" | shasum -a 256 --check
正しければ、出力は次のようになります:
kubectl-convert: OK
チェックに失敗すると、shasum
は0以外のステータスで終了し、次のような出力を表示します:
kubectl-convert: FAILED
shasum: WARNING: 1 computed checksum did NOT match
kubectl-convertバイナリを実行可能にしてください。
chmod +x ./kubectl-convert
kubectl-convertバイナリをPATH
の中に移動してください。
sudo mv ./kubectl-convert /usr/local/bin/kubectl-convert
sudo chown root: /usr/local/bin/kubectl-convert
/usr/local/bin
がPATH環境変数の中に含まれるようにしてください。インストールしたバージョンが最新であることを確認してください
kubectl convert --help
何もエラーが表示されない場合は、プラグインが正常にインストールされたことを示しています。
プラグインのインストール後、インストールファイルを削除してください:
rm kubectl-convert kubectl-convert.sha256
kubectl
のインストール方法に応じて、次の方法を使用してください。
システム上のkubectl
バイナリの場所を特定してください:
which kubectl
kubectl
バイナリを削除してください:
sudo rm <path>
<path>
を前のステップのkubectl
バイナリのパスに置き換えてください。
例えばsudo rm /usr/local/bin/kubectl
。
Homebrewを使用してkubectl
をインストールした場合は、次のコマンドを実行してください:
brew remove kubectl
kubectlのバージョンは、クラスターのマイナーバージョンとの差分が1つ以内でなければなりません。 たとえば、クライアントがv1.32であれば、v1.31、v1.32、v1.33のコントロールプレーンと通信できます。 最新の互換性のあるバージョンのkubectlを使うことで、不測の事態を避けることができるでしょう。
Windowsへkubectlをインストールするには、次の方法があります:
最新の1.32のパッチリリースをダウンロードしてください: kubectl 1.32.0。
または、curl
がインストールされていれば、次のコマンドも使用できます:
curl.exe -LO "https://dl.k8s.io/release/v1.32.0/bin/windows/amd64/kubectl.exe"
バイナリを検証してください(オプション)
kubectl
のチェックサムファイルをダウンロードします:
curl.exe -LO "https://dl.k8s.io/v1.32.0/bin/windows/amd64/kubectl.exe.sha256"
チェックサムファイルに対してkubectl
バイナリを検証します:
コマンドプロンプトを使用して、CertUtil
の出力とダウンロードしたチェックサムファイルを手動で比較します:
CertUtil -hashfile kubectl.exe SHA256
type kubectl.exe.sha256
PowerShellにて-eq
オペレーターを使用して自動で検証を行い、True
またはFalse
で結果を取得します:
$(Get-FileHash -Algorithm SHA256 .\kubectl.exe).Hash -eq $(Get-Content .\kubectl.exe.sha256)
kubectl
バイナリのフォルダーをPATH
環境変数に追加します。
kubectl
のバージョンがダウンロードしたものと同じであることを確認してください:
kubectl version --client
または、バージョンの詳細を表示するために次を使用します:
kubectl version --client --output=yaml
kubectl
をPATH
に追加します。
Docker Desktopをすでにインストールしている場合、Docker Desktopインストーラーによって追加されたPATH
の前に追加するか、Docker Desktopのkubectl
を削除してください。Windowsへkubectlをインストールするために、ChocolateyパッケージマネージャーやScoopコマンドラインインストーラー、wingetパッケージマネージャーを使用することもできます。
choco install kubernetes-cli
scoop install kubectl
winget install -e --id Kubernetes.kubectl
インストールしたバージョンが最新であることを確認してください:
kubectl version --client
ホームディレクトリへ移動してください:
# cmd.exeを使用している場合はcd %USERPROFILE%を実行してください。
cd ~
.kube
ディレクトリを作成してください:
mkdir .kube
作成した.kube
ディレクトリへ移動してください:
cd .kube
リモートのKubernetesクラスターを使うために、kubectlを設定してください:
New-Item config -type file
kubectlがKubernetesクラスターを探索し接続するために、kubeconfigファイルが必要です。
これは、kube-up.shによりクラスターを作成した際や、Minikubeクラスターを正常にデプロイした際に自動生成されます。
デフォルトでは、kubectlの設定は~/.kube/config
に格納されています。
クラスターの状態を取得し、kubectlが適切に設定されていることを確認してください:
kubectl cluster-info
URLのレスポンスが表示されている場合は、kubectlはクラスターに接続するよう正しく設定されています。
以下のようなメッセージが表示されている場合は、kubectlは正しく設定されていないか、Kubernetesクラスターに接続できていません。
The connection to the server <server-name:port> was refused - did you specify the right host or port?
たとえば、ラップトップ上(ローカル環境)でKubernetesクラスターを起動するような場合、Minikubeなどのツールを最初にインストールしてから、上記のコマンドを再実行する必要があります。
kubectl cluster-info
がURLレスポンスを返したにもかかわらずクラスターにアクセスできない場合は、次のコマンドで設定が正しいことを確認してください:
kubectl cluster-info dump
Kubernetes 1.26にて、kubectlは以下のクラウドプロバイダーが提供するマネージドKubernetesのビルトイン認証を削除しました。 これらのプロバイダーは、クラウド固有の認証を提供するkubectlプラグインをリリースしています。 手順については以下のプロバイダーのドキュメントを参照してください:
(この変更とは関係なく、他の理由で同じエラーメッセージが表示される可能性もあります。)
kubectlはBash、Zsh、Fish、PowerShellの自動補完を提供しています。 これにより、入力を大幅に削減することができます。
以下にPowerShellの自動補完の設定手順を示します。
PowerShellにおけるkubectlの補完スクリプトはkubectl completion powershell
コマンドで生成できます。
すべてのシェルセッションでこれを行うには、次の行を$PROFILE
ファイルに追加します。
kubectl completion powershell | Out-String | Invoke-Expression
このコマンドは、PowerShellを起動する度に自動補完のスクリプトを再生成します。
生成されたスクリプトを直接$PROFILE
ファイルに追加することもできます。
生成されたスクリプトを$PROFILE
ファイルに追加するためには、PowerShellのプロンプトで次の行を実行します:
kubectl completion powershell >> $PROFILE
シェルをリロードした後、kubectlの自動補完が機能します。
kubectl convert
プラグインをインストールする異なるAPIバージョン間でマニフェストを変換できる、Kubernetesコマンドラインツールkubectl
のプラグインです。
これは特に、新しいKubernetesのリリースで、非推奨ではないAPIバージョンにマニフェストを移行する場合に役に立ちます。
詳細については非推奨ではないAPIへの移行を参照してください。
次のコマンドを使用して最新リリースをダウンロードしてください:
curl.exe -LO "https://dl.k8s.io/release/v1.32.0/bin/windows/amd64/kubectl-convert.exe"
バイナリを検証してください(オプション)。
kubectl-convert
のチェックサムファイルをダウンロードします:
curl.exe -LO "https://dl.k8s.io/v1.32.0/bin/windows/amd64/kubectl-convert.exe.sha256"
チェックサムファイルに対してkubectl-convert
バイナリを検証します:
コマンドプロンプトを使用して、CertUtil
の出力とダウンロードしたチェックサムファイルを手動で比較します:
CertUtil -hashfile kubectl-convert.exe SHA256
type kubectl-convert.exe.sha256
PowerShellにて-eq
オペレーターを使用して自動で検証を行い、True
またはFalse
で結果を取得します:
$($(CertUtil -hashfile .\kubectl-convert.exe SHA256)[1] -replace " ", "") -eq $(type .\kubectl-convert.exe.sha256)
kubectl-convert
バイナリのフォルダーをPATH
環境変数に追加します。
プラグインが正常にインストールされたことを確認してください。
kubectl convert --help
何もエラーが表示されない場合は、プラグインが正常にインストールされたことを示しています。
プラグインのインストール後、インストールファイルを削除してください:
del kubectl-convert.exe
del kubectl-convert.exe.sha256
Kubernetes v1.15 [stable]
kubeadmで生成されたクライアント証明書は1年で失効します。 このページでは、kubeadmで証明書の更新を管理する方法について説明します。
KubernetesにおけるPKI証明書と要件を熟知している必要があります。
デフォルトでは、kubeadmはクラスターの実行に必要なすべての証明書を生成します。 独自の証明書を提供することで、この動作をオーバーライドできます。
そのためには、--cert-dir
フラグまたはkubeadmのClusterConfiguration
のcertificatesDir
フィールドで指定された任意のディレクトリに配置する必要があります。
デフォルトは/etc/kubernetes/pki
です。
kubeadm init
を実行する前に与えられた証明書と秘密鍵のペアが存在する場合、kubeadmはそれらを上書きしません。
つまり、例えば既存のCAを/etc/kubernetes/pki/ca.crt
と/etc/kubernetes/pki/ca.key
にコピーすれば、kubeadmは残りの証明書に署名する際、このCAを使用できます。
また、ca.crt
ファイルのみを提供し、ca.key
ファイルを提供しないことも可能です(これはルートCAファイルのみに有効で、他の証明書ペアには有効ではありません)。
他の証明書とkubeconfigファイルがすべて揃っている場合、kubeadmはこの状態を認識し、外部CAモードを有効にします。
kubeadmはディスク上のCAキーがなくても処理を進めます。
代わりに、Controller-managerをスタンドアロンで、--controllers=csrsigner
と実行し、CA証明書と鍵を指し示します。
PKI certificates and requirementsには、外部CAを使用するためのクラスターのセットアップに関するガイダンスが含まれています。
check-expiration
サブコマンドを使うと、証明書の有効期限を確認することができます。
kubeadm certs check-expiration
このような出力になります:
CERTIFICATE EXPIRES RESIDUAL TIME CERTIFICATE AUTHORITY EXTERNALLY MANAGED
admin.conf Dec 30, 2020 23:36 UTC 364d no
apiserver Dec 30, 2020 23:36 UTC 364d ca no
apiserver-etcd-client Dec 30, 2020 23:36 UTC 364d etcd-ca no
apiserver-kubelet-client Dec 30, 2020 23:36 UTC 364d ca no
controller-manager.conf Dec 30, 2020 23:36 UTC 364d no
etcd-healthcheck-client Dec 30, 2020 23:36 UTC 364d etcd-ca no
etcd-peer Dec 30, 2020 23:36 UTC 364d etcd-ca no
etcd-server Dec 30, 2020 23:36 UTC 364d etcd-ca no
front-proxy-client Dec 30, 2020 23:36 UTC 364d front-proxy-ca no
scheduler.conf Dec 30, 2020 23:36 UTC 364d no
CERTIFICATE AUTHORITY EXPIRES RESIDUAL TIME EXTERNALLY MANAGED
ca Dec 28, 2029 23:36 UTC 9y no
etcd-ca Dec 28, 2029 23:36 UTC 9y no
front-proxy-ca Dec 28, 2029 23:36 UTC 9y no
このコマンドは、/etc/kubernetes/pki
フォルダ内のクライアント証明書と、kubeadmが使用するKUBECONFIGファイル(admin.conf
,controller-manager.conf
,scheduler.conf
)に埋め込まれたクライアント証明書の有効期限/残余時間を表示します。
また、証明書が外部管理されている場合、kubeadmはユーザーに通知します。この場合、ユーザーは証明書の更新を手動または他のツールを使用して管理する必要があります。
kubeadm
は外部CAによって署名された証明書を管理することができません。kubeadmは/var/lib/kubelet/pki
以下にあるローテート可能な証明書でkubeletの証明書の自動更新を構成するのでkubelet.conf
は上記のリストに含まれません。
期限切れのkubeletクライアント証明書を修復するには、Kubelet クライアント証明書のローテーションに失敗しましたを参照ください。
kubeadm version 1.17より前のkubeadm init
で作成したノードでは、kubelet.conf
の内容を手動で変更しなければならないというbugが存在します。
kubeadm init
が終了したら、client-certificate-data
とclient-key-data
を置き換えて、ローテーションされたkubeletクライアント証明書を指すようにkubelet.conf
を更新してください。
client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem
client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
kubeadmはコントロールプレーンのアップグレード時にすべての証明書を更新します。
この機能は、最もシンプルなユースケースに対応するために設計されています。 証明書の更新に特別な要件がなく、Kubernetesのバージョンアップを定期的に行う場合(各アップグレードの間隔が1年未満)、kubeadmがクラスターを最新かつ適度に安全に保つための処理を行います。
証明書の更新に関してより複雑な要求がある場合は、--certificate-renewal=false
をkubeadm upgrade apply
やkubeadm upgrade node
に渡して、デフォルトの動作から外れるようにすることができます。
kubeadm upgrade node
コマンドの--certificate-renewal
のデフォルト値がfalse
になっているという[bug(https://github.com/kubernetes/kubeadm/issues/1818)]問題があります。
この場合、明示的に--certificate-renewal=true
を設定する必要があります。kubeadm certs renew
コマンドを使えば、いつでも証明書を手動で更新することができます。
このコマンドは/etc/kubernetes/pki
に格納されているCA(またはfront-proxy-CA)の証明書と鍵を使って更新を行います。
コマンド実行後、コントロールプレーンのPodを再起動する必要があります。 これは、現在すべてのコンポーネントと証明書について動的な証明書のリロードがサポートされていないため、必要な作業です。 スタティックPodはローカルkubeletによって管理され、API Serverによって管理されないため、kubectlで削除および再起動することはできません。
スタティックPodを再起動するには、一時的に/etc/kubernetes/manifests/
からマニフェストファイルを削除して20秒間待ちます(KubeletConfiguration structのfileCheckFrequency
値を参照してください)。
マニフェストディレクトリにPodが無くなると、kubeletはPodを終了します。
その後ファイルを戻して、さらにfileCheckFrequency
期間後に、kubeletはPodを再作成し、コンポーネントの証明書更新を完了することができます。
certs renew
は、属性(Common Name、Organization、SANなど)の信頼できるソースとして、kubeadm-config ConfigMapではなく、既存の証明書を使用します。両者を同期させておくことが強く推奨されます。kubeadm certs renew
は以下のオプションを提供します:
Kubernetesの証明書は通常1年後に有効期限を迎えます。
--csr-only
を使用すると、証明書署名要求を生成して外部CAとの証明書を更新することができます(実際にはその場で証明書を更新しません)。詳しくは次の段落を参照してください。
また、すべての証明書を更新するのではなく、1つの証明書を更新することも可能です。
ここでは、Kubernetes certificates APIを使用して手動で証明書更新を実行する方法について詳しく説明します。
Kubernetesの認証局は、そのままでは機能しません。 cert-managerなどの外部署名者を設定するか、組み込みの署名者を使用することができます。
ビルトインサイナーはkube-controller-manager
に含まれるものです。
ビルトインサイナーを有効にするには、--cluster-signing-cert-file
と--cluster-signing-key-file
フラグを渡す必要があります。
新しいクラスターを作成する場合は、kubeadm設定ファイルを使用します。
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
controllerManager:
extraArgs:
cluster-signing-cert-file: /etc/kubernetes/pki/ca.crt
cluster-signing-key-file: /etc/kubernetes/pki/ca.key
Kubernetes APIでのCSR作成については、Create CertificateSigningRequestを参照ください。
ここでは、外部認証局を利用して手動で証明書更新を行う方法について詳しく説明します。
外部CAとの連携を強化するために、kubeadmは証明書署名要求(CSR)を生成することもできます。 CSRとは、クライアント用の署名付き証明書をCAに要求することを表します。 kubeadmの用語では、通常ディスク上のCAによって署名される証明書をCSRとして生成することができます。しかし、CAはCSRとして生成することはできません。
kubeadm certs renew --csr-only
で証明書署名要求を作成することができます。
CSRとそれに付随する秘密鍵の両方が出力されます。
ディレクトリを--csr-dir
で渡すと、指定した場所にCSRを出力することができます。
csr-dir
を指定しない場合は、デフォルトの証明書ディレクトリ(/etc/kubernetes/pki
)が使用されます。
証明書はkubeadm certs renew --csr-only
で更新することができます。
kubeadm init
と同様に、--csr-dir
フラグで出力先ディレクトリを指定することができます。
CSRには、証明書の名前、ドメイン、IPが含まれますが、用途は指定されません。 証明書を発行する際に、正しい証明書の使用法を指定するのはCAの責任です。
openssl
では、openssl ca
コマンドを使って行います。
cfssl
では、configファイルのusagesで指定します。
お好みの方法で証明書に署名した後、証明書と秘密鍵をPKIディレクトリ(デフォルトでは/etc/kubernetes/pki
)にコピーする必要があります。
Kubeadmは、CA証明書のローテーションや交換を最初からサポートしているわけではありません。
CAの手動ローテーションや交換についての詳細は、manual rotation of CA certificatesを参照してください。
デフォルトでは、kubeadmによって展開されるkubeletサービング証明書は自己署名されています。
これは、metrics-serverのような外部サービスからキューブレットへの接続がTLSで保護されないことを意味します。
新しいkubeadmクラスター内のkubeletが適切に署名されたサービング証明書を取得するように設定するには、kubeadm init
に以下の最小限の設定を渡す必要があります。
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
---
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
serverTLSBootstrap: true
すでにクラスターを作成している場合は、以下の手順で適応させる必要があります。
kube-system
ネームスペースにあるkubelet-config-1.32
ConfigMapを見つけて編集します。そのConfigMapのkubelet
キーの値としてKubeletConfigurationドキュメントを指定します。KubeletConfigurationドキュメントを編集し、serverTLSBootstrap: true
を設定します。
/var/lib/kubelet/config.yaml
にserverTLSBootstrap: true
フィールドを追加し、systemctl restart kubelet
でkubeletを再起動します。serverTLSBootstrap: true
フィールドは、kubeletサービングのブートストラップを有効にします。
証明書をcertificates.k8s.io
APIにリクエストすることで、証明書を発行することができます。
既知の制限事項として、これらの証明書のCSR(Certificate Signing Requests)はkube-controller-managerのデフォルトサイナーによって自動的に承認されないことがあります。
kubernetes.io/kubelet-serving
を参照してください。
これには、ユーザーまたはサードパーティーのコントローラーからのアクションが必要です。
これらのCSRは、以下を使用して表示できます:
kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
csr-9wvgt 112s kubernetes.io/kubelet-serving system:node:worker-1 Pending
csr-lz97v 1m58s kubernetes.io/kubelet-serving system:node:control-plane-1 Pending
承認するためには、次のようにします:
kubectl certificate approve <CSR-name>
デフォルトでは、これらのサービング証明書は1年後に失効します。
KubeadmはKubeletConfiguration
フィールドrotateCertificates
をtrue
に設定します。これは有効期限が切れる間際に、サービング証明書のための新しいCSRセットを作成し、ローテーションを完了するために承認する必要があることを意味します。
詳しくはCertificate Rotationをご覧ください。
これらのCSRを自動的に承認するためのソリューションをお探しの場合は、以下をお勧めします。 クラウドプロバイダーに連絡し、ノードの識別をアウトオブバンドのメカニズムで行うCSRの署名者がいるかどうか尋ねてください。
サードパーティーのカスタムコントローラーを使用することができます。
このようなコントローラーは、CSRのCommonNameを検証するだけでなく、要求されたIPやドメイン名も検証しなければ、安全なメカニズムとは言えません。これにより、kubeletクライアント証明書にアクセスできる悪意のあるアクターが、任意のIPやドメイン名に対してサービング証明書を要求するCSRを作成することを防ぐことができます。
このページでは、kubeadmクラスターのコンテナランタイムcgroupドライバーに合わせて、kubelet cgroupドライバーを設定する方法について説明します。
Kubernetesのコンテナランタイムの要件を熟知している必要があります。
コンテナランタイムページでは、kubeadmベースのセットアップではcgroupfs
ドライバーではなく、systemd
ドライバーが推奨されると説明されています。
このページでは、デフォルトのsystemd
ドライバーを使用して多くの異なるコンテナランタイムをセットアップする方法についての詳細も説明されています。
kubeadmでは、kubeadm init
の際にKubeletConfiguration
構造体を渡すことができます。
このKubeletConfiguration
には、kubeletのcgroupドライバーを制御するcgroupDriver
フィールドを含めることができます。
KubeletConfiguration
のcgroupDriver
フィールドを設定していない場合、kubeadm
はデフォルトでsystemd
を設定するようになりました。フィールドを明示的に設定する最小限の例です:
# kubeadm-config.yaml
kind: ClusterConfiguration
apiVersion: kubeadm.k8s.io/v1beta3
kubernetesVersion: v1.21.0
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
cgroupDriver: systemd
このような設定ファイルは、kubeadmコマンドに渡すことができます:
kubeadm init --config kubeadm-config.yaml
Kubeadmはクラスター内の全ノードで同じKubeletConfiguration
を使用します。
KubeletConfiguration
はkube-system
名前空間下のConfigMapオブジェクトに格納されます。
サブコマンドinit
、join
、upgrade
を実行すると、kubeadmがKubeletConfiguration
を/var/lib/kubelet/config.yaml
以下にファイルとして書き込み、ローカルノードのkubeletに渡します。
このガイドで説明するように、cgroupfs
ドライバーをkubeadmと一緒に使用することは推奨されません。
cgroupfs
を使い続け、kubeadm upgrade
が既存のセットアップでKubeletConfiguration
cgroupドライバーを変更しないようにするには、その値を明示的に指定する必要があります。
これは、将来のバージョンのkubeadmにsystemd
ドライバーをデフォルトで適用させたくない場合に適用されます。
値を明示する方法については、後述の「kubelet ConfigMapの修正」の項を参照してください。
cgroupfs
ドライバーを使用するようにコンテナランタイムを設定したい場合は、選択したコンテナランタイムのドキュメントを参照する必要があります。
systemd
ドライバーへの移行既存のkubeadmクラスターのcgroupドライバーをsystemd
にインプレースで変更する場合は、kubeletのアップグレードと同様の手順が必要です。
これには、以下に示す両方の手順を含める必要があります。
systemd
ドライバーを使用する新しいノードに置き換えることも可能です。
この場合、新しいノードに参加する前に以下の最初のステップのみを実行し、古いノードを削除する前にワークロードが新しいノードに安全に移動できることを確認する必要があります。kubectl get cm -n kube-system | grep kubelet-config
で、kubelet ConfigMapの名前を探します。kubectl edit cm kubelet-config-x.yy -n kube-system
を呼び出します(x.yy
はKubernetesのバージョンに置き換えてください)。cgroupDriver
の値を修正するか、以下のような新しいフィールドを追加します。 cgroupDriver: systemd
このフィールドは、ConfigMapのkubelet:
セクションの下に存在する必要があります。
クラスター内の各ノードについて:
kubectl drain <node-name> --ignore-daemonsets
を使ってドレーンします。systemctl stop kubelet
を使用して、kubeletを停止します。systemd
に変更します。var/lib/kubelet/config.yaml
にcgroupDriver: systemd
を設定します。systemctl start kubelet
でkubeletを起動します。kubectl uncordon <node-name>
を使って行います。ワークロードが異なるノードでスケジュールするための十分な時間を確保するために、これらのステップを1つずつノード上で実行します。 プロセスが完了したら、すべてのノードとワークロードが健全であることを確認します。
Kubernetes v1.18 [beta]
Kubernetesを使用してLinuxノードとWindowsノードを混在させて実行できるため、Linuxで実行するPodとWindowsで実行するPodを混在させることができます。このページでは、Windowsノードをクラスターに登録する方法を示します。
kubectl version
.WindowsコンテナをホストするWindowsノードを構成するには、Windows Server 2019ライセンス(またはそれ以上)を取得します。 VXLAN/オーバーレイネットワークを使用している場合は、KB4489899もインストールされている必要があります。
コントロールプレーンにアクセスできるLinuxベースのKubernetes kubeadmクラスター(kubeadmを使用したシングルコントロールプレーンクラスターの作成を参照)
LinuxベースのKubernetesコントロールプレーンノードを取得したら、ネットワーキングソリューションを選択できます。このガイドでは、簡単にするためにVXLANモードでのFlannelの使用について説明します。
FlannelのためにKubernetesコントロールプレーンを準備する
クラスター内のKubernetesコントロールプレーンでは、多少の準備が推奨されます。Flannelを使用する場合は、iptablesチェーンへのブリッジIPv4トラフィックを有効にすることをお勧めします。すべてのLinuxノードで次のコマンドを実行する必要があります:
sudo sysctl net.bridge.bridge-nf-call-iptables=1
Linux用のFlannelをダウンロードして構成する
最新のFlannelマニフェストをダウンロード:
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
VNIを4096、ポートを4789に設定するために、flannelマニフェストのnet-conf.json
セクションを変更します。次のようになります:
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan",
"VNI" : 4096,
"Port": 4789
}
}
Type
の値を"host-gw"
に変更し、VNI
とPort
を省略します。Flannelマニフェストを適用して検証する
Flannelの構成を適用しましょう:
kubectl apply -f kube-flannel.yml
数分後、Flannel Podネットワークがデプロイされていれば、すべてのPodが実行されていることがわかります。
kubectl get pods -n kube-system
出力結果には、実行中のLinux flannel DaemonSetが含まれているはずです:
NAMESPACE NAME READY STATUS RESTARTS AGE
...
kube-system kube-flannel-ds-54954 1/1 Running 0 1m
Windows Flannelとkube-proxy DaemonSetを追加する
これで、Windows互換バージョンのFlannelおよびkube-proxyを追加できます。 互換性のあるバージョンのkube-proxyを確実に入手するには、イメージのタグを置換する必要があります。 次の例は、Kubernetes 1.32.0の使用方法を示していますが、 独自のデプロイに合わせてバージョンを調整する必要があります。
curl -L https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/kube-proxy.yml | sed 's/VERSION/v1.32.0/g' | kubectl apply -f -
kubectl apply -f https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/flannel-overlay.yml
ホストゲートウェイを使用している場合は、代わりに https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/flannel-host-gw.yml を使用してください。
Windowsノードでイーサネット(「Ethernet0 2」など)ではなく別のインターフェースを使用している場合は、次の行を変更する必要があります:
wins cli process run --path /k/flannel/setup.exe --args "--mode=overlay --interface=Ethernet"
flannel-host-gw.yml
またはflannel-overlay.yml
ファイルで、それに応じてインターフェースを指定します。
# 例
curl -L https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/flannel-overlay.yml | sed 's/Ethernet/Ethernet0 2/g' | kubectl apply -f -
Containers
機能をインストールし、Dockerをインストールする必要があります。
行うための指示としては、Dockerエンジンのインストール - Windowsサーバー上のエンタープライズを利用できます。wins、kubelet、kubeadmをインストールします。
curl.exe -LO https://raw.githubusercontent.com/kubernetes-sigs/sig-windows-tools/master/kubeadm/scripts/PrepareNode.ps1
.\PrepareNode.ps1 -KubernetesVersion v1.32.0
kubeadm
を実行してノードに参加します
コントロールプレーンホストでkubeadm init
を実行したときに提供されたコマンドを使用します。
このコマンドがなくなった場合、またはトークンの有効期限が切れている場合は、kubeadm token create --print-join-command
(コントロールプレーンホスト上で)を実行して新しいトークンを生成します。
次のコマンドを実行して、クラスター内のWindowsノードを表示できるようになります:
kubectl get nodes -o wide
新しいノードがNotReady
状態の場合は、flannelイメージがまだダウンロード中の可能性があります。
kube-system
名前空間のflannel Podを確認することで、以前と同様に進行状況を確認できます:
kubectl -n kube-system get pods -l app=flannel
flannel Podが実行されると、ノードはReady
状態になり、ワークロードを処理できるようになります。
Kubernetes v1.18 [beta]
このページでは、kubeadmで作られたWindowsノードをアップグレードする方法について説明します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
作業するKubernetesサーバーは次のバージョン以降のものである必要があります: 1.17. バージョンを確認するには次のコマンドを実行してください:kubectl version
.Windowsノードから、kubeadmをアップグレードします。:
# 1.32.0を目的のバージョンに置き換えます
curl.exe -Lo C:\k\kubeadm.exe https://dl.k8s.io/v1.32.0/bin/windows/amd64/kubeadm.exe
Kubernetes APIにアクセスできるマシンから、 ノードをスケジュール不可としてマークして、ワークロードを削除することでノードのメンテナンスを準備します:
# <node-to-drain>をドレインするノードの名前に置き換えます
kubectl drain <node-to-drain> --ignore-daemonsets
このような出力結果が表示されるはずです:
node/ip-172-31-85-18 cordoned
node/ip-172-31-85-18 drained
Windowsノードから、次のコマンドを呼び出して新しいkubelet構成を同期します:
kubeadm upgrade node
Windowsノードから、kubeletをアップグレードして再起動します:
stop-service kubelet
curl.exe -Lo C:\k\kubelet.exe https://dl.k8s.io/v1.32.0/bin/windows/amd64/kubelet.exe
restart-service kubelet
Kubernetes APIにアクセスできるマシンから、 スケジュール可能としてマークして、ノードをオンラインに戻します:
# <node-to-drain>をノードの名前に置き換えます
kubectl uncordon <node-to-drain>
Kubernetes APIにアクセスできるマシンから、次を実行します、 もう一度1.32.0を目的のバージョンに置き換えます:
curl -L https://github.com/kubernetes-sigs/sig-windows-tools/releases/latest/download/kube-proxy.yml | sed 's/VERSION/v1.32.0/g' | kubectl apply -f -
dockershimから他のコンテナランタイムに移行する際に知っておくべき情報を紹介します。
Kubernetes 1.20でdockershim deprecationが発表されてから、様々なワークロードやKubernetesインストールにどう影響するのかという質問が寄せられています。
この問題をよりよく理解するために、dockershimの削除に関するFAQブログが役に立つでしょう。
dockershimから代替のコンテナランタイムに移行することが推奨されます。 コンテナランタイムのセクションをチェックして、どのような選択肢があるかを確認してください。 問題が発生した場合は、必ず問題の報告をしてください。 そうすれば、問題が適時に修正され、クラスターがdockershimの削除に対応できるようになります。
このページでは、クラスター内のノードが使用しているコンテナランタイムを確認する手順を概説しています。
クラスターの実行方法によっては、ノード用のコンテナランタイムが事前に設定されている場合と、設定する必要がある場合があります。
マネージドKubernetesサービスを使用している場合、ノードに設定されているコンテナランタイムを確認するためのベンダー固有の方法があるかもしれません。
このページで説明する方法は、kubectl
の実行が許可されていればいつでも動作するはずです。
kubectl
をインストールし、設定します。詳細はツールのインストールの項を参照してください。
ノードの情報を取得して表示するにはkubectl
を使用します:
kubectl get nodes -o wide
出力は以下のようなものです。列CONTAINER-RUNTIME
には、ランタイムとそのバージョンが出力されます。
# For dockershim
NAME STATUS VERSION CONTAINER-RUNTIME
node-1 Ready v1.16.15 docker://19.3.1
node-2 Ready v1.16.15 docker://19.3.1
node-3 Ready v1.16.15 docker://19.3.1
# For containerd
NAME STATUS VERSION CONTAINER-RUNTIME
node-1 Ready v1.19.6 containerd://1.4.1
node-2 Ready v1.19.6 containerd://1.4.1
node-3 Ready v1.19.6 containerd://1.4.1
コンテナランタイムについては、コンテナランタイムのページで詳細を確認することができます。
Kubernetesのdockershim
コンポーネントは、DockerをKubernetesのコンテナランタイムとして使用することを可能にします。
Kubernetesの組み込みコンポーネントであるdockershim
はリリースv1.24で削除されました。
このページでは、あなたのクラスターがどのようにDockerをコンテナランタイムとして使用しているか、使用中のdockershim
が果たす役割について詳しく説明し、dockershim
の削除によって影響を受けるワークロードがあるかどうかをチェックするためのステップを示します。
アプリケーションコンテナの構築にDockerを使用している場合でも、これらのコンテナを任意のコンテナランタイム上で実行することができます。このようなDockerの使用は、コンテナランタイムとしてのDockerへの依存とはみなされません。
代替のコンテナランタイムが使用されている場合、Dockerコマンドを実行しても動作しないか、予期せぬ出力が得られる可能性があります。
このように、Dockerへの依存があるかどうかを調べることができます:
docker ps
など)を実行したり、Dockerサービスを再起動したり(systemctl restart docker.service
などのコマンド)、Docker固有のファイル(/etc/docker/daemon.json
など)を変更しないことを確認すること。/etc/docker/daemon.json
など)にプライベートレジストリやイメージミラーの設定がないか確認します。これらは通常、別のコンテナランタイムのために再設定する必要があります。コンテナランタイムとは、Kubernetes Podを構成するコンテナを実行できるソフトウェアです。
KubernetesはPodのオーケストレーションとスケジューリングを担当し、各ノードではkubeletがコンテナランタイムインターフェースを抽象化して使用するので、互換性があればどのコンテナランタイムでも使用することができます。 初期のリリースでは、Kubernetesは1つのコンテナランタイムと互換性を提供していました: Dockerです。 その後、Kubernetesプロジェクトの歴史の中で、クラスター運用者は追加のコンテナランタイムを採用することを希望しました。 CRIはこのような柔軟性を可能にするために設計され、kubeletはCRIのサポートを開始しました。 しかし、DockerはCRI仕様が考案される前から存在していたため、Kubernetesプロジェクトはアダプタコンポーネント「dockershim」を作成しました。
dockershimアダプターは、DockerがCRI互換ランタイムであるかのように、kubeletがDockerと対話することを可能にします。 Kubernetes Containerd integration goes GAブログ記事で紹介されています。
コンテナランタイムとしてContainerdに切り替えることで、中間マージンを排除することができます。
これまでと同じように、Containerdのようなコンテナランタイムですべてのコンテナを実行できます。
しかし今は、コンテナはコンテナランタイムで直接スケジュールするので、Dockerからは見えません。
そのため、これらのコンテナをチェックするために以前使っていたかもしれないDockerツールや派手なUIは、もはや利用できません。
docker ps
やdocker inspect
を使用してコンテナ情報を取得することはできません。
コンテナを一覧表示できないので、ログを取得したり、コンテナを停止したり、docker exec
を使用してコンテナ内で何かを実行したりすることもできません。
この場合でも、イメージを取得したり、docker build
コマンドを使用してビルドすることは可能です。
しかし、Dockerによってビルドまたはプルされたイメージは、コンテナランタイムとKubernetesからは見えません。
Kubernetesで使用できるようにするには、何らかのレジストリにプッシュする必要がありました。
Kubernetes 1.20でdockershimは非推奨になりました。
dockershimの削除に関するFAQから、ほとんどのアプリがコンテナをホストするランタイムに直接依存しないことは既にご存知かもしれません。 しかし、コンテナのメタデータやログ、メトリクスを収集するためにDockerに依存しているテレメトリーやセキュリティエージェントはまだ多く存在します。 この文書では、これらの依存関係を検出する方法と、これらのエージェントを汎用ツールまたは代替ランタイムに移行する方法に関するリンクを集約しています。
Kubernetesクラスター上でエージェントを実行するには、いくつかの方法があります。エージェントはノード上で直接、またはDaemonSetとして実行することができます。
歴史的には、KubernetesはDockerの上に構築されていました。 Kubernetesはネットワークとスケジューリングを管理し、Dockerはコンテナをノードに配置して操作していました。 そのため、KubernetesからはPod名などのスケジューリング関連のメタデータを、Dockerからはコンテナの状態情報を取得することができます。 時が経つにつれ、コンテナを管理するためのランタイムも増えてきました。 また、多くのランタイムにまたがるコンテナ状態情報の抽出を一般化するプロジェクトやKubernetesの機能もあります。
いくつかのエージェントはDockerツールに関連しています。
エージェントはdocker ps
やdocker top
といったコマンドを実行し、コンテナやプロセスの一覧を表示します。
またはdocker logsを使えば、dockerログを購読することができます。
Dockerがコンテナランタイムとして非推奨になったため、これらのコマンドはもう使えません。
Podがノード上で動作しているdockerd
を呼び出したい場合、Podは以下のいずれかを行う必要があります。
Dockerデーモンの特権ソケットがあるファイルシステムをvolumeのようにマウントする。
Dockerデーモンの特権ソケットの特定のパスを直接ボリュームとしてマウントします。
例: COSイメージでは、DockerはそのUnixドメインソケットを/var/run/docker.sock
に公開します。
つまり、Pod仕様には/var/run/docker.sock
のhostPath
ボリュームマウントが含まれることになります。
以下は、Dockerソケットを直接マッピングしたマウントを持つPodを探すためのシェルスクリプトのサンプルです。
このスクリプトは、Podの名前空間と名前を出力します。
grep '/var/run/docker.sock'
を削除して、他のマウントを確認することもできます。
kubectl get pods --all-namespaces \
-o=jsonpath='{range .items[*]}{"\n"}{.metadata.namespace}{":\t"}{.metadata.name}{":\t"}{range .spec.volumes[*]}{.hostPath.path}{", "}{end}{end}' \
| sort \
| grep '/var/run/docker.sock'
/var/run
をマウントすることができます(この例 のように)。
上記のスクリプトは、最も一般的な使用方法のみを検出します。クラスターノードをカスタマイズし、セキュリティやテレメトリーのエージェントをノードに追加インストールする場合、エージェントのベンダーにDockerへの依存性があるかどうかを必ず確認してください。
様々なテレメトリーおよびセキュリティエージェントベンダーのための移行指示の作業中バージョンをGoogle docに保管しています。 dockershimからの移行に関する最新の手順については、各ベンダーにお問い合わせください。
クライアント証明書認証を使用する場合、easyrsa
、openssl
またはcfssl
を使って手動で証明書を生成することができます。
easyrsaはクラスターの証明書を手動で生成することができます。
パッチが適用されたバージョンのeasyrsa3
をダウンロードして解凍し、初期化します。
curl -LO https://dl.k8s.io/easy-rsa/easy-rsa.tar.gz
tar xzf easy-rsa.tar.gz
cd easy-rsa-master/easyrsa3
./easyrsa init-pki
新しい認証局(CA)を生成します。
--batch
で自動モードに設定します。--req-cn
はCAの新しいルート証明書のコモンネーム(CN)を指定します。
./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass
サーバー証明書と鍵を生成します。
引数--subject-alt-name
は、APIサーバーがアクセス可能なIPとDNS名を設定します。
MASTER_CLUSTER_IP
は通常、APIサーバーとコントローラーマネージャーコンポーネントの両方で--service-cluster-ip-range
引数に指定したサービスCIDRの最初のIPとなります。
引数--days
は、証明書の有効期限が切れるまでの日数を設定するために使用します。
また、以下のサンプルでは、デフォルトのDNSドメイン名としてcluster.local
を使用することを想定しています。
./easyrsa --subject-alt-name="IP:${MASTER_IP},"\
"IP:${MASTER_CLUSTER_IP},"\
"DNS:kubernetes,"\
"DNS:kubernetes.default,"\
"DNS:kubernetes.default.svc,"\
"DNS:kubernetes.default.svc.cluster,"\
"DNS:kubernetes.default.svc.cluster.local" \
--days=10000 \
build-server-full server nopass
pki/ca.crt
、pki/issued/server.crt
、pki/private/server.key
を自分のディレクトリにコピーします。
APIサーバーのスタートパラメーターに以下のパラメーターを記入し、追加します。
--client-ca-file=/yourdirectory/ca.crt
--tls-cert-file=/yourdirectory/server.crt
--tls-private-key-file=/yourdirectory/server.key
opensslは、クラスター用の証明書を手動で生成することができます。
2048bitのca.keyを生成します:
openssl genrsa -out ca.key 2048
ca.keyに従ってca.crtを生成します(-days
で証明書の有効期限を設定します):
openssl req -x509 -new -nodes -key ca.key -subj "/CN=${MASTER_IP}" -days 10000 -out ca.crt
2048bitでserver.keyを生成します:
openssl genrsa -out server.key 2048
証明書署名要求(CSR)を生成するための設定ファイルを作成します。
山括弧で囲まれた値(例:<MASTER_IP>
)は必ず実際の値に置き換えてから、ファイル(例:csr.conf
)に保存してください。MASTER_CLUSTER_IP
の値は、前のサブセクションで説明したように、APIサーバーのサービスクラスターのIPであることに注意してください。また、以下のサンプルでは、デフォルトのDNSドメイン名としてcluster.local
を使用することを想定しています。
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[ dn ]
C = <country>
ST = <state>
L = <city>
O = <organization>
OU = <organization unit>
CN = <MASTER_IP>
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster
DNS.5 = kubernetes.default.svc.cluster.local
IP.1 = <MASTER_IP>
IP.2 = <MASTER_CLUSTER_IP>
[ v3_ext ]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=keyEncipherment,dataEncipherment
extendedKeyUsage=serverAuth,clientAuth
subjectAltName=@alt_names
設定ファイルに基づき、証明書署名要求を生成します:
openssl req -new -key server.key -out server.csr -config csr.conf
ca.key、ca.crt、server.csrを使用して、サーバー証明書を生成します:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 10000 \
-extensions v3_ext -extfile csr.conf -sha256
証明書署名要求を表示します:
openssl req -noout -text -in ./server.csr
証明書を表示します:
openssl x509 -noout -text -in ./server.crt
最後に、同じパラメーターをAPIサーバーのスタートパラメーターに追加します。
cfsslも証明書を生成するためのツールです。
以下のように、コマンドラインツールをダウンロードし、解凍して準備してください。
なお、サンプルのコマンドは、お使いのハードウェア・アーキテクチャやCFSSLのバージョンに合わせる必要があるかもしれません。
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl_1.5.0_linux_amd64 -o cfssl
chmod +x cfssl
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssljson_1.5.0_linux_amd64 -o cfssljson
chmod +x cfssljson
curl -L https://github.com/cloudflare/cfssl/releases/download/v1.5.0/cfssl-certinfo_1.5.0_linux_amd64 -o cfssl-certinfo
chmod +x cfssl-certinfo
成果物を格納するディレクトリを作成し、cfsslを初期化します:
mkdir cert
cd cert
../cfssl print-defaults config > config.json
../cfssl print-defaults csr > csr.json
CAファイルを生成するためのJSON設定ファイル、例えばca-config.json
を作成します:
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "8760h"
}
}
}
}
CA証明書署名要求(CSR)用のJSON設定ファイル(例:ca-csr.json
)を作成します。
山括弧で囲まれた値は、必ず使用したい実際の値に置き換えてください。
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names":[{
"C": "<country>",
"ST": "<state>",
"L": "<city>",
"O": "<organization>",
"OU": "<organization unit>"
}]
}
CAキー(ca-key.pem
)と証明書(ca.pem
)を生成します:
../cfssl gencert -initca ca-csr.json | ../cfssljson -bare ca
APIサーバーの鍵と証明書を生成するためのJSON設定ファイル、例えばserver-csr.json
を作成します。
山括弧内の値は、必ず使用したい実際の値に置き換えてください。
MASTER_CLUSTER_IP
は、前のサブセクションで説明したように、APIサーバーのサービスクラスターのIPです。
また、以下のサンプルでは、デフォルトのDNSドメイン名としてcluster.local
を使用することを想定しています。
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"<MASTER_IP>",
"<MASTER_CLUSTER_IP>",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [{
"C": "<country>",
"ST": "<state>",
"L": "<city>",
"O": "<organization>",
"OU": "<organization unit>"
}]
}
APIサーバーの鍵と証明書を生成します。
デフォルトでは、それぞれserver-key.pem
とserver.pem
というファイルに保存されます:
../cfssl gencert -ca=ca.pem -ca-key=ca-key.pem \
--config=ca-config.json -profile=kubernetes \
server-csr.json | ../cfssljson -bare server
クライアントノードが自己署名入りCA証明書を有効なものとして認識できない場合があります。
非プロダクション環境、または会社のファイアウォールの内側での開発環境であれば、自己署名入りCA証明書をすべてのクライアントに配布し、有効な証明書のローカルリストを更新することができます。
各クライアントで、次の操作を実行します:
sudo cp ca.crt /usr/local/share/ca-certificates/kubernetes.crt
sudo update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d....
done.
認証に使用するx509証明書のプロビジョニングにはcertificates.k8s.io
APIを使用することができます。クラスターでのTLSの管理に記述されています。
このページでは、ネームスペースのデフォルトのメモリー要求と制限を設定する方法を説明します。
Kubernetesクラスターはネームスペースに分割することができます。デフォルトのメモリー制限を持つネームスペースがあり、独自のメモリー制限を指定しないコンテナでPodを作成しようとすると、コントロールプレーンはそのコンテナにデフォルトのメモリー制限を割り当てます。
Kubernetesは、このトピックで後ほど説明する特定の条件下で、デフォルトのメモリー要求を割り当てます。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
クラスターにネームスペースを作成するには、アクセス権が必要です。
クラスターの各ノードには、最低でも2GiBのメモリーが必要です。
この演習で作成したリソースがクラスターの他の部分から分離されるように、ネームスペースを作成します。
kubectl create namespace default-mem-example
以下は、LimitRangeのマニフェストの例です。このマニフェストでは、デフォルトのメモリー要求とデフォルトのメモリー制限を指定しています。
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
spec:
limits:
- default:
memory: 512Mi
defaultRequest:
memory: 256Mi
type: Container
default-mem-exampleネームスペースにLimitRangeを作成します:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults.yaml --namespace=default-mem-example
default-mem-exampleネームスペースでPodを作成し、そのPod内のコンテナがメモリー要求とメモリー制限の値を独自に指定しない場合、コントロールプレーンはデフォルト値のメモリー要求256MiBとメモリー制限512MiBを適用します。
以下は、コンテナを1つ持つPodのマニフェストの例です。コンテナは、メモリー要求とメモリー制限を指定していません。
apiVersion: v1
kind: Pod
metadata:
name: default-mem-demo
spec:
containers:
- name: default-mem-demo-ctr
image: nginx
Podを作成します:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults-pod.yaml --namespace=default-mem-example
Podの詳細情報を表示します:
kubectl get pod default-mem-demo --output=yaml --namespace=default-mem-example
この出力は、Podのコンテナのメモリー要求が256MiBで、メモリー制限が512MiBであることを示しています。 これらはLimitRangeで指定されたデフォルト値です。
containers:
- image: nginx
imagePullPolicy: Always
name: default-mem-demo-ctr
resources:
limits:
memory: 512Mi
requests:
memory: 256Mi
Podを削除します:
kubectl delete pod default-mem-demo --namespace=default-mem-example
以下は1つのコンテナを持つPodのマニフェストです。コンテナはメモリー制限を指定しますが、メモリー要求は指定しません。
apiVersion: v1
kind: Pod
metadata:
name: default-mem-demo-2
spec:
containers:
- name: default-mem-demo-2-ctr
image: nginx
resources:
limits:
memory: "1Gi"
Podを作成します:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults-pod-2.yaml --namespace=default-mem-example
Podの詳細情報を表示します:
kubectl get pod default-mem-demo-2 --output=yaml --namespace=default-mem-example
この出力は、コンテナのメモリー要求がそのメモリー制限に一致するように設定されていることを示しています。 コンテナにはデフォルトのメモリー要求値である256Miが割り当てられていないことに注意してください。
resources:
limits:
memory: 1Gi
requests:
memory: 1Gi
1つのコンテナを持つPodのマニフェストです。コンテナはメモリー要求を指定しますが、メモリー制限は指定しません。
apiVersion: v1
kind: Pod
metadata:
name: default-mem-demo-3
spec:
containers:
- name: default-mem-demo-3-ctr
image: nginx
resources:
requests:
memory: "128Mi"
Podを作成します:
kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults-pod-3.yaml --namespace=default-mem-example
Podの詳細情報を表示します:
kubectl get pod default-mem-demo-3 --output=yaml --namespace=default-mem-example
この出力は、コンテナのメモリー要求が、コンテナのマニフェストで指定された値に設定されていることを示しています。 コンテナは512MiB以下のメモリーを使用するように制限されていて、これはネームスペースのデフォルトのメモリー制限と一致します。
resources:
limits:
memory: 512Mi
requests:
memory: 128Mi
ネームスペースにメモリーリソースクォータが設定されている場合、メモリー制限のデフォルト値を設定しておくと便利です。
以下はリソースクォータがネームスペースに課す制限のうちの2つです。
LimitRangeの追加時:
コンテナを含む、そのネームスペース内のいずれかのPodが独自のメモリー制限を指定していない場合、コントロールプレーンはそのコンテナにデフォルトのメモリー制限を適用し、メモリーのResourceQuotaによって制限されているネームスペース内でPodを実行できるようにします。
ネームスペースを削除します:
kubectl delete namespace default-mem-example
このページでは、Namespaceで実行されるコンテナが使用するメモリーの最小値と最大値を設定する方法を説明します。 LimitRange で最小値と最大値のメモリー値を指定します。 PodがLimitRangeによって課される制約を満たさない場合、そのNamespaceではPodを作成できません。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.クラスター内の各ノードには、少なくとも1GiBのメモリーが必要です。
この演習で作成したリソースがクラスターの他の部分から分離されるように、Namespaceを作成します。
kubectl create namespace constraints-mem-example
LimitRangeの設定ファイルです。
apiVersion: v1
kind: LimitRange
metadata:
name: mem-min-max-demo-lr
spec:
limits:
- max:
memory: 1Gi
min:
memory: 500Mi
type: Container
LimitRangeを作成します。
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints.yaml --namespace=constraints-mem-example
LimitRangeの詳細情報を表示します。
kubectl get limitrange mem-min-max-demo-lr --namespace=constraints-mem-example --output=yaml
出力されるのは、予想通りメモリー制約の最小値と最大値を示しています。 しかし、LimitRangeの設定ファイルでデフォルト値を指定していないにもかかわらず、 自動的に作成されていることに気づきます。
limits:
- default:
memory: 1Gi
defaultRequest:
memory: 1Gi
max:
memory: 1Gi
min:
memory: 500Mi
type: Container
constraints-mem-exampleNamespaceにコンテナが作成されるたびに、 Kubernetesは以下の手順を実行するようになっています。
コンテナが独自のメモリー要求と制限を指定しない場合は、デフォルトのメモリー要求と制限をコンテナに割り当てます。
コンテナに500MiB以上のメモリー要求があることを確認します。
コンテナのメモリー制限が1GiB以下であることを確認します。
以下は、1つのコンテナを持つPodの設定ファイルです。設定ファイルのコンテナ(containers)では、600MiBのメモリー要求と800MiBのメモリー制限が指定されています。これらはLimitRangeによって課される最小と最大のメモリー制約を満たしています。
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo
spec:
containers:
- name: constraints-mem-demo-ctr
image: nginx
resources:
limits:
memory: "800Mi"
requests:
memory: "600Mi"
Podの作成
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod.yaml --namespace=constraints-mem-example
Podのコンテナが実行されていることを確認します。
kubectl get pod constraints-mem-demo --namespace=constraints-mem-example
Podの詳細情報を見ます
kubectl get pod constraints-mem-demo --output=yaml --namespace=constraints-mem-example
出力は、コンテナが600MiBのメモリ要求と800MiBのメモリー制限になっていることを示しています。これらはLimitRangeによって課される制約を満たしています。
resources:
limits:
memory: 800Mi
requests:
memory: 600Mi
Podを消します。
kubectl delete pod constraints-mem-demo --namespace=constraints-mem-example
これは、1つのコンテナを持つPodの設定ファイルです。コンテナは800MiBのメモリー要求と1.5GiBのメモリー制限を指定しています。
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-2
spec:
containers:
- name: constraints-mem-demo-2-ctr
image: nginx
resources:
limits:
memory: "1.5Gi"
requests:
memory: "800Mi"
Podを作成してみます。
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-2.yaml --namespace=constraints-mem-example
出力は、コンテナが大きすぎるメモリー制限を指定しているため、Podが作成されないことを示しています。
Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-2.yaml":
pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi.
これは、1つのコンテナを持つPodの設定ファイルです。コンテナは100MiBのメモリー要求と800MiBのメモリー制限を指定しています。
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-3
spec:
containers:
- name: constraints-mem-demo-3-ctr
image: nginx
resources:
limits:
memory: "800Mi"
requests:
memory: "100Mi"
Podを作成してみます。
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-3.yaml --namespace=constraints-mem-example
出力は、コンテナが小さすぎるメモリー要求を指定しているため、Podが作成されないことを示しています。
Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-3.yaml":
pods "constraints-mem-demo-3" is forbidden: minimum memory usage per Container is 500Mi, but request is 100Mi.
これは、1つのコンテナを持つPodの設定ファイルです。コンテナはメモリー要求を指定しておらず、メモリー制限も指定していません。
apiVersion: v1
kind: Pod
metadata:
name: constraints-mem-demo-4
spec:
containers:
- name: constraints-mem-demo-4-ctr
image: nginx
Podを作成します。
kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-4.yaml --namespace=constraints-mem-example
Podの詳細情報を見ます
kubectl get pod constraints-mem-demo-4 --namespace=constraints-mem-example --output=yaml
出力を見ると、Podのコンテナのメモリ要求は1GiB、メモリー制限は1GiBであることがわかります。 コンテナはどのようにしてこれらの値を取得したのでしょうか?
resources:
limits:
memory: 1Gi
requests:
memory: 1Gi
コンテナが独自のメモリー要求と制限を指定していなかったため、LimitRangeから与えられのです。 コンテナが独自のメモリー要求と制限を指定していなかったため、LimitRangeからデフォルトのメモリー要求と制限が与えられたのです。
この時点で、コンテナは起動しているかもしれませんし、起動していないかもしれません。このタスクの前提条件は、ノードが少なくとも1GiBのメモリーを持っていることであることを思い出してください。それぞれのノードが1GiBのメモリーしか持っていない場合、どのノードにも1GiBのメモリー要求に対応するのに十分な割り当て可能なメモリーがありません。たまたま2GiBのメモリーを持つノードを使用しているのであれば、おそらく1GiBのメモリーリクエストに対応するのに十分なスペースを持っていることになります。
Podを削除します。
kubectl delete pod constraints-mem-demo-4 --namespace=constraints-mem-example
LimitRangeによってNamespaceに課される最大および最小のメモリー制約は、Podが作成または更新されたときにのみ適用されます。LimitRangeを変更しても、以前に作成されたPodには影響しません。
クラスター管理者としては、Podが使用できるメモリー量に制限を課したいと思うかもしれません。
例:
クラスター内の各ノードは2GBのメモリーを持っています。クラスター内のどのノードもその要求をサポートできないため、2GB以上のメモリーを要求するPodは受け入れたくありません。
クラスターは運用部門と開発部門で共有されています。 本番用のワークロードでは最大8GBのメモリーを消費しますが、開発用のワークロードでは512MBに制限したいとします。本番用と開発用に別々のNamespaceを作成し、それぞれのNamespaceにメモリー制限を適用します。
Namespaceを削除します。
kubectl delete namespace constraints-mem-example
このページでは、Nodeに対して拡張リソースを指定する方法を説明します。拡張リソースを利用すると、Kubernetesにとって未知のノードレベルのリソースをクラスター管理者がアドバタイズできるようになります。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.kubectl get nodes
この練習で使いたいNodeを1つ選んでください。
Node上の新しい拡張リソースをアドバタイズするには、HTTPのPATCHリクエストをKubernetes APIサーバーに送ります。たとえば、Nodeの1つに4つのドングルが接続されているとします。以下に、4つのドングルリソースをNodeにアドバタイズするPATCHリクエストの例を示します。
PATCH /api/v1/nodes/<選択したNodeの名前>/status HTTP/1.1
Accept: application/json
Content-Type: application/json-patch+json
Host: k8s-master:8080
[
{
"op": "add",
"path": "/status/capacity/example.com~1dongle",
"value": "4"
}
]
Kubernetesは、ドングルとは何かも、ドングルが何に利用できるのかを知る必要もないことに注意してください。上のPATCHリクエストは、ただNodeが4つのドングルと呼ばれるものを持っているとKubernetesに教えているだけです。
Kubernetes APIサーバーに簡単にリクエストを送れるように、プロキシを実行します。
kubectl proxy
もう1つのコマンドウィンドウを開き、HTTPのPATCHリクエストを送ります。<選択したNodeの名前>
の部分は、選択したNodeの名前に置き換えてください。
curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "add", "path": "/status/capacity/example.com~1dongle", "value": "4"}]' \
http://localhost:8001/api/v1/nodes/<選択したNodeの名前>/status
~1
は、PATCHのパスにおける/
という文字をエンコーディングしたものです。JSON-Patch内のoperationのpathはJSON-Pointerとして解釈されます。詳細については、IETF RFC 6901のsection 3を読んでください。出力には、Nodeがキャパシティー4のdongleを持っていることが示されます。
"capacity": {
"cpu": "2",
"memory": "2049008Ki",
"example.com/dongle": "4",
Nodeの説明を確認します。
kubectl describe node <選択したNodeの名前>
出力には、再びdongleリソースが表示されます。
Capacity:
cpu: 2
memory: 2049008Ki
example.com/dongle: 4
これで、アプリケーション開発者は特定の数のdongleをリクエストするPodを作成できるようになりました。詳しくは、拡張リソースをコンテナに割り当てるを読んでください。
拡張リソースは、メモリやCPUリソースと同様のものです。たとえば、Nodeが持っている特定の量のメモリやCPUがNode上で動作している他のすべてのコンポーネントと共有されるのと同様に、Nodeが搭載している特定の数のdongleが他のすべてのコンポーネントと共有されます。そして、アプリケーション開発者が特定の量のメモリとCPUをリクエストするPodを作成できるのと同様に、Nodeが搭載している特定の数のdongleをリクエストするPodが作成できます。
拡張リソースはKubernetesには詳細を意図的に公開しないため、Kubernetesは拡張リソースの実体をまったく知りません。Kubernetesが知っているのは、Nodeが特定の数の拡張リソースを持っているということだけです。拡張リソースは整数値でアドバタイズしなければなりません。たとえば、Nodeは4つのdongleをアドバタイズできますが、4.5のdongleというのはアドバタイズできません。
Nodeに800GiBの特殊なディスクストレージがあるとします。この特殊なストレージの名前、たとえばexample.com/special-storageという名前の拡張リソースが作れます。そして、そのなかの一定のサイズ、たとえば100GiBのチャンクをアドバタイズできます。この場合、Nodeはexample.com/special-storageという種類のキャパシティ8のリソースを持っているとアドバタイズします。
Capacity:
...
example.com/special-storage: 8
特殊なストレージに任意のサイズのリクエストを許可したい場合、特殊なストレージを1バイトのサイズのチャンクでアドバタイズできます。その場合、example.com/special-storageという種類の800Giのリソースとしてアドバタイズします。
Capacity:
...
example.com/special-storage: 800Gi
すると、コンテナは好きなバイト数の特殊なストレージを最大800Giまでリクエストできるようになります。
以下に、dongleのアドバタイズをNodeから削除するPATCHリクエストを示します。
PATCH /api/v1/nodes/<選択したNodeの名前>/status HTTP/1.1
Accept: application/json
Content-Type: application/json-patch+json
Host: k8s-master:8080
[
{
"op": "remove",
"path": "/status/capacity/example.com~1dongle",
}
]
Kubernetes APIサーバーに簡単にリクエストを送れるように、プロキシを実行します。
kubectl proxy
もう1つのコマンドウィンドウで、HTTPのPATCHリクエストを送ります。<選択したNodeの名前>
の部分は、選択したNodeの名前に置き換えてください。
curl --header "Content-Type: application/json-patch+json" \
--request PATCH \
--data '[{"op": "remove", "path": "/status/capacity/example.com~1dongle"}]' \
http://localhost:8001/api/v1/nodes/<選択したNodeの名前>/status
dongleのアドバタイズが削除されたことを検証します。
kubectl describe node <選択したNodeの名前> | grep dongle
(出力には何も表示されないはずです)
Kubernetes v1.11 [beta]
クラウドプロバイダーはKubernetesプロジェクトとは異なるペースで開発およびリリースされるため、プロバイダー固有のコードを`cloud-controller-manager`バイナリに抽象化することでクラウドベンダーはKubernetesのコアのコードとは独立して開発が可能となりました。
cloud-controller-manager
は、cloudprovider.Interfaceを満たす任意のクラウドプロバイダーと接続できます。下位互換性のためにKubernetesのコアプロジェクトで提供されるcloud-controller-managerはkube-controller-manager
と同じクラウドライブラリを使用します。Kubernetesのコアリポジトリですでにサポートされているクラウドプロバイダーは、Kubernetesリポジトリにあるcloud-controller-managerを使用してKubernetesのコアから移行することが期待されています。
すべてのクラウドには動作させるためにそれぞれのクラウドプロバイダーの統合を行う独自の要件があり、kube-controller-manager
を実行する場合の要件とそれほど違わないようにする必要があります。一般的な経験則として、以下のものが必要です。
cloud-controller-managerを正常に実行するにはクラスター構成にいくつかの変更が必要です。
kube-apiserver
とkube-controller-manager
は**--cloud-provider
フラグを指定してはいけません**。これによりクラウドコントローラーマネージャーによって実行されるクラウド固有のループが実行されなくなります。将来このフラグは非推奨になり削除される予定です。kubelet
は--cloud-provider=external
で実行する必要があります。これは作業をスケジュールする前にクラウドコントローラーマネージャーによって初期化する必要があることをkubeletが認識できるようにするためです。クラウドコントローラーマネージャーを使用するようにクラスターを設定するとクラスターの動作がいくつか変わることに注意してください。
--cloud-provider=external
を指定したkubeletは、初期化時にNoSchedule
のnode.cloudprovider.kubernetes.io/uninitialized
汚染を追加します。これによりノードは作業をスケジュールする前に外部のコントローラーからの2回目の初期化が必要であるとマークされます。クラウドコントローラーマネージャーが使用できない場合クラスター内の新しいノードはスケジュールできないままになることに注意してください。スケジューラーはリージョンやタイプ(高CPU、GPU、高メモリ、スポットインスタンスなど)などのノードに関するクラウド固有の情報を必要とする場合があるためこの汚染は重要です。クラウドコントローラーマネージャーは以下を実装できます。
現在Kubernetesのコアでサポートされているクラウドを使用していて、クラウドコントローラーマネージャーを利用する場合は、kubernetesのコアのクラウドコントローラーマネージャーを参照してください。
Kubernetesのコアリポジトリにないクラウドコントローラーマネージャーの場合、クラウドベンダーまたはsigリードが管理するリポジトリでプロジェクトを見つけることができます。
すでにKubernetesのコアリポジトリにあるプロバイダーの場合、クラスター内でデーモンセットとしてKubernetesリポジトリ内部のクラウドコントローラーマネージャーを実行できます。以下をガイドラインとして使用してください。
# This is an example of how to set up cloud-controller-manager as a Daemonset in your cluster.
# It assumes that your masters can run pods and has the role node-role.kubernetes.io/master
# Note that this Daemonset will not work straight out of the box for your cloud, this is
# meant to be a guideline.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: cloud-controller-manager
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:cloud-controller-manager
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: cloud-controller-manager
namespace: kube-system
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
k8s-app: cloud-controller-manager
name: cloud-controller-manager
namespace: kube-system
spec:
selector:
matchLabels:
k8s-app: cloud-controller-manager
template:
metadata:
labels:
k8s-app: cloud-controller-manager
spec:
serviceAccountName: cloud-controller-manager
containers:
- name: cloud-controller-manager
# for in-tree providers we use registry.k8s.io/cloud-controller-manager
# this can be replaced with any other image for out-of-tree providers
image: registry.k8s.io/cloud-controller-manager:v1.8.0
command:
- /usr/local/bin/cloud-controller-manager
- --cloud-provider=[YOUR_CLOUD_PROVIDER] # Add your own cloud provider here!
- --leader-elect=true
- --use-service-account-credentials
# these flags will vary for every cloud provider
- --allocate-node-cidrs=true
- --configure-cloud-routes=true
- --cluster-cidr=172.17.0.0/16
tolerations:
# this is required so CCM can bootstrap itself
- key: node.cloudprovider.kubernetes.io/uninitialized
value: "true"
effect: NoSchedule
# these tolerations are to have the daemonset runnable on control plane nodes
# remove them if your control plane nodes should not run pods
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
# this is to restrict CCM to only run on master nodes
# the node selector may vary depending on your cluster setup
nodeSelector:
node-role.kubernetes.io/master: ""
クラウドコントローラーマネージャーの実行にはいくつかの制限があります。これらの制限は今後のリリースで対処されますが、本番のワークロードにおいてはこれらの制限を認識することが重要です。
ボリュームの統合にはkubeletとの調整も必要になるためクラウドコントローラーマネージャーはkube-controller-manager
にあるボリュームコントローラーを実装しません。CSI(コンテナストレージインターフェース)が進化してFlexボリュームプラグインの強力なサポートが追加されるにつれ、クラウドがボリュームと完全に統合できるようクラウドコントローラーマネージャーに必要なサポートが追加されます。Kubernetesリポジトリの外部にあるCSIボリュームプラグインの詳細についてはこちらをご覧ください。
cloud-controller-managerは、クラウドプロバイダーのAPIにクエリーを送信して、すべてのノードの情報を取得します。非常に大きなクラスターの場合、リソース要件やAPIレートリミットなどのボトルネックの可能性を考慮する必要があります。
クラウドコントローラーマネージャープロジェクトの目標はKubernetesのコアプロジェクトからクラウドに関する機能の開発を切り離すことです。残念ながら、Kubernetesプロジェクトの多くの面でクラウドプロバイダーの機能がKubernetesプロジェクトに緊密に結びついているという前提があります。そのため、この新しいアーキテクチャを採用するとクラウドプロバイダーの情報を要求する状況が発生する可能性がありますが、クラウドコントローラーマネージャーはクラウドプロバイダーへのリクエストが完了するまでその情報を返すことができない場合があります。
これの良い例は、KubeletのTLSブートストラップ機能です。TLSブートストラップはKubeletがすべてのアドレスタイプ(プライベート、パブリックなど)をクラウドプロバイダー(またはローカルメタデータサービス)に要求する能力を持っていると仮定していますが、クラウドコントローラーマネージャーは最初に初期化されない限りノードのアドレスタイプを設定できないためapiserverと通信するためにはkubeletにTLS証明書が必要です。
このイニシアチブが成熟するに連れ、今後のリリースでこれらの問題に対処するための変更が行われます。
独自のクラウドコントローラーマネージャーを構築および開発するにはクラウドコントローラーマネージャーの開発を参照してください。
Kubernetes v1.18 [beta]
近年、CPUやハードウェア・アクセラレーターの組み合わせによって、レイテンシーが致命的となる実行や高いスループットを求められる並列計算をサポートするシステムが増えています。このようなシステムには、通信、科学技術計算、機械学習、金融サービス、データ分析などの分野のワークロードが含まれます。このようなハイブリッドシステムは、高い性能の環境で構成されます。
最高のパフォーマンスを引き出すために、CPUの分離やメモリーおよびデバイスの位置に関する最適化が求められます。しかしながら、Kubernetesでは、これらの最適化は分断されたコンポーネントによって処理されます。
トポロジーマネージャー はKubeletコンポーネントの1つで最適化の役割を担い、コンポーネント群を調和して機能させます。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
作業するKubernetesサーバーは次のバージョン以降のものである必要があります: v1.18. バージョンを確認するには次のコマンドを実行してください:kubectl version
.トポロジーマネージャー導入前は、KubernetesにおいてCPUマネージャーやデバイスマネージャーはそれぞれ独立してリソースの割り当てを決定します。 これは、マルチソケットのシステムでは望ましくない割り当てとなり、パフォーマンスやレイテンシーが求められるアプリケーションは、この望ましくない割り当てに悩まされます。 この場合の望ましくない例として、CPUやデバイスが異なるNUMAノードに割り当てられ、それによりレイテンシー悪化を招くことが挙げられます。
トポロジーマネージャーはKubeletコンポーネントであり、信頼できる情報源として振舞います。それによって、他のKubeletコンポーネントはトポロジーに沿ったリソース割り当ての選択を行うことができます。
トポロジーマネージャーは Hint Providers と呼ばれるコンポーネントのインターフェースを提供し、トポロジー情報を送受信します。トポロジーマネージャーは、ノード単位のポリシー群を保持します。ポリシーについて以下で説明します。
トポロジーマネージャーは Hint Providers からトポロジー情報を受け取ります。トポロジー情報は、利用可能なNUMAノードと優先割り当て表示を示すビットマスクです。トポロジーマネージャーのポリシーは、提供されたヒントに対して一連の操作を行い、ポリシーに沿ってヒントをまとめて最適な結果を得ます。もし、望ましくないヒントが保存された場合、ヒントの優先フィールドがfalseに設定されます。現在のポリシーでは、最も狭い優先マスクが優先されます。
選択されたヒントはトポロジーマネージャーの一部として保存されます。設定されたポリシーにしたがい、選択されたヒントに基づいてノードがPodを許可したり、拒否することができます。 トポロジーマネージャーに保存されたヒントは、Hint Providers が使用しリソース割り当てを決定します。
トポロジーマネージャーをサポートするには、TopologyManager
フィーチャーゲートを有効にする必要があります。Kubernetes 1.18ではデフォルトで有効です。
トポロジーマネージャは現在:
これらの条件が合致した場合、トポロジーマネージャーは要求されたリソースを調整します。
この調整をどのように実行するかカスタマイズするために、トポロジーマネージャーは2つのノブを提供します: スコープ
とポリシー
です。
スコープ
はリソースの配置を行う粒度を定義します(例:pod
やcontainer
)。そして、ポリシー
は調整を実行するための実戦略を定義します(best-effort
, restricted
, single-numa-node
等)。
現在利用可能なスコープ
とポリシー
の値について詳細は以下の通りです。
トポロジーマネージャーは、以下の複数の異なるスコープでリソースの調整を行う事が可能です:
container
(デフォルト)pod
いずれのオプションも、--topology-manager-scope
フラグによって、kubelet起動時に選択できます。
container
スコープはデフォルトで使用されます。
このスコープでは、トポロジーマネージャーは連続した複数のリソース調整を実行します。つまり、Pod内の各コンテナは、分離された配置計算がされます。言い換えると、このスコープでは、コンテナを特定のNUMAノードのセットにグループ化するという概念はありません。実際には、トポロジーマネージャーは各コンテナのNUMAノードへの配置を任意に実行します。
コンテナをグループ化するという概念は、以下のスコープで設定・実行されます。例えば、pod
スコープが挙げられます。
pod
スコープを選択するには、コマンドラインで--topology-manager-scope=pod
オプションを指定してkubeletを起動します。
このスコープでは、Pod内全てのコンテナを共通のNUMAノードのセットにグループ化することができます。トポロジーマネージャーはPodをまとめて1つとして扱い、ポッド全体(全てのコンテナ)を単一のNUMAノードまたはNUMAノードの共通セットのいずれかに割り当てようとします。以下の例は、さまざまな場面でトポロジーマネージャーが実行する調整を示します:
Pod全体に要求される特定のリソースの総量は有効なリクエスト/リミットの式に従って計算されるため、この総量の値は以下の最大値となります。
pod
スコープとsingle-numa-node
トポロジーマネージャーポリシーを併用することは、レイテンシーが重要なワークロードやIPCを行う高スループットのアプリケーションに対して特に有効です。両方のオプションを組み合わせることで、Pod内の全てのコンテナを単一のNUMAノードに配置できます。そのため、PodのNUMA間通信によるオーバーヘッドを排除することができます。
single-numa-node
ポリシーの場合、可能な割り当ての中に適切なNUMAノードのセットが存在する場合にのみ、Podが許可されます。上の例をもう一度考えてみましょう:
要約すると、トポロジーマネージャーはまずNUMAノードのセットを計算し、それをトポロジーマネージャーのポリシーと照合し、Podの拒否または許可を検証します。
トポロジーマネージャーは4つの調整ポリシーをサポートします。--topology-manager-policy
というKubeletフラグを通してポリシーを設定できます。
4つのサポートされるポリシーがあります:
none
(デフォルト)best-effort
restricted
single-numa-node
これはデフォルトのポリシーで、トポロジーの調整を実行しません。
Pod内の各コンテナに対して、best-effort
トポロジー管理ポリシーが設定されたkubeletは、各Hint Providerを呼び出してそれらのリソースの可用性を検出します。
トポロジーマネージャーはこの情報を使用し、そのコンテナの推奨されるNUMAノードのアフィニティーを保存します。アフィニティーが優先されない場合、トポロジーマネージャーはこれを保存し、Podをノードに許可します。
Hint Providers はこの情報を使ってリソースの割り当てを決定します。
Pod内の各コンテナに対して、restricted
トポロジー管理ポリシーが設定されたkubeletは各Hint Providerを呼び出してそれらのリソースの可用性を検出します。
トポロジーマネージャーはこの情報を使用し、そのコンテナの推奨されるNUMAノードのアフィニティーを保存します。アフィニティーが優先されない場合、トポロジーマネージャーはPodをそのノードに割り当てることを拒否します。この結果、PodはPodの受付失敗となりTerminated
状態になります。
Podが一度Terminated
状態になると、KubernetesスケジューラーはPodの再スケジューリングを試み ません 。Podの再デプロイをするためには、ReplicasetかDeploymenを使用してください。Topology Affinity
エラーとなったpodを再デプロイするために、外部のコントロールループを実行することも可能です。
Podが許可されれば、 Hint Providers はこの情報を使ってリソースの割り当てを決定します。
Pod内の各コンテナに対して、single-numa-node
トポロジー管理ポリシーが設定されたkubeletは各Hint Prociderを呼び出してそれらのリソースの可用性を検出します。
トポロジーマネージャーはこの情報を使用し、単一のNUMAノードアフィニティが可能かどうか決定します。
可能な場合、トポロジーマネージャーは、この情報を保存し、Hint Providers はこの情報を使ってリソースの割り当てを決定します。
不可能な場合、トポロジーマネージャーは、Podをそのノードに割り当てることを拒否します。この結果、Pod は Pod の受付失敗となりTerminated
状態になります。
Podが一度Terminated
状態になると、KubernetesスケジューラーはPodの再スケジューリングを試みません。Podの再デプロイをするためには、ReplicasetかDeploymentを使用してください。Topology Affinity
エラーとなったpodを再デプロイするために、外部のコントロールループを実行することも可能です。
以下のようなpodのSpecで定義されるコンテナを考えます:
spec:
containers:
- name: nginx
image: nginx
requests
もlimits
も定義されていないため、このPodはBestEffort
QoSクラスで実行します。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
requestsがlimitsより小さい値のため、このPodはBurstable
QoSクラスで実行します。
選択されたポリシーがnone
以外の場合、トポロジーマネージャーは、これらのPodのSpecを考慮します。トポロジーマネージャーは、Hint Providersからトポロジーヒントを取得します。CPUマネージャーポリシーがstatic
の場合、デフォルトのトポロジーヒントを返却します。これらのPodは明示的にCPUリソースを要求していないからです。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "2"
example.com/device: "1"
requests:
memory: "200Mi"
cpu: "2"
example.com/device: "1"
整数値でCPUリクエストを指定されたこのPodは、requests
がlimits
が同じ値のため、Guaranteed
QoSクラスで実行します。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "300m"
example.com/device: "1"
requests:
memory: "200Mi"
cpu: "300m"
example.com/device: "1"
CPUの一部をリクエストで指定されたこのPodは、requests
がlimits
が同じ値のため、Guaranteed
QoSクラスで実行します。
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
example.com/deviceA: "1"
example.com/deviceB: "1"
requests:
example.com/deviceA: "1"
example.com/deviceB: "1"
CPUもメモリもリクエスト値がないため、このPodは BestEffort
QoSクラスで実行します。
トポロジーマネージャーは、上記Podを考慮します。トポロジーマネージャーは、Hint ProvidersとなるCPUマネージャーとデバイスマネージャーに問い合わせ、トポロジーヒントを取得します。
整数値でCPU要求を指定されたGuaranteed
QoSクラスのPodの場合、static
が設定されたCPUマネージャーポリシーは、排他的なCPUに関するトポロジーヒントを返却し、デバイスマネージャーは要求されたデバイスのヒントを返します。
CPUの一部を要求を指定されたGuaranteed
QoSクラスのPodの場合、排他的ではないCPU要求のためstatic
が設定されたCPUマネージャーポリシーはデフォルトのトポロジーヒントを返却します。デバイスマネージャーは要求されたデバイスのヒントを返します。
上記のGuaranteed
QoSクラスのPodに関する2ケースでは、none
で設定されたCPUマネージャーポリシーは、デフォルトのトポロジーヒントを返却します。
BestEffort
QoSクラスのPodの場合、static
が設定されたCPUマネージャーポリシーは、CPUの要求がないためデフォルトのトポロジーヒントを返却します。デバイスマネージャーは要求されたデバイスごとのヒントを返します。
トポロジーマネージャーはこの情報を使用してPodに最適なヒントを計算し保存します。保存されたヒントは Hint Providersが使用しリソースを割り当てます。
トポロジーマネージャーが許容するNUMAノードの最大値は8です。8より多いNUMAノードでは、可能なNUMAアフィニティを列挙しヒントを生成する際に、生成する状態数が爆発的に増加します。
スケジューラーはトポロジーを意識しません。そのため、ノードにスケジュールされた後に実行に失敗する可能性があります。
このドキュメントでは、Pod同士の通信を制御するネットワークポリシーを定義するための、KubernetesのNetworkPolicy APIを使い始める手助けをします。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
作業するKubernetesサーバーは次のバージョン以降のものである必要があります: v1.8. バージョンを確認するには次のコマンドを実行してください:kubectl version
.ネットワークポリシーをサポートしているネットワークプロバイダーが設定済みであることを確認してください。さまざまなネットワークプロバイダーがNetworkPolicyをサポートしています。次に挙げるのは一例です。
nginx
Deploymentを作成してService経由で公開するKubernetesのネットワークポリシーの仕組みを理解するために、まずはnginx
Deploymentを作成することから始めましょう。
kubectl create deployment nginx --image=nginx
deployment.apps/nginx created
nginx
という名前のService経由でDeploymentを公開します。
kubectl expose deployment nginx --port=80
service/nginx exposed
上記のコマンドを実行すると、nginx Podを持つDeploymentが作成され、そのDeploymentがnginx
という名前のService経由で公開されます。nginx
のPodおよびDeploymentはdefault
名前空間の中にあります。
kubectl get svc,pod
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes 10.100.0.1 <none> 443/TCP 46m
service/nginx 10.100.0.16 <none> 80/TCP 33s
NAME READY STATUS RESTARTS AGE
pod/nginx-701339712-e0qfq 1/1 Running 0 35s
これで、新しいnginx
サービスに他のPodからアクセスできるようになったはずです。default
名前空間内の他のPodからnginx
Serviceにアクセスするために、busyboxコンテナを起動します。
kubectl run busybox --rm -ti --image=busybox -- /bin/sh
シェルの中で、次のコマンドを実行します。
wget --spider --timeout=1 nginx
Connecting to nginx (10.100.0.16:80)
remote file exists
nginx
Serviceへのアクセスを制限するnginx
Serviceへのアクセスを制限するために、access: true
というラベルが付いたPodだけがクエリできるようにします。次の内容でNetworkPolicyオブジェクトを作成してください。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: access-nginx
spec:
podSelector:
matchLabels:
app: nginx
ingress:
- from:
- podSelector:
matchLabels:
access: "true"
NetworkPolicyオブジェクトの名前は、有効なDNSサブドメイン名でなければなりません。
podSelector
が含まれています。このポリシーは、ラベルapp=nginx
の付いたPodを選択していることがわかります。このラベルは、nginx
Deployment内のPodに自動的に追加されたものです。空のpodSelector
は、その名前空間内のすべてのPodを選択します。kubectlを使って、上記のnginx-policy.yaml
ファイルからNetworkPolicyを作成します。
kubectl apply -f https://k8s.io/examples/service/networking/nginx-policy.yaml
networkpolicy.networking.k8s.io/access-nginx created
nginx
Serviceに正しいラベルが付いていないPodからアクセスを試してみると、リクエストがタイムアウトします。
kubectl run busybox --rm -ti --image=busybox -- /bin/sh
シェルの中で、次のコマンドを実行します。
wget --spider --timeout=1 nginx
Connecting to nginx (10.100.0.16:80)
wget: download timed out
正しいラベルが付いたPodを作成すると、リクエストが許可されるようになるのがわかります。
kubectl run busybox --rm -ti --labels="access=true" --image=busybox -- /bin/sh
シェルの中で、次のコマンドを実行します。
wget --spider --timeout=1 nginx
Connecting to nginx (10.100.0.16:80)
remote file exists
cloud-controller-managerは クラウド特有の制御ロジックを組み込むKubernetesのcontrol planeコンポーネントです。クラウドコントロールマネージャーは、クラスターをクラウドプロバイダーAPIをリンクし、クラスターのみで相互作用するコンポーネントからクラウドプラットフォームで相互作用するコンポーネントを分離します。
Kubernetesと下のクラウドインフラストラクチャー間の相互運用ロジックを分離することで、cloud-controller-managerコンポーネントはクラウドプロバイダを主なKubernetesプロジェクトと比較し異なるペースで機能をリリース可能にします。
クラウドプロバイダーはKubernetesプロジェクトとは異なる速度で開発しリリースすることから、プロバイダー特有なコードをcloud-controller-manager
バイナリから抽象化することで、クラウドベンダーはコアKubernetesコードから独立して発展することができます。
Kubernetesプロジェクトは、(クラウドプロバイダーの)独自実装を組み込めるGoインターフェースを備えたcloud-controller-managerのスケルトンコードを提供しています。これは、クラウドプロバイダーがKubernetesコアからパッケージをインポートすることでcloud-controller-managerを実装できることを意味します。各クラウドプロバイダーは利用可能なクラウドプロバイダーのグローバル変数を更新するためにcloudprovider.RegisterCloudProvider
を呼び出し、独自のコードを登録します。
Kubernetesには登録されていない独自のクラウドプロバイダーのクラウドコントローラーマネージャーを構築するには、
main.go
をあなたのmain.go
のテンプレートとして利用します。上で述べたように、唯一の違いはインポートされるクラウドパッケージのみです。main.go
にインポートし、パッケージに cloudprovider.RegisterCloudProvider
を実行するための init
ブロックがあることを確認します。多くのクラウドプロバイダーはオープンソースとしてコントローラーマネージャーのコードを公開しています。新たにcloud-controller-managerをスクラッチから開発する際には、既存のKubernetesには登録されていない独自クラウドプロバイダーのコントローラーマネージャーを開始地点とすることができます。
Kubernetesに登録されているクラウドプロバイダーであれば、DaemonSetを使ってあなたのクラスターで動かすことができます。詳細についてはKubernetesクラウドコントローラーマネージャーを参照してください。
etcdは 一貫性、高可用性を持ったキーバリューストアで、Kubernetesの全てのクラスター情報の保存場所として利用されています。
etcdをKubernetesのデータストアとして使用する場合、必ずデータのバックアッププランを作成して下さい。
公式ドキュメントでetcdに関する詳細な情報を見つけることができます。
Kubernetesクラスターが必要で、kubectlコマンドラインツールがクラスターと通信できるように設定されている必要があります。 コントロールプレーンノード以外に少なくとも2つのノードを持つクラスターで、このガイドに従うことを推奨します。 まだクラスターを用意していない場合は、minikubeを使用して作成することができます。
etcdは、奇数のメンバーを持つクラスターとして実行します。
etcdはリーダーベースの分散システムです。リーダーが定期的に全てのフォロワーにハートビートを送信し、クラスターの安定性を維持するようにします。
リソース不足が発生しないようにします。
クラスターのパフォーマンスと安定性は、ネットワークとディスクのI/Oに敏感です。 リソース不足はハートビートのタイムアウトを引き起こし、クラスターの不安定化につながる可能性があります。 不安定なetcdは、リーダーが選出されていないことを意味します。 そのような状況では、クラスターは現在の状態に変更を加えることができません。 これは、新しいPodがスケジュールされないことを意味します。
Kubernetesクラスターの安定性には、etcdクラスターの安定性が不可欠です。 したがって、etcdクラスターは専用のマシンまたは保証されたリソース要件を持つ隔離された環境で実行してください。
本番環境で実行するために推奨される最低限のetcdバージョンは、3.4.22
以降あるいは3.5.6
以降です。
限られたリソースでetcdを運用するのはテスト目的にのみ適しています。 本番環境へのデプロイには、高度なハードウェア構成が必要です。 本番環境へetcdをデプロイする前に、リソース要件を確認してください。
このセクションでは、単一ノードおよびマルチノードetcdクラスターの起動について説明します。
単一ノードetcdクラスターは、テスト目的でのみ使用してください。
以下を実行します:
etcd --listen-client-urls=http://$PRIVATE_IP:2379 \
--advertise-client-urls=http://$PRIVATE_IP:2379
Kubernetes APIサーバーをフラグ--etcd-servers=$PRIVATE_IP:2379
で起動します。
PRIVATE_IP
がetcdクライアントIPに設定されていることを確認してください。
耐久性と高可用性のために、本番環境ではマルチノードクラスターとしてetcdを実行し、定期的にバックアップを取ります。 本番環境では5つのメンバーによるクラスターが推奨されます。 詳細はFAQドキュメントを参照してください。
etcdクラスターは、静的なメンバー情報、または動的な検出によって構成されます。 クラスタリングに関する詳細は、etcdクラスタリングドキュメントを参照してください。
例として、次のクライアントURLで実行される5つのメンバーによるetcdクラスターを考えてみます。
5つのURLは、http://$IP1:2379
、http://$IP2:2379
、http://$IP3:2379
、http://$IP4:2379
、およびhttp://$IP5:2379
です。Kubernetes APIサーバーを起動するには、
以下を実行します:
etcd --listen-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379 --advertise-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379
フラグ--etcd-servers=$IP1:2379,$IP2:2379,$IP3:2379,$IP4:2379,$IP5:2379
を使ってKubernetes APIサーバーを起動します。
IP<n>
変数がクライアントのIPアドレスに設定されていることを確認してください。
ロードバランシングされたetcdクラスターを実行するには、次の手順に従います。
$LB
とします。--etcd-servers=$LB:2379
を使ってKubernetes APIサーバーを起動します。etcdへのアクセスはクラスター内でのルート権限に相当するため、理想的にはAPIサーバーのみがアクセスできるようにするべきです。 データの機密性を考慮して、etcdクラスターへのアクセス権を必要とするノードのみに付与することが推奨されます。
etcdをセキュアにするためには、ファイアウォールのルールを設定するか、etcdによって提供されるセキュリティ機能を使用します。
etcdのセキュリティ機能はx509公開鍵基盤(PKI)に依存します。
この機能を使用するには、キーと証明書のペアを生成して、セキュアな通信チャンネルを確立します。
例えば、etcdメンバー間の通信をセキュアにするためにpeer.key
とpeer.cert
のキーペアを使用し、etcdとそのクライアント間の通信をセキュアにするためにclient.key
とclient.cert
を使用します。
クライアント認証用のキーペアとCAファイルを生成するには、etcdプロジェクトによって提供されているサンプルスクリプトを参照してください。
セキュアなピア通信を持つetcdを構成するためには、--peer-key-file=peer.key
および--peer-cert-file=peer.cert
フラグを指定し、URLスキーマとしてHTTPSを使用します。
同様に、セキュアなクライアント通信を持つetcdを構成するためには、--key-file=k8sclient.key
および--cert-file=k8sclient.cert
フラグを指定し、URLスキーマとしてHTTPSを使用します。
セキュアな通信を使用するクライアントコマンドの例は以下の通りです:
ETCDCTL_API=3 etcdctl --endpoints 10.2.0.9:2379 \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
member list
セキュアな通信を構成した後、TLS認証を使用して、etcdクラスターへのアクセスをKubernetes APIサーバーのみに制限します。
例えば、CA etcd.ca
によって信頼されるキーペアk8sclient.key
とk8sclient.cert
を考えてみます。
--client-cert-auth
とTLSを使用してetcdが構成されている場合、etcdは--trusted-ca-file
フラグで渡されたCAまたはシステムのCAを使用してクライアントからの証明書を検証します。
--client-cert-auth=true
および--trusted-ca-file=etcd.ca
フラグを指定することで、証明書k8sclient.cert
を持つクライアントのみにアクセスを制限します。
etcdが正しく構成されると、有効な証明書を持つクライアントのみがアクセスできます。
Kubernetes APIサーバーにアクセス権を与えるためには、--etcd-certfile=k8sclient.cert
、--etcd-keyfile=k8sclient.key
および--etcd-cafile=ca.cert
フラグで構成します。
etcdクラスターは、一部のメンバーの障害を許容することで高可用性を実現します。 しかし、クラスターの全体的な状態を改善するためには、障害が発生したメンバーを直ちに交換することが重要です。 複数のメンバーに障害が発生した場合は、1つずつ交換します。 障害が発生したメンバーを交換するには、メンバーを削除し、新しいメンバーを追加するという2つのステップがあります。
etcdは内部でユニークなメンバーIDを保持していますが、人的なミスを避けるためにも各メンバーにはユニークな名前を使用することが推奨されます。
例えば、3つのメンバーのetcdクラスターを考えてみましょう。
URLがmember1=http://10.0.0.1
、member2=http://10.0.0.2
、そしてmember3=http://10.0.0.3
だとします。
member1
に障害が発生した場合、member4=http://10.0.0.4
で交換します。
障害が発生したmember1
のメンバーIDを取得します:
etcdctl --endpoints=http://10.0.0.2,http://10.0.0.3 member list
次のメッセージが表示されます:
8211f1d0f64f3269, started, member1, http://10.0.0.1:2380, http://10.0.0.1:2379
91bc3c398fb3c146, started, member2, http://10.0.0.2:2380, http://10.0.0.2:2379
fd422379fda50e48, started, member3, http://10.0.0.3:2380, http://10.0.0.3:2379
以下のいずれかを行います:
--etcd-servers
フラグから障害が発生したメンバーを削除し、各Kubernetes APIサーバーを再起動します。壊れたノード上のetcdサーバーを停止します。 Kubernetes APIサーバー以外のクライアントからetcdにトラフィックが流れている可能性があり、データディレクトリへの書き込みを防ぐためにすべてのトラフィックを停止することが望ましいです。
メンバーを削除します:
etcdctl member remove 8211f1d0f64f3269
次のメッセージが表示されます:
Removed member 8211f1d0f64f3269 from cluster
新しいメンバーを追加します:
etcdctl member add member4 --peer-urls=http://10.0.0.4:2380
次のメッセージが表示されます:
Member 2be1eb8f84b7f63e added to cluster ef37ad9dc622a7c4
IP 10.0.0.4
のマシン上で新たに追加されたメンバーを起動します:
export ETCD_NAME="member4"
export ETCD_INITIAL_CLUSTER="member2=http://10.0.0.2:2380,member3=http://10.0.0.3:2380,member4=http://10.0.0.4:2380"
export ETCD_INITIAL_CLUSTER_STATE=existing
etcd [flags]
以下のいずれかを行います:
--etcd-servers
フラグに新たに追加されたメンバーを加え、各Kubernetes APIサーバーを再起動します。クラスターの再構成に関する詳細については、etcd再構成ドキュメントを参照してください。
すべてのKubernetesオブジェクトはetcdに保存されています。 定期的にetcdクラスターのデータをバックアップすることは、すべてのコントロールプレーンノードを失うなどの災害シナリオでKubernetesクラスターを復旧するために重要です。 スナップショットファイルには、すべてのKubernetesの状態と重要な情報が含まれています。 機密性の高いKubernetesデータを安全に保つために、スナップショットファイルを暗号化してください。
etcdクラスターのバックアップは、etcdのビルトインスナップショットとボリュームスナップショットの2つの方法で実現できます。
etcdはビルトインスナップショットをサポートしています。
スナップショットは、etcdctl snapshot save
コマンドを使用してライブメンバーから、あるいはetcdプロセスによって現在使用されていないデータディレクトリからmember/snap/db
ファイルをコピーして作成できます。
スナップショットを作成しても、メンバーのパフォーマンスに影響はありません。
以下は、$ENDPOINT
によって提供されるキースペースのスナップショットをsnapshot.db
ファイルに作成する例です:
ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshot.db
スナップショットを確認します:
ETCDCTL_API=3 etcdctl --write-out=table snapshot status snapshot.db
+----------+----------+------------+------------+
| HASH | REVISION | TOTAL KEYS | TOTAL SIZE |
+----------+----------+------------+------------+
| fe01cf57 | 10 | 7 | 2.1 MB |
+----------+----------+------------+------------+
etcdがAmazon Elastic Block Storeのようなバックアップをサポートするストレージボリューム上で実行されている場合、ストレージボリュームのスナップショットを作成することによってetcdデータをバックアップします。
etcdctlによって提供されるさまざまなオプションを使用してスナップショットを作成することもできます。例えば
ETCDCTL_API=3 etcdctl -h
はetcdctlから利用可能なさまざまなオプションを一覧表示します。 例えば、以下のようにエンドポイント、証明書、キーを指定してスナップショットを作成することができます:
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=<trusted-ca-file> --cert=<cert-file> --key=<key-file> \
snapshot save <backup-file-location>
ここで、trusted-ca-file
、cert-file
、key-file
はetcd Podの説明から取得できます。
etcdクラスターのスケールアウトは、パフォーマンスとのトレードオフで可用性を高めます。 スケーリングはクラスターのパフォーマンスや能力を高めるものではありません。 一般的なルールとして、etcdクラスターをスケールアウトまたはスケールインすることはありません。 etcdクラスターに自動スケーリンググループを設定しないでください。 公式にサポートされるどんなスケールの本番環境のKubernetesクラスターにおいても、常に静的な5つのメンバーのetcdクラスターを運用することを強く推奨します。
合理的なスケーリングは、より高い信頼性が求められる場合に、3つのメンバーで構成されるクラスターを5つのメンバーにアップグレードすることです。 既存のクラスターにメンバーを追加する方法については、etcdの再構成ドキュメントを参照してください。
etcdは、major.minorバージョンのetcdプロセスから取得されたスナップショットからの復元をサポートしています。 異なるパッチバージョンのetcdからのバージョン復元もサポートされています。 復元操作は、障害が発生したクラスターのデータを回復するために用いられます。
復元操作を開始する前に、スナップショットファイルが存在している必要があります。 これは、以前のバックアップ操作からのスナップショットファイルでも、残っているデータディレクトリからのスナップショットファイルでも構いません。
クラスターを復元する場合は、--data-dir
オプションを使用して、クラスターをどのフォルダーに復元するかを指定します:
ETCDCTL_API=3 etcdctl --data-dir <data-dir-location> snapshot restore snapshot.db
ここで、<data-dir-location>
は復元プロセス中に作成されるディレクトリです。
もう一つの例としては、まずETCDCTL_API
環境変数をエクスポートします:
export ETCDCTL_API=3
etcdctl --data-dir <data-dir-location> snapshot restore snapshot.db
<data-dir-location>
が以前と同じフォルダーである場合は、クラスターを復元する前にそれを削除してetcdプロセスを停止します。そうでない場合は、etcdの構成を変更し、復元後にetcdプロセスを再起動して新しいデータディレクトリを使用するようにします。
スナップショットファイルからクラスターを復元する方法と例についての詳細は、etcd災害復旧ドキュメントを参照してください。
復元されたクラスターのアクセスURLが前のクラスターと異なる場合、Kubernetes APIサーバーをそれに応じて再設定する必要があります。
この場合、--etcd-servers=$OLD_ETCD_CLUSTER
のフラグの代わりに、--etcd-servers=$NEW_ETCD_CLUSTER
のフラグでKubernetes APIサーバーを再起動します。
$NEW_ETCD_CLUSTER
と$OLD_ETCD_CLUSTER
をそれぞれのIPアドレスに置き換えてください。
etcdクラスターの前にロードバランサーを使用している場合、代わりにロードバランサーを更新する必要があるかもしれません。
etcdメンバーの過半数に永続的な障害が発生した場合、etcdクラスターは故障したと見なされます。 このシナリオでは、Kubernetesは現在の状態に対して変更を加えることができません。 スケジュールされたPodは引き続き実行されるかもしれませんが、新しいPodはスケジュールできません。 このような場合、etcdクラスターを復旧し、必要に応じてKubernetes APIサーバーを再設定して問題を修正します。
クラスター内でAPIサーバーが実行されている場合、etcdのインスタンスを復元しようとしないでください。 代わりに、以下の手順に従ってetcdを復元してください:
また、kube-scheduler
、kube-controller-manager
、kubelet
などのコンポーネントを再起動することもお勧めします。
これは、これらが古いデータに依存していないことを確認するためです。実際には、復元には少し時間がかかります。
復元中、重要なコンポーネントはリーダーロックを失い、自動的に再起動します。
etcdのアップグレードに関する詳細は、etcdアップグレードのドキュメントを参照してください。
etcdのメンテナンスに関する詳細は、etcdメンテナンスのドキュメントを参照してください。
デフラグメンテーションはコストがかかる操作のため、できるだけ頻繁に実行しないようにしてください。 一方で、etcdメンバーがストレージのクォータを超えないようにする必要もあります。 Kubernetesプロジェクトでは、デフラグメンテーションを行う際には、etcd-defragなどのツールを使用することを推奨しています。
また、デフラグメンテーションを定期的に実行するために、KubernetesのCronJobとしてデフラグメンテーションツールを実行することもできます。
詳細はetcd-defrag-cronjob.yaml
を参照してください。
このドキュメントでは、偶発的または悪意のあるアクセスからクラスターを保護するためのトピックについて説明します。 また、全体的なセキュリティに関する推奨事項を提供します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.Kubernetesは完全にAPI駆動であるため、誰がクラスターにアクセスできるか、どのようなアクションを実行できるかを制御・制限することが第一の防御策となります。
Kubernetesは、クラスター内のすべてのAPI通信がデフォルトでTLSにより暗号化されていることを期待しており、大半のインストール方法では、必要な証明書を作成してクラスターコンポーネントに配布することができます。
コンポーネントやインストール方法によっては、HTTP上のローカルポートを有効にする場合があることに注意してください。管理者は、潜在的に保護されていないトラフィックを特定するために、各コンポーネントの設定に精通している必要があります。
クラスターのインストール時に、共通のアクセスパターンに合わせて、APIサーバーが使用する認証メカニズムを選択します。 例えば、シングルユーザーの小規模なクラスターでは、シンプルな証明書や静的なBearerトークンを使用することができます。 大規模なクラスターでは、ユーザーをグループに細分化できる既存のOIDCまたはLDAPサーバーを統合することができます。
ノード、プロキシ、スケジューラー、ボリュームプラグインなど、インフラの一部であるものも含めて、すべてのAPIクライアントを認証する必要があります。 これらのクライアントは通常、service accountsであるか、またはx509クライアント証明書を使用しており、クラスター起動時に自動的に作成されるか、クラスターインストールの一部として設定されます。
詳細については、認証を参照してください。
認証されると、すべてのAPIコールは認可チェックを通過することになります。
Kubernetesには、統合されたRBACコンポーネントが搭載されており、入力されたユーザーやグループを、ロールにまとめられたパーミッションのセットにマッチさせます。 これらのパーミッションは、動詞(get, create, delete)とリソース(pods, services, nodes)を組み合わせたもので、ネームスペース・スコープまたはクラスター・スコープに対応しています。 すぐに使えるロールのセットが提供されており、クライアントが実行したいアクションに応じて、デフォルトで適切な責任の分離を提供します。
NodeとRBACの承認者は、NodeRestrictionのアドミッションプラグインと組み合わせて使用することをお勧めします。
認証の場合と同様に、小規模なクラスターにはシンプルで幅広い役割が適切かもしれません。 しかし、より多くのユーザーがクラスターに関わるようになるとチームを別の名前空間に分け、より限定的な役割を持たせることが必要になるかもしれません。 認可においては、あるオブジェクトの更新が、他の場所でどのようなアクションを起こすかを理解することが重要です。
たとえば、ユーザーは直接Podを作成することはできませんが、ユーザーに代わってPodを作成するDeploymentの作成を許可することで、間接的にそれらのPodを作成することができます。 同様に、APIからノードを削除すると、そのノードにスケジューリングされていたPodが終了し、他のノードに再作成されます。 すぐに使えるロールは、柔軟性と一般的なユースケースのバランスを表していますが、より限定的なロールは、偶発的なエスカレーションを防ぐために慎重に検討する必要があります。 すぐに使えるロールがニーズを満たさない場合は、ユースケースに合わせてロールを作成することができます。
詳しくはauthorization reference sectionに参照してください。
Kubeletsは、ノードやコンテナの強力な制御を可能にするHTTPSエンドポイントを公開しています。 デフォルトでは、KubeletsはこのAPIへの認証されていないアクセスを許可しています。
本番環境のクラスターでは、Kubeletの認証と認可を有効にする必要があります。
詳細は、Kubelet 認証/認可に参照してください。
Kubernetesにおける権限付与は、意図的にハイレベルであり、リソースに対する粗いアクションに焦点を当てています。
より強力なコントロールはpoliciesとして存在し、それらのオブジェクトがクラスターや自身、その他のリソースにどのように作用するかをユースケースによって制限します。
リソースクォータは、ネームスペースに付与されるリソースの数や容量を制限するものです。
これは、ネームスペースが割り当てることのできるCPU、メモリー、永続的なディスクの量を制限するためによく使われますが、各ネームスペースに存在するPod、サービス、ボリュームの数を制御することもできます。
Limit rangesは、上記のリソースの一部の最大または最小サイズを制限することで、ユーザーがメモリーなどの一般的に予約されたリソースに対して不当に高いまたは低い値を要求するのを防いだり、何も指定されていない場合にデフォルトの制限を提供したりします。
Podの定義には、security contextが含まれており、ノード上の特定の Linux ユーザー(rootなど)として実行するためのアクセス、特権的に実行するためのアクセス、ホストネットワークにアクセスするためのアクセス、その他の制御を要求することができます。 Pod security policiesは、危険なセキュリティコンテキスト設定を提供できるユーザーやサービスアカウントを制限することができます。
たとえば、Podのセキュリティポリシーでは、ボリュームマウント、特にhostPath
を制限することができ、これはPodの制御すべき側面です。
一般に、ほとんどのアプリケーションワークロードでは、ホストリソースへのアクセスを制限する必要があります。
ホスト情報にアクセスすることなく、ルートプロセス(uid 0)として正常に実行できます。
ただし、ルートユーザーに関連する権限を考慮して、非ルートユーザーとして実行するようにアプリケーションコンテナを記述する必要があります。
Linuxカーネルは、ハードウェアが接続されたときやファイルシステムがマウントされたときなど、特定の状況下で必要となるカーネルモジュールをディスクから自動的にロードします。 特にKubernetesでは、非特権プロセスであっても、適切なタイプのソケットを作成するだけで、特定のネットワークプロトコル関連のカーネルモジュールをロードさせることができます。これにより、管理者が使用されていないと思い込んでいるカーネルモジュールのセキュリティホールを攻撃者が利用できる可能性があります。 特定のモジュールが自動的にロードされないようにするには、そのモジュールをノードからアンインストールしたり、ルールを追加してブロックしたりします。
ほとんどのLinuxディストリビューションでは、/etc/modprobe.d/kubernetes-blacklist.conf
のような内容のファイルを作成することで実現できます。
# DCCPは必要性が低く、複数の深刻な脆弱性があり、保守も十分ではありません。
blacklist dccp
# SCTPはほとんどのKubernetesクラスターでは使用されておらず、また過去には脆弱性がありました。
blacklist sctp
モジュールのロードをより一般的にブロックするには、SELinuxなどのLinuxセキュリティモジュールを使って、コンテナに対する module_request
権限を完全に拒否し、いかなる状況下でもカーネルがコンテナ用のモジュールをロードできないようにすることができます。
(Podは、手動でロードされたモジュールや、より高い権限を持つプロセスに代わってカーネルがロードしたモジュールを使用することはできます)。
名前空間のネットワークポリシーにより、アプリケーション作成者は、他の名前空間のPodが自分の名前空間内のPodやポートにアクセスすることを制限することができます。
サポートされているKubernetes networking providersの多くは、ネットワークポリシーを尊重するようになりました。 クォータやリミットの範囲は、ユーザーがノードポートや負荷分散サービスを要求するかどうかを制御するためにも使用でき、多くのクラスターでは、ユーザーのアプリケーションがクラスターの外で見えるかどうかを制御できます。 ノードごとのファイアウォール、クロストークを防ぐための物理的なクラスターノードの分離、高度なネットワークポリシーなど、プラグインや環境ごとにネットワークルールを制御する追加の保護機能が利用できる場合もあります。
クラウドプラットフォーム(AWS、Azure、GCEなど)では、しばしばメタデータサービスをインスタンスローカルに公開しています。 デフォルトでは、これらのAPIはインスタンス上で実行されているPodからアクセスでき、そのノードのクラウド認証情報や、kubelet認証情報などのプロビジョニングデータを含むことができます。 これらの認証情報は、クラスター内でのエスカレーションや、同じアカウントの他のクラウドサービスへのエスカレーションに使用できます。
クラウドプラットフォーム上でKubernetesを実行する場合は、インスタンスの認証情報に与えられるパーミッションを制限し、ネットワークポリシーを使用してメタデータAPIへのPodのアクセスを制限し、プロビジョニングデータを使用してシークレットを配信することは避けてください。
デフォルトでは、どのノードがPodを実行できるかについての制限はありません。 Kubernetesは、エンドユーザーが利用できるNode上へのPodのスケジューリングとTaintとTolerationを提供します。 多くのクラスターでは、ワークロードを分離するためにこれらのポリシーを使用することは、作者が採用したり、ツールを使って強制したりする慣習になっています。
管理者としては、ベータ版のアドミッションプラグイン「PodNodeSelector」を使用して、ネームスペース内のPodをデフォルトまたは特定のノードセレクタを必要とするように強制することができます。 エンドユーザーがネームスペースを変更できない場合は、特定のワークロード内のすべてのPodの配置を強く制限することができます。
このセクションでは、クラスターを危険から守るための一般的なパターンを説明します。
API用のetcdバックエンドへの書き込みアクセスは、クラスター全体のrootを取得するのと同等であり、読み取りアクセスはかなり迅速にエスカレートするために使用できます。 管理者は、TLSクライアント証明書による相互認証など、APIサーバーからetcdサーバーへの強力な認証情報を常に使用すべきであり、API サーバーのみがアクセスできるファイアウォールの後ろにetcdサーバーを隔離することがしばしば推奨されます。
audit loggerはベータ版の機能で、APIによって行われたアクションを記録し、侵害があった場合に後から分析できるようにするものです。
監査ログを有効にして、ログファイルを安全なサーバーにアーカイブすることをお勧めします。
アルファ版およびベータ版のKubernetesの機能は活発に開発が行われており、セキュリティ上の脆弱性をもたらす制限やバグがある可能性があります。 常に、アルファ版またはベータ版の機能が提供する価値と、セキュリティ体制に起こりうるリスクを比較して評価してください。 疑問がある場合は、使用しない機能を無効にしてください。
秘密やクレデンシャルの有効期間が短いほど、攻撃者がそのクレデンシャルを利用することは難しくなります。 証明書の有効期間を短く設定し、そのローテーションを自動化します。 発行されたトークンの利用可能期間を制御できる認証プロバイダーを使用し、可能な限り短いライフタイムを使用します。 外部統合でサービス・アカウント・トークンを使用する場合、これらのトークンを頻繁にローテーションすることを計画します。 例えば、ブートストラップ・フェーズが完了したら、ノードのセットアップに使用したブートストラップ・トークンを失効させるか、その認証を解除する必要があります。
Kubernetesへの多くのサードパーティの統合は、クラスターのセキュリティプロファイルを変更する可能性があります。 統合を有効にする際には、アクセスを許可する前に、拡張機能が要求するパーミッションを常に確認してください。
例えば、多くのセキュリティ統合は、事実上そのコンポーネントをクラスター管理者にしているクラスター上のすべての秘密を見るためのアクセスを要求するかもしれません。
疑問がある場合は、可能な限り単一の名前空間で機能するように統合を制限してください。
Podを作成するコンポーネントも、kube-system
名前空間のような名前空間内で行うことができれば、予想外に強力になる可能性があります。これは、サービスアカウントのシークレットにアクセスしたり、サービスアカウントに寛容なpod security policiesへのアクセスが許可されている場合に、昇格したパーミッションでPodが実行される可能性があるからです。
一般的に、etcdデータベースにはKubernetes APIを介してアクセス可能なあらゆる情報が含まれており、クラスターの状態に対する大きな可視性を攻撃者へ与える可能性があります。 よく吟味されたバックアップおよび暗号化ソリューションを使用して、常にバックアップを暗号化し、可能な場合はフルディスク暗号化の使用を検討してください。
Kubernetesは1.7で導入された機能であるencryption at restをサポートしており、これは1.13からはベータ版となっています。
これは、etcdのSecret
リソースを暗号化し、etcdのバックアップにアクセスした人が、それらのシークレットの内容を見ることを防ぎます。
この機能は現在ベータ版ですが、バックアップが暗号化されていない場合や、攻撃者がetcdへの読み取りアクセスを得た場合に、追加の防御レベルを提供します。
kubernetes-announceに参加してください。 グループに参加すると、セキュリティアナウンスに関するメールを受け取ることができます。 脆弱性の報告方法については、security reportingページを参照してください。
このページでは、Kubernetesクラスターをアップグレードする際に従うべき手順の概要を提供します。
クラスターのアップグレード方法は、初期のデプロイ方法やその後の変更によって異なります。
大まかな手順は以下の通りです:
既存のクラスターが必要です。このページではKubernetes 1.31からKubernetes 1.32へのアップグレードについて説明しています。現在のクラスターがKubernetes 1.31を実行していない場合は、アップグレードしようとしているKubernetesバージョンのドキュメントを確認してください。
クラスターがkubeadm
ツールを使用してデプロイされた場合の詳細なアップグレード方法は、kubeadmクラスターのアップグレードを参照してください。
クラスターをアップグレードしたら、忘れずに最新バージョンのkubectl
をインストールしてください。
次の順序でコントロールプレーンを手動で更新する必要があります:
この時点で、最新バージョンのkubectl
をインストールしてください。
クラスター内の各ノードに対して、そのノードをドレインし、1.32 kubeletを使用する新しいノードと置き換えるか、そのノードのkubeletをアップグレードして再稼働させます。
クラスターデプロイメントツールのドキュメントを参照して、メンテナンスの推奨手順を確認してください。
クラスターの内部表現でアクティブなKubernetesリソースのためにetcdにシリアル化されるオブジェクトは、特定のAPIバージョンを使用して書き込まれます。
サポートされるAPIが変更されると、これらのオブジェクトは新しいAPIで再書き込みする必要があります。これを行わないと、最終的にはKubernetes APIサーバーによってデコードまたは使用できなくなるリソースが発生する可能性があります。
影響を受ける各オブジェクトについて、最新のサポートされるAPIを使用して取得し、最新のサポートされるAPIを使用して再書き込みします。
新しいKubernetesバージョンへのアップグレードにより、新しいAPIが提供されることがあります。
異なるAPIバージョン間でマニフェストを変換するためにkubectl convert
コマンドを使用できます。例えば:
kubectl convert -f pod.yaml --output-version v1
kubectl
ツールはpod.yaml
の内容を、kind
がPod(変更なし)で、apiVersion
が改訂されたマニフェストに置き換えます。
クラスターがデバイスプラグインを実行しており、ノードを新しいデバイスプラグインAPIバージョンを含むKubernetesリリースにアップグレードする必要がある場合、デバイスプラグインをアップグレードして両方のバージョンをサポートする必要があります。これにより、アップグレード中にデバイスの割り当てが正常に完了し続けることが保証されます。
詳細については、API互換性およびkubeletのデバイスマネージャーAPIバージョンを参照してください。
このページでは、ガベージコレクション中にクラスターで使用するカスケード削除のタイプを指定する方法を示します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
また、さまざまな種類のカスケード削除を試すために、サンプルのDeploymentを作成する必要があります。 タイプごとにDeploymentを再作成する必要があります。
PodにownerReferences
フィールドが存在することを確認します:
kubectl get pods -l app=nginx --output=yaml
出力には、次のようにownerReferences
フィールドがあります。
apiVersion: v1
...
ownerReferences:
- apiVersion: apps/v1
blockOwnerDeletion: true
controller: true
kind: ReplicaSet
name: nginx-deployment-6b474476c4
uid: 4fdcd81c-bd5d-41f7-97af-3a3b759af9a7
...
デフォルトでは、Kubernetesはバックグラウンドカスケード削除を使用して、オブジェクトの依存関係を削除します。
クラスターが動作しているKubernetesのバージョンに応じて、kubectl
またはKubernetes APIのいずれかを使用して、フォアグラウンドカスケード削除に切り替えることができます。
バージョンを確認するには次のコマンドを実行してください: kubectl version
.
kubectl
またはKubernetes APIを使用して、フォアグラウンドカスケード削除を使用してオブジェクトを削除することができます。
kubectlを使用する
以下のコマンドを実行してください:
kubectl delete deployment nginx-deployment --cascade=foreground
Kubernetes APIを使用する
ローカルプロキシセッションを開始します:
kubectl proxy --port=8080
削除のトリガーとしてcurl
を使用します:
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Foreground"}' \
-H "Content-Type: application/json"
出力には、次のようにforegroundDeletion
ファイナライザーが含まれています。
"kind": "Deployment",
"apiVersion": "apps/v1",
"metadata": {
"name": "nginx-deployment",
"namespace": "default",
"uid": "d1ce1b02-cae8-4288-8a53-30e84d8fa505",
"resourceVersion": "1363097",
"creationTimestamp": "2021-07-08T20:24:37Z",
"deletionTimestamp": "2021-07-08T20:27:39Z",
"finalizers": [
"foregroundDeletion"
]
...
kubectl
またはKubernetes APIのいずれかを使用してDeploymentを削除します。
バージョンを確認するには次のコマンドを実行してください: kubectl version
.kubectl
またはKubernetes APIを使用して、バックグラウンドカスケード削除を使用してオブジェクトを削除できます。
Kubernetesはデフォルトでバックグラウンドカスケード削除を使用し、--cascade
フラグまたはpropagationPolicy
引数なしで以下のコマンドを実行した場合も同様です。
kubectlを使用する
以下のコマンドを実行してください:
kubectl delete deployment nginx-deployment --cascade=background
Kubernetes APIを使用する
ローカルプロキシセッションを開始します:
kubectl proxy --port=8080
削除のトリガーとしてcurl
を使用します:
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
-H "Content-Type: application/json"
出力は、次のようになります。
"kind": "Status",
"apiVersion": "v1",
...
"status": "Success",
"details": {
"name": "nginx-deployment",
"group": "apps",
"kind": "deployments",
"uid": "cc9eefb9-2d49-4445-b1c1-d261c9396456"
}
デフォルトでは、Kubernetesにオブジェクトの削除を指示すると、コントローラーは従属オブジェクトも削除します。クラスターが動作しているKubernetesのバージョンに応じて、kubectl
またはKubernetes APIを使用して、これらの従属オブジェクトをKubernetesでorphanにすることができます。
バージョンを確認するには次のコマンドを実行してください: kubectl version
.
kubectlを使用する
以下のコマンドを実行してください:
kubectl delete deployment nginx-deployment --cascade=orphan
Kubernetes APIを使用する
ローカルプロキシセッションを開始します:
kubectl proxy --port=8080
削除のトリガーとしてcurl
を使用します:
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
-H "Content-Type: application/json"
出力には、次のようにfinalizers
フィールドにorphan
が含まれます。
"kind": "Deployment",
"apiVersion": "apps/v1",
"namespace": "default",
"uid": "6f577034-42a0-479d-be21-78018c466f1f",
"creationTimestamp": "2021-07-09T16:46:37Z",
"deletionTimestamp": "2021-07-09T16:47:08Z",
"deletionGracePeriodSeconds": 0,
"finalizers": [
"orphan"
],
...
Deploymentによって管理されているPodがまだ実行中であることを確認できます。
kubectl get pods -l app=nginx
このページでは、CoreDNSのアップグレードプロセスと、kube-dnsの代わりにCoreDNSをインストールする方法を説明します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
作業するKubernetesサーバーは次のバージョン以降のものである必要があります: v1.9. バージョンを確認するには次のコマンドを実行してください:kubectl version
.CoreDNSは、KubernetesクラスターDNSとして稼働させることができる柔軟で拡張可能なDNSサーバーです。Kubernetesと同様に、CoreDNSプロジェクトはCNCFによってホストされています。
既存のデプロイでkube-dnsを置き換えるか、クラスターのデプロイとアップグレードを代行してくれるkubeadmのようなツールを使用することで、クラスターでkube-dnsの代わりにCoreDNSを使用することができます。
kube-dnsの手動デプロイや置き換えについては、CoreDNS websiteのドキュメントを参照してください。
Kubernetesバージョン1.21でkubeadm
はDNSアプリケーションとしてのkube-dns
に対するサポートを削除しました。
kubeadm
v1.32に対してサポートされるクラスターDNSアプリケーションはCoreDNS
のみです。
kube-dns
を使用しているクラスターをkubeadm
を使用してアップグレードするときに、CoreDNSに移行することができます。
この場合、kubeadm
は、kube-dns
ConfigMapをベースにしてCoreDNS
設定("Corefile")を生成し、スタブドメインおよび上流のネームサーバーの設定を保持します。
Kubernetesのバージョンごとにkubeadm
がインストールするCoreDNS
のバージョンは、KubernetesにおけるCoreDNSのバージョンのページで確認することができます。
CoreDNS
のみをアップグレードしたい場合や、独自のカスタムイメージを使用したい場合は、CoreDNS
を手動でアップグレードすることができます。
スムーズなアップグレードのために役立つガイドラインとウォークスルーが用意されています。
クラスターをアップグレードする際には、既存のCoreDNS
設定("Corefile")が保持されていることを確認してください。
kubeadm
ツールを使用してクラスターをアップグレードしている場合、kubeadm
は既存のCoreDNSの設定を自動的に保持する処理を行うことができます。
リソース使用率が問題になる場合は、CoreDNSの設定を調整すると役立つ場合があります。 詳細は、CoreDNSのスケーリングに関するドキュメントを参照してください。
CoreDNSは、設定("Corefile")を変更することで、kube-dns
よりも多くのユースケースをサポートする構成にすることができます。
詳細はKubernetes CoreDNSプラグインのドキュメントを参照するか、CoreDNSブログを参照してください。
Kubernetes v1.18 [stable]
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.NodeLocal DNSキャッシュは、クラスターノード上でDNSキャッシュエージェントをDaemonSetで稼働させることで、クラスターのDNSパフォーマンスを向上させます。現在のアーキテクチャにおいて、ClusterFirstのDNSモードでのPodは、DNSクエリー用にkube-dnsのService IPに疎通します。これにより、kube-proxyによって追加されたiptablesを介してkube-dns/CoreDNSのエンドポイントへ変換されます。この新しいアーキテクチャによって、Podは同じノード上で稼働するDNSキャッシュエージェントに対して疎通し、それによってiptablesのDNATルールとコネクショントラッキングを回避します。ローカルのキャッシュエージェントはクラスターのホスト名(デフォルトではcluster.localというサフィックス)に対するキャッシュミスがあるときはkube-dnsサービスへ問い合わせます。
現在のDNSアーキテクチャでは、ローカルのkube-dns/CoreDNSがないとき、DNSへの秒間クエリー数が最も高いPodは他のノードへ疎通する可能性があります。ローカルでキャッシュを持つことにより、この状況におけるレイテンシーの改善に役立ちます。
iptables DNATとコネクショントラッキングをスキップすることはconntrackの競合を減らし、UDPでのDNSエントリーがconntrackテーブルを満杯にすることを避けるのに役立ちます。
ローカルのキャッシュエージェントからkube-dnsサービスへの接続がTCPにアップグレードされます。タイムアウトをしなくてはならないUDPエントリーと比べ、TCPのconntrackエントリーはコネクションクローズ時に削除されます(デフォルトの nf_conntrack_udp_timeout
は30秒です)。
DNSクエリーをUDPからTCPにアップグレードすることで、UDPパケットの欠損や、通常30秒(10秒のタイムアウトで3回再試行する)であるDNSのタイムアウトによるテイルレイテンシーを減少させます。NodeLocalキャッシュはUDPのDNSクエリーを待ち受けるため、アプリケーションを変更する必要はありません。
DNSクエリーに対するノードレベルのメトリクスと可視性を得られます。
DNSの不在応答のキャッシュも再度有効にされ、それによりkube-dnsサービスに対するクエリー数を減らします。
この図はNodeLocal DNSキャッシュが有効にされた後にDNSクエリーがあったときの流れとなります。
この機能は、下記の手順により有効化できます。
nodelocaldns.yaml
と同様のマニフェストを用意し、nodelocaldns.yaml
という名前で保存してください。
マニフェスト内の変数を正しい値に置き換えてください。
kubedns=kubectl get svc kube-dns -n kube-system -o jsonpath={.spec.clusterIP}
domain=<cluster-domain>
localdns=<node-local-address>
<cluster-domain>
はデフォルトで"cluster.local"です。<node-local-address>
はNodeLocal DNSキャッシュ用に確保されたローカルの待ち受けIPアドレスです。
kube-proxyがIPTABLESモードで稼働中のとき:
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__/$kubedns/g" nodelocaldns.yaml
__PILLAR__CLUSTER__DNS__
と__PILLAR__UPSTREAM__SERVERS__
はnode-local-dnsというPodによって生成されます。
このモードでは、node-local-dns Podは<node-local-address>
とkube-dnsのサービスIPの両方で待ち受けるため、PodはIPアドレスでもDNSレコードのルップアップができます。
kube-proxyがIPVSモードで稼働中のとき:
sed -i "s/__PILLAR__LOCAL__DNS__/$localdns/g; s/__PILLAR__DNS__DOMAIN__/$domain/g; s/__PILLAR__DNS__SERVER__//g; s/__PILLAR__CLUSTER__DNS__/$kubedns/g" nodelocaldns.yaml
このモードでは、node-local-dns Podは<node-local-address>
上のみで待ち受けます。node-local-dnsのインターフェースはkube-dnsのクラスターIPをバインドしません。なぜならばIPVSロードバランシング用に使われているインターフェースは既にこのアドレスを使用しているためです。
__PILLAR__UPSTREAM__SERVERS__
はnode-local-dns Podにより生成されます。
kubectl create -f nodelocaldns.yaml
を実行してください。
kube-proxyをIPVSモードで使用しているとき、NodeLocal DNSキャッシュが待ち受けている<node-local-address>
を使用するため、kubeletに対する--cluster-dns
フラグを修正する必要があります。IPVSモード以外のとき、--cluster-dns
フラグの値を修正する必要はありません。なぜならNodeLocal DNSキャッシュはkube-dnsのサービスIPと<node-local-address>
の両方で待ち受けているためです。
一度有効にすると、クラスターの各Node上で、kube-systemという名前空間でnode-local-dns Podが、稼働します。このPodはCoreDNSをキャッシュモードで稼働させるため、異なるプラグインによって公開された全てのCoreDNSのメトリクスがNode単位で利用可能となります。
kubectl delete -f <manifest>
を実行してDaemonSetを削除することによって、この機能を無効にできます。また、kubeletの設定に対して行った全ての変更をリバートすべきです。
このページはKubernetesのEndpointSliceの有効化の概要を説明します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.EndpointSliceは、KubernetesのEndpointsに対してスケーラブルで拡張可能な代替手段を提供します。Endpointsが提供する機能のベースの上に構築し、スケーラブルな方法で拡張します。Serviceが多数(100以上)のネットワークエンドポイントを持つ場合、それらは単一の大きなEndpointsリソースではなく、複数の小さなEndpointSliceに分割されます。
Kubernetes v1.17 [beta]
EndpoitSliceはベータ版の機能です。APIとEndpointSliceコントローラーはデフォルトで有効です。kube-proxyはデフォルトでEndpointSliceではなくEndpointsを使用します。
スケーラビリティと性能向上のため、kube-proxy上でEndpointSliceProxying
フィーチャーゲートを有効にできます。この変更はデータソースをEndpointSliceに移します、これはkube-proxyとKubernetes API間のトラフィックの量を削減します。
クラスター内でEndpointSliceを完全に有効にすると、各Endpointsリソースに対応するEndpointSliceリソースが表示されます。既存のEndpointsの機能をサポートすることに加えて、EndpointSliceはトポロジーなどの新しい情報を含みます。これらにより、クラスター内のネットワークエンドポイントのスケーラビリティと拡張性が大きく向上します。
このページでは、メモリーの 要求 と 制限 をコンテナに割り当てる方法について示します。コンテナは要求されたメモリーを確保することを保証しますが、その制限を超えるメモリーの使用は許可されません。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.クラスターの各ノードには、少なくとも300MiBのメモリーが必要になります。
このページのいくつかの手順では、クラスターにてmetrics-serverサービスを実行する必要があります。すでにmetrics-serverが動作している場合、これらの手順をスキップできます。
Minikubeを動作させている場合、以下のコマンドによりmetrics-serverを有効にできます:
minikube addons enable metrics-server
metrics-serverが実行されているか、もしくはリソースメトリクスAPI (metrics.k8s.io
) の別のプロバイダが実行されていることを確認するには、以下のコマンドを実行してください:
kubectl get apiservices
リソースメトリクスAPIが利用可能であれば、出力には metrics.k8s.io
への参照が含まれます。
NAME
v1beta1.metrics.k8s.io
この練習で作成するリソースがクラスター内で分離されるよう、namespaceを作成します。
kubectl create namespace mem-example
コンテナにメモリーの要求を指定するには、コンテナのリソースマニフェストにresources:requests
フィールドを追記します。メモリーの制限を指定するには、resources:limits
を追記します。
この練習では、一つのコンテナをもつPodを作成します。コンテナに100MiBのメモリー要求と200MiBのメモリー制限を与えます。Podの設定ファイルは次のようになります:
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
設定ファイルのargs
セクションでは、コンテナ起動時の引数を与えます。"--vm-bytes", "150M"
という引数では、コンテナに150MiBのメモリーを割り当てます。
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
Podのコンテナが起動していることを検証してください:
kubectl get pod memory-demo --namespace=mem-example
Podの詳細な情報を確認してください:
kubectl get pod memory-demo --output=yaml --namespace=mem-example
この出力では、Pod内の一つのコンテナに100MiBのメモリー要求と200MiBのメモリー制限があることを示しています。
...
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
kubectl top
を実行し、Podのメトリクスを取得してください:
kubectl top pod memory-demo --namespace=mem-example
この出力では、Podが約162,900,000バイト(約150MiB)のメモリーを使用していることを示しています。Podの100MiBの要求を超えていますが、200MiBの制限には収まっています。
NAME CPU(cores) MEMORY(bytes)
memory-demo <something> 162856960
Podを削除してください:
kubectl delete pod memory-demo --namespace=mem-example
ノードに利用可能なメモリーがある場合、コンテナはメモリー要求を超えることができます。しかしながら、メモリー制限を超えて使用することは許可されません。コンテナが制限を超えてメモリーを確保しようとした場合、そのコンテナは終了候補となります。コンテナが制限を超えてメモリーを消費し続ける場合、コンテナは終了されます。終了したコンテナを再起動できる場合、ほかのランタイムの失敗時と同様に、kubeletがコンテナを再起動させます。
この練習では、制限を超えてメモリーを確保しようとするPodを作成します。以下に50MiBのメモリー要求と100MiBのメモリー制限を与えたコンテナを持つ、Podの設定ファイルを示します:
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:
- name: memory-demo-2-ctr
image: polinux/stress
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
設定ファイルのargs
セクションでは、コンテナに250MiBのメモリーを割り当てており、これは100MiBの制限を十分に超えています。
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
Podの詳細な情報を確認してください:
kubectl get pod memory-demo-2 --namespace=mem-example
この時点で、コンテナは起動中か強制終了されているでしょう。コンテナが強制終了されるまで上記のコマンドをくり返し実行してください:
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s
コンテナステータスの詳細な情報を取得してください:
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
この出力では、コンテナがメモリー不足 (OOM) により強制終了されたことを示しています。
lastState:
terminated:
containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
exitCode: 137
finishedAt: 2017-06-20T20:52:19Z
reason: OOMKilled
startedAt: null
この練習のコンテナはkubeletによって再起動されます。次のコマンドを数回くり返し実行し、コンテナが強制終了と再起動を続けていることを確認してください:
kubectl get pod memory-demo-2 --namespace=mem-example
この出力では、コンテナが強制終了され、再起動され、再度強制終了および再起動が続いていることを示しています:
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 1/1 Running 2 40s
Podの履歴について詳細な情報を確認してください:
kubectl describe pod memory-demo-2 --namespace=mem-example
この出力では、コンテナの開始とその失敗が繰り返されていることを示しています:
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff Back-off restarting failed container
クラスターのノードの詳細な情報を確認してください:
kubectl describe nodes
この出力には、メモリー不足の状態のためコンテナが強制終了された記録が含まれます:
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child
Podを削除してください:
kubectl delete pod memory-demo-2 --namespace=mem-example
メモリー要求と制限はコンテナと関連づけられていますが、Podにメモリー要求と制限が与えられていると考えるとわかりやすいでしょう。Podのメモリー要求は、Pod内のすべてのコンテナのメモリー要求の合計となります。同様に、Podのメモリー制限は、Pod内のすべてのコンテナのメモリー制限の合計となります。
Podのスケジューリングは要求に基づいています。Podはノード上で動作するうえで、そのメモリー要求に対してノードに十分利用可能なメモリーがある場合のみスケジュールされます。
この練習では、クラスター内のノードのキャパシティを超える大きさのメモリー要求を与えたPodを作成します。以下に1000GiBのメモリー要求を与えた一つのコンテナを持つ、Podの設定ファイルを示します。これは、クラスター内のノードのキャパシティを超える可能性があります。
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:
- name: memory-demo-3-ctr
image: polinux/stress
resources:
limits:
memory: "1000Gi"
requests:
memory: "1000Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
Podの状態を確認してください:
kubectl get pod memory-demo-3 --namespace=mem-example
この出力では、Podのステータスが待機中であることを示しています。つまり、Podがどのノードに対しても実行するようスケジュールされておらず、いつまでも待機状態のままであることを表しています:
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s
イベントを含むPodの詳細な情報を確認してください:
kubectl describe pod memory-demo-3 --namespace=mem-example
この出力では、ノードのメモリー不足のためコンテナがスケジュールされないことを示しています:
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
メモリーリソースはバイト単位で示されます。メモリーをE、P、T、G、M、K、Ei、Pi、Ti、Gi、Mi、Kiという接尾辞とともに、整数型または固定小数点整数で表現できます。たとえば、以下はおおよそ同じ値を表します:
128974848, 129e6, 129M , 123Mi
Podを削除してください:
kubectl delete pod memory-demo-3 --namespace=mem-example
コンテナのメモリー制限を指定しない場合、次のいずれかの状態となります:
コンテナのメモリー使用量に上限がない状態となります。コンテナは実行中のノードで利用可能なすべてのメモリーを使用でき、その後OOM Killerが呼び出される可能性があります。さらに、OOM killの場合、リソース制限のないコンテナは強制終了される可能性が高くなります。
メモリー制限を与えられたnamespaceでコンテナを実行されると、コンテナにはデフォルトの制限値が自動的に指定されます。クラスターの管理者はLimitRangeによってメモリー制限のデフォルト値を指定できます。
クラスターで動作するコンテナにメモリー要求と制限を設定することで、クラスターのノードで利用可能なメモリーリソースを効率的に使用することができます。Podのメモリー要求を低く保つことで、Podがスケジュールされやすくなります。メモリー要求よりも大きい制限を与えることで、次の2つを実現できます:
namespaceを削除してください。これにより、今回のタスクで作成したすべてのPodが削除されます:
kubectl delete namespace mem-example
このページでは、CPUの request と limit をコンテナに割り当てる方法について示します。コンテナは設定された制限を超えてCPUを使用することはできません。システムにCPUの空き時間がある場合、コンテナには要求されたCPUを割り当てられます。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.タスク例を実行するには、クラスターに少なくとも利用可能な1 CPUが必要です。
このページのいくつかの手順では、クラスターにてmetrics-serverサービスを実行する必要があります。すでにmetrics-serverが動作している場合、これらの手順をスキップできます。
Minikubeを動作させている場合、以下のコマンドによりmetrics-serverを有効にできます:
minikube addons enable metrics-server
metrics-serverが実行されているか、もしくはリソースメトリクスAPI (metrics.k8s.io
) の別のプロバイダーが実行されていることを確認するには、以下のコマンドを実行してください:
kubectl get apiservices
リソースメトリクスAPIが利用可能であれば、出力には metrics.k8s.io
への参照が含まれます。
NAME
v1beta1.metrics.k8s.io
この練習で作成するリソースがクラスター内で分離されるよう、Namespaceを作成します。
kubectl create namespace cpu-example
コンテナにCPUの要求を指定するには、コンテナのリソースマニフェストにresources:requests
フィールドを追記します。CPUの制限を指定するには、resources:limits
を追記します。
この練習では、一つのコンテナをもつPodを作成します。コンテナに0.5 CPUの要求と1 CPUの制限を与えます。Podの設定ファイルは次のようになります:
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
args:
- -cpus
- "2"
設定ファイルのargs
セクションでは、コンテナ起動時の引数を与えます。-cpus "2"
という引数では、コンテナに2 CPUを割り当てます。
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit.yaml --namespace=cpu-example
Podのコンテナが起動していることを検証してください:
kubectl get pod cpu-demo --namespace=cpu-example
Podの詳細な情報を確認してください:
kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
この出力では、Pod内の一つのコンテナに500ミリCPUの要求と1 CPUの制限があることを示しています。
resources:
limits:
cpu: "1"
requests:
cpu: 500m
kubectl top
を実行し、Podのメトリクスを取得してください:
kubectl top pod cpu-demo --namespace=cpu-example
この出力では、Podが974ミリCPUを使用していることを示しています。Podの設定で指定した1 CPUの制限よりわずかに小さい値です。
NAME CPU(cores) MEMORY(bytes)
cpu-demo 974m <something>
-cpu "2"
を設定することで、コンテナが2 CPU利用しようとすることを思い出してください。しかしながら、コンテナは約1 CPUしか使用することができません。コンテナが制限よりも多くのCPUリソースを利用しようとしているため、コンテナのCPUの利用が抑制されています。
CPUリソースは CPU の単位で示されます。Kubernetesにおいて1つのCPUは次に等しくなります:
小数値も利用可能です。0.5 CPUを要求するコンテナには、1 CPUを要求するコンテナの半分のCPUが与えられます。mというミリを表す接尾辞も使用できます。たとえば、100m CPU、100 milliCPU、0.1 CPUはすべて同じです。1m以上の精度は指定できません。
CPUはつねに絶対量として要求され、決して相対量としては要求されません。0.1はシングルコア、デュアルコア、48コアCPUのマシンで同じ量となります。
Podを削除してください:
kubectl delete pod cpu-demo --namespace=cpu-example
CPU要求と制限はコンテナと関連づけられていますが、PodにCPU要求と制限が与えられていると考えるとわかりやすいでしょう。PodのCPU要求は、Pod内のすべてのコンテナのCPU要求の合計となります。同様に、PodのCPU制限は、Pod内のすべてのコンテナのCPU制限の合計となります。
Podのスケジューリングはリソースの要求量に基づいています。Podはノード上で動作するうえで、そのCPU要求に対してノードに十分利用可能なCPUリソースがある場合のみスケジュールされます。
この練習では、クラスター内のノードのキャパシティを超える大きさのCPU要求を与えたPodを作成します。以下に100 CPUの要求を与えた一つのコンテナを持つ、Podの設定ファイルを示します。これは、クラスター内のノードのキャパシティを超える可能性があります。
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo-2
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr-2
image: vish/stress
resources:
limits:
cpu: "100"
requests:
cpu: "100"
args:
- -cpus
- "2"
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml --namespace=cpu-example
Podの状態を確認してください:
kubectl get pod cpu-demo-2 --namespace=cpu-example
この出力では、Podのステータスが待機中であることを示しています。つまり、Podがどのノードに対しても実行するようスケジュールされておらず、いつまでも待機状態のままであることを表しています:
NAME READY STATUS RESTARTS AGE
cpu-demo-2 0/1 Pending 0 7m
イベントを含むPodの詳細な情報を確認してください:
kubectl describe pod cpu-demo-2 --namespace=cpu-example
この出力では、ノードのCPU不足のためコンテナがスケジュールされないことを示しています:
Events:
Reason Message
------ -------
FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3).
Podを削除してください:
kubectl delete pod cpu-demo-2 --namespace=cpu-example
コンテナのCPU制限を指定しない場合、次のいずれかの状態となります:
コンテナのCPUリソースの使用量に上限がない状態となります。コンテナは実行中のノードで利用可能なすべてのCPUを使用できます。
CPU制限を与えられたnamespaceでコンテナを実行されると、コンテナにはデフォルトの制限値が自動的に指定されます。クラスターの管理者はLimitRangeによってCPU制限のデフォルト値を指定できます。
クラスターで動作するコンテナにCPU要求と制限を設定することで、クラスターのノードで利用可能なCPUリソースを効率的に使用することができます。PodのCPU要求を低く保つことで、Podがスケジュールされやすくなります。CPU要求よりも大きい制限を与えることで、次の2つを実現できます:
namespaceを削除してください:
kubectl delete namespace cpu-example
Kubernetes v1.18 [stable]
このページでは、Windowsノード上で動作するPodとコンテナに対するグループ管理サービスアカウント(GMSA)の設定方法を示します。 グループ管理サービスアカウントは特別な種類のActive Directoryアカウントで、パスワードの自動管理、簡略化されたサービスプリンシパル名(SPN)の管理、および管理を他の管理者に委任する機能を複数のサーバーに提供します。
Kubernetesでは、GMSA資格情報仕様は、Kubernetesクラスター全体をスコープとするカスタムリソースとして設定されます。 WindowsのPodおよびPod内の個々のコンテナは、他のWindowsサービスとやり取りする際に、ドメインベースの機能(例えばKerberos認証)に対してGMSAを使用するように設定できます。
Kubernetesクラスターが必要で、kubectl
コマンドラインツールがクラスターと通信できるように設定されている必要があります。
クラスターにはWindowsワーカーノードを持つことが求められます。
このセクションでは、各クラスターに対して一度だけ実施する必要がある一連の初期ステップについて説明します:
カスタムリソースタイプGMSACredentialSpec
を定義するために、GMSA資格情報仕様リソースに対するCustomResourceDefinition(CRD)をクラスター上で設定する必要があります。
GMSA CRDのYAMLをダウンロードし、gmsa-crd.yamlとして保存します。
次に、kubectl apply -f gmsa-crd.yaml
を実行してCRDをインストールします。
Podまたはコンテナレベルで参照するGMSA資格情報仕様を追加および検証するために、Kubernetesクラスター上で2つのWebhookを設定する必要があります:
Mutating Webhookは、(Podの仕様から名前で指定された)GMSAへの参照を、JSON形式の完全な資格情報仕様としてPodのspecの中へ展開します。
Validating Webhookは、すべてのGMSAへの参照に対して、Podサービスアカウントによる利用が認可されているか確認します。
上記Webhookと関連するオブジェクトをインストールするためには、次の手順が必要です:
証明書と鍵のペアを作成します(Webhookコンテナがクラスターと通信できるようにするために使用されます)
上記の証明書を含むSecretをインストールします。
コアとなるWebhookロジックのためのDeploymentを作成します。
Deploymentを参照するValidating WebhookとMutating Webhookの設定を作成します。
上で述べたGMSA Webhookと関連するオブジェクトを展開、構成するためのスクリプトがあります。
スクリプトは、--dry-run=server
オプションをつけることで、クラスターに対して行われる変更内容をレビューすることができます。
Webhookと関連するオプジェクトを(適切なパラメーターを渡すことで)手動で展開するためのYAMLテンプレートもあります。
Windows GMSAのドキュメントに記載されている通り、Kubernetes内のPodがGMSAを使用するために設定できるようにする前に、Active Directory内に目的のGMSAを展開する必要があります。 Windows GMSAのドキュメントに記載されている通り、(Kubernetesクラスターの一部である)Windowsワーカーノードは、目的のGMSAに関連づけられたシークレット資格情報にアクセスできるように、Active Directory内で設定されている必要があります。
(前述の通り)GMSACredentialSpec CRDをインストールすると、GMSA資格情報仕様を含むカスタムリソースを設定できます。 GMSA資格情報仕様には、シークレットや機密データは含まれません。 それは、コンテナランタイムが目的のコンテナのGMSAをWindowsに対して記述するために使用できる情報です。 GMSA資格情報仕様は、PowerShellスクリプトのユーティリティを使用して、YAMLフォーマットで生成することができます。
以下は、GMSA資格情報仕様をJSON形式で手動で生成し、その後それをYAMLに変換する手順です:
CredentialSpecモジュールをインポートします: ipmo CredentialSpec.psm1
New-CredentialSpec
を使用してJSONフォーマットの資格情報仕様を作成します。
WebApp1という名前のGMSA資格情報仕様を作成するには、New-CredentialSpec -Name WebApp1 -AccountName WebApp1 -Domain $(Get-ADDomain -Current LocalComputer)
を実行します
Get-CredentialSpec
を使用して、JSONファイルのパスを表示します。
credspecファイルをJSON形式からYAML形式に変換し、Kubernetesで設定可能なGMSACredentialSpecカスタムリソースにするために、必要なヘッダーフィールドであるapiVersion
、kind
、metadata
、credspec
を記述します。
次のYAML設定は、gmsa-WebApp1
という名前のGMSA資格情報仕様を記述しています:
apiVersion: windows.k8s.io/v1
kind: GMSACredentialSpec
metadata:
name: gmsa-WebApp1 # これは任意の名前で構いませんが、参照時に使用されます
credspec:
ActiveDirectoryConfig:
GroupManagedServiceAccounts:
- Name: WebApp1 # GMSAアカウントのユーザー名
Scope: CONTOSO # NETBIOSドメイン名
- Name: WebApp1 # GMSAアカウントのユーザー名
Scope: contoso.com # DNSドメイン名
CmsPlugins:
- ActiveDirectory
DomainJoinConfig:
DnsName: contoso.com # DNSドメイン名
DnsTreeName: contoso.com # DNSルートドメイン名
Guid: 244818ae-87ac-4fcd-92ec-e79e5252348a # GUID
MachineAccountName: WebApp1 # GMSAアカウントのユーザー名
NetBiosName: CONTOSO # NETBIOSドメイン名
Sid: S-1-5-21-2126449477-2524075714-3094792973 # GMSAのSID
上記の資格情報仕様リソースはgmsa-Webapp1-credspec.yaml
として保存され、次のコマンドを使用してクラスターに適用されます: kubectl apply -f gmsa-Webapp1-credspec.yml
各GMSA資格情報仕様リソースに対して、クラスターロールを定義する必要があります。
これは特定のGMSAリソース上のuse
verbを、通常はサービスアカウントであるsubjectに対して認可します。
次の例は、前述のgmsa-WebApp1
資格情報仕様の利用を認可するクラスターロールを示しています。
ファイルをgmsa-webapp1-role.yamlとして保存し、kubectl apply -f gmsa-webapp1-role.yaml
を使用して適用します。
# credspecを読むためのロールを作成
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: webapp1-role
rules:
- apiGroups: ["windows.k8s.io"]
resources: ["gmsacredentialspecs"]
verbs: ["use"]
resourceNames: ["gmsa-WebApp1"]
(Podに対して設定される)サービスアカウントを、上で作成したクラスターロールに結びつける必要があります。
これによって、要求されたGMSA資格情報仕様のリソースの利用をサービスアカウントに対して認可できます。
以下は、上で作成した資格情報仕様リソースgmsa-WebApp1
を使うために、既定のサービスアカウントに対してクラスターロールwebapp1-role
を割り当てる方法を示しています。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: allow-default-svc-account-read-on-gmsa-WebApp1
namespace: default
subjects:
- kind: ServiceAccount
name: default
namespace: default
roleRef:
kind: ClusterRole
name: webapp1-role
apiGroup: rbac.authorization.k8s.io
PodのspecのフィールドsecurityContext.windowsOptions.gmsaCredentialSpecName
は、要求されたGMSA資格情報仕様のカスタムリソースに対する参照を、Podのspec内で指定するために使用されます。
これは、Podのspec内の全てのコンテナに対して、指定されたGMSAを使用するように設定します。
gmsa-WebApp1
を参照するために追加された注釈を持つPodのspecのサンプルです:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-webapp1
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
nodeSelector:
kubernetes.io/os: windows
Podのspec内の個々のコンテナも、コンテナ毎のsecurityContext.windowsOptions.gmsaCredentialSpecName
フィールドを使用することで、要求されたGMSA credspecを指定することができます。
設定例:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: with-creds
name: with-creds
namespace: default
spec:
replicas: 1
selector:
matchLabels:
run: with-creds
template:
metadata:
labels:
run: with-creds
spec:
containers:
- image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
imagePullPolicy: Always
name: iis
securityContext:
windowsOptions:
gmsaCredentialSpecName: gmsa-Webapp1
nodeSelector:
kubernetes.io/os: windows
(上記のような)GMSAフィールドが入力されたPod specがクラスターに適用されると、次の一連のイベントが発生します:
Mutating WebhookがGMSA資格情報仕様リソースへの全ての参照を解決し、GMSA資格情報仕様の内容を展開します。
Validating Webhookは、Podに関連付けられたサービスアカウントが、指定されたGMSA資格情報仕様上のuse
verbに対して認可されていることを保証します。
コンテナランタイムは、指定されたGMSA資格情報仕様で各Windowsコンテナを設定します。 それによってコンテナはGMSAのIDがActive Directory内にあることを仮定でき、そのIDを使用してドメイン内のサービスにアクセスできます。
PodからSMB共有へのホスト名やFQDNを使用した接続で問題が発生した際に、IPv4アドレスではSMB共有にアクセスすることはできる場合には、次のレジストリキーがWindowsノード上で設定されているか確認してください。
reg add "HKLM\SYSTEM\CurrentControlSet\Services\hns\State" /v EnableCompartmentNamespace /t REG_DWORD /d 1
その後、動作の変更を反映させるために、実行中のPodを再作成する必要があります。 このレジストリキーがどのように使用されるかについてのより詳細な情報は、こちらを参照してください。
自分の環境でGMSAがうまく動作しない時に実行できるトラブルシューティングステップがあります。
まず、credspecがPodに渡されたことを確認します。
そのためには、Podのひとつにexec
で入り、nltest.exe /parentdomain
コマンドの出力をチェックする必要があります。
以下の例では、Podはcredspecを正しく取得できませんでした:
kubectl exec -it iis-auth-7776966999-n5nzr powershell.exe
nltest.exe /parentdomain
の結果は次のようなエラーになります:
Getting parent domain failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
Podが正しくcredspecを取得したら、次にドメインと正しく通信できることを確認します。 まずはPodの中から、ドメインのルートを見つけるために、手短にnslookupを実行します。
これから3つのことがわかります:
DNSと通信のテストをパスしたら、次にPodがドメインとセキュアチャネル通信を構築することができるか確認する必要があります。
そのためには、再びexec
を使用してPodの中に入り、nltest.exe /query
コマンドを実行します。
nltest.exe /query
結果は次のように出力されます:
I_NetLogonControl failed: Status = 1722 0x6ba RPC_S_SERVER_UNAVAILABLE
これは、Podがなんらかの理由で、credspec内で指定されたアカウントを使用してドメインにログオンできなかったことを示しています。 次のコマンドを実行してセキュアチャネルを修復してみてください:
nltest /sc_reset:domain.example
コマンドが成功したら、このような出力を確認することができます:
Flags: 30 HAS_IP HAS_TIMESERV
Trusted DC Name \\dc10.domain.example
Trusted DC Connection Status Status = 0 0x0 NERR_Success
The command completed successfully
もし上記によってエラーが解消された場合は、次のライフサイクルフックをPodのspecに追加することで、手順を自動化できます。 エラーが解消されなかった場合は、credspecをもう一度調べ、正しく完全であることを確認する必要があります。
image: registry.domain.example/iis-auth:1809v1
lifecycle:
postStart:
exec:
command: ["powershell.exe","-command","do { Restart-Service -Name netlogon } while ( $($Result = (nltest.exe /query); if ($Result -like '*0x0 NERR_Success*') {return $true} else {return $false}) -eq $false)"]
imagePullPolicy: IfNotPresent
Podのspecに上記のlifecycle
セクションを追加すると、nltest.exe /query
コマンドがエラーとならずに終了するまでnetlogon
サービスを再起動するために、Podは一連のコマンドを実行します。
Kubernetes v1.27 [alpha]
(enabled by default: false)このページはQuality of Serviceに馴染みのある読者を前提としています。
このページでは、稼働中のPodやコンテナを再起動することなく、コンテナに割り当てられるCPUやメモリ容量を変更(リサイズ)するための方法を示します。
Kubernetesノードは、PodのContainerに指定したrequests
に基づいてPodにリソースを割り当て、limits
に基づいてPodのリソース使用量を制限します。
稼働中のPodのリソース割当を変更するには、 InPlacePodVerticalScaling
フィーチャーゲートを有効化する必要があります。
代替手法としては、Podを削除した上で、異なるリソース要求を有するPodをワークロードコントローラー に作成させることもできます。
稼働中のPodのリソースを変更するために
requests
と limits
はCPUおよびメモリリソースに対して 可変 なものとなっています。containerStatuses
における allocatedResources
フィールドは、PodのContainerに割り当てられたリソースを反映します。containerStatuses
における resources
フィールドは、稼働中Containerに設定済みの実際のリソース要求(requests
)とリソース制限(limits
)を反映しており、これらの値はコンテナランタイムが通知したものです。resize
フィールドは直前の適用待ちのリサイズ要求を示します。
このフィールドの値には次のようなものがあります。Proposed
: リサイズ要求の受理を表し、リクエストが検証済みかつ記録済み
であることを示します。InProgress
: リサイズ要求がノードによって受理され、Podのコンテナに対する
適用が進行中であることを示します。Deferred
: リサイズ要求が現時点では通っていないことを示します。
他のPodが除去されてノードの資源が開放されたら、リサイズが承認されるかもしれません。Infeasible
: ノードがリサイズ要求に対応できないことを示すシグナルです。
Podに対してノードが割り当て可能なリソースの最大値を上回るリサイズ要求がある時に
発生する可能性があります。Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
作業するKubernetesサーバーは次のバージョン以降のものである必要があります: 1.27. バージョンを確認するには次のコマンドを実行してください:kubectl version
.クラスターのコントロールプレーンを含む全ノードでInPlacePodVerticalScaling
フィーチャーゲートが有効化されている必要があります。
リサイズポリシーはPodにおけるコンテナのCPUやメモリリソースを取り扱うためのきめ細かい制御を可能にします。 例えば、アプリケーションを再起動せずにコンテナのCPUリソースのリサイズを行える場合でも、メモリのリサイズについてはアプリケーションとコンテナの再起動が必要となる場合があります。
これを実現するために、ユーザーはContainerの仕様に resizePolicy
を指定できるようになっています。
以下の再起動ポリシーをCPUやメモリのリサイズの際に指定できます。
NotRequired
: 稼働中のコンテナリソースをリサイズします。RestartContainer
: コンテナを再起動させ、再起動時に新しいリソースを適用します。resizePolicy[*].restartPolicy
が指定されない場合のデフォルトは、NotRequired
です。
restartPolicy
がNever
である場合、Podの全コンテナの再起動ポリシーがNotRequired
である必要があります。以下のPodの例は、ContainerのCPUのリサイズは再起動なしで実施させ、メモリのリサイズにはコンテナの再起動を要求するものです。
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-5
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr-5
image: nginx
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: RestartContainer
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
リソース要求やリソース制限をPodのコンテナに指定することで、保証(Guaranteed)ないしは バースト可能(Burstable)なQuality of ServiceクラスのPodを作成することができます。
次のような単一のコンテナを含むPodのマニフェストを考えてみましょう。
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-5
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr-5
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Podをqos-example
Namespace に作成します。
kubectl create namespace qos-example
kubectl create -f https://k8s.io/examples/pods/qos/qos-pod-5.yaml
このPodは保証QoSクラスに区分され、700mのCPU、200Miのメモリを要求します。
Podの詳細な情報を見てみましょう。
kubectl get pod qos-demo-5 --output=yaml --namespace=qos-example
resizePolicy[*].restartPolicy
の値がデフォルトのNotRequired
になっていることに気づいたでしょうか。
これはCPUとメモリがコンテナ稼働中にリサイズできることを示しています。
spec:
containers:
...
resizePolicy:
- resourceName: cpu
restartPolicy: NotRequired
- resourceName: memory
restartPolicy: NotRequired
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
containerStatuses:
...
name: qos-demo-ctr-5
ready: true
...
allocatedResources:
cpu: 700m
memory: 200Mi
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
restartCount: 0
started: true
...
qosClass: Guaranteed
要求CPUを0.8CPUに増やしてみます。 これは手動でも指定できますし、VerticalPodAutoscaler(VPA)などを用いて自動的に検出/適用することもできます。
PodのContainerのCPU要求とCPU制限をいずれも800m
に指定するパッチを当ててみます。
kubectl -n qos-example patch pod qos-demo-5 --patch '{"spec":{"containers":[{"name":"qos-demo-ctr-5", "resources":{"requests":{"cpu":"800m"}, "limits":{"cpu":"800m"}}}]}}'
Podへのパッチが当たったら、Podの詳細情報を参照してみましょう。
kubectl get pod qos-demo-5 --output=yaml --namespace=qos-example
以下のPod仕様は更新済みのCPU要求とCPU制限を反映しています。
spec:
containers:
...
resources:
limits:
cpu: 800m
memory: 200Mi
requests:
cpu: 800m
memory: 200Mi
...
containerStatuses:
...
allocatedResources:
cpu: 800m
memory: 200Mi
resources:
limits:
cpu: 800m
memory: 200Mi
requests:
cpu: 800m
memory: 200Mi
restartCount: 0
started: true
期待する新しいCPU要求を反映する形で allocatedResources
の値が更新されていることを確認しておきましょう。
これはノードがCPUリソースの追加要求に対応できたことを示しています。
Containerの状態においてはCPUリソースの値が更新されており、新しいCPUリソースが適用されたことを示しています。
ContainerのrestartCount
は変化しておらず、コンテナのCPUリソースがコンテナの再起動なしで変更されたことを示しています。
名前空間を削除しましょう。
kubectl delete namespace qos-example
このページでは、特定のQuality of Service (QoS)クラスをPodに割り当てるための設定方法を示します。Kubernetesは、Podのスケジューリングおよび退役を決定するためにQoSクラスを用います。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.KubernetesはPodの作成時に次のいずれかのQoSクラスをPodに割り当てます:
この演習で作成するリソースがクラスター内で分離されるよう、namespaceを作成します。
kubectl create namespace qos-example
PodにGuaranteedのQoSクラスを与えるには、以下が必要になります:
以下に1つのコンテナをもつPodの設定ファイルを示します。コンテナには200MiBのメモリー制限とリクエストを与え、700ミリCPUの制限と要求を与えます。
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=qos-example
Podの詳細な情報を確認してください:
kubectl get pod qos-demo --namespace=qos-example --output=yaml
この出力では、KubernetesがPodにGuaranteed QoSクラスを与えたことを示しています。Podのコンテナにメモリー制限と一致するメモリー要求があり、CPU制限と一致するCPU要求があることも確認できます。
spec:
containers:
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
qosClass: Guaranteed
Podを削除してください:
kubectl delete pod qos-demo --namespace=qos-example
次のような場合に、Burstable QoSクラスがPodに与えられます:
以下に1つのコンテナをもつPodの設定ファイルを示します。コンテナには200MiBのメモリー制限と100MiBのメモリー要求を与えます。
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-2.yaml --namespace=qos-example
Podの詳細な情報を確認してください:
kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml
この出力では、KubernetesがPodにBurstable QoSクラスを与えたことを示しています。
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
qosClass: Burstable
Podを削除してください:
kubectl delete pod qos-demo-2 --namespace=qos-example
PodにBestEffort QoSクラスを与えるには、Pod内のコンテナにはメモリーやCPUの制限や要求を指定してはなりません。
以下に1つのコンテナをもつPodの設定ファイルを示します。コンテナにはメモリーやCPUの制限や要求がありません:
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-3.yaml --namespace=qos-example
Podの詳細な情報を確認してください:
kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml
この出力では、KubernetesがPodにBestEffort QoSクラスを与えたことを示しています。
spec:
containers:
...
resources: {}
...
status:
qosClass: BestEffort
Podを削除してください:
kubectl delete pod qos-demo-3 --namespace=qos-example
以下に2つのコンテナをもつPodの設定ファイルを示します。一方のコンテナは200MiBのメモリー要求を指定し、もう一方のコンテナには要求や制限を指定しません。
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-4
namespace: qos-example
spec:
containers:
- name: qos-demo-4-ctr-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-4-ctr-2
image: redis
このPodがBurstable QoSクラスの基準を満たしていることに注目してください。つまり、Guaranteed QoSクラスの基準に満たしておらず、一方のコンテナにはメモリー要求を与えられています。
Podを作成してください:
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-4.yaml --namespace=qos-example
Podの詳細な情報を確認してください:
kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml
この出力では、KubernetesがPodにBurstable QoSクラスを与えたことを示しています:
spec:
containers:
...
name: qos-demo-4-ctr-1
resources:
requests:
memory: 200Mi
...
name: qos-demo-4-ctr-2
resources: {}
...
status:
qosClass: Burstable
Podを削除してください:
kubectl delete pod qos-demo-4 --namespace=qos-example
namespaceを削除してください:
kubectl delete namespace qos-example
Kubernetes v1.32 [stable]
このページでは、拡張リソースをコンテナに割り当てる方法について説明します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.この練習を始める前に、Nodeに拡張リソースをアドバタイズするの練習を行ってください。これにより、Nodeの1つがドングルリソースをアドバタイズするように設定されます。
拡張リソースをリクエストするには、コンテナのマニフェストにresources:requests
フィールドを含めます。拡張リソースは、*.kubernetes.io/
以外の任意のドメインで完全修飾されます。有効な拡張リソース名は、example.com/foo
という形式になります。ここで、example.com
はあなたの組織のドメインで、foo
は記述的なリソース名で置き換えます。
1つのコンテナからなるPodの構成ファイルを示します。
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo
spec:
containers:
- name: extended-resource-demo-ctr
image: nginx
resources:
requests:
example.com/dongle: 3
limits:
example.com/dongle: 3
構成ファイルでは、コンテナが3つのdongleをリクエストしていることがわかります。
次のコマンドでPodを作成します。
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod.yaml
Podが起動したことを確認します。
kubectl get pod extended-resource-demo
Podの説明を表示します。
kubectl describe pod extended-resource-demo
dongleのリクエストが表示されます。
Limits:
example.com/dongle: 3
Requests:
example.com/dongle: 3
以下に、1つのコンテナを持つPodの構成ファイルを示します。コンテナは2つのdongleをリクエストします。
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo-2
spec:
containers:
- name: extended-resource-demo-2-ctr
image: nginx
resources:
requests:
example.com/dongle: 2
limits:
example.com/dongle: 2
Kubernetesは、2つのdongleのリクエストを満たすことができません。1つ目のPodが、利用可能な4つのdongleのうち3つを使用してしまっているためです。
Podを作成してみます。
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod-2.yaml
Podの説明を表示します。
kubectl describe pod extended-resource-demo-2
出力にはPodがスケジュールできないことが示されます。2つのdongleが利用できるNodeが存在しないためです。
Conditions:
Type Status
PodScheduled False
...
Events:
...
... Warning FailedScheduling pod (extended-resource-demo-2) failed to fit in any node
fit failure summary on nodes : Insufficient example.com/dongle (1)
Podのステータスを表示します。
kubectl get pod extended-resource-demo-2
出力には、Podは作成されたものの、Nodeにスケジュールされなかったことが示されています。PodはPending状態になっています。
NAME READY STATUS RESTARTS AGE
extended-resource-demo-2 0/1 Pending 0 6m
この練習で作成したPodを削除します。
kubectl delete pod extended-resource-demo
kubectl delete pod extended-resource-demo-2
このページでは、ストレージにボリュームを使用するPodを構成する方法を示します。
コンテナのファイルシステムは、コンテナが存在する間のみ存続します。 そのため、コンテナが終了して再起動すると、ファイルシステムの変更は失われます。 コンテナに依存しない、より一貫したストレージを実現するには、ボリュームを使用できます。 これは、キーバリューストア(Redisなど)やデータベースなどのステートフルアプリケーションにとって特に重要です。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.この演習では、1つのコンテナを実行するPodを作成します。 今回作成するPodには、コンテナが終了して再起動した場合でもPodの寿命が続くemptyDirタイプのボリュームがあります。 これがPodの設定ファイルです:
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
Podを作成します:
kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml
Podのコンテナが実行されていることを確認し、Podへの変更を監視します:
kubectl get pod redis --watch
出力は次のようになります:
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
別のターミナルで、実行中のコンテナへのシェルを取得します:
kubectl exec -it redis -- /bin/bash
シェルで、/data/redis
に移動し、ファイルを作成します:
root@redis:/data# cd /data/redis/
root@redis:/data/redis# echo Hello > test-file
シェルで、実行中のプロセスを一覧表示します:
root@redis:/data/redis# apt-get update
root@redis:/data/redis# apt-get install procps
root@redis:/data/redis# ps aux
出力はこのようになります:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
redis 1 0.1 0.1 33308 3828 ? Ssl 00:46 0:00 redis-server *:6379
root 12 0.0 0.0 20228 3020 ? Ss 00:47 0:00 /bin/bash
root 15 0.0 0.0 17500 2072 ? R+ 00:48 0:00 ps aux
シェルで、Redisプロセスを終了します:
root@redis:/data/redis# kill <pid>
ここで<pid>
はRedisプロセスID(PID)です。
元の端末で、Redis Podへの変更を監視します。最終的には、このようなものが表示されます:
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
redis 0/1 Completed 0 6m
redis 1/1 Running 1 6m
この時点で、コンテナは終了して再起動しました。
これは、Redis PodのrestartPolicyがAlways
であるためです。
再起動されたコンテナへのシェルを取得します:
kubectl exec -it redis -- /bin/bash
シェルで/data/redis
に移動し、test-file
がまだ存在することを確認します。
root@redis:/data/redis# cd /data/redis/
root@redis:/data/redis# ls
test-file
この演習用に作成したPodを削除します:
kubectl delete pod redis
このページでは、projected
(投影)ボリュームを使用して、既存の複数のボリュームソースを同一ディレクトリ内にマウントする方法を説明します。
現在、secret
、configMap
、downwardAPI
およびserviceAccountToken
ボリュームを投影できます。
serviceAccountToken
はボリュームタイプではありません。Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.この課題では、ローカルファイルからユーザーネームおよびパスワードのSecretを作成します。
次に、単一のコンテナを実行するPodを作成し、projected
ボリュームを使用してそれぞれのSecretを同じ共有ディレクトリにマウントします。
以下にPodの設定ファイルを示します:
apiVersion: v1
kind: Pod
metadata:
name: test-projected-volume
spec:
containers:
- name: test-projected-volume
image: busybox
args:
- sleep
- "86400"
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: user
- secret:
name: pass
Secretを作成します:
# ユーザーネームおよびパスワードを含むファイルを作成します:
echo -n "admin" > ./username.txt
echo -n "1f2d1e2e67df" > ./password.txt
# これらのファイルからSecretを作成します:
kubectl create secret generic user --from-file=./username.txt
kubectl create secret generic pass --from-file=./password.txt
Podを作成します:
kubectl apply -f https://k8s.io/examples/pods/storage/projected.yaml
Pod内のコンテナが実行されていることを確認するため、Podの変更を監視します:
kubectl get --watch pod test-projected-volume
出力は次のようになります:
NAME READY STATUS RESTARTS AGE
test-projected-volume 1/1 Running 0 14s
別の端末にて、実行中のコンテナへのシェルを取得します:
kubectl exec -it test-projected-volume -- /bin/sh
シェル内にて、投影されたソースを含むprojected-volume
ディレクトリが存在することを確認します:
ls /projected-volume/
PodおよびSecretを削除します:
kubectl delete pod test-projected-volume
kubectl delete secret user pass
projected
ボリュームについてさらに学ぶセキュリティコンテキストはPod・コンテナの特権やアクセスコントロールの設定を定義します。 セキュリティコンテキストの設定には以下のものが含まれますが、これらに限定はされません。
任意アクセス制御: user ID (UID) と group ID (GID)に基づいて、ファイルなどのオブジェクトに対する許可を行います。
Security Enhanced Linux (SELinux): オブジェクトにセキュリティラベルを付与します。
特権または非特権として実行します。
Linux Capabilities: rootユーザーのすべての特権ではなく、一部の特権をプロセスに与えます。
AppArmor: プロファイルを用いて、個々のプログラムのcapabilityを制限します。
Seccomp: プロセスのシステムコールを限定します。
allowPrivilegeEscalation
: あるプロセスが親プロセスよりも多くの特権を得ることができるかを制御します。 この真偽値は、コンテナプロセスに
no_new_privs
フラグが設定されるかどうかを直接制御します。
コンテナが以下の場合、allowPrivilegeEscalation
は常にtrueになります。
CAP_SYS_ADMIN
を持っているreadOnlyRootFilesystem
: コンテナのルートファイルシステムが読み取り専用でマウントされます。
上記の項目は全てのセキュリティコンテキスト設定を記載しているわけではありません。 より広範囲なリストはSecurityContextを確認してください。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.Podにセキュリティ設定を行うには、Podの設定にsecurityContext
フィールドを追加してください。
securityContext
フィールドはPodSecurityContextオブジェクトが入ります。
Podに設定したセキュリティ設定はPod内の全てのコンテナに適用されます。こちらはsecurityContext
とemptyDir
ボリュームを持ったPodの設定ファイルです。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
supplementalGroups: [4000]
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: busybox:1.28
command: [ "sh", "-c", "sleep 1h" ]
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
securityContext:
allowPrivilegeEscalation: false
設定ファイルの中のrunAsUser
フィールドは、Pod内のコンテナに対して全てのプロセスをユーザーID 1000で実行するように指定します。
runAsGroup
フィールドはPod内のコンテナに対して全てのプロセスをプライマリーグループID 3000で実行するように指定します。このフィールドが省略されたときは、コンテナのプライマリーグループIDはroot(0)になります。runAsGroup
が指定されている場合、作成されたファイルもユーザー1000とグループ3000の所有物になります。
またfsGroup
も指定されているため、全てのコンテナ内のプロセスは補助グループID 2000にも含まれます。/data/demo
ボリュームとこのボリュームに作成されたファイルはグループID 2000になります。加えて、supplementalGroups
フィールドが指定されている場合、全てのコンテナ内のプロセスは指定されている補助グループIDにも含まれます。もしこのフィールドが指定されていない場合、空を意味します。
Podを作成してみましょう。
kubectl apply -f https://k8s.io/examples/pods/security/security-context.yaml
Podのコンテナが実行されていることを確認します。
kubectl get pod security-context-demo
実行中のコンテナでshellを取ります。
kubectl exec -it security-context-demo -- sh
shellで、実行中のプロセスの一覧を確認します。
ps
runAsUser
で指定した値である、ユーザー1000でプロセスが実行されていることが確認できます。
PID USER TIME COMMAND
1 1000 0:00 sleep 1h
6 1000 0:00 sh
...
shellで/data
に入り、ディレクトリの一覧を確認します。
cd /data
ls -l
fsGroup
で指定した値であるグループID 2000で/data/demo
ディレクトリが作成されていることが確認できます。
drwxrwsrwx 2 root 2000 4096 Jun 6 20:08 demo
shellで/data/demo
に入り、ファイルを作成します。
cd demo
echo hello > testfile
/data/demo
ディレクトリでファイルの一覧を確認します。
ls -l
fsGroup
で指定した値であるグループID 2000でtestfile
が作成されていることが確認できます。
-rw-r--r-- 1 1000 2000 6 Jun 6 20:08 testfile
以下のコマンドを実行してください。
id
出力はこのようになります。
uid=1000 gid=3000 groups=2000,3000,4000
出力からrunAsGroup
フィールドと同じくgid
が3000になっていることが確認できるでしょう。runAsGroup
が省略された場合、gid
は0(root)になり、そのプロセスはグループroot(0)とグループroot(0)に必要なグループパーミッションを持つグループが所有しているファイルを操作することができるようになります。また、groups
の出力に、gid
に加えて、fsGroups
、supplementalGroups
フィールドで指定したグループIDも含まれていることも確認できるでしょう。
shellから抜けましょう。
exit
/etc/group
から暗黙的にマージされるグループ情報Kubernetesは、デフォルトでは、Podで定義された情報に加えて、コンテナイメージ内の/etc/group
のグループ情報をマージします。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
containers:
- name: sec-ctx-demo
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
このPodはsecurity contextでrunAsUser
、runAsGroup
、supplementalGroups
フィールドが指定されています。しかし、コンテナ内のプロセスには、コンテナイメージ内の/etc/group
に定義されたグループIDが、補助グループとして付与されていることが確認できるでしょう。
Podを作成してみましょう。
kubectl apply -f https://k8s.io/examples/pods/security/security-context-5.yaml
Podのコンテナが実行されていることを確認します。
kubectl get pod security-context-demo
実行中のコンテナでshellを取ります。
kubectl exec -it security-context-demo -- sh
プロセスのユーザー、グループ情報を確認します。
$ id
出力はこのようになります。
uid=1000 gid=3000 groups=3000,4000,50000
groups
にグループID50000
が含まれていることが確認できるでしょう。これは、ユーザー(uid=1000
)がコンテナイメージで定義されており、コンテナイメージ内の/etc/group
でグループ(gid=50000
)に所属しているためです。
コンテナイメージの/etc/group
の内容を確認してみましょう。
$ cat /etc/group
ユーザー1000
がグループ50000
に所属していることが確認できるでしょう。
...
user-defined-in-image:x:1000:
group-defined-in-image:x:50000:user-defined-in-image
shellから抜けましょう。
exit
Kubernetes v1.31 [alpha]
(enabled by default: false)この機能はkubeletとkube-apiseverにSupplementalGroupsPolicy
フィーチャーゲートを設定し、Podの.spec.securityContext.supplementalGroupsPolicy
フィールドを指定することで利用できます。
supplementalGroupsPolicy
フィールドは、Pod内のコンテナプロセスに付与される補助グループを、どのように決定するかを定義します。有効な値は次の2つです。
Merge
: /etc/group
で定義されている、コンテナのプライマリユーザーが所属するグループをマージします。指定されていない場合、このポリシーがデフォルトです。
Strict
: fsGroup
、supplementalGroups
、runAsGroup
フィールドで指定されたグループのみ補助グループに指定されます。つまり、/etc/group
で定義された、コンテナのプライマリユーザーのグループ情報はマージされません。
この機能が有効な場合、.status.containerStatuses[].user.linux
フィールドで、コンテナの最初のプロセスに付与されたユーザー、グループ情報が確認出来ます。暗黙的なグループIDが付与されているかどうかを確認するのに便利でしょう。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
supplementalGroups: [4000]
supplementalGroupsPolicy: Strict
containers:
- name: sec-ctx-demo
image: registry.k8s.io/e2e-test-images/agnhost:2.45
command: [ "sh", "-c", "sleep 1h" ]
securityContext:
allowPrivilegeEscalation: false
このPodマニフェストはsupplementalGroupsPolicy=Strict
を指定しています。/etc/group
に定義されているグループ情報が、コンテナ内のプロセスの補助グループにマージされないことが確認できるでしょう。
Podを作成してみましょう。
kubectl apply -f https://k8s.io/examples/pods/security/security-context-6.yaml
Podのコンテナが実行されていることを確認します。
kubectl get pod security-context-demo
プロセスのユーザー、グループ情報を確認します。
kubectl exec -it security-context-demo -- id
出力はこのようになります。
uid=1000 gid=3000 groups=3000,4000
Podのステータスを確認します。
kubectl get pod security-context-demo -o yaml
status.containerStatuses[].user.linux
フィールドでコンテナの最初のプロセスに付与されたユーザー、グループ情報が確認出来ます。
...
status:
containerStatuses:
- name: sec-ctx-demo
user:
linux:
gid: 3000
supplementalGroups:
- 3000
- 4000
uid: 1000
...
status.containerStatuses[].user.linux
フィールドで公開されているユーザー、グループ情報は、コンテナの最初のプロセスに、最初に付与された 情報であることに注意してください。
もしそのプロセスが、自身のユーザー、グループ情報を変更できるシステムコール(例えば setuid(2)
,
setgid(2)
,
setgroups(2)
等)を実行する権限を持っている場合、プロセス自身で動的に変更が可能なためです。
つまり、実際にプロセスに付与されているユーザー、グループ情報は動的に変化します。下記のコンテナランタイムがfine-grained(きめ細かい) SupplementalGroups controlを実装しています。
CRI実装:
ノードのステータスでこの機能が利用可能かどうか確認出来ます。
apiVersion: v1
kind: Node
...
status:
features:
supplementalGroupsPolicy: true
Kubernetes v1.23 [stable]
デフォルトでは、Kubernetesはボリュームがマウントされたときに、PodのsecurityContext
で指定されたfsGroup
に合わせて再帰的に各ボリュームの中の所有権とパーミッションを変更します。
大きなボリュームでは所有権の確認と変更に時間がかかり、Podの起動が遅くなります。
securityContext
の中のfsGroupChangePolicy
フィールドを設定することで、Kubernetesがボリュームの所有権・パーミッションの確認と変更をどう行うかを管理することができます。
fsGroupChangePolicy - fsGroupChangePolicy
は、ボリュームがPod内部で公開される前に所有権とパーミッションを変更するための動作を定義します。
このフィールドはfsGroup
で所有権とパーミッションを制御することができるボリュームタイプにのみ適用されます。このフィールドは以下の2つの値を取ります。
例:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
fsGroupChangePolicy: "OnRootMismatch"
Kubernetes v1.26 [stable]
VOLUME_MOUNT_GROUP
NodeServiceCapability
をサポートしているContainer Storage Interface (CSI)ドライバーをデプロイした場合、securityContext
のfsGroup
で指定された値に基づいてKubernetesの代わりにCSIドライバーがファイルの所有権とパーミッションの設定処理を行います。
この場合Kubernetesは所有権とパーミッションの設定を行わないためfsGroupChangePolicy
は無効となり、CSIで指定されている通りドライバーはfsGroup
に従ってボリュームをマウントすると考えられるため、ボリュームはfsGroup
に従って読み取り・書き込み可能になります。
コンテナに対してセキュリティ設定を行うには、コンテナマニフェストにsecurityContext
フィールドを含めてください。securityContext
フィールドにはSecurityContextオブジェクトが入ります。
コンテナに指定したセキュリティ設定は個々のコンテナに対してのみ反映され、Podレベルの設定を上書きします。コンテナの設定はPodのボリュームに対しては影響しません。
こちらは一つのコンテナを持つPodの設定ファイルです。PodもコンテナもsecurityContext
フィールドを含んでいます。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-2
spec:
securityContext:
runAsUser: 1000
containers:
- name: sec-ctx-demo-2
image: gcr.io/google-samples/node-hello:1.0
securityContext:
runAsUser: 2000
allowPrivilegeEscalation: false
Podを作成します。
kubectl apply -f https://k8s.io/examples/pods/security/security-context-2.yaml
Podのコンテナが実行されていることを確認します。
kubectl get pod security-context-demo-2
実行中のコンテナでshellを取ります。
kubectl exec -it security-context-demo-2 -- sh
shellの中で、実行中のプロセスの一覧を表示します。
ps aux
ユーザー2000として実行されているプロセスが表示されました。これはコンテナのrunAsUser
で指定された値です。Podで指定された値である1000を上書きしています。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
2000 1 0.0 0.0 4336 764 ? Ss 20:36 0:00 /bin/sh -c node server.js
2000 8 0.1 0.5 772124 22604 ? Sl 20:36 0:00 node server.js
...
shellから抜けます。
exit
Linuxケーパビリティを用いると、プロセスに対してrootユーザーの全権を渡すことなく特定の権限を与えることができます。
コンテナに対してLinuxケーパビリティを追加したり削除したりするには、コンテナマニフェストのsecurityContext
セクションのcapabilities
フィールドに追加してください。
まず、capabilities
フィールドを含まない場合どうなるかを見てみましょう。
こちらはコンテナに対してケーパビリティを渡していない設定ファイルです。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-3
spec:
containers:
- name: sec-ctx-3
image: gcr.io/google-samples/node-hello:1.0
Podを作成します。
kubectl apply -f https://k8s.io/examples/pods/security/security-context-3.yaml
Podが実行されていることを確認します。
kubectl get pod security-context-demo-3
実行中のコンテナでshellを取ります。
kubectl exec -it security-context-demo-3 -- sh
shellの中で、実行中のプロセスの一覧を表示します。
ps aux
コンテナのプロセスID(PID)が出力されます。
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js
root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js
shellの中で、プロセス1のステータスを確認します。
cd /proc/1
cat status
プロセスのケーパビリティビットマップが表示されます。
...
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
...
ケーパビリティビットマップのメモを取った後、shellから抜けます。
exit
次に、追加のケーパビリティを除いて上と同じ設定のコンテナを実行します。
こちらは1つのコンテナを実行するPodの設定ファイルです。
CAP_NET_ADMIN
とCAP_SYS_TIME
ケーパビリティを設定に追加しました。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/node-hello:1.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
Podを作成します。
kubectl apply -f https://k8s.io/examples/pods/security/security-context-4.yaml
実行中のコンテナでshellを取ります。
kubectl exec -it security-context-demo-4 -- sh
shellの中で、プロセス1のケーパビリティを確認します。
cd /proc/1
cat status
プロセスのケーパビリティビットマップが表示されます。
...
CapPrm: 00000000aa0435fb
CapEff: 00000000aa0435fb
...
2つのコンテナのケーパビリティを比較します。
00000000a80425fb
00000000aa0435fb
1つ目のコンテナのケーパビリティビットマップでは、12, 25ビット目がクリアされています。2つ目のコンテナでは12, 25ビット目がセットされています。12ビット目はCAP_NET_ADMIN
、25ビット目はCAP_SYS_TIME
です。
ケーパビリティの定数の定義はcapability.hを確認してください。
CAP_XXX
形式です。
ただしコンテナのマニフェストでケーパビリティを記述する際は、定数のCAP_
の部分を省いてください。
例えば、CAP_SYS_TIME
を追加したい場合はケーパビリティにSYS_TIME
を追加してください。コンテナにSeccompプロフィールを設定するには、Pod・コンテナマニフェストのsecurityContext
にseccompProfile
フィールドを追加してください。
seccompProfile
フィールドはSeccompProfileオブジェクトで、type
とlocalhostProfile
で構成されています。
type
ではRuntimeDefault
、Unconfined
、Localhost
が有効です。
localhostProfile
はtype: Localhost
のときのみ指定可能です。こちらはノード上で事前に設定されたプロファイルのパスを示していて、kubeletのSeccompプロファイルの場所(--root-dir
フラグで設定したもの)からの相対パスです。
こちらはノードのコンテナランタイムのデフォルトプロフィールをSeccompプロフィールとして設定した例です。
...
securityContext:
seccompProfile:
type: RuntimeDefault
こちらは<kubelet-root-dir>/seccomp/my-profiles/profile-allow.json
で事前に設定したファイルをSeccompプロフィールに設定した例です。
...
securityContext:
seccompProfile:
type: Localhost
localhostProfile: my-profiles/profile-allow.json
コンテナにAppArmorプロフィールを設定するには、securityContext
セクションにappAormorProfile
フィールドを含めてください。
appAormerProfile
フィールドには、type
フィールドとlocalhostProfile
フィールドから構成されるAppArmorProfileオブジェクトが入ります。type
フィールドの有効なオプションはRuntimeDefault
(デフォルト)、Unconfined
、Localhost
です。
localhostProfile
はtype
がLocalhost
のときには必ず設定しなければなりません。この値はノードで事前に設定されたプロフィール名を示します。Podは事前にどのノードにスケジュールされるかわからないため、指定されたプロフィールはPodがスケジュールされ得る全てのノードにロードされている必要があります。カスタムプロフィールをセットアップする方法はSetting up nodes with profilesを参照してください。
注意: containers[*].securityContext.appArmorProfile.type
が明示的にRuntimeDefault
に設定されている場合は、もしノードでAppArmorが有効化されていなければ、Podの作成は許可されません。
しかし、containers[*].securityContext.appArmorProfile.type
が設定されていない場合、AppArmorが有効化されていれば、デフォルト(RuntimeDefault
)が適用されます。もし、AppArmorが無効化されている場合は、Podの作成は許可されますが、コンテナにはRuntimeDefault
プロフィールの制限は適用されません。
これは、AppArmorプロフィールとして、ノードのコンテナランタイムのデフォルトプロフィールを設定する例です。
...
containers:
- name: container-1
securityContext:
appArmorProfile:
type: RuntimeDefault
これは、AppArmorプロフィールとして、k8s-apparmor-example-deny-write
という名前で事前に設定されたプロフィールを設定する例です。
...
containers:
- name: container-1
securityContext:
appArmorProfile:
type: Localhost
localhostProfile: k8s-apparmor-example-deny-write
より詳細な内容についてはRestrict a Container's Access to Resources with AppArmorを参照してください。
コンテナにSELinuxラベルをつけるには、Pod・コンテナマニフェストのsecurityContext
セクションにseLinuxOptions
フィールドを追加してください。
seLinuxOptions
フィールドはSELinuxOptionsオブジェクトが入ります。
こちらはSELinuxレベルを適用する例です。
...
securityContext:
seLinuxOptions:
level: "s0:c123,c456"
Kubernetes v1.28 [beta]
(enabled by default: true)Kubernetes v1.27で、ReadWriteOncePod
アクセスモードを使用するボリューム(およびPersistentVolumeClaim)にのみ、この機能の限定的な機能が早期提供されています。
Alphaフィーチャーとして、SELinuxMount
フィーチャーゲートを有効にすることで、以下で説明するように、他の種類のPersistentVolumeClaimにもパフォーマンス改善の範囲を広げる事ができます。
デフォルトでは、コンテナランタイムは全てのPodのボリュームの全てのファイルに再帰的にSELinuxラベルを付与します。処理速度を上げるために、Kubernetesはマウントオプションで-o context=<label>
を使うことでボリュームのSELinuxラベルを即座に変更することができます。
この高速化の恩恵を受けるには、以下の全ての条件を満たす必要があります。
ReadWriteOncePod
とSELinuxMountReadWriteOncePod
を有効にすることaccessModes
でPersistentVolumeClaimを使うことaccessModes: ["ReadWriteOncePod"]
を持ち、フィーチャーゲートSELinuxMountReadWriteOncePod
が有効であることSELinuxMountReadWriteOncePod
とSELinuxMount
の両方が有効であることseLinuxOptions
が設定されていることiscs
、rbd
、fc
ボリュームタイプであることspec.seLinuxMount: true
を指定したときに-o context
でマウントを行うとアナウンスしていることそれ以外のボリュームタイプでは、コンテナランタイムはボリュームに含まれる全てのinode(ファイルやディレクトリ)に対してSELinuxラベルを再帰的に変更します。 ボリューム内のファイルやディレクトリが増えるほど、ラベリングにかかる時間は増加します。
/proc
ファイルシステムへのアクセスを管理するKubernetes v1.31 [beta]
(enabled by default: false)OCI runtime specificationに準拠するランタイムでは、コンテナはデフォルトで、いくつかの複数のパスはマスクされ、かつ、読み取り専用のモードで実行されます。 その結果、コンテナのマウントネームスペース内にはこれらのパスが存在し、あたかもコンテナが隔離されたホストであるかのように機能しますが、コンテナプロセスはそれらのパスに書き込むことはできません。 マスクされるパスおよび読み取り専用のパスのリストは次のとおりです。
マスクされるパス:
/proc/asound
/proc/acpi
/proc/kcore
/proc/keys
/proc/latency_stats
/proc/timer_list
/proc/timer_stats
/proc/sched_debug
/proc/scsi
/sys/firmware
/sys/devices/virtual/powercap
読み取り専用のパス:
/proc/bus
/proc/fs
/proc/irq
/proc/sys
/proc/sysrq-trigger
一部のPodでは、デフォルトでパスがマスクされるのを回避したい場合があります。このようなケースで最も一般的なのは、Kubernetesコンテナ(Pod内のコンテナ)内でコンテナを実行しようとする場合です。
securityContext
のprocMount
フィールドを使用すると、コンテナの/proc
をUnmasked
にしたり、コンテナプロセスによって読み書き可能な状態でマウントすることができます。この設定は、/proc
以外の/sys/firmware
にも適用されます。
...
securityContext:
procMount: Unmasked
procMount
をUnmaskedに設定するには、Podのspec.hostUsers
の値がfalse
である必要があります。
つまり、Unmaskedな/proc
やUnmaskedな/sys
を使用したいコンテナは、user namespace内で動作している必要があります。
Kubernetes v1.12からv1.29までは、この要件は強制されません。PodのセキュリティコンテキストはPodのコンテナや、適用可能であればPodのボリュームに対しても適用されます。
特にfsGroup
とseLinuxOptions
は以下のようにボリュームに対して適用されます。
fsGroup
: 所有権管理をサポートしているボリュームはfsGroup
で指定されているGIDで所有権・書き込み権限が設定されます。詳しくはOwnership Management design documentを確認してください。
seLinuxOptions
: SELinuxラベリングをサポートしているボリュームではseLinuxOptions
で指定されているラベルでアクセス可能になるように貼り直されます。通常、level
セクションのみ設定する必要があります。
これはPod内の全てのボリュームとコンテナに対しMulti-Category Security (MCS)ラベルを設定します。
Podを削除します。
kubectl delete pod security-context-demo
kubectl delete pod security-context-demo-2
kubectl delete pod security-context-demo-3
kubectl delete pod security-context-demo-4
このページでは、Secretを用いるPodを作成するためにイメージをプライベートコンテナイメージレジストリもしくはリポジトリから取得する方法について説明します。 多くのプライベートレジストリが存在しますが、このタスクではDocker Hubをレジストリの一例として使用します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
この演習を行うためには、docker
コマンドラインツールと自身のDocker IDが必要です。
別のプライベートコンテナレジストリを使用している場合は、そのレジストリのコマンドラインツールとログイン情報が必要です。
ラップトップ(ローカル環境)上では、プライベートイメージを取得するためにレジストリに認証する必要があります。
docker
ツールを使用してDocker Hubにログインしてください。詳細はDocker IDアカウントの Sign in セクションを参照してください。
docker login
プロンプトが表示されたら、Docker IDと使用したい認証情報(アクセストークンまたはDocker IDのパスワード)を入力してください。
ログインプロセスは、認証トークンを保持するconfig.json
ファイルを作成または更新します。Kubernetesがこのファイルを解釈する方法を確認してください。
以下のようにconfig.json
ファイルを確認します:
cat ~/.docker/config.json
出力には以下のような部分が含まれています:
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "c3R...zE2"
}
}
}
auth
エントリの代わりに、ストア名を値とするcredsStore
エントリが表示されます。
この場合、Secretを直接作成できます。
コマンドライン上で認証情報を入力してSecretを作成するを参照してください。Kubernetesクラスターはプライベートイメージを取得するためのレジストリとの認証にkubernetes.io/dockerconfigjson
タイプのSecretを使用します。
既にdocker login
を実行済みの場合、その認証情報をKubernetesにコピーできます:
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=<path/to/.docker/config.json> \
--type=kubernetes.io/dockerconfigjson
新しいSecretをカスタマイズする必要がある場合(例えば、新しいSecretにNamespaceやLabelを設定する場合)は、保存する前にSecretをカスタマイズできます。 必ず以下を行ってください:
data
項目の名前を.dockerconfigjson
に設定するdata[".dockerconfigjson"]
の値として貼り付けるtype
をkubernetes.io/dockerconfigjson
に設定するSecretをカスタマイズする場合のマニフェストの例:
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: awesomeapps
data:
.dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
type: kubernetes.io/dockerconfigjson
error: no objects passed to create
をエラーメッセージとして受け取った場合、base64エンコードされた文字列が無効である可能性があります。
Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...
をエラーメッセージとして受け取った場合は、data
内のbase64エンコードされた文字列は正常にデコードされたものの、.docker/config.json
ファイルとして読み込むことができなかったことを意味します。
このSecretをregcred
という名前で作成します:
kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
ここでは:
<your-registry-server>
は、プライベートDockerレジストリのFQDN(完全修飾ドメイン名)です。
Docker Hubを使用する場合は、https://index.docker.io/v1/
を設定して下さい。<your-name>
は、Dockerのユーザー名です。<your-pword>
は、Dockerのパスワードです。<your-email>
は、Dockerのメールアドレスです。Dockerレジストリの認証情報がSecretとしてregcred
という名前でクラスターに正常に設定されました。
kubectl
実行中はPCの他のユーザーがそれらの認証情報を閲覧できる可能性があります。regcred
Secretを確認する作成したregcred
Secretの内容を理解するために、まずYAML形式でSecretを表示します:
kubectl get secret regcred --output=yaml
出力は以下のようになります:
apiVersion: v1
kind: Secret
metadata:
...
name: regcred
...
data:
.dockerconfigjson: eyJodHRwczovL2luZGV4L ... J0QUl6RTIifX0=
type: kubernetes.io/dockerconfigjson
.dockerconfigjson
フィールドの値は、Docker認証情報をbase64でエンコードしたものです。
.dockerconfigjson
フィールドの内容を理解するために、認証情報のデータを読解可能な形式に変換します:
kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
出力は以下のようになります:
{"auths":{"your.private.registry.example.com":{"username":"janedoe","password":"xxxxxxxxxxx","email":"jdoe@example.com","auth":"c3R...zE2"}}}
auth
フィールドの内容を理解するために、base64エンコードされたデータを読解可能な形式に変換します:
echo "c3R...zE2" | base64 --decode
出力はユーザー名とパスワードが:
で連結された以下のような形式になります:
janedoe:xxxxxxxxxxx
Secretのdata
には、ローカルの~/.docker/config.json
ファイルと同様の認証トークンが含まれていることが分かります。
クラスターにregcred
という名前のSecretとしてDockerの認証情報が正常に設定されました。
以下はregcred
という名前のDockerの認証情報へのアクセスが必要なPodのマニフェストの例です:
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regcred
上記のファイルをあなたのコンピューターにダウンロードします:
curl -L -o my-private-reg-pod.yaml https://k8s.io/examples/pods/private-reg-pod.yaml
my-private-reg-pod.yaml
ファイル内の<your-private-image>
を、以下のようなプライベートレジストリのイメージのパスに置き換えてください:
your.private.registry.example.com/janedoe/jdoe-private:v1
プライベートレジストリからイメージを取得するために、Kubernetesは認証情報を必要とします。
設定ファイル内のimagePullSecrets
フィールドは、Kubernetesがregcred
という名前のSecretから認証情報を取得することを指定します。
以下のようにして作成したSecretを使用するPodを作成し、Podが実行されていることを確認します:
kubectl apply -f my-private-reg-pod.yaml
kubectl get pod private-reg
また、PodのステータスがImagePullBackOff
になり起動に失敗した場合は、Podのイベントを確認してください:
kubectl describe pod private-reg
もしFailedToRetrieveImagePullSecret
という理由を持つイベントが表示された場合は、Kubernetesが指定された名前のSecret(この例ではregcred
)を見つけることができないことを示します。
指定したSecretが存在し、その名前が正しく記載されていることを確認してください。
Events:
... Reason ... Message
------ -------
... FailedToRetrieveImagePullSecret ... Unable to retrieve some image pull secrets (<regcred>); attempting to pull the image may not succeed.
1つのPodは複数のコンテナを持つことができ、各コンテナのイメージは異なるレジストリから取得できます。
1つのPodで複数のimagePullSecrets
を使用でき、それぞれに複数の認証情報を含めることができます。
レジストリに一致する各認証情報を使用してイメージの取得が試行されます。 レジストリに一致する認証情報がない場合、認証なしで、またはカスタムランタイム固有の設定を使用してイメージの取得が試行されます。
imagePullSecrets
フィールドを参照する。このページでは、Liveness Probe、Readiness ProbeおよびStartup Probeの使用方法について説明します。
kubeletは、Liveness Probeを使用して、コンテナをいつ再起動するかを認識します。 例えば、アプリケーション自体は起動しているが、処理を継続することができないデッドロック状態を検知することができます。 このような状態のコンテナを再起動することで、バグがある場合でもアプリケーションの可用性を高めることができます。
kubeletは、Readiness Probeを使用して、コンテナがトラフィックを受け入れられる状態であるかを認識します。 Podが準備ができていると見なされるのは、Pod内の全てのコンテナの準備が整ったときです。 一例として、このシグナルはServiceのバックエンドとして使用されるPodを制御するときに使用されます。 Podの準備ができていない場合、そのPodはServiceのロードバランシングから切り離されます。
kubeletは、Startup Probeを使用して、コンテナアプリケーションの起動が完了したかを認識します。 Startup Probeを使用している場合、Startup Probeが成功するまでは、Liveness Probeと Readiness Probeによるチェックを無効にし、これらがアプリケーションの起動に干渉しないようにします。 例えば、これを起動が遅いコンテナの起動チェックとして使用することで、起動する前にkubeletによって 強制終了されることを防ぐことができます。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.長期間実行されているアプリケーションの多くは、再起動されるまで回復できないような異常な状態になることがあります。 Kubernetesはこのような状況を検知し、回復するためのLiveness Probeを提供します。
この演習では、registry.k8s.io/busybox
イメージのコンテナを起動するPodを作成します。
Podの構成ファイルは次の通りです。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: registry.k8s.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
この構成ファイルでは、Podは一つのContainer
を起動します。
periodSeconds
フィールドは、kubeletがLiveness Probeを5秒おきに行うように指定しています。
initialDelaySeconds
フィールドは、kubeletが最初のProbeを実行する前に5秒間待機するように指示しています。
Probeの動作としては、kubeletはcat /tmp/healthy
を対象のコンテナ内で実行します。
このコマンドが成功し、リターンコード0が返ると、kubeletはコンテナが問題なく動いていると判断します。
リターンコードとして0以外の値が返ると、kubeletはコンテナを終了し、再起動を行います。
このコンテナは、起動すると次のコマンドを実行します:
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600"
コンテナが起動してから初めの30秒間は/tmp/healthy
ファイルがコンテナ内に存在します。
そのため初めの30秒間はcat /tmp/healthy
コマンドは成功し、正常なリターンコードが返ります。
その後30秒が経過すると、cat /tmp/healthy
コマンドは異常なリターンコードを返します。
このPodを起動してください:
kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
30秒間以内に、Podのイベントを確認します。
kubectl describe pod liveness-exec
この出力結果は、Liveness Probeがまだ失敗していないことを示しています。
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "registry.k8s.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "registry.k8s.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
35秒後に、Podのイベントをもう一度確認します:
kubectl describe pod liveness-exec
出力結果の最後に、Liveness Probeが失敗していることを示すメッセージが表示されます。これによりコンテナは強制終了し、再作成されました。
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "registry.k8s.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "registry.k8s.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
さらに30秒後、コンテナが再起動していることを確認します:
kubectl get pod liveness-exec
出力結果から、RESTARTS
がインクリメントされていることを確認します:
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
別の種類のLiveness Probeでは、HTTP GETリクエストを使用します。
次の構成ファイルは、registry.k8s.io/e2e-test-images/agnhost
イメージを使用したコンテナを起動するPodを作成します。
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: registry.k8s.io/e2e-test-images/agnhost:2.40
args:
- liveness
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
この構成ファイルでは、Podは一つのContainer
を起動します。
periodSeconds
フィールドは、kubeletがLiveness Probeを3秒おきに行うように指定しています。
initialDelaySeconds
フィールドは、kubeletが最初のProbeを実行する前に3秒間待機するように指示しています。
Probeの動作としては、kubeletは8080ポートをリッスンしているコンテナ内のサーバーに対してHTTP GETリクエストを送ります。
サーバー内の/healthz
パスに対するハンドラーが正常なリターンコードを応答した場合、
kubeletはコンテナが問題なく動いていると判断します。
異常なリターンコードを応答すると、kubeletはコンテナを終了し、再起動を行います。
200以上400未満のコードは成功とみなされ、その他のコードは失敗とみなされます。
server.go にてサーバーのソースコードを確認することができます。
コンテナが生きている初めの10秒間は、/healthz
ハンドラーが200ステータスを返します。
その後、ハンドラーは500ステータスを返します。
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
kubeletは、コンテナが起動してから3秒後からヘルスチェックを行います。 そのため、初めのいくつかのヘルスチェックは成功します。しかし、10秒経過するとヘルスチェックは失敗し、kubeletはコンテナを終了し、再起動します。
HTTPリクエストのチェックによるLiveness Probeを試すには、以下のようにPodを作成します:
kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml
10秒後、Podのイベントを表示して、Liveness Probeが失敗し、コンテナが再起動されていることを確認します。
kubectl describe pod liveness-http
v1.13以前(v1.13を含む)のリリースにおいては、Podが起動しているノードに環境変数http_proxy
(または HTTP_PROXY
)が設定されている場合、HTTPリクエストのLiveness Probeは設定されたプロキシを使用します。
v1.13より後のリリースにおいては、ローカルHTTPプロキシ環境変数の設定はHTTPリクエストのLiveness Probeに影響しません。
3つ目のLiveness ProbeはTCPソケットを使用するタイプです。 この構成においては、kubeletは指定したコンテナのソケットを開くことを試みます。 コネクションが確立できる場合はコンテナを正常とみなし、失敗する場合は異常とみなします。
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: registry.k8s.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
見ての通り、TCPによるチェックの構成はHTTPによるチェックと非常に似ています。
この例では、Readiness ProbeとLiveness Probeを両方使用しています。
kubeletは、コンテナが起動してから5秒後に最初のReadiness Probeを開始します。
これはgoproxy
コンテナの8080ポートに対して接続を試みます。
このProbeが成功すると、Podは準備ができていると通知されます。kubeletはこのチェックを10秒ごとに行います。
この構成では、Readiness Probeに加えてLiveness Probeが含まれています。
kubeletは、コンテナが起動してから15秒後に最初のLiveness Probeを実行します。
Readiness Probeと同様に、これはgoproxy
コンテナの8080ポートに対して接続を試みます。
Liveness Probeが失敗した場合、コンテナは再起動されます。
TCPのチェックによるLiveness Probeを試すには、以下のようにPodを作成します:
kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
15秒後、Podのイベントを表示し、Liveness Probeが行われていることを確認します:
kubectl describe pod goproxy
HTTPまたはTCPによるProbeにおいて、ContainerPort で定義した名前付きポートを使用することができます。
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
場合によっては、最初の初期化において追加の起動時間が必要になるようなレガシーアプリケーションを扱う必要があります。 そのような場合、デッドロックに対する迅速な反応を損なうことなくLiveness Probeのパラメーターを設定することは難しい場合があります。
これに対する解決策の一つは、Liveness Probeと同じ構成のコマンドを用いるか、HTTPまたはTCPによるチェックを使用したStartup Probeをセットアップすることです。
その際、failureThreshold * periodSeconds
で計算される時間を、起動時間として想定される最も遅いケースをカバーできる十分な長さに設定します。
上記の例は、次のようになります:
ports:
- name: liveness-port
containerPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10
Startup Probeにより、アプリケーションは起動が完了するまでに最大5分間の猶予(30 * 10 = 300秒)が与えられます。
Startup Probeに一度成功すると、その後はLiveness Probeが引き継ぎ、コンテナのデッドロックに対して迅速に反応します。
Startup Probeが成功しない場合、コンテナは300秒後に終了し、その後はPodのrestartPolicy
に従います。
アプリケーションは一時的にトラフィックを処理できないことが起こり得ます。 例えば、アプリケーションは起動時に大きなデータまたは構成ファイルを読み込む必要がある場合や、起動後に外部サービスに依存している場合があります。 このような場合、アプリケーション自体を終了させたくはありませんが、このアプリケーションに対してリクエストも送信したくないと思います。 Kubernetesは、これらの状況を検知して緩和するための機能としてReadiness Probeを提供します。 これにより、準備ができていないことを報告するコンテナを含むPodは、KubernetesのServiceを通してトラフィックを受信しないようになります。
Readiness ProbeはLiveness Probeと同様に構成します。
唯一の違いはreadinessProbe
フィールドをlivenessProbe
フィールドの代わりに利用することだけです。
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
HTTPおよびTCPによるReadiness Probeの構成もLiveness Probeと同じです。
Readiness ProbeとLiveness Probeは同じコンテナで同時に使用できます。 両方使用することで、準備できていないコンテナへのトラフィックが到達しないようにし、コンテナが失敗したときに再起動することができます。
Probe には、 Liveness ProbeおよびReadiness Probeのチェック動作をより正確に制御するために使用できるフィールドがあります:
initialDelaySeconds
: コンテナが起動してから、Liveness ProbeまたはReadiness Probeが開始されるまでの秒数。デフォルトは0秒。最小値は0。periodSeconds
: Probeが実行される頻度(秒数)。デフォルトは10秒。最小値は1。
コンテナが起動してから準備が整うまでの間、periodSeconds
で指定した間隔とは異なるタイミングでReadiness Probeが実行される場合があります。
これは、Podをより早く準備完了の状態に移行させるためです。timeoutSeconds
: Probeがタイムアウトになるまでの秒数。デフォルトは1秒。最小値は1。successThreshold
: 一度Probeが失敗した後、次のProbeが成功したとみなされるための最小連続成功数。
デフォルトは1。Liveness ProbeおよびStartup Probeには1を設定する必要があります。最小値は1。failureThreshold
: Probeが失敗した場合、KubernetesはfailureThreshold
に設定した回数までProbeを試行します。
Liveness Probeにおいて、試行回数に到達することはコンテナを再起動することを意味します。
Readiness Probeの場合は、Podが準備できていない状態として通知されます。デフォルトは3。最小値は1。HTTPによるProbe
には、httpGet
にて設定できる追加のフィールドがあります:
host
: 接続先ホスト名。デフォルトはPod IP。おそらくはこのフィールドの代わりにhttpHeaders
内の"Host"を代わりに使用することになります。scheme
: ホストへの接続で使用するスキーマ(HTTP または HTTPS)。デフォルトは HTTP。path
: HTTPサーバーへアクセスする際のパスhttpHeaders
: リクエスト内のカスタムヘッダー。HTTPでは重複したヘッダーが許可されています。port
: コンテナにアクセスする際のポートの名前または番号。ポート番号の場合、1から65535の範囲内である必要があります。HTTPによるProbeの場合、kubeletは指定したパスとポートに対するHTTPリクエストを送ることでチェックを行います。
httpGet
のオプションであるhost
フィールドでアドレスが上書きされない限り、kubeletはPodのIPアドレスに対してProbeを送ります。
scheme
フィールドにHTTPS
がセットされている場合、kubeletは証明書の検証を行わずにHTTPSリクエストを送ります。
ほとんどのシナリオにおいては、host
フィールドを使用する必要はありません。次のシナリオは使用する場合の一例です。
仮にコンテナが127.0.0.1をリッスンしており、かつPodのhostNetwork
フィールドがtrueだとします。
その場合においては、httpGet
フィールド内のhost
には127.0.0.1をセットする必要があります。
より一般的なケースにおいてPodが仮想ホストに依存している場合は、おそらくhost
フィールドではなく、httpHeaders
フィールド内のHost
ヘッダーを使用する必要があります。
TCPによるProbeの場合、kubeletはPodの中ではなく、ノードに対してコネクションを確立するProbeを実行します。
kubeletはServiceの名前を解決できないため、host
パラメーター内でServiceの名前を使用することはできません。
また、次のAPIリファレンスも参考にしてください:
このページでは、KubernetesのPodをKubernetesクラスター上の特定のノードに割り当てる方法を説明します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.クラスター内のノードのリストをラベル付きで表示します。
kubectl get nodes --show-labels
出力は次のようになります。
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
ノードの1つを選択して、ラベルを追加します。
kubectl label nodes <your-node-name> disktype=ssd
ここで、<your-node-name>
は選択したノードの名前です。
選択したノードにdisktype=ssd
ラベルがあることを確認します。
kubectl get nodes --show-labels
出力は次のようになります。
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
上の出力を見ると、worker0
にdisktype=ssd
というラベルがあることがわかります。
以下のPodの構成ファイルには、nodeSelectorにdisktype: ssd
を持つPodが書かれています。これにより、Podはdisktype: ssd
というラベルを持っているノードにスケジューリングされるようになります。
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
構成ファイルを使用して、選択したノードにスケジューリングされるPodを作成します。
kubectl apply -f https://k8s.io/examples/pods/pod-nginx.yaml
Podが選択したノード上で実行されているをことを確認します。
kubectl get pods --output=wide
出力は次のようになります。
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
nodeName
という設定を使用して、Podを特定のノードにスケジューリングすることもできます。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: foo-node # 特定のノードにPodをスケジューリングする
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
構成ファイルを使用して、foo-node
にだけスケジューリングされるPodを作成します。
このページでは、Node Affinityを利用して、PodをKubernetesクラスター内の特定のノードに割り当てる方法を説明します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
作業するKubernetesサーバーは次のバージョン以降のものである必要があります: v1.10. バージョンを確認するには次のコマンドを実行してください:kubectl version
.クラスター内のノードを一覧表示して、ラベルを確認します。
kubectl get nodes --show-labels
出力は次のようになります。
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
ノードを選択して、ラベルを追加します。
kubectl label nodes <your-node-name> disktype=ssd
ここで、<your-node-name>
は選択したノードの名前で置換します。
選択したノードにdisktype=ssd
ラベルがあることを確認します。
kubectl get nodes --show-labels
出力は次のようになります。
NAME STATUS ROLES AGE VERSION LABELS
worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0
worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1
worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
この出力を見ると、worker0
ノードにdisktype=ssd
というラベルが追加されたことがわかります。
以下に示すマニフェストには、requiredDuringSchedulingIgnoredDuringExecution
にdisktype: ssd
というnode affinityを使用したPodが書かれています。このように書くと、Podはdisktype=ssd
というラベルを持つノードにだけスケジューリングされるようになります。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
マニフェストを適用して、選択したノード上にスケジューリングされるPodを作成します。
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-required-affinity.yaml
Podが選択したノード上で実行されていることを確認します。
kubectl get pods --output=wide
出力は次のようになります。
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
以下に示すマニフェストには、preferredDuringSchedulingIgnoredDuringExecution
にdisktype: ssd
というnode affinityを使用したPodが書かれています。このように書くと、Podはdisktype=ssd
というラベルを持つノードに優先的にスケジューリングされるようになります。
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
マニフェストを適用して、選択したノード上にスケジューリングされるPodを作成します。
kubectl apply -f https://k8s.io/examples/pods/pod-nginx-preferred-affinity.yaml
Podが選択したノード上で実行されていることを確認します。
kubectl get pods --output=wide
出力は次のようになります。
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
Node Affinityについてさらに学ぶ。
このページでは、アプリケーションコンテナが実行される前に、Initコンテナを使用してPodを初期化する方法を示します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.この演習では、アプリケーションコンテナが1つ、Initコンテナが1つのPodを作成します。 Initコンテナはアプリケーションコンテナが実行される前に完了します。
Podの設定ファイルは次の通りです:
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# These containers are run during pod initialization
initContainers:
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://kubernetes.io
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
設定ファイルを確認すると、PodはInitコンテナとアプリケーションコンテナが共有するボリュームを持っています。
Initコンテナは共有ボリュームを/work-dir
にマウントし、アプリケーションコンテナは共有ボリュームを/usr/share/nginx/html
にマウントします。
Initコンテナは以下のコマンドを実行してから終了します:
wget -O /work-dir/index.html http://info.cern.ch
Initコンテナは、nginxサーバーのルートディレクトリのindex.html
ファイルに書き込むことに注意してください。
Podを作成します:
kubectl apply -f https://k8s.io/examples/pods/init-containers.yaml
nginxコンテナが実行中であることを確認します:
kubectl get pod init-demo
次の出力はnginxコンテナが実行中であることを示します:
NAME READY STATUS RESTARTS AGE
init-demo 1/1 Running 0 1m
init-demo Podで実行中のnginxコンテナのシェルを取得します:
kubectl exec -it init-demo -- /bin/bash
シェルで、nginxサーバーにGETリクエストを送信します:
root@nginx:~# apt-get update
root@nginx:~# apt-get install curl
root@nginx:~# curl localhost
出力は、Initコンテナが書き込んだウェブページをnginxが提供していることを示します:
<html><head></head><body><header>
<title>http://info.cern.ch</title>
</header>
<h1>http://info.cern.ch - home of the first website</h1>
...
<li><a href="http://info.cern.ch/hypertext/WWW/TheProject.html">Browse the first website</a></li>
...
このページでは、コンテナのライフサイクルイベントにハンドラーを紐付けする方法を説明します。KubernetesはpostStartとpreStopイベントをサポートしています。Kubernetesはコンテナの起動直後にpostStartイベントを送信し、コンテナの終了直前にpreStopイベントを送信します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.この課題では、1つのコンテナを持つPodを作成します。コンテナには、postStartイベントとpreStopイベントのハンドラーがあります。
これがPodの設定ファイルです:
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
設定ファイルでは、postStartコマンドがmessage
ファイルをコンテナの/usr/share
ディレクトリに書き込むことがわかります。preStopコマンドはnginxを適切にシャットダウンします。これは、障害のためにコンテナが終了している場合に役立ちます。
Podを作成します:
kubectl apply -f https://k8s.io/examples/pods/lifecycle-events.yaml
Pod内のコンテナが実行されていることを確認します:
kubectl get pod lifecycle-demo
Pod内で実行されているコンテナでシェルを実行します:
kubectl exec -it lifecycle-demo -- /bin/bash
シェルで、postStart
ハンドラーがmessage
ファイルを作成したことを確認します:
root@lifecycle-demo:/# cat /usr/share/message
出力は、postStartハンドラーによって書き込まれたテキストを示しています。
Hello from the postStart handler
コンテナが作成された直後にKubernetesはpostStartイベントを送信します。 ただし、コンテナのエントリーポイントが呼び出される前にpostStartハンドラーが呼び出されるという保証はありません。postStartハンドラーはコンテナのコードに対して非同期的に実行されますが、postStartハンドラーが完了するまでコンテナのKubernetesによる管理はブロックされます。postStartハンドラーが完了するまで、コンテナのステータスはRUNNINGに設定されません。
Kubernetesはコンテナが終了する直前にpreStopイベントを送信します。 コンテナのKubernetesによる管理は、Podの猶予期間が終了しない限り、preStopハンドラーが完了するまでブロックされます。詳細はPodのライフサイクルを参照してください。
ConfigMapを使用すると、設定をイメージのコンテンツから切り離して、コンテナ化されたアプリケーションの移植性を維持できます。このページでは、ConfigMapを作成し、ConfigMapに保存されているデータを使用してPodを構成する一連の使用例を示します。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.kubectl create configmap
またはkustomization.yaml
のConfigMap generatorを使用すると、ConfigMapを作成できます。kubectl
がkustomization.yaml
をサポートをしているのは1.14からである点に注意してください。
kubectl create configmap
を使用してConfigMapをディレクトリ、ファイル、またはリテラル値から作成します:
kubectl create configmap <map-name> <data-source>
<map-name>の部分はConfigMapに割り当てる名前で、<data-source>はデータを取得するディレクトリ、ファイル、またはリテラル値です。ConfigMapの名前は有効なDNSサブドメイン名である必要があります。
ファイルをベースにConfigMapを作成する場合、<data-source> のキーはデフォルトでファイル名になり、値はデフォルトでファイルの中身になります。
kubectl describe
または
kubectl get
を使用すると、ConfigMapに関する情報を取得できます。
kubectl create configmap
を使用すると、同一ディレクトリ内にある複数のファイルから1つのConfigMapを作成できます。ディレクトリをベースにConfigMapを作成する場合、kubectlはディレクトリ内でベース名が有効なキーであるファイルを識別し、それらのファイルを新たなConfigMapにパッケージ化します。ディレクトリ内にある通常のファイルでないものは無視されます(例: サブディレクトリ、シンボリックリンク、デバイス、パイプなど)。
例えば:
# ローカルディレクトリを作成します
mkdir -p configure-pod-container/configmap/
# `configure-pod-container/configmap/`ディレクトリにサンプルファイルをダウンロードします
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties
# ConfigMapを作成します
kubectl create configmap game-config --from-file=configure-pod-container/configmap/
上記のコマンドは各ファイルをパッケージ化します。この場合、configure-pod-container/configmap/
ディレクトリのgame.properties
と ui.properties
をgame-config ConfigMapにパッケージ化します。 以下のコマンドを使用すると、ConfigMapの詳細を表示できます:
kubectl describe configmaps game-config
出力結果は以下のようになります:
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
configure-pod-container/configmap/
ディレクトリのgame.properties
と ui.properties
ファイルはConfigMapのdata
セクションに表示されます。
kubectl get configmaps game-config -o yaml
出力結果は以下のようになります:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:52:05Z
name: game-config
namespace: default
resourceVersion: "516"
uid: b4952dc3-d670-11e5-8cd0-68f728db1985
data:
game.properties: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
kubectl create configmap
を使用して、個別のファイルまたは複数のファイルからConfigMapを作成できます。
例えば、
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties
は、以下のConfigMapを生成します:
kubectl describe configmaps game-config-2
出力結果は以下のようになります:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
--from-file
引数を複数回渡し、ConfigMapを複数のデータソースから作成できます。
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties
以下のコマンドを使用すると、ConfigMapgame-config-2
の詳細を表示できます:
kubectl describe configmaps game-config-2
出力結果は以下のようになります:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties:
----
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
--from-env-file
オプションを利用してConfigMapをenv-fileから作成します。例えば:
# Env-filesは環境編集のリストを含んでいます。
# 以下のシンタックスルールが適用されます:
# envファイルの各行はVAR=VALの形式である必要がある。
# #で始まる行 (例えばコメント)は無視される。
# 空の行は無視される。
# クオーテーションマークは特別な扱いは処理をしない(例えばConfigMapの値の一部になる).
# `configure-pod-container/configmap/`ディレクトリにサンプルファイルをダウンロードします
wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties
# env-file `game-env-file.properties`は以下のようになります
cat configure-pod-container/configmap/game-env-file.properties
enemies=aliens
lives=3
allowed="true"
# このコメントと上記の空の行は無視されます
kubectl create configmap game-config-env-file \
--from-env-file=configure-pod-container/configmap/game-env-file.properties
は、以下のConfigMapを生成します:
kubectl get configmap game-config-env-file -o yaml
出力結果は以下のようになります:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:36:28Z
name: game-config-env-file
namespace: default
resourceVersion: "809965"
uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
data:
allowed: '"true"'
enemies: aliens
lives: "3"
--from-env-file
を複数回渡してConfigMapを複数のデータソースから作成する場合、最後のenv-fileのみが使用されます。--from-env-file
を複数回渡す場合の挙動は以下のように示されます:
# `configure-pod-container/configmap/`ディレクトリにサンブルファイルをダウンロードします
wget https://kubernetes.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties
# ConfigMapを作成します
kubectl create configmap config-multi-env-files \
--from-env-file=configure-pod-container/configmap/game-env-file.properties \
--from-env-file=configure-pod-container/configmap/ui-env-file.properties
は、以下のConfigMapを生成します:
kubectl get configmap config-multi-env-files -o yaml
出力結果は以下のようになります:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:38:34Z
name: config-multi-env-files
namespace: default
resourceVersion: "810136"
uid: 252c4572-eb35-11e7-887b-42010a8002b8
data:
color: purple
how: fairlyNice
textmode: "true"
--from-file
引数を使用する場合、ConfigMapのdata
セクションでキーにファイル名以外を定義できます:
kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file>
<my-key-name>
の部分はConfigMapで使うキー、<path-to-file>
はキーで表示したいデータソースファイルの場所です。
例えば:
kubectl create configmap game-config-3 --from-file=game-special-key=configure-pod-container/configmap/game.properties
は、以下のConfigMapを生成します:
kubectl get configmaps game-config-3 -o yaml
出力結果は以下のようになります:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:54:22Z
name: game-config-3
namespace: default
resourceVersion: "530"
uid: 05f8da22-d671-11e5-8cd0-68f728db1985
data:
game-special-key: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
--from-literal
引数を指定してkubectl create configmap
を使用すると、コマンドラインからリテラル値を定義できます:
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
複数のキーバリューペアを渡せます。CLIに提供された各ペアは、ConfigMapのdata
セクションで別のエントリーとして表示されます。
kubectl get configmaps special-config -o yaml
出力結果は以下のようになります:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: special-config
namespace: default
resourceVersion: "651"
uid: dadce046-d673-11e5-8cd0-68f728db1985
data:
special.how: very
special.type: charm
kubectl
はkustomization.yaml
を1.14からサポートしています。
ジェネレーターからConfigMapを作成して適用すると、APIサーバー上でオブジェクトを作成できます。ジェネレーターはディレクトリ内のkustomization.yaml
で指定する必要があリます。
例えば、ファイルconfigure-pod-container/configmap/game.properties
からConfigMapを生成するには、
# ConfigMapGeneratorを含むkustomization.yamlファイルを作成する
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-4
files:
- configure-pod-container/configmap/game.properties
EOF
ConfigMapを作成するためにkustomizationディレクトリを適用します。
kubectl apply -k .
configmap/game-config-4-m9dm2f92bt created
ConfigMapが作成されたことを以下のようにチェックできます:
kubectl get configmap
NAME DATA AGE
game-config-4-m9dm2f92bt 1 37s
kubectl describe configmaps/game-config-4-m9dm2f92bt
Name: game-config-4-m9dm2f92bt
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Events: <none>
生成されたConfigMapの名前は、コンテンツをハッシュ化したサフィックスを持つことに注意してください。これにより、コンテンツが変更されるたびに新しいConfigMapが生成されます。
ConfigMapジェネレーターで使用するキーはファイルの名前以外を定義できます。
例えば、ファイルconfigure-pod-container/configmap/game.properties
からキーgame-special-key
を持つConfigMapを作成する場合
# ConfigMapGeneratorを含むkustomization.yamlファイルを作成する
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-5
files:
- game-special-key=configure-pod-container/configmap/game.properties
EOF
kustomizationディレクトリを適用してConfigMapを作成します。
kubectl apply -k .
configmap/game-config-5-m67dt67794 created
リテラルspecial.type=charm
とspecial.how=very
からConfigMapを作成する場合は、
以下のようにkustomization.yaml
のConfigMapジェネレーターで指定できます。
# ConfigMapGeneratorを含むkustomization.yamlファイルを作成します
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: special-config-2
literals:
- special.how=very
- special.type=charm
EOF
kustomizationディレクトリを適用してConfigMapを作成します。
kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created
ConfigMapに環境変数をキーバリューペアとして定義します:
kubectl create configmap special-config --from-literal=special.how=very
ConfigMapに定義された値special.how
をPod specificationの環境変数SPECIAL_LEVEL_KEY
に割り当てます。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
# 環境変数を定義します
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# SPECIAL_LEVEL_KEYに割り当てる値をConfigMapが保持します
name: special-config
# 値に紐付けるキーを指定します
key: special.how
restartPolicy: Never
Podを作成します:
kubectl create -f https://kubernetes.io/examples/pods/pod-single-configmap-env-variable.yaml
すると、Podの出力結果に環境変数SPECIAL_LEVEL_KEY=very
が含まれています。
先ほどの例の通り、まずはConfigMapを作成します。
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
---
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
ConfigMapを作成します:
kubectl create -f https://kubernetes.io/examples/configmap/configmaps.yaml
Pod specificationの環境変数を定義します
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: Never
Podを作成します:
kubectl create -f https://kubernetes.io/examples/pods/pod-multiple-configmap-env-variable.yaml
すると、Podの出力結果に環境変数SPECIAL_LEVEL_KEY=very
and LOG_LEVEL=INFO
が含まれています。
複数のキーバリューペアを含むConfigMapを作成します。
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
ConfigMapを作成します:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
envFrom
を利用して全てのConfigMapのデータをコンテナ環境変数として定義します。ConfigMapからのキーがPodの環境変数名になります。apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never
Podを作成します:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-envFrom.yaml
すると、Podの出力結果は環境変数SPECIAL_LEVEL=very
とSPECIAL_TYPE=charm
が含まれています。
ConfigMapに環境変数を定義し、Pod specificationのcommand
セクションで$(VAR_NAME)
Kubernetes置換構文を介して使用できます。
例えば以下のPod specificationは
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
以下コマンドの実行で作成され、
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-env-var-valueFrom.yaml
test-container
コンテナで以下の出力結果を表示します:
kubectl logs dapi-test-pod
very charm
ファイルからConfigMapを作成するで説明したように、--from-file
を使用してConfigMapを作成する場合は、ファイル名がConfigMapのdata
セクションに保存されるキーになり、ファイルのコンテンツがキーの値になります。
このセクションの例は以下に示されているspecial-configと名付けれたConfigMapについて言及したものです。
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
ConfigMapを作成します:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
ConfigMap名をPod specificationのvolumes
セクション配下に追加します。
これによりConfigMapデータがvolumeMounts.mountPath
で指定されたディレクトリに追加されます (このケースでは、/etc/config
に)。command
セクションはConfigMapのキーに合致したディレクトリファイルを名前別でリスト表示します。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# コンテナに追加するファイルを含むConfigMapの名前を提供する
name: special-config
restartPolicy: Never
Podを作成します:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume.yaml
Podが稼働していると、ls /etc/config/
は以下の出力結果を表示します:
SPECIAL_LEVEL
SPECIAL_TYPE
/etc/config/
ディレクトリに何かファイルがある場合、それらは削除されます。path
フィールドを利用して特定のConfigMapのアイテム向けに希望のファイルパスを指定します。
このケースではSPECIAL_LEVEL
アイテムが/etc/config/keys
のconfig-volume
ボリュームにマウントされます。
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: SPECIAL_LEVEL
path: keys
restartPolicy: Never
Podを作成します:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume-specific-key.yaml
Podが稼働していると、 cat /etc/config/keys
は以下の出力結果を表示します:
very
/etc/config/
ディレクトリのこれまでのファイルは全て削除されますキーをファイル単位で特定のパスとアクセス許可に投影できます。Secretのユーザーガイドで構文が解説されています。
ボリュームで使用されているConfigMapが更新されている場合、投影されているキーも同じく結果的に更新されます。kubeletは定期的な同期ごとにマウントされているConfigMapが更新されているかチェックします。しかし、これはローカルのttlを基にしたキャッシュでConfigMapの現在の値を取得しています。その結果、新しいキーがPodに投影されてからConfigMapに更新されるまでのトータルの遅延はkubeletで、kubeletの同期期間(デフォルトで1分) + ConfigMapキャッシュのttl(デフォルトで1分)の長さになる可能性があります。Podのアノテーションを1つ更新すると即時のリフレッシュをトリガーできます。
ConfigMap APIリソースは構成情報をキーバリューペアとして保存します。データはPodで利用したり、コントローラーなどのシステムコンポーネントに提供できます。ConfigMapはSecretに似ていますが、機密情報を含まない文字列を含まない操作する手段を提供します。ユーザーとシステムコンポーネントはどちらも構成情報をConfigMapに保存できます。
/etc
ディレクトリとそのコンテンツのように捉えましょう。例えば、Kubernetes VolumeをConfigMapから作成した場合、ConfigMapのデータアイテムはボリューム内で個別のファイルとして表示されます。ConfigMapのdata
フィールドは構成情報を含みます。下記の例のように、シンプルに個別のプロパティーを--from-literal
で定義、または複雑に構成ファイルまたはJSON blobsを--from-file
で定義できます。
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data:
# --from-literalを使用してシンプルにプロパティーを定義する例
example.property.1: hello
example.property.2: world
# --from-fileを使用して複雑にプロパティーを定義する例
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
ConfigMapはPod specificationを参照させる前に作成する必要があります(ConfigMapを"optional"として設定しない限り)。存在しないConfigMapを参照させた場合、Podは起動しません。同様にConfigMapに存在しないキーを参照させた場合も、Podは起動しません。
ConfigMapでenvFrom
を使用して環境変数を定義した場合、無効と判断されたキーはスキップされます。Podは起動されますが、無効な名前はイベントログに(InvalidVariableNames
)と記録されます。ログメッセージはスキップされたキーごとにリスト表示されます。例えば:
kubectl get events
出力結果は以下のようになります:
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
ConfigMapは特定のNamespaceに属します。ConfigMapは同じ名前空間に属するPodからのみ参照できます。
static podsはKubeletがサポートしていないため、ConfigMapに使用できません。
Kubernetes v1.17 [stable]
このページでは、プロセス名前空間を共有するPodを構成する方法を示します。 プロセス名前空間の共有が有効になっている場合、コンテナ内のプロセスは、そのPod内の他のすべてのコンテナに表示されます。
この機能を使用して、ログハンドラーサイドカーコンテナなどの協調コンテナを構成したり、シェルなどのデバッグユーティリティを含まないコンテナイメージをトラブルシューティングしたりできます。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
作業するKubernetesサーバーは次のバージョン以降のものである必要があります: v1.10. バージョンを確認するには次のコマンドを実行してください:kubectl version
.プロセス名前空間の共有は、v1.PodSpec
のshareProcessNamespace
フィールドを使用して有効にします。
例:
クラスターにPod nginx
を作成します:
kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
shell
コンテナにアタッチしてps
を実行します:
kubectl exec -it nginx -c shell -- /bin/sh
コマンドプロンプトが表示されない場合は、Enterキーを押してみてください。
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
14 101 0:00 nginx: worker process
15 root 0:00 sh
21 root 0:00 ps ax
他のコンテナのプロセスにシグナルを送ることができます。
たとえば、ワーカープロセスを再起動するには、SIGHUP
をnginxに送信します。
この操作にはSYS_PTRACE
機能が必要です。
/ # kill -HUP 8
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
/proc/$pid/root
リンクを使用して別のコンテナイメージにアクセスすることもできます。
/ # head /proc/8/root/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
Podは多くのリソースを共有するため、プロセスの名前空間も共有することになります。 ただし、一部のコンテナイメージは他のコンテナから分離されることが期待されるため、これらの違いを理解することが重要です:
コンテナプロセスは PID 1ではなくなります。
一部のコンテナイメージは、PID 1なしで起動することを拒否し(たとえば、systemd
を使用するコンテナ)、kill -HUP 1
などのコマンドを実行してコンテナプロセスにシグナルを送信します。
共有プロセス名前空間を持つPodでは、kill -HUP 1
はPodサンドボックスにシグナルを送ります。(上の例では/pause
)
プロセスはPod内の他のコンテナに表示されます。
これには、引数または環境変数として渡されたパスワードなど、/proc
に表示されるすべての情報が含まれます。
これらは、通常のUnixアクセス許可によってのみ保護されます。
コンテナファイルシステムは、/proc/$pid/root
リンクを介してPod内の他のコンテナに表示されます。
これによりデバッグが容易になりますが、ファイルシステム内の秘密情報はファイルシステムのアクセス許可によってのみ保護されることも意味します。
Static Podとは、APIサーバーが監視せず、特定のノード上のkubeletデーモンによって直接管理されるPodです。コントロールプレーンに管理されるPod(たとえばDeploymentなど)とは異なり、kubeletがそれぞれのstatic Podを監視(および障害時には再起動)します。
Static Podは、常に特定のノード上の1つのKubeletに紐付けられます。
kubeletは、各static Podに対して、自動的にKubernetes APIサーバー上にミラーPodの作成を試みます。つまり、ノード上で実行中のPodはAPIサーバーから検出されますが、APIサーバー自身から制御されることはないということです。
Kubernetesクラスターが必要、かつそのクラスターと通信するためにkubectlコマンドラインツールが設定されている必要があります。 このチュートリアルは、コントロールプレーンのホストとして動作していない少なくとも2つのノードを持つクラスターで実行することをおすすめします。 まだクラスターがない場合、minikubeを使って作成するか、 以下のいずれかのKubernetesプレイグラウンドも使用できます:
バージョンを確認するには次のコマンドを実行してください:kubectl version
.このページの説明では、Podを実行するためにDockerを使用しており、ノード上のOSがFedoraであることを前提としています。他のディストリビューションやKubernetesのインストール方法によっては、操作が異なる場合があります。
static Podは、ファイルシステム上でホストされた設定ファイルまたはウェブ上でホストされた設定ファイルを使用して設定できます。
マニフェストは、JSONまたはYAML形式の標準のPod定義で、特定のディレクトリに置きます。kubeletの設定ファイルの中で、staticPodPath: <ディレクトリの場所>
というフィールドを使用すると、kubeletがこのディレクトリを定期的にスキャンして、YAML/JSONファイルが作成/削除されるたびに、static Podの作成/削除が行われるようになります。指定したディレクトリをスキャンする際、kubeletはドットから始まる名前のファイルを無視することに注意してください。
例として、単純なウェブサーバーをstatic Podとして実行する方法を示します。
static Podを実行したいノードを選択します。この例では、my-node1
です。
ssh my-node1
ディレクトリを選び(ここでは/etc/kubelet.d
とします)、ここにウェブサーバーのPodの定義を置きます。たとえば、/etc/kubelet.d/static-web.yaml
に置きます。
# このコマンドは、kubeletが実行中のノード上で実行してください
mkdir /etc/kubelet.d/
cat <<EOF >/etc/kubelet.d/static-web.yaml
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
EOF
ノード上のkubeletがこのディレクトリを使用するようにするために、--pod-manifest-path=/etc/kubelet.d/
引数を付けてkubeletを実行するように設定します。Fedoraの場合、次の行が含まれるように/etc/kubernetes/kubelet
を編集します。
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --pod-manifest-path=/etc/kubelet.d/"
あるいは、kubeletの設定ファイルに、staticPodPath: <ディレクトリの場所>
フィールドを追加することでも設定できます。
kubeletを再起動します。Fedoraの場合、次のコマンドを実行します。
# このコマンドは、kubeletが実行中のノード上で実行してください
systemctl restart kubelet
kubeletは、--manifest-url=<URL>
引数で指定されたファイルを定期的にダウンロードし、Podの定義が含まれたJSON/YAMLファイルとして解釈します。kubeletは、ファイルシステム上でホストされたマニフェストでの動作方法と同じように、定期的にマニフェストを再取得します。static Podのリスト中に変更が見つかると、kubeletがその変更を適用します。
このアプローチを採用する場合、次のように設定します。
YAMLファイルを作成し、kubeletにファイルのURLを渡せるようにするために、ウェブサーバー上に保存する。
apiVersion: v1
kind: Pod
metadata:
name: static-web
labels:
role: myrole
spec:
containers:
- name: web
image: nginx
ports:
- name: web
containerPort: 80
protocol: TCP
選択したノード上のkubeletを--manifest-url=<manifest-url>
を使用して実行することで、このウェブ上のマニフェストを使用するように設定する。Fedoraの場合、/etc/kubernetes/kubelet
に次の行が含まれるように編集します。
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<マニフェストのURL"
kubeletを再起動する。Fedoraの場合、次のコマンドを実行します。
# このコマンドは、kubeletが実行中のノード上で実行してください
systemctl restart kubelet
kubeletが起動すると、定義されたすべてのstatic Podを起動します。ここまででstatic Podを設定してkubeletを再起動したため、すでに新しいstatic Podが実行中になっているはずです。
次のコマンドを(ノード上で)実行することで、(static Podを含む)実行中のコンテナを確認できます。
# このコマンドは、kubeletが実行中のノード上で実行してください
docker ps
出力は次のようになります。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-node1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c
APIサーバー上では、ミラーPodを確認できます。
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 2m
static Podに付けたラベルはミラーPodに伝搬します。ミラーPodに付けたラベルは、通常のPodと同じようにセレクターなどから利用できます。
もしkubectl
を使用してAPIサーバーからミラーPodを削除しようとしても、kubeletはstatic Podを削除しません。
kubectl delete pod static-web-my-node1
pod "static-web-my-node1" deleted
Podはまだ実行中であることがわかります。
kubectl get pods
NAME READY STATUS RESTARTS AGE
static-web-my-node1 1/1 Running 0 12s
kubeletが実行中のノードに戻り、Dockerコンテナを手動で停止してみることができます。しばらくすると、kubeletが変化に気づき、Podを自動的に再起動することがわかります。
# このコマンドは、kubeletが実行中のノード上で実行してください
docker stop f6d05272b57e # 実際のコンテナIDと置き換えてください
sleep 20
docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ...
実行中のkubeletは設定ディレクトリ(この例では/etc/kubelet.d
)の変更を定期的にスキャンし、このディレクトリ内にファイルが追加/削除されると、Podの追加/削除を行います。
# This assumes you are using filesystem-hosted static Pod configuration
# このコマンドは、kubeletが実行中のノード上で実行してください
#
mv /etc/kubernetes/manifests/static-web.yaml /tmp
sleep 20
docker ps
# You see that no nginx container is running
mv /tmp/static-web.yaml /etc/kubernetes/manifests/
sleep 20
docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago
時には物事がうまくいかないこともあります。このガイドは、それらを正すことを目的としています。
2つのセクションから構成されています:
また、使用しているリリースの既知の問題を確認する必要があります。
もしあなたの問題が上記のどのガイドでも解決されない場合は、Kubernetesコミュニティから助けを得るための様々な方法があります。
本サイトのドキュメントは、様々な疑問に対する答えを提供するために構成されています。
コンセプトでは、Kubernetesのアーキテクチャと各コンポーネントの動作について説明し、セットアップでは、使い始めるための実用的な手順を提供しています。
タスク は、よく使われるタスクの実行方法を示し、 チュートリアルは、実世界の業界特有、またはエンドツーエンドの開発シナリオ、より包括的なウォークスルーとなります。
リファレンスセクションでは、Kubernetes APIやkubectl
などのコマンドラインインターフェース(CLI)に関する詳しいドキュメントが提供されています。
コミュニティの誰かがすでに同じような質問をしている可能性があり、あなたの問題を解決できるかもしれません。 KubernetesチームもKubernetesタグが付けられた投稿を監視しています。 もし役立つ既存の質問がない場合は、新しく質問する前に、あなたの質問がStack Overflowのトピックに沿ったものであることを確認し、新しく質問する方法のガイダンスに目を通してください!
Kubernetesコミュニティの多くの人々は、Kubernetes Slackの#kubernetes-users
チャンネルに集まっています。
Slackは登録が必要です。招待をリクエストすることができ、登録は誰でも可能です。
お気軽にお越しいただき、何でも質問してください。
登録が完了したら、WebブラウザまたはSlackの専用アプリからKubernetes organization in Slackにアクセスします。
登録が完了したら、増え続けるチャンネルリストを見て、興味のある様々なテーマについて調べてみましょう。
たとえば、Kubernetesの初心者は、#kubernetes-novice
に参加してみるのもよいでしょう。
別の例として、開発者は#kubernetes-contributors
チャンネルに参加するとよいでしょう。
また、多くの国別/言語別チャンネルがあります。これらのチャンネルに参加すれば、地域特有のサポートや情報を得ることができます。
Country | Channels |
---|---|
中国 | #cn-users , #cn-events |
フィンランド | #fi-users |
フランス | #fr-users , #fr-events |
ドイツ | #de-users , #de-events |
インド | #in-users , #in-events |
イタリア | #it-users , #it-events |
日本 | #jp-users , #jp-events |
韓国 | #kr-users |
オランダ | #nl-users |
ノルウェー | #norw-users |
ポーランド | #pl-users |
ロシア | #ru-users |
スペイン | #es-users |
スウェーデン | #se-users |
トルコ | #tr-users , #tr-events |
Kubernetesの公式フォーラムへの参加は大歓迎ですdiscuss.kubernetes.io。
バグらしきものを発見した場合、または機能要望を出したい場合、GitHub課題追跡システムをご利用ください。 課題を提出する前に、既存の課題を検索して、あなたの課題が解決されているかどうかを確認してください。
バグを報告する場合は、そのバグを再現するための詳細な情報を含めてください。
kubectl version
このドキュメントには、コンテナ化されたアプリケーションの問題を解決するための、一連のリソースが記載されています。Kubernetesリソース(Pod、Service、StatefulSetなど)に関する一般的な問題や、コンテナ終了メッセージを理解するためのアドバイス、実行中のコンテナをデバッグする方法などが網羅されています。
このガイドは、Kubernetesにデプロイされ、正しく動作しないアプリケーションをユーザーがデバッグするためのものです。 これは、自分のクラスターをデバッグしたい人のためのガイドでは ありません。 そのためには、debug-clusterを確認する必要があります。
トラブルシューティングの最初のステップは切り分けです。何が問題なのでしょうか? Podなのか、レプリケーションコントローラーなのか、それともサービスなのか?
デバッグの第一歩は、Podを見てみることです。 以下のコマンドで、Podの現在の状態や最近のイベントを確認します。
kubectl describe pods ${POD_NAME}
Pod内のコンテナの状態を見てください。
すべてRunning
ですか? 最近、再起動がありましたか?
Podの状態に応じてデバッグを続けます。
PodがPending
で止まっている場合、それはノードにスケジュールできないことを意味します。
一般に、これはある種のリソースが不十分で、スケジューリングできないことが原因です。
上のkubectl describe ...
コマンドの出力を見てください。
なぜあなたのPodをスケジュールできないのか、スケジューラーからのメッセージがあるはずです。 理由は以下の通りです。
リソースが不足しています。 クラスターのCPUまたはメモリーを使い果たしている可能性があります。Podを削除するか、リソースの要求値を調整するか、クラスターに新しいノードを追加する必要があります。詳しくはCompute Resources documentを参照してください。
あなたが使用しているのはhostPort
です。 PodをhostPort
にバインドすると、そのPodがスケジュールできる場所が限定されます。ほとんどの場合、hostPort
は不要なので、Serviceオブジェクトを使ってPodを公開するようにしてください。もしhostPort
が必要な場合は、Kubernetesクラスターのノード数だけPodをスケジュールすることができます。
PodがWaiting
状態で止まっている場合、ワーカーノードにスケジュールされていますが、そのノード上で実行することができません。この場合も、kubectl describe ...
の情報が参考になるはずです。Waiting
状態のPodの最も一般的な原因は、コンテナイメージのプルに失敗することです。
確認すべきことは3つあります。
docker pull <image>
を実行し、イメージをプルできるかどうか確認してください。Podがスケジュールされると、実行中のPodのデバッグで説明されている方法がデバッグに利用できるようになります。
Podが期待した動作をしない場合、ポッドの記述(ローカルマシンの mypod.yaml
ファイルなど)に誤りがあり、Pod作成時にその誤りが黙って無視された可能性があります。Pod記述のセクションのネストが正しくないか、キー名が間違って入力されていることがよくあり、そのようなとき、そのキーは無視されます。たとえば、command
のスペルをcommnd
と間違えた場合、Podは作成されますが、あなたが意図したコマンドラインは使用されません。
まずPodを削除して、--validate
オプションを付けて再度作成してみてください。
例えば、kubectl apply --validate -f mypod.yaml
と実行します。
command
のスペルをcommnd
に間違えると、以下のようなエラーになります。
I0805 10:43:25.129850 46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973 46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod
次に確認することは、apiserver上のPodが、作成しようとしたPod(例えば、ローカルマシンのyamlファイル)と一致しているかどうかです。
例えば、kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml
を実行して、元のポッドの説明であるmypod.yaml
とapiserverから戻ってきたmypod-on-apiserver.yaml
を手動で比較してみてください。
通常、"apiserver" バージョンには、元のバージョンにはない行がいくつかあります。これは予想されることです。
しかし、もし元のバージョンにある行がapiserverバージョンにない場合、これはあなたのPod specに問題があることを示している可能性があります。
レプリケーションコントローラーはかなり単純なものです。
彼らはPodを作ることができるか、できないか、どちらかです。
もしPodを作成できないのであれば、上記の説明を参照して、Podをデバッグしてください。
また、kubectl describe rc ${CONTROLLER_NAME}
を使用すると、レプリケーションコントローラーに関連するイベントを確認することができます。
Serviceは、Podの集合全体でロードバランシングを提供します。 Serviceが正しく動作しない原因には、いくつかの一般的な問題があります。
以下の手順は、Serviceの問題をデバッグするのに役立つはずです。
まず、Serviceに対応するEndpointが存在することを確認します。
全てのServiceオブジェクトに対して、apiserverは endpoints
リソースを利用できるようにします。
このリソースは次のようにして見ることができます。
kubectl get endpoints ${SERVICE_NAME}
EndpointがServiceのメンバーとして想定されるPod数と一致していることを確認してください。 例えば、3つのレプリカを持つnginxコンテナ用のServiceであれば、ServiceのEndpointには3つの異なるIPアドレスが表示されるはずです。
Endpointが見つからない場合は、Serviceが使用しているラベルを使用してPodをリストアップしてみてください。 ラベルがあるところにServiceがあると想像してください。
...
spec:
- selector:
name: nginx
type: frontend
セレクタに一致するPodを一覧表示するには、次のコマンドを使用します。
kubectl get pods --selector=name=nginx,type=frontend
リストがServiceを提供する予定のPodと一致することを確認します。
PodのcontainerPort
がServiceのtargetPort
と一致することを確認します。
詳しくはServiceのデバッグを参照してください。
上記のいずれの方法でも問題が解決しない場合は、以下の手順に従ってください。
Serviceのデバッグに関するドキュメントで、Service
が実行されていること、Endpoints
があること、Pods
が実際にサービスを提供していること、DNSが機能していること、IPtablesルールがインストールされていること、kube-proxyが誤作動を起こしていないようなことを確認してください。
トラブルシューティングドキュメントに詳細が記載されています。
新規にKubernetesをインストールした環境でかなり頻繁に発生する問題は、Serviceが適切に機能しないというものです。Deployment(または他のワークロードコントローラー)を通じてPodを実行し、サービスを作成したにもかかわらず、アクセスしようとしても応答がありません。何が問題になっているのかを理解するのに、このドキュメントがきっと役立つでしょう。
ここでの多くのステップでは、クラスターで実行されているPodが見ているものを確認する必要があります。これを行う最も簡単な方法は、インタラクティブなalpineのPodを実行することです。
kubectl run -it --rm --restart=Never alpine --image=alpine sh
使用したい実行中のPodがすでにある場合は、以下のようにしてそのPod内でコマンドを実行できます。
kubectl exec <POD-NAME> -c <CONTAINER-NAME> -- <COMMAND>
このドキュメントのウォークスルーのために、いくつかのPodを実行しましょう。おそらくあなた自身のServiceをデバッグしているため、あなた自身の詳細に置き換えることもできますし、これに沿って2番目のデータポイントを取得することもできます。
kubectl create deployment hostnames --image=registry.k8s.io/serve_hostname
deployment.apps/hostnames created
kubectl
コマンドは作成、変更されたリソースのタイプと名前を出力するため、この後のコマンドで使用することもできます。
Deploymentを3つのレプリカにスケールさせてみましょう。
kubectl scale deployment hostnames --replicas=3
deployment.apps/hostnames scaled
これは、次のYAMLでDeploymentを開始した場合と同じです。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostnames
labels:
app: hostnames
spec:
selector:
matchLabels:
app: hostnames
replicas: 3
template:
metadata:
labels:
app: hostnames
spec:
containers:
- name: hostnames
image: registry.k8s.io/serve_hostname
"app"ラベルはkubectl create deployment
によって、Deploymentの名前に自動的にセットされます。
Podが実行されていることを確認できます。
kubectl get pods -l app=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 2m
hostnames-632524106-ly40y 1/1 Running 0 2m
hostnames-632524106-tlaok 1/1 Running 0 2m
Podが機能していることも確認できます。Pod IP アドレスリストを取得し、直接テストできます。
kubectl get pods -l app=hostnames \
-o go-template='{{range .items}}{{.status.podIP}}{{"\n"}}{{end}}'
10.244.0.5
10.244.0.6
10.244.0.7
このウォークスルーに使用されるサンプルコンテナは、ポート9376でHTTPを介して独自のホスト名を提供するだけですが、独自のアプリをデバッグする場合は、Podがリッスンしているポート番号を使用する必要があります。
Pod内から実行します。
for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do
wget -qO- $ep
done
次のように表示されます。
hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok
この時点で期待通りの応答が得られない場合、Podが正常でないか、想定しているポートでリッスンしていない可能性があります。なにが起きているかを確認するためにkubectl logs
が役立ちます。Podに直接に入りデバッグする場合はkubectl exec
が必要になります。
これまでにすべての計画が完了していると想定すると、Serviceが機能しない理由を調査することができます。
賢明な読者は、Serviceをまだ実際に作成していないことにお気付きかと思いますが、これは意図的です。これは時々忘れられるステップであり、最初に確認すべきことです。
存在しないServiceにアクセスしようとするとどうなるでしょうか?このServiceを名前で利用する別のPodがあると仮定すると、次のような結果が得られます。
wget -O- hostnames
Resolving hostnames (hostnames)... failed: Name or service not known.
wget: unable to resolve host address 'hostnames'
最初に確認するのは、そのServiceが実際に存在するかどうかです。
kubectl get svc hostnames
No resources found.
Error from server (NotFound): services "hostnames" not found
Serviceを作成しましょう。前と同様に、これはウォークスルー用です。ご自身のServiceの詳細を使用することもできます。
kubectl expose deployment hostnames --port=80 --target-port=9376
service/hostnames exposed
そして、念のため内容を確認します。
kubectl get svc hostnames
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hostnames ClusterIP 10.0.1.175 <none> 80/TCP 5s
これで、Serviceが存在することがわかりました。
前と同様に、これは次のようなYAMLでServiceを開始した場合と同じです。
apiVersion: v1
kind: Service
metadata:
name: hostnames
spec:
selector:
app: hostnames
ports:
- name: default
protocol: TCP
port: 80
targetPort: 9376
構成の全範囲をハイライトするため、ここで作成したServiceはPodとは異なるポート番号を使用します。多くの実際のServiceでは、これらのポートは同じになる場合があります。
クライアントがサービスを使用する最も一般的な方法の1つは、DNS名を使用することです。同じNamespaceのPodから次のコマンドを実行してください。
nslookup hostnames
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: hostnames
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local
これが失敗した場合、おそらくPodとServiceが異なるNamespaceにあるため、ネームスペースで修飾された名前を試してください。(Podの中からもう一度)
nslookup hostnames.default
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: hostnames.default
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local
これが機能する場合、クロスネームスペース名を使用するようにアプリケーションを調整するか、同じNamespaceでアプリとServiceを実行する必要があります。これでも失敗する場合は、完全修飾名を試してください。
nslookup hostnames.default.svc.cluster.local
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: hostnames.default.svc.cluster.local
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local
ここでのサフィックス"default.svc.cluster.local"に注意してください。"default"は、操作しているNamespaceです。"svc"は、これがServiceであることを示します。"cluster.local"はクラスタードメインであり、あなたのクラスターでは異なる場合があります。
クラスター内のノードからも試すこともできます。
nslookup hostnames.default.svc.cluster.local 10.0.0.10
Server: 10.0.0.10
Address: 10.0.0.10#53
Name: hostnames.default.svc.cluster.local
Address: 10.0.1.175
完全修飾名では検索できるのに、相対名ではできない場合、Podの/etc/resolv.conf
ファイルが正しいことを確認する必要があります。Pod内から実行します。
cat /etc/resolv.conf
次のように表示されます。
nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local example.com
options ndots:5
nameserver行はクラスターのDNS Serviceを示さなければなりません。これは、--cluster-dns
フラグでkubelet
に渡されます。
search
行には、Service
名を見つけるための適切なサフィックスを含める必要があります。この場合、ローカルのNamespace
でService
を見つけるためのサフィックス(default.svc.cluster.local
)、すべてのNamespaces
でService
を見つけるためのサフィックス(svc.cluster.local
)、およびクラスターのサフィックス(cluster.local
)です。インストール方法によっては、その後に追加のレコードがある場合があります(合計6つまで)。クラスターのサフィックスは、--cluster-domain
フラグを使用してkubelet
に渡されます。このドキュメントではそれが"cluster.local"であると仮定していますが、あなたのクラスターでは異なる場合があります。その場合は、上記のすべてのコマンドでクラスターのサフィックスを変更する必要があります。
options
行では、DNSクライアントライブラリーが検索パスをまったく考慮しないようにndots
を十分に高く設定する必要があります。Kubernetesはデフォルトでこれを5に設定します。これは、生成されるすべてのDNS名をカバーするのに十分な大きさです。
上記がまだ失敗する場合、DNSルックアップがServiceに対して機能していません。一歩離れて、他の何が機能していないかを確認しましょう。KubernetesマスターのServiceは常に機能するはずです。Pod内から実行します。
nslookup kubernetes.default
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes.default
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local
これが失敗する場合は、このドキュメントのkube-proxyセクションを参照するか、このドキュメントの先頭に戻って最初からやり直してください。ただし、あなた自身のServiceをデバッグするのではなく、DNSサービスをデバッグします。
DNSサービスが正しく動作できると仮定すると、次にテストするのはIPによってServiceが動作しているかどうかです。上述のkubectl get
で確認できるIPに、クラスター内のPodからアクセスします。
for i in $(seq 1 3); do
wget -qO- 10.0.1.175:80
done
次のように表示されます。
hostnames-0uton
hostnames-bvc05
hostnames-yp2kp
Serviceが機能している場合は、正しい応答が得られるはずです。そうでない場合、おかしい可能性のあるものがいくつかあるため、続けましょう。
馬鹿げているように聞こえるかもしれませんが、Serviceが正しく定義されPodのポートとマッチすることを二度、三度と確認すべきです。Serviceを読み返して確認しましょう。
kubectl get service hostnames -o json
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "hostnames",
"namespace": "default",
"uid": "428c8b6c-24bc-11e5-936d-42010af0a9bc",
"resourceVersion": "347189",
"creationTimestamp": "2015-07-07T15:24:29Z",
"labels": {
"app": "hostnames"
}
},
"spec": {
"ports": [
{
"name": "default",
"protocol": "TCP",
"port": 80,
"targetPort": 9376,
"nodePort": 0
}
],
"selector": {
"app": "hostnames"
},
"clusterIP": "10.0.1.175",
"type": "ClusterIP",
"sessionAffinity": "None"
},
"status": {
"loadBalancer": {}
}
}
spec.ports[]
のリストのなかに定義されていますか?targetPort
はPodに対して適切ですか(いくつかのPodはServiceとは異なるポートを使用します)?targetPort
を数値で定義しようとしている場合、それは数値(9376)、文字列"9376"のどちらですか?targetPort
を名前で定義しようとしている場合、Podは同じ名前でポートを公開していますか?protocol
はPodに適切ですか?ここまで来たということは、Serviceは正しく定義され、DNSによって名前解決できることが確認できているでしょう。ここでは、実行したPodがServiceによって実際に選択されていることを確認しましょう。
以前に、Podが実行されていることを確認しました。再確認しましょう。
kubectl get pods -l app=hostnames
NAME READY STATUS RESTARTS AGE
hostnames-632524106-bbpiw 1/1 Running 0 1h
hostnames-632524106-ly40y 1/1 Running 0 1h
hostnames-632524106-tlaok 1/1 Running 0 1h
-l app=hostnames
引数はラベルセレクターで、ちょうど私たちのService
に定義されているものと同じです。
"AGE"列は、これらのPodが約1時間前のものであることを示しており、それらが正常に実行され、クラッシュしていないことを意味します。
"RESTARTS"列は、これらのポッドが頻繁にクラッシュしたり、再起動されていないことを示しています。頻繁に再起動すると、断続的な接続性の問題が発生する可能性があります。再起動回数が多い場合は、ポッドをデバッグするを参照してください。
Kubernetesシステム内には、すべてのServiceのセレクターを評価し、結果をEndpointsオブジェクトに保存するコントロールループがあります。
kubectl get endpoints hostnames
NAME ENDPOINTS
hostnames 10.244.0.5:9376,10.244.0.6:9376,10.244.0.7:9376
これにより、EndpointsコントローラーがServiceの正しいPodを見つけていることを確認できます。ENDPOINTS
列が<none>
の場合、Serviceのspec.selector
フィールドが実際にPodのmetadata.labels
値を選択していることを確認する必要があります。よくある間違いは、タイプミスやその他のエラー、たとえばDeployment作成にもkubectl run
が使われた1.18以前のバージョンのように、Serviceがapp=hostnames
を選択しているのにDeploymentがrun=hostnames
を指定していることです。
この時点で、Serviceが存在し、Podを選択していることがわかります。このウォークスルーの最初に、Pod自体を確認しました。Podが実際に機能していることを確認しましょう。Serviceメカニズムをバイパスして、上記EndpointsにリストされているPodに直接アクセスすることができます。
Pod内から実行します。
for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do
wget -qO- $ep
done
次のように表示されます。
hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok
Endpointsリスト内の各Podは、それぞれの自身のホスト名を返すはずです。そうならない(または、あなた自身のPodの正しい振る舞いにならない)場合は、そこで何が起こっているのかを調査する必要があります。
ここに到達したのなら、Serviceは実行され、Endpointsがあり、Podが実際にサービスを提供しています。この時点で、Serviceのプロキシメカニズム全体が疑わしいです。ひとつひとつ確認しましょう。
Serviceのデフォルト実装、およびほとんどのクラスターで使用されるものは、kube-proxyです。kube-proxyはそれぞれのノードで実行され、Serviceの抽象化を提供するための小さなメカニズムセットの1つを構成するプログラムです。クラスターがkube-proxyを使用しない場合、以下のセクションは適用されず、使用しているServiceの実装を調査する必要があります。
kube-proxy
がノード上で実行されていることを確認しましょう。ノードで実行されていれば、以下のような結果が得られるはずです。
ps auxw | grep kube-proxy
root 4194 0.4 0.1 101864 17696 ? Sl Jul04 25:43 /usr/local/bin/kube-proxy --master=https://kubernetes-master --kubeconfig=/var/lib/kube-proxy/kubeconfig --v=2
次に、マスターとの接続など、明らかな失敗をしていないことを確認します。これを行うには、ログを確認する必要があります。ログへのアクセス方法は、ノードのOSに依存します。一部のOSでは/var/log/kube-proxy.logのようなファイルですが、他のOSではjournalctl
を使用してログにアクセスします。次のように表示されます。
I1027 22:14:53.995134 5063 server.go:200] Running in resource-only container "/kube-proxy"
I1027 22:14:53.998163 5063 server.go:247] Using iptables Proxier.
I1027 22:14:53.999055 5063 server.go:255] Tearing down userspace rules. Errors here are acceptable.
I1027 22:14:54.038140 5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns-tcp" to [10.244.1.3:53]
I1027 22:14:54.038164 5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns" to [10.244.1.3:53]
I1027 22:14:54.038209 5063 proxier.go:352] Setting endpoints for "default/kubernetes:https" to [10.240.0.2:443]
I1027 22:14:54.038238 5063 proxier.go:429] Not syncing iptables until Services and Endpoints have been received from master
I1027 22:14:54.040048 5063 proxier.go:294] Adding new service "default/kubernetes:https" at 10.0.0.1:443/TCP
I1027 22:14:54.040154 5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns" at 10.0.0.10:53/UDP
I1027 22:14:54.040223 5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns-tcp" at 10.0.0.10:53/TCP
マスターに接続できないことに関するエラーメッセージが表示された場合、ノードの設定とインストール手順をダブルチェックする必要があります。
kube-proxy
が正しく実行できない理由の可能性の1つは、必須のconntrack
バイナリが見つからないことです。これは、例えばKubernetesをスクラッチからインストールするなど、クラスターのインストール方法に依存して、一部のLinuxシステムで発生する場合があります。これが該当する場合は、conntrack
パッケージを手動でインストール(例: Ubuntuではsudo apt install conntrack
)する必要があり、その後に再試行する必要があります。
kube-proxyは、いくつかのモードのいずれかで実行できます。上記のログのUsing iptables Proxier
という行は、kube-proxyが「iptables」モードで実行されていることを示しています。最も一般的な他のモードは「ipvs」です。古い「ユーザースペース」モードは、主にこれらに置き換えられました。
「iptables」モードでは、ノードに次のようなものが表示されます。
iptables-save | grep hostnames
-A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376
-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR
各サービスのポートごとに、KUBE-SERVICES
に1つのルールと1つのKUBE-SVC- <hash>
チェーンが必要です。Podエンドポイントごとに、そのKUBE-SVC- <hash>
に少数のルールがあり、少数のルールが含まれる1つのKUBE-SEP- <hash>
チェーンがあるはずです。正確なルールは、正確な構成(NodePortとLoadBalancerを含む)に基づいて異なります。
「ipvs」モードでは、ノードに次のようなものが表示されます。
ipvsadm -ln
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
...
TCP 10.0.1.175:80 rr
-> 10.244.0.5:9376 Masq 1 0 0
-> 10.244.0.6:9376