跳到主要内容

Harbor 纯 MetalLB 部署方案

一、前置条件(已满足)​

  1. Kubernetes 集群(1.20+),已部署:
    • MetalLB(地址池已配置,有可用固定 IP,如 10.2.10.101)
    • Helm 3.x
    • 默认 StorageClass

二、完整部署步骤​

步骤 1:创建 Harbor 命名空间​

kubectl create namespace harbor
# 验证命名空间
kubectl get ns harbor

步骤 2:准备 Harbor 配置文件(harbor-longhorn.yaml)​

核心配置:直接通过 LoadBalancer 暴露 Harbor,指定 MetalLB 固定 IP:

sudo tee harbor-longhorn.yaml << 'EOF'
# ===================== 全局基础配置 =====================
harborAdminPassword: "Harbor12345"
externalURL: http://harbor.local # 纯HTTP,与环境一致
logLevel: info
imagePullPolicy: IfNotPresent
secretKey: "CHANGE_ME_HARBOR_SECRET_KEY" # 请替换为实际加密密钥(16 位以上随机字符串),勿提交真实值
updateStrategy:
type: Recreate

# ===================== 暴露配置(纯HTTP,无TLS) =====================
expose:
type: ingress
tls:
enabled: false # 禁用TLS,纯HTTP
certSource: auto
ingress:
hosts:
core: harbor.local
controller: default
className: nginx
annotations:
# 仅保留必要配置:允许大文件上传
nginx.ingress.kubernetes.io/proxy-body-size: "0"
# 关键:删除SSL重定向(HTTP环境无需跳转)
# nginx.ingress.kubernetes.io/ssl-redirect: "true" # 注释/删除
# 关键:删除HTTPS协议头(HTTP环境无需转发)
# nginx.ingress.kubernetes.io/forwarded-for-header: "X-Forwarded-For" # 删除
# nginx.ingress.kubernetes.io/x-forwarded-proto: "https" # 删除

# ===================== 持久化配置(保留你的S3+Longhorn) =====================
persistence:
enabled: true
resourcePolicy: "keep"
persistentVolumeClaim:
jobservice:
jobLog:
size: 1Gi
accessMode: ReadWriteOnce
storageClass: longhorn
annotations: {}
database:
size: 1Gi
accessMode: ReadWriteOnce
storageClass: longhorn
annotations: {}
redis:
size: 1Gi
accessMode: ReadWriteOnce
storageClass: longhorn
annotations: {}
# S3存储配置(保留原有)
imageChartStorage:
type: s3
disableredirect: true
s3:
region: "us-east-1"
regionendpoint: "http://192.168.192.119:9000"
accesskey: "harbor-user"
secretkey: "CHANGE_ME_S3_SECRET_KEY" # 请替换为实际 S3 凭据,勿提交真实密钥
bucket: "harbor-registry"
encrypt: false
secure: false
v4Auth: true
rootDirectory: "/registry"
skipverify: false

# ===================== 数据库配置(保留原有) =====================
database:
type: internal
internal:
password: "Harbor12345"
securityContext:
runAsUser: 999
runAsGroup: 999
fsGroup: 999
runAsNonRoot: true
livenessProbe:
exec:
command: ["pg_isready", "-U", "postgres"]
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
command: ["pg_isready", "-U", "postgres"]
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
maxIdleConns: 50
maxOpenConns: 200

# ===================== Redis配置(保留原有) =====================
redis:
type: internal
internal:
livenessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command: ["redis-cli", "ping"]
initialDelaySeconds: 5
periodSeconds: 5
jobserviceDatabaseIndex: "1"
registryDatabaseIndex: "2"

# ===================== 禁用内置Nginx(保留) =====================
nginx:
enabled: false

# ===================== 关闭冗余组件(保留) =====================
notary:
enabled: false
chartmuseum:
enabled: false
metrics:
enabled: false
trivy:
enabled: false

# ===================== 核心组件配置(适配HTTP的CSRF) =====================
core:
replicas: 1
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
extraEnvVars:
# 关键1:HTTP环境下,协议头设为http
- name: CORE_X_FORWARDED_PROTO
value: "http"
# 关键2:HTTP环境下,关闭CSRF Cookie的Secure标记(浏览器可携带)
- name: CORE_CSRF_COOKIE_SECURE
value: "false"
# 关键3:保留Cookie有效期(可选)
- name: CORE_CSRF_COOKIE_MAX_AGE
value: "86400"
# 关键4:信任代理(测试环境简化)
- name: CORE_TRUSTED_PROXIES
value: "0.0.0.0/0"

