Red Hat OpenShift on IBM Cloudで、内部レジストリ「OpenShift Container Registry（OCR）」にビルドされたイメージをローカルPCにpullする

はじめに
-
Red Hat OpenShift on IBM Cloud (ROKS)上で、アプリケーションをクイックにビルドする場合にROKSのビルダーイメージ機能を利用して、簡単にアプリケーションをROKS上にビルドすることができます。

ROKSのビルダーイメージ機能を利用した場合、ビルド＆デプロイされたイメージは、OpenShift内でデフォルトで用意されているOpenShift Container Registry（OCR）に保管されます。

OpenShift Container Registry（OCR）は、通常ROKS内部からのアクセスは可能ですが、セキュリティ上、ローカルPCでビルドしたイメージを直接pushしたり、pullするといったような外部からのアクセスができない状態になっています。

この記事では、ROKSクラスター上のOpenShift Container Registry（OCR）に対して、外部からセキュアにアクセスできるように設定し、OCRからデプロイ イメージをpullできるように設定する手順を紹介します。

この記事の内容は、基本的に「<a href="https://cloud.ibm.com/docs/openshift?topic=openshift-registry&amp;locale=ja#route_internal_registry" rel="nofollow noopener" target="_blank">IBM Cloudドキュメント：内部レジストリーのためのセキュアな外部経路のセットアップ</a>」に基づいています。</p>
<h1 data-sourcepos="9:1-9:14">

前提環境
-
・Red Hat OpenShift on IBM Cloud (OpenShiftバージョン：4.10.52_1558）
・ROKSクラスターに対してIBM Cloud IAMの「マネージャ」サービス役割を保持していること
・パブリック経路を使用して内部レジストリー（OCR)を公開するためにROKSクラスターがパブリック・ネットワークに接続できていること
・ローカルPCに Docker をインストールされ、Docerが起動できること

内部レジストリ「OpenShift Container Registry（OCR）」からビルドイメージをローカルPCにpullできるようにする
-
①openshift-image-registry プロジェクトから、内部レジストリー用の image-registry サービスが存在することを確認します。
```:＄oc get svc -n openshift-image-registry
```
出力例
```
❯ oc get svc -n openshift-image-registry
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)     AGE
image-registry            ClusterIP   xxx.xxx.xx.xxx   <none>        5000/TCP    327d
image-registry-operator   ClusterIP   None             <none>        60000/TCP   327d
```

②image-registry サービスのために暗号化されたセキュアな通信経路を作成します。 この方式を使用すると、ユーザーと内部レジストリーの間の接続パスの全体が暗号化されます。 独自のカスタム・ドメイン・ネームを指定するには、 --hostname オプションを含めます。

```:＄ oc create route reencrypt --service=image-registry -n openshift-image-registry
```
出力例
```:❯ oc create route reencrypt --service=image-registry -n openshift-image-registry
route.route.openshift.io/image-registry created
```

③** 経路に割り当てられたホスト名 (HOST/PORT) と **PORTimage-registry を取得します。
　　　「②」で作成したrouteに割り当てられたホスト名、ポートを確認します。

```:$ oc get route image-registry -n openshift-image-registry
```

出力例
```:❯ oc get route image-registry -n openshift-image-registry
NAME             HOST/PORT                                                                                                                                   PATH   SERVICES         PORT       TERMINATION   WILDCARD
image-registry   image-registry-openshift-image-registry.xxxxx.jp-tok.containers.appdomain.cloud          image-registry   5000-tcp   reencrypt     None

```

④「②」で作成したrouteをoc editコマンドで編集し、ロードバランスの方式をsourceに変更します。これにより、同じIPアドレスからのアクセスは同じPodに到達するようになります。

この機能を設定するには、metadata.annotations セクションにアノテーション「haproxy.router.openshift.io/balance: source」を追加します。 

```:$ oc edit route image-registry -n openshift-image-registry
```

以下のアノテーションを追加して保存します。

```:apiVersion: route.openshift.io/v1
kind: Route
metadata:
annotations:
    haproxy.router.openshift.io/balance: source
...
```

以上により外部から内部レジストリに対してセキュアにアクセスできるように設定されました。

⑤対象のプロジェクトを確認する。
　　　対象のプロジェクトおよび内部レジストリ「OpenShift Container Registry（OCR）」を確認します。

```:❯ oc project <対象のプロジェクト名>

Now using project "<対象のプロジェクト名>" on server "https://c115-e.jp-tok.containers.cloud.ibm.com:xxxxx".
```
⑥defaultサービスアカウントの詳細を表示し、Image pull secretsで指定されているSecretを確認します。
```:$ oc describe sa default
```
出力例
```:❯ oc describe sa default

Name:                default
Namespace:           <対象のプロジェクト名>
Labels:              <none>
Annotations:         <none>
Image pull secrets:  default-dockercfg-tz2hm
Mountable secrets:   default-token-khfp4
                     default-dockercfg-tz2hm
Tokens:              default-token-62rn4
                     default-token-khfp4
Events:              <none>
```

