これは、なにをしたくて書いたもの?
- 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 – 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" },
開発用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 – 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