jobservice:
replicas: 1
maxJobWorkers: 5
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi

registry:
replicas: 1
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
EOF

步骤 3:添加 Harbor Helm 仓库(首次部署)​

helm repo add harbor https://helm.goharbor.io
helm repo update

#helm fetch harbor/harbor --untar

步骤 4:安装 Harbor​

helm upgrade --install harbor harbor/harbor --namespace harbor --values harbor-longhorn.yaml

步骤 5:验证 MetalLB 绑定与 Harbor 部署​

5.1 检查 Service 状态(核心)​

kubectl get svc -n harbor

预期输出(harbor Service 的 TYPE 为 LoadBalancer,EXTERNAL-IP 为指定的 10.2.10.101):

NAME                TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
harbor LoadBalancer 10.96.100.10 10.2.10.101 80:30080/TCP,443:30443/TCP 5m
harbor-database ClusterIP 10.96.100.11 <none> 5432/TCP 5m
harbor-redis ClusterIP 10.96.100.12 <none> 6379/TCP 5m
harbor-core ClusterIP 10.96.100.13 <none> 80/TCP 5m
harbor-registry ClusterIP 10.96.100.14 <none> 5000/TCP 5m

5.2 检查 Pod 状态​

kubectl get pods -n harbor -w

所有 Pod 状态变为 Running 即为部署完成(初始化约 2-5 分钟)。

步骤 6:访问与功能验证​

6.1 访问 Harbor Web 界面​

直接在浏览器访问 MetalLB 固定 IP:https://10.2.10.101,使用账号 admin/Harbor12345 登录(忽略自签名证书警告)。

6.2 镜像推送/拉取测试​

sudo tee -a /etc/hosts <<EOF
10.2.10.100 harbor.local # 替换为你的Harbor所在K3s节点IP
EOF
# 1. 登录Harbor(忽略自签名证书)
docker login -u 10.2.10.101:80 --insecure-registry

# 2. 标记并推送镜像
docker tag nginx:latest 10.2.10.101/library/nginx:latest
docker push 10.2.10.101/library/nginx:latest

# 3. 拉取镜像验证
docker pull 10.2.10.101/library/nginx:latest

三、核心说明​

