Oracle Cloud Hangout Cafe Season5 #1「Kubernetes Operator 超入門」(2022年1月19日開催)

2023年3月17日(金)
仁井田 拓也
連載第3回の今回は、2022年1月19日に開催された「Oracle Cloud Hangout Cafe Season5 #1『Kubernetes Operator 超入門』」の発表内容に基づいて紹介していきます。

●STEP1:プロジェクトの作成

まずは、プロジェクトを作成します。

プロジェクトを作成するにはoperator initコマンドを利用します。この際に、CRの"apiVersion"の一部になる--domainオプションと、必要に応じてGitHubリポジトリを指定する--repoオプションを付与します。今回は適当なGitHubリポジトリを付与します。

次に、APIを作成します。APIを作成することで、プロジェクト内に様々なボイラープレートコード*2が作成されます。この際にCRの"apiVersion"の一部になる--groupオプション、CRの"Kind"(=Operatorの操作対象)になる--kindオプション、OperatorやManifestのボイラープレートコードの自動生成フラグである--controller --resourceを付与します。

*2:ボイラープレートコード : 定型的なソースコードのことで、ここでは雛形となるソースコードやManifestです。

実は、これらのコマンドの裏ではapimachinerycontroller-toolscontroller-genなどが利用されており、その様子がコマンドを実行した際の標準出力ログから以下のように確認できます。

[root@ocha]$ operator-sdk init --domain oracle.com --repo github.com/oracle-japan/ochacafe-operator-intro
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.13.0
go: downloading sigs.k8s.io/controller-runtime v0.13.0
go: downloading k8s.io/apimachinery v0.25.0
~~~~~
go: downloading github.com/benbjohnson/clock v1.1.0
Next: define a resource with:
$ operator-sdk create api
[root@ocha]$ operator-sdk create api --group ochacafe --version v1alpha1 --kind Ochacafe  --controller --resource 
~~~~~
test -s /home/ochacafe/ochacafe-operator-intro/bin/controller-gen || GOBIN=/home/ochacafe/ochacafe-operator-intro/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.10.0
go: downloading sigs.k8s.io/controller-tools v0.10.0
~~~~~
/home/ochacafe/ochacafe-operator-intro/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
Next: implement your new API and generate the manifests (e.g. CRDs,CRs) with:
$ make manifests
[root@instance-20230213-1423 test]# 

この時点でのディレクトリ構成を確認します。全ては紹介できないので、一部を抜粋して説明します。

.
├── api ==> APIリソース(CR)の定義。Kind毎に生成。Manifestのフィールド定義とも言える
│   └── v1alpha1
│       ├── groupversion_info.go
│       ├── ochacafe_types.go
│       └── zz_generated.deepcopy.go
├── bin
│   └── controller-gen ==> 各種コマンド実行時に利用される`controller-gen`バイナリ
├── config ==> 各種Manifestファイル。ソースコードのアノテーションを元に生成(controller-toolsが生成)
│   ├── crd
│   ├── default
│   ・
│   ・
│   ・
├── controllers ==> Operatorの実装部分。テンプレートをもとに実装(controller-runtimeを利用)
│   ├── ochacafe_controller.go
│   └── suite_test.go
├── Dockerfile ==> OperatorをコンテナとしてビルドするためのDockerfile
├── Makefile
├── PROJECT
└── README.md
17 directories, 43 files

●STEP2:CRの実装

ここからは、実装に入っていきます。まずは、CRを実装します。編集するファイルはapi/v1alpha1/ochacafe_types.goです。今回は、以下のフィールドを定義します。

  • ユーザが定義するOchacafeリソースのsizeフィールド
  • Operatorが追記するPodがスケジューリングされたNode名(kubectl describe時にスケジューリングしたNode名を確認可能にするため)

実際のコードは、下図の通りです。

これでCRの実装は完了ですが、ここで以下の2つのコマンドを実行します。

./make generate
./make manifests

前者のコマンドはbin/controller-genを呼び出し、api/v1/zz_generated.deepcopy.goを更新します。このファイルには、Operatorが実装する必要のあるインタフェースが実装されていますが、これを自動的に更新します。

後者のコマンドはbin/controller-genを呼び出し、config/crd/bases/ochacafe.oracle.com_ochacafe.yamlを自動生成します。これは、実装したCRに基づいたCRDを生成します。

ここまでの作業の全体イメージは下図の通りです。

●STEP3:RBACの実装

ここでは、RBACの実装を進めます。OperatorはKubernetesのリソースを操作できなくてはなりません。今回で言えば、標準リソースであるDeployment/Podを操作できる必要があります。そのため、ここではRBACを実装します。

