写在前面:源自工作压力和对职业前景的迷茫,好久没更新技术文章了,以及售前岗对技术上手操作越来越少,写的笔记到也有不少,但都比较零散(只记录遇到的故障了)。
Harbor简介
Harbor 是VMware开源的一个私有化部署的注册表,是 CNCF 毕业项目,主要用于企业或个人搭建私有的容器镜像仓库,同时也支持作为 helmchart 仓库服务。
部署规划
1. 部署规划
1.1. 应用访问入口规划
- 使用traefik ingress作为应用入口
- 启用https:通过traefik ingress启用https
1.2. 数据存储规划
- 使用外部PostgreSQL数据库,数据库已创建完成
- 使用内部Redis
- 使用S3存储 docker 镜像和 Helm charts 包
- 使用NFS创建Storage Class
序号 | 存储类型 | 存储信息 | 存储用途及备注 |
---|---|---|---|
1 | PostgreSQL13.11 | 主机:192.168.xxx.xxx:5432 数据库名:harbor 用户名:harbor 密码:***** |
数据库 |
2 | Redis | 主机: 数据库名: 用户名: 密码:***** |
缓存 |
3 | s3存储 | regionendpoint:https://s3.xdpai.site:8443 bucket:harbor accesskey: pVEEWhUZx8NmIY9J secretkey: zU6Yqz4op7i3z4dKo7NUPzFZMFdDuNQT |
存储 docker 镜像和 Helm charts 包 |
4 | Storage Class和PVC | Storage Class的NFS服务地址:192.168.xxx.xxx 共享路径:/mnt/data01/k3s-nfs-sc01 |
harbor 本身服务(JobService 和 trivy 等)使用 |
- 备注:
- harbor 2.8.1部署时,PostgreSQL版本不能过高,否则notary-server和notary-signer容器内部报”Error starting postgres driver: pq: unknown authentication response: 10“错误。
2. 先决条件准备
- traefik ingress部署已完成
- 数据库、存储准备已完成
- 本章节重点配置存储类,创建harbor 本身服务存储使用的pv及pvc
2.1. 安装NFS CSI驱动器
-
Kubernetes 不包含内部 NFS 驱动,
k8s官方手册推荐使用“NFS subdir external provisioner”和“NFS Ganesha server and external provisioner”作为外部驱动,本次案例使用外部的NFS服务,所以provisioner使用“NFS subdir external provisioner”。2024年8月更新:最新发现k8s官方手册改为推荐“csi-driver-nfs”作为nfs的驱动程序,它的 CSI 插件名为 nfs.csi.k8s.io。
注:网络不好的,请多次尝试或科学上网。
1)通过kubectl联网安装(kubectl命令在脚本中,也可以用helm安装) root@op[~]# curl -skSL https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/v4.9.0/deploy/install-driver.sh | bash -s v4.9.0 -- 或者:通过kubectl本地安装 root@op[~]# git clone https://github.com/kubernetes-csi/csi-driver-nfs.git root@op[~]# cd csi-driver-nfs ./deploy/install-driver.sh v4.9.0 local
-
检查 Pod 状态:
root@op[~]# kubectl -n kube-system get pod -o wide -l app=csi-nfs-controller root@op[~]# kubectl -n kube-system get pod -o wide -l app=csi-nfs-node
-
查看 Kubernetes 集群中支持的所有 CSI 驱动程
root@op[~]# kubectl get csidrivers NAME ATTACHREQUIRED PODINFOONMOUNT STORAGECAPACITY TOKENREQUESTS REQUIRESREPUBLISH MODES AGE nfs.csi.k8s.io false false false
false Persistent 0d
2.2. 创建存储类(StorageClass)
-
创建存储类
1) 创建yaml文件 root@op[~]# cat nfs-sc01.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: nfs-client annotations: # 此操作是1.25的以上的一个alpha的新功能,是将此storageclass设置为默认 storageclass.kubernetes.io/is-default-class: "true" # 此处指定了csidrivers的名称 provisioner: nfs.csi.k8s.io parameters: # NFS的Server server: 192.168.xxx.xxx # NFS的存储路径 share: /mnt/data01/nfs-sc01 # csi.storage.k8s.io/provisioner-secret is only needed for providing mountOptions in DeleteVolume # csi.storage.k8s.io/provisioner-secret-name: "mount-options" # csi.storage.k8s.io/provisioner-secret-namespace: "default" reclaimPolicy: Retain volumeBindingMode: Immediate mountOptions: # 这里不只可以配置nfs的版本 - nfsvers=4.1 2)通过yaml创建存储类资源 root@op[~]# kubectl apply -f nfs-sc01.yaml
-
查看存储类
root@op[~]# $ kubectl get sc NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE nfs-client (default) nfs.csi.k8s.io Retain Immediate false 38d
2.3. PVC创建
harbor多个服务对应的存储可选择独立pvc;也可以选择共用一个pvc,通过子路径的方式区别不同服务的存储。本次使用共享pvc的方式,所以需要手动创建pvc
-
创建一个用于安装Harbor的Kubernetes命名空间。可以使用以下命令:
root@op[~]# kubectl create namespace harbor
-
创建PVC的yaml文件
root@op[~]# cat harbor-pvc.yaml apiVersion: v1 kind: PersistentVolumeClaim metadata: name: harbor-pv-claim namespace: harbor spec: storageClassName: nfs-client #从上述的存储类中自动申请pv并绑定 accessModes: - ReadWriteOnce resources: requests: storage: 30Gi
-
创建PVC资源
root@op[~]# kubectl apply -f harbor-pvc.yaml
在 K8S 上部署 Harbor
安装Harbor可以使用Kubernetes Helm Chart来简化部署过程。以下是在Kubernetes上安装Harbor的基本步骤:
-
添加Harbor Helm Chart的仓库。可以使用以下命令:
1. 首次安装执行: root@op[~]# helm repo add harbor https://helm.goharbor.io 2. 如果之前添加过,请更新可用chart的信息,否则最新版查询不到 root@op[~]# helm repo update harbor //说明:此命令harbor是之前添加库的名称
-
查找harbor
root@op[~]# helm search repo harbor -l // -l参数显示每个chart的每个版本,不加-l参数将显示最新版本 NAME CHART VERSION APP VERSION DESCRIPTION harbor/harbor 1.12.1 2.8.1 An open source trusted cloud native registry th... harbor/harbor 1.12.0 2.8.0 An open source trusted cloud native registry th... harbor/harbor 1.11.2 2.7.2 An open source trusted cloud native registry th... harbor/harbor 1.11.1 2.7.1 An open source trusted cloud native registry th... harbor/harbor 1.11.0 2.7.0 An open source trusted cloud native registry th...
-
从Helm Chart中提取配置文件。可以使用以下命令:
root@op[~]# helm fetch harbor/harbor --version=
--untar - 这里需要将
<version>
替换为您要安装的Harbor版本号,安装最新版本可省略此参数。
- 这里需要将
-
配置Harbor:可以编辑
values.yaml
文件以根据您的需要更改配置。一些重要的配置项包括Harbor的域名和数据库设置。#服务公开配置 expose: # 设置如何公开服务,设置类型支持“ingress”、“clusterIP”、“nodePort”或“loadBalancer”,本项目以traefik ingress为例 type: ingress tls: # 启用TLS. enabled: true # traefik ingress配置了默认的tls证书,所以不用配置入口TLS证书,certSource配置为none即可 certSource: none ingress: hosts: core: harbor.xdpai.site notary: notary.xdpai.site # 设置 ingress 控制器类型: # 1. 大多数的 ingress 控制器使用
default
即可. # 如果使用 GCE ingress 控制器,设置为gce
# 如果使用 NCP (NSX-T Container Plugin) ingress 控制器,设置为ncp
# 如果使用 ALB ingress 控制器,设置为alb
# 如果使用 F5 BIG-IP ingress 控制器,设置为f5-bigip
controller: default annotations: # 不同的 ingress 控制器可能需要不同的ssl-redirect注释,这里以 traefik ingress 为例 ingress.kubernetes.io/ssl-redirect: "true" ingress.kubernetes.io/proxy-body-size: "0" kubernetes.io/ingress.class: traefik traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.tls.certresolver: default # Harbor core 服务的外部URL,就是我们web界面访问的地址,也是 docker/helm 命令使用的地址 # 格式: protocol://domain[:port]. 通常来说: # 1) 如果 "expose.type" 是 "ingress", 上述格式的 "domain" 的值是 "expose.ingress.hosts.core" # 2) 如果 "expose.type" 是 "clusterIP", 上述格式的 "domain" 的值是 "expose.clusterIP.name" # 3) 如果 "expose.type" 是 "nodePort", 上述格式的 "domain" 的值是 k8s 节点的 IP 地址 # 如果Harbor部署在代理后面,则将其设置为代理的URL externalURL: https://harbor.xdpai.site # 存储配置 persistence: enabled: true # 将其设置为 "keep" 以避免在 helm 删除过程中删除 PVC,但不包含内部数据库和 redis 组件创建的 PVC resourcePolicy: "keep" persistentVolumeClaim: registry: # Use the existing PVC which must be created manually before bound, # and specify the "subPath" if the PVC is shared with other components existingClaim: "harbor-pv-claim" # Specify the "storageClass" used to provision the volume. Or the default # StorageClass will be used (the default). # Set it to "-" to disable dynamic provisioning storageClass: "" subPath: "registry" accessMode: ReadWriteOnce size: 5Gi annotations: {} chartmuseum: existingClaim: "harbor-pv-claim" storageClass: "" subPath: "chartmuseum" accessMode: ReadWriteOnce size: 5Gi annotations: {} jobservice: jobLog: existingClaim: "harbor-pv-claim" storageClass: "" subPath: "jobservice" accessMode: ReadWriteOnce size: 1Gi annotations: {} # If external database is used, the following settings for database will # be ignored database: existingClaim: "harbor-pv-claim" storageClass: "" subPath: "database" accessMode: ReadWriteOnce size: 1Gi annotations: {} # If external Redis is used, the following settings for Redis will # be ignored redis: existingClaim: "harbor-pv-claim" storageClass: "" subPath: "redis" accessMode: ReadWriteOnce size: 1Gi annotations: {} trivy: existingClaim: "harbor-pv-claim" storageClass: "" subPath: "trivy" accessMode: ReadWriteOnce size: 5Gi annotations: {} # Define which storage backend is used for registry and chartmuseum to store # images and charts. Refer to # https://github.com/docker/distribution/blob/master/docs/configuration.md#storage # for the detail. imageChartStorage: # Specify whether to disableredirect
for images and chart storage, for # backends which not supported it (such as using minio fors3
storage type), please disable # it. To disable redirects, simply setdisableredirect
totrue
instead. # Refer to # https://github.com/docker/distribution/blob/master/docs/configuration.md#redirect # for the detail. disableredirect: false # Specify the "caBundleSecretName" if the storage service uses a self-signed certificate. # The secret must contain keys named "ca.crt" which will be injected into the trust store # of registry's and chartmuseum's containers. # caBundleSecretName: # Specify the type of storage: "filesystem", "azure", "gcs", "s3", "swift", # "oss" and fill the information needed in the corresponding section. The type # must be "filesystem" if you want to use persistent volumes for registry # and chartmuseum type: s3 s3: # Set an existing secret for S3 accesskey and secretkey # keys in the secret should be AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY for chartmuseum # keys in the secret should be REGISTRY_STORAGE_S3_ACCESSKEY and REGISTRY_STORAGE_S3_SECRETKEY for registry #existingSecret: "" region: us-west-1 #必须填写,否则registry容器会异常,如果minio没有配置地区(region),填写默认的us-west-1即可 bucket: harbor accesskey: pVEEWhUZx8NmI2dJ secretkey: zU6Y123op7i3z4dKo7NUPzFZ321DuNQT regionendpoint: https://s3.xdpai.site:8443 encrypt: false #keyid: mykeyid secure: true #skipverify: false v4auth: true #chunksize: "5242880" rootdirectory: / #storageclass: STANDARD #multipartcopychunksize: "33554432" #multipartcopymaxconcurrency: 100 #multipartcopythresholdsize: "33554432" # The initial password of Harbor admin. Change it from portal after launching Harbor harborAdminPassword: "Harbor1245" database: # if external database is used, set "type" to "external" # and fill the connection informations in "external" section type: external external: host: "192.168.xxx.xxx" port: "5432" username: "harbor" password: "xxxxxxxxxxxxxxxx" coreDatabase: "registry" notaryServerDatabase: "notary_server" notarySignerDatabase: "notary_signer" redis: # if external Redis is used, set "type" to "external" # and fill the connection informations in "external" section type: internal -
安装Harbor:可以使用以下命令:
root@op[~]# helm install harbor harbor/harbor -n harbor -f values.yaml
- 这里的
-n harbor
表示将Harbor安装到名为harbor
的Kubernetes命名空间中,-f values.yaml
表示使用先前配置的值。
- 这里的
-
等待Harbor安装完成。可以使用以下命令检查Harbor是否已完全安装:
root@op[~]# kubectl get pods -n harbor
- 一旦所有Harbor的pod都处于"Running"状态,就可以访问Harbor了。
-
配置域名。如果您在values.yaml文件中设置了Harbor的域名,请将该域名解析到Harbor的IP地址上。
现在,您可以使用浏览器访问Harbor,并开始上传和管理容器
QA's
Q1:k8s中使用私有仓库x509问题
-
解决方案:
- 下载harbor的ca证书
- 将harbor的ca.crt文件上传到所有k8s节点的/etc/ssl/certs目录,重启containerd服务即可
root@op[~]# mv ca.crt /etc/ssl/certs/harbor.crt root@op[~]# systemctl restart containerd.service