⑦「⑥」で確認したSecretをYAML形式で出力し、.dockercfgの値を確認します。

コマンド例
```:❯ oc get secret default-dockercfg-tz2hm -o yaml                                                                  
apiVersion: v1
data:
  .dockercfg:xxxxx
```

⑧.dockercfgの値はBase64でエンコードされているため、それをデコードします（echoコマンドに渡しているのが.dockercfgの値です）。
　　　　デコードすることで、イメージをpullするために必要なusername、passwordを得ることができます。

```:echo "<ey...=>" | base64 -D
＜途中省略＞
{"172.xx.xxx.xxx:5000":{"username":"serviceaccount","password":"ey......
```

⑨「⑧」で取得した「routeのホスト名」、「username」、「password」の値を用いて、内部レジストリ用の新たなImage Pull Secretを作成します。
ここではinternal-registryという名前のSecretを作成します。各オプションではそれぞれ以下を指定します。

コマンドラインで、次のコマンドを実行するか、もしくは、Red Hat OpenShift アプリケーション・コンソールで対象のプロジェクト配下にImage Pull Secretを作成します。ここではinternal-registryで作成します。

--docker-server 　：　routeのホスト名＋:5000（ポート番号）
--docker-username　：　上記のusernameの値
--docker-password　：　上記のpasswordの値
--docker-email　：　適当なメールアドレス（例：a@b.c）

コマンド例
```:❯ oc create secret image-registry internal-registry --namespace <対象のプロジェクト名> --docker-server image-registry-openshift-image-registry.xxxxxxx.jp-tok.containers.appdomain.cloud:5000 --docker-username serviceaccount --docker-password <eyJ...> --docker-email a@b.c
```

⑩イメージ・プル・シークレットをプロジェクトのデフォルトのサービス・アカウントに追加します。

コマンド例
```:❯ oc patch -n sample serviceaccount/default --type='json' -p='[{"op":"add","path":"/imagePullSecrets/-","value":{"name":"internal-registry"}}]'
serviceaccount/default patched
```

```:$ oc patch -n <namespace_name> serviceaccount/default --type='json' -p='[{"op":"add","path":"/imagePullSecrets/-","value":{"name":"<image_pull_secret_name>"}}]'
```

⑪Dockerにログインする
コマンド例
```:❯ docker login -u $(oc whoami) -p $(oc whoami -t) image-registry-openshift-image-registry.xxxxxxx.jp-tok.containers.appdomain.cloud
```

⑫OCR上の最初イメージを確認する
```:$ oc get imagestream
```
出力例
```:❯ oc get imagestream
NAME                 IMAGE REPOSITORY                                                                         TAGS     UPDATED
xxxxx   image-registry.openshift-image-registry.svc:5000/xxxxx/xxxxx   latest   52 days ago
```

⑬OCR上の最新イメージファイルを指定してイメージをpullする

コマンド例
```:❯ docker pull image-registry-openshift-image-registry.xxxxx.jp-tok.containers.appdomain.cloud/xxxxx/xxxxx
Using default tag: latest
latest: Pulling from scis-plus-core-dev/scis-plus-core-dev
4752687a61a9: Pull complete
0344366a246a: Pull complete
1e443c4e5fd4: Pull complete
55ec70c49a53: Pull complete
Digest: sha256:64cddb50467ae963ba0c8380436e9eebdfc98c82604a9499d35cd2bcb7f29e89
Status: Downloaded newer image for image-registry-openshift-image-registry.xxxxx.jp-tok.containers.appdomain.cloud/xxxxx/xxxxx:latest

image-registry-openshift-image-registry.xxxxx.jp-tok.containers.appdomain.cloud/xxxxx/xxxxx:latest
```


⑭ローカルPCにイメージファイルとして保存するコマンド
 　　イメージファイルは、コマンドを実行した作業ディレクトリ（カレントディレクトリ）配下に保存されます。
コマンド例
```:❯ docker save image-registry-openshift-image-registry.xxxxx.jp-tok.containers.appdomain.cloud/xxxxx/xxxxx -o <ファイル名>.tar
```

以上の手順で内部レジストリ「OpenShift Container Registry（OCR）」からビルドイメージをローカルPCにpullできるようになり、ローカルPCにイメージファイルとして保存ができるようになります。

コマンドを実行した作業ディレクトリ（カレントディレクトリ）配下にイメージファイル（<ファイル名>.tar）が保管されていることを確認します。

以上