Kubernetes Operator基本③(Ansibleベースのoperatorデモ）

前回の記事ではHelmベースのoperatorのデモに関して説明しました。
https://qiita.com/huachiting/items/9f0a7788fc83ea562dcb

本記事ではRedHatのOperator SDKを使用し、AnsibleベースのOperatorのチュートリアルをやってみようと思います。

### 1. 背景
私自身はkubernetesへのアプリデプロイ経験、運用経験がありますが、開発経験が一切ございません。
理解深めるためには簡単なデモを公式サイトやYoutubeのビデオを見ながら実施しました。

### 2. Operator sdk インストール
バイナリファイルダウンロード
```
export ARCH=$(case $(uname -m) in x86_64) echo -n amd64 ;; aarch64) echo -n arm64 ;; *) echo -n $(uname -m) ;; esac)
export OS=$(uname | awk '{print tolower($0)}')
export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/download/v1.39.2
curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH}
```

```
chmod +x operator-sdk_${OS}_${ARCH} && sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk
```

以下のコマンドを実施し、問題なくインストールされたことを確認
```
operator-sdk version
```

### 3. 前提条件
1.OpenshiftクラスタやKubernetesクラスタが構築され、ユーザーに cluster-admin 権限があること。（私の場合、Azure Red Hat OpenShiftを構築しました。）
2.アクセスできるイメージレジストリがあること。
（私の場合、Dockerhubのアカウントを持っているので、作業用のサーバからCLIでログイン済）
※もしレジストリアカウントを持っていない場合、Local実行（Kubernetes外実行）という方法がございます。手順を公式サイトにご参照いただければと思います。


### 4.チュートリアル
#### 4.1 チュートリアル内容
AnsibleベースのMemcachedのOperatorを作成する
Operatorを使用し、Memcachedのデプロイを実施。
Deployment のレプリカ数が、Memcachedのカスタムリソース（CR）仕様で指定された数と一致していること。

#### 4.2 新規プロジェクト作成

以下のコマンドでOperator プロジェクトを作成
```
mkdir memcached-operator
cd memcached-operator
operator-sdk init --plugins=ansible --domain huachiting
```

#### 4.3 新規でAPIの作成
Memcached API を作成し、Ansible ロールのひな形コードを生成します。これにより、コントローラーが APIVersion: cache.huachiting/v1alpha1 および Kind: Memcached の Memcached リソースを監視するように設定されます。
```
operator-sdk create api --group cache --version v1alpha1 --kind Memcached --generate-role
```
ls -l コマンドを実施し、以下のディレクトリ構成になっています。
※詳細ファイルまで確認したい場合、treeコマンドを実施ください。

```
total 28
drwx------. 12 azureuser azureuser   163 Apr 23 07:58 config
-rw-r--r--.  1 azureuser azureuser   312 Apr 23 07:58 Dockerfile
-rw-r--r--.  1 azureuser azureuser 10059 Apr 23 07:58 Makefile
drwxr-xr-x.  4 azureuser azureuser    33 Apr 23 07:58 molecule
drwxr-xr-x.  2 azureuser azureuser    26 Apr 23 07:58 playbooks
-rw-------.  1 azureuser azureuser   556 Apr 23 07:58 PROJECT
-rw-r--r--.  1 azureuser azureuser   206 Apr 23 07:58 requirements.yml
drwxr-xr-x.  3 azureuser azureuser    43 Apr 23 07:58 roles
-rw-r--r--.  1 azureuser azureuser   179 Apr 23 07:58 watches.yaml
```
watches.yml — API と Ansible のplaybookやroleとのマッピングを定義する
Dockerfile — Controllerイメージ用マニフェスト
PROJECTファイル — domainやapiバージョンなどの設定を記述
Makefile — プロジェクトのビルド、デプロイ、アンデプロイを行う
requirements.yaml — Ansible の依存関係
playbooks および roles ディレクトリ — 各 Ansible ファイルを格納
moleculeディレクトリ — Molecule（Ansible のテストフレームワーク）用のソースコード
configディレクトリ — 各リソースのマニフェストファイル、CRDファイル、Prometheusのメトリクス有効化にするPatchファイルなど

#### 4.4 ロジック(reconcile logic)の設定
本記事ではAnsibleのroleファイルを使い、Reconcileロジックを作成する。
roles/memcached/tasks/main.ymlファイルを以下のように編集する。
```
---
- name: start memcached
  kubernetes.core.k8s:
    definition:
      kind: Deployment
      apiVersion: apps/v1
      metadata:
        name: '{{ ansible_operator_meta.name }}-memcached'
        namespace: '{{ ansible_operator_meta.namespace }}'
      spec:
        replicas: "{{size}}"
        selector:
          matchLabels:
            app: memcached
        template:
          metadata:
            labels:
              app: memcached
          spec:
            containers:
            - name: memcached
              command:
              - memcached
              - -m=64
              - -o
              - modern
              - -v
              image: "docker.io/memcached:1.4.36-alpine"
              ports:
                - containerPort: 11211
```
Ansible playbookの変数のデフォルト値を以下のファイルに設定。
roles/memcached/defaults/main.yml
```
---
# defaults file for Memcached
size: 1
```

#### 4.5 CRファイルを作成
生成されたサンプルファイルを編集する。
config/samples/cache_v1alpha1_memcached.yaml

```
apiVersion: cache.huachiting/v1alpha1
kind: Memcached
metadata:
  name: memcached-sample
spec:
  size: 3
```
※CRファイルのspec配下に定義されたすべてのkey-value（今回はsize:3)はAnsibleの追加変数（extra vars）としてplaybookに渡される。


#### 4.6 デプロイ
通常開発者としてはlocalデプロイがよく使われるようです。localデプロイの場合、operatorはKubernetesの外からKubernetes APIを呼び出して、リソースの作成、削除、変更を実施する。その一方でKubernetesにデプロイする場合、operatorのイメージをまず生成し→レジストリにイメージプッシュ→Kubernetesへデプロイという流れになるので、Localデプロイより手間がかかります。

本記事ではKubernetesクラスタにデプロイを試します。

プッシュする前に、CLIからdockerにログインする必要がございます。
```
podman login --username XXXXXXXX --password XXXXXXXXX docker.io/huachiting/operator
```
ビルド、プッシュ：
```
make docker-build IMG=huachiting/controller:latest
make docker-push IMG=huachiting/controller:latest
```
以下のコマンドでOperatorをデプロイする
```
make install
make deploy IMG=huachiting/controller:latest
```
デプロイ後、Controllerが問題なく稼働されていることを確認。
```
kubectl get deploy -n memcached-operator-system
```

最後、4.5で作成されたCRファイルをデプロイする。
```
kubectl -n memcached-operator-system apply -f config/samples/cache_v1alpha1_memcached.yaml
```

### 5.感想
世の中、GoやpythonでKubernetes Operatorを開発するのは多いかと思いますが、プログラミング経験が少ない人にとってハードルが高いと思います。
Ansibleの場合、YAML中心の開発であり、かつ、Kubernetesのマニフェストファイルを再利用できるので、学習コストが低いかと思います。