ImageStream 概要
ImageStream1 は OpenShift のリソースの 1 つです。コンテナイメージそのものは含まず、コンテナイメージを参照を行うためのリソースとなります。コンテナイメージの参照を抽象化し、ImageStream とタグによって利用可能なイメージを管理します。
OpenShift DeploymentConfig に指定することができますが、ImageStream を指定せずに直接コンテナイメージの URL やタグを指定することも可能です。
疑問点
ここで 1つ 気になる点が出てきます。ImageStream を DeploymentConfig に指定せずに利用できるのであれば、ImageStream の存在意義とは何でしょうか? ImageStream を利用することで、DeploymentConfig の ImageChange Trigger2 を利用することができますが、それだけでしょうか? コンテナイメージ変更を契機に Pod の Updaet を行わない場合は不要となるのでしょうか。
ImageStream を利用しない場合
DeploymentConfig によるコンテナのデプロイ
サンプルとして OpenShift で私がよくデプロイする ruby-ex アプリケーションを利用します。デプロイに必要なリソースは oc new-app
コマンドで予め作成しておきます。
oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git
コマンド実行完了後、利用しない DeploymentConfig を削除しておきます。
oc delete dc ruby-ex
ここで ImageStream を利用しない方法で DeploymentConfig を定義してみます。
oc create -f ruby-ex-without-is.yaml
ruby-ex-without-is.yaml の詳細は次のとおりです。spec.template.containers[0].image に直接コンテナイメージの URL とタグが記載されています。
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
creationTimestamp: null
generation: 1
labels:
app: ruby-ex
name: ruby-ex
selfLink: /apis/apps.openshift.io/v1/namespaces/without-is/deploymentconfigs/ruby-ex
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
app: ruby-ex
deploymentconfig: ruby-ex
strategy:
activeDeadlineSeconds: 21600
resources: {}
rollingParams:
intervalSeconds: 1
maxSurge: 25%
maxUnavailable: 25%
timeoutSeconds: 600
updatePeriodSeconds: 1
type: Rolling
template:
metadata:
creationTimestamp: null
labels:
app: ruby-ex
deploymentconfig: ruby-ex
spec:
containers:
- image: docker-registry.default.svc:5000/without-is/ruby-ex:latest
imagePullPolicy: Always
name: ruby-ex
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
status:
availableReplicas: 0
latestVersion: 0
observedGeneration: 0
replicas: 0
unavailableReplicas: 0
updatedReplicas: 0
Pod が正常にデプロイされていることを確認します。
# oc get pod
NAME READY STATUS RESTARTS AGE
ruby-ex-1-build 0/1 Completed 0 4m
ruby-ex-4-5ffss 1/1 Running 0 32s
レプリカ数を 2 に変更してみます。
# oc scale dc/ruby-ex --replicas 2
コンテナのイメージIDを確認します。とちらの Pod も同じ Image ID を参照していることがわかります。
]# oc describe pod -l app=ruby-ex | grep "Image ID:"
Image ID: docker-pullable://docker-registry.default.svc:5000/sample-is/ruby-ex@sha256:ea3dccca08d1cedb5f42d952519c40b6bc8db9b857d280b60180017107f6fc5a
Image ID: docker-pullable://docker-registry.default.svc:5000/sample-is/ruby-ex@sha256:ea3dccca08d1cedb5f42d952519c40b6bc8db9b857d280b60180017107f6fc5a
ここでコンテナをビルドし直します。
# oc start-build ruby-ex
ビルド完了後にレプリカ数を 3 へ変更し、Pod が参照している Image ID を確認してみます。ことなるコンテナイメージを参照している Pod が存在していることがわかります。
# oc describe pod -l app=ruby-ex | grep "Image ID:"
Image ID: docker-pullable://docker-registry.default.svc:5000/sample-is/ruby-ex@sha256:ea3dccca08d1cedb5f42d952519c40b6bc8db9b857d280b60180017107f6fc5a
Image ID: docker-pullable://docker-registry.default.svc:5000/sample-is/ruby-ex@sha256:9e0dfb3183cf741b3092d5482467e4a327040e5cc9646017828213dc438f4665
Image ID: docker-pullable://docker-registry.default.svc:5000/sample-is/ruby-ex@sha256:ea3dccca08d1cedb5f42d952519c40b6bc8db9b857d280b60180017107f6fc5a
何が起きたのでしょうか。DeploymentConfig に指定したコンテナイメージの URL とタグは変更していません。
そうです。タグは変えていませんが、先程実施したコンテナビルドにより、タグが参照しているイメージが変更となりました。
ImageStream を利用した場合
ImageStream を指定した場合の DeploymentConfig
まず、ImageStream を利用した DeploymentConfig を作成します。ImageStream を利用した DeploymentConfig の一番簡単な作成方法は oc new-app
を利用することです。
oc コマンドでプロジェクト作成時にサンプルとして出力される例をそのまま利用します。
oc new-app centos/ruby-25-centos7~https://github.com/sclorg/ruby-ex.git
--> Found Docker image dc0e72c (4 weeks old) from Docker Hub for "centos/ruby-25-centos7"
Ruby 2.5
--------
Ruby 2.5 available as container is a base platform for building and running various Ruby 2.5 applications and frameworks. Ruby is the interpreted scripting language for quick and easy object-oriented programming. It has many features to process text files and to do system management tasks (as in Perl). It is simple, straight-forward, and extensible.
Tags: builder, ruby, ruby25, rh-ruby25
* An image stream tag will be created as "ruby-25-centos7:latest" that will track the source image
* A source build using source code from https://github.com/sclorg/ruby-ex.git will be created
* The resulting image will be pushed to image stream tag "ruby-ex:latest"
* Every time "ruby-25-centos7:latest" changes a new build will be triggered
* This image will be deployed in deployment config "ruby-ex"
* Port 8080/tcp will be load balanced by service "ruby-ex"
* Other containers can access this service through the hostname "ruby-ex"
--> Creating resources ...
imagestream.image.openshift.io "ruby-25-centos7" created
imagestream.image.openshift.io "ruby-ex" created
buildconfig.build.openshift.io "ruby-ex" created
deploymentconfig.apps.openshift.io "ruby-ex" created
service "ruby-ex" created
--> Success
Build scheduled, use 'oc logs -f bc/ruby-ex' to track its progress.
Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
'oc expose svc/ruby-ex'
Run 'oc status' to view your app.
Image更新を検出して勝手にアップデートされないようにトリガーはオフにします。
oc set triggers dc/ruby-ex --manual
設定が完了した DeploymentConfig は次のとおりです。ImageStream がない場合の違いがあります。Image に指定されているのがURLとタグではなく、URLとハッシュタグとなりました。
また、triggers が設定されており、ImageChange に ImageStream とタグが指定されています。
apiVersion: apps.openshift.io/v1
kind: DeploymentConfig
metadata:
annotations:
openshift.io/generated-by: OpenShiftNewApp
creationTimestamp: null
generation: 1
labels:
app: ruby-ex
name: ruby-ex
selfLink: /apis/apps.openshift.io/v1/namespaces/is/deploymentconfigs/ruby-ex
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
app: ruby-ex
deploymentconfig: ruby-ex
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:
app: ruby-ex
deploymentconfig: ruby-ex
spec:
containers:
- image: docker-registry.default.svc:5000/is/ruby-ex@sha256:ad60376e709fec2764d249327cc8a1cb6f5b085c392f95b8c786ff67875e74bf
imagePullPolicy: Always
name: ruby-ex
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:
- imageChangeParams:
containerNames:
- ruby-ex
from:
kind: ImageStreamTag
name: ruby-ex:latest
namespace: is
type: ImageChange
status:
availableReplicas: 0
latestVersion: 0
observedGeneration: 0
replicas: 0
unavailableReplicas: 0
updatedReplicas: 0
Pod のレプリカ数を 2 に変更します。
# oc scale dc/ruby-ex --replicas 2
Pod のイメージIDを確認します。どちらも同じイメージが参照されています。
oc describe pod -l app=ruby-ex | grep "Image ID:"
Image ID: docker-pullable://docker-registry.default.svc:5000/is/ruby-ex@sha256:8ebf0e1e2016241077934270246353d15742afa2d45b521d77fac399c9e0e32b
Image ID: docker-pullable://docker-registry.default.svc:5000/is/ruby-ex@sha256:8ebf0e1e2016241077934270246353d15742afa2d45b521d77fac399c9e0e32b
コンテナイメージをビルドします。
# oc start-build ruby-ex
レプリカ数を 3 に変更した後に、コンテナイメージの ID を確認します。すべて同じイメージを参照していることがわかります。
# oc describe pod -l app=ruby-ex | grep "Image ID:"
Image ID: docker-pullable://docker-registry.default.svc:5000/is/ruby-ex@sha256:e7e2ce3f129d1d98b615ed8efd157a281a0aeee5760efb04e074c3cda39df78b
Image ID: docker-pullable://docker-registry.default.svc:5000/is/ruby-ex@sha256:e7e2ce3f129d1d98b615ed8efd157a281a0aeee5760efb04e074c3cda39df78b
Image ID: docker-pullable://docker-registry.default.svc:5000/is/ruby-ex@sha256:e7e2ce3f129d1d98b615ed8efd157a281a0aeee5760efb04e074c3cda39df78b
まとめ
タグを変えずにコンテナイメージをビルドした場合、Pod をスケールさせた場合異なるバージョンのイメージを参照してしまう事象を確認しました。これを回避するためには、タグを分けるという手段もありますが、ImageStream を利用すればハッシュ値を利用してこの問題を解決することも可能であるということがわかりました。
今回は ImageSteam の1つの役割について確認しました。その他の ImageStream の詳細については製品ドキュメント3を参照して貰えればと思います。