1. 关键配置注意事项​

  • expose.loadBalancer.IP:必须是 MetalLB 地址池内的可用 IP,且未被其他 Service 占用;
  • externalURL:必须与 MetalLB IP 一致(https://<MetalLB_IP>),否则镜像推送/拉取会报「重定向错误」;
  • tls.commonName:建议与 MetalLB IP 一致,避免证书域名不匹配警告。

2. 存储配置说明​

Harbor 组件需要持久化存储来保存数据,包括:

  • chartmuseum:Helm Chart 存储
  • jobservice:任务服务数据
  • database:内部数据库数据
  • redis:缓存数据
  • trivy:漏洞扫描数据

在配置中指定了使用 longhorn StorageClass,确保集群中已部署 Longhorn 并创建了相应的 StorageClass。

3. 生产环境优化(可选)​

3.1 替换自定义 TLS 证书​

# 1. 创建证书Secret(证书CN需为MetalLB IP)
kubectl create secret tls harbor-tls-secret -n harbor \
--cert=./10.2.10.101.crt \
--key=./10.2.10.101.key

# 2. 修改配置文件(harbor-value.yaml)
expose:
tls:
enabled: true
secretName: harbor-tls-secret # 指定自定义证书Secret

3.2 资源限制配置(避免资源抢占)​

在配置文件中添加组件资源限制:

resources:
core:
requests: {cpu: 200m, memory: 512Mi}
limits: {cpu: 1000m, memory: 1Gi}
registry:
requests: {cpu: 200m, memory: 512Mi}
limits: {cpu: 1000m, memory: 1Gi}
jobservice:
requests: {cpu: 200m, memory: 512Mi}
limits: {cpu: 1000m, memory: 1Gi}

4. 故障排查​

故障现象排查方向
Service EXTERNAL-IP 为 1. 检查MetalLB地址池是否包含指定IP;2. 检查MetalLB Pod是否正常运行;3. 检查IP是否被占用
访问 IP 超时1. 检查Harbor Pod是否全部Running;2. 检查节点防火墙是否放行80/443端口;3. 检查MetalLB L2广告是否正常
镜像推送失败1. 检查externalURL是否与IP一致;2. 检查docker login是否成功;3. 查看harbor-core日志
PVC 状态为 Pending1. 检查StorageClass是否存在;2. 检查Longhorn是否正常运行

四、常用运维命令​

# 1. 查看Harbor核心日志
kubectl logs -n harbor deploy/harbor-core -f
kubectl logs -n harbor deploy/harbor-registry -f

# 2. 升级Harbor(修改配置后)
helm upgrade harbor harbor/harbor -n harbor --values harbor-value.yaml

# 3. 卸载Harbor(保留PVC)
helm uninstall harbor -n harbor

# 4. 查看MetalLB绑定详情
kubectl describe svc harbor -n harbor

国内镜像​

sudo ctr -n k8s.io images  pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-core:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-core:v2.14.1 docker.io/goharbor/harbor-core:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-db:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-db:v2.14.1 docker.io/goharbor/harbor-db:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-jobservice:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-jobservice:v2.14.1 docker.io/goharbor/harbor-jobservice:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/nginx-photon:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/nginx-photon:v2.14.1 docker.io/goharbor/nginx-photon:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-portal:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-portal:v2.14.1 docker.io/goharbor/harbor-portal:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/redis-photon:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/redis-photon:v2.14.1 docker.io/goharbor/redis-photon:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/registry-photon:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/registry-photon:v2.14.1 docker.io/goharbor/registry-photon:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-registryctl:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/harbor-registryctl:v2.14.1 docker.io/goharbor/harbor-registryctl:v2.14.1

sudo ctr -n k8s.io images pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/trivy-adapter-photon:v2.14.1
sudo ctr -n k8s.io images tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/goharbor/trivy-adapter-photon:v2.14.1 docker.io/goharbor/trivy-adapter-photon:v2.14.1

K3S透明代理配置​

sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/registries.yaml <<EOF
mirrors:
docker.io:
endpoint:
- "https://docker.1panel.live"
- "https://docker.1panelproxy.com"
- "https://docker.m.daocloud.io"
- "https://huecker.io"
- "https://dockerhub.timeweb.cloud"
- "https://noohub.ru"
- "https://b6ce57c867d045bob163be8658fd1438.mirror.swr.myhuaweicloud.com"
- "https://f2kfz0k0.mirror.aliyuncs.com"
- "https://registry.docker-cn.com"
- "http://hub-mirror.c.163.com"
- "https://docker.mirrors.ustc.edu.cn"
"k8s.gcr.io":
endpoint:
- "https://lank8s.cn"
- "https://k8s.lank8s.cn"
- "https://registry.aliyuncs.com/google_containers"
"gcr.io":
endpoint:
- "https://gcr.m.daocloud.io"
- "https://gcr.lank8s.cn"
"ghcr.io":
endpoint:
- "https://gcr.m.daocloud.io"
- "https://ghcr.lank8s.cn"
"registry.k8s.io":
endpoint:
- "https://registry.lank8s.cn"
- "https://registry.aliyuncs.com/v2/google_containers"
quay.io:
endpoint:
- "https://quay.tencentcloudcr.com/"
# Harbor自身地址(兜底,识别私有镜像)
"harbor.local":
endpoint:
- "http://harbor.local"

# 配置Harbor的认证和不安全访问(核心,必须保留)
configs:
"harbor.local":
auth:
username: wengtx # 替换为你的Harbor用户名
password: 123456 # 替换为你的Harbor密码
tls:
insecure_skip_verify: true # 兜底配置
EOF
sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/registries.yaml <<EOF
mirrors:
# Harbor自身地址(私有镜像)
"harbor.local":
endpoint:
- "http://harbor.local"

# 配置Harbor的认证和不安全访问(核心)
configs:
"harbor.local":
auth:
username: admin # 替换为你的Harbor用户名
password: 123456 # 替换为你的Harbor密码
tls:
insecure_skip_verify: true # 兜底配置
EOF

# 重启k3s生效
sudo systemctl restart k3s # master节点
sudo systemctl restart k3s-agent # worker节点

sudo k3s crictl pull k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.0.0-beta

(可选)配置 Harbor 访问外网的 HTTP(S) 代理​

不使用外网代理无法获取 gcr.io / k8s.gcr.io 的镜像

# 设置 HTTP_PROXY、HTTPS_PROXY 条目
kubectl edit -n harbor configmaps/harbor-core

# 重启 harbor-core 让设置生效
kubectl rollout restart -n harbor deployments/harbor-core
kubectl rollout status -n harbor deployments/harbor-core