CLOVER🍀

That was when it all began.

OKD/Minishiftで、Across Environments Image Promotion

これは、なにをしたくて書いたもの?

  • OpenShift(OKD)上で、Project(Namespace)を跨いでアプリケーションを使いたい
  • イメージ的には、開発用Projectで作ったアプリケーションを、本番用Projectに展開するといった感じ

このような話を、Promotionと呼ぶようです。

今回は、こちらを試してみます。

お題

上述のそのままで、以下のことをやります。

  • 開発用Projectと、そのProjectに所属するユーザーを作成する
  • 本番用Projectと、そのProjectに所属するユーザーを作成する
  • 開発用Projectに、単純なアプリケーションをGitリポジトリを指定してデプロイする
  • 本番用Projectからは、開発用Projectで作成したアプリケーションのイメージをデプロイする
  • 開発用Projectでアプリケーションをアップデートし、本番用Projectに反映する

Promoting Applications Across Environments

参考にしたのは、こちらのドキュメントとブログエントリ。

Promoting Applications Across Environments - Application Life Cycle Management | Developer Guide | OKD 3.11

Promoting Applications Across Environments – Red Hat OpenShift Blog

開発用Projectでビルドとデプロイを行い、本番用ProjectにPromotionする流れが書いてあります。

もちろん、アプリケーションのイメージだけあってもダメなので、RouteやConfigMapとかSecretとか、いろいろ個別に
考慮するものはあるようなのですが、今回はシンプルにアプリケーションにフォーカスします。
Promoting Applications Across Environments - Application Life Cycle Management | Developer Guide | OKD 3.11参照

環境

今回の環境は、こちら。

$ minishift version
minishift v1.27.0+707887e


$ oc version
oc v3.11.0+0cbc58b
kubernetes v1.11.0+d4cacc0
features: Basic-Auth GSSAPI Kerberos SPNEGO

Server https://192.168.42.132:8443
kubernetes v1.11.0+d4cacc0

サンプルアプリケーション

今回は、Node.jsで簡単なサンプルアプリケーションを作成します。

Expressを使った、サーバーにしましょう。

$ npm i express

インストールされたExpressのバージョンは、こちら。

  "dependencies": {
    "express": "^4.16.4"
  }

アプリケーションは、単にバージョン付きのメッセージを返すだけにします。 server.js

const express = require('express');
const app = express();

const version = '1.0';

app.get('/', (req, res) => res.send(`this app version = ${version}`));

console.log(`[${new Date()}] server startup.`);

app.listen(8080);

package.json上のscripts指定は、こんな感じで。

  "scripts": {
    "start": "node server.js"
  },

このソースコードを、Gitリポジトリに登録しておきます。

開発用Projectでのビルド・デプロイと、本番用ProjectへのPromotion

では、作成したアプリケーションをデプロイしたりしていきましょう。

まず、OKD上に開発用ProjectのユーザーとProjectそのものを作成します。

## 開発用のユーザー&Project
$ oc login https://$(minishift ip):8443 -u dev-user1
$ oc new-project dev


## 本番用のユーザー&Project
$ oc login https://$(minishift ip):8443 -u prod-user1
$ oc new-project prod

開発用のユーザーでログインし、開発用Projectに切り替えます。

$ oc login https://$(minishift ip):8443 -u dev-user1
$ oc project dev

アプリケーションのデプロイと、Routeの作成。アプリケーション名は「simple-app」としています。

$ oc new-app [GitリポジトリのURL]
$ oc expose svc/simple-app

動作確認。OKですね。

$ curl simple-app-dev.192.168.42.132.nip.io
this app version = 1.0

で、今回作成したイメージに、タグを作ります。今の「latest」を「promote」というタグで指定しました。

$ oc tag dev/simple-app:latest dev/simple-app:promote

「oc describe」すると、こんな感じ。今は「latest」と「promote」で、ImageStreamが指しているハッシュの値が同じですね。

$ oc describe is
Name:           simple-app
Namespace:      dev
Created:        About a minute ago
Labels:         app=simple-app
Annotations:        openshift.io/generated-by=OpenShiftNewApp
Docker Pull Spec:   172.30.1.1:5000/dev/simple-app
Image Lookup:       local=false
Unique Images:      1
Tags:           2

latest
  no spec tag

  * 172.30.1.1:5000/dev/simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67
      About a minute ago

promote
  tagged from simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67

  * 172.30.1.1:5000/dev/simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67
      8 seconds ago

では、本番用ユーザーでログインして、Projectも切り替えて

$ oc login https://$(minishift ip):8443 -u prod-user1
$ oc project prod

このアプリケーションをデプロイしようとすると…失敗します。

