Red Hat OpenShift on IBM Cloudに自作Ansible Operatorをデプロイする（OLMインストール編）

# 目的

前回の記事では、自作のOperatorをクラスタに手動でインストールしました。今回はOperator Lifecycle Manager（OLM）を使ってみます。OLMを使うことで、OpenShiftコンソールからOperatorの操作が可能になります。

https://qiita.com/teruq/items/4fc4193a5e1de2b3802b

# 手順

前回記事の手順実施直後の状態からの開始を想定します。

## Bundleの作成

OLMで管理するためのOperatorのパッケージ情報をBundleと呼びます。Bundleの定義を生成します。いくつか手動で入力する必要があります。

```
$ make bundle
operator-sdk generate kustomize manifests -q

Display name for the operator (required):
> Hello Operator

Description for the operator (required):
> An example of Ansible Operator

Provider's name for the operator (required):
> teruq

Any relevant URL for the provider name (optional):
> https://qiita.com/teruq

Comma-separated list of keywords for your operator (required):
> ansible,hello

Comma-separated list of maintainers and their emails (e.g. 'name1:email1, name2:email2') (required):
> teruq
cd config/manager && /.../hello-ansible-operator/bin/kustomize edit set image controller=jp.icr.io/teruq/hello-ansible-operator:0.0.1
/.../hello-ansible-operator/bin/kustomize build config/manifests | operator-sdk generate bundle -q --overwrite --version 0.0.1
INFO[0002] Creating bundle.Dockerfile
INFO[0002] Creating bundle/metadata/annotations.yaml
INFO[0002] Bundle metadata generated suceessfully
operator-sdk bundle validate ./bundle
INFO[0000] All validation tests have completed successfully
```

## Bundleイメージのビルド

Bundle自体もコンテナイメージです。イメージをビルドします。

```
$ make bundle-build
docker build -f bundle.Dockerfile -t jp.icr.io/teruq/hello-ansible-operator-bundle:v0.0.1 .
...
```

## Bundleイメージのプッシュ

前回の記事の手順から時間がたっていると認証が切れている場合があるので、再認証しておきます。

```
$ export IBMCLOUD_API_KEY=********
$ ibmcloud login
$ ibmcloud cr login
```

イメージをICRにプッシュします。

```
$ make bundle-push
make docker-push IMG=jp.icr.io/teruq/hello-ansible-operator-bundle:v0.0.1
make[1]: ディレクトリ '/.../hello-ansible-operator' に入ります
docker push jp.icr.io/teruq/hello-ansible-operator-bundle:v0.0.1
The push refers to repository [jp.icr.io/teruq/hello-ansible-operator-bundle]
598401fa8392: Layer already exists
14f153f590a2: Layer already exists
9d6970a7da8f: Layer already exists
v0.0.1: digest: sha256:aa57c38c38d897e1275e4b95dbc62c3b53d37399bdbb7529e9ff15ab4c098494 size: 939
make[1]: ディレクトリ '/.../hello-ansible-operator' から出ます
```

ICRに登録されたことを確認します。

```
$ ibmcloud cr images | grep hello-ansible
$ ibmcloud cr images | grep hello-ansible
jp.icr.io/teruq/hello-ansible-operator               0.0.1                              031595ea6f53   teruq      2 hours ago    156 MB   55 件の問題
jp.icr.io/teruq/hello-ansible-operator-bundle        v0.0.1                             aa57c38c38d8   teruq      1 hour ago     3.4 kB   サポート対象外 OS
```

## ImagePullSecretのコピーとリンク

例によってICRから各種イメージをプルするために、ImagePullSecretをコピーします。

### ネームスペースの作成

Operatorをインストールするネームスペースをあらかじめ作成します。今回は``qiita-operators``とします。

```
$ oc create ns qiita-operators
```

### ImagePullSecretのコピー

defaultネームスペースからコピーします。

```
$ oc get secret all-icr-io -n default -o yaml | grep -v namespace: | oc create -n qiita-operators -f-
```

### ImagePullSecretのSeviceAccountへのリンク

all-icr-ioをBundle用の``default``ServiceAccountにリンクします。

```
$ oc secrets link default all-icr-io --for pull -n qiita-operators
```

## OLMを使用したインストール

### OLMの確認

OpenShift 4.x以降では、OLMは標準でインストールされています。ROKSの場合も同様です。下記のように状態を確認できます。

```
$ operator-sdk olm status --olm-namespace openshift-operator-lifecycle-manager
I0930 15:08:43.304528   15260 request.go:668] Waited for 1.0293062s due to client-side throttling, not priority and fairness, request: GET:https://c100-e.jp-tok.containers.cloud.ibm.com:32154/apis/samples.operator.openshift.io/v1?timeout=32s
INFO[0004] Fetching CRDs for version "0.16.1"
INFO[0004] Using locally stored resource manifests
INFO[0004] Successfully got OLM status for version "0.16.1"

NAME                                            NAMESPACE    KIND                        STATUS
operators.operators.coreos.com                               CustomResourceDefinition    Installed
operatorgroups.operators.coreos.com                          CustomResourceDefinition    Installed
installplans.operators.coreos.com                            CustomResourceDefinition    Installed
clusterserviceversions.operators.coreos.com                  CustomResourceDefinition    Installed
subscriptions.operators.coreos.com                           CustomResourceDefinition    Installed
system:controller:operator-lifecycle-manager                 ClusterRole                 Installed
aggregate-olm-edit                                           ClusterRole                 Installed
aggregate-olm-view                                           ClusterRole                 Installed
catalogsources.operators.coreos.com                          CustomResourceDefinition    Installed
olm                                                          Namespace                   namespaces "olm" not found
olm-operator-binding-olm                                     ClusterRoleBinding          clusterrolebindings.rbac.authorization.k8s.io "olm-operator-binding-olm" not found
olm-operator                                    olm          Deployment                  deployments.apps "olm-operator" not found
catalog-operator                                olm          Deployment                  deployments.apps "catalog-operator" not found
olm-operator-serviceaccount                     olm          ServiceAccount              serviceaccounts "olm-operator-serviceaccount" not found
operators                                                    Namespace                   namespaces "operators" not found
global-operators                                operators    OperatorGroup               operatorgroups.operators.coreos.com "global-operators" not found
olm-operators                                   olm          OperatorGroup               operatorgroups.operators.coreos.com "olm-operators" not found
packageserver                                   olm          ClusterServiceVersion       clusterserviceversions.operators.coreos.com "packageserver" not found
operatorhubio-catalog                           olm          CatalogSource               catalogsources.operators.coreos.com "operatorhubio-catalog" not found
```

### Bundleの実行

下記のコマンドでBundleを実行します。先ほどServiceAccountにリンクしたばかりのImagePullSecretを再度ここで指定する必要があります。

```
$ operator-sdk run bundle jp.icr.io/teruq/hello-ansible-operator-bundle:v0.0.1 --pull-secret-name all-icr-io -n qiita-operators
INFO[0009] Successfully created registry pod: jp-icr-io-teruq-hello-ansible-operator-bundle-v0-0-1
INFO[0010] Created CatalogSource: hello-ansible-operator-catalog
INFO[0010] OperatorGroup "operator-sdk-og" created
INFO[0010] Created Subscription: hello-ansible-operator-v0-0-1-sub
INFO[0012] Approved InstallPlan install-lcqlh for the Subscription: hello-ansible-operator-v0-0-1-sub
INFO[0012] Waiting for ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.1" to reach 'Succeeded' phase
INFO[0012]   Waiting for ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.1" to appear
INFO[0018]   Found ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.1" phase: Pending
INFO[0020]   Found ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.1" phase: Installing
INFO[0107]   Found ClusterServiceVersion "qiita-operators/hello-ansible-operator.v0.0.1" phase: Succeeded
INFO[0108] OLM has successfully installed "hello-ansible-operator.v0.0.1"
```

Podは下記の状態です。

```
$ oc get pods -n qiita-operators
NAME                                                              READY   STATUS      RESTARTS   AGE
9cbeaa081bdcc6ecb2ba12064d0e68820efc754b3a48e9acca07d3987bcgsgl   0/1     Completed   0          28s
hello-ansible-operator-controller-manager-7cb6dcf49d-99rnt        2/2     Running     0          14s
jp-icr-io-teruq-hello-ansible-operator-bundle-v0-0-1              1/1     Running     0          40s
```

> ImagePullSecretについて補足します。jp-icr-io-teruq～はdefault ServiceAccountにリンクされたものを、9cbeaa081bd～はCLI実行時に指定したものを、hello-ansible-operator～はDeploymentに指定したものを使っています。この不統一さから察するに、このSDKを開発した人は恐らくイメージがプライべートレジストリにあることを想定していなかったのではと思います。

## OpenShiftコンソールの確認

OpenShiftコンソールから、OperatorHubを選択します。Hello Operatorが存在しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/2636ff95-805d-f6fa-aa19-dba71594f81c.png)

Installed Operatorsを見ると、Hello Operatorがインストール済となっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/85f7d449-1edf-5794-6c64-638c12742612.png)

## アプリのデプロイ

Installed Operatorsで画面上部のProjectをアプリをデプロイしたいプロジェクトに変更します。その後Hello Operatorを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/782b3fbb-086f-cb69-9918-cf805a552b10.png)

Create Instanceを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/7e19c79e-fafb-2722-d233-37902f57690b.png)

前回Custom Resource Definitionで``replicas``を必須プロパティとしましたが、画面で入力することができるようになっています。Createを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/1387055a-3e94-e36d-55de-c49283c427ca.png)

ConditionがRunningになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/4bd00533-576d-4784-e387-e9478f90bca4.png)

Podが起動していることを確認します。

```
$ oc get pods -n qiita | grep hello
sample-hello-c54fb8b58-7hmbn      1/1     Running   0          28s
sample-hello-c54fb8b58-sdjlk      1/1     Running   0          28s
```

アプリの動作確認は前回記事を参照ください。

## クリーンアップ

SDKからクリーンアップ可能です。

```
$ operator-sdk cleanup hello-ansible-operator
INFO[0002] subscription "hello-ansible-operator-v0-0-1-sub" deleted
INFO[0002] customresourcedefinition "hellos.example.teruq.example.com" deleted
INFO[0002] clusterserviceversion "hello-ansible-operator.v0.0.1" deleted
INFO[0002] catalogsource "hello-ansible-operator-catalog" deleted
INFO[0002] operatorgroup "operator-sdk-og" deleted
INFO[0002] Operator "hello-ansible-operator" uninstalled
```

完全にクリーンアップするためには手動で作成したものを個別に削除する必要があります。

```
$ oc secrets unlink default all-icr-io
$ oc delete secret all-icr-io
$ oc delete ns qiita-operators
```

# 感想

やはりプライベートレジストリを使用すると手順が複雑化します。このままだとOperatorをカタログ化して気軽にインストールするというわけにはいかないので、何とかしたいです。いい方法がないか、今後検証していきたいと思います。

# 参考

* https://operatorhub.io/getting-started
* https://sdk.operatorframework.io/docs/building-operators/ansible/tutorial/