【OKE Hands-On】OCIRのプライベートレポジトリからコンテナイメージをデプロイする

# はじめに
組織でコンテナワークロードを開発・運用する際、プライベートなコンテナレジストリを使用し、コンテナイメージを外部と共有することなく利用する環境が求められます。
プライベートなコンテナレジストリからのPodのデプロイは、アプリケーションのマニフェスト・ファイルで、プルするイメージ、プル元のレジストリ、およびイメージのプル時に使用する資格証明を指定することで実現できます。

本記事では、KubernetesのリソースであるSecretを使い、資格情報を.dockerconfigjsonに含めることで、OCIR(Oracle Cloud Infrastrucure Reistory)からOKE(Oracle Cloud Infrastructure Container Engine for Kubernetes)にPodをセキュアにデプロイする手順を解説します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/0dfff723-e85f-f3c6-aa8d-0c890b7ff40f.png)

# OCIR(Oracle Cloud Infrastructure Registry)とは

コンテナ・イメージ(Dockerイメージなど)を格納、共有および管理するコンテナレジストリサービスです。ユーザー設定で認証トークンを作成し、Docker CLIを使用してログインすると利用できます。

https://docs.oracle.com/ja-jp/iaas/Content/Registry/Concepts/registryoverview.htm

今回は、Secretを使用し、機密データである認証トークンをアプリケーションコードに含めることなく、プライベートレポジトリからNginxのコンテナイメージをデプロイします。

https://kubernetes.io/ja/docs/concepts/configuration/secret/

# 前提

【作業用インスタンス】
・作業用インスタンスとして ComputeVM（Oracle Linux8） が構築されていること
・作業用インスタンスにDocker CLIがインストールされていること
・作業用インスタンスにkubectlがインストールされていること

【OKEクラスタ】
・OKEクラスターが作成されていること
・OKEクラスターのカスタム作成については下記記事を参考にしてください。

https://qiita.com/s_obata/items/4431d5cac2addd0b9809

# 手順
1. プライベートコンテナレジストリ(OCIR)の作成とイメージのPush
1. Dockerレジストリ・シークレットの作成
1. Dockerシークレットを指定し、コンテナ・レジストリからコンテナイメージのデプロイ

# 1. プライベートコンテナレジストリ(OCIR)の作成とイメージのPush
## 1-1. プライベートコンテナレジストリ(OCIR)の作成

OCIコンソール画面を開き、「ナビゲーションメニュー」->「開発者サービス」から「コンテナ・レジストリ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/b8595d20-15f7-9274-bfbd-6c49dc98dddd.png)

「Create repository」を押下します。
画面右にCreate repository画面が表示されるので、作成するレポジトリのコンパートメントを指定し、AccessをPrivateに設定します。
また、Repojitory nameを記載します。今回はnginxをdockerコマンドでpushするため、レポジトリ名の末尾を"/nginx"としています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/9cb4dbaa-1c5a-0782-1e58-7dd03a2aae80.png)

画面下にあるCreateボタンを押下し、コンテナ・レジストリの画面に戻ります。
Repositories and imagesのラベルで作成したレポジトリを指定すると、リポジトリ情報が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/afcf06c8-5fe7-2597-7117-6e4302639a0a.png)

## 1-2. Nginxイメージのプッシュ
作業用のCompute VMから、作成したコンテナレジストリにイメージをプッシュします。
はじめにコンテナレジストリへログインする必要があります。
コンテナレジストリへのログインには、ユーザの認証トークンが必要です。
認証トークンを作成していない場合は、下記リファレンスを参考に認証トークンを作成します。

https://docs.oracle.com/ja-jp/iaas/Content/Registry/Tasks/registrygettingauthtoken.htm

:::note warn
認証トークンは再度表示されないため、安全な場所で保管してください。
:::

認証トークンを取得したら、作業用のCompute VMから下記コマンドでコンテナレジストリにログインします。
```
$ docker login repository_name
```
レポジトリ名は下記の命名規則となっています。

```
<リージョンコード>.ocir.io
```
リージョン別のOCIRレポジトリ名はこちらを参照してください。

https://docs.oracle.com/ja-jp/iaas/Content/Registry/Concepts/registryprerequisites.htm#regional-availability

今回はロンドンリージョンでOCIRを作成したため、レポジトリ名は lhr.ocir.io となります。

