DUICUO

KubeBuilderの簡潔なチュートリアル

[[398025]]

オペレーターの概要

Operatorは、カスタムリソース管理アプリケーションとそのコンポーネントを活用するKubernetesソフトウェアの拡張機能です。Operatorは、特にコントローラーの実装においてKubernetesの原則に従っています。[^1]

Kubernetesは高度に自動化されたシステムであり、サービスディスカバリ、ロードバランシング、HPAなど、一般的なアプリケーションに必要な機能のほとんどをカバーしています。これらの機能は、Kubernetesに付属するいくつかのコントローラーによって実装されています。しかし、ニーズは常に無限にあります。同様のニーズがあり、Kubernetesでは十分に満たせない場合は、オペレーターとカスタムリソースを使用して同様の効果を実現できます。

一般的な要件には、データベースのデプロイ、ノードメンテナンスの自動化、ログ収集コンポーネントの構成などがあります。

Operatorコンセプトの導入以来、迅速かつ低コストで開発を支援するツールが数多く登場しています。中でも最もよく使われているのは、CoreOSのオープンソースのoperator-sdk[^3]と、k8s sigグループがメンテナンスするkubebuilder[^2]です。本シリーズではkubebuilderを使用します。

始める前に、これから説明する 2 つの中心となる概念を理解しておきましょう。

GV & GVK & GVR

GV: API グループとバージョン

  • API グループは、関連する API 機能のコレクションです。
  • 各グループには1つ以上のバージョンがあります

GVK: グループバージョンの種類

  • 各GVには、Kindと呼ばれるN個のAPIタイプが含まれます。同じKindでも、バージョンによって値が異なる場合があります。

GVR: グループバージョンリソース

  • リソースは、Kind のオブジェクト識別子です。通常、Kind とリソースは 1:1 の関係を持ちますが、1:n の関係を持つ場合もあります。ただし、Operator の場合は常に 1:1 の関係です。

たとえば、Kubernetes の YAML ファイルには、前回の記事でデプロイした nginx デプロイメントのように、通常、次の 2 行が含まれます。

  1. apiVersion: apps/v1 # これは GV です。G はアプリ、V は v1 を表します。
  2. kind: デプロイメント # これは種類です
  3. sepc: # 分散仕様を追加すると、リソースになります。
  4. ...

GVK Kubernetes を使用すると、作成したいリソースの種類を正確に把握できます。定義したスペックに従ってリソースが作成されると、リソース、つまり GVR になります。GVK/GVR は Kubernetes リソースの座標であり、リソースの作成、削除、変更、読み取りの基盤となります[^4]。

KubeBuilder クイックスタートガイド

インストール

公式リポジトリからコンパイル済みのバイナリファイルをダウンロードします: Releases · kubernetes-sigs/kubebuilder (github.com)

  • この記事の執筆時点では、kubebuilder は既にバージョン v3.0.0-rc.0 をリリースしていました。そのため、新しいバージョンの作成が完了したと思ったら既にリリースされていたという厄介な状況を避けるため、この記事ではバージョン 3.0 を直接使用します。
  • ダウンロード後、対応するファイルを PATH に追加することを忘れないでください。

インストールが成功したら、kubebuilder version コマンドを使用して、インストールされたバージョン情報を表示できます。

  1. ❯ kubebuilder バージョン
  2. バージョン: main.version{KubeBuilderVersion: "3.0.0-rc.0" 、KubernetesVendor: "1.19.2" 、GitCommit: "90fe4124c4c6965c6bfac63339888956952cda90" 、BuildDate: "2021-04-08T17:36:28Z" 、GoOs: "linux" 、GoArch: "amd64" }

プロジェクトの初期化

まず、空のフォルダを作成し、そのフォルダ内で次のコマンドを実行します。

  1. kubebuilder init --domain lailin.xyz --repo github.com/mohuishou/blog-code/k8s-operator/02-kubebuilder  
  • --domain lailin.xyz これはプロジェクトのドメイン名です。
  • `--repo xxx` はリポジトリ アドレスを指定します。これは Go モードのリポジトリ アドレスでもあります。

