携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情
本文已参与「开源摘星计划」,欢迎正在阅读的你加入。
活动链接:github.com/weopenproje…
【文章来源】:《Harbor进阶实战》公众号
前言
作为企业级的私有镜像仓库,Harbor提供了公有项目(Projects)和私有项目两种不同类型的仓库。公有项目中的镜像,任何的用户都可以直接拉取,而私有项目中的镜像,为保证镜像的安全性,仅拥有对应权限的用户才可以进行拉取,从而需要进行登录验证。
那么,在kubernetes部署应用的业务环境中,每次拉取镜像都需要我们登录Harbor吗?如果如此,那便太不符合需求了吧。
我们可以利用k8s的Secret资源对象,将Harbor用户的登录信息制作成密钥,在Pod创建资源时引用对应的Secret即可实现。
本篇文章以docker为k8s的容器运行时为例进行相关操作,containerd为容器运行时的配置将在后续文章进行分享!
环境说明
- Harbor version: 2.5.3
- kubernetes version: 1.20.15
- docker version: 19.03.8
- 操作系统: CentOS 7.8
- harbor服务地址: https://192.168.2.250:443
1、docker配置
kubernetes的节点若想从Harbor中拉取镜像,都需要在docker的配置文件中通过insecure-registries参数指定Harbor的服务地址。参考示例:
$ cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"insecure-registries": ["192.168.2.250:443"],
"storage-driver": "overlay2",
"log-driver": "json-file",
"live-restore": true,
"log-opts": {
"max-size": "500m",
"max-file": "2"
}
}
$ systemctl daemon-reload #重新加载配置
$ systemctl restart docker #重启docker使配置生效
注意:
每台运行Pod的kubernetes节点都需要进行该配置!
2、登录Harbor
在命令行登录Harbor,登录成功后会在当前用户下生成.docker/config.json文件,该文件含登录密钥,制作Secret时会根据该密钥
$ docker login 192.168.2.250:443
Username: admin #输入登录用户
Password: #输入用户密码
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded #出现该提示则表示登录成功!
如果报错请检查dockers的配置是否正常!
3、查看docker登录密钥数据
当docker login登录成功后,相信细心的你早已发现在~/.docker目录下多了个config.json文件。
注意:
每台运行Pod的kubernetes节点都需要进行该操作!未进行该操作的节点无法拉取到私有镜像。
$ ls -la ~/.docker/config.json
-rw------- 1 root root 155 8月 17 23:48 /root/.docker/config.json
$ cat ~/.docker/config.json
{
"auths": {
"192.168.2.250:443": {
"auth": "YWRtaW46SGFyYm9yMTIzNDU="
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.8 (linux)"
}
}
4、对密钥进行加密
用BASE64编码dockercfg内容。
$ cat ~/.docker/config.json | base64 -w 0
ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjIuMjUwOjQ0MyI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9IgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOS4wMy44IChsaW51eCkiCgl9Cn0=
-w 0 表示生成秘钥不转行,默认转行不是正确的格式会出错!
5、创建secrest资源对象
在kubernetes集群的master节点进行该操作。
1)编写资源清单文件
$ cat <<EOF > harbor-image-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: harbor-pull
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: ewoJImF1dGhzIjogewoJCSIxOTIuMTY4LjIuMjUwOjQ0MyI6IHsKCQkJImF1dGgiOiAiWVdSdGFXNDZTR0Z5WW05eU1USXpORFU9IgoJCX0KCX0sCgkiSHR0cEhlYWRlcnMiOiB7CgkJIlVzZXItQWdlbnQiOiAiRG9ja2VyLUNsaWVudC8xOS4wMy44IChsaW51eCkiCgl9Cn0=
EOF
注意:
.dockerconfigjson的值为前面执行命令cat ~/.docker/config.json | base64 -w 0获取到的值,需要填写自己生成的字符串!
Secret资源对象是命名空间级别的资源对象,可通过namespace参数将该secret创建在指定的命名空间。
2)创建Secret资源
根据刚才编写的yaml资源清单文件创建Secret资源对象。
$ kubectl apply -f harbor-image-secret.yaml
secret/harbor-pull created
3)查看验证
$ kubectl get secrets
NAME TYPE DATA AGE
default-token-xmdv2 kubernetes.io/service-account-token 3 25d
harbor-pull kubernetes.io/dockerconfigjson 1 2m11
6、Pod中指定镜像拉取凭证参数
下面基于Deployment控制器部署nginx服务,从Harbor的私有项目jenkins-demo中拉取私有镜像。
通过spec.imagePullSecrets参数指定刚才创建的secrets名称(可多个),该参数与containers参数同级别。
$ cat <<EOF > nginx-test.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
imagePullSecrets:
- name: harbor-pull
containers:
- name: nginx
image: 192.168.2.250:443/jenkins-demo/nginx:1.23.1-alpine
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: default
spec:
type: NodePort
selector:
app: nginx
ports:
- name: web
port: 80
protocol: TCP
targetPort: 80
EOF
$ kubectl apply -f nginx-test.yaml #创建nginx服务
- 验证Pod是否被成功创建
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-test-56b4465749-xpwqk 1/1 Running 0 3m54s
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 26d
nginx NodePort 10.107.180.109 <none> 80:42509/TCP 8m36s
可以发现镜像拉取成功,服务也创建成功!