Operator SDK Go言語チュートリアルの進め方

Operator-SDK公式の[Go言語チュートリアル](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/)は、[Memcached](https://www.memcached.org/)のOperatorを開発するチュートリアルとして提供されています。

この記事は、Operator-SDKの公式の[Go言語チュートリアル](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/)を参考に、独自のOperatorを開発するための補足資料です。また、最新のOperator-SDKや付属するサンプルには追従していないため、その点の修正にも言及しています。

※ 本記事は、Operato-SDK v1.34.1をベースとしたものです。

# Kubernetes Operator とは

Operatorは、カスタムリソースを使用してKubernetesアプリケーションとコンポーネントを管理するKubernetesの拡張機能です。

- [オペレーターパターン | Kubernetes](https://kubernetes.io/ja/docs/concepts/extend-kubernetes/operator/)

まずは、Operator SDKのチュートリアルを進める上で、Operatorの基本的な概念や用語を習得しておきましょう。

# Operator SDKとは

Operator SDKは、オペレーターの構築に必要な複雑なロジックを抽象化した基本機能を提供することで、開発者の負担を軽減するツールです。

- [Welcome to Operator framework](https://operatorframework.io/)
- [Operator SDK](https://sdk.operatorframework.io/)

Operatorの構築には、Operator SDK以外にも補助となるツールが色々と[提供](https://kubernetes.io/ja/docs/concepts/extend-kubernetes/operator/)されており、Operator SDKもその一つです。

公式資料の補足として、以下のOperator SDKをベースとする動画チュートリアルも参考になります。着手の前に確認しておきましょう。

- [Get started using Kubernetes Operator - IBM Developer](https://developer.ibm.com/learningpaths/kubernetes-operators/develop-deploy-simple-operator/create-operator/)
  - [Introduction to Kubernetes Operators - IBM Developer](https://developer.ibm.com/articles/introduction-to-kubernetes-operators/)
  - [Build and deploy a basic operator - IBM Developer](https://developer.ibm.com/learningpaths/kubernetes-operators/develop-deploy-simple-operator/create-operator/)

今回は、Operator-SDKの公式の[Go言語チュートリアル](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/)を参考に進めますが、上記のチュートリアルにも沿った実装の説明となります。


# Operator-SDKによる独自Operatorの開発

Operator-SDKの公式の[Go言語チュートリアル](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/)は、[Memcached](https://www.memcached.org/)のOperatorを開発するチュートリアルとして提供されています。今回は、[Memcached](https://www.memcached.org/)を題材とする「[Go Operator Tutorial](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/)」の手順を沿って、独自のOperatorを開発する手順を説明します。

なお、本記事は「[Go Operator Tutorial](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/)」の補足記事として、独自のOperatorを開発するための要点や注意点にのみ記載しています。実際のコマンドや手順については、公式のチュートリアルを参照しつつ進めて下さい。

## STEP1: Create a new project

まず、最初のステップであるOperator-SDKのによるプロジェクト生成(初期化)です。プロジェクトディレクトリ、ドメイン名、リポジトリURLを変更して生成します。

| 変更項目 | チュートリアルでの指定 |
| ---- | ---- |
| ディレクトリ | memcached-operator |
| --domain | example.com |
| --repo | github.com/example/memcached-operator |

生成プロジェクトディレクトリは単なる生成ディレクトリですが、独自のドメイン名や、運用するレポジトリが確定している場合には、それに合わせて変更しておきましょう。

### GO 1.22での対応 

operator-sdk(v1.34.1)はGo1.21ベースであり、operator-sdkで生成されたスケルトンプロジェクトを、現在の最新版であるGo1.22でビルドすると、コントローラーツールに起因した、エラーが発生します。

- [quickstart does not work · Issue #6681 · operator-framework/operator-sdk](https://github.com/operator-framework/operator-sdk/issues/6681)


解決するには、生成されたMakefileにある`CONTROLLER_TOOLS_VERSION`を修正してください。

```
- CONTROLLER_TOOLS_VERSION ?= v0.13.0
+ CONTROLLER_TOOLS_VERSION ?= v0.14.0
```

既にビルド済の場合には、生成済みのファイルを削除(`rm bin/*`)してからビルドしてください。

## STEP2: Create a new API and Controller

次は、Custom Resource Definition (CRD) APIとコントローラーの作成です。チュートリアルでは、API種別(kind)として`Memcached`、グループ(group)、バージョン(version)ともに暫定的なものが指定されていますので、変更して生成します。

| 変更項目 | チュートリアルでの指定 | 関連資料 |
| ---- | ---- | ---- | 
| --kind | Memcached | [Kubernetes API Concepts](https://kubernetes.io/docs/reference/using-api/api-concepts/) |
| --group | cache | [API概要](https://kubernetes.io/ja/docs/reference/using-api/), [Kubernetes API Reference Docs](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#strong-api-groups-strong-) |
| --version | v1alpha1 | [API概要](https://kubernetes.io/ja/docs/reference/using-api/), [Kubernetes API Reference Docs](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#strong-api-groups-strong-), [Versions in CustomResourceDefinitions](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/) |

既存のOperator実装を[OperatorHub.io](https://operatorhub.io/operator/aerospike-kubernetes-operator)で確認すると、グループにはに公式([Kubernetes API Reference Docs](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#strong-api-groups-strong-))に定義されている`apiextensions.k8s.io`が選択されているようです。

### Define the API

今回は、このチュートリアルで実装済みのコントローラーの流用が目的なため、まずはチュートリアル通りにCustom Resource (CR)を追加します。

チュートリアル通りに`Size`、`ContainerPort`、`Condition`を、STEP1で生成された対象の定義ファイル(`api/<version>/<kind>_types.go`)にCustom Resource (CR)として追加します。 

## STEP3：Implement the Controller 

次は、STEP2の定義に沿った、コントローラーの実装です。公式のチュートリアルでは、実装済みのMemechachedコントローラーのファイルをコピーすることを前提に説明されています。

今回は、以下にある最新のMemechachedコントローラーのサンプルを改修することで、独自のOperatorを実装していきます。
- [memcached-operator/internal/controller](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/memcached-operator/internal/controller/)
  - [memcached_controller.go](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/memcached-operator/internal/controller/memcached_controller.go)
  - [memcached_controller_test.go](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/memcached-operator/internal/controller/memcached_controller_test.go)
  - [suite_test.go](https://github.com/operator-framework/operator-sdk/blob/master/testdata/go/v4/memcached-operator/internal/controller/suite_test.go)

Operator-SDKのサンプルを参考に、STEP1で生成されたコントローラーディレクトリ(`internal\controller`)にある実装を置き換えて修正します。

STEP2で、追加したCRDのスキーマ定義に合わせたサンプルのため、Kind名(Memcached)に関連する修正が主にとなります。

また、本サンプルは対象となるイメージ名を環境変数(`MEMCACHED_IMAGE`)で指定しているので、STEP2のKind名の変更に伴い、環境変数の名称も修正しておきましょう。

※ Operator-SDKのバージョンにより、公式チュートリアルにはないPrometheus監視動作が含まれている場合があります。必要に応じて削除してください。

## STEP4: Configure the operator’s image registry

この章については、チュートリアルに記載されている通りです。

STEP1で生成されたMakefileを修正します。

## STEP5: Run the Operator

チュートリアルに記載されている通り、STEP3で変更した環境変数を設定してテスト(`make test`)実行しましょう。

また、STEP1ではGithubアクション(`.github/workflows/make.yml`)でのテストも生成されているため、同様に変更した環境変数を`env`に追加しておきましょう。

# 最後に

本記事では、Operator-SDKの公式のGo言語チュートリアルを参考にして、独自のOperatorを開発する手順を紹介しました。この記事が、独自のOperatorを開発する最初の一歩となれば幸いです。

## 参考資料

- [オペレーターパターン | Kubernetes](https://kubernetes.io/ja/docs/concepts/extend-kubernetes/operator/)
- [Operator SDK](https://sdk.operatorframework.io/)
  - [Go | Operator SDK](https://sdk.operatorframework.io/docs/building-operators/golang/)
    - [Quickstart for Go-based Operators | Operator SDK](https://sdk.operatorframework.io/docs/building-operators/golang/quickstart/)
    - [Go Operator Tutorial | Operator SDK](https://sdk.operatorframework.io/docs/building-operators/golang/tutorial/)
    - [operator-sdk/testdata/go at latest · operator-framework/operator-sdk](https://github.com/operator-framework/operator-sdk/tree/latest/testdata/go)
- [OperatorHub.io | The registry for Kubernetes Operators](https://operatorhub.io)
- [Get started using Kubernetes Operator - IBM Developer](https://developer.ibm.com/learningpaths/kubernetes-operators/develop-deploy-simple-operator/create-operator/)
  - [Introduction to Kubernetes Operators - IBM Developer](https://developer.ibm.com/articles/introduction-to-kubernetes-operators/)
  - [Build and deploy a basic operator - IBM Developer](https://developer.ibm.com/learningpaths/kubernetes-operators/develop-deploy-simple-operator/create-operator/)
  - [Deep dive into Kubernetes operators - IBM Developer](https://developer.ibm.com/learningpaths/kubernetes-operators/operators-extend-kubernetes/)
- [Kubernetes Operators - Red Hat Developer](https://developers.redhat.com/e-books/kubernetes-operators)
- [Kubernetes Operator初心者がOperatorを作成してみた (operator-sdk編)](https://qiita.com/nakamasato/items/2a49d93e17893dcc3378)
- [Operatorの開発の始め方...の前に必要な知識 #kubernetes - Qiita](https://qiita.com/go_vargo/items/71b988105174909732ef)
- [ゼロから始めるKubernetes Controller / Under the Kubernetes Controller - Speaker Deck](https://speakerdeck.com/govargo/under-the-kubernetes-controller-36f9b71b-9781-4846-9625-23c31da93014)