Goのバージョンが低すぎるか高すぎる場合、以下のエラーメッセージが表示されることがあります。私の場合は、バージョン1.16を使用しているため、高すぎるのです。

  1. 2021/04/25 20:47:14プロジェクト初期化失敗しました:事前スキャフォールディングタスクを実行できません  "base.go.kubebuilder.io/v3" : Go バージョン'go1.16'   'requires 1.13 <= version < 1.16'のため互換性がありません。-- skip-go-version-check フラグを使用してこのチェックをスキップできます。  

この場合、エラーを無視するために `--skip-go-version-check` を追加できますが、公式に推奨されているバージョンを使用することをお勧めします。

  1. kubebuilder init --domain lailin.xyz --repo github.com/mohuishou/blog-code/k8s-operator/02-kubebuilder --skip-go-version-check  

プロジェクトディレクトリ

  1. ├── Dockerファイル
  2. ├── Makefile # テストの実行、実行の開始など、多くのスクリプト コマンドを定義します。
  3. ├── PROJECT # これはkubebuilderのメタデータ情報です
  4. ├── 設定
  5. │ ├── default # いくつかのデフォルト設定
  6. │ ├── manager # crd のデプロイに必要な YAML
  7. │ ├── prometheus # メトリックデータ収集を監視するための設定
  8. │ └── rbac # デプロイメントにはRBACライセンスが必要です yaml
  9. ├── go.mod
  10. ├── 行く。合計 
  11. ├── ハック
  12. │ └── ボイラープレート.go.txt
  13. └── main.go

APIを作成する

  1. kubebuilder create api --group apps --version v1 --kind アプリケーション 

実行後、プロジェクト構造が多少変更されたことがわかります。

  1. ├── アピ
  2. │ └── v1
  3. │ ├── application_types.go # ここで仕様が定義されます。
  4. │ ├── groupversion_info.go # GVの定義。通常は変更不要
  5. │ └── zz_generated.deepcopy.go
  6. ├── 設定
  7. │ ├── crd # 自動生成されたcrdファイル。これを変更する必要はありません。v1のgoファイルを変更し、make generateを実行するだけです。
  8. │ ├──デフォルト 
  9. │ ├── マネージャー
  10. │ ├── プロメテウス
  11. │ ├── rbac
  12. │ └── samples # これはクラスターにデプロイするために使用できるサンプル CRD ファイルです。
  13. ├── コントローラー
  14. │ ├── application_controller.go # ここでコントローラーのロジックを実装します
  15. │ └── suite_test.go # ここでテストを記述します。

コントローラーを実装する

CRを定義する

  1. // api/v1/application_types.go
  2.  
  3. //ApplicationSpecはアプリケーション望ましい状態を定義します
  4. アプリケーションスペック構造体型{
  5. //追加の仕様フィールドを挿入-クラスター望ましい状態
  6. // 重要: "make"を実行してください このファイルを変更した後にコードを再生成する
  7.  
  8. // 製品: このアプリケーションが属する製品
  9. 製品文字列 `json: "product,omitempty" `
  10. }

変更を加えた後、「make manifests generate」を実行すると、関連するフィールドが生成され、コード内のフィールドコメントが YAML ファイル内のコメントと同じであることが示されます。

  1. # config/crd/bases/apps.lailin.xyz_applications.yaml
  2. ……
  3. プロパティ:
  4. 製品:
  5. 説明: 製品 このアプリケーションは製品カテゴリに属します。
  6. タイプ: 文字列
  7. ……

コントローラを実装する

KubeBuilder はすでに Operator に必要なロジックの大部分を実装しているので、Reconcile でビジネス ロジックを実装するだけで済みます。

  1. // コントローラー/アプリケーションコントローラー.go
  2.  
  3. func (r *ApplicationReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
  4. _ = r.Log.WithValues( "アプリケーション" , req.NamespacedName)
  5.  
  6. r.Log.Info( "アプリが変更されました" , "ns" , req.Namespace)
  7.  
  8. ctrl.Result{}, nilを返す
  9. }

ロジックを変更した後、最初に `make install` を実行して CRD をインストールし、次に `make run` を実行してコントローラーを実行します。

  1. ./main.go を実行します。
  2. 2021-04-25T21:55:55.578+0800 INFO controller-runtime.metrics メトリクスサーバーが listen開始しています{ " addr" : ":8080" }
  3. 2021-04-25T21:55:55.579+0800 INFO セットアップ開始マネージャー
  4. 2021-04-25T21:55:55.579+0800 INFO controller-runtime.manager メトリクスサーバーを起動しています { "path" : "/metrics" }
  5. 2021-04-25T21:55:55.579+0800 INFO controller-runtime.manager.controller.application 開始イベントソース { "reconciler group" : "apps.lailin.xyz" "reconciler kind" : "Application" "source" : "kind source: /, Kind=" }
  6. 2021-04-25T21:55:55.680+0800 INFO controller-runtime.manager.controller.application コントローラーを起動しています { "reconciler group" : "apps.lailin.xyz" , "reconciler kind" : "Application" }
  7. 2021-04-25T21:55:55.680+0800 INFO controller-runtime.manager.controller.application ワーカーを起動しています { "reconciler group" : "apps.lailin.xyz" "reconciler kind" : "Application" "worker count" : 1}

次に、`kubectl apply -f config/samples/apps_v1_application.yaml` を使用してテスト CRD をデプロイします。

  1. apiバージョン: apps.lailin.xyz/v1
  2. 種類: アプリケーション
  3. メタデータ:
  4. 名前: アプリケーションサンプル
  5. 仕様:
  6. #ここにフィールドを追加
  7. 製品: テスト

すると、先ほど記述したログ記録ロジックがトリガーされたことがわかります。

  1. 2021-04-25T21:57:12.618+0800 INFO controllers.Application アプリが変更されました { "ns" : "default" }

Kubebuilderのノート

生成されたコードには、//+kubebuilder:xxx で始まるコメントが多数あります。Go に精通している方なら、これらのコメントは対応するコードジェネレーターに関するものであることをご存知でしょう。Go では、対応する Go コードを生成するために `go generator` を使用するのが一般的です。

KubeBuilderは、controller-genを使用してコードと対応するYAMLファイルを生成します。これには主に、CRDの生成、検証、処理、そしてWebHooksのRBAC生成が含まれます。以下は簡単な紹介です。完全版については、KubeBuilderの公式ドキュメントをご覧ください。

CRD生成

  • `//+kubebuilder:subresource:status` コメントは `status` サブリソースを有効にします。このコメントを追加することで、`status` オブジェクトを更新できるようになります。
  • //+groupName=nodes.lailin.xyz はグループ名を指定します
  • `+kubebuilder:printcolumn` コマンドは `kubectl get xxx` に列を追加します。これは非常に便利です。
  • ……

CRD 検証では、いくつかのコメントを追加するだけで、ほとんどの検証機能を実行できます。

  • //+kubebuilder:default:= フィールドのデフォルト値を設定します
  • //+kubebuilder:validation:Pattern:=string 正規表現を使用してフィールドを検証する
  • ……

ウェブフック

  • `+kubebuilder:webhook` ディレクティブは、Webhook の生成方法を指定します。例えば、`Update` イベントのみをリッスンする Webhook を指定できます。

RBAC は、RBAC ファイルを生成するために使用される権限です。

  • //+kubebuilder:rbac

要約

この記事では、kubebuilderのインストール方法と使い方、そして基本的な概念とプロジェクトのディレクトリ構造について主に説明します。次の記事では、実際のOperatorの要件を一緒に実装していきます。

参考文献

[^1]: オペレーターモード | Kubernetes:

https://kubernetes.io/zh/docs/concepts/extend-kubernetes/operator/

[^2]: これはkubebuilderの公式ドキュメントであり、具体的にはmasterブランチに関するものです。バージョン3.0のリリース後、「master」の表記は削除されます。

https://master.book.kubebuilder.io/クイックスタート.html

[^3]: オペレータSDK:

https://sdk.operatorframework.io/

[^4]: Kubebuilderの詳細な分析: CRDの記述をより簡単に:

https://developer.aliyun.com/article/719215