IBM Cloud SatelliteのOpenShiftクラスターでOpenShift Container RegistryのストレージにIBM Cloud Object Storageを使用する（Satellite Link編）

# 目的

以下過去記事で触れているとおり、IBM Cloud SatelliteのRed Hat OpenShift on IBM Cloud（ROKS）クラスターは、初期状態でOpenShift Container Registry（OCR）が無効化されています。理由ですが、Satelliteではどのインフラストラクチャーにクラスターがデプロイされるかわからないためです。OCRを有効化するにはいくつかの作業が必要です。

https://qiita.com/teruq/items/fa9b7f370dd852d55e45

今回もOCRを有効にしつつ、永続ストレージにIBM Cloud Object Storage（ICOS）を使用ますが、接続方法はパブリックではなくSatellite Linkを使ってみます。Satellite Linkを使うことで、ROKSクラスターからICOSのエンドポイントがあるIBM Cloudまでトンネリングされた通信をすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/09d2da0c-8c62-b6e0-90f7-9bbb64061b28.png)


# 手順

## デフォルト状態の確認

あらためて、デフォルトの状態を確認します。内部イメージレジストリが実行されているとそれ用のPodがあるはずですが、ありません。

```
$ oc get pods -n openshift-image-registry
NAME                                               READY   STATUS    RESTARTS   AGE
cluster-image-registry-operator-6c8bcb8f69-gr645   1/1     Running   10         7d8h
node-ca-26j9s                                      1/1     Running   0          15d
node-ca-55hqz                                      1/1     Running   0          15d
node-ca-c7755                                      1/1     Running   0          34m
```

内部イメージレジストリの設定を確認します。``managementState: Removed``または``Unmanaged``はイメージレジストリを使用していないことを表してみます。

```
$ oc get configs.imageregistry.operator.openshift.io/cluster -o yaml
...
spec:
  defaultRoute: false
  httpSecret: k7QodUI7fwt34fe9Laj7AH85Nu48kv5urMp7KydetmNSKu0dGBRcpObWrAF76qWX
  logLevel: Normal
  logging: 2
  managementState: Removed
  operatorLogLevel: Normal
...
```

この状態で内部イメージレジストリを使ってみます。S2Iでイメージをビルドすると失敗します。

```
$ oc new-build --name hello-in-internal-registry -D $'FROM docker.io/ibmcom/hello'
--> Found container image 8e2cb75 (2 months old) from docker.io for "docker.io/ibmcom/hello"

    * An image stream tag will be created as "hello:latest" that will track the source image
    * A Docker build using a predefined Dockerfile will be created
      * The resulting image will be pushed to image stream tag "hello-in-internal-registry:latest"
      * Every time "hello:latest" changes a new build will be triggered

--> Creating resources with label build=hello-in-internal-registry ...
    imagestream.image.openshift.io "hello" created
    imagestream.image.openshift.io "hello-in-internal-registry" created
    buildconfig.build.openshift.io "hello-in-internal-registry" created
--> Success

$ oc get pods
NAME                                 READY   STATUS   RESTARTS   AGE
hello-in-internal-registry-1-build   0/1     Error    0          44s

$ oc logs hello-in-internal-registry-1-build
...
Warning: Push failed, retrying in 5s ...
error: build error: Failed to push image: error copying layers and metadata from "containers-storage:[overlay@/var/lib/containers/storage+/var/run/containers/storage:overlay.imagestore=/var/lib/shared]image-registry.openshift-image-registry.svc:5000/qiita/hello-in-internal-registry:latest" to "docker://image-registry.openshift-image-registry.svc:5000/qiita/hello-in-internal-registry:latest": Error trying to reuse blob sha256:e95f33c60a645d6d31f52fdc334aecec0d79a1b410789eae37fbf69efcd587ab at destination: error pinging docker registry image-registry.openshift-image-registry.svc:5000: Get "https://image-registry.openshift-image-registry.svc:5000/v2/": dial tcp: lookup image-registry.openshift-image-registry.svc on 172.21.0.10:53: no such host
```

configsのmanagementStateをManagedに変更すると、Podは起動しますが、ボリュームはemptyDirです。

```
$ oc patch configs.imageregistry.operator.openshift.io/cluster -p '{"spec": {"managementState": "Managed"}}' --type merge
config.imageregistry.operator.openshift.io/cluster patched

$ oc get pods -n openshift-image-registry
NAME                                               READY   STATUS    RESTARTS   AGE
cluster-image-registry-operator-6c8bcb8f69-gr645   1/1     Running   10         7d11h
image-registry-5cc9b5c4c4-qndt2                    1/1     Running   0          54s
node-ca-26j9s                                      1/1     Running   0          15d
node-ca-55hqz                                      1/1     Running   0          15d
node-ca-c7755                                      1/1     Running   0          3h15m

$ oc get pod image-registry-5cc9b5c4c4-qndt2 -n openshift-image-registry -o yaml
...
    key: node.kubernetes.io/memory-pressure
    operator: Exists
  volumes:
  - emptyDir: {}
    name: registry-storage
  - name: registry-tls
...
```

## ICOS用Link Endpointの確認

Satelliteのクラスターを構成すると、自動的に各リージョンに応じてCOS用のSatellite Linkが出来ています。IBM Cloudコンソールで確認すると、

* satellite-cosCrossRegion-
* satellite-cosRegional-

で始まるエンドポイントがあることがわかります。今回はcosRegionalの方を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/42def51a-e701-3aa8-fd1b-89f9673c53ea.png)

宛先FQDNまたはIPが``s3.private.jp-tok.cloud-object-storage.appdomain.cloud``になっており、エンドポイントアドレスが``sd634c45dbc813606a233-6b64a6ccc9c596bf59a86625d8fa2202-c000.jp-tok.satellite.appdomain.cloud:31064``になっています。これは、Satelliteロケーション側から後者のアドレスにアクセスするとSatellite Linkを通ってICOSのプライベートエンドポイントに到達できることを示しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/0170c2c3-6657-7732-5d76-9ab2bb8ddaaf.png)

## Object Storageの準備

IBM Cloud Object Storageのインスタンスを作成し、サービス資格情報でHMACを有効にします。今回はバケットを自動生成させたいので、管理者権限とします。

（手順省略）

## アクセスキーのSecret登録

サービス資格情報からアクセスキーとシークレットキーをSecretとして登録します。Secret名は固定値で``image-registry-private-configuration-user``にする必要があります。

```
$ REGISTRY_STORAGE_S3_ACCESSKEY=********
$ REGISTRY_STORAGE_S3_SECRETKEY=********

$ oc create secret generic image-registry-private-configuration-user \
  --from-literal=REGISTRY_STORAGE_S3_ACCESSKEY=${REGISTRY_STORAGE_S3_ACCESSKEY} \
  --from-literal=REGISTRY_STORAGE_S3_SECRETKEY=${REGISTRY_STORAGE_S3_SECRETKEY} \
  -n openshift-image-registry
```

## OpenShift Container RegistryのストレージにObject Storageを指定

今回はバケットを自動生成します。configsを修正し、spec.storageを次のようにします。regionEndpointは先ほど確認したSatellite Linkのエンドポイントです。

```
$ oc edit configs.imageregistry.operator.openshift.io/cluster

spec:
  storage:
    s3:
      region: jp-tok-smart
      regionEndpoint: sd634c45dbc813606a233-6b64a6ccc9c596bf59a86625d8fa2202-c000.jp-tok.satellite.appdomain.cloud:31064
```

> （注）regionは https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-classes#classes-locationconstraint で確認可能な値です

構成を保存し再度確認すると、``bucket``キーが自動で追加されています。

```
$ oc get configs.imageregistry.operator.openshift.io/cluster -o yaml
...
  storage:
    managementState: Managed
    s3:
      bucket: kubernetes-image-registry-jp-tok-smart-soabrnpnsadyhraefleqxrv
      region: jp-tok-smart
      regionEndpoint: sd634c45dbc813606a233-6b64a6ccc9c596bf59a86625d8fa2202-c000.jp-tok.satellite.appdomain.cloud:31064
      virtualHostedStyle: false
  unsupportedConfigOverrides: null
...
```

同名のバケットが作成されていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/d702eabc-eadd-1362-c91b-a3ff4f221f2b.png)

## 動作確認

先ほど失敗したビルドを再実行します。今度は成功しました。

```
$ oc start-build hello-in-internal-registry
build.build.openshift.io/hello-in-internal-registry-2 started

$ oc get pods
NAME                                 READY   STATUS      RESTARTS   AGE
hello-in-internal-registry-1-build   0/1     Error       0          164m
hello-in-internal-registry-2-build   0/1     Completed   0          31s

$ oc logs hello-in-internal-registry-2-build
...
Successfully pushed image-registry.openshift-image-registry.svc:5000/qiita/hello-in-internal-registry@sha256:5b53d5220c53db1038e5118e7adbac66b499d19669f988fa7e4f88bcb08c94d5
Push successful
```

バケット内にも何かしらが保存されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/f20b1179-a9bf-54f4-09f6-08333a328b98.png)

# まとめ

* IBM Cloud SatelliteのROKSクラスターではOpenShift Container Registryは無効化されている
* 有効化する際、バックエンドにICOSを指定可能
* Satellite Linkを使って、よりセキュアに接続可能