一、简介
Harbor 是一个用于存储和分发 Docker 镜像的企业级 Registry 服务器,通过添加一些企业必需的功能特性,例如安全、标识和管理等,扩展了开源 Docker Distribution。作为一个企业级私有 Registry 服务器,Harbor 提供了更好的性能和安全。提升用户使用 Registry 构建和运行环境传输镜像的效率。
二、先决条件
- Kubernetes 1.12+
- Helm 2.12+ 或 Helm 3.0-beta3 +
- 集群有默认的动态存储可用
- 使用 StorageClass 提供 PV 动态存储
三、准备环境
1、系统环境
- kubernetes 版本:1.18.5
- Nginx Ingress 版本:2.2.8
- Harbor Chart 版本:1.4.2
- Harbor 版本:2.0.2
- Helm 版本:3.2.4
- 持久化存储驱动:NFS
2、核实动态存储
确认默认 StorageClass:
$ kubectl get storageclass
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-storage nfs-nfs-storage Delete WaitForFirstConsumer false 17d
nfs-storage-new (default) nfs-client Delete Immediate false 2d19h
如果不是期望的,可以通过以下命令进行修改:
$ kubectl patch storageclass rook-ceph-block -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
具体参考:https://kubernetes.io/docs/tasks/administer-cluster/change-default-storage-class/
3、安装 Helm3
3.1、在线安装
Helm 现在具有一个安装程序脚本,该脚本将自动获取最新版本的 Helm 并将其本地安装。
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh
Downloading https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz
Preparing to install helm into /usr/local/bin
helm installed into /usr/local/bin/helm
官方参考:https://helm.sh/docs/intro/quickstart/
3.2、下载安装
访问 Helm Github 下载页面 https://github.com/helm/helm/releases 找到最新的客户端,里面有不同系统下的包,这里我们选择 Linux amd64,然后在 Linux 系统中使用 Wget 命令进行下载。
# 下载Helm客户端
wget https://get.helm.sh/helm-v3.2.4-linux-amd64.tar.gz
# 接下来解压下载的包,然后将客户端放置到 /usr/local/bin/ 目录下:
# 解压 Helm
tar -zxvf helm-v3.2.4-linux-amd64.tar.gz
# 复制客户端执行文件到 bin 目录下,方便在系统下能执行 helm 命令
cp linux-amd64/helm /usr/local/bin/
❝
注意:helm 客户端需要下载到安装了 kubectl 并且能执行能正常通过 kubectl 操作 kubernetes 的服务器上,否则 helm 将不可用。
❞
4、创建 Namespace
由于 Harbor 组件较多,一般我们会采取新建一个 Namespace 专用于部署 Harbor 相关组件,输入下面命令创建名为 harbor
kubectl create namespace harbor
四、创建自定义证书
安装 Harbor 我们会默认使用 HTTPS 协议,需要 TLS 证书,如果我们没用自己设定自定义证书文件,那么 Harbor 将自动创建证书文件,不过这个有效期只有一年时间,所以这里我们生成自签名证书,为了避免频繁修改证书,将证书有效期为 10 年,操作如下:
1、生成证书文件:
下面执行步骤时,需要输入一些证书信息,其中 Common Name 必须要设置为和你要给 Harbor 的域名保持一致,如 Common Name (eg, your name or your server's hostname) []:hub.7d.com。
# 获得证书
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt
# 生成证书签名请求
openssl req -newkey rsa:4096 -nodes -sha256 -keyout tls.key -out tls.csr
# 生成证书
openssl x509 -req -days 3650 -in tls.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt
2、生成 secret 对象
创建 Kubernetes 的 Secret 资源,且将证书文件导入:
kubectl create secret generic hub-7d-tls --from-file=tls.crt --from-file=tls.key --from-file=ca.crt -n harbor
查看是否创建成功:
kubectl get secret hub-7d-tls -n harbor
可以观察到:
NAME TYPE DATA AGE
hub-7d-tls Opaque 3 52m
五、设置自定义参数
由于我们需要通过 Helm 安装 Harbor 仓库,需要提前创建 Harbor Chart 的配置清单文件,里面是对要创建的应用 Harbor 进行一系列参数配置,由于参数过多,关于都有 Harbor Chart 都能够配置哪些参数这里就不一一罗列,可以通过访问 Harbor-helm 的 Github 地址 进行了解。
下面描述下,需要的一些配置参数:
「values.yaml:」
#Ingress 网关入口配置
expose:
type: ingress
tls:
### 是否启用 https 协议
enabled: true
ingress:
hosts:
### 配置 Harbor 的访问域名,需要注意的是配置 notary 域名要和 core 处第一个单词外,其余保持一致
core: hub.7d.com
notary: notary.7d.com
controller: default
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/proxy-body-size: "0"
#### 如果是 traefik ingress,则按下面配置:
# kubernetes.io/ingress.class: "traefik"
# traefik.ingress.kubernetes.io/router.tls: 'true'
# traefik.ingress.kubernetes.io/router.entrypoints: websecure
#### 如果是 nginx ingress,则按下面配置:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
nginx.org/client-max-body-size: "0"
## 如果Harbor部署在代理后,将其设置为代理的URL,这个值一般要和上面的 Ingress 配置的地址保存一致
externalURL: https://hub.7d.com
### Harbor 各个组件的持久化配置,并设置各个组件 existingClaim 参数为上面创建的对应 PVC 名称
persistence:
enabled: true
### 存储保留策略,当PVC、PV删除后,是否保留存储数据
resourcePolicy: "keep"
persistentVolumeClaim:
registry:
storageClass: "nfs-storage-new"
size: 20Gi
chartmuseum:
storageClass: "nfs-storage-new"
size: 5Gi
jobservice:
storageClass: "nfs-storage-new"
size: 1Gi
database:
storageClass: "nfs-storage-new"
size: 1Gi
redis:
storageClass: "nfs-storage-new"
size: 1Gi
trivy:
storageClass: "nfs-storage-new"
size: 5Gi
### 默认用户名 admin 的密码配置,注意:密码中一定要包含大小写字母与数字
harborAdminPassword: "admin@123"
### 设置日志级别
logLevel: info
#各个组件 CPU & Memory 资源相关配置
nginx:
resources:
requests:
memory: 256Mi
cpu: 500m
portal:
resources:
requests:
memory: 256Mi
cpu: 500m
core:
resources:
requests:
memory: 256Mi
cpu: 1000m
jobservice:
resources:
requests:
memory: 256Mi
cpu: 500m
registry:
registry:
resources:
requests:
memory: 256Mi
cpu: 500m
controller:
resources:
requests:
memory: 256Mi
cpu: 500m
clair:
clair:
resources:
requests:
memory: 256Mi
cpu: 500m
adapter:
resources:
requests:
memory: 256Mi
cpu: 500m
notary:
server:
resources:
requests:
memory: 256Mi
cpu: 500m
signer:
resources:
requests:
memory: 256Mi
cpu: 500m
database:
internal:
resources:
requests:
memory: 256Mi
cpu: 500m
redis:
internal:
resources:
requests:
memory: 256Mi
cpu: 500m
trivy:
enabled: true
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
cpu: 1000m
memory: 1024Mi
#开启 chartmuseum,使 Harbor 能够存储 Helm 的 chart
chartmuseum:
enabled: true
resources:
requests:
memory: 256Mi
cpu: 500m
六、安装 Harbor
1、添加 Helm 仓库
helm repo add harbor https://helm.goharbor.io
2、部署 Harbor
helm install harbor harbor/harbor --version 1.4.2 -f values.yaml -n harbor
安装完成后,我们核实下安装情况:
$ kubectl get deployment -n harbor
NAME READY UP-TO-DATE AVAILABLE AGE
harbor-harbor-chartmuseum 1/1 1 1 122m
harbor-harbor-clair 1/1 1 1 122m
harbor-harbor-core 1/1 1 1 122m
harbor-harbor-jobservice 1/1 1 1 122m
harbor-harbor-notary-server 1/1 1 1 122m
harbor-harbor-notary-signer 1/1 1 1 122m
harbor-harbor-portal 1/1 1 1 122m
harbor-harbor-registry 1/1 1 1 122m
查看 ingress:
$ kubectl get ingress -n harbor
NAME CLASS HOSTS ADDRESS PORTS AGE
harbor-harbor-ingress <none> hub.7d.com 80, 443 21h
harbor-harbor-ingress-notary <none> notary.7d.com 80, 443 21h
3、Host 配置域名
接下来配置 Hosts,客户端想通过域名访问服务,必须要进行 DNS 解析,由于这里没有 DNS 服务器进行域名解析,所以修改 hosts 文件将 Harbor 指定节点的 IP 和自定义 host 绑定。
需要将域名的 DNS 指向任意 node 服务器地址
$ cat /etc/hosts
172.16.106.203 hub.7d.com
4、访问 harbor
输入地址 https://hub.7d.com 访问 Harbor 仓库。
- 用户:admin
- 密码:admin@123 (在安装配置中自定义的密码)、
进入后可以看到 Harbor 的管理后台:
5、服务器配置镜像仓库
1、下载 Harbor 证书
由于 Harbor 是基于 Https 的,故而需要提前配置 tls 证书,进入:Harobr主页->配置管理->系统配置->镜像库根证书
2、服务器 Docker 中配置 Harbor 证书
然后进入服务器,在服务器上 /etc/docker
目录下创建 certs.d 文件夹,然后在 certs.d 文件夹下创建 Harobr 域名文件夹,可以输入下面命令创建对应文件夹:
mkdir -p /etc/docker/certs.d/hub.7d.com
然后再 /etc/docker/certs.d/hub.mydlq.club 目录下上床上面的 ca 证书文件。
3、登录 Harbor 仓库
只有登录成功后才能将镜像推送到镜像仓库,所以配置完证书后尝试登录,测试是否能够登录成功:
如果提示 ca 证书错误,则重建检测证书配置是否有误。
docker login -u admin -p admin@123 hub.7d.com
6、服务器配置 Helm Chart 仓库
1、配置 Helm 证书
跟配置 Docker 仓库一样,配置 Helm 仓库也得提前配置证书,上传 ca 签名到目录 /etc/pki/ca-trust/source/anchors/
:
$ cat /etc/pki/ca-trust/source/anchors/ca.crt
-----BEGIN CERTIFICATE-----
MIIC9TCCAd2gAwIBAgIRALztT/b8wlhjw50UECEOTR8wDQYJKoZIhvcNAQELBQAw
FDESMBAGA1UEAxMJaGFyYm9yLWNhMB4XDTIwMDIxOTA3NTgwMFoXDTIxMDIxODA3
NTgwMFowFDESMBAGA1UEAxMJaGFyYm9yLWNhMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEArYbsxYmNksU5eQhVIM3OKac4l6MV/5u5belAlWSdpbbQCwMF
G/gAliTSQMgqcmhQ3odYTKImvx+5zrhP5b1CWXCQCVOlOFSLrs3ZLv68ZpKoDLkg
6XhoQFVPLM0v5V+YzWCGAson81LfX3tDhltnOItSpe2KESABVH+5L/2vo25P7Mvw
4bWEWMyY4AS/3toiDZjhwNMrMb2lpICrlH9Sc3dAOzUteyVznA5/WF8IyPI64aKn
tl0gxLOZgUBTkBoxVhPj7dNNZu8lMnqAYXmhWt+oRr7t1HHp2lOtk2u/ndyV0kKL
xufx5FYVJQel2yRBGc/C1QLN18nC1y6u5pITaQIDAQABo0IwQDAOBgNVHQ8BAf8E
BAMCAqQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8GA1UdEwEB/wQF
MAMBAf8wDQYJKoZIhvcNAQELBQADggEBACFT92PWBFeCT7By8y8+EkB2TD1QVMZm
NDpBS75q5s2yIumFwJrbY6YsHtRkN1Zx9jc4LiJFHC6r0ES3tbCDapsxocvzn7dW
XLNTtnSx0zPxNXZzgmTsamfunBd4gszdXMshJ+bKsEoTXhJEXVjZq/k0EZS8L4Mp
NZ7ciPqwAI1Tg+mFGp5UOvzxYLyW8nCLPykC73y3ob1tiO6xdyD/orTAbA6pIMc9
7ajTfwYj4Q6JPY/QAmu0S+4hJHs724IrC6hiXUlQNVVRW/d3k+nXbYttnnmPnQXC
RyK2ru7R8H43Zlwj26kQJo6naQoQ0+Xcjcyk5llPqJxCrk3uoHF0r4U=
-----END CERTIFICATE-----
❝
如果下面执行的目录不存在,请用 yum 安装 ca-certificates 包。
❞
执行更新命令,使证书生效:
update-ca-trust extract
2、添加 Helm 仓库
添加 Helm 仓库:
helm repo add myrepo --username=admin --password=admin@123 https://hub.7d.com/chartrepo/library
-username
:harbor仓库用户名-password
:harbor仓库密码-ca-file
:指向ca.crt证书地址chartrepo
:如果是chart仓库地址,中间必须加 chartrepolibrary
:仓库的项目名称
查看仓库列表:
$ helm repo list
NAME URL
myrepo https://hub.7d.com/chartrepo/library
七、测试功能
1、推送与拉取 Docker 镜像
这里为了测试推送镜像,先下载一个用于测试的 helloworld 小镜像,然后推送到 hub.mydlq.club 仓库:
# 拉取 Helloworld 镜像
docker pull hello-world:latest
# 将下载的镜像使用 tag 命令改变镜像名
docker tag hello-world:latest hub.7d.com/library/hello-world:latest
# 推送镜像到镜像仓库
docker push hub.7d.com/library/hello-world:latest
将之前的下载的镜像删除,然后测试从 hub.7d.com
下载镜像进行测试:
# 删除之前镜像
docker rmi hello-world:latest
docker rmi hello-world:latest hub.7d.com/library/hello-world:latest
# 测试从 `hub.7d.com` 下载新镜像
docker pull hub.7d.com/library/hello-world:latest
2、推送与拉取 Chart
Helm 要想推送 Chart 到 Helm 仓库,需要提前安装上传插件:
helm plugin install https://github.com/chartmuseum/helm-push
# 然后创建一个测试的 Chart 进行推送测试:
helm create hello
# 打包chart,将chart打包成tgz格式
helm package hello
# 推送 chart 进行测试
helm push hello-0.1.0.tgz myrepo
Pushing hello-0.1.0.tgz to myrepo...
八、遇到的问题
1、Error response from daemon: Get https://hub.7d.com/v2/: x509: certificate signed by unknown authorit
需要到 docker.service
中修改下参数就可以了
修改 /usr/lib/systemd/system/docker.service
配置:
# ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock
重启docker:
## 守护进程重启
sudo systemctl daemon-reload
## 重启docker服务
sudo systemctl restart docker
2、413 Request Entity Too Large
$ docker push hub.7d.com/mall_repo/mall-portal:1.0
The push refers to repository [hub.7d.com/mall_repo/mall-portal]
5a8f64cc7f4c: Pushing [==================================================>] 73.98MB/73.98MB
35c20f26d188: Layer already exists
c3fe59dd9556: Preparing
6ed1a81ba5b6: Layer already exists
a3483ce177ce: Layer already exists
ce6c8756685b: Waiting
30339f20ced0: Waiting
0eb22bfb707d: Waiting
a2ae92ffcd29: Waiting
error parsing HTTP 413 response body: invalid character '<' looking for beginning of value: "<html>\r\n<head><title>413 Request Entity Too Large</title></head>\r\n<body>\r\n<center><h1>413 Request Entity Too Large</h1></center>\r\n<hr><center>nginx/1.17.3</center>\r\n</body>\r\n</html>\r\n"
解决办法是自定义参数文件增加:
ingress:
hosts:
### 配置 Harbor 的访问域名,需要注意的是配置 notary 域名要和 core 处第一个单词外,其余保持一致
core: hub.7d.com
notary: notary.7d.com
controller: default
annotations:
ingress.kubernetes.io/ssl-redirect: "true"
ingress.kubernetes.io/proxy-body-size: "0"
#### 如果是 traefik ingress,则按下面配置:
# kubernetes.io/ingress.class: "traefik"
# traefik.ingress.kubernetes.io/router.tls: 'true'
# traefik.ingress.kubernetes.io/router.entrypoints: websecure
#### 如果是 nginx ingress,则按下面配置:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
# 增加 Nignx配置,放开限制:A
nginx.org/client-max-body-size: "0"
示例源码: