Skip to content

Kubernetes Deployment

This guide covers deploying Nexus on Kubernetes clusters using various deployment strategies and configurations.

Overview

Nexus can be deployed on Kubernetes using Helm charts, raw manifests, or operators. This documentation provides comprehensive guidance for production-ready deployments.

Prerequisites

  • Kubernetes cluster (v1.20+)
  • kubectl configured to access your cluster
  • Helm 3.x (for Helm deployments)
  • Persistent storage provisioner
  • Load balancer or ingress controller

Quick Start with Helm

Add Nexus Helm Repository

helm repo add nexus https://charts.nexus.io
helm repo update

Install Nexus

helm install nexus nexus/nexus \
  --namespace nexus-system \
  --create-namespace \
  --set image.tag=latest \
  --set persistence.enabled=true \
  --set persistence.size=10Gi

Configuration

Values File

Create a values.yaml file for customization:

# Nexus configuration
image:
  repository: nexus/nexus
  tag: "v1.0.0"
  pullPolicy: IfNotPresent

# Service configuration
service:
  type: ClusterIP
  port: 8080
  targetPort: 8080

# Ingress configuration
ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: nexus.example.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: nexus-tls
      hosts:
        - nexus.example.com

# Database configuration
database:
  type: postgresql
  host: postgres.database.svc.cluster.local
  port: 5432
  name: nexus
  username: nexus
  passwordSecret: nexus-db-secret

# Redis configuration
redis:
  enabled: true
  host: redis.cache.svc.cluster.local
  port: 6379
  passwordSecret: redis-secret

# Persistence
persistence:
  enabled: true
  storageClass: fast-ssd
  size: 20Gi
  accessMode: ReadWriteOnce

# Resource limits
resources:
  limits:
    cpu: 2000m
    memory: 4Gi
  requests:
    cpu: 500m
    memory: 1Gi

# Autoscaling
autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70
  targetMemoryUtilizationPercentage: 80

# Security context
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  fsGroup: 2000

Install with Custom Values

helm install nexus nexus/nexus \
  --namespace nexus-system \
  --create-namespace \
  --values values.yaml

Manual Deployment

Namespace

apiVersion: v1
kind: Namespace
metadata:
  name: nexus-system
  labels:
    app.kubernetes.io/name: nexus

ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: nexus-config
  namespace: nexus-system
data:
  config.yaml: |
    server:
      host: 0.0.0.0
      port: 8080
    database:
      host: ${DB_HOST}
      port: ${DB_PORT}
      name: ${DB_NAME}
      username: ${DB_USERNAME}
      password: ${DB_PASSWORD}
    redis:
      host: ${REDIS_HOST}
      port: ${REDIS_PORT}
      password: ${REDIS_PASSWORD}
    logging:
      level: info
      format: json

Secret

apiVersion: v1
kind: Secret
metadata:
  name: nexus-secrets
  namespace: nexus-system
type: Opaque
stringData:
  db-password: "your-database-password"
  redis-password: "your-redis-password"
  jwt-secret: "your-jwt-secret"

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nexus
  namespace: nexus-system
  labels:
    app.kubernetes.io/name: nexus
    app.kubernetes.io/version: "1.0.0"
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: nexus
  template:
    metadata:
      labels:
        app.kubernetes.io/name: nexus
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        fsGroup: 2000
      containers:
      - name: nexus
        image: nexus/nexus:v1.0.0
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 8080
          protocol: TCP
        env:
        - name: DB_HOST
          value: "postgres.database.svc.cluster.local"
        - name: DB_PORT
          value: "5432"
        - name: DB_NAME
          value: "nexus"
        - name: DB_USERNAME
          value: "nexus"
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: nexus-secrets
              key: db-password
        - name: REDIS_HOST
          value: "redis.cache.svc.cluster.local"
        - name: REDIS_PORT
          value: "6379"
        - name: REDIS_PASSWORD
          valueFrom:
            secretKeyRef:
              name: nexus-secrets
              key: redis-password
        livenessProbe:
          httpGet:
            path: /health
            port: http
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: http
          initialDelaySeconds: 5
          periodSeconds: 5
        resources:
          limits:
            cpu: 2000m
            memory: 4Gi
          requests:
            cpu: 500m
            memory: 1Gi
        volumeMounts:
        - name: config
          mountPath: /app/config
        - name: data
          mountPath: /app/data
      volumes:
      - name: config
        configMap:
          name: nexus-config
      - name: data
        persistentVolumeClaim:
          claimName: nexus-data