下記コマンドでログインします。
```
$ docker login lhr.ocir.io
```
プロンプトが表示されたら、下記命名規則に則ったユーザー名を入力します。
```
<tenancy-namespace>/oracleidentitycloudservice/<username>
```
tenancy-namespaceは画面右上のユーザアイコンからテナンシを参照してください。
usernameはナビゲーションメニューから「アイデンティティとセキュリティ」→「ユーザ」で確認できます。
例えば、tenancy-namespaceがoracle、usernameがRallyの場合、ユーザ名が下記となります。
```
oracle/oracleidentitycloudservice/Rally
```
パスワードの入力を求められたら、取得した認証トークンの文字列を入力します。

Login Succeededと表示されればログイン完了です。

予めDockerHubからpullし、タグ付けしたnginxのコンテナイメージをpushします。
```
$ docker push lhr.ocir.io/oracle/test-repo/nginx:1.0.0
```
OCIRのコンソール画面から、コンテナレポジトリにイメージが追加されたことを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2325706/128a8fa8-09c6-14ca-aebe-d0c308a0d368.png)

# 2. Dockerレジストリ・シークレットの作成

このプライベートレポジトリからコンテナイメージをpullし、Podをデプロイしたいと思います。
今回、Dockerシークレットを作成し、アプリケーションのマニフェスト・ファイル内でプライベートレポジトリへの認証情報を指定することで、コンテナイメージをpullします。
プライベートレポジトリからコンテナイメージをpullする際に、Secretに含まれているdockerconfigの認証情報が使用されます。

Dockerレジストリ・シークレットの作成には、下記コマンドを実行します。
```
kubectl create secret docker-registry <secret-name> \
  --docker-server=<region-key>.ocir.io \
  --docker-username=<tenancy-namespace>/<oci-username> \
  --docker-password='<oci-auth-token>' \
  --docker-email=<email-address>
```


"secret-name" には、任意のシークレットの名前を入力します。
"oci-auth-token" には、取得した認証トークンの文字列を入力します。
"email-address" は、任意のメールアドレスで結構です。

作成したシークレットは下記コマンドで確認できます。
今回は、repo-secretという名前でシークレットを作成しました。
```
$ kubectl get secret
NAME          TYPE                             DATA   AGE
repo-secret   kubernetes.io/dockerconfigjson   1      2d
```

# 3. Dockerシークレットを指定し、コンテナ・レジストリからコンテナイメージのデプロイ

Podをデプロイするためのyamlファイルを作成します。

**nginx.yaml**
```rb
apiVersion: v1
kind: Pod
metadata:
  name: ngnix-image
spec:
  containers:
    - name: ngnix
      image: lhr.ocir.io/oracle/test-repo/nginx:1.0.0
      imagePullPolicy: Always
      ports:
      - name: nginx
        containerPort: 8080
        protocol: TCP
  imagePullSecrets:
    - name: repo-secret

```
下記コマンドでデプロイします。
```
$ kubectl apply -f nginx.yaml
```

podがデプロイされたか確認します。
```
$ kubectl get pods
NAME          READY   STATUS    RESTARTS   AGE
ngnix-image   1/1     Running   0          89m
```
STATUSがRunningになり、Podが正常に稼働していることが確認できました。

## 参考：Secretを指定せずにデプロイしたパターン

参考に、SecretをimagePullSecretsに指定しないパターンでデプロイしてみます。
下記のyamlファイルでデプロイを行います。

**nosecret.yaml**
```rb
apiVersion: v1
kind: Pod
metadata:
  name: no-secret
spec:
  containers:
    - name: ngnix
      image: lhr.ocir.io/oracle/test-repo/nginx:1.0.0
      imagePullPolicy: Always
      ports:
      - name: nginx
        containerPort: 8080
        protocol: TCP
```

```
$ kubectl apply -f nosecret.yaml 
pod/no-secret created
$ kubectl get pods
NAME          READY   STATUS         RESTARTS   AGE
ngnix-image   1/1     Running        0          91m
no-secret     0/1     ErrImagePull   0          11s

```
Podを確認すると、STATUSにErrImagePullと表示され、Podがデプロイできていないことがわかります。

# まとめ
KubernetesのリソースであるSecretを作成し、Secretにコンテナレジストリの資格情報を含めることで、プライベートレジストリからPodをデプロイする手順を解説しました。
Secretを利用することで、Kubernetesクラスタにアクセスできる複数ユーザが共通のプライベートレジストリからコンテナイメージをpullすることができます。


# 参考

https://docs.oracle.com/ja-jp/iaas/Content/Registry/Concepts/registryoverview.htm

https://docs.oracle.com/ja-jp/iaas/Content/Registry/Tasks/registrygettingauthtoken.htm

https://docs.oracle.com/ja-jp/iaas/Content/Registry/Concepts/registryprerequisites.htm#regional-availability

https://docs.oracle.com/ja-jp/iaas/Content/Registry/Tasks/registrypullingimagesfromocir.htm