# Install Harbor

Harbor logo

# Install Harbor using Helm

Lab architecture:

Lab architecture

Label Harbor namespace and copy there the secret with certificates signed by Let's Encrypt certificate:

kubectl get namespace harbor-system &> /dev/null || kubectl create namespace harbor-system
kubectl label namespace --overwrite harbor-system app=kubed


namespace/harbor-system labeled

Check if the certificate generated by cert-manager in cert-manager namespace was successfully copied to harbor-system namespace:

kubectl get secrets ingress-cert-${LETSENCRYPT_ENVIRONMENT} -n harbor-system -o json | jq ".metadata | .annotations, .labels"



  "certmanager.k8s.io/alt-names": "*.mylabs.dev",
  "certmanager.k8s.io/common-name": "*.mylabs.dev",
  "certmanager.k8s.io/ip-sans": "",
  "certmanager.k8s.io/issuer-kind": "ClusterIssuer",
  "certmanager.k8s.io/issuer-name": "letsencrypt-production-dns",
  "kubed.appscode.com/origin": "{\"namespace\":\"cert-manager\",\"name\":\"ingress-cert-production\",\"uid\":\"51b889ad-aa0a-11e9-8d10-06a66d4e34ba\",\"resourceVersion\":\"2916\"}"
  "certmanager.k8s.io/certificate-name": "ingress-cert-production",
  "kubed.appscode.com/origin.cluster": "my_k8s_cluster",
  "kubed.appscode.com/origin.name": "ingress-cert-production",
  "kubed.appscode.com/origin.namespace": "cert-manager"

Add Harbor Helm repository:

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


"harbor" has been added to your repositories

Install Harbor using Helm:

helm ls | grep harbor || \
helm install --wait --name harbor --namespace harbor-system harbor/harbor --version v1.2.1 \
  --set expose.ingress.hosts.core=harbor.${MY_DOMAIN} \
  --set expose.ingress.hosts.notary=notary.${MY_DOMAIN} \
  --set expose.tls.secretName=ingress-cert-${LETSENCRYPT_ENVIRONMENT} \
  --set persistence.enabled=false \
  --set externalURL=https://harbor.${MY_DOMAIN} \
  --set harborAdminPassword=admin


NAME:   harbor
LAST DEPLOYED: Fri Jul 19 11:49:59 2019
NAMESPACE: harbor-system

==> v1/ConfigMap
NAME                         DATA  AGE
harbor-harbor-chartmuseum    23    65s
harbor-harbor-clair          1     65s
harbor-harbor-core           34    65s
harbor-harbor-jobservice     1     65s
harbor-harbor-notary-server  5     65s
harbor-harbor-registry       2     65s

==> v1/Deployment
NAME                         READY  UP-TO-DATE  AVAILABLE  AGE
harbor-harbor-chartmuseum    1/1    1           1          65s
harbor-harbor-clair          1/1    1           1          65s
harbor-harbor-core           1/1    1           1          65s
harbor-harbor-jobservice     1/1    1           1          65s
harbor-harbor-notary-server  1/1    1           1          65s
harbor-harbor-notary-signer  1/1    1           1          65s
harbor-harbor-portal         1/1    1           1          65s
harbor-harbor-registry       1/1    1           1          65s

==> v1/Pod(related)
NAME                                          READY  STATUS   RESTARTS  AGE
harbor-harbor-chartmuseum-8647f45994-8nvd7    1/1    Running  0         65s
harbor-harbor-clair-55c56ccf4-kjc67           1/1    Running  2         65s
harbor-harbor-core-8554f8c5cd-n5dks           1/1    Running  0         65s
harbor-harbor-database-0                      1/1    Running  0         64s
harbor-harbor-jobservice-5989b8c6c4-nwxns     1/1    Running  0         65s
harbor-harbor-notary-server-694d84d7-vwgdm    1/1    Running  0         65s
harbor-harbor-notary-signer-749cbf5948-b7b6g  1/1    Running  0         65s
harbor-harbor-portal-64899d584-gtr4x          1/1    Running  0         64s
harbor-harbor-redis-0                         1/1    Running  0         64s
harbor-harbor-registry-69bb76d7-8pcf9         2/2    Running  0         64s

==> v1/Secret
NAME                       TYPE    DATA  AGE
harbor-harbor-chartmuseum  Opaque  1     65s
harbor-harbor-core         Opaque  7     65s
harbor-harbor-database     Opaque  1     65s
harbor-harbor-jobservice   Opaque  1     65s
harbor-harbor-registry     Opaque  2     65s

==> v1/Service
NAME                         TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)            AGE
harbor-harbor-chartmuseum    ClusterIP   <none>       80/TCP             65s
harbor-harbor-clair          ClusterIP   <none>       6060/TCP,6061/TCP  65s
harbor-harbor-core           ClusterIP    <none>       80/TCP             65s
harbor-harbor-database       ClusterIP  <none>       5432/TCP           65s
harbor-harbor-jobservice     ClusterIP  <none>       80/TCP             65s
harbor-harbor-notary-server  ClusterIP    <none>       4443/TCP           65s
harbor-harbor-notary-signer  ClusterIP  <none>       7899/TCP           65s
harbor-harbor-portal         ClusterIP  <none>       80/TCP             65s
harbor-harbor-redis          ClusterIP   <none>       6379/TCP           65s
harbor-harbor-registry       ClusterIP   <none>       5000/TCP,8080/TCP  65s

==> v1/StatefulSet
NAME                    READY  AGE
harbor-harbor-database  1/1    65s
harbor-harbor-redis     1/1    64s

==> v1beta1/Ingress
NAME                   HOSTS                                ADDRESS      PORTS    AGE
harbor-harbor-ingress  harbor.mylabs.dev,notary.mylabs.dev  80, 443  64s

Please wait for several minutes for Harbor deployment to complete.
Then you should be able to visit the Harbor portal at https://harbor.mylabs.dev.
For more details, please visit https://github.com/goharbor/harbor.

Harbor architecture:

Harbor Architecture

Check how the Harbor Ingress looks like:

kubectl describe ingresses -n harbor-system harbor-harbor-ingress





Name:             harbor-harbor-ingress
Namespace:        harbor-system
Default backend:  default-http-backend:80 (<none>)
  ingress-cert-production terminates harbor.mylabs.dev
  ingress-cert-production terminates notary.mylabs.dev
  Host               Path  Backends
  ----               ----  --------
                     /             harbor-harbor-portal:80 (
                     /api/         harbor-harbor-core:80 (
                     /service/     harbor-harbor-core:80 (
                     /v2/          harbor-harbor-core:80 (
                     /chartrepo/   harbor-harbor-core:80 (
                     /c/           harbor-harbor-core:80 (
                     /   harbor-harbor-notary-server:4443 (
  ingress.kubernetes.io/ssl-redirect:           true
  nginx.ingress.kubernetes.io/proxy-body-size:  0
  nginx.ingress.kubernetes.io/ssl-redirect:     true
  ingress.kubernetes.io/proxy-body-size:        0
  Type    Reason  Age   From                      Message
  ----    ------  ----  ----                      -------
  Normal  CREATE  29m   nginx-ingress-controller  Ingress harbor-system/harbor-harbor-ingress
  Normal  UPDATE  29m   nginx-ingress-controller  Ingress harbor-system/harbor-harbor-ingress

Open the https://harbor.mylabs.dev:

Harbor login page

Log in:

  • User: admin
  • Password: admin

You should see the Web UI: