​Kubernetes 集群仓库 harbor Helm3 部署_推送

一、简介

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 (在安装配置中自定义的密码)、​Kubernetes 集群仓库 harbor Helm3 部署_服务器_02

进入后可以看到 Harbor 的管理后台:​Kubernetes 集群仓库 harbor Helm3 部署_服务器_03

5、服务器配置镜像仓库

1、下载 Harbor 证书

由于 Harbor 是基于 Https 的,故而需要提前配置 tls 证书,进入:Harobr主页->配置管理->系统配置->镜像库根证书​Kubernetes 集群仓库 harbor Helm3 部署_docker_04

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仓库地址,中间必须加 chartrepo
  • library:仓库的项目名称

查看仓库列表:

$ 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"

示例源码: