OpenShift容器平台提供了一个内置的Container Image Registry,该Image Registry用户提供了一个开箱即用的解决方案来管理运行OpenShift工作负载所用到的Image。Image Registry可以像其他任何集群工作负载一样扩展,不需要特定的基础设施配置。此外,它集成到了集群用户认证和授权系统中,这意味着通过定义Image资源的用户权限来控制创建和检索Image的访问。
Image Registry Operator在 openshift-image-registry 命名空间中运行,并在该位置管理Image Registry实例。Image Registry的所有配置和工作负载资源都位于该命名空间中。Image数据存储在两个位置。实际的Image数据存储在可配置的存储位置,如云存储或文件系统卷等。Image元数据被存储为标准的API资源,这些API资源包括Image和ImageStream。
当使用podman工具向OpenShift内部Image Registry推送Image的时候,OpenShift会自动为Image创建对应的ImageStream,这样在OpenShift中就可以使用ImageStream访问这些保存在本地的Image了。
podman push命令会将外部Image传到内部Image Registry中并保存,并根据Image的元数据生成对应的ImageStream对象;而oc import-image命令只是根据外部镜像的元数据生成ImageStream对象,ImageSteam还是指向外部镜像。
$ oc login -u admin -p <password> https://api-int.<cluster_name>.<base_domain>:6443
$ oc whoami -t
jbwPGpIzDra8XCNIrBjsWkKhdHEEugBpuqNUHLVVH00
为了能操作内部Image Registry,首先要有权限。用OpenShift集群管理员(例如admin)登录后执行命令,为自己赋权
$ oc policy add-role-to-user registry-viewer $(oc whoami)
$ oc policy add-role-to-user registry-editor $(oc whoami)
本文未来手动导入到内部Image Registry的Image是被放在以下命令新建的特定的新建项目中。其实导入的Image也可放在所有用户都可访问的公共项目OpenShift中。
$ oc new-project myproject
首先需要进入的某个OpenShift节点,这样我们就可以用OpenShift集群内部地址访问Image Registry了。
$ oc get nodes
NAME STATUS ROLES AGE VERSION
ip-10-0-133-204.ec2.internal Ready master 3d8h v1.17.1
ip-10-0-134-17.ec2.internal Ready worker 3d7h v1.17.1
ip-10-0-147-125.ec2.internal Ready master 3d8h v1.17.1
ip-10-0-154-19.ec2.internal Ready worker 3d7h v1.17.1
ip-10-0-161-178.ec2.internal Ready master 3d8h v1.17.1
$ oc debug nodes/ip-10-0-133-204.ec2.internal
Starting pod/ip-10-0-133-204ec2internal-debug ...
To use host binaries, run `chroot /host`
Pod IP: 10.0.133.204
If you don't see a command prompt, try pressing enter.
sh-4.2# chroot /host
sh-4.4# podman pull openshift/hello-openshift
Trying to pull registry.access.redhat.com/openshift/hello-openshift...
name unknown: Repo not found
Trying to pull docker.io/openshift/hello-openshift...
Getting image source signatures
Copying blob 4f4fb700ef54 done
Copying blob 8b32988996c5 done
Copying config 7af3297a3f done
Writing manifest to image destination
Storing signatures
7af3297a3fb4487b740ed6798163f618e6eddea1ee5fa0ba340329fcae31c8f6
sh-4.4# podman images | grep hello-openshift
docker.io/openshift/hello-openshift latest 7af3297a3fb4 2 years ago 6.1 MB
sh-4.4# podman tag docker.io/openshift/hello-openshift:latest image-registry.openshift-image-registry.svc:5000/myproject/hello-openshift-1:latest
sh-4.4# podman images | grep hello-openshift
image-registry.openshift-image-registry.svc:5000/myproject/hello-openshift-1 latest 7af3297a3fb4 2 years ago 6.1 MB
docker.io/openshift/hello-openshift latest 7af3297a3fb4 2 years ago 6.1 MB
sh-4.4# podman login image-registry.openshift-image-registry.svc:5000 -u admin -p
sh-4.4# podman push image-registry.openshift-image-registry.svc:5000/myproject/hello-openshift-1:latest
Getting image source signatures
Copying blob 5f70bf18a086 skipped: already exists
Copying blob da0e4d9121c7 [--------------------------------------] 0.0b / 0.0b
Copying config 7af3297a3f [--------------------------------------] 0.0b / 1.3KiB
Writing manifest to image destination
Storing signatures
sh-4.4# curl -s -k -H "Authorization: Bearer sMrJBUs_3MNvKnzxMJyOeILGYianzib8itx3jyJaJW0" https://image-registry.openshift-image-registry.svc:5000/v2/_catalog | jq
{
"repositories": [
"myproject/hello-openshift-1",
"openshift/apicast-gateway",
"openshift/apicurito-ui",
"openshift/cli",
"openshift/cli-artifacts",
"openshift/dotnet",
"openshift/dotnet-runtime",
"openshift/eap-cd-openshift",
"openshift/fis-java-openshift",
"openshift/fis-karaf-openshift",
"openshift/fuse-apicurito-generator",
"openshift/fuse7-console",
"openshift/fuse7-eap-openshift",
"openshift/fuse7-java-openshift",
。。。
sh-4.4#curl -s -k -H "Authorization: Bearer sMrJBUs_3MNvKnzxMJyOeILGYianzib8itx3jyJaJW0" https://image-registry.openshift-image-registry.svc:5000/v2/myproject/hello-openshift-1/manifests/latest | jq
{
"schemaVersion": 1,
"name": "myproject/hello-openshift-1",
"tag": "latest",
"architecture": "amd64",
"fsLayers": [
{
"blobSum": "sha256:ffbad57ff065cbecdd369f56b40d42e3434ecc70d048f57a7391000911ebd7a7"
},
{
"blobSum": "sha256:ff53f95d20d5f6ca55d46980861da4798ee325927876aa53bfc5e2a32a864dc7"
}
],
"history": [
{
"v1Compatibility": "{\"architecture\":\"amd64\",\"author\":\"Jessica Forrester \\[email protected]\\u003e\",\"config\":{\"Hostname\":\"\",\"Domainname\":\"\",\"User\":\"1001\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"ExposedPorts\":{\"8080/tcp\":{},\"8888/tcp\":{}},\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":[\"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\"],\"Cmd\":null,\"Image\":\"\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/hello-openshift\"],\"OnBuild\":null,\"Labels\":{}},\"container\":\"64ede50d59ead12e9e867f6c48681b3cde9e0c920db433666fc20cd7c322de02\",\"container_config\":{\"Hostname\":\"64ede50d59ea\",\"Domainname\":\"\",\"User\":\"\",\"AttachStdin\":false,\"AttachStdout\":false,\"AttachStderr\":false,\"Tty\":false,\"OpenStdin\":false,\"StdinOnce\":false,\"Env\":null,\"Cmd\":null,\"Image\":\"scratchljl6nbgci72oxgam2jh83pe3\",\"Volumes\":null,\"WorkingDir\":\"\",\"Entrypoint\":[\"/bin/sh\",\"-c\",\"# NOP\"],\"OnBuild\":null,\"Labels\":{}},\"created\":\"2018-04-18T10:38:59.552935845Z\",\"docker_version\":\"1.13.1\",\"id\":\"a510d6aa46bf3dbf2fa761156d12d79e3d1b44f2bda36fb7e8b9c23c7bdb41de\",\"os\":\"linux\",\"parent\":\"a5d5ba10159cb80b424cb96a62c273468b681298895860aa2ac28e62f0ae6d6f\"}"
},
{
"v1Compatibility": "{\"id\":\"a5d5ba10159cb80b424cb96a62c273468b681298895860aa2ac28e62f0ae6d6f\",\"comment\":\"Imported from -\",\"created\":\"2018-04-18T10:38:57.341799685Z\",\"container_config\":{\"Cmd\":[\"\"]}}"
}
],
"signatures": [
{
"header": {
"jwk": {
"crv": "P-256",
"kid": "EQAM:NVI4:I73M:JKBT:VO3P:QXMN:WVTW:5CNZ:QIZ5:2I3M:EFYN:PGTF",
"kty": "EC",
"x": "cRUOvyQ4YmzipMvs0HFx6u_mSJ0lh77CVTo4JWfZy_Q",
"y": "t1FC6F3k0KvVAcjvpHPQ7WW0QdrLWtfp3qSt7tkq8O8"
},
"alg": "ES256"
},
"signature": "k_pNCjBHQZBn9ssK76DWIYQVB7zjwGZ5Qgqwe49Nb-MbewZJNqVdkV2eD7rFh2WmwQVqV1pVps0ZKT6r9-Ux_w",
"protected": "eyJmb3JtYXRMZW5ndGgiOjE5NDcsImZvcm1hdFRhaWwiOiJDbjAiLCJ0aW1lIjoiMjAyMC0wNy0wN1QxNTo0MDowMVoifQ"
}
]
}
本方法是将OpenShift内部镜像Registry通过Route暴露出来,可以从集群外部访直接问到内部镜像Registry。
确保已经在集群外部的执行节点中安装了podman或docker。
$ oc patch configs.imageregistry.operator.openshift.io/cluster --patch '{"spec":{"defaultRoute":true}}' --type=merge
$ HOST=$(oc get route default-route -n openshift-image-registry --template='{{ .spec.host }}')
$ sudo podman login -u $(oc whoami) -p $(oc whoami -t) --tls-verify=false ${HOST}
Login Succeeded!
$ sudo podman pull openshift/hello-openshift
Trying to pull registry.access.redhat.com/openshift/hello-openshift...
name unknown: Repo not found
Trying to pull registry.fedoraproject.org/openshift/hello-openshift...
manifest unknown: manifest unknown
Trying to pull registry.centos.org/openshift/hello-openshift...
manifest unknown: manifest unknown
Trying to pull docker.io/openshift/hello-openshift...
Getting image source signatures
Copying blob 4f4fb700ef54 done
Copying blob 8b32988996c5 done
Copying config 7af3297a3f done
Writing manifest to image destination
Storing signatures
7af3297a3fb4487b740ed6798163f618e6eddea1ee5fa0ba340329fcae31c8f6
$ sudo podman images | grep hello-openshift
docker.io/openshift/hello-openshift latest 7af3297a3fb4 2 years ago 6.1 MB
$ sudo podman tag docker.io/openshift/hello-openshift:latest ${HOST}/myproject/hello-openshift-2:latest
$ sudo podman images | grep hello-openshift
default-route-openshift-image-registry.apps.cluster-beijing-1374.beijing-1374.example.opentlc.com/myproject/hello-openshift-2 latest 7af3297a3fb4 2 years ago 6.1 MB
docker.io/openshift/hello-openshift latest 7af3297a3fb4 2 years ago 6.1 MB
$ sudo podman push ${HOST}/myproject/hello-openshift-2:latest --tls-verify=false
Getting image source signatures
Copying blob da0e4d9121c7 done
Copying blob 5f70bf18a086 done
Copying config 7af3297a3f done
Writing manifest to image destination
Storing signatures
$ curl -s -k -H "Authorization: Bearer $(oc whoami -t)" https://${HOST}/v2/_catalog | jq
{
"repositories": [
"hello/hello-world",
"openshift/apicast-gateway",
"openshift/apicurito-ui",
"openshift/cli",
"openshift/cli-artifacts",
"openshift/dotnet",
"openshift/dotnet-runtime",
。。。
]
}
$ curl -sk -H "Authorization: Bearer $(oc whoami -t)" https://${HOST}/v2/openshift/dotnet/tags/list
{"name":"openshift/dotnet","tags":["2.1","3.0","3.1","latest"]}
$ curl -sk -H "Authorization: Bearer $(oc whoami -t)" https://${HOST}/v2/openshift/dotnet/manifests/latest
{
"schemaVersion": 1,
"name": "openshift/dotnet",
"tag": "latest",
"architecture": "amd64",
"fsLayers": [
{
"blobSum": "sha256:6ac77d92f478f0bf79acbfb76283f5a65acafeb9660d64bf2aae10b6ff7dd2f9"
},
{
"blobSum": "sha256:0208d4ebd72521c70965645fb58ea50a3d8f4dfa9ef526c66fdbd25e4f66736b"
},
{
"blobSum": "sha256:feaa73091cc9545dcd9c137c911a7b96bb15faad8a7ec24c136c1b8e7739611a"
},
{
"blobSum": "sha256:e20f387c7bf5a184eeef83f7e5626661f593ca05c788f377a01e2df62f613e44"
}
],
"history": [
{
....
以下从OpenShift集群外部的节点操作。
$ oc get image -n myproject | grep hello-openshift
sha256:a79c6182e8581564bcdd6c6c91e3a9bfe5acc3e48903a1640f6effe12243cb7f image-registry.openshift-image-registry.svc:5000/myproject/hello-openshift-1@sha256:a79c6182e8581564bcdd6c6c91e3a9bfe5acc3e48903a1640f6effe12243cb7f
sha256:03e2cf83f6ec05a187a86bbbde9a2d47f62463ace5308a2446b828b2aeefe04e image-registry.openshift-image-registry.svc:5000/myproject/hello-openshift-2@sha256:03e2cf83f6ec05a187a86bbbde9a2d47f62463ace5308a2446b828b2aeefe04e
$ oc get is -n myproject
NAME IMAGE REPOSITORY TAGS UPDATED
hello-openshift-1 default-route-openshift-image-registry.apps.cluster-beijing-1374.beijing-1374.example.opentlc.com/myproject/hello-openshift-1 latest 11 seconds ago
hello-openshift-2 default-route-openshift-image-registry.apps.cluster-beijing-fd91.beijing-fd91.example.opentlc.com/myproject/hello-openshift-2 latest About a minute ago
$ oc new-app hello-openshift-1 --docker-image=image-registry.openshift-image-registry.svc:5000/myproject/hello-openshift-1:latest
$ oc new-app hello-openshift-2 --image-stream=myproject/hello-openshift-2:latest
$ oc expose svc hello-openshift-1
$ oc expose svc hello-openshift-2
$ curl $(oc get route hello-openshift-1 -o template --template '{{.spec.host}}')
Hello OpenShift!
$ curl $(oc get route hello-openshift-2 -o template --template '{{.spec.host}}')
Hello OpenShift!