$ oc new-app dev/simple-app:promote
error:  local file access failed with: stat dev/simple-app:promote: no such file or directory
error: unable to locate any images in image streams, templates loaded in accessible projects, template files, local docker images with name "dev/simple-app:promote"

本番用のユーザーやプロジェクトから、開発用のProjectの情報が見えていません、と。

ここで、1度開発用のユーザーに切り替え、

$ oc login https://$(minishift ip):8443 -u dev-user1

本番用のユーザーに参照権限の付与と

$ oc policy add-role-to-user view prod-user1
role "view" added: "prod-user1"

本番用のデフォルトのServiceAccountである「prod」に「system:image-puller」ロールを与えます。

$ oc policy add-role-to-group system:image-puller system:serviceaccounts:prod -n dev
role "system:image-puller" added: "system:serviceaccounts:prod"

Service Accounts | Developer Guide | OKD 3.11

これで、本番用のユーザーから開発用Projectの内容が参照でき、またイメージのpullができるようになります。

本番用ユーザーとプロジェクトに切り替え。

$ oc login https://$(minishift ip):8443 -u prod-user1
$ oc project prod

なお、この時本番用のユーザーからは、開発用ProjectがProjectの一覧に表示されるようになっています。

$ oc projects
You have access to the following projects and can switch between them with 'oc project <projectname>':

    dev
  * prod

Using project "prod" on server "https://192.168.42.132:8443".

タグで指定したイメージを使って、再度「oc new-app」。今度は成功します。

$ oc new-app dev/simple-app:promote

ただ、この状態だとRouteがないので、exposeしておきます。

$ oc expose svc/simple-app

「oc get all」で確認。デプロイできているようです。

$ oc get all
NAME                     READY     STATUS    RESTARTS   AGE
pod/simple-app-1-lr8w6   1/1       Running   0          21s

NAME                                 DESIRED   CURRENT   READY     AGE
replicationcontroller/simple-app-1   1         1         1         22s

NAME                 TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/simple-app   ClusterIP   172.30.188.192   <none>        8080/TCP   24s

NAME                                            REVISION   DESIRED   CURRENT   TRIGGERED BY
deploymentconfig.apps.openshift.io/simple-app   1          1         1         config,image(simple-app:promote)

NAME                                        DOCKER REPO                       TAGS      UPDATED
imagestream.image.openshift.io/simple-app   172.30.1.1:5000/prod/simple-app   promote   

NAME                                  HOST/PORT                               PATH      SERVICES     PORT       TERMINATION   WILDCARD
route.route.openshift.io/simple-app   simple-app-prod.192.168.42.132.nip.io             simple-app   8080-tcp                 None

ちなみに、ビルドはしていないので、BuildConfigはありません。

$ oc get bc
No resources found.

アプリケーションの動作確認。

$ curl simple-app-prod.192.168.42.132.nip.io
this app version = 1.0

OKですね。これで、開発用Projectから本番用Projectへ、アプリケーションのPromotionができました。

アプリケーションを修正してみる

続いて、アプリケーションを修正して、再度ビルド&デプロイしてみましょう。

開発用ユーザー&Projectに切り替え。

$ oc login https://$(minishift ip):8443 -u dev-user1
$ oc project dev

アプリケーションのバージョン表記を「2.0」にして、Gitリポジトリに反映します。

const version = '2.0';

ビルド&デプロイ。

$ oc start-build bc/simple-app

しばらく待っていると、デプロイが完了しアプリケーションの更新が反映されます。

$ curl simple-app-dev.192.168.42.132.nip.io
this app version = 2.0

本番用Projectの方は、変わっていません。

$ curl simple-app-prod.192.168.42.132.nip.io
this app version = 1.0

これは、先ほど作成したイメージの「promote」タグが指しているイメージが変わっていないからです。

$ oc describe is/simple-app
Name:           simple-app
Namespace:      dev
Created:        26 minutes ago
Labels:         app=simple-app
Annotations:        openshift.io/generated-by=OpenShiftNewApp
Docker Pull Spec:   172.30.1.1:5000/dev/simple-app
Image Lookup:       local=false
Unique Images:      2
Tags:           2

latest
  no spec tag

  * 172.30.1.1:5000/dev/simple-app@sha256:10ed61895c1866e39394b90a3c89e355349ed63b1addcb6b9febfb89035561f4
      30 seconds ago
    172.30.1.1:5000/dev/simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67
      26 minutes ago

promote
  tagged from simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67

  * 172.30.1.1:5000/dev/simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67
      25 minutes ago

再度、タグを振り直します。

$ oc tag dev/simple-app:latest dev/simple-app:promote

「promote」タグが最新化されました。

$ oc describe is/simple-app
Name:           simple-app
Namespace:      dev
Created:        27 minutes ago
Labels:         app=simple-app
Annotations:        openshift.io/generated-by=OpenShiftNewApp
Docker Pull Spec:   172.30.1.1:5000/dev/simple-app
Image Lookup:       local=false
Unique Images:      2
Tags:           2

