Harbor 是一个 CNCF 基金会托管的开源的可信的云原生 docker registry 项目,可以用于存储、签名、扫描镜像内容,Harbor 通过添加一些常用的功能如安全性、身份权限管理等来扩展 docker registry 项目,此外还支持在 registry 之间复制镜像,还提供更加高级的安全功能,如用户管理、访问控制和活动审计等,在新版本中还添加了 Helm 仓库托管的支持。
Harbor 最核心的功能就是给 docker registry 添加上一层权限保护的功能,要实现这个功能,就需要我们在使用 docker login、pull、push 等命令的时候进行拦截,先进行一些权限相关的校验,再进行操作,其实这一系列的操作 docker registry v2 就已经为我们提供了支持,v2 集成了一个安全认证的功能,将安全认证暴露给外部服务,让外部服务去实现。
本章使用到的yaml文件地址:https://files.cnblogs.com/files/sanduzxcvbnm/harbor_yaml.zip?t=1654757668
上面我们说了 docker registry v2 将安全认证暴露给了外部服务使用,那么是怎样暴露的呢?我们在命令行中输入 docker login https://registry.qikqiak.com 为例来为大家说明下认证流程:
要完成上面的登录认证过程有两个关键点需要注意:怎样让 registry 服务知道服务认证地址?我们自己提供的认证服务生成的 token 为什么 registry 就能够识别?
对于第一个问题,比较好解决,registry 服务本身就提供了一个配置文件,可以在启动 registry 服务的配置文件中指定上认证服务地址即可,其中有如下这样的一段配置信息:
......
auth:
token:
realm: token-realm
service: token-service
issuer: registry-token-issuer
rootcertbundle: /root/certs/bundle
......
其中 realm 就可以用来指定一个认证服务的地址,下面我们可以看到 Harbor 中该配置的内容。
关于 registry 的配置,可以参考官方文档:https://docs.docker.com/registry/configuration/
第二个问题,就是 registry 怎么能够识别我们返回的 token 文件?如果按照 registry 的要求生成一个 token,是不是 registry 就可以识别了?所以我们需要在我们的认证服务器中按照 registry 的要求生成 token,而不是随便乱生成。那么要怎么生成呢?我们可以在 docker registry 的源码中可以看到 token 是通过 JWT(JSON Web Token)来实现的,所以我们按照要求生成一个 JWT 的 token 就可以了。
对 golang 熟悉的同学可以去 clone 下 Harbor 的代码查看下,Harbor 采用 beego 这个 web 开发框架,源码阅读起来不是特别困难。我们可以很容易的看到 Harbor 中关于上面我们讲解的认证服务部分的实现方法。
由于 Harbor 涉及的组件太多了,所以我们这里用更加便捷的 Helm 来进行安装。首先添加仓库地址:
$ helm repo add harbor https://helm.goharbor.io
"harbor" has been added to your repositories
在安装 Harbor 的时候有很多可以配置的参数,可以在 harbor-helm 项目上进行查看。
比如这里我们将主域名配置为 harbor.k8s.local,通过前面的 Ceph RBD 的 StorageClass 来提供存储,又因为前面我们在安装 GitLab 的时候就已经单独安装了 postgresql 和 reids 两个数据库,所以我们也可以配置 Harbor 使用这两个外置的数据库,这样可以降低资源的使用。但是使用外置的数据库我们需要提前手动创建数据库,比如我们这里使用的 GitLab 提供的数据库,则进入该 Pod 创建 registry、clair、notary_server、notary_signer 这4个数据库:
$ kubectl get pods -n kube-ops -l name=postgresql
NAME READY STATUS RESTARTS AGE
postgresql-6f494df48-frsvp 1/1 Running 0 5d3h
$ kubectl exec -it postgresql-6f494df48-frsvp /bin/bash -n kube-ops
root@postgresql-6f494df48-frsvp:~$ sudo su - postgres
postgres@postgresql-6f494df48-frsvp:~$ psql
psql (10.9 (Ubuntu 10.9-1.pgdg18.04+1))
Type "help" for help.
postgres=# CREATE DATABASE registry OWNER postgres; # 创建 registry 数据库
CREATE DATABASE
postgres=# GRANT ALL PRIVILEGES ON DATABASE registry to postgres; # 授权给 postgres 用户
GRANT
postgres=# GRANT ALL PRIVILEGES ON DATABASE registry to gitlab; # 授权给 gitlab 用户
GRANT
# Todo: 用同样的方式创建其他三个数据库:clair、notary_server、notary_signer
......
postgres-# \q # 退出
数据库准备过后,就可以使用我们自己定制的 values 文件来进行安装了,完整的定制的 values 文件如下所示:(harbor-values.yaml)
externalURL: https://harbor.k8s.local
harborAdminPassword: Harbor12345
logLevel: debug
expose:
type: ingress
tls:
enabled: true
ingress:
hosts:
core: harbor.k8s.local
notary: notary.k8s.local
persistence:
enabled: true
resourcePolicy: "keep"
persistentVolumeClaim:
registry:
# 如果需要做高可用,多个副本的组件则需要使用支持 ReadWriteMany 的后端,ceph rbd 是不支持的,可以使用 cephfs,可以换成前面我们使用的 rook-ceph-fs
storageClass: "rook-ceph-block"
# 如果是高可用的,多个副本组件需要使用 ReadWriteMany,默认为 ReadWriteOnce
accessMode: ReadWriteOnce
size: 50Gi
chartmuseum:
storageClass: "rook-ceph-block"
accessMode: ReadWriteOnce
size: 10Gi
jobservice:
storageClass: "rook-ceph-block"
accessMode: ReadWriteOnce
size: 2Gi
database:
type: external
external:
host: "postgresql.kube-ops.svc.cluster.local"
port: "5432"
username: "gitlab"
password: "passw0rd"
redis:
type: external
external:
#host: "redis.kube-ops.svc.cluster.local"
#port: "6379"
addr: "redis.kube-ops.svc.cluster.local:6379" # 不再使用host和port,否则使用host和port写法,不会采用配置,而是用默认的192.168.0.2:6379
# 默认为一个副本,如果要做高可用,只需要设置为 replicas >= 2 即可
portal:
replicas: 1
core:
replicas: 1
jobservice:
replicas: 1
registry:
replicas: 1
chartmuseum:
replicas: 1
clair:
replicas: 1
notary:
server:
replicas: 1
signer:
replicas: 1
这些配置信息都是根据 Harbor 的 Chart 包默认的 values 值进行覆盖的。现在我们直接安装即可:
$ helm install myharbor harbor/harbor -f values.yaml -n kube-ops
NAME: myharbor
LAST DEPLOYED: Tue May 12 15:23:15 2020
NAMESPACE: kube-ops
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at https://harbor.k8s.local.
For more details, please visit https://github.com/goharbor/harbor.
正常情况下隔一会儿就可以安装成功了:
$ helm ls -n kube-ops
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
myharbor kube-ops 1 2020-05-12 15:23:15.194263 +0800 CST deployed harbor-1.3.21.10.2
$ kubectl get pods -n kube-ops -l app=harbor
NAME READY STATUS RESTARTS AGE
myharbor-harbor-chartmuseum-95f9d9898-mqqnn 1/1 Running 0 40m
myharbor-harbor-clair-79fb8694b4-5dnk5 2/2 Running 10 40m
myharbor-harbor-core-c7bdc46d9-qw9hc 1/1 Running 0 79s
myharbor-harbor-jobservice-549d67dc87-j6hr8 1/1 Running 0 79s
myharbor-harbor-notary-server-9d57d5d9f-9fvbw 1/1 Running 10 40m
myharbor-harbor-notary-signer-658d7886-2ssrl 1/1 Running 10 40m
myharbor-harbor-portal-65588b87db-d7whd 1/1 Running 0 40m
myharbor-harbor-registry-5f7cc9d69d-89hkw 2/2 Running 0 40m
安装完成后,我们就可以将域名 harbor.k8s.local 解析到 Ingress Controller 所在的节点,我们这里使用的仍然是 Traefik,由于我们开启了 KubernetesIngress 支持的,所以我们只需要将域名解析到 Traefik 的 Pod 所在节点即可,然后就可以通过该域名在浏览器中访问了:
$ kubectl get ingress -n kube-ops
NAME HOSTS ADDRESS PORTS AGE
myharbor-harbor-ingress harbor.k8s.local,notary.k8s.local 80, 443 41m
用户名使用默认的 admin,密码则是上面配置的默认 Harbor12345:
登录过后即可进入 Harbor 的 Dashboard 页面:
我们可以看到有很多功能,默认情况下会有一个名叫 library 的项目,该项目默认是公开访问权限的,进入项目可以看到里面还有 Helm Chart 包的管理,可以手动在这里上传,也可以对该项目里面的镜像进行一些其他配置。
现在我们来测试下使用 docker cli 来进行 pull/push 镜像,直接使用 docker login 命令登录:
$ docker login harbor.k8s.local
Username: admin
Password:
INFO[0006] Error logging in to v2 endpoint, trying next endpoint: Get https://harbor.k8s.local/v2/: x509: certificat
e signed by unknown authority
Get https://harbor.k8s.local/v2/: x509: certificate signed by unknown authority
这是因为在使用 docker login 登录的时候会使用 https 的服务,而我们这里是自签名的证书,所以就报错了,我们可以将使用到的 CA 证书文件复制到 /etc/docker/certs.d/harbor.k8s.local 目录下面来解决这个问题(如果该目录不存在,则创建它)。ca.crt 这个证书文件我们可以通过 Ingress 中使用的 Secret 资源对象来提供:
$ kubectl get secret myharbor-harbor-ingress -n kube-ops -o yaml
apiVersion: v1
data:
ca.crt: <ca.crt>
tls.crt: <tls.crt>
tls.key: <tls.key>
kind: Secret
metadata:
creationTimestamp: "2020-05-12T07:23:20Z"
labels:
app: harbor
chart: harbor
heritage: Helm
release: myharbor
name: myharbor-harbor-ingress
namespace: kube-ops
resourceVersion: "67162075"
selfLink: /api/v1/namespaces/kube-ops/secrets/myharbor-harbor-ingress
uid: 10a9d22d-3889-4ac4-87c4-5cda7e701828
type: kubernetes.io/tls
其中 data 区域中 ca.crt 对应的值就是我们需要证书,不过需要注意还需要做一个 base64 的解码,这样证书配置上以后就可以正常访问了。
不过由于上面的方法较为繁琐,所以一般情况下面我们在使用 docker cli 的时候是在 docker 启动参数后面添加一个 --insecure-registry 参数来忽略证书的校验的,在 docker 启动配置文件 /usr/lib/systemd/system/docker.service 中修改ExecStart的启动参数:
ExecStart=/usr/bin/dockerd --insecure-registry harbor.k8s.local
或者在 Docker Daemon 的配置文件中添加:
$ cat /etc/docker/daemon.json
{
"insecure-registries" : [
"harbor.k8s.local"
],
"registry-mirrors" : [
"https://ot2k4d59.mirror.aliyuncs.com/"
]
}
然后保存重启 docker,再使用 docker cli 就没有任何问题了:
$ docker login harbor.k8s.local
Username: admin
Password:
Login Succeeded
比如我们本地现在有一个名为 busybox 的镜像,现在我们想要将该镜像推送到我们的私有仓库中去,应该怎样操作呢?首先我们需要给该镜像重新打一个具有 harbor.k8s.local 前缀的镜像,然后推送的时候就可以识别到推送到哪个镜像仓库:
$ docker tag busybox harbor.k8s.local/library/busybox
$ docker push harbor.k8s.local/library/busybox
The push refers to repository [harbor.k8s.local/library/busybox]
5b0d2d635df8: Pushed
latest: digest: sha256:a2490cec4484ee6c1068ba3a05f89934010c85242f736280b35343483b2264b6 size: 527
推送完成后,我们同样可以在 Portal 页面上看到这个镜像的信息:
镜像 push 成功,同样可以测试下 pull:
$ docker rmi harbor.k8s.local/library/busybox
Untagged: harbor.k8s.local/library/busybox:latest
Untagged: harbor.k8s.local/library/busybox@sha256:a2490cec4484ee6c1068ba3a05f89934010c85242f736280b35343483b2264b6
$ docker rmi busybox
Untagged: busybox:latest
Untagged: busybox@sha256:061ca9704a714ee3e8b80523ec720c64f6209ad3f97c0ff7cb9ec7d19f15149f
$ docker pull harbor.k8s.local/library/busybox:latest
latest: Pulling from library/busybox
e2334dd9fee4: Already exists
Digest: sha256:a2490cec4484ee6c1068ba3a05f89934010c85242f736280b35343483b2264b6
Status: Downloaded newer image for harbor.k8s.local/library/busybox:latest
harbor.k8s.local/library/busybox:latest
$ docker images |grep busybox
harbor.k8s.local/library/busybox latest be5888e67be6 3 weeks ago 1.22MB
到这里证明上面我们的私有 docker 仓库搭建成功了,大家可以尝试去创建一个私有的项目,然后创建一个新的用户,使用这个用户来进行 pull/push 镜像,Harbor还具有其他的一些功能,比如镜像复制,大家可以自行测试,感受下 Harbor 和官方自带的 registry 仓库的差别。
Harbor 的大部分组件都是无状态的应用,比如 portal、core 等只需要增加其相应的副本数量即可;在存储数据层面,需要提供高可用的 Postgresql、Redis 集群,另外针对镜像和 chart 服务也需要提供可持久的存储。
要做高可用的 Harbor,我们需要将数据库通过外置方式进行提供,当然也需要保证数据库是高可用的。然后存储需要允许跨节点数据共享,也就是要支持 ReadWriteMany 模式,我们这里使用 Ceph 的话就需要使用 CephFS。然后将其他组件副本数设置为大于等于2:portal.replicas、core.replicas、jobservice.replicas、registry.replicas、chartmuseum.replicas、clair.replicas、notary.server.replicas 以及 notary.signer.replicas。
然后重新使用 Helm 进行安装即可。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章