使用 Helm 部署 Harbor 并配置为 Docker 和 Helm Chart 仓库

前言

在现代云原生应用开发中,容器镜像和 Helm Chart 的高效管理变得至关重要。Harbor 是一个开源的企业级 Docker Registry 管理项目,提供了权限管理、镜像漏洞扫描、镜像复制等功能。结合 Helm 这个 Kubernetes 的包管理工具,我们可以轻松地在 Kubernetes 集群中部署和管理 Harbor。

本文将详细介绍如何安装 Helm,使用 Helm 部署 Harbor,并配置 Docker 和 Helm 客户端使用 Harbor 作为镜像和 Chart 仓库。


1. Helm 介绍与安装

什么是 Helm?

Helm 是 Kubernetes 的包管理器,类似于 Ubuntu 的 apt 或 CentOS 的 yum。它允许开发者和运维人员轻松地查找、共享和使用为 Kubernetes 构建的应用程序。

Helm 使用称为 Chart 的包装格式,Chart 是描述一组相关 Kubernetes 资源的文件集合。通过 Helm,您可以:

  • 简化 Kubernetes 应用程序的部署和管理
  • 轻松实现应用程序的版本控制
  • 共享应用程序配置模板
  • 管理应用程序的依赖关系

安装 Helm

Helm 的安装非常简单,只需执行以下命令:

bash 复制代码
# 下载并安装 Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# 验证安装
helm version

这条命令会下载最新的 Helm 版本并自动安装。安装完成后,您可以通过 helm version 命令验证安装是否成功。


2. 安装和配置 kubectl

kubectl 是 Kubernetes 命令行工具,允许您对 Kubernetes 集群运行命令。我们需要安装 kubectl 以便与 Kubernetes 集群交互。

配置 Kubernetes 仓库并安装 kubectl

bash 复制代码
# 创建 Kubernetes 仓库配置文件
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF

# 安装指定版本的 kubectl
yum install -y kubectl-1.18.0

# 验证安装
kubectl version --client

配置集群访问权限

为了让 Helm 能够与 Kubernetes API Server 交互,我们需要将集群的认证配置复制到 Helm 所在的主机:

bash 复制代码
# 在 Kubernetes Master 节点上执行
scp .kube/config root@helm_ip:~/.kube/config

请将 helm_ip 替换为实际运行 Helm 的主机 IP 地址。此操作会将 Kubernetes 集群的访问配置复制到 Helm 主机,使 Helm 能够管理集群资源。


3. 使用 Helm 部署 Harbor

添加 Harbor Helm 仓库

首先,我们需要将 Harbor 的 Helm 仓库添加到本地:

bash 复制代码
# 添加 Harbor Helm 仓库
helm repo add harbor https://helm.goharbor.io

# 更新仓库信息
helm repo update

创建持久化存储

Harbor 需要持久化存储来保存镜像、Chart 和数据库等数据。我们需要创建相应的持久卷(Persistent Volume)。

创建存储目录
bash 复制代码
# 创建存储目录
mkdir -p /usr/data/k8spv
chmod 777 /usr/data/k8spv
创建持久卷配置文件

创建 harbor-pv.yaml 文件并添加以下内容:

yaml 复制代码
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-pv-registry
  labels:
    app: harbor
    component: registry
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /usr/data/k8spv/registry
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1
          - k8s-node2
          - k8s-node3
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-pv-database
  labels:
    app: harbor
    component: database
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /usr/data/k8spv/database
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1
          - k8s-node2
          - k8s-node3
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-pv-chartmuseum
  labels:
    app: harbor
    component: chartmuseum
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /usr/data/k8spv/chartmuseum
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1
          - k8s-node2
          - k8s-node3
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-pv-jobservice
  labels:
    app: harbor
    component: jobservice
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /usr/data/k8spv/jobservice
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1
          - k8s-node2
          - k8s-node3
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-pv-redis
  labels:
    app: harbor
    component: redis
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /usr/data/k8spv/redis
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1
          - k8s-node2
          - k8s-node3
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: harbor-pv-trivy
  labels:
    app: harbor
    component: trivy
spec:
  capacity:
    storage: 1Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /usr/data/k8spv/trivy
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1
          - k8s-node2
          - k8s-node3

应用持久卷配置:

bash 复制代码
kubectl apply -f harbor-pv.yaml

自定义 Harbor 配置

获取默认的 Harbor 配置值:

bash 复制代码
helm show values harbor/harbor --version 1.10.0 > harbor-values.yaml

编辑 harbor-values.yaml 文件,修改以下关键配置:

yaml 复制代码
# 设置管理员密码
harborAdminPassword: "Harbor12345"

# 设置外部访问地址,替换 <NODE_IP> 为实际节点 IP
externalURL: http://<NODE_IP>:30001

# 禁用 TLS
tls:
  enabled: false

# 修改存储类配置,为每个组件添加选择器
registry:
  storageClass: "local-storage"
  selector:
    matchLabels:
      component: registry

jobservice:
  jobLog:
    storageClass: "local-storage"
    selector:
      matchLabels:
        component: jobservice

database:
  storageClass: "local-storage"
  selector:
    matchLabels:
      component: database

redis:
  storageClass: "local-storage"
  selector:
    matchLabels:
      component: redis

trivy:
  storageClass: "local-storage"
  size: 1Gi
  selector:
    matchLabels:
      component: trivy

安装 Harbor

使用 Helm 安装 Harbor:

bash 复制代码
# 创建命名空间
kubectl create namespace harbor

# 安装 Harbor
helm install my-harbor harbor/harbor --version 1.10.0 -n harbor -f harbor-values.yaml

等待所有 Pod 启动完成:

bash 复制代码
# 查看 Pod 状态
kubectl get pods -n harbor

# 查看服务状态
kubectl get svc -n harbor

安装完成后,您可以通过 http://<NODE_IP>:30001 访问 Harbor Web 界面,使用用户名 admin 和密码 Harbor12345 登录。


4. 配置 Docker 使用 Harbor 仓库

配置 Docker Daemon

为了让 Docker 能够与 Harbor 通信,我们需要配置 Docker Daemon 信任 Harbor 的私有仓库:

bash 复制代码
# 编辑 Docker Daemon 配置
vim /etc/docker/daemon.json

添加以下内容(如果文件已存在,请将新内容合并到现有配置中):

json 复制代码
{
  "insecure-registries": ["<NODE_IP>:30001"]
}

请将 <NODE_IP> 替换为实际运行 Harbor 的节点 IP 地址。

重启 Docker 服务使配置生效:

bash 复制代码
# 重新加载 Daemon 配置
systemctl daemon-reload

# 重启 Docker
systemctl restart docker

登录 Harbor 仓库

使用 Docker 登录 Harbor:

bash 复制代码
# 登录 Harbor
docker login <NODE_IP>:30001

# 输入用户名和密码
Username: admin
Password: Harbor12345

推送和拉取镜像

现在您可以推送镜像到 Harbor:

bash 复制代码
# 标记镜像
docker tag nginx:latest <NODE_IP>:30001/library/nginx:latest

# 推送镜像
docker push <NODE_IP>:30001/library/nginx:latest

# 拉取镜像
docker pull <NODE_IP>:30001/library/nginx:latest

5. 配置 Helm 使用 Harbor Chart 仓库

添加 Harbor 作为 Helm Chart 仓库

Harbor 不仅可以作为 Docker 镜像仓库,还可以作为 Helm Chart 仓库使用。

bash 复制代码
# 添加 Harbor 作为 Helm 仓库
helm repo add harbor http://<NODE_IP>:30001/chartrepo/library

# 更新仓库信息
helm repo update

推送 Chart 到 Harbor

首先,安装 Helm push 插件:

bash 复制代码
# 安装 Helm push 插件
helm plugin install https://github.com/chartmuseum/helm-push

推送 Chart 到 Harbor:

bash 复制代码
# 创建一个示例 Chart
helm create my-chart

# 打包 Chart
helm package my-chart

# 推送 Chart 到 Harbor
helm push my-chart-0.1.0.tgz harbor --username=admin --password=Harbor12345

从 Harbor 安装 Chart

现在您可以从 Harbor 安装 Chart:

bash 复制代码
# 搜索 Chart
helm search repo harbor

# 安装 Chart
helm install my-release harbor/my-chart --version 0.1.0

6. Harbor 高级配置

配置认证和授权

Harbor 支持多种认证方式,包括本地数据库、LDAP 和 OIDC。您可以在 Harbor Web 界面的"系统管理" -> "认证模式"中配置。

配置镜像复制

Harbor 支持在不同 Harbor 实例之间复制镜像,可以在"系统管理" -> "复制管理"中配置复制规则。

配置漏洞扫描

Harbor 集成了 Trivy 和 Clair 等漏洞扫描工具,可以在"项目" -> 选择项目 -> "扫描器"中配置。


7. 故障排除

常见问题

  1. Pod 无法启动

    • 检查持久卷是否正确创建和绑定
    • 查看 Pod 日志:kubectl logs <pod-name> -n harbor
  2. 无法访问 Harbor

    • 检查服务是否正常暴露:kubectl get svc -n harbor
    • 检查防火墙规则是否允许相应端口
  3. Docker 无法推送镜像

    • 检查 Docker Daemon 配置是否正确
    • 确认已登录到 Harbor:docker login <NODE_IP>:30001
  4. Helm 无法推送 Chart

    • 确认已安装 Helm push 插件
    • 检查 Harbor 的 Chart 仓库功能是否启用

查看日志

如果遇到问题,可以查看相关组件的日志:

bash 复制代码
# 查看 Harbor 核心组件日志
kubectl logs -l app=harbor,component=core -n harbor

# 查看注册表日志
kubectl logs -l app=harbor,component=registry -n harbor

# 查看数据库日志
kubectl logs -l app=harbor,component=database -n harbor

总结

通过本文,我们学习了:

  1. Helm 的安装与介绍:了解了 Helm 的基本概念和安装方法
  2. kubectl 的安装与配置:配置了 Kubernetes 命令行工具
  3. Harbor 的 Helm 部署:使用 Helm 在 Kubernetes 集群中部署 Harbor
  4. 持久化存储配置:为 Harbor 各个组件配置了持久化存储
  5. Docker 仓库配置:配置 Docker 使用 Harbor 作为私有镜像仓库
  6. Helm Chart 仓库配置:配置 Helm 使用 Harbor 作为 Chart 仓库
  7. 镜像和 Chart 管理:学习了如何推送和拉取镜像与 Chart

Harbor 作为一个企业级的容器镜像仓库,提供了丰富的功能和完善的权限管理。结合 Helm 的部署和管理,我们可以在 Kubernetes 环境中轻松搭建一套完整的镜像和 Chart 管理平台。

下一步建议:

  1. 配置 HTTPS 访问以提高安全性
  2. 设置定期备份和恢复策略
  3. 集成 CI/CD 流水线,实现自动化的镜像构建和部署
  4. 配置监控和告警,确保 Harbor 的高可用性

相关资源:

希望本文对您部署和使用 Harbor 有所帮助!如有任何问题,欢迎在评论区留言讨论。