容器镜像存储在镜像注册表中(如Docker Hub、Quay.io),我们可以从那里手动pull出来单独运行,也可以在Kubernetes集群中运行。Kubernetes没有内置的镜像注册表,然而这在企业环境中又是通常是需要的。Red Hat OpenShift 提供了一个开箱即用的集成注册表来填补这一空白,并引入了一个名为ImageStream的新的Kubernetes资源,以“Kubernetes-native方式”管理镜像。
ImageStreams 是为了支持不同用途而设计的。但在一开始,某些参数可能会让人感到困惑。本文将对于OpenShift中的镜像管理的基本概念。
技术上来说,ImageStream只是一个包含元数据的Kubernetes资源。除了管理内部的镜像–通常是在OpenShift集群中构建的–ImageStreams可以指向外部注册表中的图像。在这种情况下,它们只是一个额外的抽象层,提供了一些额外的功能(例如轮询更新、缓存)。由于 ImageStream 可以有两种不同的行为方式,如果我们区分它们是指向内部图像还是指向外部图像,就更容易理解它们。
首先,下面是关于存储在Internal Registry中的Image的一些注意事项:
在OpenShift之外的External Registry保存了外部Image。ImageStream和External Registry、以及其上的外部Image的关系如下:
我们可以把OpenShift的ImageStream看成是一个指向Image的指针(当然还有一些其它元数据),ImageStream指向的Image目标可以是多种不同类型的目标,它们包括:
我们可以用以下oc的import-image命令或tag命令创建一个存放在myproject下的ImageStream,并让它指向外部Image,这个外部Image就是docker.io/balazsszeti/hello:sleeper。
$ oc import-image myproject/myimage-ref-source:mytag --from="docker.io/balazsszeti/hello:sleeper" --confirm
$ oc tag docker.io/balazsszeti/hello:sleeper myproject/myimage-ref-source:mytag
然后我们可以查看这个ImageStream和ImageStreamTag的详细信息。
$ oc get is myimage-ref-source -oyaml
apiVersion: image.openshift.io/v1
kind: ImageStream
metadata:
annotations:
openshift.io/image.dockerRepositoryCheck: "2020-04-12T08:18:25Z"
creationTimestamp: "2020-04-12T08:18:25Z"
generation: 1
name: myimage-ref-source
namespace: myproject
resourceVersion: "2844402"
selfLink: /apis/image.openshift.io/v1/namespaces/myproject/imagestreams/myimage-ref-source
uid: 2e541461-7c96-11ea-8ba8-0a580a81000f
spec:
lookupPolicy:
local: false
tags:
- from:
kind: DockerImage
name: docker.io/balazsszeti/hello:sleeper
importPolicy: {}
name: mytag
referencePolicy:
type: Source
status:
dockerImageRepository: image-registry.openshift-image-registry.svc:5000/myproject/myimage-ref-source
publicDockerImageRepository: default-route-openshift-image-registry.apps.cluster-beijing-78c7.beijing-78c7.example.opentlc.com/myproject/myimage-ref-source
tags:
- items:
- created: "2020-04-12T08:18:25Z"
dockerImageReference: docker.io/balazsszeti/hello@sha256:42957024b43e121a210a1b3a8a44f497233a2385f7ef48227a6866afdb9b8e1b
generation: 1
image: sha256:42957024b43e121a210a1b3a8a44f497233a2385f7ef48227a6866afdb9b8e1b
tag: mytag
$ oc get istag
NAME IMAGE REF UPDATED
myimage-ref-source:mytag docker.io/balazsszeti/hello@sha256:42957024b43e121a210a1b3a8a44f497233a2385f7ef48227a6866afdb9b8e1b 10 minutes ago
docker.io/balazsszeti/hello@sha256:42957024b43e121a210a1b3a8a44f497233a2385f7ef48227a6866afdb9b8e1b
$ oc set image-lookup IMAGESTREAM
以下是一个例子:如果为名为hello的ImageStream启用了本地名称查询功能,那么在pod或其他资源中使用“–image=hello”就可以访问到ImageSteamTag指向的Image,无而来自上游Image Registry。如果没有启动本地名称查询功能,那么使用“–image=hello”访问Image的时候会出问题,例如下面的“ErrImagePull”错误。
$ oc import-image myproject/hello:latest --from="openshift/hello-openshift:latest" --confirm
$ oc run hello --image=hello
$ oc get pod -w
NAME READY STATUS RESTARTS AGE
hello-1-deploy 0/1 ContainerCreating 0 4s
hello-1-mnnmz 0/1 Pending 0 0s
hello-1-mnnmz 0/1 ContainerCreating 0 0s
hello-1-deploy 1/1 Running 0 9s
hello-1-mnnmz 0/1 ContainerCreating 0 7s
hello-1-mnnmz 0/1 ErrImagePull 0 8s
下面在使用了“set image-lookup”后就可通过“–image=hello”使用该镜像了。
$ oc delete dc hello
$ oc set image-lookup hello
$ oc run hello --image=hello
$ oc get pod -w
NAME READY STATUS RESTARTS AGE
hello-1-vxcph 0/1 Pending 0 0s
hello-1-vxcph 0/1 ContainerCreating 0 0s
hello-1-deploy 1/1 Running 0 9s
hello-1-vxcph 0/1 ContainerCreating 0 7s
hello-1-vxcph 1/1 Running 0 9s
hello-1-deploy 0/1 Completed 0 18s
hello-1-deploy 0/1 Completed 0 18s
为了让ImageStream使用pullthrough特性,我们可以在oc import-image或oc tag命令中通过“–reference-policy=local”参数。
$ oc import-image myproject/myimage-ref-local:mytag --from="docker.io/balazsszeti/hello:sleeper" --confirm --reference-policy=local
$ oc tag docker.io/balazsszeti/hello:sleeper myproject/myimage-ref-local:mytag --reference-policy=local
“–reference-policy=local”参数会将ImageStream的referencePolicy.local设置成true。
。。。
referencePolicy:
type: Local
。。。
当StreamImage使用的是pullthrough方式指向External Image时候,那么:
image-registry.openshift-image-registry.svc:5000/myproject/myimage-ref-local@sha256:42957024b43e121a210a1b3a8a44f497233a2385f7ef48227a6866afdb9b8e1b
通过使用oc tag命令的–reference=true参数可创建一个ImageStream。在通过它运行Pod的时候,OpenShift不会直接使用ImageStreamTag的sha256 ID来找到对应的Image,而是每次都是通过指定的External Image名称和对应的Tag去找那个对应特定的Image。下面我们对比使用–reference=true参数和–reference=false(缺省情况)的区别。
$ oc tag docker.io/openshift/hello-openshift:latest myproject/hello-1:latest --reference=true
$ oc get istag hello-1:latest
Error from server (NotFound): imagestreamtags.image.openshift.io "hello-1:latest" not found
$ oc tag docker.io/openshift/hello-openshift:latest myproject/hello-2:latest --reference=false
$ oc get istag hello-2:latest
$ oc get istag hello-2:latest
NAME IMAGE REF UPDATED
hello-2:latest docker.io/openshift/hello-openshift@sha256:aaea76ff622d2f8bcb32e538e7b3cd0ef6d291953f3e7c9f556c1ba5baf47e2e 5 seconds ago
当我们使用–reference=false的ImageStream的时候,具有以下特性:
docker.io/openshift/hello-openshift:latest
通过OpenShift的build生成的Image会推送到 Internal Registry上,OpenShift同时会为其生成ImageStream。
$ oc new-build --to='myimage-internal:mytag' --strategy=docker --binary=true --name=myimage-internal
$ oc start-build myimage-internal --from-dir=. --follow
$ oc get is myimage-internal
NAME IMAGE REPOSITORY TAGS UPDATED
myimage-internal default-route-openshift-image-registry.apps.cluster-beijing-78c7.beijing-78c7.example.opentlc.com/myproject/myimage-internal
使用这种方式的ImageStream有以下特性:
image-registry.openshift-image-registry.svc:5000/myproject/myimage-internal@sha256:ff3b3c5e3d09bf93e2a05ece04235f4ea8212f36b617161d8f11f374a14aeb74