Service

apiVersion: v1
kind: Service
metadata:
  name: nexus
  namespace: nexus-system
  labels:
    app.kubernetes.io/name: nexus
spec:
  type: ClusterIP
  ports:
  - port: 80
    targetPort: http
    protocol: TCP
    name: http
  selector:
    app.kubernetes.io/name: nexus

Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nexus
  namespace: nexus-system
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - nexus.example.com
    secretName: nexus-tls
  rules:
  - host: nexus.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nexus
            port:
              number: 80

Persistent Volume Claim

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nexus-data
  namespace: nexus-system
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 20Gi

High Availability Setup

Multi-Zone Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nexus
spec:
  replicas: 6
  template:
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app.kubernetes.io/name
                  operator: In
                  values:
                  - nexus
              topologyKey: kubernetes.io/hostname
          - weight: 50
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app.kubernetes.io/name
                  operator: In
                  values:
                  - nexus
              topologyKey: topology.kubernetes.io/zone

HorizontalPodAutoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nexus-hpa
  namespace: nexus-system
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nexus
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Monitoring and Observability

ServiceMonitor for Prometheus

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: nexus
  namespace: nexus-system
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: nexus
  endpoints:
  - port: http
    path: /metrics
    interval: 30s

Grafana Dashboard

Deploy monitoring dashboards:

kubectl apply -f https://raw.githubusercontent.com/nexus/nexus/main/deploy/k8s/monitoring/grafana-dashboard.yaml

Security

Network Policies

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: nexus-network-policy
  namespace: nexus-system
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: nexus
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - namespaceSelector:
        matchLabels:
          name: database
    ports:
    - protocol: TCP
      port: 5432
  - to:
    - namespaceSelector:
        matchLabels:
          name: cache
    ports:
    - protocol: TCP
      port: 6379

Pod Security Standards

apiVersion: v1
kind: Namespace
metadata:
  name: nexus-system
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Backup and Disaster Recovery

Database Backup Job

apiVersion: batch/v1
kind: CronJob
metadata:
  name: nexus-db-backup
  namespace: nexus-system
spec:
  schedule: "0 2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: postgres-backup
            image: postgres:15
            command:
            - /bin/bash
            - -c
            - |
              pg_dump -h $DB_HOST -U $DB_USERNAME -d $DB_NAME | \
              gzip > /backup/nexus-$(date +%Y%m%d-%H%M%S).sql.gz
            env:
            - name: DB_HOST
              value: postgres.database.svc.cluster.local
            - name: DB_USERNAME
              value: nexus
            - name: PGPASSWORD
              valueFrom:
                secretKeyRef:
                  name: nexus-secrets
                  key: db-password
            volumeMounts:
            - name: backup-storage
              mountPath: /backup
          volumes:
          - name: backup-storage
            persistentVolumeClaim:
              claimName: backup-pvc
          restartPolicy: OnFailure

Troubleshooting

Common Issues

Pod Startup Issues

# Check pod status
kubectl get pods -n nexus-system

# View pod logs
kubectl logs -n nexus-system deployment/nexus

# Describe pod for events
kubectl describe pod -n nexus-system <pod-name>

Database Connection Issues

# Test database connectivity
kubectl run -it --rm debug --image=postgres:15 --restart=Never -- \
  psql -h postgres.database.svc.cluster.local -U nexus -d nexus

Performance Issues

# Check resource usage
kubectl top pods -n nexus-system

# Check HPA status
kubectl get hpa -n nexus-system

Upgrading

Rolling Update

# Update image tag
helm upgrade nexus nexus/nexus \
  --namespace nexus-system \
  --set image.tag=v1.1.0 \
  --reuse-values

Blue-Green Deployment

# Deploy new version
helm install nexus-green nexus/nexus \
  --namespace nexus-system \
  --set image.tag=v1.1.0 \
  --set service.name=nexus-green

# Switch traffic
kubectl patch ingress nexus -n nexus-system \
  --type='json' \
  -p='[{"op": "replace", "path": "/spec/rules/0/http/paths/0/backend/service/name", "value": "nexus-green"}]'

See Also