Red Hat OpenShift Study / コンテナのデプロイ - (1) Dockerイメージを元にしたデプロイ

# はじめに
当連載記事ではRed Hat OpenShift上にコンテナ化されたアプリケーションをデプロイする流れを見ていきます。
Open Shiftではアプリケーションをデプロイする際の機能が充実しています。具体的には`oc new-app`コマンドでアプリケーションをデプロイするパターンが複雑なのでその辺りを整理していきたいと思います。
まずはシンプルなケースからということで、今回はDockerイメージを元にそれをそのままOpenShift上にデプロイするシナリオを取り上げます。

環境はIBM Cloud上のマネージドOpenShiftクラスターを前提とします。(OpenShift V4.5)

今回のシナリオ: **Dockerイメージ => OpenShift上のPodとしてデプロイ**

## 関連記事
[Red Hat OpenShift Study / コンテナのデプロイ - (0) Dockerおさらい](https://qiita.com/tomotagwork/items/6b64cb54eaf45c057196)
[Red Hat OpenShift Study / コンテナのデプロイ - (1) Dockerイメージを元にしたデプロイ](https://qiita.com/tomotagwork/items/f7398ac3c71eefe24835)
[Red Hat OpenShift Study / コンテナのデプロイ - (2) Dockerビルド](https://qiita.com/tomotagwork/items/bb5919c27ed53a459d09)
[Red Hat OpenShift Study / コンテナのデプロイ - (3) s2i ビルド](https://qiita.com/tomotagwork/items/a86848e979b98910e4d4)

# 全体像

すでにサービスとして提供したいアプリケーションが組み込まれたDockerイメージが存在している(ビルドされている)前提で、それをOpenShiftクラスター上に`oc new-app`でデプロイしてみるというシナリオです。
具体的な例として単純なgo言語のサンプルを動かすDockerイメージを作成して、それをquay.ioというレジストリに登録しておきます。そのイメージをoc new-appでOpenShiftクラスター上にデプロイする、という流れを試してみます。

今回実施するシナリオの大まかな流れを以下の図に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/cbe804da-d9cc-5b01-7055-b68870d7f9ec.png)

# 事前準備
まずは上の全体像の図の(1)～(5)の部分を事前準備として実施します。

## レジストリの準備
プライベートのレジストリとして[quay.io](https://quay.io/)というサービスを使いますので、アカウントを作成しておきます。フリートライアルだとpublicのレジストリしか作れないようで、かつ1レジストリしか使えないようですが、まぁテストで使う分には問題ないのでフリートライアルのアカウントを利用します(ここではtomotagworkというアカウントを作って試します)。

## Dockerイメージの準備
出来合いのものを使ってもよいですが、今回は簡易的なgoのサンプルを動かすイメージを作ってそれをOpenShiftにデプロイすることにします。

### Dockerfile作成
OpenShift上にデプロイするDockerイメージを作成する際は、OpenShift用にいくつか注意点があります。
OpenShiftにデプロイする前提のDockerイメージを作成するために、以下のようなDockerfileを作成します。

```Dockerfile
FROM golang:latest

RUN mkdir /test
COPY main.go /test

RUN chgrp -R 0 /test && \
    chmod -R g=u /test

USER 1001
EXPOSE 8080

CMD export GOCACHE=/test/;go run /test/main.go
```

OpenShift上で稼働させるコンテナーの注意点について補足します。
参考: [OpenShift Container Platform V4.5 - イメージ - 4.1.2. OpenShift Container Platform 固有のガイドライン](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.5/html/images/creating-images#images-create-guide-openshift_create-images)

**注意点: 実行ユーザーについて**
>任意のユーザー ID のサポート
デフォルトでは OpenShift Container Platform は、任意に割り当てられたユーザー ID を使用してコンテナーを実行します。こうすることで、コンテナーエンジンの脆弱性が原因でコンテナーから出ていくプロセスに対して追加のセキュリティーを設定でき、ホストノードでパーミッションのエスカレーションが可能になります。
イメージが任意ユーザーとしての実行をサポートできるように、イメージ内のプロセスで記述されるディレクトリーやファイルは、root グループが所有し、このグループに対して読み取り/書き込みの権限を割り当てる必要があります。実行予定のファイルには、グループの実行権限も必要です。
...
コンテナーユーザーは常に root グループのメンバーであるため、コンテナーユーザーはこれらのファイルに対する読み取り、書き込みが可能です。

OpenShift上で稼働されるコンテナーは上の記述の通り任意のユーザー(rootグループ)で実行されます。DockerfileでUSERを指定する場合root(0)以外の任意のIDが指定できるようですが、慣例的に1001が使われることが多いようです。
コンテナーは基本的にroot(0)以外で実行されますが、グループはroot(0)となっています。そのため、コンテナー実行ユーザーがアクセスするディレクトリ/ファイルはrootグループ(0)に対してアクセス権を付与する必要があります。上の例では、goのソースを配置する/testディレクトリ以下の全ディレクトリ、ファイルのグループをroot(0)に設定し(chgrpコマンド)、かつグループのアクセス権をユーザーと同一に設定しています(chmodコマンド)。
また、goを実行するとキャッシュ用のディレクトリを作成しにいくみたいなので、そのキャッシュディレクトリを権限のある/testにするためにGACACHE環境変数を指定して、`go run`を実行するようにしています。

**注意点: 公開ポートについて**
>さらに、コンテナーで実行中のプロセスは、特権のあるユーザーとして実行されていないので、特権のあるポート (1024 未満のポート) をリッスンできません。

上の通り一般的にコンテナーはroot以外のユーザーで実行されるので、公開するポートは1024以降のポートにする必要があります。(例えばWebサーバーのデフォルトで使用される80番や443番ポートはListenできない)。


### Go言語ソース作成

これは前にサンプルで使ったものそのまま。(8080ポートでHTTPリクエストを受け取って特定メッセージを返すだけのもの)

```go:main.go
package main

import (
        "fmt"
        "log"
        "net/http"
)

func main(){
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request){
                log.Println("received request")
                fmt.Fprintf(w, "Hello Docker!")
        })

        log.Println("start server")
        server := &http.Server{Addr: ":8080"}
        if err := server.ListenAndServe(); err != nil {
                log.Println(err)
        }
}
```

### Dockerイメージのビルド

Dockerfile, main.goファイルが配置されたディレクトリに移動して、podmanコマンドでビルドします。

```
# podman build -t gotest .
STEP 1: FROM golang:latest
STEP 2: RUN mkdir /test
--> Using cache 1a88a0492136d3cf409519d9a9f85f5770cf7402292e66e63ff37e5a501ef3cd
STEP 3: COPY main.go /test
dc11469c6bb956097fc20f62fcd972d24f42d0cdcec66e7b3fd9a4aa23ce173e
STEP 4: RUN chgrp -R 0 /test &&     chmod -R g=u /test
0658e0857abc6dbee41cb29860ee48ad6a6698ea01499b91510d8006884279e2
STEP 5: USER 1001
d992d0076de80bc7ab348186a5a5d75892c7b1ec892e878b4dd82d3b30d26fad
STEP 6: EXPOSE 8080
c502b67a2123bcd5f2e6fd8eef7b4c1e9e0f3e4c07dfb4580698b816beb8925c
STEP 7: CMD ["go", "run", "/test/main.go"]
STEP 8: COMMIT gotest
b133999ccf701ea36d9573be33144ac8e10d1dffb45228834d23496c1a74882a
```

一応ローカルで動かしてみて稼働確認。

```
# podman run --rm -d -p 8080:8080 --name gotest gotest
a049694edb4604401120e8730ecff64b98630e1a8903157194b6e6e29de8101c

[root@Test05 ~/openshift/test/deploy_docker]# curl localhost:8080
Hello Docker!

# podman stop gotest
a049694edb4604401120e8730ecff64b98630e1a8903157194b6e6e29de8101c
```

OKのようです。
Dockerイメージは以下のようにローカルのPodman環境に作成されています。

```
# podman images | grep gotest
localhost/gotest                                  latest   37f0650de76d   50 minutes ago      883 MB
```

### Dockerイメージをレジストリにコピー

ローカルのPodman環境に作成されたDockerイメージをレジストリQuay.ioにコピーします。

```
# podman login -u tomotagwork quay.io
Password:
Login Succeeded!

# skopeo copy containers-storage:localhost/gotest:latest docker://quay.io/tomotagwork/gotest
Getting image source signatures
Copying blob 688e187d6c79 done
Copying blob 9d52e952d0a7 done
Copying blob ccb9b68523fd done
Copying blob 762eb5b089c5 done
Copying blob 685934357c89 done
Copying blob 00bcea93703b done
Copying blob c92e53084342 done
Copying blob 88ed9abc7def done
Copying blob cee2d7433c7e done
Copying blob 3e6fcc1c3d80 done
Copying config b133999ccf done
Writing manifest to image destination
Copying config b133999ccf done
Writing manifest to image destination
Storing signatures
```

Quay.ioのサイトにブラウザからアクセスすると、tomotagwork/gotestというリポジトリが作成されたことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132331/ef161558-dd4b-b364-ec4b-c4c769f254a4.png)

# コンテナのデプロイ
さて、上で準備したDockerイメージをOpenShiftクラスターにデプロイしてみます。

## プロジェクトの作成
ここではtomotag-test01というプロジェクトに作成します。

```
# oc new-project tomotag-test01
Now using project "tomotag-test01" on server "https://xxx.cloud.ibm.com:nnn".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app rails-postgresql-example

to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:

    kubectl create deployment hello-node --image=k8s.gcr.io/serve_hostname
```

## Dockerレジストリーアクセス用シークレット作成

今回はQuay.ioという外部のレジストリ上にあるDockerイメージを使用するので、Quay.ioに対する認証情報を設定しておく必要があります。

参考: [OpenShift Container Platform V4.5 - イメージ - 5.4.2. Pod が他のセキュリティー保護されたレジストリーからイメージを参照できるようにする設定](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.5/html/images/using-image-pull-secrets#images-allow-pods-to-reference-images-from-secure-registries_using-image-pull-secrets)

podmanでレジストリにログインすると、`${XDG_RUNTIME_DIR}/containers/auth.json`ファイルが作成されてここにレジストリへのアクセス情報が格納されます。
参考: [podman-login](http://docs.podman.io/en/latest/markdown/podman-login.1.html)

これを上のガイドに従ってシークレットとして登録し、デフォルトのサービスアカウント(default)に紐づけておきます。

```
# oc create secret generic quayio --from-file .dockerconfigjson=${XDG_RUNTIME_DIR}/containers/auth.json --type kubernetes.io/dockerconfigjson
secret/quayio created
# oc secrets link default quayio --for pull
```

## デプロイ

これで一通り準備は整ったので、いよいよoc new-appコマンドでDockerイメージをデプロイします。

```
# oc new-app --as-deployment-config --name gotest --docker-image quay.io/tomotagwork/gotest
--> Found container image d0a3912 (3 weeks old) from quay.io for "quay.io/tomotagwork/gotest"

    * An image stream tag will be created as "gotest:latest" that will track this image
    * This image will be deployed in deployment config "gotest"
    * Port 8080/tcp will be load balanced by service "gotest"
      * Other containers can access this service through the hostname "gotest"

--> Creating resources ...
    imagestream.image.openshift.io "gotest" created
    deploymentconfig.apps.openshift.io "gotest" created
    service "gotest" created
--> Success
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose service/gotest'
    Run 'oc status' to view your app.
```

これで先に準備したDockerイメージがOpenShiftクラスター上にデプロイされました。

```
# oc get all
NAME                  READY   STATUS      RESTARTS   AGE
pod/gotest-1-deploy   0/1     Completed   0          117s
pod/gotest-1-wfq5w    1/1     Running     0          112s

NAME                             DESIRED   CURRENT   READY   AGE
replicationcontroller/gotest-1   1         1         1       117s

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/gotest   ClusterIP   172.21.xx.xxx   <none>        8080/TCP   119s

NAME                                        REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/gotest   1          1         1         config,image(gotest:latest)

NAME                                    IMAGE REPOSITORY                                                         TAGS     UPDATED
imagestream.image.openshift.io/gotest   image-registry.openshift-image-registry.svc:5000/tomotag-test01/gotest   latest   2 minutes ago
```

# 稼働確認

作成されたserviceをrouteとして公開して実際にアクセスしてみます。

```
# oc get svc
NAME     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
gotest   ClusterIP   172.21.xx.xxx   <none>        8080/TCP   3m11s

# oc expose svc gotest
route.route.openshift.io/gotest exposed

# oc get route
NAME     HOST/PORT                                                                                                            PATH   SERVICES   PORT       TERMINATION   WILDCARD
gotest   gotest-tomotag-test01.xxx.appdomain.cloud          gotest     8080-tcp                 None
```

curlでアクセスしてみる。

```
# curl gotest-tag-test01.xxx.appdomain.cloud
Hello Docker!
```

きちんと結果が返されました！


# 生成されたリソースの確認
oc new-appコマンドで生成されたリソースを確認しておきます。

## 元のDockerイメージの情報(参考)
これはoc new-appで生成されたものではなく、事前に準備しておいたDockerイメージの情報です。値の突合せのために載せておきます。

<details><summary><font color="blue">skopeo inspect docker://quay.io/tomotagwork/gotest:latest</font></summary><div>

```json
{
    "Name": "quay.io/tomotagwork/gotest",
    "Tag": "latest",
    "Digest": "sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31",
    "RepoTags": [
        "latest"
    ],
    "Created": "2021-06-20T05:08:59.847945868Z",
    "DockerVersion": "",
    "Labels": null,
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:47528640bafc58742142cfa0e153cba4b8d266af54e906436351bd6a49d7e5ed",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:b0141febd267c2a990df3786ac8fb691d65b7fa028ef81079b7e4bd5a6b993e3",
        "sha256:4e1fdd77bbac6bfaf67ff8c1e074d31a98e1f8e80bdf7dd4815483b405277d57",
        "sha256:16b46970de2a55311c713efea5927bd9339f3616e38c6158852b1ca9bae63ee5",
        "sha256:236e29628a836a6fdf6227ed8ace133adb2b81880c910d5b89a01be6a7cbab58",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:7e4e360464de08d89aa1aed4418a5668254d8a5a23cea924cc58f44b94e64664",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:992584736a55339d46bad944a150f8c5785136cf2301dc80b46750ce95a6cb27",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:e3c63389e1c4e58e477e63424ae6869f2f683d1a8b480dbfe3e5cebd81e2b506",
        "sha256:c039d1ddde4ca12607bb56530f6bba90dc9242febacb71f4a0842b82ffa16fb9",
        "sha256:a2c9283973328e6780a466f291095c88dc295d4732cbf915a7fedcc5a98322d2",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4",
        "sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4"
    ],
    "Env": [
        "PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
        "GOLANG_VERSION=1.16.5",
        "GOPATH=/go"
    ]
}
```

</div></details>

## ImageStream

<details><summary><font color="blue">oc get is/gotest -o yaml</font></summary><div>

```yaml
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
  annotations:
    openshift.io/generated-by: OpenShiftNewApp
    openshift.io/image.dockerRepositoryCheck: "2021-07-17T05:09:52Z"
  creationTimestamp: "2021-07-17T05:09:50Z"
  generation: 2
  labels:
    app: gotest
    app.kubernetes.io/component: gotest
    app.kubernetes.io/instance: gotest
  managedFields:
  - apiVersion: image.openshift.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:openshift.io/generated-by: {}
        f:labels:
          .: {}
          f:app: {}
          f:app.kubernetes.io/component: {}
          f:app.kubernetes.io/instance: {}
      f:spec:
        f:tags:
          .: {}
          k:{"name":"latest"}:
            .: {}
            f:annotations:
              .: {}
              f:openshift.io/imported-from: {}
            f:from:
              .: {}
              f:kind: {}
              f:name: {}
            f:generation: {}
            f:importPolicy: {}
            f:name: {}
            f:referencePolicy:
              .: {}
              f:type: {}
    manager: oc
    operation: Update
    time: "2021-07-17T05:09:50Z"
  name: gotest
  namespace: tomotag-test01
  resourceVersion: "73087921"
  selfLink: /apis/image.openshift.io/v1/namespaces/tomotag-test01/imagestreams/gotest
  uid: 79d7df94-1647-4f3c-aa76-2ce050f5a080
spec:
  lookupPolicy:
    local: false
  tags:
  - annotations:
      openshift.io/imported-from: quay.io/tomotagwork/gotest
    from:
      kind: DockerImage
      name: quay.io/tomotagwork/gotest
    generation: 2
    importPolicy: {}
    name: latest
    referencePolicy:
      type: Source
status:
  dockerImageRepository: image-registry.openshift-image-registry.svc:5000/tomotag-test01/gotest
  tags:
  - items:
    - created: "2021-07-17T05:09:52Z"
      dockerImageReference: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
      generation: 2
      image: sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    tag: latest
```

</div></details>

<details><summary><font color="blue">oc describe is/gotest</font></summary><div>

```
Name:                   gotest
Namespace:              tomotag-test01
Created:                6 minutes ago
Labels:                 app=gotest
                        app.kubernetes.io/component=gotest
                        app.kubernetes.io/instance=gotest
Annotations:            openshift.io/generated-by=OpenShiftNewApp
                        openshift.io/image.dockerRepositoryCheck=2021-07-17T05:09:52Z
Image Repository:       image-registry.openshift-image-registry.svc:5000/tomotag-test01/gotest
Image Lookup:           local=false
Unique Images:          1
Tags:                   1

latest
  tagged from quay.io/tomotagwork/gotest

  * quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
      6 minutes ago
```

</div></details>



## ImageStreamTag

<details><summary><font color="blue">oc get istag/gotest:latest -o yaml</font></summary><div>

```yaml
apiVersion: image.openshift.io/v1
generation: 2
image:
  dockerImageLayers:
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:47528640bafc58742142cfa0e153cba4b8d266af54e906436351bd6a49d7e5ed
    size: 52190749
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 32
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:b0141febd267c2a990df3786ac8fb691d65b7fa028ef81079b7e4bd5a6b993e3
    size: 8078517
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:4e1fdd77bbac6bfaf67ff8c1e074d31a98e1f8e80bdf7dd4815483b405277d57
    size: 10217855
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:16b46970de2a55311c713efea5927bd9339f3616e38c6158852b1ca9bae63ee5
    size: 54478208
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:236e29628a836a6fdf6227ed8ace133adb2b81880c910d5b89a01be6a7cbab58
    size: 71951156
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:7e4e360464de08d89aa1aed4418a5668254d8a5a23cea924cc58f44b94e64664
    size: 136942435
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:992584736a55339d46bad944a150f8c5785136cf2301dc80b46750ce95a6cb27
    size: 181
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:e3c63389e1c4e58e477e63424ae6869f2f683d1a8b480dbfe3e5cebd81e2b506
    size: 220
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:c039d1ddde4ca12607bb56530f6bba90dc9242febacb71f4a0842b82ffa16fb9
    size: 396
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a2c9283973328e6780a466f291095c88dc295d4732cbf915a7fedcc5a98322d2
    size: 396
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  - mediaType: application/vnd.docker.container.image.rootfs.diff+x-gtar
    name: sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
    size: 0
  dockerImageManifestMediaType: application/vnd.docker.distribution.manifest.v1+json
  dockerImageMetadata:
    Architecture: amd64
    Config:
      Cmd:
      - /bin/sh
      - -c
      - export GOCACHE=/test/;go run /test/main.go
      Env:
      - PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      - GOLANG_VERSION=1.16.5
      - GOPATH=/go
      ExposedPorts:
        8080/tcp: {}
      User: "1001"
      WorkingDir: /go
    ContainerConfig: {}
    Created: "2021-06-20T05:08:59Z"
    Id: d0a39128ff919b1c0c86672d4ffd332566d44da6e843cf8b4fb5b36c22edefb5
    Parent: 207faa5d0628e3642e032c78b52ccf47a6a6770f2876169cbe2fe2b1317dbff6
    Size: 333860145
    apiVersion: "1.0"
    kind: DockerImage
  dockerImageMetadataVersion: "1.0"
  dockerImageReference: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
  metadata:
    annotations:
      image.openshift.io/dockerLayersOrder: ascending
      openshift.io/imported-from: quay.io/tomotagwork/gotest
    creationTimestamp: "2021-07-17T04:48:02Z"
    name: sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    resourceVersion: "73082939"
    uid: 8a505431-0af6-4b5f-a672-f40026f55d40
kind: ImageStreamTag
lookupPolicy:
  local: false
metadata:
  annotations:
    openshift.io/imported-from: quay.io/tomotagwork/gotest
  creationTimestamp: "2021-07-17T05:09:52Z"
  labels:
    app: gotest
    app.kubernetes.io/component: gotest
    app.kubernetes.io/instance: gotest
  name: gotest:latest
  namespace: tomotag-test01
  resourceVersion: "73087921"
  selfLink: /apis/image.openshift.io/v1/namespaces/tomotag-test01/imagestreamtags/gotest:latest
  uid: 79d7df94-1647-4f3c-aa76-2ce050f5a080
tag:
  annotations:
    openshift.io/imported-from: quay.io/tomotagwork/gotest
  from:
    kind: DockerImage
    name: quay.io/tomotagwork/gotest
  generation: 2
  importPolicy: {}
  name: latest
  referencePolicy:
    type: Source
```

</div></details>


<details><summary><font color="blue">oc describe istag/gotest:latest</font></summary><div>

```
Image Name:     sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
Docker Image:   quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
Name:           sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
Created:        29 minutes ago
Annotations:    image.openshift.io/dockerLayersOrder=ascending
                openshift.io/imported-from=quay.io/tomotagwork/gotest
Image Size:     333.9MB in 19 layers
Layers:         52.19MB sha256:47528640bafc58742142cfa0e153cba4b8d266af54e906436351bd6a49d7e5ed
                32B     sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                8.079MB sha256:b0141febd267c2a990df3786ac8fb691d65b7fa028ef81079b7e4bd5a6b993e3
                10.22MB sha256:4e1fdd77bbac6bfaf67ff8c1e074d31a98e1f8e80bdf7dd4815483b405277d57
                54.48MB sha256:16b46970de2a55311c713efea5927bd9339f3616e38c6158852b1ca9bae63ee5
                71.95MB sha256:236e29628a836a6fdf6227ed8ace133adb2b81880c910d5b89a01be6a7cbab58
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                136.9MB sha256:7e4e360464de08d89aa1aed4418a5668254d8a5a23cea924cc58f44b94e64664
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                181B    sha256:992584736a55339d46bad944a150f8c5785136cf2301dc80b46750ce95a6cb27
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                220B    sha256:e3c63389e1c4e58e477e63424ae6869f2f683d1a8b480dbfe3e5cebd81e2b506
                396B    sha256:c039d1ddde4ca12607bb56530f6bba90dc9242febacb71f4a0842b82ffa16fb9
                396B    sha256:a2c9283973328e6780a466f291095c88dc295d4732cbf915a7fedcc5a98322d2
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
                0B      sha256:a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
Image Created:  3 weeks ago
Author:         <none>
Arch:           amd64
Command:        /bin/sh -c export GOCACHE=/test/;go run /test/main.go
Working Dir:    /go
User:           1001
Exposes Ports:  8080/tcp
Docker Labels:  <none>
Environment:    PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                GOLANG_VERSION=1.16.5
                GOPATH=/go
```

</div></details>

## DeploymentConfig

<details><summary><font color="blue">oc get dc/gotest -o yaml</font></summary><div>

```yaml
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
  annotations:
    openshift.io/generated-by: OpenShiftNewApp
  creationTimestamp: "2021-07-17T05:09:51Z"
  generation: 2
  labels:
    app: gotest
    app.kubernetes.io/component: gotest
    app.kubernetes.io/instance: gotest
  managedFields:
  - apiVersion: apps.openshift.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:openshift.io/generated-by: {}
        f:labels:
          .: {}
          f:app: {}
          f:app.kubernetes.io/component: {}
          f:app.kubernetes.io/instance: {}
      f:spec:
        f:replicas: {}
        f:selector:
          .: {}
          f:deploymentconfig: {}
        f:strategy:
          f:activeDeadlineSeconds: {}
          f:rollingParams:
            .: {}
            f:intervalSeconds: {}
            f:maxSurge: {}
            f:maxUnavailable: {}
            f:timeoutSeconds: {}
            f:updatePeriodSeconds: {}
          f:type: {}
        f:template:
          .: {}
          f:metadata:
            .: {}
            f:annotations:
              .: {}
              f:openshift.io/generated-by: {}
            f:creationTimestamp: {}
            f:labels:
              .: {}
              f:deploymentconfig: {}
          f:spec:
            .: {}
            f:containers:
              .: {}
              k:{"name":"gotest"}:
                .: {}
                f:imagePullPolicy: {}
                f:name: {}
                f:ports:
                  .: {}
                  k:{"containerPort":8080,"protocol":"TCP"}:
                    .: {}
                    f:containerPort: {}
                    f:protocol: {}
                f:resources: {}
                f:terminationMessagePath: {}
                f:terminationMessagePolicy: {}
            f:dnsPolicy: {}
            f:restartPolicy: {}
            f:schedulerName: {}
            f:securityContext: {}
            f:terminationGracePeriodSeconds: {}
    manager: oc
    operation: Update
    time: "2021-07-17T05:09:51Z"
  - apiVersion: apps.openshift.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:spec:
        f:template:
          f:spec:
            f:containers:
              k:{"name":"gotest"}:
                f:image: {}
        f:triggers: {}
      f:status:
        f:availableReplicas: {}
        f:conditions:
          .: {}
          k:{"type":"Available"}:
            .: {}
            f:lastTransitionTime: {}
            f:lastUpdateTime: {}
            f:message: {}
            f:status: {}
            f:type: {}
          k:{"type":"Progressing"}:
            .: {}
            f:lastTransitionTime: {}
            f:lastUpdateTime: {}
            f:message: {}
            f:reason: {}
            f:status: {}
            f:type: {}
        f:details:
          .: {}
          f:causes: {}
          f:message: {}
        f:latestVersion: {}
        f:observedGeneration: {}
        f:readyReplicas: {}
        f:replicas: {}
        f:unavailableReplicas: {}
        f:updatedReplicas: {}
    manager: openshift-controller-manager
    operation: Update
    time: "2021-07-17T05:10:07Z"
  name: gotest
  namespace: tomotag-test01
  resourceVersion: "73088023"
  selfLink: /apis/apps.openshift.io/v1/namespaces/tomotag-test01/deploymentconfigs/gotest
  uid: eb282767-5434-4388-8aa9-ee32d81d8c21
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    deploymentconfig: gotest
  strategy:
    activeDeadlineSeconds: 21600
    resources: {}
    rollingParams:
      intervalSeconds: 1
      maxSurge: 25%
      maxUnavailable: 25%
      timeoutSeconds: 600
      updatePeriodSeconds: 1
    type: Rolling
  template:
    metadata:
      annotations:
        openshift.io/generated-by: OpenShiftNewApp
      creationTimestamp: null
      labels:
        deploymentconfig: gotest
    spec:
      containers:
      - image: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
        imagePullPolicy: Always
        name: gotest
        ports:
        - containerPort: 8080
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
  test: false
  triggers:
  - type: ConfigChange
  - imageChangeParams:
      automatic: true
      containerNames:
      - gotest
      from:
        kind: ImageStreamTag
        name: gotest:latest
        namespace: tomotag-test01
      lastTriggeredImage: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    type: ImageChange
status:
  availableReplicas: 1
  conditions:
  - lastTransitionTime: "2021-07-17T05:10:06Z"
    lastUpdateTime: "2021-07-17T05:10:06Z"
    message: Deployment config has minimum availability.
    status: "True"
    type: Available
  - lastTransitionTime: "2021-07-17T05:09:57Z"
    lastUpdateTime: "2021-07-17T05:10:07Z"
    message: replication controller "gotest-1" successfully rolled out
    reason: NewReplicationControllerAvailable
    status: "True"
    type: Progressing
  details:
    causes:
    - type: ConfigChange
    message: config change
  latestVersion: 1
  observedGeneration: 2
  readyReplicas: 1
  replicas: 1
  unavailableReplicas: 0
  updatedReplicas: 1
```

</div></details>


<details><summary><font color="blue">oc describe dc/gotest</font></summary><div>

```
Name:           gotest
Namespace:      tomotag-test01
Created:        9 minutes ago
Labels:         app=gotest
                app.kubernetes.io/component=gotest
                app.kubernetes.io/instance=gotest
Annotations:    openshift.io/generated-by=OpenShiftNewApp
Latest Version: 1
Selector:       deploymentconfig=gotest
Replicas:       1
Triggers:       Config, Image(gotest@latest, auto=true)
Strategy:       Rolling
Template:
Pod Template:
  Labels:       deploymentconfig=gotest
  Annotations:  openshift.io/generated-by: OpenShiftNewApp
  Containers:
   gotest:
    Image:              quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    Port:               8080/TCP
    Host Port:          0/TCP
    Environment:        <none>
    Mounts:             <none>
  Volumes:              <none>

Deployment #1 (latest):
        Name:           gotest-1
        Created:        9 minutes ago
        Status:         Complete
        Replicas:       1 current / 1 desired
        Selector:       deployment=gotest-1,deploymentconfig=gotest
        Labels:         app.kubernetes.io/component=gotest,app.kubernetes.io/instance=gotest,app=gotest,openshift.io/deployment-config.name=gotest
        Pods Status:    1 Running / 0 Waiting / 0 Succeeded / 0 Failed

Events:
  Type          Reason                  Age     From                            Message
  ----          ------                  ----    ----                            -------
  Normal        DeploymentCreated       9m40s   deploymentconfig-controller     Created new replication controller "gotest-1" for version 1
```

</div></details>

## ReplicationController

<details><summary><font color="blue">oc get rc/gotest-1 -o yaml</font></summary><div>

```yaml
apiVersion: v1
kind: ReplicationController
metadata:
  annotations:
    openshift.io/deployer-pod.completed-at: 2021-07-17 05:10:06 +0000 UTC
    openshift.io/deployer-pod.created-at: 2021-07-17 05:09:52 +0000 UTC
    openshift.io/deployer-pod.name: gotest-1-deploy
    openshift.io/deployment-config.latest-version: "1"
    openshift.io/deployment-config.name: gotest
    openshift.io/deployment.phase: Complete
    openshift.io/deployment.replicas: "1"
    openshift.io/deployment.status-reason: config change
    openshift.io/encoded-deployment-config: |
      {"kind":"DeploymentConfig","apiVersion":"apps.openshift.io/v1","metadata":{"name":"gotest","namespace":"tomotag-test01","selfLink":"/apis/apps.openshift.io/v1/namespaces/tomotag-test01/deploymentconfigs/gotest","uid":"eb282767-5434-4388-8aa9-ee32d81d8c21","resourceVersion":"73087924","generation":2,"creationTimestamp":"2021-07-17T05:09:51Z","labels":{"app":"gotest","app.kubernetes.io/component":"gotest","app.kubernetes.io/instance":"gotest"},"annotations":{"openshift.io/generated-by":"OpenShiftNewApp"},"managedFields":[{"manager":"oc","operation":"Update","apiVersion":"apps.openshift.io/v1","time":"2021-07-17T05:09:51Z","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:openshift.io/generated-by":{}},"f:labels":{".":{},"f:app":{},"f:app.kubernetes.io/component":{},"f:app.kubernetes.io/instance":{}}},"f:spec":{"f:replicas":{},"f:selector":{".":{},"f:deploymentconfig":{}},"f:strategy":{"f:activeDeadlineSeconds":{},"f:rollingParams":{".":{},"f:intervalSeconds":{},"f:maxSurge":{},"f:maxUnavailable":{},"f:timeoutSeconds":{},"f:updatePeriodSeconds":{}},"f:type":{}},"f:template":{".":{},"f:metadata":{".":{},"f:annotations":{".":{},"f:openshift.io/generated-by":{}},"f:creationTimestamp":{},"f:labels":{".":{},"f:deploymentconfig":{}}},"f:spec":{".":{},"f:containers":{".":{},"k:{\"name\":\"gotest\"}":{".":{},"f:imagePullPolicy":{},"f:name":{},"f:ports":{".":{},"k:{\"containerPort\":8080,\"protocol\":\"TCP\"}":{".":{},"f:containerPort":{},"f:protocol":{}}},"f:resources":{},"f:terminationMessagePath":{},"f:terminationMessagePolicy":{}}},"f:dnsPolicy":{},"f:restartPolicy":{},"f:schedulerName":{},"f:securityContext":{},"f:terminationGracePeriodSeconds":{}}}}}},{"manager":"openshift-controller-manager","operation":"Update","apiVersion":"apps.openshift.io/v1","time":"2021-07-17T05:09:52Z","fieldsType":"FieldsV1","fieldsV1":{"f:spec":{"f:template":{"f:spec":{"f:containers":{"k:{\"name\":\"gotest\"}":{"f:image":{}}}}},"f:triggers":{}},"f:status":{"f:conditions":{".":{},"k:{\"type\":\"Available\"}":{".":{},"f:lastTransitionTime":{},"f:lastUpdateTime":{},"f:message":{},"f:status":{},"f:type":{}}},"f:details":{".":{},"f:causes":{},"f:message":{}},"f:latestVersion":{},"f:observedGeneration":{}}}}]},"spec":{"strategy":{"type":"Rolling","rollingParams":{"updatePeriodSeconds":1,"intervalSeconds":1,"timeoutSeconds":600,"maxUnavailable":"25%","maxSurge":"25%"},"resources":{},"activeDeadlineSeconds":21600},"triggers":[{"type":"ConfigChange"},{"type":"ImageChange","imageChangeParams":{"automatic":true,"containerNames":["gotest"],"from":{"kind":"ImageStreamTag","namespace":"tomotag-test01","name":"gotest:latest"},"lastTriggeredImage":"quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31"}}],"replicas":1,"revisionHistoryLimit":10,"test":false,"selector":{"deploymentconfig":"gotest"},"template":{"metadata":{"creationTimestamp":null,"labels":{"deploymentconfig":"gotest"},"annotations":{"openshift.io/generated-by":"OpenShiftNewApp"}},"spec":{"containers":[{"name":"gotest","image":"quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31","ports":[{"containerPort":8080,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"Always"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","securityContext":{},"schedulerName":"default-scheduler"}}},"status":{"latestVersion":1,"observedGeneration":1,"replicas":0,"updatedReplicas":0,"availableReplicas":0,"unavailableReplicas":0,"details":{"message":"config change","causes":[{"type":"ConfigChange"}]},"conditions":[{"type":"Available","status":"False","lastUpdateTime":"2021-07-17T05:09:51Z","lastTransitionTime":"2021-07-17T05:09:51Z","message":"Deployment config does not have minimum availability."}]}}
  creationTimestamp: "2021-07-17T05:09:52Z"
  generation: 2
  labels:
    app: gotest
    app.kubernetes.io/component: gotest
    app.kubernetes.io/instance: gotest
    openshift.io/deployment-config.name: gotest
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:status:
        f:availableReplicas: {}
        f:fullyLabeledReplicas: {}
        f:observedGeneration: {}
        f:readyReplicas: {}
        f:replicas: {}
    manager: kube-controller-manager
    operation: Update
    time: "2021-07-17T05:10:06Z"
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:openshift.io/deployer-pod.completed-at: {}
          f:openshift.io/deployer-pod.created-at: {}
          f:openshift.io/deployer-pod.name: {}
          f:openshift.io/deployment-config.latest-version: {}
          f:openshift.io/deployment-config.name: {}
          f:openshift.io/deployment.phase: {}
          f:openshift.io/deployment.replicas: {}
          f:openshift.io/deployment.status-reason: {}
          f:openshift.io/encoded-deployment-config: {}
        f:labels:
          .: {}
          f:app: {}
          f:app.kubernetes.io/component: {}
          f:app.kubernetes.io/instance: {}
          f:openshift.io/deployment-config.name: {}
        f:ownerReferences:
          .: {}
          k:{"uid":"eb282767-5434-4388-8aa9-ee32d81d8c21"}:
            .: {}
            f:apiVersion: {}
            f:blockOwnerDeletion: {}
            f:controller: {}
            f:kind: {}
            f:name: {}
            f:uid: {}
      f:spec:
        f:replicas: {}
        f:selector:
          .: {}
          f:deployment: {}
          f:deploymentconfig: {}
        f:template:
          .: {}
          f:metadata:
            .: {}
            f:annotations:
              .: {}
              f:openshift.io/deployment-config.latest-version: {}
              f:openshift.io/deployment-config.name: {}
              f:openshift.io/deployment.name: {}
              f:openshift.io/generated-by: {}
            f:creationTimestamp: {}
            f:labels:
              .: {}
              f:deployment: {}
              f:deploymentconfig: {}
          f:spec:
            .: {}
            f:containers:
              .: {}
              k:{"name":"gotest"}:
                .: {}
                f:image: {}
                f:imagePullPolicy: {}
                f:name: {}
                f:ports:
                  .: {}
                  k:{"containerPort":8080,"protocol":"TCP"}:
                    .: {}
                    f:containerPort: {}
                    f:protocol: {}
                f:resources: {}
                f:terminationMessagePath: {}
                f:terminationMessagePolicy: {}
            f:dnsPolicy: {}
            f:restartPolicy: {}
            f:schedulerName: {}
            f:securityContext: {}
            f:terminationGracePeriodSeconds: {}
    manager: openshift-controller-manager
    operation: Update
    time: "2021-07-17T05:10:07Z"
  name: gotest-1
  namespace: tomotag-test01
  ownerReferences:
  - apiVersion: apps.openshift.io/v1
    blockOwnerDeletion: true
    controller: true
    kind: DeploymentConfig
    name: gotest
    uid: eb282767-5434-4388-8aa9-ee32d81d8c21
  resourceVersion: "73088022"
  selfLink: /api/v1/namespaces/tomotag-test01/replicationcontrollers/gotest-1
  uid: e54cbeb7-1576-48d4-b5b3-858ae37078b0
spec:
  replicas: 1
  selector:
    deployment: gotest-1
    deploymentconfig: gotest
  template:
    metadata:
      annotations:
        openshift.io/deployment-config.latest-version: "1"
        openshift.io/deployment-config.name: gotest
        openshift.io/deployment.name: gotest-1
        openshift.io/generated-by: OpenShiftNewApp
      creationTimestamp: null
      labels:
        deployment: gotest-1
        deploymentconfig: gotest
    spec:
      containers:
      - image: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
        imagePullPolicy: Always
        name: gotest
        ports:
        - containerPort: 8080
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 1
  fullyLabeledReplicas: 1
  observedGeneration: 2
  readyReplicas: 1
  replicas: 1
```

</div></details>

<details><summary><font color="blue">oc describe rc/gotest-1</font></summary><div>

```
Name:         gotest-1
Namespace:    tomotag-test01
Selector:     deployment=gotest-1,deploymentconfig=gotest
Labels:       app=gotest
              app.kubernetes.io/component=gotest
              app.kubernetes.io/instance=gotest
              openshift.io/deployment-config.name=gotest
Annotations:  openshift.io/deployer-pod.completed-at: 2021-07-17 05:10:06 +0000 UTC
              openshift.io/deployer-pod.created-at: 2021-07-17 05:09:52 +0000 UTC
              openshift.io/deployer-pod.name: gotest-1-deploy
              openshift.io/deployment-config.latest-version: 1
              openshift.io/deployment-config.name: gotest
              openshift.io/deployment.phase: Complete
              openshift.io/deployment.replicas: 1
              openshift.io/deployment.status-reason: config change
              openshift.io/encoded-deployment-config:
                {"kind":"DeploymentConfig","apiVersion":"apps.openshift.io/v1","metadata":{"name":"gotest","namespace":"tomotag-test01","selfLink":"/apis/...
Replicas:     1 current / 1 desired
Pods Status:  1 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
  Labels:       deployment=gotest-1
                deploymentconfig=gotest
  Annotations:  openshift.io/deployment-config.latest-version: 1
                openshift.io/deployment-config.name: gotest
                openshift.io/deployment.name: gotest-1
                openshift.io/generated-by: OpenShiftNewApp
  Containers:
   gotest:
    Image:        quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    Port:         8080/TCP
    Host Port:    0/TCP
    Environment:  <none>
    Mounts:       <none>
  Volumes:        <none>
Events:
  Type    Reason            Age   From                    Message
  ----    ------            ----  ----                    -------
  Normal  SuccessfulCreate  13m   replication-controller  Created pod: gotest-1-wfq5w
```

</div></details>

## Pod

<details><summary><font color="blue">oc get pod/gotest-1-wfq5w -o yaml</font></summary><div>

```yaml
apiVersion: v1
kind: Pod
metadata:
  annotations:
    cni.projectcalico.org/podIP: 172.30.xx.xxx/32
    cni.projectcalico.org/podIPs: 172.30.xx.xxx/32
    k8s.v1.cni.cncf.io/network-status: |-
      [{
          "name": "k8s-pod-network",
          "ips": [
              "172.30.xx.xxx"
          ],
          "default": true,
          "dns": {}
      }]
    k8s.v1.cni.cncf.io/networks-status: |-
      [{
          "name": "k8s-pod-network",
          "ips": [
              "172.30.xx.xxx"
          ],
          "default": true,
          "dns": {}
      }]
    openshift.io/deployment-config.latest-version: "1"
    openshift.io/deployment-config.name: gotest
    openshift.io/deployment.name: gotest-1
    openshift.io/generated-by: OpenShiftNewApp
    openshift.io/scc: dbb-scc
  creationTimestamp: "2021-07-17T05:09:57Z"
  generateName: gotest-1-
  labels:
    deployment: gotest-1
    deploymentconfig: gotest
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:openshift.io/deployment-config.latest-version: {}
          f:openshift.io/deployment-config.name: {}
          f:openshift.io/deployment.name: {}
          f:openshift.io/generated-by: {}
        f:generateName: {}
        f:labels:
          .: {}
          f:deployment: {}
          f:deploymentconfig: {}
        f:ownerReferences:
          .: {}
          k:{"uid":"e54cbeb7-1576-48d4-b5b3-858ae37078b0"}:
            .: {}
            f:apiVersion: {}
            f:blockOwnerDeletion: {}
            f:controller: {}
            f:kind: {}
            f:name: {}
            f:uid: {}
      f:spec:
        f:containers:
          k:{"name":"gotest"}:
            .: {}
            f:image: {}
            f:imagePullPolicy: {}
            f:name: {}
            f:ports:
              .: {}
              k:{"containerPort":8080,"protocol":"TCP"}:
                .: {}
                f:containerPort: {}
                f:protocol: {}
            f:resources: {}
            f:terminationMessagePath: {}
            f:terminationMessagePolicy: {}
        f:dnsPolicy: {}
        f:enableServiceLinks: {}
        f:restartPolicy: {}
        f:schedulerName: {}
        f:securityContext: {}
        f:terminationGracePeriodSeconds: {}
    manager: kube-controller-manager
    operation: Update
    time: "2021-07-17T05:09:57Z"
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          f:cni.projectcalico.org/podIP: {}
          f:cni.projectcalico.org/podIPs: {}
    manager: calico
    operation: Update
    time: "2021-07-17T05:09:59Z"
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          f:k8s.v1.cni.cncf.io/network-status: {}
          f:k8s.v1.cni.cncf.io/networks-status: {}
    manager: multus
    operation: Update
    time: "2021-07-17T05:09:59Z"
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:status:
        f:conditions:
          k:{"type":"ContainersReady"}:
            .: {}
            f:lastProbeTime: {}
            f:lastTransitionTime: {}
            f:status: {}
            f:type: {}
          k:{"type":"Initialized"}:
            .: {}
            f:lastProbeTime: {}
            f:lastTransitionTime: {}
            f:status: {}
            f:type: {}
          k:{"type":"Ready"}:
            .: {}
            f:lastProbeTime: {}
            f:lastTransitionTime: {}
            f:status: {}
            f:type: {}
        f:containerStatuses: {}
        f:hostIP: {}
        f:phase: {}
        f:podIP: {}
        f:podIPs:
          .: {}
          k:{"ip":"172.30.xx.xxx"}:
            .: {}
            f:ip: {}
        f:startTime: {}
    manager: kubelet
    operation: Update
    time: "2021-07-17T05:10:06Z"
  name: gotest-1-wfq5w
  namespace: tomotag-test01
  ownerReferences:
  - apiVersion: v1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicationController
    name: gotest-1
    uid: e54cbeb7-1576-48d4-b5b3-858ae37078b0
  resourceVersion: "73088014"
  selfLink: /api/v1/namespaces/tomotag-test01/pods/gotest-1-wfq5w
  uid: 1abeabf5-9173-43f1-bc5d-95320a74d361
spec:
  containers:
  - image: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    imagePullPolicy: Always
    name: gotest
    ports:
    - containerPort: 8080
      protocol: TCP
    resources: {}
    securityContext:
      capabilities:
        drop:
        - KILL
        - MKNOD
        - SETGID
        - SETUID
      runAsUser: 1000640000
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-4jrqd
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  imagePullSecrets:
  - name: default-dockercfg-lm9b2
  - name: quayio
  nodeName: 10.129.xxx.xx
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext:
    fsGroup: 1000640000
    seLinuxOptions:
      level: s0:c25,c20
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: default-token-4jrqd
    secret:
      defaultMode: 420
      secretName: default-token-4jrqd
status:
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2021-07-17T05:09:57Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2021-07-17T05:10:06Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2021-07-17T05:10:06Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2021-07-17T05:09:57Z"
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: cri-o://233734b9d28cd8cb0cdab96af7c903fa86baea0a50b95d01fda2d212446c91c5
    image: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    imageID: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    lastState: {}
    name: gotest
    ready: true
    restartCount: 0
    started: true
    state:
      running:
        startedAt: "2021-07-17T05:10:05Z"
  hostIP: 10.129.xxx.xx
  phase: Running
  podIP: 172.30.xx.xxx
  podIPs:
  - ip: 172.30.xx.xxx
  qosClass: BestEffort
  startTime: "2021-07-17T05:09:57Z"
```

</div></details>


<details><summary><font color="blue">oc describe pod/gotest-1-wfq5w</font></summary><div>

```
Name:         gotest-1-wfq5w
Namespace:    tomotag-test01
Priority:     0
Node:         10.129.176.11/10.129.176.11
Start Time:   Sat, 17 Jul 2021 14:09:57 +0900
Labels:       deployment=gotest-1
              deploymentconfig=gotest
Annotations:  cni.projectcalico.org/podIP: 172.30.19.137/32
              cni.projectcalico.org/podIPs: 172.30.19.137/32
              k8s.v1.cni.cncf.io/network-status:
                [{
                    "name": "k8s-pod-network",
                    "ips": [
                        "172.30.19.137"
                    ],
                    "default": true,
                    "dns": {}
                }]
              k8s.v1.cni.cncf.io/networks-status:
                [{
                    "name": "k8s-pod-network",
                    "ips": [
                        "172.30.19.137"
                    ],
                    "default": true,
                    "dns": {}
                }]
              openshift.io/deployment-config.latest-version: 1
              openshift.io/deployment-config.name: gotest
              openshift.io/deployment.name: gotest-1
              openshift.io/generated-by: OpenShiftNewApp
              openshift.io/scc: dbb-scc
Status:       Running
IP:           172.30.19.137
IPs:
  IP:           172.30.19.137
Controlled By:  ReplicationController/gotest-1
Containers:
  gotest:
    Container ID:   cri-o://233734b9d28cd8cb0cdab96af7c903fa86baea0a50b95d01fda2d212446c91c5
    Image:          quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    Image ID:       quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    Port:           8080/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Sat, 17 Jul 2021 14:10:05 +0900
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-4jrqd (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-4jrqd:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-4jrqd
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
  Type    Reason          Age   From               Message
  ----    ------          ----  ----               -------
  Normal  Scheduled       15m   default-scheduler  Successfully assigned tomotag-test01/gotest-1-wfq5w to 10.129.176.11
  Normal  AddedInterface  15m   multus             Add eth0 [172.30.19.137/32]
  Normal  Pulling         15m   kubelet            Pulling image "quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31"
  Normal  Pulled          15m   kubelet            Successfully pulled image "quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31"
  Normal  Created         15m   kubelet            Created container gotest
  Normal  Started         15m   kubelet            Started container gotest
```

</div></details>

## Service

<details><summary><font color="blue">oc get svc/gotest -o yaml</font></summary><div>

```yaml
apiVersion: v1
kind: Service
metadata:
  annotations:
    openshift.io/generated-by: OpenShiftNewApp
  creationTimestamp: "2021-07-17T05:09:51Z"
  labels:
    app: gotest
    app.kubernetes.io/component: gotest
    app.kubernetes.io/instance: gotest
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:metadata:
        f:annotations:
          .: {}
          f:openshift.io/generated-by: {}
        f:labels:
          .: {}
          f:app: {}
          f:app.kubernetes.io/component: {}
          f:app.kubernetes.io/instance: {}
      f:spec:
        f:ports:
          .: {}
          k:{"port":8080,"protocol":"TCP"}:
            .: {}
            f:name: {}
            f:port: {}
            f:protocol: {}
            f:targetPort: {}
        f:selector:
          .: {}
          f:deploymentconfig: {}
        f:sessionAffinity: {}
        f:type: {}
    manager: oc
    operation: Update
    time: "2021-07-17T05:09:51Z"
  name: gotest
  namespace: tomotag-test01
  resourceVersion: "73087916"
  selfLink: /api/v1/namespaces/tomotag-test01/services/gotest
  uid: 79a4e488-7a6b-417e-8bc7-cf27a9d9fa94
spec:
  clusterIP: 172.21.xx.xxx
  ports:
  - name: 8080-tcp
    port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    deploymentconfig: gotest
  sessionAffinity: None
  type: ClusterIP
status:
  loadBalancer: {}
```

</div></details>

<details><summary><font color="blue">oc describe svc/gotest</font></summary><div>

```
Name:              gotest
Namespace:         tomotag-test01
Labels:            app=gotest
                   app.kubernetes.io/component=gotest
                   app.kubernetes.io/instance=gotest
Annotations:       openshift.io/generated-by: OpenShiftNewApp
Selector:          deploymentconfig=gotest
Type:              ClusterIP
IP:                172.21.xx.xxx
Port:              8080-tcp  8080/TCP
TargetPort:        8080/TCP
Endpoints:         172.30.xx.xxx:8080
Session Affinity:  None
Events:            <none>
```

</div></details>


# 補足

## ImageStream/ImageStreamTagについて

OpenShift上では元になるDockerイメージを抽象化してImageStream/ImageStreamTagというリソースで管理するようです。

Quai.io上にあるデプロイ対象のイメージの情報(skopeo inspect結果)のDigestを見てみます。

```json:Dockerイメージのinspect抜粋
...
"Digest": "sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31",
...
```

ImageStreamを見ると、上のハッシュ値を参照していることが分かります。

```yaml:ImageStream抜粋
...
status:
  dockerImageRepository: image-registry.openshift-image-registry.svc:5000/tomotag-test01/gotest
  tags:
  - items:
    - created: "2021-07-17T05:09:52Z"
      dockerImageReference: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
      generation: 2
      image: sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    tag: latest
```

dockerImageRepositoryに`image-registry.openshift-image-registry.svc:5000/xxx`という指定がされています。これはOpenShiftクラスター上にある内部レジストリを指しています。内部レジストリ上ではプロジェクト名(namespace名)の下にイメージがコピーされるようです。
参考: [OpenShift Container Platform V4.5 - イメージ - 6.2. イメージストリームの設定](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.5/html/images/images-imagestream-configure_image-streams-managing)

DeploymentConfigも見てみます。こちらのconteinerの元になるイメージもハッシュ値が付いた値になっています。さらにImageStreamTagの変更に基づいたトリガーが設定されています。

```yaml:DeploymentConfig抜粋
...
  template:
    metadata:
      annotations:
        openshift.io/generated-by: OpenShiftNewApp
      creationTimestamp: null
      labels:
        deploymentconfig: gotest
    spec:
      containers:
      - image: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
        imagePullPolicy: Always
        name: gotest

...

  triggers:
  - type: ConfigChange
  - imageChangeParams:
      automatic: true
      containerNames:
      - gotest
      from:
        kind: ImageStreamTag
        name: gotest:latest
        namespace: tomotag-test01
      lastTriggeredImage: quay.io/tomotagwork/gotest@sha256:7abe387cf9e3bc876259271fc13c59e532145b9a1c3c26dba4c3933ca5bb5f31
    type: ImageChange
...
```

## ラベルについて
oc new-appコマンドの`--name`で指定した名前が`app`というラベルに指定されて、各リソースが生成されます。従って、ラベル指定することで関連するリソースを一括で管理できます。

```
# oc get all -l app=gotest
NAME                             DESIRED   CURRENT   READY   AGE
replicationcontroller/gotest-1   1         1         1       99m

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/gotest   ClusterIP   172.21.xx.xxx   <none>        8080/TCP   99m

NAME                                        REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/gotest   1          1         1         config,image(gotest:latest)

NAME                                    IMAGE REPOSITORY                                                         TAGS     UPDATED
imagestream.image.openshift.io/gotest   image-registry.openshift-image-registry.svc:5000/tomotag-test01/gotest   latest   2 hours ago

NAME                              HOST/PORT                                                                                                            PATH   SERVICES   PORT       TERMINATION   WILDCARD
route.route.openshift.io/gotest   gotest-tomotag-test01.xxx.appdomain.cloud          gotest     8080-tcp                 None
```

その他、`oc delete all -l app=gotest` でgotestに関するリソースのみ全削除するなど。


## DeploymentConfig/ReplicationControllerについて
oc new-appコマンド実行時に、OpenShift V4.4まではデフォルトではDeploymentConfig/ReplicationControllerが作成されますが、V4.5以降ではデフォルトでDeployment/ReplicaSetが作成されるようです。(前者はOpenShift固有リソース、後者はKubernetesと互換のリソースです。)
両者は基本的には同じような位置づけのリソースですが微妙に特性が違うらしく、ざっくり言うと前者は整合性重視、後者は可用性重視の挙動になっているようです。
今回はoc new-appコマンド実行時に --as-deploymentConfigオプションを指定することで明示的にDeploymentConfig/ReplicationControllerを生成させるようにしています。

参考: 
[OpenShift Container Platform V4.5 - アプリケーション- 3.1. Deployment および DeploymentConfig オブジェクトについて](https://access.redhat.com/documentation/ja-jp/openshift_container_platform/4.5/html/applications/deployments#what-deployments-are)
[OpenShift DeploymentConfigとKubernetes Deploymentの違い](https://nishipy.com/archives/1731)
[OpenShift学習メモ](https://note.com/tkhm_dev/n/nc11ff074df3e)