とは言っても、何かしらのロジックを実装するわけではなく、Operatorのロジックを実装する箇所にアノテーションで付与したいRBACを定義するだけで実装できます。

ここでは、Deployment/に対するフル権限(get/list/watch/create/update/patch/delete)、Podに対する参照権限(get/list/watch)を付与します。

編集するファイルはcontrollers/ochacafe_controller.goです。

このようにRBACを定義したら、先ほどと同様にmake manifestsコマンドを実行します。これにより、config/rbac/role.yamlに定義されているOperatorのRBAC定義が更新されます。

ちなみに、追記した行を見ると//+kubebuilder:rbac:~となっていることが分かります。ここにOperator SDKとKubebuilderが統合されている様子が垣間見えます。

ここまでの作業の全体イメージは下図の通りです。

●STEP4:Operatorの実装

ここでは、Operator本体の処理を実装します。なお、この実装について詳細を書くことは難しいので、Operatorで実装すべき入出力パラメーターと実装時の注意点だけ整理しておきます。

・Operatorで実装すべき入出力パラメーター
Operatorで実装すべき入出力パラメーターは、以下の通りです。

内容 説明
入力 Context(goroutine(スレッド)*3を扱うための情報) / Request(CRに関する情報など)
出力 Result(処理結果) / error(エラー情報)| Result.Requeue / Result.RequeueAfterというフィールドに再キューイング要否と遅延時間をそれぞれ指定。正常終了時はerror=nil、異常終了時はerror=Exception情報

*3:goroutine : Golangで利用される軽量スレッドです。

入出力のみ実装すると、下図になります。

・Operator実装時に注意すべきこと
補足として、Operator実装時に注意すべき点をまとめます。ここで取り上げるポイントは2点です。

  • 結果が必ず収束するように実装
  • 処理内で待機したり、時間のかかる処理を実装しない

前者については、Kubernetesで重要なコンセプトである"宣言的オペレーション"に準拠するにはOperatorの処理結果をべき等にすることが必須です。エラーになったとしても、もう一度処理を呼び出した時に必ずリカバリできるようにしておくことが重要です。エラー発生時には前述した出力パラメーターのResult.Requeuetrueに設定すれば再実行されます。

後者については、リソースの状態が変化するまで待機したり、時間がかかる処理を実装するとスケーラブルなOperatorにならず、また大量のリソースを取得するような実装はAPI Serverの負荷を高めることにもつながります。時間のかかる処理や待機が必要な場合はスレッド(goroutineで実行)にし、Result.RequeueAfterに待機時間を指定するか、キャッシュを上手く活用してAPI Serverへの不必要なアクセスは行わないようにしましょう。

Operator実装時の注意点については、非常に詳しく解説された資料と動画が公開されています。

上記のOperatorのソースコードは、こちらのリポジトリで公開しています。必要に応じて確認してください。

日本オラクル株式会社

Oracle Groundbreaker Advocate
Senior Cloud Solution Engineer

日本オラクル株式会社所属。SIerにて様々なOSSを活用したシステム開発を経験し現職。現在は、SIer時代の知見を活かし、ソリューションアーキテクトとしてクラウドでのアプリケーション開発やクラウドネイティブ技術に関する技術/案件支援に従事。

Community:
Oracle Cloud Hangout Cafe メンバー(#ochacafe)

連載バックナンバー

仮想化/コンテナ技術解説
第6回

Oracle Cloud Hangout Cafe Season6 #1「Service Mesh がっつり入門!」(2022年9月7日開催)

2023/6/22
連載第6回の今回は、2022年9月7日に開催された「Oracle Cloud Hangout Cafe Season6 #1『Service Mesh がっつり入門!』」の発表内容に基づいて紹介していきます。
仮想化/コンテナ技術解説
第5回

Oracle Cloud Hangout Cafe Season5 #5「実験! カオスエンジニアリング」(2022年5月11日開催)

2023/5/18
連載第5回の今回は、2022年5月11日に開催された「Oracle Cloud Hangout Cafe Season5 #5『実験! カオスエンジニアリング』」の発表内容に基づいて紹介していきます。
仮想化/コンテナ技術解説
第4回

Oracle Cloud Hangout Cafe Season5 #3「Kubernetes のセキュリティ」(2022年3月9日開催)

2023/4/18
連載第4回の今回は、2022年3月9日に開催された「Oracle Cloud Hangout Cafe Season5 #3『Kubernetes のセキュリティ』」の発表内容に基づいて紹介していきます。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています