feat: initialize Harbor Helm chart with full component templates and configuration values

This commit is contained in:
2026-04-13 18:19:27 +07:00
parent 4d17b17d1c
commit 12ef1b9cb5
55 changed files with 6420 additions and 0 deletions

View File

@@ -0,0 +1,92 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "harbor.core" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
data:
app.conf: |+
appname = Harbor
runmode = prod
enablegzip = true
[prod]
httpport = {{ ternary "8443" "8080" .Values.internalTLS.enabled }}
PORT: "{{ ternary "8443" "8080" .Values.internalTLS.enabled }}"
DATABASE_TYPE: "postgresql"
POSTGRESQL_HOST: "{{ template "harbor.database.host" . }}"
POSTGRESQL_PORT: "{{ template "harbor.database.port" . }}"
POSTGRESQL_USERNAME: "{{ template "harbor.database.username" . }}"
POSTGRESQL_DATABASE: "{{ template "harbor.database.coreDatabase" . }}"
POSTGRESQL_SSLMODE: "{{ template "harbor.database.sslmode" . }}"
POSTGRESQL_MAX_IDLE_CONNS: "{{ .Values.database.maxIdleConns }}"
POSTGRESQL_MAX_OPEN_CONNS: "{{ .Values.database.maxOpenConns }}"
EXT_ENDPOINT: "{{ .Values.externalURL }}"
CORE_URL: "{{ template "harbor.coreURL" . }}"
JOBSERVICE_URL: "{{ template "harbor.jobserviceURL" . }}"
REGISTRY_URL: "{{ template "harbor.registryURL" . }}"
TOKEN_SERVICE_URL: "{{ template "harbor.tokenServiceURL" . }}"
CORE_LOCAL_URL: "{{ ternary "https://127.0.0.1:8443" "http://127.0.0.1:8080" .Values.internalTLS.enabled }}"
WITH_TRIVY: {{ .Values.trivy.enabled | quote }}
TRIVY_ADAPTER_URL: "{{ template "harbor.trivyAdapterURL" . }}"
REGISTRY_STORAGE_PROVIDER_NAME: "{{ .Values.persistence.imageChartStorage.type }}"
LOG_LEVEL: "{{ .Values.logLevel }}"
CONFIG_PATH: "/etc/core/app.conf"
CHART_CACHE_DRIVER: "redis"
_REDIS_URL_CORE: "{{ template "harbor.redis.urlForCore" . }}"
_REDIS_URL_REG: "{{ template "harbor.redis.urlForRegistry" . }}"
{{- if or (and (eq .Values.redis.type "internal") .Values.redis.internal.harborDatabaseIndex) (and (eq .Values.redis.type "external") .Values.redis.external.harborDatabaseIndex) }}
_REDIS_URL_HARBOR: "{{ template "harbor.redis.urlForHarbor" . }}"
{{- end }}
{{- if or (and (eq .Values.redis.type "internal") .Values.redis.internal.cacheLayerDatabaseIndex) (and (eq .Values.redis.type "external") .Values.redis.external.cacheLayerDatabaseIndex) }}
_REDIS_URL_CACHE_LAYER: "{{ template "harbor.redis.urlForCache" . }}"
{{- end }}
PORTAL_URL: "{{ template "harbor.portalURL" . }}"
REGISTRY_CONTROLLER_URL: "{{ template "harbor.registryControllerURL" . }}"
REGISTRY_CREDENTIAL_USERNAME: "{{ .Values.registry.credentials.username }}"
{{- if .Values.uaaSecretName }}
UAA_CA_ROOT: "/etc/core/auth-ca/auth-ca.crt"
{{- end }}
{{- if has "core" .Values.proxy.components }}
HTTP_PROXY: "{{ .Values.proxy.httpProxy }}"
HTTPS_PROXY: "{{ .Values.proxy.httpsProxy }}"
NO_PROXY: "{{ template "harbor.noProxy" . }}"
{{- end }}
PERMITTED_REGISTRY_TYPES_FOR_PROXY_CACHE: "docker-hub,harbor,azure-acr,ali-acr,aws-ecr,google-gcr,docker-registry,github-ghcr,jfrog-artifactory"
REPLICATION_ADAPTER_WHITELIST: "ali-acr,aws-ecr,azure-acr,docker-hub,docker-registry,github-ghcr,google-gcr,harbor,huawei-SWR,jfrog-artifactory,tencent-tcr,volcengine-cr"
{{- if .Values.metrics.enabled}}
METRIC_ENABLE: "true"
METRIC_PATH: "{{ .Values.metrics.core.path }}"
METRIC_PORT: "{{ .Values.metrics.core.port }}"
METRIC_NAMESPACE: harbor
METRIC_SUBSYSTEM: core
{{- end }}
{{- if hasKey .Values.core "gcTimeWindowHours" }}
#make the GC time window configurable for testing
GC_TIME_WINDOW_HOURS: "{{ .Values.core.gcTimeWindowHours }}"
{{- end }}
{{- template "harbor.traceEnvsForCore" . }}
{{- if .Values.core.artifactPullAsyncFlushDuration }}
ARTIFACT_PULL_ASYNC_FLUSH_DURATION: {{ .Values.core.artifactPullAsyncFlushDuration | quote }}
{{- end }}
{{- if .Values.core.gdpr}}
{{- if .Values.core.gdpr.deleteUser}}
GDPR_DELETE_USER: "true"
{{- end }}
{{- if .Values.core.gdpr.auditLogsCompliant}}
GDPR_AUDIT_LOGS: "true"
{{- end }}
{{- end }}
{{- if .Values.cache.enabled }}
CACHE_ENABLED: "true"
CACHE_EXPIRE_HOURS: "{{ .Values.cache.expireHours }}"
{{- end }}
{{- if .Values.core.quotaUpdateProvider }}
QUOTA_UPDATE_PROVIDER: "{{ .Values.core.quotaUpdateProvider }}"
{{- end }}

