Skip to content

Harbor Installation

This content is not available in your language yet.

Harbor is an open-source trusted cloud-native registry that stores, signs, and scans content. In Opstella, Harbor is used as the central artifact registry.

The following steps describe how to install Harbor on the 🟢 Management cluster, utilizing PostgreSQL (via CloudnativePG) for metadata and SeaweedFS HA for artifact storage.

Ensure you have defined and loaded your Global Shell Variables as described in Shell Variables.

  1. Connect to 🟢 Management Kubernetes Cluster ; _i.e w/ Kubeconfig File.

    Ensure you have defined and loaded your Global Shell Variables as described in Shell Variables.

    Terminal window
    source $HOME/opstella-installation/shell-values/kubernetes/management_cluster.vars.sh
    source $HOME/opstella-installation/shell-values/tools/harbor.vars.sh
    Terminal window
    export KUBECONFIG="$HOME/opstella-installation/kubeconfigs/management_cluster.yaml"
  2. Export Required Shell Variables

    Ensure HARBOR_DOMAIN and HARBOR_ADMIN_PASSWORD are defined as per the Shell Variables guide.

    Ensure K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME, K8S_INGRESSCLASS_NAME, K8S_STORAGECLASS_NAME are defined as per the Shell Variables guide. Additionally, export the following backend-related variables:

    Terminal window
    # PostgreSQL Backend Passwords
    export HARBOR_POSTGRES_SUPERUSER_PASSWORD="CHANGEME"
    export HARBOR_POSTGRES_USER_PASSWORD="CHANGEME"
    export SEAWEEDFS_HA_S3_POSTGRES_BACKUP_PASSWORD="CHANGEME"
    # S3 Storage Password
    export SEAWEEDFS_HA_S3_HARBOR_PASSWORD="CHANGEME"
  3. Create Namespace for Harbor

    Terminal window
    kubectl create namespace registry-system
  4. Install PostgreSQL Backend (CloudnativePG)

    Apply the PostgreSQL cluster manifest. This instance will store Harbor’s registry and core metadata.

    Terminal window
    cat <<EOF > $HOME/opstella-installation/kubernetes-manifests/harbor-postgres.yaml
    ---
    # Postgres Superuser (root) Credentials
    apiVersion: v1
    kind: Secret
    type: kubernetes.io/basic-auth
    metadata:
    name: harbor-postgres-superuser
    namespace: registry-system
    stringData:
    username: postgres
    password: "${HARBOR_POSTGRES_SUPERUSER_PASSWORD}"
    ---
    # Harbor Application User Credentials
    apiVersion: v1
    kind: Secret
    type: kubernetes.io/basic-auth
    metadata:
    name: harbor-postgres-user
    namespace: registry-system
    stringData:
    username: harbor
    password: "${HARBOR_POSTGRES_USER_PASSWORD}"
    ---
    # S3 Credentials for Postgres Backups (to SeaweedFS HA)
    apiVersion: v1
    kind: Secret
    type: Opaque
    metadata:
    name: harbor-postgres-s3-secret
    namespace: registry-system
    stringData:
    S3_ACCESS_KEY: postgres-backup
    S3_SECRET_KEY: "${SEAWEEDFS_HA_S3_POSTGRES_BACKUP_PASSWORD}"
    ---
    apiVersion: barmancloud.cnpg.io/v1
    kind: ObjectStore
    metadata:
    name: harbor-postgres-backup
    namespace: registry-system
    spec:
    # This resource defines the backup destination for the Barman Cloud Plugin
    configuration:
    destinationPath: s3://postgres-backups/
    endpointURL: http://seaweedfs-s3.seaweedfs-bootstrap.svc:9000
    s3Credentials:
    accessKeyId:
    name: harbor-postgres-s3-secret
    key: S3_ACCESS_KEY
    secretAccessKey:
    name: harbor-postgres-s3-secret
    key: S3_SECRET_KEY
    wal:
    compression: gzip
    data:
    compression: gzip
    # Retention policy for backups and WALs handled by the plugin
    retentionPolicy: "30d"
    ---
    apiVersion: postgresql.cnpg.io/v1
    kind: Cluster
    metadata:
    name: harbor-postgres
    namespace: registry-system
    labels:
    app.kubernetes.io/name: harbor-postgres
    app.kubernetes.io/part-of: harbor
    spec:
    instances: 1
    # Image configuration (Postgres 15)
    imageName: ghcr.io/cloudnative-pg/postgresql:15
    # Enable the Barman Cloud Plugin for backups
    plugins:
    - name: barman-cloud.cloudnative-pg.io
    isWALArchiver: true
    parameters:
    serverName: "harbor-postgres"
    barmanObjectName: "harbor-postgres-backup"
    # Storage Configuration
    storage:
    size: 5Gi
    storageClass: "${K8S_STORAGECLASS_NAME}"
    walStorage:
    size: 2Gi
    storageClass: "${K8S_STORAGECLASS_NAME}"
    # Bootstrap Configuration
    bootstrap:
    initdb:
    database: harbor
    owner: harbor
    # Secret containing password for the Harbor application user
    secret:
    name: harbor-postgres-user
    # Harbor specific schema initializations could go here if needed
    # postInitApplicationSQL: []
    # Superuser credentials (root/postgres)
    superuserSecret:
    name: harbor-postgres-superuser
    # Backup Configuration (Barman Cloud Plugin will automatically detect matching ObjectStore)
    backup:
    {}
    # Monitoring (disabled for now)
    monitoring:
    enablePodMonitor: false
    # Resources
    resources:
    requests:
    memory: "256Mi"
    cpu: "200m"
    limits:
    memory: "1Gi"
    cpu: "1000m"
    EOF
    Terminal window
    kubectl apply -f harbor-postgres.yaml
  5. Create Harbor Application Credentials

    Apply the secret containing the Harbor admin password and PostgreSQL connection credentials.

    Terminal window
    cat <<EOF > $HOME/opstella-installation/kubernetes-manifests/harbor.yaml
    ---
    apiVersion: v1
    kind: Secret
    type: Opaque
    metadata:
    name: harbor-credentials
    namespace: registry-system
    stringData:
    HARBOR_ADMIN_PASSWORD: "${HARBOR_ADMIN_PASSWORD}"
    EOF
    Terminal window
    kubectl apply -f harbor.yaml
  6. Add Harbor Helm Repository

    Terminal window
    helm repo add harbor https://helm.goharbor.io
    helm repo update
  7. Create Harbor Helm Values

    Terminal window
    cat <<EOF > $HOME/opstella-installation/helm-values/harbor-values.yaml
    ---
    # Application: Harbor Configuration
    externalURL: "https://${HARBOR_DOMAIN}"
    # Kubernetes/Application: Harbor Authentication
    existingSecretAdminPassword: harbor-credentials
    # Kubernetes: Expose through Ingress
    expose:
    type: ingress
    tls:
    enabled: true
    certSource: secret
    secret:
    secretName: "${K8S_INGRESS_TLS_CERTIFICATE_SECRET_NAME}"
    ingress:
    hosts:
    core: "${HARBOR_DOMAIN}"
    className: ${K8S_INGRESSCLASS_NAME}
    # Kubernetes/Application: Enable Persistence
    persistence:
    enabled: true
    persistentVolumeClaim:
    jobservice:
    jobLog:
    storageClass: "${K8S_STORAGECLASS_NAME}"
    trivy:
    storageClass: "${K8S_STORAGECLASS_NAME}"
    redis:
    storageClass: "${K8S_STORAGECLASS_NAME}"
    # Kubernetes/Application: Persistence S3 Storage
    imageChartStorage:
    type: s3
    s3:
    regionendpoint: "${SEAWEEDFS_HA_API_DOMAIN}"
    bucket: harbor
    region: us-east-1
    accesskey: harbor
    secretkey: "${SEAWEEDFS_HA_S3_HARBOR_PASSWORD}"
    v4auth: true
    # Application: Database Configuration
    database:
    type: external
    external:
    host: harbor-postgres-rw.registry-system.svc
    port: 5432
    coreDatabase: harbor
    username: harbor
    existingSecret: harbor-postgres-user
    # Application: Relative URLs
    registry:
    relativeurls: true
    EOF
  8. Install Harbor Helm Release

    Terminal window
    helm upgrade --install harbor harbor/harbor \
    --namespace registry-system \
    --version 1.15.2 \
    -f $HOME/opstella-installation/helm-values/harbor-values.yaml
  1. Verify Pod Status

    Terminal window
    kubectl get pods -n registry-system

    💡 All Harbor components and the PostgreSQL cluster should be Running:

    NAME READY STATUS RESTARTS AGE
    harbor-core-XXXXXXXXXX-YYYYY 1/1 Running 0 ...
    harbor-jobservice-XXXXXXXXXX-YYYYY 1/1 Running 0 ...
    harbor-portal-XXXXXXXXXX-YYYYY 1/1 Running 0 ...
    harbor-registry-XXXXXXXXXX-YYYYY 2/2 Running 0 ...
    harbor-trivy-0 1/1 Running 0 ...
    harbor-postgres-1 1/1 Running 0 ...
  2. Verify Harbor UI Access

    • Access the Harbor UI at https://${HARBOR_DOMAIN}.
    • Login with the admin account and the password defined in ${HARBOR_ADMIN_PASSWORD}.
    • Confirm that the system is healthy and responsive.

Finished?

Use the below navigation to proceed