Kubernetes中使用私有镜像仓库
Kubernetes应用在生产环境中时,一般都会搭建一套私有的镜像仓库。在使用私有镜像仓库pull镜像时需要密钥,可以提前在节点上pull所需镜像,也可以使用ImagePullSecrets来解决这个问题。
Note: 本文使用Harbor作为私有镜像仓库。
1. Docker login(方案一)
Docker pull 公有镜像仓库中的镜像时不需要认证信息,但pull私有仓库需要认证信息,所以需要用户提前登陆才可以pull该用户的镜像。
登陆成功之后会生成一个文件 $HOME/.docker/config.json或$HOME/.dockercfg,$HOME/.docker/config.json内容如下所示:
{ "auths": { "10.10.101.101": { "auth": "YWRtaW46MTIz" } } }
$HOME/.dockercfg内容如下所示:
{ "10.100.100.77": { "username":"hc", "password":"Harbor123456", "email":" ", "auth":"aGM6SGFyYm9yMTIzNDU2" } }
Note: auth为“用户名:密码”经base64加密后的字符串
确保集群所有节点都有.docker/config.json,可以通过Kubernetes直接创建Pod,因为有了认证信息Docker可以直接从仓库里面pull镜像。
2. 提前pull镜像(方案二)
通常情况下,Kubelet组件会从指定的镜像仓库pull所有需要的镜像;
如果imagePullPolicy设为IfNotPresent或Never,将会使用本地镜像;
如果使用提前pull所需镜像作为一种方案,必须确保及群中所有的节点都有所需的镜像;
这种方案可以节约pull镜像所需时间,也可以作为私有镜像仓库身份认证的一种替代方法;
3. ImgePullSecrets(方案三)
3.1 用户名、密码加密(base64)
# echo -n "hc" | base64aGM=# echo -n "Harbor12345" | base64SGFyYm9yMTIzNDU=
3.2 解密
# echo "SGFyYm9yMTIzNDU=" | base64 --decodeHarbor12345
3.3 Kubectl Create Secret
在tom namespace中创建myregistrysecret,这种方式实际上创建了一个.dockercfg
# kubectl create secret docker-registry myregistrysecret --docker-server=10.100.100.77 --docker-username=hc --docker-password=Harbor12345 --docker-email=" " -n tomsecret "myregistrysecret" created
如果需要访问多个私有仓库,可以给每个仓库创建一个secret,Kubelete在为Pod拉镜像时会把imagePullSecret合并到一个.docker/config.json文件中;需要注意的是,imagePullSecrets资源对象是属于namespace的。
3.4 yaml文件创建Secret
前面提到Docker登陆之后会生成两种类型的认证文件,Kubernetes同样支持创建这两种类型的ImagePullSecrets。
.docker/config.json 类型的ImagePullSecrets
# .docker/config.json 结构如下所示{"auths": {"10.100.100.77": {"auth": "Y2FwdGFpbjpDYXB0YWluODg4"}}}# 对.docker/config.json进行加密 # Note: 这里应特别注意使用\对分号“”进行转义,否则加密后的字符串会报错# echo -n "{\"auths\": {\"10.100.100.77\": {\"auth\": \"Y2FwdGFpbjpDYXB0YWluODg4\"}}}" | base64eyJhdXRocyI6IHsiMTAuMTAwLjEwMC43NyI6IHsiYXV0aCI6ICJZMkZ3ZEdGcGJqcERZWEIwWVdsdU9EZzQifX19#创建secretapiVersion: v1 kind: Secret metadata: name: configjson namespace: tom data: .dockerconfigjson: eyJhdXRocyI6IHsiMTAuMTAwLjEwMC43NyI6IHsiYXV0aCI6ICJZMkZ3ZEdGcGJqcERZWEIwWVdsdU9EZzQifX19 type: kubernetes.io/dockerconfigjson
.dockercfg 类型的ImagePullSecrets
# .dockercfg 结构如下所示: {"10.100.100.77":{"username":"captain","password":"Captain888","email":" ","auth":"Y2FwdGFpbjpDYXB0YWluODg4"}}# 对.dockercfg文件进行加密# echo "{\"10.100.100.77\":{\"username\":\"captain\",\"password\":\"Captain888\",\"email\":\" \",\"auth\":\"Y2FwdGFpbjpDYXB0YWluODg4\"}}" | base64 eyIxMC4xMDAuMTAwLjc3Ijp7InVzZXJuYW1lIjoiY2FwdGFpbiIsInBhc3N3b3JkIjoiQ2FwdGFpbjg4OCIsImVtYWlsIjoiICIsImF1dGgiOiJZMkZ3ZEdGcGJqcERZWEIwWVdsdU9EZzQifX0K# 创建secretapiVersion: v1 kind: Secret metadata: name: dockercfg namespace: tom data: .dockercfg: eyIxMC4xMDAuMTAwLjc3Ijp7InVzZXJuYW1lIjoiY2FwdGFpbiIsInBhc3N3b3JkIjoiQ2FwdGFpbjg4OCIsImVtYWlsIjoiICIsImF1dGgiOiJZMkZ3ZEdGcGJqcERZWEIwWVdsdU9EZzQifX0K type: kubernetes.io/dockercfg
3.5 使用ImagePullSecrets
使用ImagePullSecrets创建Pod,yaml文件如下;
apiVersion: v1 kind: Pod metadata: name: foo namespace: tom spec: containers: - name: foo image: 10.100.100.77/captain/nginx imagePullSecrets: - name: configjson #这里使用上面创建的2个ImagePullSecrets进行验证
4. 添加ImgePullSecrets到ServiceAccount(方案四)
ServiceAccount也是授权认证的一种方式,用于Pod内的进程与kube-apiserver通信时进行权限验证,后面会对ServiceAccount进行详解;创建namespace时,会默认创建一个名为default的serviceAccount;
按照3.4中的方法创建imagePullSecrets,并确保已经创建成功;
编辑默认serviceAccount default,添加imagePullSecrets,如下:
apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2017-06-03T10:14:35Z name: default namespace: tom resourceVersion: "3286613" selfLink: /api/v1/namespaces/tom/serviceaccounts/default uid: 71f62f3b-4845-11e7-8a65-005056bc0f6b secrets: - name: default-token-bwh8x# -----------------------------添加以下内容-------------------------------imagePullSecrets: - name: configjsons# -----------------------------添加内容结束-------------------------------
5. 小结
本文概述了私有镜像仓库的四种方案,各有优劣;
方案一,使用过程比较繁琐,在集群环境节点很多的情况下,每个节点登陆Docker无疑是一个非常繁琐的过程;
方案二,提前pull镜像,解决了权限认证的问题,但需要每个节点上都提前pull需要的镜像,这无疑也是一个非常繁琐的过程;另外,如果在一个有100个节点的集群中创建一个副本为3的rc,这100个节点都要提前pull镜像,会造成不必要的资源浪费;如果集群扩容新加节点,而这些节点没有之前的镜像,那么之前的应用将无法调度到这些新加的节点;
方案三,目前而言是相对较好的一个方案,适用于多租户环境下,可以细化到每个用户一个imagePullSecret; 创建Pod需要镜像的时候,通过imagePullSecrets的方式pull所需镜像,不会造成磁盘资源的浪费,也保证了镜像的安全性;
方案四,有一定优势,但不太适用于在多租户的环境下;
当然,使用哪种方式,还要根据实际情况而定,希望对你有所帮助!
作者:iCaptain
链接:https://www.jianshu.com/p/363827051406