Sonatype Nexus Repository

A repository is a server where artifacts that are used in the build process or produced as the output of the build process are stored. There are various paid and opensource repository solutions. Github and Gitlab often offer a repository as well. JFrog is a great software repository with decent OSS version. Sonatype offers a lot of repository options for maven, npm, apt, docker, helm and a lot of others which are not generally offered by JFrog on their OSS version. Also a docker image of Sonatype Nexus Repository is available making it a prefect candidate to run repository on kubernetes. We are going to run Sonatype Nexus on kubernetes cluster.

Prepare a persistent storage

Longhorn is used as the persistent storage provider for this setup. Create a PVC (Persistent volume claim) claiming some space to be used by the sonatype nexus repository to store artifacts. We have allocated 10GB as the persistent storage for the registry.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
 name: registry-pvc
spec:
 storageClassName: longhorn
 accessModes:
   - ReadWriteOnce
 resources:
   requests:
     storage: 10Gi

Prepare nexus deployment with an InitContainer

The specific purpose of an initContainer is to set the permission and user group on the data volume used by Sonatype Nexus repository.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nexus
  namespace: registry
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nexus-server
  template:
    metadata:
      labels:
        app: nexus-server
    spec:
      initContainers:
        - name: chown-nexusdata-owner-to-nexus
          image: busybox
          command: ['chown','-R','200:200','nexus-data']
          volumeMounts:
          - name: nexus-data
            mountPath: /nexus-data
      containers:
        - name: nexus
          image: sonatype/nexus3:latest
          resources:
            limits:
              memory: "4Gi"
              cpu: "1000m"
            requests:
              memory: "2Gi"
              cpu: "500m"
          ports:
            - containerPort: 8081
              name: admin-port
            - containerPort: 8082
              name: docker-port
          volumeMounts:
            - name: nexus-data
              mountPath: /nexus-data
      volumes:
        - name: nexus-data
          persistentVolumeClaim:
            claimName: registry-pvc

The busybox InitContainer changes the ownership of the data volume mounted on /nexus-data to nexus user. The InitContainer just sets the stage for the rest of the deployment to start. We have used different ports for accessing admin interface and docker registry on the Sonatype nexus repository.

Prepare service definition and ingress definitions

The service definition exposes ports 8081 as the administrative port and 8082 as the docker registry port for the repository.

apiVersion: v1
kind: Service
metadata:
  name: nexus
spec:
  ports:
  - name: admin-port 
    port: 8081
    protocol: TCP
    targetPort: 8081
  - name: docker-port
    port: 8082
    protocol: TCP
    targetPort: 8082
  selector:
    app: nexus-server
  type: ClusterIP 
status:
  loadBalancer: {}

The Ingress definitions allow us to use hostnames instead of the ports to access the services from outside the cluster.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: sonatype-ingress
  namespace: registry
  annotations:
    cert-manager.io/cluster-issuer: ca-issuer
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
    nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
    # type of authentication
    # nginx.ingress.kubernetes.io/auth-type: basic
    # name of the secret that contains the user/password definitions
    # nginx.ingress.kubernetes.io/auth-secret: basic-auth
    # message to display with an appropriate context why the authentication is required
    # nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required '
spec:
  ingressClassName: nginx
  rules:
  - host: registry.k8s.cluster 
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nexus
            port: 
              number: 8081
  tls:
  - hosts:
    - registry.k8s.cluster
    secretName: registry-tls
  - host: hub.k8s.cluster 
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nexus
            port:
              number: 8082
  tls:
  - hosts:
    - hub.k8s.cluster
    secretName: hub-tls

The annotations used rely on cert-manager based setup to generate TLS certifcates on the fly. More on cert-manager coming on the next blog article.

The UI of Sonatype nexus repository can be viewed as