ビルドは一度だけ!

継続的デリバリを実現するための鉄則の一つに「バイナリのビルドは一度だけ!」というものがあります。しかし、ソースコードリポジトリに登録されているソースコードを正として、ビルドやデプロイを行うツールを利用している場合には、この鉄則の実現が難しくなります。

OpenShiftでは、ビルド済みの Docker Image をバージョン管理しているので、「ビルドは一度だけ!」を容易に実現可能です。

ということで、OpenShift v3その実現方法をご紹介します。

「ビルドは一度だけ!」を実現するためのOpenShiftの概念

ImageStream

OpenShiftにデプロイするアプリケーションのDockerイメージへの参照。SCMのブランチのようなイメージで利用可能。

ServiceAccount

OpenShift APIを利用する権限を持つオブジェクト。Podのビルドを実行するsystem:image-builder権限を持つbuilder、Podのデプロイをするsystem:deployer権限をもつdeployer、builder, deployer以外のすべての権限をもつdefaultがある。

手順

アプリケーションの作成

ビルドは一度だけを実現するために元となるプロジェクトとアプリケーションを作成します。

1. テスト用プロジェクト(hello)の作成

oc new-project hello

2. アプリケーションの作成

oc new-app https://github.com/akubicharm/php-hello-world.git

3.ルーティングの設定と確認

oc expose service php-hello-world --hostname=php-hello-world.hello.apps.cloud
curl php-hello-world.hello.apps.cloud

Hello World」と出力されれば OK です。

ビルド済みイメージをデプロイするプロジェクト(hello-prod)の作成

OpenShift v3.0.2.0 では、異なるプロジェクトのImageStreamを利用してアプリケーションがデプロイできるようになりました。

1. プロジェクトの作成

oc new-project prod-hello

2. helloプロジェクトのポリシーの確認

oc describe policyBindings :default -n hello

system:image-pullers ロールに Service Account が設定されていません。

RoleBinding[system:image-pullers]:   
                    Role:           system:image-puller
                    Users:          <none>
                    Groups:         system:serviceaccounts:hello
                    ServiceAccounts:    <none>
                    Subjects:       <none>

3.prod-hello プロジェクトに権限の付与

oc policy add-role-to-user system:image-puller system:serviceaccount:prod-hello:default -n hello

prod-helloプロジェクトのdefaultサービスアカウントにimage-pullerロールが付与されました。これでprod-helloプロジェクトはアプリケーションのデプロイ時にhelloプロジェクトのImageStreamを利用することができるようになります。

RoleBinding[system:image-pullers]:   
                    Role:           system:image-puller
                    Users:          <none>
                    Groups:         system:serviceaccounts:hello
                    ServiceAccounts:prod-hello/default
                    Subjects:       <none>

ビルド済みイメージからのアプリケーションのデプロイ

1. テスト用プロジェクトからテンプレート作成

helloプロジェクトからアプリケーションのテンプレートを作成します。ビルドは行う必要がないので、buildConfigはエクスポート対象から除外し、deploymentConfig, service, route のみをエクスポートします。

oc export deploymentConfig,service,route -o yaml --as-template=php-hello-world > prod-php-hello-world.yaml

テンプレートの ImageStreamのタグとルーティングの設定を編集します。

perl -i -pe 's/name: php-hello-world:latest/name: php-hello-world:prod-hello/g' prod-php-hello-world.yaml
perl -i -pe 's/php-hello-world.hello.apps.cloud/php-hello-world.prod.apps.cloud/g' prod-php-hello-world.yaml

この段階ではhello-prodというタグの付いた php-hello-worldのImageStreamがまだないので、デプロイはされません。

2. プロダクション用プロジェクトへアプリケーションのデプロイ

oc project prod-hello
oc new-app -f prod-php-hello-world.yaml

3. ImageStream の確認

oc project hello
oc get imageStream
oc describe is php-hello-world
Name:           php-hello-world
Created:        28 minutes ago
Labels:         app=php-hello-world
Docker Pull Spec:   172.30.131.34:5000/hello/php-hello-world

Tag Spec        Created     PullSpec                                Image
latest  <pushed>    26 minutes ago  172.30.131.34:5000/hello/php-hello-world@sha256:a94f7113d501dea557c952886d099b59825ad14e2a3f25aa545fe0311aef7b4c    

4. タグ付け

oc tag hello/php-hello-world@sha256:a94f7113d501dea557c952886d099b59825ad14e2a3f25aa545fe0311aef7b4c prod-hello/php-hello-world:prod

5. デプロイ

oc deploy prod-php-helo-world --latest -n prod-hello

これで、hello プロジェクトで動作確認されたアプリケーションをprod-helloにデプロイすることができました。 この後は、以下の手順を繰り返すことで「ビルドは一度だけ!」を実現できるようになります。

  1. ソースコードの変更
  2. hello プロジェクトのビルド
  3. hello プロジェクトでのテスト
  4. 最新のイメージへのタグ付け

f:id:akubicharm:20150930022657p:plain

修正履歴

  • [2015/10/21] oc tag の第2引数を修正しました。他のプロジェクトで作成されたイメージを利用するには、[MyProjectName]/[Image Stream]:[tag] とする必要があります。