View File

@@ -0,0 +1,258 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "harbor.core" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: core
app.kubernetes.io/component: core
spec:
replicas: {{ .Values.core.replicas }}
revisionHistoryLimit: {{ .Values.core.revisionHistoryLimit }}
selector:
matchLabels:
{{ include "harbor.matchLabels" . | indent 6 }}
component: core
template:
metadata:
labels:
{{ include "harbor.labels" . | indent 8 }}
component: core
app.kubernetes.io/component: core
{{- if .Values.core.podLabels }}
{{ toYaml .Values.core.podLabels | indent 8 }}
{{- end }}
annotations:
checksum/configmap: {{ include (print $.Template.BasePath "/core/core-cm.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/core/core-secret.yaml") . | sha256sum }}
checksum/secret-jobservice: {{ include (print $.Template.BasePath "/jobservice/jobservice-secrets.yaml") . | sha256sum }}
{{- if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "auto") }}
checksum/tls: {{ include (print $.Template.BasePath "/internal/auto-tls.yaml") . | sha256sum }}
{{- else if and .Values.internalTLS.enabled (eq .Values.internalTLS.certSource "manual") }}
checksum/tls: {{ include (print $.Template.BasePath "/core/core-tls.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.core.podAnnotations }}
{{ toYaml .Values.core.podAnnotations | indent 8 }}
{{- end }}
spec:
securityContext:
runAsUser: 10000
fsGroup: 10000
{{- if .Values.core.serviceAccountName }}
serviceAccountName: {{ .Values.core.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
automountServiceAccountToken: {{ .Values.core.automountServiceAccountToken | default false }}
terminationGracePeriodSeconds: 120
{{- with .Values.core.topologySpreadConstraints}}
topologySpreadConstraints:
{{- range . }}
- {{ . | toYaml | indent 8 | trim }}
labelSelector:
matchLabels:
{{ include "harbor.matchLabels" $ | indent 12 }}
component: core
{{- end }}
{{- end }}
{{- with .Values.core.initContainers }}
initContainers:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: core
image: {{ .Values.core.image.repository }}:{{ .Values.core.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
{{- if .Values.core.startupProbe.enabled }}
startupProbe:
httpGet:
path: /api/v2.0/ping
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.core.containerPort" . }}
failureThreshold: 360
initialDelaySeconds: {{ .Values.core.startupProbe.initialDelaySeconds }}
periodSeconds: 10
{{- end }}
livenessProbe:
httpGet:
path: /api/v2.0/ping
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.core.containerPort" . }}
failureThreshold: 2
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/v2.0/ping
scheme: {{ include "harbor.component.scheme" . | upper }}
port: {{ template "harbor.core.containerPort" . }}
failureThreshold: 2
periodSeconds: 10
envFrom:
- configMapRef:
name: "{{ template "harbor.core" . }}"
- secretRef:
name: "{{ template "harbor.core" . }}"
env:
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: {{ default (include "harbor.core" .) .Values.core.existingSecret }}
key: secret
- name: JOBSERVICE_SECRET
valueFrom:
secretKeyRef:
name: {{ default (include "harbor.jobservice" .) .Values.jobservice.existingSecret }}
{{- if .Values.jobservice.existingSecret }}
key: {{ .Values.jobservice.existingSecretKey }}
{{- else }}
key: JOBSERVICE_SECRET
{{- end }}
{{- if .Values.existingSecretAdminPassword }}
- name: HARBOR_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.existingSecretAdminPassword }}
key: {{ .Values.existingSecretAdminPasswordKey }}
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: INTERNAL_TLS_ENABLED
value: "true"
- name: INTERNAL_TLS_KEY_PATH
value: /etc/harbor/ssl/core/tls.key
- name: INTERNAL_TLS_CERT_PATH
value: /etc/harbor/ssl/core/tls.crt
- name: INTERNAL_TLS_TRUST_CA_PATH
value: /etc/harbor/ssl/core/ca.crt
{{- end }}
{{- if .Values.database.external.existingSecret }}
- name: POSTGRESQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.database.external.existingSecret }}
key: password
{{- end }}
{{- if .Values.registry.credentials.existingSecret }}
- name: REGISTRY_CREDENTIAL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.registry.credentials.existingSecret }}
key: REGISTRY_PASSWD
{{- end }}
{{- if .Values.core.existingXsrfSecret }}
- name: CSRF_KEY
valueFrom:
secretKeyRef:
name: {{ .Values.core.existingXsrfSecret }}
key: {{ .Values.core.existingXsrfSecretKey }}
{{- end }}
{{- with .Values.core.extraEnvVars }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- if not (empty .Values.containerSecurityContext) }}
securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
{{- end }}
ports:
- containerPort: {{ template "harbor.core.containerPort" . }}
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
{{- if .Values.expose.tls.enabled }}
- name: ca-download
mountPath: /etc/core/ca
{{- end }}
{{- if .Values.uaaSecretName }}
- name: auth-ca-cert
mountPath: /etc/core/auth-ca/auth-ca.crt
subPath: auth-ca.crt
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: core-internal-certs
mountPath: /etc/harbor/ssl/core
{{- end }}
- name: psc
mountPath: /etc/core/token
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolumeMount" . | indent 8 }}
{{- end }}
{{- if .Values.core.resources }}
resources:
{{ toYaml .Values.core.resources | indent 10 }}
{{- end }}
volumes:
- name: config
configMap:
name: {{ template "harbor.core" . }}
items:
- key: app.conf
path: app.conf
- name: secret-key
secret:
{{- if .Values.existingSecretSecretKey }}
secretName: {{ .Values.existingSecretSecretKey }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
items:
- key: secretKey
path: key
- name: token-service-private-key
secret:
{{- if .Values.core.secretName }}
secretName: {{ .Values.core.secretName }}
{{- else }}
secretName: {{ template "harbor.core" . }}
{{- end }}
{{- if .Values.expose.tls.enabled }}
- name: ca-download
secret:
{{- if .Values.caSecretName }}
secretName: {{ .Values.caSecretName }}
{{- else if eq (include "harbor.autoGenCertForIngress" .) "true" }}
secretName: "{{ template "harbor.ingress" . }}"
{{- else if eq (include "harbor.autoGenCertForNginx" .) "true" }}
secretName: {{ template "harbor.tlsSecretForNginx" . }}
{{- end }}
{{- end }}
{{- if .Values.uaaSecretName }}
- name: auth-ca-cert
secret:
secretName: {{ .Values.uaaSecretName }}
items:
- key: ca.crt
path: auth-ca.crt
{{- end }}
{{- if .Values.internalTLS.enabled }}
- name: core-internal-certs
secret:
secretName: {{ template "harbor.internalTLS.core.secretName" . }}
{{- end }}
- name: psc
emptyDir: {}
{{- if .Values.caBundleSecretName }}
{{ include "harbor.caBundleVolume" . | indent 6 }}
{{- end }}
{{- with .Values.core.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- if .Values.core.priorityClassName }}
priorityClassName: {{ .Values.core.priorityClassName }}
{{- end }}

View File

@@ -0,0 +1,78 @@
{{- if .Values.enableMigrateHelmHook }}
apiVersion: batch/v1
kind: Job
metadata:
name: migration-job
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
component: migrator
annotations:
# This is what defines this resource as a hook. Without this line, the
# job is considered part of the release.
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "-5"
spec:
template:
metadata:
labels:
{{ include "harbor.matchLabels" . | indent 8 }}
component: migrator
spec:
restartPolicy: Never
securityContext:
runAsUser: 10000
fsGroup: 10000
{{- if .Values.core.serviceAccountName }}
serviceAccountName: {{ .Values.core.serviceAccountName }}
{{- end -}}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
terminationGracePeriodSeconds: 120
containers:
- name: core-job
image: {{ .Values.core.image.repository }}:{{ .Values.core.image.tag }}
imagePullPolicy: {{ .Values.imagePullPolicy }}
command: ["/harbor/harbor_core", "-mode=migrate"]
envFrom:
- configMapRef:
name: "{{ template "harbor.core" . }}"
- secretRef:
name: "{{ template "harbor.core" . }}"
{{- if .Values.database.external.existingSecret }}
env:
- name: POSTGRESQL_PASSWORD
valueFrom:
secretKeyRef:
name: {{ .Values.database.external.existingSecret }}
key: password
{{- end }}
{{- if not (empty .Values.containerSecurityContext) }}
securityContext: {{ .Values.containerSecurityContext | toYaml | nindent 10 }}
{{- end }}
volumeMounts:
- name: config
mountPath: /etc/core/app.conf
subPath: app.conf
volumes:
- name: config
configMap:
name: {{ template "harbor.core" . }}
items:
- key: app.conf
path: app.conf
{{- with .Values.core.nodeSelector }}
nodeSelector:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.affinity }}
affinity:
{{ toYaml . | indent 8 }}
{{- end }}
{{- with .Values.core.tolerations }}
tolerations:
{{ toYaml . | indent 8 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,37 @@
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace (include "harbor.core" .) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "harbor.core" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: Opaque
data:
{{- if not .Values.existingSecretSecretKey }}
secretKey: {{ .Values.secretKey | b64enc | quote }}
{{- end }}
{{- if not .Values.core.existingSecret }}
secret: {{ .Values.core.secret | default (include "harbor.secretKeyHelper" (dict "key" "secret" "data" $existingSecret.data)) | default (randAlphaNum 16) | b64enc | quote }}
{{- end }}
{{- if not .Values.core.secretName }}
{{- $ca := genCA "harbor-token-ca" 365 }}
tls.key: {{ .Values.core.tokenKey | default $ca.Key | b64enc | quote }}
tls.crt: {{ .Values.core.tokenCert | default $ca.Cert | b64enc | quote }}
{{- end }}
{{- if not .Values.existingSecretAdminPassword }}
HARBOR_ADMIN_PASSWORD: {{ .Values.harborAdminPassword | b64enc | quote }}
{{- end }}
{{- if not .Values.database.external.existingSecret }}
POSTGRESQL_PASSWORD: {{ template "harbor.database.encryptedPassword" . }}
{{- end }}
{{- if not .Values.registry.credentials.existingSecret }}
REGISTRY_CREDENTIAL_PASSWORD: {{ .Values.registry.credentials.password | b64enc | quote }}
{{- end }}
{{- if not .Values.core.existingXsrfSecret }}
CSRF_KEY: {{ .Values.core.xsrfKey | default (include "harbor.secretKeyHelper" (dict "key" "CSRF_KEY" "data" $existingSecret.data)) | default (randAlphaNum 32) | b64enc | quote }}
{{- end }}
{{- if .Values.core.configureUserSettings }}
CONFIG_OVERWRITE_JSON: {{ .Values.core.configureUserSettings | b64enc | quote }}
{{- end }}
{{- template "harbor.traceJaegerPassword" . }}

View File

@@ -0,0 +1,32 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "harbor.core" . }}
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
{{- with .Values.core.serviceAnnotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if or (eq .Values.expose.ingress.controller "gce") (eq .Values.expose.ingress.controller "alb") (eq .Values.expose.ingress.controller "f5-bigip") }}
type: NodePort
{{- end }}
{{- if .Values.ipFamily.policy }}
ipFamilyPolicy: {{ .Values.ipFamily.policy }}
{{- end }}
{{- if .Values.ipFamily.families }}
ipFamilies: {{ toYaml .Values.ipFamily.families | nindent 4 }}
{{- end }}
ports:
- name: {{ ternary "https-web" "http-web" .Values.internalTLS.enabled }}
port: {{ template "harbor.core.servicePort" . }}
targetPort: {{ template "harbor.core.containerPort" . }}
{{- if .Values.metrics.enabled}}
- name: {{ template "harbor.metricsPortName" . }}
port: {{ .Values.metrics.core.port }}
{{- end }}
selector:
{{ include "harbor.matchLabels" . | indent 4 }}
component: core

View File

@@ -0,0 +1,16 @@
{{- if and .Values.internalTLS.enabled }}
{{- if eq .Values.internalTLS.certSource "manual" }}
apiVersion: v1
kind: Secret
metadata:
name: "{{ template "harbor.internalTLS.core.secretName" . }}"
namespace: {{ .Release.Namespace | quote }}
labels:
{{ include "harbor.labels" . | indent 4 }}
type: kubernetes.io/tls
data:
ca.crt: {{ (required "The \"internalTLS.trustCa\" is required!" .Values.internalTLS.trustCa) | b64enc | quote }}
tls.crt: {{ (required "The \"internalTLS.core.crt\" is required!" .Values.internalTLS.core.crt) | b64enc | quote }}
tls.key: {{ (required "The \"internalTLS.core.key\" is required!" .Values.internalTLS.core.key) | b64enc | quote }}
{{- end }}
{{- end }}