これは、このセクションの複数ページの印刷可能なビューです。 印刷するには、ここをクリックしてください.
Kubernetesオブジェクトを利用する
1 - Kubernetesオブジェクトを理解する
このページでは、KubernetesオブジェクトがKubernetes APIでどのように表現されているか、またそれらを.yaml
フォーマットでどのように表現するかを説明します。
Kubernetesオブジェクトを理解する
Kubernetesオブジェクト は、Kubernetes上で永続的なエンティティです。Kubernetesはこれらのエンティティを使い、クラスターの状態を表現します。具体的に言うと、下記のような内容が表現できます:
- どのようなコンテナ化されたアプリケーションが稼働しているか(またそれらはどのノード上で動いているか)
- それらのアプリケーションから利用可能なリソース
- アプリケーションがどのように振る舞うかのポリシー、例えば再起動、アップグレード、耐障害性ポリシーなど
Kubernetesオブジェクトは「意図の記録」です。一度オブジェクトを作成すると、Kubernetesは常にそのオブジェクトが存在し続けるように動きます。オブジェクトを作成することで、Kubernetesに対し効果的にあなたのクラスターのワークロードがこのようになっていて欲しいと伝えているのです。これが、あなたのクラスターの望ましい状態です。
Kubernetesオブジェクトを操作するには、作成、変更、または削除に関わらずKubernetes APIを使う必要があるでしょう。例えばkubectl
コマンドラインインターフェースを使った場合、このCLIが処理に必要なKubernetes API命令を、あなたに代わり発行します。あなたのプログラムからクライアントライブラリを利用し、直接Kubernetes APIを利用することも可能です。
オブジェクトのspec(仕様)とstatus(状態)
ほとんどのKubernetesオブジェクトは、オブジェクトの設定を管理する2つの入れ子になったオブジェクトのフィールドを持っています。それはオブジェクト spec
とオブジェクト status
です。spec
を持っているオブジェクトに関しては、オブジェクト作成時にspec
を設定する必要があり、望ましい状態としてオブジェクトに持たせたい特徴を記述する必要があります。
status
オブジェクトはオブジェクトの 現在の状態 を示し、その情報はKubernetesシステムとそのコンポーネントにより提供、更新されます。Kubernetesコントロールプレーンは、あなたから指定された望ましい状態と現在の状態が一致するよう常にかつ積極的に管理をします。
例えば、KubernetesのDeploymentはクラスター上で稼働するアプリケーションを表現するオブジェクトです。Deploymentを作成するとき、アプリケーションの複製を3つ稼働させるようDeploymentのspecで指定するかもしれません。KubernetesはDeploymentのspecを読み取り、指定されたアプリケーションを3つ起動し、現在の状態がspecに一致するようにします。もしこれらのインスタンスでどれかが落ちた場合(statusが変わる)、Kubernetesはspecと、statusの違いに反応し、修正しようとします。この場合は、落ちたインスタンスの代わりのインスタンスを立ち上げます。
spec、status、metadataに関するさらなる情報は、Kubernetes API Conventionsをご確認ください。
Kubernetesオブジェクトを記述する
Kubernetesでオブジェクトを作成する場合、オブジェクトの基本的な情報(例えば名前)と共に、望ましい状態を記述したオブジェクトのspecを渡さなければいけません。KubernetesAPIを利用しオブジェクトを作成する場合(直接APIを呼ぶか、kubectl
を利用するかに関わらず)、APIリクエストはそれらの情報をJSON形式でリクエストのBody部に含んでいなければなりません。
ここで、KubernetesのDeploymentに必要なフィールドとオブジェクトのspecを記載した.yaml
ファイルの例を示します:
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
上に示した.yaml
ファイルを利用してDeploymentを作成するには、kubectl
コマンドラインインターフェースに含まれているkubectl apply
コマンドに.yaml
ファイルを引数に指定し、実行します。ここで例を示します:
kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record
出力結果は、下記に似た形になります:
deployment.apps/nginx-deployment created
必須フィールド
Kubernetesオブジェクトを.yaml
ファイルに記載して作成する場合、下記に示すフィールドに値をセットしておく必要があります:
apiVersion
- どのバージョンのKubernetesAPIを利用してオブジェクトを作成するかkind
- どの種類のオブジェクトを作成するかmetadata
- オブジェクトを一意に特定するための情報、文字列のname
、UID
、また任意のnamespace
が該当するspec
- オブジェクトの望ましい状態
spec
の正確なフォーマットは、Kubernetesオブジェクトごとに異なり、オブジェクトごとに特有な入れ子のフィールドを持っています。Kubernetes API リファレンスが、Kubernetesで作成できる全てのオブジェクトに関するspecのフォーマットを探すのに役立ちます。
例えば、Pod
オブジェクトに関するspec
のフォーマットはPodSpec v1 coreを、またDeployment
オブジェクトに関するspec
のフォーマットはDeploymentSpec v1 appsをご確認ください。
次の項目
- 最も重要、かつ基本的なKubernetesオブジェクト群を学びましょう、例えば、Podです。
- Kubernetesのコントローラーを学びましょう。
- Using the Kubernetes APIはこのページでは取り上げていない他のAPIについて説明します。
2 - Kubernetesオブジェクト管理
kubectl
コマンドラインツールは、Kubernetesオブジェクトを作成、管理するためにいくつかの異なる方法をサポートしています。
このドキュメントでは、それらの異なるアプローチごとの概要を提供します。
Kubectlを使ったオブジェクト管理の詳細は、Kubectl bookを参照してください。
管理手法
管理手法 | 何を対象にするか | 推奨環境 | サポートライター | 学習曲線 |
---|---|---|---|---|
命令型コマンド | 現行のオブジェクト | 開発用プロジェクト | 1+ | 緩やか |
命令型オブジェクト設定 | 個々のファイル | 本番用プロジェクト | 1 | 中程度 |
宣言型オブジェクト設定 | ファイルのディレクトリ | 本番用プロジェクト | 1+ | 急 |
命令型コマンド
命令型コマンドを使う場合、ユーザーはクラスター内の現行のオブジェクトに対して処理を行います。
ユーザーはkubectl
コマンドに処理内容を引数、もしくはフラグで指定します。
これはKubernetesの使い始め、またはクラスターに対して一度限りのタスクを行う際の最も簡単な手法です。 なぜなら、この手法は現行のオブジェクトに対して直接操作ができ、以前の設定履歴は提供されないからです。
例
Deploymentオブジェクトを作成し、nginxコンテナの単一インスタンスを起動します:
kubectl run nginx --image nginx
同じことを異なる構文で行います:
kubectl create deployment nginx --image nginx
トレードオフ
オブジェクト設定手法に対する長所:
- コマンドは簡潔、簡単に学ぶことができ、そして覚えやすいです
- コマンドではクラスタの設定を変えるのに、わずか1ステップしか必要としません
オブジェクト設定手法に対する短所:
- コマンドは変更レビュープロセスと連携しません
- コマンドは変更に伴う監査証跡を提供しません
- コマンドは現行がどうなっているかという情報を除き、レコードのソースを提供しません
- コマンドはオブジェクトを作成するためのテンプレートを提供しません
命令型オブジェクト設定
命令型オブジェクト設定では、kubectlコマンドに処理内容(create、replaceなど)、任意のフラグ、そして最低1つのファイル名を指定します。 指定されたファイルは、YAMLまたはJSON形式でオブジェクトの全ての定義情報を含んでいなければいけません。
オブジェクト定義の詳細は、APIリファレンスを参照してください。
replace
コマンドは、既存の構成情報を新しく提供された設定に置き換え、設定ファイルに無いオブジェクトの全ての変更を削除します。
このアプローチは、構成情報が設定ファイルとは無関係に更新されるリソースタイプでは使用しないでください。
例えば、タイプがLoadBalancer
のServiceオブジェクトにおけるexternalIPs
フィールドは、設定ファイルとは無関係に、クラスターによって更新されます。例
設定ファイルに定義されたオブジェクトを作成します:
kubectl create -f nginx.yaml
設定ファイルに定義されたオブジェクトを削除します:
kubectl delete -f nginx.yaml -f redis.yaml
設定ファイルに定義された情報で、現行の設定を上書き更新します:
kubectl replace -f nginx.yaml
トレードオフ
命令型コマンド手法に対する長所:
- オブジェクト設定をGitのような、ソースコード管理システムに格納することができます
- オブジェクト設定の変更内容をプッシュする前にレビュー、監査証跡を残すようなプロセスと連携することができます
- オブジェクト設定は新しいオブジェクトを作る際のテンプレートを提供します
命令型コマンド手法に対する短所:
- オブジェクト設定ではオブジェクトスキーマの基礎的な理解が必要です
- オブジェクト設定ではYAMLファイルを書くという、追加のステップが必要です
宣言型オブジェクト設定手法に対する長所:
- 命令型オブジェクト設定の振る舞いは、よりシンプルで簡単に理解ができます
- Kubernetesバージョン1.5においては、命令型オブジェクト設定の方がより成熟しています
宣言型オブジェクト設定手法に対する短所:
- 命令型オブジェクト設定は各ファイルごとに設定を書くには最も適していますが、ディレクトリには適していません
- 現行オブジェクトの更新は設定ファイルに対して反映しなければなりません。反映されない場合、次の置き換え時に更新内容が失われてしまいます
宣言型オブジェクト設定
宣言型オブジェクト設定を利用する場合、ユーザーはローカルに置かれている設定ファイルを操作します。
しかし、ユーザーはファイルに対する操作内容を指定しません。作成、更新、そして削除といった操作はオブジェクトごとにkubectl
が検出します。
この仕組みが、異なるオブジェクトごとに異なる操作をディレクトリに対して行うことを可能にしています。
replace
API操作のように、全てのオブジェクト設定を置き換えるわけではなく、patch
API操作による、変更箇所のみの更新が可能にしています。例
config
ディレクトリ配下にある全てのオブジェクト設定ファイルを処理し、作成、または現行オブジェクトへのパッチを行います。
まず、diff
でどのような変更が行われるかを確認した後に適用します:
kubectl diff -f configs/
kubectl apply -f configs/
再帰的にディレクトリを処理します:
kubectl diff -R -f configs/
kubectl apply -R -f configs/
トレードオフ
命令型オブジェクト設定手法に対する長所:
- 現行オブジェクトに直接行われた変更が、それらが設定ファイルに反映されていなかったとしても、保持されます
- 宣言型オブジェクト設定は、ディレクトリごとの処理をより良くサポートしており、自動的にオブジェクトごとに操作のタイプ(作成、パッチ、削除)を検出します
命令型オブジェクト設定手法に対する短所:
- 宣言型オブジェクト設定は、デバッグ、そして想定外の結果が出たときに理解するのが困難です
- 差分を利用した一部のみの更新は、複雑なマージ、パッチの操作が必要です
次の項目
3 - オブジェクトの名前とID
クラスター内の各オブジェクトには、そのタイプのリソースに固有の名前があります。すべてのKubernetesオブジェクトには、クラスター全体で一意のUIDもあります。
たとえば、同じ名前空間内にmyapp-1234
という名前のPodは1つしか含められませんが、myapp-1234
という名前の1つのPodと1つのDeploymentを含めることができます。
ユーザーが一意ではない属性を付与するために、Kubernetesはラベルとアノテーションを提供しています。
名前
クライアントから提供され、リソースURL内のオブジェクトを参照する文字列です。例えば/api/v1/pods/何らかの名前
のようになります。
同じ種類のオブジェクトは、同じ名前を同時に持つことはできません。しかし、オブジェクトを削除することで、旧オブジェクトと同じ名前で新しいオブジェクトを作成できます。
次の3つの命名規則がよく使われます。
DNSサブドメイン名
ほとんどのリソースタイプには、RFC 1123で定義されているDNSサブドメイン名として使用できる名前が必要です。 つまり、名前は次のとおりでなければなりません:
- 253文字以内
- 英小文字、数字、「-」または「.」のみを含む
- 英数字で始まる
- 英数字で終わる
DNSラベル名
一部のリソースタイプでは、RFC 1123で定義されているDNSラベル標準に従う名前が必要です。 つまり、名前は次のとおりでなければなりません:
- 63文字以内
- 英小文字、数字または「-」のみを含む
- 英数字で始まる
- 英数字で終わる
パスセグメント名
一部のリソースタイプでは、名前をパスセグメントとして安全にエンコードできるようにする必要があります。 つまり、名前を「.」や「..」にすることはできず、名前に「/」または「%」を含めることはできません。
以下は、nginx-demo
という名前のPodのマニフェストの例です。
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
UID
オブジェクトを一意に識別するためのKubernetesが生成する文字列です。
Kubernetesクラスターの生存期間中にわたって生成された全てのオブジェクトは、異なるUIDを持っています。これは類似のエンティティの、同一時間軸での存在を区別するのが目的です。
Kubernetes UIDは、UUIDのことを指します。 UUIDは、ISO/IEC 9834-8およびITU-T X.667として標準化されています。
次の項目
- Kubernetesのラベルについてお読みください。
- Kubernetesの識別子と名前デザインドキュメントをご覧ください。
4 - Namespace(名前空間)
Kubernetesは、同一の物理クラスター上で複数の仮想クラスターの動作をサポートします。 この仮想クラスターをNamespaceと呼びます。
複数のNamespaceを使う時
Namespaceは、複数のチーム・プロジェクトにまたがる多くのユーザーがいる環境での使用を目的としています。 数人から数十人しかユーザーのいないクラスターに対して、あなたはNamespaceを作成したり、考える必要は全くありません。 Kubernetesが提供するNamespaceの機能が必要となった時に、Namespaceの使用を始めてください。
Namespaceは名前空間のスコープを提供します。リソース名は単一のNamespace内ではユニークである必要がありますが、Namespace全体ではその必要はありません。Namespaceは相互にネストすることはできず、各Kubernetesリソースは1つのNamespaceにのみ存在できます。
Namespaceは、複数のユーザーの間でクラスターリソースを分割する方法です。(これはリソースクォータを介して分割します。)
同じアプリケーションの異なるバージョンなど、少し違うリソースをただ分割するだけに、複数のNamespaceを使う必要はありません。 同一のNamespace内でリソースを区別するためにはラベルを使用してください。
Namespaceを利用する
Namespaceの作成と削除方法はNamespaceの管理ガイドドキュメントに記載されています。
kube-
を持つNamespaceは、KubernetesシステムのNamespaceとして予約されているため利用は避けてください。Namespaceの表示
ユーザーは、以下の方法で単一クラスター内の現在のNamespaceの一覧を表示できます。
kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-node-lease Active 1d
kube-system Active 1d
kube-public Active 1d
Kubernetesの起動時には4つの初期Namespaceが作成されています。
default
他にNamespaceを持っていないオブジェクトのためのデフォルトNamespacekube-system
Kubernetesシステムによって作成されたオブジェクトのためのNamespacekube-public
このNamespaceは自動的に作成され、全てのユーザーから読み取り可能です。(認証されていないユーザーも含みます。) このNamespaceは、リソースをクラスター全体を通じてパブリックに表示・読み取り可能にするため、ほとんどクラスターによって使用される用途で予約されます。 このNamespaceのパブリックな側面は単なる慣例であり、要件ではありません。kube-node-lease
クラスターのスケールに応じたノードハートビートのパフォーマンスを向上させる各ノードに関連したLeaseオブジェクトのためのNamespace。
Namespaceの設定
現在のリクエストのNamespaceを設定するには、--namespace
フラグを使用します。
例:
kubectl run nginx --image=nginx --namespace=<insert-namespace-name-here>
kubectl get pods --namespace=<insert-namespace-name-here>
Namespace設定の永続化
ユーザーはあるコンテキストのその後のコマンドで使うために、コンテキスト内で永続的にNamespaceを保存できます。
kubectl config set-context --current --namespace=<insert-namespace-name-here>
# Validate it
kubectl config view --minify | grep namespace:
NamespaceとDNS
ユーザーがServiceを作成するとき、Serviceは対応するDNSエントリを作成します。
このエントリは<service-name>.<namespace-name>.svc.cluster.local
という形式になり、これはもしあるコンテナがただ<service-name>
を指定していた場合、Namespace内のローカルのServiceに対して名前解決されます。
これはデベロップメント、ステージング、プロダクションといった複数のNamespaceをまたいで同じ設定を使う時に効果的です。
もしユーザーがNamespaceをまたいでアクセスしたい時、 完全修飾ドメイン名(FQDN)を指定する必要があります。
すべてのオブジェクトはNamespaceに属しているとは限らない
ほとんどのKubernetesリソース(例えば、Pod、Service、ReplicationControllerなど)はいくつかのNamespaceにあります。 しかしNamespaceのリソースそれ自体は単一のNamespace内にありません。 そしてNodeやPersistentVolumeのような低レベルのリソースはどのNamespaceにも属していません。
どのKubernetesリソースがNamespaceに属しているか、属していないかを見るためには、以下のコマンドで確認できます。
# Namespaceに属しているもの
kubectl api-resources --namespaced=true
# Namespaceに属していないもの
kubectl api-resources --namespaced=false
次の項目
- 新しいNamespaceの作成について学習してください。
- Namespaceの削除について学習してください。
5 - ラベル(Labels)とセレクター(Selectors)
ラベル(Labels) はPodなどのオブジェクトに割り当てられたキーとバリューのペアです。
ラベルはユーザーに関連した意味のあるオブジェクトの属性を指定するために使われることを目的としています。しかしKubernetesのコアシステムに対して直接的にその意味を暗示するものではありません。
ラベルはオブジェクトのサブセットを選択し、グルーピングするために使うことができます。また、ラベルはオブジェクトの作成時に割り当てられ、その後いつでも追加、修正ができます。
各オブジェクトはキーとバリューのラベルのセットを定義できます。各キーは、単一のオブジェクトに対してはユニークである必要があります。
"metadata": {
"labels": {
"key1" : "value1",
"key2" : "value2"
}
}
ラベルは効率的な検索・閲覧を可能にし、UIやCLI上での利用に最適です。 識別用途でない情報は、アノテーションを用いて記録されるべきです。
ラベルを使う動機
ラベルは、クライアントにそのマッピング情報を保存することを要求することなく、ユーザー独自の組織構造をシステムオブジェクト上で疎結合にマッピングできます。
サービスデプロイメントとバッチ処理のパイプラインは多くの場合、多次元のエンティティとなります(例: 複数のパーティション、Deployment、リリーストラック、ティアー、ティアー毎のマイクロサービスなど)
管理は分野横断的な操作が必要になることが多く、それによって厳密な階層表現、特にユーザーによるものでなく、インフラストラクチャーによって定義された厳格な階層のカプセル化が破られます。
ラベルの例:
"release" : "stable"
,"release" : "canary"
"environment" : "dev"
,"environment" : "qa"
,"environment" : "production"
"tier" : "frontend"
,"tier" : "backend"
,"tier" : "cache"
"partition" : "customerA"
,"partition" : "customerB"
"track" : "daily"
,"track" : "weekly"
これらは単によく使われるラベルの例です。ユーザーは自由に規約を決めることができます。 ラベルのキーは、ある1つのオブジェクトに対してユニークである必要があることは覚えておかなくてはなりません。
構文と文字セット
ラベルは、キーとバリューのベアです。正しいラベルキーは2つのセグメントを持ちます。
それは/
によって分割されたオプショナルなプレフィックスと名前です。
名前セグメントは必須で、63文字以下である必要があり、文字列の最初と最後は英数字([a-z0-9A-Z]
)で、文字列の間ではこれに加えてダッシュ(-
)、アンダースコア(_
)、ドット(.
)を使うことができます。
プレフィックスはオプションです。もしプレフィックスが指定されていた場合、プレフィックスはDNSサブドメイン形式である必要があり、それはドット(.
)で区切られたDNSラベルのセットで、253文字以下である必要があり、最後にスラッシュ(/
)が続きます。
もしプレフィックスが省略された場合、ラベルキーはそのユーザーに対してプライベートであると推定されます。
エンドユーザーのオブジェクトにラベルを追加するような自動化されたシステムコンポーネント(例: kube-scheduler
kube-controller-manager
kube-apiserver
kubectl
やその他のサードパーティツール)は、プレフィックスを指定しなくてはなりません。
kubernetes.io/
とk8s.io/
プレフィックスは、Kubernetesコアコンポーネントのために予約されています。
正しいラベル値は63文字以下の長さで、空文字か、もしくは開始と終了が英数字([a-z0-9A-Z]
)で、文字列の間がダッシュ(-
)、アンダースコア(_
)、ドット(.
)と英数字である文字列を使うことができます。
例えば、environment: production
とapp: nginx
の2つのラベルを持つPodの設定ファイルは下記のようになります。
apiVersion: v1
kind: Pod
metadata:
name: label-demo
labels:
environment: production
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
ラベルセレクター
名前とUIDとは異なり、ラベルはユニーク性を提供しません。通常、多くのオブジェクトが同じラベルを保持することを想定します。
ラベルセレクター を介して、クライアントとユーザーはオブジェクトのセットを指定できます。ラベルセレクターはKubernetesにおいてコアなグルーピング機能となります。
Kubernetes APIは現在2タイプのセレクターをサポートしています。
それは等価ベース(equality-based) と集合ベース(set-based) です。
単一のラベルセレクターは、コンマ区切りの複数の要件(requirements) で構成されています。
複数の要件がある場合、コンマセパレーターは論理積 AND(&&
)オペレーターと同様にふるまい、全ての要件を満たす必要があります。
空文字の場合や、指定なしのセレクターに関するセマンティクスは、コンテキストに依存します。 そしてセレクターを使うAPIタイプは、それらのセレクターの妥当性とそれらが示す意味をドキュメントに記載するべきです。
||
) オペレーターは存在しません。フィルターステートメントが意図した通りになっていることを確認してください。等価ベース(Equality-based) の要件(requirement)
等価ベース(Equality-based) もしくは不等ベース(Inequality-based) の要件は、ラベルキーとラベル値によるフィルタリングを可能にします。
要件に一致したオブジェクトは、指定されたラベルの全てを満たさなくてはいけませんが、それらのオブジェクトはさらに追加のラベルも持つことができます。
そして等価ベースの要件においては、3つの種類のオペレーターの利用が許可されています。=
、==
、!=
となります。
最初の2つのオペレーター(=
、==
)は等価(Equality) を表現し(この2つは単なる同義語)、最後の1つ(!=
)は不等(Inequality) を意味します。
例えば
environment = production
tier != frontend
最初の例は、キーがenvironment
で、値がproduction
である全てのリソースを対象にします。
次の例は、キーがtier
で、値がfrontend
とは異なるリソースと、tier
という名前のキーを持たない全てのリソースを対象にします。
コンマセパレーター,
を使って、production
の中から、frontend
のものを除外するようにフィルターすることもできます。environment=production,tier!=frontend
等価ベースのラベル要件の1つの使用シナリオとして、PodにおけるNodeの選択要件を指定するケースがあります。
例えば、下記のサンプルPodは、ラベルaccelerator=nvidia-tesla-p100
をもったNodeを選択します。
apiVersion: v1
kind: Pod
metadata:
name: cuda-test
spec:
containers:
- name: cuda-test
image: "k8s.gcr.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1
nodeSelector:
accelerator: nvidia-tesla-p100
集合ベース(Set-based) の要件(requirement)
集合ベース(Set-based) のラベルの要件は値のセットによってキーをフィルタリングします。in
、notin
、exists
の3つのオペレーターをサポートしています(キーを特定するのみ)。
例えば:
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition
- 最初の例では、キーが
environment
で、値がproduction
かqa
に等しいリソースを全て選択します。 - 第2の例では、キーが
tier
で、値がfrontend
とbackend
以外のもの、そしてtier
キーを持たないリソースを全て選択します。 - 第3の例では、
partition
というキーをもつラベルを全て選択し、値はチェックしません。 - 第4の例では、
partition
というキーを持たないラベルを全て選択し、値はチェックしません。
同様に、コンマセパレーターは、AND オペレーターと同様にふるまいます。そのため、partition
とenvironment
キーの値がともにqa
でないラベルを選択するには、partition,environment notin (qa)
と記述することで可能です。
集合ベース のラベルセレクターは、environment=production
という記述がenvironment in (production)
と等しいため、一般的な等価形式となります。 !=
とnotin
も同様に等価となります。
集合ベース の要件は、等価ベース の要件と混在できます。
例えば:partition in (customerA, customerB),environment!=qa
.
API
LISTとWATCHによるフィルタリング
LISTとWATCHオペレーションは、単一のクエリパラメータを使うことによって返されるオブジェクトのセットをフィルターするためのラベルセレクターを指定できます。
集合ベース と等価ベース のどちらの要件も許可されています(ここでは、URLクエリストリング内で出現します)。
- 等価ベース での要件:
?labelSelector=environment%3Dproduction,tier%3Dfrontend
- 集合ベース での要件:
?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29
上記の2つの形式のラベルセレクターはRESTクライアントを介してリストにしたり、もしくは確認するために使われます。
例えば、kubectl
によってapiserver
をターゲットにし、等価ベース の要件でフィルターすると以下のように書けます。
kubectl get pods -l environment=production,tier=frontend
もしくは、集合ベース の要件を指定すると以下のようになります。
kubectl get pods -l 'environment in (production),tier in (frontend)'
すでに言及したように、集合ベース の要件は、等価ベース の要件より表現力があります。
例えば、値に対する OR オペレーターを実装して以下のように書けます。
kubectl get pods -l 'environment in (production, qa)'
もしくは、exists オペレーターを介して、否定マッチングによる制限もできます。
kubectl get pods -l 'environment,environment notin (frontend)'
APIオブジェクトに参照を設定する
Service
と ReplicationController
のような、いくつかのKubernetesオブジェクトでは、ラベルセレクターをPodのような他のリソースのセットを指定するのにも使われます。
ServiceとReplicationController
Service
が対象とするPodの集合は、ラベルセレクターによって定義されます。
同様に、ReplicationController
が管理するべきPod数についてもラベルセレクターを使って定義されます。
それぞれのオブジェクトに対するラベルセレクターはマップを使ってjson
もしくはyaml
形式のファイルで定義され、等価ベース のセレクターのみサポートされています。
"selector": {
"component" : "redis",
}
もしくは
selector:
component: redis
このセレクター(それぞれjson
またはyaml
形式)は、component=redis
またはcomponent in (redis)
と等価です。
集合ベース の要件指定をサポートするリソース
Job
やDeployment
、ReplicaSet
やDaemonSet
などの比較的新しいリソースは、集合ベース での要件指定もサポートしています。
selector:
matchLabels:
component: redis
matchExpressions:
- {key: tier, operator: In, values: [cache]}
- {key: environment, operator: NotIn, values: [dev]}
matchLabels
は、{key,value}
ペアのマップです。matchLabels
内の単一の{key,value}
は、matchExpressions
の要素と等しく、それは、key
フィールドがキー名で、operator
が"In"で、values
配列は単に"値"を保持します。matchExpressions
はPodセレクター要件のリストです。対応しているオペレーターはIn
、NotIn
、Exists
とDoesNotExist
です。values
のセットは、In
とNotIn
オペレーターにおいては空文字を許容しません。matchLabels
とmatchExpressions
の両方によって指定された全ての要件指定はANDで判定されます。つまり要件にマッチするには指定された全ての要件を満たす必要があります。
Nodeのセットを選択する
ラベルを選択するための1つのユースケースはPodがスケジュールできるNodeのセットを制限することです。
さらなる情報に関しては、Node選定 のドキュメントを参照してください。
6 - アノテーション(Annotations)
ユーザーは、識別用途でない任意のメタデータをオブジェクトに割り当てるためにアノテーションを使用できます。ツールやライブラリなどのクライアントは、このメタデータを取得できます。
オブジェクトにメタデータを割り当てる
ユーザーは、Kubernetesオブジェクトに対してラベルやアノテーションの両方またはどちらか一方を割り当てることができます。 ラベルはオブジェクトの選択や、特定の条件を満たしたオブジェクトの集合を探すことに使うことができます。 それと対照的に、アノテーションはオブジェクトを識別、または選択するために使用されません。 アノテーション内のメタデータは大小様々で、構造化されているものや、そうでないものも設定でき、ラベルでは許可されていない文字も含むことができます。
アノテーションは、ラベルと同様に、キーとバリューのマップとなります。
"metadata": {
"annotations": {
"key1" : "value1",
"key2" : "value2"
}
}
下記は、アノテーション内で記録できる情報の例です。
宣言的設定レイヤによって管理されているフィールド。これらのフィールドをアノテーションとして割り当てることで、クライアントもしくはサーバによってセットされたデフォルト値、オートサイジングやオートスケーリングシステムによってセットされたフィールドや、自動生成のフィールドなどと区別することができます。
ビルド、リリースやタイムスタンプのようなイメージの情報、リリースID、gitのブランチ、PR番号、イメージハッシュ、レジストリアドレスなど
ロギング、監視、分析用のポインタ、もしくは監査用リポジトリ
デバッグ目的で使用されるためのクライアントライブラリやツールの情報。例えば、名前、バージョン、ビルド情報など。
他のエコシステムのコンポーネントからの関連オブジェクトのURLなど、ユーザーやツール、システムの出所情報。
軽量ロールアウトツールのメタデータ。 例えば設定やチェックポイントなど。
情報をどこで確認できるかを示すためのもの。例えばチームのウェブサイト、責任者の電話番号や、ページャー番号やディレクトリエンティティなど。
システムのふるまいの変更や、標準ではない機能を利用可能にするために、エンドユーザーがシステムに対して指定する値
アノテーションを使用するかわりに、ユーザーはこのようなタイプの情報を外部のデータベースやディレクトリに保存することもできます。しかし、それによりデプロイ、管理、イントロスペクションを行うためのクライアンライブラリやツールの生成が非常に難しくなります。
構文と文字セット
アノテーション はキーとバリューのペアです。有効なアノテーションのキーの形式は2つのセグメントがあります。
プレフィックス(オプション)と名前で、それらはスラッシュ/
で区切られます。
名前セグメントは必須で、63文字以下である必要があり、文字列の最初と最後は英数字([a-z0-9A-Z]
)と、文字列の間にダッシュ(-
)、アンダースコア(_
)、ドット(.
)を使うことができます。
プレフィックスはオプションです。もしプレフィックスが指定されていた場合、プレフィックスはDNSサブドメイン形式である必要があり、それはドット(.
)で区切られたDNSラベルのセットで、253文字以下である必要があり、最後にスラッシュ(/
)が続きます。
もしプレフィックスが除外された場合、アノテーションキーはそのユーザーに対してプライベートであると推定されます。
エンドユーザーのオブジェクトにアノテーションを追加するような自動化されたシステムコンポーネント(例: kube-scheduler
kube-controller-manager
kube-apiserver
kubectl
やその他のサードパーティツール)は、プレフィックスを指定しなくてはなりません。
kubernetes.io/
とk8s.io/
プレフィックスは、Kubernetesコアコンポーネントのために予約されています。
たとえば、imageregistry: https://hub.docker.com/
というアノテーションが付いたPodの構成ファイルは次のとおりです:
apiVersion: v1
kind: Pod
metadata:
name: annotations-demo
annotations:
imageregistry: "https://hub.docker.com/"
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
次の項目
ラベルとセレクターについて学習してください。
7 - フィールドセレクター(Field Selectors)
フィールドセレクター(Field Selectors) は、1つかそれ以上のリソースフィールドの値を元にKubernetesリソースを選択するためのものです。
フィールドセレクタークエリの例は以下の通りです。
metadata.name=my-service
metadata.namespace!=default
status.phase=Pending
下記のkubectl
コマンドは、status.phase
フィールドの値がRunning
である全てのPodを選択します。
kubectl get pods --field-selector status.phase=Running
kubectl
クエリのkubectl get pods
とkubectl get pods --field-selector ""
が同じであることを意味します。サポートされているフィールド
サポートされているフィールドセレクターはKubernetesリソースタイプによって異なります。全てのリソースタイプはmetadata.name
とmetadata.namespace
フィールドをサポートしています。サポートされていないフィールドセレクターの使用をするとエラーとなります。
例えば以下の通りです。
kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"
サポートされているオペレーター
ユーザーは、=
、==
や!=
といったオペレーターをフィールドセレクターと組み合わせて使用できます。(=
と==
は同義)
例として、下記のkubectl
コマンドはdefault
ネームスペースに属していない全てのKubernetes Serviceを選択します。
kubectl get services --all-namespaces --field-selector metadata.namespace!=default
連結されたセレクター
ラベルや他のセレクターと同様に、フィールドセレクターはコンマ区切りのリストとして連結することができます。
下記のkubectl
コマンドは、status.phase
がRunnning
でなく、かつspec.restartPolicy
フィールドがAlways
に等しいような全てのPodを選択します。
kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always
複数のリソースタイプ
ユーザーは複数のリソースタイプにまたがったフィールドセレクターを利用できます。
下記のkubectl
コマンドは、default
ネームスペースに属していない全てのStatefulSetとServiceを選択します。
kubectl get statefulsets,services --field-selector metadata.namespace!=default
8 - 推奨ラベル(Recommended Labels)
ユーザーはkubectlやダッシュボード以外に、多くのツールでKubernetesオブジェクトの管理と可視化ができます。共通のラベルセットにより、全てのツールにおいて解釈可能な共通のマナーに沿ってオブジェクトを表現することで、ツールの相互運用を可能にします。
ツール化に対するサポートに加えて、推奨ラベルはクエリ可能な方法でアプリケーションを表現します。
メタデータは、アプリケーション のコンセプトを中心に構成されています。KubernetesはPaaS(Platform as a Service)でなく、アプリケーションの公式な概念を持たず、またそれを強制することはありません。 そのかわり、アプリケーションは、非公式で、メタデータによって表現されています。単一のアプリケーションが有する項目に対する定義は厳密に決められていません。
共有されたラベルとアノテーションは、app.kubernetes.io
という共通のプレフィックスを持ちます。プレフィックスの無いラベルはユーザーに対してプライベートなものになります。その共有されたプレフィックスは、共有ラベルがユーザーのカスタムラベルに干渉しないことを保証します。
ラベル
これらの推奨ラベルの利点を最大限得るためには、全てのリソースオブジェクトに対して推奨ラベルが適用されるべきです。
キー | 説明 | 例 | 型 |
---|---|---|---|
app.kubernetes.io/name | アプリケーション名 | mysql | 文字列 |
app.kubernetes.io/instance | アプリケーションのインスタンスを特定するための固有名 | mysql-abcxzy | 文字列 |
app.kubernetes.io/version | アプリケーションの現在のバージョン (例: セマンティックバージョン、リビジョンのハッシュなど) | 5.7.21 | 文字列 |
app.kubernetes.io/component | アーキテクチャ内のコンポーネント | database | 文字列 |
app.kubernetes.io/part-of | このアプリケーションによって構成される上位レベルのアプリケーション | wordpress | 文字列 |
app.kubernetes.io/managed-by | このアプリケーションの操作を管理するために使われているツール | helm | 文字列 |
これらのラベルが実際にどう使われているかを表すために、下記のStatefulSetのオブジェクトを考えましょう。
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/managed-by: helm
アプリケーションとアプリケーションのインスタンス
単一のアプリケーションは、Kubernetesクラスタ内で、いくつかのケースでは同一の名前空間に対して1回または複数回インストールされることがあります。 例えば、WordPressは複数のウェブサイトがあれば、それぞれ別のWordPressが複数回インストールされることがあります。
アプリケーション名と、アプリケーションのインスタンス名はそれぞれ別に記録されます。
例えば、WordPressはapp.kubernetes.io/name
にwordpress
と記述され、インスタンス名に関してはapp.kubernetes.io/instance
にwordpress-abcxzy
と記述されます。この仕組みはアプリケーションと、アプリケーションのインスタンスを特定可能にします。全てのアプリケーションインスタンスは固有の名前を持たなければなりません。
ラベルの使用例
ここでは、ラベルの異なる使用例を示します。これらの例はそれぞれシステムの複雑さが異なります。
シンプルなステートレスサービス
Deployment
とService
オブジェクトを使って、シンプルなステートレスサービスをデプロイするケースを考えます。下記の2つのスニペットはラベルが最もシンプルな形式においてどのように使われるかをあらわします。
下記のDeployment
は、アプリケーションを稼働させるポッドを管理するのに使われます。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
下記のService
は、アプリケーションを公開するために使われます。
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: myservice
app.kubernetes.io/instance: myservice-abcxzy
...
データベースを使ったウェブアプリケーション
次にもう少し複雑なアプリケーションについて考えます。データベース(MySQL)を使ったウェブアプリケーション(WordPress)で、Helmを使ってインストールします。 下記のスニペットは、このアプリケーションをデプロイするために使うオブジェクト設定の出だし部分です。
はじめに下記のDeployment
は、WordPressのために使われます。
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
下記のService
は、WordPressを公開するために使われます。
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: wordpress
app.kubernetes.io/instance: wordpress-abcxzy
app.kubernetes.io/version: "4.9.4"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: server
app.kubernetes.io/part-of: wordpress
...
MySQLはStatefulSet
として公開され、MySQL自身と、MySQLが属する親アプリケーションのメタデータを持ちます。
apiVersion: apps/v1
kind: StatefulSet
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
このService
はMySQLをWordPressアプリケーションの一部として公開します。
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: mysql
app.kubernetes.io/instance: mysql-abcxzy
app.kubernetes.io/version: "5.7.21"
app.kubernetes.io/managed-by: helm
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
...
MySQLのStatefulSet
とService
により、MySQLとWordPressに関するより広範な情報が含まれていることに気づくでしょう。