--- # Source: harbor/templates/core/core-cm.yaml apiVersion: v1 kind: ConfigMap metadata: name: harbor-core labels: app: harbor data: app.conf: |+ appname = Harbor runmode = prod enablegzip = true [prod] httpport = 8080 PORT: "8080" DATABASE_TYPE: "postgresql" POSTGRESQL_HOST: harbor-database POSTGRESQL_PORT: "5432" POSTGRESQL_USERNAME: "postgres" POSTGRESQL_DATABASE: "registry" POSTGRESQL_SSLMODE: "disable" POSTGRESQL_MAX_IDLE_CONNS: "100" POSTGRESQL_MAX_OPEN_CONNS: "900" EXT_ENDPOINT: "https://harbor.k-space.ee" CORE_URL: "http://harbor-core:80" JOBSERVICE_URL: "http://harbor-jobservice" REGISTRY_URL: "http://harbor-registry:5000" TOKEN_SERVICE_URL: "http://harbor-core:80/service/token" WITH_NOTARY: "false" NOTARY_URL: "http://harbor-notary-server:4443" CORE_LOCAL_URL: "http://127.0.0.1:8080" WITH_TRIVY: "true" TRIVY_ADAPTER_URL: "http://harbor-trivy:8080" REGISTRY_STORAGE_PROVIDER_NAME: "filesystem" WITH_CHARTMUSEUM: "false" LOG_LEVEL: "warning" CONFIG_PATH: "/etc/core/app.conf" CHART_CACHE_DRIVER: "redis" _REDIS_URL_CORE: "redis://harbor-redis:6379/0?idle_timeout_seconds=30" _REDIS_URL_REG: "redis://harbor-redis:6379/2?idle_timeout_seconds=30" PORTAL_URL: "http://harbor-portal" REGISTRY_CONTROLLER_URL: "http://harbor-registry:8080" REGISTRY_CREDENTIAL_USERNAME: "harbor_registry_user" HTTP_PROXY: "" HTTPS_PROXY: "" NO_PROXY: "harbor-core,harbor-jobservice,harbor-database,harbor-registry,harbor-portal,harbor-trivy,harbor-exporter,127.0.0.1,localhost,.local,.internal" PERMITTED_REGISTRY_TYPES_FOR_PROXY_CACHE: "docker-hub,harbor,azure-acr,aws-ecr,google-gcr,quay,docker-registry" METRIC_ENABLE: "true" METRIC_PATH: "/metrics" METRIC_PORT: "8001" METRIC_NAMESPACE: harbor METRIC_SUBSYSTEM: core --- # Source: harbor/templates/jobservice/jobservice-cm-env.yaml apiVersion: v1 kind: ConfigMap metadata: name: "harbor-jobservice-env" labels: app: harbor data: CORE_URL: "http://harbor-core:80" TOKEN_SERVICE_URL: "http://harbor-core:80/service/token" REGISTRY_URL: "http://harbor-registry:5000" REGISTRY_CONTROLLER_URL: "http://harbor-registry:8080" REGISTRY_CREDENTIAL_USERNAME: "harbor_registry_user" HTTP_PROXY: "" HTTPS_PROXY: "" NO_PROXY: "harbor-core,harbor-jobservice,harbor-database,harbor-registry,harbor-portal,harbor-trivy,harbor-exporter,127.0.0.1,localhost,.local,.internal" --- # Source: harbor/templates/jobservice/jobservice-cm.yaml apiVersion: v1 kind: ConfigMap metadata: name: "harbor-jobservice" labels: app: harbor data: config.yml: |+ #Server listening port protocol: "http" port: 8080 worker_pool: workers: 10 backend: "redis" redis_pool: redis_url: "redis://harbor-redis:6379/1" namespace: "harbor_job_service_namespace" idle_timeout_second: 3600 job_loggers: - name: "FILE" level: INFO settings: # Customized settings of logger base_dir: "/var/log/jobs" sweeper: duration: 14 #days settings: # Customized settings of sweeper work_dir: "/var/log/jobs" metric: enabled: false path: /metrics port: 8001 #Loggers for the job service loggers: - name: "STD_OUTPUT" level: INFO --- # Source: harbor/templates/portal/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: "harbor-portal" labels: app: harbor data: nginx.conf: |+ worker_processes auto; pid /tmp/nginx.pid; events { worker_connections 1024; } http { client_body_temp_path /tmp/client_body_temp; proxy_temp_path /tmp/proxy_temp; fastcgi_temp_path /tmp/fastcgi_temp; uwsgi_temp_path /tmp/uwsgi_temp; scgi_temp_path /tmp/scgi_temp; server { listen 8080; listen [::]:8080; server_name localhost; root /usr/share/nginx/html; index index.html index.htm; include /etc/nginx/mime.types; gzip on; gzip_min_length 1000; gzip_proxied expired no-cache no-store private auth; gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript; location / { try_files $uri $uri/ /index.html; } location = /index.html { add_header Cache-Control "no-store, no-cache, must-revalidate"; } } } --- # Source: harbor/templates/registry/registry-cm.yaml apiVersion: v1 kind: ConfigMap metadata: name: "harbor-registry" labels: app: harbor data: config.yml: |+ version: 0.1 log: level: info fields: service: registry storage: filesystem: rootdirectory: /storage cache: layerinfo: redis maintenance: uploadpurging: enabled: false delete: enabled: true redirect: disable: false redis: addr: harbor-redis:6379 db: 2 readtimeout: 10s writetimeout: 10s dialtimeout: 10s pool: maxidle: 100 maxactive: 500 idletimeout: 60s http: addr: :5000 relativeurls: false # set via environment variable # secret: placeholder debug: addr: localhost:5001 auth: htpasswd: realm: harbor-registry-basic-realm path: /etc/registry/passwd validation: disabled: true compatibility: schema1: enabled: true ctl-config.yml: |+ --- protocol: "http" port: 8080 log_level: info registry_config: "/etc/registry/config.yml" --- # Source: harbor/templates/registry/registryctl-cm.yaml apiVersion: v1 kind: ConfigMap metadata: name: "harbor-registryctl" labels: app: harbor data: --- # Source: harbor/templates/jobservice/jobservice-pvc.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: harbor-jobservice labels: app: harbor component: jobservice spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: longhorn --- # Source: harbor/templates/registry/registry-pvc.yaml kind: PersistentVolumeClaim apiVersion: v1 metadata: name: harbor-registry labels: app: harbor component: registry spec: accessModes: - ReadWriteOnce resources: requests: storage: 30Gi storageClassName: longhorn --- # Source: harbor/templates/core/core-svc.yaml apiVersion: v1 kind: Service metadata: name: harbor-core labels: app: harbor spec: ports: - name: http-web port: 80 targetPort: 8080 - name: http-metrics port: 8001 selector: app: harbor component: core --- # Source: harbor/templates/database/database-svc.yaml apiVersion: v1 kind: Service metadata: name: harbor-database spec: ports: - port: 5432 selector: app: harbor component: database --- # Source: harbor/templates/jobservice/jobservice-svc.yaml apiVersion: v1 kind: Service metadata: name: "harbor-jobservice" labels: app: harbor spec: ports: - name: http-jobservice port: 80 targetPort: 8080 selector: app: harbor component: jobservice --- # Source: harbor/templates/portal/service.yaml apiVersion: v1 kind: Service metadata: name: "harbor-portal" labels: app: harbor spec: ports: - port: 80 targetPort: 8080 selector: app: harbor component: portal --- # Source: harbor/templates/redis/service.yaml apiVersion: v1 kind: Service metadata: name: harbor-redis labels: app: harbor spec: ports: - port: 6379 selector: app: harbor component: redis --- # Source: harbor/templates/redis/service.yaml apiVersion: v1 kind: Service metadata: name: k6-harbor-redis labels: app: harbor spec: ports: - port: 6379 selector: app: harbor component: redis --- # Source: harbor/templates/registry/registry-svc.yaml apiVersion: v1 kind: Service metadata: name: "harbor-registry" labels: app: harbor spec: ports: - name: http-registry port: 5000 - name: http-controller port: 8080 selector: app: harbor component: registry --- # Source: harbor/templates/trivy/trivy-svc.yaml apiVersion: v1 kind: Service metadata: name: harbor-trivy spec: ports: - name: http-trivy protocol: TCP port: 8080 selector: app: harbor component: trivy --- # Source: harbor/templates/core/core-dpl.yaml apiVersion: apps/v1 kind: Deployment metadata: name: harbor-core labels: app: harbor component: core spec: replicas: 3 selector: matchLabels: app: harbor component: core template: metadata: labels: release: k6 app: harbor component: core spec: securityContext: runAsUser: 10000 fsGroup: 10000 automountServiceAccountToken: false terminationGracePeriodSeconds: 120 containers: - name: core image: goharbor/harbor-core:v2.4.2 startupProbe: httpGet: path: /api/v2.0/ping scheme: HTTP port: 8080 failureThreshold: 360 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /api/v2.0/projects scheme: HTTP port: 8080 failureThreshold: 2 periodSeconds: 10 envFrom: - configMapRef: name: "harbor-core" - secretRef: name: "harbor-core" env: - name: CORE_SECRET valueFrom: secretKeyRef: name: harbor-core key: secret - name: JOBSERVICE_SECRET valueFrom: secretKeyRef: name: "harbor-jobservice" key: JOBSERVICE_SECRET ports: - containerPort: 8080 volumeMounts: - name: config mountPath: /etc/core/app.conf subPath: app.conf - name: secret-key mountPath: /etc/core/key subPath: key - name: token-service-private-key mountPath: /etc/core/private_key.pem subPath: tls.key - name: ca-download mountPath: /etc/core/ca - name: psc mountPath: /etc/core/token volumes: - name: config configMap: name: harbor-core items: - key: app.conf path: app.conf - name: secret-key secret: secretName: harbor-core items: - key: secretKey path: key - name: token-service-private-key secret: secretName: harbor-core - name: ca-download secret: - name: psc emptyDir: {} nodeSelector: dedicated: storage tolerations: - key: dedicated operator: Equal value: storage effect: NoSchedule --- # Source: harbor/templates/jobservice/jobservice-dpl.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: "harbor-jobservice" labels: app: harbor component: jobservice spec: replicas: 1 serviceName: jobservice selector: matchLabels: app: harbor component: jobservice template: metadata: labels: app: harbor component: jobservice spec: securityContext: runAsUser: 10000 fsGroup: 10000 automountServiceAccountToken: false terminationGracePeriodSeconds: 120 containers: - name: jobservice image: goharbor/harbor-jobservice:v2.4.2 readinessProbe: httpGet: path: /api/v1/stats scheme: HTTP port: 8080 initialDelaySeconds: 20 periodSeconds: 10 env: - name: CORE_SECRET valueFrom: secretKeyRef: name: harbor-core key: secret envFrom: - configMapRef: name: "harbor-jobservice-env" - secretRef: name: "harbor-jobservice" ports: - containerPort: 8080 volumeMounts: - name: jobservice-config mountPath: /etc/jobservice/config.yml subPath: config.yml - name: job-logs mountPath: /var/log/jobs subPath: volumes: - name: jobservice-config configMap: name: "harbor-jobservice" - name: job-logs persistentVolumeClaim: claimName: harbor-jobservice nodeSelector: dedicated: storage tolerations: - key: dedicated operator: Equal value: storage effect: NoSchedule --- # Source: harbor/templates/portal/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: "harbor-portal" labels: app: harbor component: portal spec: replicas: 1 selector: matchLabels: app: harbor component: portal template: metadata: labels: release: k6 app: harbor component: portal annotations: spec: securityContext: runAsUser: 10000 fsGroup: 10000 automountServiceAccountToken: false containers: - name: portal image: goharbor/harbor-portal:v2.4.2 readinessProbe: httpGet: path: / scheme: HTTP port: 8080 initialDelaySeconds: 1 periodSeconds: 10 ports: - containerPort: 8080 volumeMounts: - name: portal-config mountPath: /etc/nginx/nginx.conf subPath: nginx.conf volumes: - name: portal-config configMap: name: "harbor-portal" nodeSelector: dedicated: storage tolerations: - key: dedicated operator: Equal value: storage effect: NoSchedule --- # Source: harbor/templates/registry/registry-dpl.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: "harbor-registry" labels: app: harbor component: registry spec: replicas: 1 serviceName: registry selector: matchLabels: app: harbor component: registry template: metadata: labels: app: harbor component: registry spec: securityContext: runAsUser: 10000 fsGroup: 10000 automountServiceAccountToken: false terminationGracePeriodSeconds: 120 containers: - name: registry image: goharbor/registry-photon:v2.4.2 readinessProbe: httpGet: path: / scheme: HTTP port: 5000 initialDelaySeconds: 1 periodSeconds: 10 args: ["serve", "/etc/registry/config.yml"] envFrom: - secretRef: name: "harbor-registry" env: ports: - containerPort: 5000 - containerPort: 5001 volumeMounts: - name: registry-data mountPath: /storage subPath: - name: registry-htpasswd mountPath: /etc/registry/passwd subPath: passwd - name: registry-config mountPath: /etc/registry/config.yml subPath: config.yml - name: registryctl image: goharbor/harbor-registryctl:v2.4.2 readinessProbe: httpGet: path: /api/health scheme: HTTP port: 8080 initialDelaySeconds: 1 periodSeconds: 10 envFrom: - configMapRef: name: "harbor-registryctl" - secretRef: name: "harbor-registry" - secretRef: name: "harbor-registryctl" env: - name: CORE_SECRET valueFrom: secretKeyRef: name: harbor-core key: secret - name: JOBSERVICE_SECRET valueFrom: secretKeyRef: name: harbor-jobservice key: JOBSERVICE_SECRET ports: - containerPort: 8080 volumeMounts: - name: registry-data mountPath: /storage subPath: - name: registry-config mountPath: /etc/registry/config.yml subPath: config.yml - name: registry-config mountPath: /etc/registryctl/config.yml subPath: ctl-config.yml volumes: - name: registry-htpasswd secret: secretName: harbor-registry-htpasswd items: - key: REGISTRY_HTPASSWD path: passwd - name: registry-config configMap: name: "harbor-registry" - name: registry-data persistentVolumeClaim: claimName: harbor-registry nodeSelector: dedicated: storage tolerations: - key: dedicated operator: Equal value: storage effect: NoSchedule --- # Source: harbor/templates/database/database-ss.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: harbor-database labels: app: harbor component: database spec: replicas: 1 serviceName: harbor-database selector: matchLabels: app: harbor component: database template: metadata: labels: app: harbor component: database spec: securityContext: runAsUser: 999 fsGroup: 999 automountServiceAccountToken: false terminationGracePeriodSeconds: 120 initContainers: # as we change the data directory to a sub folder to support psp, the init container here # is used to migrate the existing data. See https://github.com/goharbor/harbor-helm/issues/756 # for more detail. # we may remove it after several releases - name: "data-migrator" image: goharbor/harbor-db:v2.4.2 command: ["/bin/sh"] args: ["-c", "[ -e /var/lib/postgresql/data/postgresql.conf ] && [ ! -d /var/lib/postgresql/data/pgdata ] && mkdir -m 0700 /var/lib/postgresql/data/pgdata && mv /var/lib/postgresql/data/* /var/lib/postgresql/data/pgdata/ || true"] volumeMounts: - name: database-data mountPath: /var/lib/postgresql/data subPath: # with "fsGroup" set, each time a volume is mounted, Kubernetes must recursively chown() and chmod() all the files and directories inside the volume # this causes the postgresql reports the "data directory /var/lib/postgresql/data/pgdata has group or world access" issue when using some CSIs e.g. Ceph # use this init container to correct the permission # as "fsGroup" applied before the init container running, the container has enough permission to execute the command - name: "data-permissions-ensurer" image: goharbor/harbor-db:v2.4.2 command: ["/bin/sh"] args: ["-c", "chmod -R 700 /var/lib/postgresql/data/pgdata || true"] volumeMounts: - name: database-data mountPath: /var/lib/postgresql/data subPath: containers: - name: database image: goharbor/harbor-db:v2.4.2 readinessProbe: exec: command: - /docker-healthcheck.sh initialDelaySeconds: 1 periodSeconds: 10 envFrom: - secretRef: name: harbor-database env: # put the data into a sub directory to avoid the permission issue in k8s with restricted psp enabled # more detail refer to https://github.com/goharbor/harbor-helm/issues/756 - name: PGDATA value: "/var/lib/postgresql/data/pgdata" volumeMounts: - name: database-data mountPath: /var/lib/postgresql/data subPath: - name: shm-volume mountPath: /dev/shm volumes: - name: shm-volume emptyDir: medium: Memory sizeLimit: 512Mi nodeSelector: dedicated: storage tolerations: - key: dedicated operator: Equal value: storage effect: NoSchedule volumeClaimTemplates: - metadata: name: "database-data" labels: app: harbor spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: "1Gi" --- # Source: harbor/templates/redis/statefulset.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: harbor-redis labels: app: harbor component: redis spec: replicas: 1 serviceName: harbor-redis selector: matchLabels: app: harbor component: redis template: metadata: labels: app: harbor component: redis spec: securityContext: runAsUser: 999 fsGroup: 999 automountServiceAccountToken: false terminationGracePeriodSeconds: 120 containers: - name: redis image: goharbor/redis-photon:v2.4.2 readinessProbe: tcpSocket: port: 6379 initialDelaySeconds: 1 periodSeconds: 10 volumeMounts: - name: data mountPath: /var/lib/redis subPath: nodeSelector: dedicated: storage tolerations: - key: dedicated operator: Equal value: storage effect: NoSchedule volumeClaimTemplates: - metadata: name: data labels: app: harbor spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: "1Gi" --- # Source: harbor/templates/trivy/trivy-sts.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: harbor-trivy labels: app: harbor component: trivy spec: replicas: 1 serviceName: harbor-trivy selector: matchLabels: app: harbor component: trivy template: metadata: labels: app: harbor component: trivy spec: securityContext: runAsUser: 10000 fsGroup: 10000 automountServiceAccountToken: false containers: - name: trivy image: goharbor/trivy-adapter-photon:v2.4.2 imagePullPolicy: IfNotPresent securityContext: privileged: false allowPrivilegeEscalation: false env: - name: HTTP_PROXY value: "" - name: HTTPS_PROXY value: "" - name: NO_PROXY value: "harbor-core,harbor-jobservice,harbor-database,harbor-registry,harbor-portal,harbor-trivy,harbor-exporter,127.0.0.1,localhost,.local,.internal" - name: "SCANNER_LOG_LEVEL" value: "info" - name: "SCANNER_TRIVY_CACHE_DIR" value: "/home/scanner/.cache/trivy" - name: "SCANNER_TRIVY_REPORTS_DIR" value: "/home/scanner/.cache/reports" - name: "SCANNER_TRIVY_DEBUG_MODE" value: "false" - name: "SCANNER_TRIVY_VULN_TYPE" value: "os,library" - name: "SCANNER_TRIVY_TIMEOUT" value: "5m0s" - name: "SCANNER_TRIVY_GITHUB_TOKEN" valueFrom: secretKeyRef: name: harbor-trivy key: gitHubToken - name: "SCANNER_TRIVY_SEVERITY" value: "UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL" - name: "SCANNER_TRIVY_IGNORE_UNFIXED" value: "false" - name: "SCANNER_TRIVY_SKIP_UPDATE" value: "false" - name: "SCANNER_TRIVY_INSECURE" value: "false" - name: SCANNER_API_SERVER_ADDR value: ":8080" - name: "SCANNER_REDIS_URL" valueFrom: secretKeyRef: name: harbor-trivy key: redisURL - name: "SCANNER_STORE_REDIS_URL" valueFrom: secretKeyRef: name: harbor-trivy key: redisURL - name: "SCANNER_JOB_QUEUE_REDIS_URL" valueFrom: secretKeyRef: name: harbor-trivy key: redisURL ports: - name: api-server containerPort: 8080 volumeMounts: - name: data mountPath: /home/scanner/.cache subPath: readOnly: false readinessProbe: httpGet: scheme: HTTP path: /probe/ready port: api-server initialDelaySeconds: 5 periodSeconds: 10 successThreshold: 1 failureThreshold: 3 resources: limits: cpu: 1 memory: 1Gi requests: cpu: 200m memory: 512Mi nodeSelector: dedicated: storage tolerations: - key: dedicated operator: Equal value: storage effect: NoSchedule volumeClaimTemplates: - metadata: name: data labels: app: harbor spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: "10Gi" --- # Source: harbor/templates/ingress/ingress.yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: "harbor-ingress" labels: app: harbor annotations: external-dns.alpha.kubernetes.io/target: traefik.k-space.ee ingress.kubernetes.io/proxy-body-size: "0" ingress.kubernetes.io/ssl-redirect: "true" kubernetes.io/ingress.class: traefik nginx.ingress.kubernetes.io/proxy-body-size: "0" nginx.ingress.kubernetes.io/ssl-redirect: "true" traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" spec: tls: - hosts: - "*.k-space.ee" rules: - http: paths: - path: / pathType: Prefix backend: service: name: harbor-portal port: number: 80 - path: /api/ pathType: Prefix backend: service: name: harbor-core port: number: 80 - path: /service/ pathType: Prefix backend: service: name: harbor-core port: number: 80 - path: /v2 pathType: Prefix backend: service: name: harbor-core port: number: 80 - path: /chartrepo/ pathType: Prefix backend: service: name: harbor-core port: number: 80 - path: /c/ pathType: Prefix backend: service: name: harbor-core port: number: 80 host: harbor.k-space.ee