Skip to main content
Version: 3.3

Harbor with Portworx on Kubernetes

This reference architecture document shows how you can deploy Harbor, an open-source container image registry, and its dependencies with Portworx on Kubernetes. Under this architecture, Portworx provides reliable and persistent storage to ensure Harbor runs with HA.

Create StorageClass​

All of the components will use a StorageClass with 3 replicas, so create and apply the following spec:

kubectl apply -f - <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: portworx-sc-repl3
provisioner: pxd.portworx.com
parameters:
repl: "3"
priority_io: "high"
EOF

For details about the Portworx-specific parameters, refer to the Portworx Volume section.

note

If you're using Portworx with CSI, you must set the value of the provisioner parameter to pxd.portworx.com.

Setup Harbor​

Prequisites​

  • By default, the instructions in this document deploy everything in the harbor namespace, but you can change this by specifying your own namespace:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: Namespace
    metadata:
    name: harbor
    EOF
  • Harbor is deployed using Helm, so it will need to be installed and have permissions on the harbor namespace. You can find instructions here.

Deploy dependencies​

Harbor requires a PostgreSQL and Redis database.

  1. Apply the following spec to deploy PostgreSQL, making sure to change the password and username to your preferred values:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: postgres-pvc
    namespace: harbor
    annotations:
    volume.beta.kubernetes.io/storage-class: portworx-sc-repl3
    spec:
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
    storage: 2Gi
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: postgres
    namespace: harbor
    labels:
    app: postgres
    spec:
    ports:
    - port: 5432
    selector:
    app: postgres
    clusterIP: None
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: postgres
    namespace: harbor
    labels:
    app: postgres
    spec:
    strategy:
    type: Recreate
    replicas: 1
    selector:
    matchLabels:
    app: postgres
    template:
    metadata:
    labels:
    app: postgres
    spec:
    schedulerName: stork
    containers:
    - name: postgres
    image: postgres:13.2
    readinessProbe:
    exec:
    command: ["psql", "-w", "-U", "postgres", "-c", "SELECT 1"]
    initialDelaySeconds: 15
    timeoutSeconds: 2
    livenessProbe:
    exec:
    command: ["psql", "-w", "-U", "postgres", "-c", "SELECT 1"]
    initialDelaySeconds: 45
    timeoutSeconds: 2
    ports:
    - containerPort: 5432
    name: postgres
    env:
    - name: POSTGRES_USER
    value: postgres
    - name: POSTGRES_PASSWORD
    value: password
    - name: PGDATA
    value: /var/lib/postgresql/data/pgdata
    volumeMounts:
    - name: postgres-persistent-storage
    mountPath: /var/lib/postgresql/data
    volumes:
    - name: postgres-persistent-storage
    persistentVolumeClaim:
    claimName: postgres-pvc
    EOF
  2. Apply the following spec to deploy Redis:

    kubectl apply -f - <<EOF
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
    name: redis-pvc
    namespace: harbor
    annotations:
    volume.beta.kubernetes.io/storage-class: portworx-sc-repl3
    spec:
    accessModes:
    - ReadWriteOnce
    resources:
    requests:
    storage: 2Gi
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: redis
    namespace: harbor
    spec:
    ports:
    - port: 6379
    name: redis
    clusterIP: None
    selector:
    app: redis
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: redis
    namespace: harbor
    labels:
    app: redis
    spec:
    selector:
    matchLabels:
    app: redis
    template:
    metadata:
    labels:
    app: redis
    spec:
    schedulerName: stork
    containers:
    - name: redis
    image: redis:3.2-alpine
    imagePullPolicy: Always
    args: ["--requirepass", "password"]
    ports:
    - containerPort: 6379
    name: redis
    volumeMounts:
    - name: redis-vol
    mountPath: /data
    volumes:
    - name: redis-vol
    persistentVolumeClaim:
    claimName: redis-pvc
    EOF
  3. Enter the following command to create the four PostgreSQL databases Harbor requires:

    DB_POD=$(kubectl get pods -n harbor -l app=postgres | awk '/postgres/{print$1}')
    kubectl exec $DB_POD -n harbor -- createdb -Upostgres registry
    kubectl exec $DB_POD -n harbor -- createdb -Upostgres clair
    kubectl exec $DB_POD -n harbor -- createdb -Upostgres notary_server
    kubectl exec $DB_POD -n harbor -- createdb -Upostgres notary_signer

Deploy Harbor​

Enter the following commands to add the Harbor repository and deploy Harbor. Replace myharbor with a name of your choosing:

NAMESPACE=harbor
helm repo add harbor https://helm.goharbor.io
helm install myharbor harbor/harbor \
--set redis.type=external \
--set redis.external.addr=redis.$NAMESPACE:6379 \
--set redis.external.password=password \
--set database.type=external \
--set database.external.host=postgres.$NAMESPACE \
--set database.external.username=postgres \
--set database.external.password=password \
--set persistence.persistentVolumeClaim.registry.storageClass=portworx-sc-repl3 \
--set persistence.persistentVolumeClaim.chartmuseum.storageClass=portworx-sc-repl3 \
--set persistence.persistentVolumeClaim.jobservice.storageClass=portworx-sc-repl3 \
--set persistence.persistentVolumeClaim.trivy.storageClass=portworx-sc-repl3 \
--namespace $NAMESPACE

If you want to expose the portal as NodePort, you may add the flags:

--set expose.type=nodePort \
--set expose.tls.enabled=false \
--set externalURL=http://<hostname.domain>:30002 \

Clean up Harbor​

To clean up the environment created above, run the following:

helm uninstall myharbor -n harbor
kubectl delete -n harbor \
deploy/redis \
svc/redis \
pvc/redis-pvc \
deploy/postgres \
svc/postgres \
pvc/postgres-pvc \
pvc/myharbor-harbor-chartmuseum \
pvc/myharbor-harbor-jobservice \
pvc/data-myharbor-harbor-trivy-0 \
pvc/myharbor-harbor-registry
kubectl delete sc/portworx-sc-repl3

Configuring snapshots​

Scheduled snapshots can be configured. PostgreSQL does not require any special Pre or Post rules to be added; Redis is only used for cache and temporary storage, so it does not need a Pre rule to ensure it is flushed to disk. See the Create and use snapshots page for more details about snapshots.

In this topic: