体はドクペで出来ている

インフラ、Goの割合が多い技術ブログ

Kubernetesのオブジェクト管理手法に関する公式ドキュメントを読解

始めに

本記事はKubernetes Object Managementから読み取ったことをなるべく自分の言葉として書き下し最後に所感を加えたものです。原文に書かれていない意訳的表現が多数含まれ、少なくとも翻訳記事ではありません。

前書きと警告

KubernetesのCLI管理ツールkubectlはいくつかの異なったアプローチでKubernetesオブジェクトを管理することができる。

Kubernetesのオブジェクト(Pods, Service, Deployments, etc...)は単一に管理される必要があり、複数の方法且つ重複したタイミングで同一のオブジェクトに干渉した場合は予期しない動作を引き起こす恐れがある。

管理手法の一覧

名前 操作方法 推奨される管理対象の環境 学習難易度
命令的コマンド オブジェクトをコマンドにより直接操作 検証環境
命令的オブジェクト設定 オブジェクト定義ファイル+命令で操作 商用環境
宣言的オブジェクト設定 複数のオブジェクト定義をディレクトリにまとめ一斉に反映 商用環境

命令的コマンド

kubectlコマンドの引数・フラグによりKubernetesオブジェクトを直接操作するやり方。変更履歴の管理等に支障を来す恐れがあるため、主に入門段階や検証環境の操作を行う場合に使用する。

命令的コマンドを使ってnginxインスタンスを作る例

$ kubectl run nginx --image nginx

  • 命令的オブジェクト設定と比較したメリット
    • コマンドがシンプル・簡単で学習コストが低い
    • コマンド1発で操作が完結する
  • 命令的オブジェクト設定と比較したデメリット
    • レビュー等の管理・監査プロセスを通さず操作できてしまう
    • 今現在稼働しているオブジェクトに関する情報しか参照できない
    • テンプレートを使ったオブジェクトの作成ができず再現性が低い

命令的オブジェクト設定

これはオブジェクトを定義したYAML/JSONファイルをkubectlで適用するやり方であり、そのオブジェクトをどう操作するか(create, replace, etc...)という命令を含めたコマンドとなる。命令の内replaceには注意を要する部分があり、これは既存のオブジェクトを全く新しいものに置き換えることになるためファイルに記した設定内容とは別の動的な要素がサービスに影響するオブジェクトに関しては使ってはいけない。例えばロードバランサー系のサービスではトラフィックの窓口となるIPアドレスが変更されてしまう。

命令的オブジェクト設定を使ってnginxインスタンスを作る例

$ kubectl create -f nging.yaml

命令的オブジェクト設定を使ってnginxとredisのインスタンスを削除する例

$ kubectl delete -f nging.yaml -f redis.yaml

命令的オブジェクト設定を使ってnginxインスタンスを差し替える例

$ kubectl replace -f nging.yaml

  • 命令的コマンドと比較したメリット
    • 設定内容をgit等により変更管理することができる
    • レビュー等の管理・監査プロセスに乗せることができる
    • テンプレートから新しいオブジェクトを作成でき再現性が高い
  • 命令的コマンドと比較したデメリット

    • 基本的なオブジェクトの記述方法を学習する必要がある
    • 設定を行う場合にYAMLファイルを作成するステップが追加で必要になる
  • 宣言的オブジェクト設定と比較したメリット

    • 簡単で学習コストが低い
  • 宣言的オブジェクト設定と比較したデメリット
    • ファイル単位の管理であり、関連する複数のオブジェクトをディレクトリ単位で管理することができない
    • 稼働中のオブジェクトの設定が直接変更された場合は自分でYAMLに反映させなければならない(或いはそれを無視して次回の操作で変更内容が失われることを甘受する)

宣言的オブジェクト設定

ローカルにあるオブジェクト設定ファイルを適用するという面では命令的オブジェクト設定と同じだが、操作の内容(create, replace, etc...)について定義する必要が無く、対象のディレクトリに収められた各オブジェクトの設定内容と現在のクラスターの状態を自動的に比較しその差分を反映させる。命令的オブジェクトと違い、オブジェクトが直接変更された場合にそれをファイルに反映させない場合でもその内容は維持される。これはPatch的動作をするAPIにより操作されるためで、Replace的な全体の置き換えではないからである。

宣言的オブジェクト設定を使って設定を反映させる例

$ kubectl apply -f configs/

  • 命令的オブジェクト設定と比較したメリット
    • オブジェクトが直接変更された場合にそれをファイルに反映させなくても設定が維持される
    • 各オブジェクトにどのような動作が必要となるか自動的に検出されるので指定が不要
  • 命令的オブジェクト設定と比較したデメリット
    • 具体的な動作を想定しづらいためデバッグに労力が必要

所感

命令的コマンド・オブジェクト設定と宣言的オブジェクト設定の違いについてですが、私はこのドキュメントを読んで「現在の状態を意識した操作が必要か否か」というところが最大の違いであると認識しました。命令的な設定の場合「(現状がxxxだから……)yyyな操作をしろ」という形の命令であり前提を考慮したオペレーションが必要になりますが、宣言的な設定であれば「とにかくこの状態にしてくれ」という考え方で済みます。

実際に試してみると$ kubectl create -f nginx.yamlというコマンドを実行した場合、既にオブジェクトが存在する場合はエラーになります。同様に存在しないオブジェクトに対してdeleteを行った場合もエラーになりますし、upsert的な動きを期待してreplaceを行った場合もやはりエラーになります。

宣言的設定はコンテナクラスターの設定でAnsibleのような冪等性を実現しており、前提条件の考慮が不要なので積極的に使うべきだと思います。特にCI/CDを組む場合にはこういった考慮は面倒なのでとても助かるでしょう。

公式ドキュメントを読み込んだことでKubernetesの管理について大分イメージが湧いてきましたので、今後はCI等も含めた運用フローを検証して行きたいと思います。