DaemonSet は全て(またはいくつか)のNodeが単一のPodのコピーを稼働させることを保証します。Nodeがクラスターに追加されるとき、PodがNode上に追加されます。Nodeがクラスターから削除されたとき、それらのPodはガーベージコレクターにより除去されます。DaemonSetの削除により、DaemonSetが作成したPodもクリーンアップします。
DaemonSetのいくつかの典型的な使用例は以下の通りです。
glusterdやcephのようなクラスターのストレージデーモンを各Node上で稼働させる。fluentdやlogstashのようなログ集計デーモンを各Node上で稼働させる。collectd、Dynatrace OneAgent、 AppDynamics Agent、 Datadog agent、 New Relic agent、GangliaのgmondやInstana agentなどのようなNodeのモニタリングデーモンを各Node上で稼働させる。シンプルなケースとして、各タイプのデーモンにおいて、全てのNodeをカバーする1つのDaemonSetが使用されるケースがあります。 さらに複雑な設定では、単一のタイプのデーモン用ですが、異なるフラグや、異なるハードウェアタイプに対するメモリー、CPUリクエストを要求する複数のDaemonSetを使用するケースもあります。
ユーザーはYAMLファイル内でDaemonSetの設定を記述することができます。
例えば、下記のdaemonset.yamlファイルではfluentd-elasticsearchというDockerイメージを稼働させるDaemonSetの設定を記述します。
controllers/daemonset.yaml
|
|---|
|
YAMLファイルに基づいてDaemonSetを作成します。
kubectl apply -f https://k8s.io/examples/controllers/daemonset.yaml
他の全てのKubernetesの設定と同様に、DaemonSetはapiVersion、kindとmetadataフィールドが必須となります。
設定ファイルの活用法に関する一般的な情報は、アプリケーションのデプロイ、コンテナの設定、kuberctlを用いたオブジェクトの管理といったドキュメントを参照ください。
また、DaemonSetにおいて.specセクションも必須となります。
.spec.templateは.spec内での必須のフィールドの1つです。
.spec.templateはPodテンプレートとなります。これはフィールドがネストされていて、apiVersionやkindをもたないことを除いては、Podのテンプレートと同じスキーマとなります。
Podに対する必須のフィールドに加えて、DaemonSet内のPodテンプレートは適切なラベルを指定しなくてはなりません(Podセレクターの項目を参照ください)。
DaemonSet内のPodテンプレートでは、RestartPolicyフィールドを指定せずにデフォルトのAlwaysを使用するか、明示的にAlwaysを設定するかのどちらかである必要があります。
.spec.selectorフィールドはPodセレクターとなります。これはJobの.spec.selectorと同じものです。
Kubernetes1.8のように、ユーザーは.spec.templateのラベルにマッチするPodセレクターを指定しなくてはいけません。Podセレクターは、値を空のままにしてもデフォルト設定にならなくなりました。セレクターのデフォルト化はkubectl applyと互換性はありません。また、一度DaemonSetが作成されると、その.spec.selectorは変更不可能になります。Podセレクターの変更は、意図しないPodの孤立を引き起こし、ユーザーにとってやっかいなものとなります。
.spec.selectorは2つのフィールドからなるオブジェクトです。
matchLabels - ReplicationControllerの.spec.selectorと同じように機能します。matchExpressions - キーと、値のリストとさらにはそれらのキーとバリューに関連したオペレーターを指定することにより、より洗練された形式のセレクターを構成できます。上記の2つが指定された場合は、2つの条件をANDでどちらも満たすものを結果として返します。
もしspec.selectorが指定されたとき、.spec.template.metadata.labelsとマッチしなければなりません。この2つの値がマッチしない設定をした場合、APIによってリジェクトされます。
また、ユーザーは通常、DaemonSetやReplicaSetのような他のコントローラーを使用するか直接かによらず、このセレクターとマッチするラベルを持つPodを作成すべきではありません。 さもないと、DaemonSetコントローラーが、それらのPodがDaemonSetによって作成されたものと扱われてしまいます。Kubernetesはユーザーがこれを行うことを止めることはありません。ユーザーがこれを行いたい1つのケースとしては、テストのためにNode上に異なる値をもったPodを手動で作成するような場合があります。
もしユーザーが.spec.template.spec.nodeSelectorを指定したとき、DaemonSetコントローラーは、そのnode
selectorにマッチするPodをNode上に作成します。
同様に、もし.spec.template.spec.affinityを指定したとき、DaemonSetコントローラーはnode affinityマッチするPodをNode上に作成します。
もしユーザーがどちらも指定しないとき、DaemonSetコントローラーは全てのNode上にPodを作成します。
通常、Podが稼働するマシンはKubernetesスケジューラーによって選択されます。
しかし、DaemonSetコントローラーによって作成されたPodは既に選択されたマシンを持っています(.spec.nodeNameはPodの作成時に指定され、Kubernetesスケジューラーによって無視されます)。
従って:
unschedulableフィールドはDaemonSetコントローラーによって尊重されません。Kubernetes v1.16
beta
beta がつきます(例:v2beta3)。DaemonSetは全ての利用可能なNodeが単一のPodのコピーを稼働させることを保証します。通常、Podが稼働するNodeはKubernetesスケジューラーによって選択されます。しかし、DaemonSetのPodは代わりにDaemonSetコントローラーによって作成され、スケジューリングされます。
下記の問題について説明します:
Pending状態となりますが、DaemonSetのPodはPending状態で作成されません。これはユーザーにとって困惑するものです。ScheduleDaemonSetPodsは、DaemonSetのPodに対してNodeAffinity項目を追加することにより、DaemonSetコントローラーの代わりにデフォルトスケジューラーを使ってDaemonSetのスケジュールを可能にします。その際に、デフォルトスケジューラーはPodをターゲットのホストにバインドします。もしDaemonSetのNodeAffinityが存在するとき、それは新しいものに置き換えられます。DaemonSetコントローラーはDaemonSetのPodの作成や修正を行うときのみそれらの操作を実施します。そしてDaemonSetの.spec.templateフィールドに対しては何も変更が加えられません。
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchFields:
- key: metadata.name
operator: In
values:
- target-host-nameさらに、node.kubernetes.io/unschedulable:NoScheduleというtolarationがDaemonSetのPodに自動的に追加されます。デフォルトスケジューラーは、DaemonSetのPodのスケジューリングのときに、unschedulableなNodeを無視します。
DaemonSetのPodはTaintsとTolerationsの設定を尊重します。
下記のTolerationsは、関連する機能によって自動的にDaemonSetのPodに追加されます。
| Toleration Key | Effect | Version | Description |
|---|---|---|---|
node.kubernetes.io/not-ready |
NoExecute | 1.13+ | DaemonSetのPodはネットワーク分割のようなNodeの問題が発生したときに除外されません。 |
node.kubernetes.io/unreachable |
NoExecute | 1.13+ | DaemonSetのPodはネットワーク分割のようなNodeの問題が発生したときに除外されません。 |
node.kubernetes.io/disk-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/memory-pressure |
NoSchedule | 1.8+ | |
node.kubernetes.io/unschedulable |
NoSchedule | 1.12+ | DaemonSetのPodはデフォルトスケジューラーによってスケジュール不可能な属性を許容(tolerate)します。 |
node.kubernetes.io/network-unavailable |
NoSchedule | 1.12+ | ホストネットワークを使うDaemonSetのPodはデフォルトスケジューラーによってネットワーク利用不可能な属性を許容(tolerate)します。 |
DaemonSet内のPodとのコミュニケーションをする際に考えられるパターンは以下の通りです。:
hostPortを使用できます。慣例により、クライアントはNodeIPのリストとポートを知っています。endpointsリソースを使ってDaemonSetを探すか、DNSから複数のAレコードを取得します。もしNodeラベルが変更されたとき、そのDaemonSetは直ちに新しくマッチしたNodeにPodを追加し、マッチしなくなったNodeからPodを削除します。
ユーザーはDaemonSetが作成したPodを修正可能です。しかし、Podは全てのフィールドの更新を許可していません。また、DaemonSetコントローラーは次のNode(同じ名前でも)が作成されたときにオリジナルのテンプレートを使ってPodを作成します。
ユーザーはDaemonSetを削除可能です。もしkubectlコマンドで--cascade=falseを指定したとき、DaemonSetのPodはNode上で残り続けます。そしてユーザーは異なるテンプレートを使って新しいDaemonSetを作成可能です。
異なるテンプレートを使った新しいDaemonSetは、マッチしたラベルを持っている全ての存在しているPodを認識します。DaemonSetはPodのテンプレートがミスマッチしていたとしても、それらのPodを修正もしくは削除をしません。
ユーザーはPodもしくはNodeの削除によって新しいPodの作成を強制する必要があります。
Kubernetes1.6とそれ以降のバージョンでは、ユーザーはDaemonSet上でローリングアップデートの実施が可能です。
Node上で直接起動することにより(例: init、upstartd、systemdを使用する)、デーモンプロセスを稼働することが可能です。この方法は非常に良いですが、このようなプロセスをDaemonSetを介して起動することはいくつかの利点があります。
kubectl)を使える。特定のNode上で稼働するように指定したPodを直接作成することは可能です。しかし、DaemonSetはNodeの故障やNodeの破壊的なメンテナンスやカーネルのアップグレードなど、どのような理由に限らず、削除されたもしくは停止されたPodを置き換えます。このような理由で、ユーザーはPod単体を作成するよりもむしろDaemonSetを使うべきです。
Kubeletによって監視されているディレクトリに対してファイルを書き込むことによって、Podを作成することが可能です。これは静的Podと呼ばれます。
DaemonSetと違い、静的Podはkubectlや他のKubernetes APIクライアントで管理できません。静的PodはApiServerに依存しておらず、クラスターの自立起動時に最適です。また、静的Podは将来的には廃止される予定です。
DaemonSetは、Podの作成し、そのPodが停止されることのないプロセスを持つことにおいてDeploymentと同様です(例: webサーバー、ストレージサーバー)。
フロントエンドのようなServiceのように、どのホスト上にPodが稼働するか制御するよりも、レプリカ数をスケールアップまたはスケールダウンしたりローリングアップデートする方が重要であるような、状態をもたないServiceに対してDeploymentを使ってください。 Podのコピーが全てまたは特定のホスト上で常に稼働していることが重要な場合や、他のPodの前に起動させる必要があるときにDaemonSetを使ってください。
このページは役に立ちましたか?
Thanks for the feedback. If you have a specific, answerable question about how to use Kubernetes, ask it on Stack Overflow. Open an issue in the GitHub repo if you want to 問題を報告する or 改善を提案.