Kubernetes从Private Registry中拉取容器镜像的方法

方法1:利用Node上的配置访问Private Registry

在玩Docker时,很多朋友都 搭建过自己的Private Registry。Docker访问那些以basic auth方式进行鉴权的Private Registry,只需在本地执行docker login,输入用户名、密码后,就可以自由向Registry Push镜像或pull 镜像到本地了:

1
2
3
4
[root@node3 docker]# docker login registry.martin.com:5000
Username (martin): martin
Password:
Login Succeeded

在这一过程结束后,Docker实际上会在~/.docker目录下创建一个config.json文件,保存后续与Registry交互过程中所要使用的鉴权串(这个鉴权串只是一个base64编码结果,安全性欠佳)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
➜  nexus cat ~/.docker/config.json 
{
"auths": {
"daocloud.io": {
"auth": "xxxxQ=="
},
"https://index.docker.io/v1/": {
"auth": "axxw=="
},
"registry.martin.com:5000": {
"auth": "sdxxxxxxB"
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/17.09.0-ce (linux)"
}
}#

一但Node上有了这个配置,那么K8s就可以通过docker直接访问Private Registry了,这是K8s文档中与私有镜像仓库交互的第一个方法 。考虑到Pod可以被调度到集群中的任意一个Node上,需要在每个Node上执行上述login操作,或者可以简单地将/.docker/config.json scp到各个node上的/.docker目录下。

但实际效果却不尽人意.

创建一个Pod.yaml,测试一下是否能run起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
  nexus cat test.yaml 
apiVersion: v1
kind: Pod
metadata:
name: rbd-rest-api-using-node-config
spec:
containers:
- name: rbd-rest-api-using-node-config
image: registry.martin.com:5000/registry
imagePullPolicy: Always
nodeSelector: #指定节点启用pod
kubernetes.io/hostname: 192.168.1.16
nexus

创建这个Pod并查看Pod的创建状态:

1
2
3
4
5
6
➜  nexus kubectl create -f test.yaml 
pod "rbd-rest-api-using-node-config" created
➜ nexus kubectl get pods
NAME READY STATUS RESTARTS AGE
nexus3-68f55d9746-vfnf8 1/1 Running 0 17h
rbd-rest-api-using-node-config 0/1 ImagePullBackOff 0 5s

通过log查看Pod:

1
2
3
➜  nexus kubectl logs pod/rbd-rest-api-using-node-config
Error from server (BadRequest): container "rbd-rest-api-using-node-config" in pod "rbd-rest-api-using-node-config" is waiting to start: trying and failing to pull image
➜ nexus

通过describe查看pod失败的更加详细的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
➜  nexus kubectl describe pod/rbd-rest-api-using-node-config
....
前面部分省略
....
QoS Class: BestEffort
Node-Selectors: kubernetes.io/hostname=192.168.1.16
Tolerations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 13m default-scheduler Successfully assigned rbd-rest-api-using-node-config to 192.168.1.16
Normal SuccessfulMountVolume 13m kubelet, 192.168.1.16 MountVolume.SetUp succeeded for volume "default-token-fck44"
Normal SandboxChanged 13m kubelet, 192.168.1.16 Pod sandbox changed, it will be killed and re-created.
Warning Failed 12m (x3 over 13m) kubelet, 192.168.1.16 Failed to pull image "registry.martin.com:5000/registry": rpc error: code = Unknown desc = Error response from daemon: Get https://registry.martin.com:5000/v2/registry/manifests/latest: no basic auth credentials
Normal Pulling 11m (x4 over 13m) kubelet, 192.168.1.16 pulling image "registry.martin.com:5000/registry"
Warning Failed 11m (x4 over 13m) kubelet, 192.168.1.16 Error: ErrImagePull
Normal BackOff 8m (x21 over 13m) kubelet, 192.168.1.16 Back-off pulling image "registry.martin.com:5000/registry"
Warning Failed 3m (x42 over 13m) kubelet, 192.168.1.16 Error: ImagePullBackOff
➜ nexus

貌似不能生效,一直提示”no basic auth credentials”,结果是K8s无法从Private Registry获取我们想要的镜像文件.

删除该Pod,尝试手动pull registry仓库镜像

  • 删除Pod
1
2
3
4
5
➜  nexus kubectl delete pod rbd-rest-api-using-node-config
pod "rbd-rest-api-using-node-config" deleted
➜ nexus kubectl get pods
NAME READY STATUS RESTARTS AGE
已经没有该pod了
  • 手动pull registry image
1
2
3
4
5
6
7
8
9
10
11
[root@node3 docker]# docker pull registry.martin.com:5000/registry  
Using default tag: latest
latest: Pulling from registry
81033e7c1d6a: Pull complete
b235084c2315: Pull complete
c692f3a6894b: Pull complete
ba2177f3a70e: Pull complete
a8d793620947: Pull complete
Digest: sha256:feb40d14cd33e646b9985e2d6754ed66616fedb840226c4d917ef53d616dcd6c
Status: Downloaded newer image for registry.martin.com:5000/registry:latest
==node3为指定运行pod的节点==

再次创建rbd-rest-api-using-node-config pod

如果需要借助该image运行某些环境的话,是可以使用了,因为image已经手动拉取了。不然如果自动拉取的话会一直提示没有basic认证


方法2:通过kubectl创建docker-registry的secret

K8s提供的第二种方法是通过kubectl创建一个docker-registry的secret,并在Pod描述文件中引用该secret以达到从Private Registry Pull Image的目的。

操作之前,先删除掉各个Node上的~/.docker/config.json。

执行kubectl create secret docker-registry时需要提供private registry的访问UserName和Password:

1
2
3
4
5
6
7
8
9
10
11
12
13
➜  nexus kubectl get secret
NAME TYPE DATA AGE
default-token-fck44 kubernetes.io/service-account-token 3 15d
可以看到之前已经有个default-token的secret
➜ nexus
➜ nexus kubectl create secret docker-registry registrykey-2.6.2 --docker-server=registry.martin.com:5000 --docker-username=martin --docker-password=xxx1 --docker-email=hanniusshine@gmail.com
secret "registrykey-2.6.2" created

➜ nexus kubectl get secret
NAME TYPE DATA AGE
default-token-fck44 kubernetes.io/service-account-token 3 15d
registrykey-2.6.2 kubernetes.io/dockerconfigjson 1 3s
➜ nexus

secret: registrykey-2.6.2创建成功。测试一下引用这个secret对象的Pod是否能Pull Image成功并Run起来,引用时Pod的YAML文件中必须指定imagePullSecrets为创建的secrety,Pod yaml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  nexus cat test.yaml 
apiVersion: v1
kind: Pod
metadata:
name: rbd-rest-api-registrykey-2.6.2
spec:
containers:
- name: rbd-rest-api-registrykey-2.6.2
image: registry.martin.com:5000/registry
imagePullPolicy: Always
imagePullSecrets:
- name: registrykey-2.6.2
nodeSelector:
kubernetes.io/hostname: 192.168.1.16
nexus

创建Pod,查看Pod状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
➜  nexus kubectl create -f test.yaml
The Pod "rbd-rest-api-registrykey-m2.6.2-1" is invalid: spec.containers[0].name: Invalid value: "rbd-rest-api-registrykey-m2.6.2-1": a DNS-1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')
原来container的name命名只能用小写字母和-,不能用.号,所以修改name为:"rbd-rest-api-registrykey-m262-1"

再次创建ok:
➜ nexus kubectl create -f test.yaml
pod "rbd-rest-api-registrykey-m262-1" created
➜ nexus
➜ nexus kubectl get pods
NAME READY STATUS RESTARTS AGE
nexus3-68f55d9746-vfnf8 1/1 Running 0 18h
rbd-rest-api-registrykey-m262-1 1/1 Running 0 6s
➜ nexus

通过describe pod,查看创建的event序列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜  nexus kubectl describe pod/rbd-rest-api-registrykey-m262-1
...
部分省略
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 1m default-scheduler Successfully assigned rbd-rest-api-registrykey-m262-1 to 192.168.1.16
Normal SuccessfulMountVolume 1m kubelet, 192.168.1.16 MountVolume.SetUp succeeded for volume "default-token-fck44"
Normal Pulling 1m kubelet, 192.168.1.16 pulling image "registry.martin.com:5000/registry"
Normal Pulled 1m kubelet, 192.168.1.16 Successfully pulled image "registry.martin.com:5000/registry"
Normal Created 1m kubelet, 192.168.1.16 Created container
Normal Started 1m kubelet, 192.168.1.16 Started container
➜ nexus

正如期望的那样,引用了secret: registrykey-2.6.2的Pod成功Run起来了。

查看指定运行pod的节点是否run了对应的image:

1
2
3
[root@node3 docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
457e48f68bd7 registry.martin.com:5000/registry "/entrypoint.sh /e..." 6 minutes ago Up 5 minutes k8s_rbd-rest-api-registrykey-m262-1_rbd-rest-api-registrykey-m262-1_default_1265c1f5-75f3-11e8-8760-5254004f2222_0

如果一个pod中有来自不同私有仓库的不同镜像,需要怎么做呢?

通过kubectl create secret docker-registry一次只能建立一个registrykey,如果要访问两个镜像仓库,就需要分别为每个仓库创建一个registrykey。再来创建一个registrykey,对应的仓库为:registry.martin.com:6000

1
2
3
4
5
6
7
8
9
10
➜  nexus 
➜ nexus kubectl create secret docker-registry registrykey-2.6.3 --docker-server=registry.martin.com:6000 --docker-username=martin --docker-password=xxx2 --docker-email=hanniusshine@gmail.com
secret "registrykey-2.6.3" created

➜ nexus kubectl get secret
NAME TYPE DATA AGE
default-token-fck44 kubernetes.io/service-account-token 3 15d
registrykey-2.6.2 kubernetes.io/dockerconfigjson 1 3s
registrykey-2.6.3 kubernetes.io/dockerconfigjson 1 3s
➜ nexus

创建一个包含多个container的Pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  nexus cat test2.yaml 
apiVersion: v1
kind: Pod
metadata:
name: rbd-rest-api-multi-registrykeys-m262-2
spec:
containers:
- name: rbd-rest-api-multi-registrykeys-m262-2
image: registry.martin.com:5000/registry
imagePullPolicy: Always
- name: test-multi-registrykeys-m262-2
image: registry.martin.com:6000/registry
imagePullPolicy: Always
command:
- "tail"
- "-f"
- "/var/log/bootstrap.log"
imagePullSecrets:
- name: registrykey-2.6.2
- name: registrykey-2.6.3
nodeSelector:
kubernetes.io/hostname: 192.168.1.16
nexus

在secret引用中,将两个key都引用了进来。创建该pod

1
2
3
4
5
6
# kubectl create -f test2.yaml
pod "rbd-rest-api-multi-registrykeys-m262-2" created

# kubectl get pod
NAME READY STATUS RESTARTS AGE
rbd-rest-api-multi-registrykeys-m262-2 2/2 Running 0 5s

通过pod的event,看下启动的操作顺序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 1m default-scheduler Successfully assigned rbd-rest-api-registrykey-m262-1 to 192.168.1.16
Normal SuccessfulMountVolume 1m kubelet, 192.168.1.16 MountVolume.SetUp succeeded for volume "default-token-fck44"
Normal Pulling 1m kubelet, 192.168.1.16 pulling image "registry.martin.com:5000/registry"
Normal Pulled 1m kubelet, 192.168.1.16 Successfully pulled image "registry.martin.com:5000/registry"
Normal Created 1m kubelet, 192.168.1.16 Created container
Normal Started 1m kubelet, 192.168.1.16 Started container
Normal Pulling 1m kubelet, 192.168.1.16 pulling image "registry.martin.com:6000/registry"
Normal Pulled 1m kubelet, 192.168.1.16 Successfully pulled image "registry.martin.com:6000/registry"
Normal Created 1m kubelet, 192.168.1.16 Created container
Normal Started 1m kubelet, 192.168.1.16 Started container
➜ nexus

方法3:通过secret yaml文件创建pull image所用的secret

除了上面通过kubectl可以快捷的创建pull image所用的secret外,还可以使用常规的手段-yaml描述文件来创建需要的secret资源。

1
2
3
4
5
6
7
8
9
10
11
➜  nexus cat registrykey-m262-3.yaml 
apiVersion: v1
kind: Secret
metadata:
name: registrykey-m262-3
namespace: default
data:
#.dockerconfigjson: {base64 -w 0 ~/.docker/config.json}
.dockerconfigjson: xxxxx
type: kubernetes.io/dockerconfigjson
➜ nexus

前面说过docker login会在~/.docker下面创建一个config.json文件保存鉴权串,这里secret yaml的.dockerconfigjson后面的数据就是那个json文件的base64编码输出(-w 0让base64输出在单行上,避免折行)。

创建registrykey-m262-3 secret:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
➜  nexus cat ~/.docker/config.json                
{
"auths": {
"daocloud.io": {
"auth": "aGFubml1czppYnhnMVE1QQ=="
},
"https://index.docker.io/v1/": {
"auth": "aGFubml1czppYnhnMVE1QTg4Ng=="
},
"registry.martin.com:5000": {
"auth": "bWFydGluOmlieGcxUTVB"
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/17.09.0-ce (linux)"
}
}#
➜ nexus
因为此处"#"的问题,导致通过base64 -w 0 ~/.docker/config.json生成的base转码有问题,一直创建pod失败,原因是zsh模拟器引起的"#",切换到正常shell下ok

➜ nexus kubectl create -f registrykey-m262-3.yaml
secret "registrykey-m262-3" created
➜ nexus

➜ nexus kubectl get secret
NAME TYPE DATA AGE
default-token-fck44 kubernetes.io/service-account-token 3 15d
registrykey-2.6.2 kubernetes.io/dockerconfigjson 1 2h
registrykey-m262-3 kubernetes.io/dockerconfigjson 1 4m

如果是以前老版本可能出现:
两个registrykey secret的类型略有不同,前者是:kubernetes.io/dockercfg,后者是:kubernetes.io/dockerconfigjson

同样的可以使用describe命令来查看详细信息:

1
2
3
4
5
6
7
8
9
10
11
➜  nexus kubectl describe secret registrykey-m262-3
Name: registrykey-m262-3
Namespace: default
Labels: <none>
Annotations: <none>

Type: kubernetes.io/dockerconfigjson

Data
====
.dockerconfigjson: 305 bytes

可以看到Data区域没有直接展示出来,如果想查看的话可以使用-o yaml来输出展示出来:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜  nexus kubectl get secret registrykey-m262-3 -o yaml
apiVersion: v1
data:
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSJkYW9jbG91ZC5pbyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTsdsdcmc9PSIKCQl9LAoJCSJyZWdpc3RyeS5tYXJ0aW4uY29tOjUwMDAiOiB7CgkJCSJhdXRoIjogImJXRnlkR2x1T21saWVHY3hVVFZCIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xNy4wOS4wLWNlIChsaW51eCkiCgl9Cn0=
kind: Secret
metadata:
creationTimestamp: 2018-06-22T10:06:27Z
name: registrykey-m262-3
namespace: default
resourceVersion: "1519892"
selfLink: /api/v1/namespaces/default/secrets/registrykey-m262-3
uid: ed2f027e-7603-11e8-8760-5254004f2222
type: kubernetes.io/dockerconfigjson
➜ nexus

可以把上面的data.dockerconfigjson下面的数据做一个base64解码,看看里面的数据是怎样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
nexus echo ewoJImF1dGhzIjogewoJCSJkYW9jbG91ZC5pbyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRUT09IgoJCX0sCgkJImh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRVGc0Tmc9PSIKCQl9LAoJCSJyZWdpc3RyeS5tYXJ0aW4uY29tOjUwMDAiOiB7CgkJCSJdsddImJXRnlkR2x1T21saWVHY3hVVFZCIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xNy4wOS4wLWNlIChsaW51eCkiCgl9Cn0= |base64 -d
{
"auths": {
"daocloud.io": {
"auth": "aGFubmldffnhnMVE1QQ=="
},
"https://index.docker.io/v1/": {
"auth": "aGFubml1czffnhnMVE1QTg4Ng=="
},
"registry.martin.com:5000": {
"auth": "bWFydGff4dieGcxUTVB"
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/17.09.0-ce (linux)"
}
}# ➜ nexus

编写引用registrykey-m262-3的pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  nexus cat test3.yaml 
apiVersion: v1
kind: Pod
metadata:
name: rbd-rest-api-registrykey-m262-3
spec:
containers:
- name: rbd-rest-api-registrykey-m262-3
image: registry.martin.com:5000/os/alpine
imagePullPolicy: Always
imagePullSecrets:
- name: registrykey-m262-3
nodeSelector:
kubernetes.io/hostname: 192.168.1.16
nexus

创建运行pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
➜  nexus kubectl create -f test3.yaml 
pod "rbd-rest-api-registrykey-m262-3" created
➜ nexus kubectl get pod
NAME READY STATUS RESTARTS AGE
nexus3-68f55d9746-vfnf8 1/1 Running 0 3d
rbd-rest-api-registrykey-m262-1 1/1 Running 0 2d
rbd-rest-api-registrykey-m262-3 0/1 CrashLoopBackOff 1 7s
➜ nexus
➜ nexus kubectl describe pod rbd-rest-api-registrykey-m262-3
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 39s default-scheduler Successfully assigned rbd-rest-api-registrykey-m262-3 to 192.168.1.16
Normal SuccessfulMountVolume 39s kubelet, 192.168.1.16 MountVolume.SetUp succeeded for volume "default-token-fck44"
Normal Pulling 22s (x3 over 38s) kubelet, 192.168.1.16 pulling image "registry.martin.com:5000/os/alpine"
Normal Pulled 22s (x3 over 38s) kubelet, 192.168.1.16 Successfully pulled image "registry.martin.com:5000/os/alpine"
Normal Created 22s (x3 over 38s) kubelet, 192.168.1.16 Created container
Normal Started 22s (x3 over 37s) kubelet, 192.168.1.16 Started container
Warning BackOff 7s (x4 over 36s) kubelet, 192.168.1.16 Back-off restarting failed container

➜ nexus kubectl get pod
NAME READY STATUS RESTARTS AGE
nexus3-68f55d9746-vfnf8 1/1 Running 0 3d
rbd-rest-api-registrykey-m262-1 1/1 Running 0 2d
rbd-rest-api-registrykey-m262-3 1/1 Running 3 50s

创建成功。

那么这种方法如何应对含有来自多个镜像仓库container的Pod的呢?

这里的思路与方法2略有不同。不需要创建并引用两个或多个secret,而是==创建一个可以访问多个私有镜像仓库的secret==,需要将多个镜像仓库的访问鉴权串都放到~/.docker/config.json中:

1
2
3
4
5
6
7
{
"auths": {
"registry.martin.com:5000": {
"auth": "....省略...."
}
}
}

再docker login registry.martin.com:6000,得到config.json如下:

1
2
3
4
5
6
7
8
9
{
"auths": {
"registry.martin.com:5000": {
"auth": "....省略...."
},
"registry.martin.com:6000": {
"auth": "....省略...."
}
}

看到Docker自动将新login的private registry的鉴权串merge到了同一个config.json中了,与云镜像加速器daocloud.io类似

现在基于该包含了两个库鉴权串的config.json创建一个新secret:registrykey-m262-4:

1
2
3
4
5
6
7
8
9
10
➜  nexus cat registrykey-m262-4.yaml 
apiVersion: v1
kind: Secret
metadata:
name: registrykey-m262-4
namespace: default
data:
#.dockerconfigjson: {base64 -w 0 ~/.docker/config.json} #基于该命令创建下面base64 encode码
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSJkYW9jbG91ZC5pbyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRUT09IgoJCX0sCgkJImh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRVGc0Tmc9PSIKCQl9LAoJCSJyZWdpc3RyeS5tYXJ0aW4uY29tOjUwMDAiOiB7CgkJCSJhdXRoIjogImJXRnlkR2x1T21saWVHY3hVVFZCIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xNy4wOS4wLWNlIChsaW51eCkiCgl9Cn0=
type: kubernetes.io/dockerconfigjson

创建secret:registrykey-m262-4

1
# kubectl create -f registrykey-m262-4.yaml 

编辑一个包含两个容器,引用secret “registrykey-m262-4″ 的Pod yaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat test4.yaml
apiVersion: v1
kind: Pod
metadata:
name: rbd-rest-api-multi-registrykeys-m262-2
spec:
containers:
- name: rbd-rest-api-multi-registrykeys-m262-2
image: registry.martin.com:5000/xxxx/rbd-rest-api:latest
imagePullPolicy: Always
- name: test-multi-registrykeys-m262-2
image: registry.martin.com:6000/xxxx/test:latest
imagePullPolicy: Always
command:
- "tail"
- "-f"
- "/var/log/bootstrap.log"
imagePullSecrets:
- name: registrykey-m262-4

创建改pod:

1
2
3
4
5
6
7
# kubectl create -f test4.yaml
pod "rbd-rest-api-multi-registrykeys-m262-2" created

# kubectl get pod
NAME READY STATUS RESTARTS AGE
rbd-rest-api-multi-registrykeys-m262-2 2/2 Running 0 4s

Pod创建成功

调用API创建registrykey secret

对比了方法2和方法3,方法2更简洁,方法3更强大。但在任何一个产品中,secret都不应该是手动创建的,在这种情况下, API创建 registrykey secret便是必经之路。一旦选择通过API创建,我们显然将依仗着方法2中的原理,将config.json中的内容通过API请求的Body Post给K8s api server。

如何在远端构建出config.json的内容继而构建出secret yaml中.dockerconfigjson的值数据呢?

我们发现config.json套路中,唯一不确定的就是每个private repository下的auth串,那么这个串是啥?你大可base64 -d一下:

1
2
# echo -n "sddfhbfUGFzcgg3dgf="|base64 -d
UserName:Password

可以看到实质上这个auth串就是UserName:Password的base64编码值。因此,首先要用某个仓库的UserName和Password按照’UserName:Password’格式进行base64编码,利用编码的结果值构造json内容,比如:

1
2
3
4
5
6
{
"auths": {
"registry.martin.com:5000/xxxx/rbd-rest-api": {
"auth": "Vsddff3dfFzc3dfgQ="
}
}

然后对这段json数据再做base64编码,所得到的值就是secret yaml中的.dockerconfigjson的值数据。

通过API创建一个secret:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
➜  nexus cat secret_api.sh 
#!/bin/bash
#".dockerconfigjson": "{cat ~/.docker/config.json |base64 -w 0}"
curl -v -H "Content-type: application/json" -X POST -d ' {
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"name": "registrykey-m262-5",
"namespace": "default"
},
"data": {
".dockerconfigjson": "ewoJImF1dGhzIjogewoJCSJkYW9jbG91ZC5pbyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRUT09IgoJCX0sCgkJImh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRVGc0Tmc9PSIKCQl9LAoJCSJyZWdpc3RyeS5tYXJ0aW4uY29tOjUwMDAiOiB7CgkJCSJhdXRoIjogImJXRnlkR2x1T21saWVHY3hVVFZCIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xNy4wOS4wLWNlIChsaW51eCkiCgl9Cn0="
},
"type": "kubernetes.io/dockerconfigjson"
}' http://127.0.0.1:8080/api/v1/namespaces/default/secrets
➜ nexus
➜ nexus ./secret_api.sh
* About to connect() to 127.0.0.1 port 8080 (#0)
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
> POST /api/v1/namespaces/default/secrets HTTP/1.1
> User-Agent: curl/7.29.0
> Host: 127.0.0.1:8080
> Accept: */*
> Content-type: application/json
> Content-Length: 624
>
* upload completely sent off: 624 out of 624 bytes
< HTTP/1.1 201 Created
< Content-Type: application/json
< Date: Mon, 25 Jun 2018 07:01:04 GMT
< Content-Length: 830
<
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "registrykey-m262-5",
"namespace": "default",
"selfLink": "/api/v1/namespaces/default/secrets/registrykey-m262-5",
"uid": "86ccae15-7845-11e8-8760-5254004f2222",
"resourceVersion": "1815470",
"creationTimestamp": "2018-06-25T07:01:04Z"
},
"data": {
".dockerconfigjson": "ewoJImF1dGhzIjogewoJCSJkYW9jbG91ZC5pbyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRUT09IgoJCX0sCgkJImh0dHBzOi8vaW5kZXguZG9ja2VyLmlvL3YxLyI6IHsKCQkJImF1dGgiOiAiYUdGdWJtbDFjenBwWW5obk1WRTFRVGc0Tmc9PSIKCQl9LAoJCSJyZWdpc3RyeS5tYXJ0aW4uY29tOjUwMDAiOiB7CgkJCSJhdXRoIjogImJXRnlkR2x1T21saWVHY3hVVFZCIgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xNy4wOS4wLWNlIChsaW51eCkiCgl9Cn0="
},
"type": "kubernetes.io/dockerconfigjson"
* Connection #0 to host 127.0.0.1 left intact
}
➜ nexus kubectl get secret
NAME TYPE DATA AGE
default-token-fck44 kubernetes.io/service-account-token 3 17d
registrykey-2.6.2 kubernetes.io/dockerconfigjson 1 2d
registrykey-m262-3 kubernetes.io/dockerconfigjson 1 2d
registrykey-m262-5 kubernetes.io/dockerconfigjson 1 2m
➜ nexus

基于registrykey-m262-5,启动一个Pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Pod
metadata:
name: rbd-rest-api-registrykey-m262-5
spec:
containers:
- name: rbd-rest-api-registrykey-m262-5
image: registry.martin.com:5000/xxxx/api:latest
imagePullPolicy: Always
imagePullSecrets:
- name: registrykey-m262-5

# kubectl create -f test5.yaml
pod "rbd-rest-api-registrykey-m262-5" created

# kubectl get pod
NAME READY STATUS RESTARTS AGE
rbd-rest-api-registrykey-m262-5 1/1 Running 0 5s

Pod创建成功!


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!