拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Harbor 私有镜像仓库部署

Harbor 私有镜像仓库部署 Harbor 私有镜像仓库部署一、方案概述1.1 目标在 K8s 高可用集群上部署一套 Harbor 私有镜像仓库具备镜像存储存储 Docker 镜像和 Helm Chart访问控制用户认证、项目权限HTTPSLet’s Encrypt 泛域名证书持久化Longhorn 分布式存储高可用核心组件多副本外部访问FRP Ingress 从公网访问1.2 技术选型组件用途Harbor Helm Chart部署 HarborNginx Ingress Controller外部访问入口Longhorn持久化存储Let’s EncryptTLS 证书FRP内网穿透1.3 架构text外网用户 ↓ https://harbor.域名:40443 ↓ frpsvhost_https_port 40443 ↓ frpc ↓ 内网 VIP:443 ↓ HAProxy ↓ Ingress ControllerTLS 终止 ↓ Harbor Service ↓ Harbor Podcore、portal、registry、jobservice二、前置条件2.1 集群状态K8s 集群kubectl get nodes全部ReadyNginx Ingress Controller 已部署Longhorn 已部署longhornStorageClass 就绪FRP 已配置2.2 存储要求Harbor 需要 PVC 持久化数据。本文档使用Longhorn作为存储后端。关键约束Harbor registry 组件不支持多副本共享 RWO 卷所以registry和jobservice必须单副本。Longhorn 卷默认 3 副本如果节点磁盘空间紧张可以降到 2 副本。Longhorn 的storage-over-provisioning-percentage和storage-minimal-available-percentage需要提前调整否则卷会因insufficient storage调度失败。2.3 TLS 证书需要泛域名证书*.域名。本文档使用acme.sh Let’s Encrypt申请。2.4 FRP 配置frpc 需要加 HTTP 和 HTTPS 的 vhost 映射[harbor-http] type http local_ip 内网VIP local_port 80 custom_domains harbor.域名 [harbor-https] type https local_ip 内网VIP local_port 443 custom_domains harbor.域名三、申请 TLS 证书3.1 安装 acme.shcurl https://get.acme.sh | sh -s email邮箱 source ~/.bashrc3.2 配置 DNS API以阿里云为例export Ali_KeyAccessKeyID export Ali_SecretAccessKeySecret3.3 申请泛域名证书acme.sh --issue --server letsencrypt --dns dns_ali --dnssleep 60 -d 域名 -d *.域名解析--server letsencrypt指定 Let’s Encrypt不用 ZeroSSL。--dnssleep 60加完 TXT 记录后等 60 秒再验证。-d 域名 -d *.域名同时申请根域名和泛域名。证书路径~/.acme.sh/域名_ecc/fullchain.cer ~/.acme.sh/域名_ecc/域名.key3.4 配置自动续期脚本创建/root/update-tls-secrets.sh#!/bin/bash CERT_DIR/root/.acme.sh/域名_ecc NAMESPACES(harbor argocd jenkins gitlab default) for ns in ${NAMESPACES[]}; do kubectl create secret tls 域名-tls \ --cert$CERT_DIR/fullchain.cer \ --key$CERT_DIR/域名.key \ --namespace $ns \ --dry-runclient -o yaml | kubectl apply -f - done加执行权限chmod x /root/update-tls-secrets.sh配置 acme.sh 续期回调acme.sh --install-cert -d 域名 --ecc --reloadcmd /root/update-tls-secrets.sh四、安装 Harbor4.1 添加 Helm 仓库helm repo add harbor https://helm.goharbor.io helm repo update helm search repo harbor/harbor如果helm.goharbor.io访问超时从 GitHub 代理下载 chartcurl -fsSL https://ghproxy.net/https://github.com/goharbor/harbor-helm/releases/download/v1.19.2/harbor-1.19.2.tgz -o harbor-1.19.2.tgz4.2 创建命名空间kubectl create namespace harbor4.3 创建 TLS Secretkubectl create secret tls 域名-tls \ --cert/root/.acme.sh/域名_ecc/fullchain.cer \ --key/root/.acme.sh/域名_ecc/域名.key \ --namespace harbor4.4 创建 values.yamlexpose: type: ingress tls: enabled: true certSource: secret secret: secretName: 域名-tls notarySecretName: 域名-tls ingress: hosts: core: harbor.域名 className: nginx annotations: nginx.ingress.kubernetes.io/proxy-body-size: 0 nginx.ingress.kubernetes.io/proxy-read-timeout: 600 nginx.ingress.kubernetes.io/proxy-send-timeout: 600 nginx.ingress.kubernetes.io/ssl-redirect: true nginx.ingress.kubernetes.io/force-ssl-redirect: true externalURL: https://harbor.域名:40443 persistence: enabled: true resourcePolicy: keep persistentVolumeClaim: registry: storageClass: longhorn size: 15Gi database: storageClass: longhorn size: 20Gi redis: storageClass: longhorn size: 10Gi jobservice: storageClass: longhorn size: 10Gi trivy: storageClass: longhorn size: 10Gi harborAdminPassword: 强密码 core: replicas: 2 resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2 memory: 2Gi portal: replicas: 2 resources: requests: cpu: 200m memory: 256Mi limits: cpu: 1 memory: 1Gi jobservice: replicas: 1 resources: requests: cpu: 500m memory: 512Mi limits: cpu: 2 memory: 2Gi registry: replicas: 1 resources: requests: cpu: 500m memory: 512Mi limits: cpu: 2 memory: 2Gi database: type: internal internal: resources: requests: cpu: 500m memory: 1Gi limits: cpu: 2 memory: 2Gi redis: type: internal internal: resources: requests: cpu: 200m memory: 256Mi limits: cpu: 1 memory: 1Gi trivy: enabled: true replicas: 1 resources: requests: cpu: 200m memory: 512Mi limits: cpu: 1 memory: 1Gi4.5 逐项解析字段含义expose.type: ingress用 Ingress 暴露tls.enabled: true开启 HTTPStls.certSource: secret证书从 K8s Secret 读tls.secret.secretNameTLS Secret 名字ingress.hosts.coreHarbor 域名proxy-body-size: 0不限上传大小proxy-read-timeout: 600读超时 10 分钟ssl-redirect: trueHTTP 自动跳转 HTTPSexternalURL外部访问地址带端口persistence各组件 PVC 配置harborAdminPasswordadmin 初始密码core.replicas: 2core 双副本portal.replicas: 2portal 双副本jobservice.replicas: 1jobservice 单副本registry.replicas: 1registry 单副本关键点registry和jobservice必须单副本因为它们的卷是 RWO多副本会报Multi-Attach error。externalURL必须带端口因为外网访问是https://harbor.域名:40443。4.6 安装 Harborhelm install harbor harbor/harbor \ --namespace harbor \ -f /root/harbor-values.yaml如果helm.goharbor.io不通用本地 charthelm install harbor ./harbor-1.19.2.tgz \ --namespace harbor \ -f /root/harbor-values.yaml4.7 观察 Pod 启动kubectl get pods -n harbor -w按CtrlC退出。预期harbor-core-xxx 1/1 Running (2个) harbor-database-0 1/1 Running harbor-jobservice-xxx 1/1 Running harbor-portal-xxx 1/1 Running (2个) harbor-redis-0 1/1 Running harbor-registry-xxx 2/2 Running harbor-trivy-0 1/1 Running五、验证 Harbor5.1 查看 Pod 和 PVCkubectl get pods -n harbor kubectl get pvc -n harbor kubectl get ingress -n harbor预期所有 PodRunning。PVC 全部BoundSTORAGECLASS是longhorn。Ingress 有harbor-ingress域名harbor.域名。5.2 测试 HTTPS 访问curl -v https://harbor.域名:40443 21 | grep SSL certificate预期SSL certificate verify ok.5.3 浏览器访问https://harbor.域名:40443用户名admin密码你设置的强密码第一次登录会要求修改密码。5.4 创建项目登录后创建项目比如library。解析项目是 Harbor 里镜像的组织单位。推送镜像时路径是harbor.域名:40443/library/image:tag。六、配置 K8s 拉取 Harbor 镜像6.1 配置 containerd 信任 Harbor在每台节点上编辑/etc/containerd/config.toml在registry.mirrors段加[plugins.io.containerd.grpc.v1.cri.registry.mirrors.harbor.域名:40443] endpoint [https://harbor.域名:40443]用 Ansible 批量推ansible k8s_cluster -i inventory.ini -m shell -a grep -q registry.mirrors.\harbor.域名:40443\ /etc/containerd/config.toml || sed -i /\[plugins.\io.containerd.grpc.v1.cri\.registry.mirrors\]/a\ [plugins.\io.containerd.grpc.v1.cri\.registry.mirrors\.\harbor.域名:40443\]\n endpoint [\https://harbor.域名:40443\] /etc/containerd/config.toml systemctl restart containerd -b6.2 创建镜像拉取 Secretkubectl create secret docker-registry harbor-secret \ --docker-serverharbor.域名:40443 \ --docker-usernameadmin \ --docker-password强密码 \ --namespace default6.3 在 Deployment 里引用spec: template: spec: imagePullSecrets: - name: harbor-secret containers: - name: myapp image: harbor.域名:40443/library/myapp:1.06.4 验证拉取crictl pull harbor.域名:40443/library/nginx:latest七、常见问题7.1 Pod 卡在ImagePullBackOffHarbor 镜像在docker.io/goharbor上containerd 镜像加速应该能覆盖。如果拉不下来手动拉取并打标签crictl pull docker.m.daocloud.io/goharbor/harbor-jobservice:v2.15.2 ctr -n k8s.io images tag docker.m.daocloud.io/goharbor/harbor-jobservice:v2.15.2 docker.m.daocloud.io/goharbor/harbor-jobservice:v2.15.2如果某个节点拉不下来从其他节点导出ctr -n k8s.io images export /tmp/jobservice.tar docker.m.daocloud.io/goharbor/harbor-jobservice:v2.15.2 scp /tmp/jobservice.tar root目标节点:/tmp/ ctr -n k8s.io images import /tmp/jobservice.tar7.2 registry 多副本时Multi-Attach error原因registry 用 RWO 卷多副本无法共享。解决方案registry.replicas: 1。或者改 Deployment 的更新策略为Recreatekubectl patch deployment -n harbor harbor-registry -p {spec:{strategy:{type:Recreate}}}7.3 PVC 绑不上卷faulted或degraded原因Longhorn 卷调度失败。排查kubectl get volumes.longhorn.io -n longhorn-system kubectl get volume.longhorn.io volume-name -n longhorn-system -o yaml | grep -A5 type: Scheduled如果报insufficient storagekubectl patch settings.longhorn.io storage-over-provisioning-percentage -n longhorn-system --typemerge -p {value:200} kubectl patch settings.longhorn.io storage-minimal-available-percentage -n longhorn-system --typemerge -p {value:10}然后触发副本重建kubectl get engines.longhorn.io -n longhorn-system | grep volume-name kubectl delete engine.longhorn.io engine-name -n longhorn-system7.4 Harbor 登不上报relation properties does not exist原因database 重建后表没建。解决方案删掉 Harbor 和所有 PVC重建。helm uninstall harbor -n harbor kubectl delete pvc -n harbor --all kubectl delete namespace harbor kubectl create namespace harbor kubectl create secret tls 域名-tls --cert/root/.acme.sh/域名_ecc/fullchain.cer --key/root/.acme.sh/域名_ecc/域名.key --namespace harbor helm install harbor harbor/harbor -n harbor -f /root/harbor-values.yaml7.5 413 Request Entity Too Large原因Ingress 的proxy-body-size太小。解决方案设为0不限大小。7.6 HTTPS 访问报证书错误原因证书链不完整或 Secret 没配对。排查kubectl get secret 域名-tls -n harbor kubectl describe ingress -n harbor harbor-ingress | grep TLS7.7 镜像拉取超时Harbor 镜像在docker.io/goharbor上。如果拉不下来配置 containerd 镜像加速或手动导入。八、常用操作8.1 查看 Harbor 状态kubectl get pods -n harbor kubectl get svc -n harbor kubectl get ingress -n harbor kubectl get pvc -n harbor8.2 查看日志kubectl logs -n harbor -l componentcore --tail100 kubectl logs -n harbor -l componentregistry --tail100 kubectl logs -n harbor -l componentdatabase --tail1008.3 取 admin 密码kubectl get secret -n harbor harbor-core -o jsonpath{.data.HARBOR_ADMIN_PASSWORD} | base64 -d echo8.4 升级 Harborhelm upgrade harbor harbor/harbor -n harbor -f /root/harbor-values.yaml8.5 删除 Harborhelm uninstall harbor -n harbor kubectl delete pvc -n harbor --all kubectl delete namespace harbor警告删除 PVC 会删除所有镜像数据操作前先备份。九、架构总结9.1 组件清单组件副本数作用harbor-core2API 服务、认证harbor-portal2Web UIharbor-registry1镜像存储harbor-jobservice1镜像复制、扫描任务harbor-database1PostgreSQL 数据库harbor-redis1缓存harbor-trivy1镜像扫描9.2 端口速查端口用途40443外网 HTTPS 入口40080外网 HTTP 入口443内网 HAProxy HTTPS80内网 HAProxy HTTP30443Ingress Controller HTTPS NodePort30080Ingress Controller HTTP NodePort9.3 已知隐患隐患影响解决方案registry/jobservice 单副本节点故障服务中断需要 RWX 存储才能多副本Longhorn 空间调度保守卷报insufficient storage改 over-provisioning 和 minimal-available证书手动更新续期后 Secret 需更新配 acme.sh 续期回调脚本database 重建后表没建Harbor 登不上删掉 Harbor 和 PVC重建十、总结这套 Harbor 基于官方 Helm Chart 部署提供了镜像存储私有 Docker 镜像仓库访问控制用户认证和项目权限外部访问FRP Ingress 从公网访问HTTPSLet’s Encrypt 泛域名证书持久化Longhorn 分布式存储高可用core、portal 多副本部署中最容易踩的坑chart 拉取超时用 GitHub 代理下载本地安装。registry 多副本 Multi-Attachregistry 和 jobservice 必须单副本。卷容量超过节点可用空间registry 卷不要超过 20Gi。Longhorn 空间调度保守改storage-over-provisioning-percentage200和storage-minimal-available-percentage10。Harbor database 表没建删掉 Harbor 和所有 PVC重建。HTTPS 证书链不完整用fullchain.cer。externalURL 不带端口外网访问带 40443externalURL必须包含端口。解决了这七个问题Harbor 就能稳定运行。
返回列表