# Running a Harbor registry - There are many open source registries available out there - We're going to show an end-to-end example using a very popular one: [Harbor](https://goharbor.io) (https://goharbor.io) - We will: - install Harbor - create a private registry on Harbor - set up an automated build pipeline pushing images to Harbor - configure an app to use images from the private registry --- ## Requirements - Virtually all registry clients **require** TLS when communicating with registries (one exception: when the registry is on `localhost`) - This means that we'll need a valid TLS certificate for our registry - We can easily get one with cert-manager and e.g. Let's Encrypt (as long as we can associate a domain with our ingress controller) - To run the demos in this chapter, **we need a domain name!** --- ## Alternatives - We could configure our build pipeline to ignore certificates (so that it can push images without complaining) - We could hack something so that the registry is available over `localhost` - Or we could add the registry's certificate everywhere (in our build pipeline, on our container engines...) - These extra steps are out of scope for this chapter - **We need a domain name!** --- ## Automating TLS certificates - Let's install Traefik: ```bash kubectl apply -f ~/container.training/k8s/traefik.yml ``` - And cert-manager: ```bash kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.19.1/cert-manager.yaml ``` - Edit the `ClusterIssuer` manifest and apply it: ```bash vim ~/container.training/k8s/cm-clusterissuer.yaml kubectl apply -f ~/container.training/k8s/cm-clusterissuer.yaml ``` ⚠️ Make sure to update the cluster issuer name to `letsencrypt-production` ! --- ## Checking that it works - Deploy a simple application and expose it with TLS: ```bash kubectl create deployment blue --image jpetazzo/color --replicas 2 --port 80 kubectl expose deployment blue kubectl create ingress blue --rule=blue.`$DOMAIN`/*=blue:80,tls \ --annotation cert-manager.io/cluster-issuer=letsencrypt-production ``` - Check that the certificate was correctly issued: ```bash kubectl get cert curl https://blue.`$DOMAIN`/ ``` --- ## Deploying Harbor - There is a Helm chart (https://artifacthub.io/packages/helm/harbor/harbor) - Let's install it: ```bash helm upgrade --install --repo https://helm.goharbor.io \ --namespace harbor --create-namespace harbor harbor \ --set persistence.enabled=false \ --set expose.ingress.hosts.core=harbor.`$DOMAIN` \ --set expose.ingress.annotations."cert-manager\.io/cluster-issuer"=letsencrypt-production \ --version 1.18.0 ``` - Wait until all pods are `Running` in the `harbor` namespace --- ## Logging into Harbor - Go to https://harbor.$DOMAIN/ - The default login is `admin` - The default password is `Harbor12345` (yes, it would be a good idea to change that in production😁) --- ## Creating a new repository - In Harbor, repositories are associated to "projects" - Create a new project named `dockercoins` --- ## Creating Harbor users - We will create two "robot accounts": - one with `push` permission (for the build pipeline) - one with `pull` permission (for our Kubernetes workloads) - Create a first robot account, `dockercoins-push` - don't give any systems permission - for project permissions, check `dockercoins` - then select permissions, check `push` and `pull` - Write down the user and password! --- ## Setting up the build pipeline - This part requires a GitHub account - On GitHub, fork https://github.com/jpetazzo/dockercoins (it has a GitHub Actions workflow that is almost ready to use!) - In your fork, go to settings / secrets and variables / actions - Create the following secrets: `REGISTRY_ADDRESS` = `harbor.$DOMAIN` (make sure to enter the real domain of course!) `REGISTRY_USERNAME` = the user name generated by Harbor `REGISTRY_PASSWORD` = the password generated by Harbor --- ## Setting up the build pipeline - Edit `.github/workflows/automated-build.yaml` - Comment out the steps related to GitHub Container Registry and Docker Hub - Uncomment the steps related to the custom external registry - Commit - In your fork, click on the "Actions" button on top - You should see the workflow running - After a couple of minutes, it should (hopefully) report success --- ## Creating the `pull` robot account - In Harbor, create another robot account - Let's name it `dockercoins-pull` - Again, don't give it any systems permission - Give it `pull` permissions for the `dockercions` project - Write down the user and password --- ## Create a Secret for the `pull` account - Let's create a Kubernetes Secret holding the registry credentials: ```bash kubectl create secret docker-registry dockercoins-pull \ --docker-username '`robot$dockercoins-pull``' \ --docker-password `abcdefghijKLMNOPQRST` \ --docker-server harbor.`$DOMAIN` ``` - Make sure to quote the username (the `$` will cause problems otherwise) --- ## Use the Secret - We have two possibilities here: - add `imagePullSecrets` to every Pod template that needs them - add `imagePullSecrets` to the ServiceAccount used by the Pods - Let's patch the default ServiceAccount: ```bash kubectl patch serviceaccount default \ --patch 'imagePullSecrets: [ name: dockercoins-pull ]' ``` --- ## Use the private registry - Make a copy of `~/container.training/k8s/dockercoins.yml` - In that copy, replace every `dockercoins/*` image with `harbor.$DOMAIN/dockercoins/*` (put the actual domain, not `$DOMAIN`!) - Apply that YAML - Check that the application is up and running - Check that the number of pulls has increased in the Harbor web UI - Congratulations, you've deployed an image from a self-hosted private registry! 🎉 ??? :EN:- Hosting private images with Harbor :FR:- Héberger des images privées avec Harbor