ワークロードの管理
アプリケーションをデプロイし、Serviceを介して公開しました。次に何をすべきでしょうか? Kubernetesには、スケーリングや更新など、アプリケーションのデプロイメントを管理するためのいくつかのツールが用意されています。
リソース構成の整理
多くのアプリケーションでは、Serviceに加えてDeploymentなどの複数のリソースを作成する必要があります。複数のリソースを管理しやすくするために、同じファイル内にまとめて記述することができます(YAMLでは---
で区切ります)。例えば、以下のように定義します。
apiVersion: v1
kind: Service
metadata:
name: my-nginx-svc
labels:
app: nginx
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
複数のリソースは、単一のリソースと同じ方法で作成できます。
kubectl apply -f https://k8s.io/examples/application/nginx-app.yaml
service/my-nginx-svc created
deployment.apps/my-nginx created
リソースはマニフェスト内に記述された順番で作成されます。したがって、Serviceを先に指定するのが望ましいです。これにより、DeploymentなどのコントローラーによってPodが作成される際に、スケジューラーがServiceに関連付けられたPodを適切に分散できるようになります。
また、kubectl apply
は複数の-f
引数を受け付けます。
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-svc.yaml \
-f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
同じマイクロサービスやアプリケーションの階層に関連するリソースは、同じファイルにまとめることが推奨されます。また、アプリケーションに関連するすべてのファイルを同じディレクトリに整理することで、管理しやすくなります。アプリケーションの各階層がDNSを使用して相互に接続される場合、スタックのすべてのコンポーネントをまとめてデプロイできます。
さらに、設定ソースとしてURLを指定することも可能です。これにより、ソース管理システム内のマニフェストから直接デプロイする際に便利です。
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created
さらに、ConfigMapを追加するなど、追加のマニフェストを定義することも可能です。
外部ツール
このセクションでは、Kubernetes上でワークロードを管理するために一般的に使用されるツールのみを紹介します。 より多くのツールの一覧については、CNCF Landscapeの アプリケーション定義とイメージビルドを参照してください。
Helm
Helmは、あらかじめ設定されたKubernetesリソースのパッケージを管理するためのツールです。これらのパッケージは Helmチャート と呼ばれます。
Kustomize
Kustomizeは、Kubernetesのマニフェストを処理し、設定オプションを追加・削除・更新するツールです。Kustomizeは単独のバイナリとして利用できるほか、kubectlのネイティブ機能としても利用できます。
kubectlにおける一括操作
リソースの作成だけがkubectl
による一括操作の対象ではありません。設定ファイルからリソース名を抽出し、他の操作を実行することも可能です。特に、作成したリソースを削除する際に利用できます。
kubectl delete -f https://k8s.io/examples/application/nginx-app.yaml
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
2つのリソースを対象とする場合、resource/nameの構文を使って、両方のリソースをコマンドラインで指定することができます。
kubectl delete deployments/my-nginx services/my-nginx-svc
さらに多数のリソースを扱う場合は、-l
または--selector
を使用してラベルによるフィルタリング(ラベルクエリ)を行う方が簡単です。
kubectl delete deployment,services -l app=nginx
deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
チェーン処理とフィルタリング
kubectl
は、受け入れるのと同じ構文でリソース名を出力するため、$()
やxargs
を使用して操作を連結できます。
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/)
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/ | xargs -i kubectl get '{}'
出力は次のようになります。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx-svc LoadBalancer 10.0.0.208 <pending> 80/TCP 0s
上記のコマンドでは、まずexamples/application/nginx/
内のリソースを作成し、-o name
出力形式を使用して作成されたリソースを出力します(各リソースをresource/nameの形式で出力します)。次にgrep
を使ってServiceのみを抽出し、それをkubectl get
で表示します。
ローカルファイルに対する再帰的操作
特定のディレクトリ内でリソースを複数のサブディレクトリに整理している場合、--filename
/-f
引数とともに--recursive
または-R
を指定することで、サブディレクトリ内のリソースにも再帰的に操作を実行できます。
例えば、開発環境に必要なすべての マニフェスト を保持し、リソースの種類ごとに整理されたproject/k8s/development
というディレクトリがあるとします。
project/k8s/development
├── configmap
│ └── my-configmap.yaml
├── deployment
│ └── my-deployment.yaml
└── pvc
└── my-pvc.yaml
デフォルトでは、project/k8s/development
に対して一括操作を実行すると、ディレクトリの最上位レベルで処理が止まり、サブディレクトリ内のリソースは処理されません。そのため、以下のコマンドを使用してこのディレクトリ内のリソースを作成しようとすると、エラーが発生します。
kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)
その代わりに、--filename
/-f
引数とともに--recursive
または-R
を指定してください。
kubectl apply -f project/k8s/development --recursive
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
--recursive
引数は、--filename
/-f
引数を受け付けるすべての操作で使用できます。例えば、kubectl create
、kubectl get
、kubectl delete
、kubectl describe
、kubectl rollout
などに適用できます。
また、--recursive
引数は、複数の-f
引数が指定された場合にも機能します。
kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
namespace/development created
namespace/staging created
configmap/my-config created
deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
kubectl
について詳しく知りたい場合は、コマンドラインツール(kubectl)を参照してください。
アプリケーションをダウンタイムなしで更新する
デプロイ済みのアプリケーションは、いずれ更新が必要になります。通常は、新しいイメージまたはイメージタグを指定することで更新を行います。kubectl
には、さまざまな更新操作が用意されており、それぞれ異なるシナリオに適用できます。
アプリケーションの複数のコピーを実行し、ロールアウト を使用して新しい正常なPodへ段階的にトラフィックを移行することで、ダウンタイムなしの更新が可能です。最終的には、すべての実行中のPodが新しいソフトウェアへ更新されます。
このセクションでは、Deploymentを使用してアプリケーションを作成し、更新する方法について説明します。
例えば、nginxのバージョン1.14.2を実行しているとします。
kubectl create deployment my-nginx --image=nginx:1.14.2
deployment.apps/my-nginx created
1つのレプリカが存在することを確認します。
kubectl scale --replicas 1 deployments/my-nginx --subresource='scale' --type='merge' -p '{"spec":{"replicas": 1}}'
deployment.apps/my-nginx scaled
そして、ロールアウト時にKubernetesが一時的なレプリカをより多く追加できるようにするため、最大サージ を100%に設定します。
kubectl patch --type='merge' -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge": "100%" }}}}'
deployment.apps/my-nginx patched
バージョン1.16.1へ更新するには、.spec.template.spec.containers[0].image
をnginx:1.14.2
からnginx:1.16.1
に変更します。kubectl edit
を使用してマニフェストを編集します。
kubectl edit deployment/my-nginx
# 新しいコンテナイメージを使用するようにマニフェストを変更し、変更を保存
以上で完了です!Deploymentは、デプロイされたnginxアプリケーションを宣言的に更新し、バックグラウンドで段階的に処理を進めます。これにより、更新中に一定数の古いレプリカのみが停止され、新しいレプリカが必要なPod数を超えて作成されることがないように制御されます。この仕組みの詳細については、Deploymentを参照してください。
ロールアウトは、DaemonSet、Deployment、StatefulSetに対して使用できます。
ロールアウトの管理
kubectl rollout
を使用すると、既存のアプリケーションの段階的な更新を管理できます。
例えば、次のように実行できます。
kubectl apply -f my-deployment.yaml
# ロールアウトの完了を待機
kubectl rollout status deployment/my-deployment --timeout 10m # 10分のタイムアウト
または、次のように実行できます。
kubectl apply -f backing-stateful-component.yaml
# ロールアウトの完了を待たず、ステータスのみを確認
kubectl rollout status statefulsets/backing-stateful-component --watch=false
さらに、ロールアウトを一時停止、再開、または取り消すことも可能です。
詳細については、kubectl rollout
を参照してください。
カナリアデプロイ
複数のラベルが必要となる別のシナリオとして、同じコンポーネントの異なるリリースや設定を区別する場合があります。 一般的な方法として、新しいアプリケーションリリース(Podテンプレート内のイメージタグで指定)を、以前のリリースと並行してカナリアデプロイすることがあります。これにより、新しいリリースが本番環境のトラフィックを受け取りつつ、完全にロールアウトする前に動作を確認できます。
例えば、track
ラベルを使用して異なるリリースを区別することができます。
プライマリの安定したリリースには、track
ラベルの値としてstable
を設定します。
name: frontend
replicas: 3
...
labels:
app: guestbook
tier: frontend
track: stable
...
image: gb-frontend:v3
その後、track
ラベルの値を異なる値(例:canary
)に設定した新しいguestbook frontendのリリースを作成することで、2つのPodセットが重ならないようにすることができます。
name: frontend-canary
replicas: 1
...
labels:
app: guestbook
tier: frontend
track: canary
...
image: gb-frontend:v4
フロントエンドのServiceは、両方のレプリカセットにまたがるように、共通のラベルの部分集合(つまり、track
ラベルを省略)を選択することで、トラフィックを両方のアプリケーションに振り分けることができます。
selector:
app: guestbook
tier: frontend
stableリリースとcanaryリリースのレプリカ数を調整することで、それぞれのリリースが本番トラフィックを受け取る割合(この例では、3:1)を決定できます。新しいリリースに十分な自信が持てたら、stableトラックを新しいアプリケーションリリースに更新し、canaryリリースを削除します。
アノテーションの更新
リソースにアノテーションを付与したい場合があります。
アノテーションは、ツールやライブラリなどのAPIクライアントが取得できる、識別情報ではない任意のメタデータです。
これを行うには、kubectl annotate
を使用します。例えば、次のように実行できます。
kubectl annotate pods my-nginx-v4-9gw19 description='my frontend running nginx'
kubectl get pods my-nginx-v4-9gw19 -o yaml
apiVersion: v1
kind: pod
metadata:
annotations:
description: my frontend running nginx
...
詳細については、アノテーションおよびkubectl annotateを参照してください。
アプリケーションのスケーリング
アプリケーションの負荷が増減した際には、kubectl
を使用してスケーリングを行うことができます。
例えば、nginxのレプリカ数を3から1に減らすには、次のように実行します。
kubectl scale deployment/my-nginx --replicas=1
deployment.apps/my-nginx scaled
これで、Deploymentによって管理されるPodは1つだけになりました。
kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
my-nginx-2035384211-j5fhi 1/1 Running 0 30m
システムに必要に応じてnginxのレプリカ数(1~3の範囲)を自動的に選択させるには、次のコマンドを実行します。
# これには、コンテナおよびPodのメトリクスの取得元が必要です
kubectl autoscale deployment/my-nginx --min=1 --max=3
horizontalpodautoscaler.autoscaling/my-nginx autoscaled
これで、nginxのレプリカ数は必要に応じて自動的にスケールアップおよびスケールダウンされます。
詳しくは、kubectl scale、kubectl autoscale、および水平Pod自動スケーリングのドキュメントを参照してください。
リソースのインプレース更新
作成したリソースに対して、小規模で影響の少ない更新を行う必要がある場合があります。
kubectl apply
構成ファイルのセットをソース管理下で管理すること(構成のコード化を参照)が推奨されています。これにより、構成対象のリソースのコードとともに、構成を保守・バージョン管理することができます。その後、kubectl apply
を使用して、構成の変更をクラスターに反映できます。
このコマンドは、適用しようとしている設定のバージョンと、以前のバージョンを比較し、変更を適用します。指定していないプロパティに対する自動的な変更は上書きされません。
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured
基盤となる仕組みについて詳しく知りたい場合は、server-side applyを参照してください。
kubectl edit
あるいは、kubectl edit
を使用してリソースを更新することもできます。
kubectl edit deployment/my-nginx
これは、まずリソースをget
で取得し、テキストエディターで編集した後、更新されたバージョンをapply
で適用するのと同等です。
kubectl get deployment my-nginx -o yaml > /tmp/nginx.yaml
vi /tmp/nginx.yaml
# 何らかの編集を行い、ファイルを保存
kubectl apply -f /tmp/nginx.yaml
deployment.apps/my-nginx configured
rm /tmp/nginx.yaml
これにより、より大きな変更を簡単に行うことができます。
なお、EDITOR
またはKUBE_EDITOR
環境変数を指定することで、使用するエディターを設定できます。
詳しくは、kubectl editを参照してください。
kubectl patch
kubectl patch
を使用すると、APIオブジェクトをインプレースで更新できます。このサブコマンドは、JSONパッチ、JSONマージパッチ、戦略的マージパッチをサポートしています。
詳細については、kubectl patchを使用したAPIオブジェクトのインプレース更新を参照してください。
破壊的な更新
場合によっては、一度初期化されると更新できないリソースのフィールドを変更する必要があることがあります。また、Deploymentによって作成された異常なPodを修正するなど、即座に再帰的な変更を行いたい場合もあります。そのようなフィールドを変更するには、replace --force
を使用します。このコマンドは、リソースを削除し再作成することで変更を適用します。この場合、元の設定ファイルを修正して適用できます。
kubectl replace -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml --force
deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced
次の項目
このページの項目は、Kubernetesが必要とする機能を提供するサードパーティー製品またはプロジェクトです。Kubernetesプロジェクトの作者は、それらのサードパーティー製品またはプロジェクトに責任を負いません。詳しくは、CNCFウェブサイトのガイドラインをご覧ください。第三者のリンクを追加するような変更を提案する前に、コンテンツガイドを読むべきです。