latest
  no spec tag

  * 172.30.1.1:5000/dev/simple-app@sha256:10ed61895c1866e39394b90a3c89e355349ed63b1addcb6b9febfb89035561f4
      50 seconds ago
    172.30.1.1:5000/dev/simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67
      26 minutes ago

promote
  tagged from simple-app@sha256:10ed61895c1866e39394b90a3c89e355349ed63b1addcb6b9febfb89035561f4

  * 172.30.1.1:5000/dev/simple-app@sha256:10ed61895c1866e39394b90a3c89e355349ed63b1addcb6b9febfb89035561f4
      3 seconds ago
    172.30.1.1:5000/dev/simple-app@sha256:3271132ce05787a6f24919eb4501979d87068e1b9fb56d6b13152db261eb0c67
      25 minutes ago

すると、本番用Projectの方にも自動でデプロイされています。

$ curl simple-app-prod.192.168.42.132.nip.io
this app version = 2.0

これ、どうなっているんでしょう?

本番用ユーザー&Projectに切り替えて、確認してみます。

$ oc login https://$(minishift ip):8443 -u prod-user1
$ oc project prod

DeploymentConfigの内容を見てみます。「spec.triggers.imageChangeParams.automatic」の部分が関係ありそうですね。

$ oc get dc/simple-app -o yaml
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:

...

spec:

...

  template:

...

  triggers:
  - type: ConfigChange
  - imageChangeParams:
      automatic: true
      containerNames:
      - simple-app
      from:
        kind: ImageStreamTag
        name: simple-app:promote
        namespace: dev
      lastTriggeredImage: 172.30.1.1:5000/dev/simple-app@sha256:10ed61895c1866e39394b90a3c89e355349ed63b1addcb6b9febfb89035561f4
    type: ImageChange

...

ここで、DeploymentConfigを修正してみましょう。

$ oc edit dc/simple-app

「automatic: true」の部分を削除します(「automatic: false」にして保存しても、削除されます)。

  triggers:
  - type: ConfigChange
  - imageChangeParams:
      containerNames:
      - simple-app
      from:
        kind: ImageStreamTag
        name: simple-app:promote
        namespace: dev
      lastTriggeredImage: 172.30.1.1:5000/dev/simple-app@sha256:e9d8d5a09337c25cae7f3aa4b4c05be788e28f180ba15b7c828ccc5d213838df
    type: ImageChange

もう1度、アプリケーションを修正してデプロイしてみましょう。

開発用ユーザー&Projectに切り替え。

$ oc login https://$(minishift ip):8443 -u dev-user1
$ oc project dev

アプリケーションのバージョンを今度は「3.0」にして、Gitリポジトリへ反映。

const version = '3.0';

ビルド&デプロイ。

$ oc start-build bc/simple-app

開発用Projectの方には反映されました。

$  curl simple-app-dev.192.168.42.132.nip.io
this app version = 3.0

では、タグを付けなおしてみます。

$ oc tag dev/simple-app:latest dev/simple-app:promote

ですが、今度は本番用Projectには反映されていません。

$ curl simple-app-prod.192.168.42.132.nip.io
this app version = 2.0

では、この場合どうやって反映するかですが「oc rollout」します。

本番用ユーザー&Projectに切り替え。

$ oc login https://$(minishift ip):8443 -u prod-user1
$ oc project prod

「oc rollout latest」を実行。

$ oc rollout latest dc/simple-app

今度は、反映されました。

$ curl simple-app-prod.192.168.42.132.nip.io
this app version = 3.0

こんなところで確認はOKでしょうか。

まとめ

OKD(Minishift)上で、Projectを跨いだアプリケーションのPromotionを試してみました。

最初、Projectを別にしても、ユーザーをわけなかったら、ロールを付与しなくてもあっさりとイメージのPromotionに成功して
「あれ?ブログに書かれている設定は…?」とか思ったりしたのですが、権限まわりをちゃんと把握しないとダメだなぁと
思いましたねぇ。

とりあえず、このネタはけっこう気になっていたことなので、自分で実践してみて少しは雰囲気がわかったと思います。

参考情報

Promoting Applications Across Environments - Application Life Cycle Management | Developer Guide | OKD 3.11

Promoting Applications Across Environments – Red Hat OpenShift Blog

Cross-Cluster Image Promotion Techniques – Red Hat OpenShift Blog

Building Declarative Pipelines with OpenShift DSL Plugin – Red Hat OpenShift Blog

Multiple Deployment Methods for OpenShift – Red Hat OpenShift Blog

OpenShift with Jenkins for dev/prod parity – /techblog