From 5587603c8c92bd10a677a296a7cc5b78c93f0717 Mon Sep 17 00:00:00 2001 From: justin-six <57092032+justin-six@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:08:17 +0200 Subject: [PATCH 1/9] Update distribution-svc.yaml Align with Xray svc options. This is required for hybrid deployments. We are a Enterprise Plus customer. --- stable/distribution/templates/distribution-svc.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stable/distribution/templates/distribution-svc.yaml b/stable/distribution/templates/distribution-svc.yaml index 407aafb49..8b847cc3a 100644 --- a/stable/distribution/templates/distribution-svc.yaml +++ b/stable/distribution/templates/distribution-svc.yaml @@ -27,6 +27,9 @@ spec: - name: http-distro port: {{ .Values.distribution.externalPort }} targetPort: http-distro + - name: http-router + port: {{ .Values.router.externalPort }} + targetPort: http-router selector: app: {{ template "distribution.name" . }} release: {{ .Release.Name }} From 058ac629bc9c31cd8475ae27f2f6a18ae1ae7058 Mon Sep 17 00:00:00 2001 From: Rick Stokkingreef Date: Wed, 30 Oct 2024 08:57:25 +0100 Subject: [PATCH 2/9] [artifactory-ha] Add option to set Environment Variables option to filebeat sidecar (#1377) --- stable/artifactory-ha/CHANGELOG.md | 1 + .../templates/artifactory-node-statefulset.yaml | 4 ++++ .../templates/artifactory-primary-statefulset.yaml | 4 ++++ stable/artifactory-ha/values.yaml | 1 + 4 files changed, 10 insertions(+) diff --git a/stable/artifactory-ha/CHANGELOG.md b/stable/artifactory-ha/CHANGELOG.md index 1370bd3ff..6804030dc 100644 --- a/stable/artifactory-ha/CHANGELOG.md +++ b/stable/artifactory-ha/CHANGELOG.md @@ -17,6 +17,7 @@ All changes to this chart will be documented in this file. `access.extraEnvironmentVariables` * Updating the example link for downloading the DB driver * Added Binary Provider recommendations +* Add support for EnvironmentVaraiables on Filebeat Sidecar ## [107.89.0] - May 30, 2024 * Fix the indentation of the commented-out sections in the values.yaml file diff --git a/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml b/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml index 9a5d4fd84..1b0973110 100644 --- a/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml +++ b/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml @@ -1357,6 +1357,10 @@ spec: subPath: filebeat.yml - name: volume mountPath: "{{ .Values.artifactory.persistence.mountPath }}" + env: +{{- with .Values.filebeat.EnvironmentVariables }} +{{ tpl (toYaml .) $ | indent 10 }} +{{- end }} livenessProbe: {{ toYaml .Values.filebeat.livenessProbe | indent 10 }} readinessProbe: diff --git a/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml b/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml index 0e9bb6400..e629724fe 100644 --- a/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml +++ b/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml @@ -1468,6 +1468,10 @@ spec: subPath: filebeat.yml - name: volume mountPath: "{{ .Values.artifactory.persistence.mountPath }}" + env: +{{- with .Values.filebeat.EnvironmentVariables }} +{{ tpl (toYaml .) $ | indent 10 }} +{{- end }} livenessProbe: {{ toYaml .Values.filebeat.livenessProbe | indent 10 }} readinessProbe: diff --git a/stable/artifactory-ha/values.yaml b/stable/artifactory-ha/values.yaml index 3d1a325af..47f6de4e8 100644 --- a/stable/artifactory-ha/values.yaml +++ b/stable/artifactory-ha/values.yaml @@ -1783,6 +1783,7 @@ filebeat: initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 + EnvironmentVariables: {} resources: {} # requests: # memory: "100Mi" From 8d677423fa11fb7179ec16a6944f6e9e20fa22c4 Mon Sep 17 00:00:00 2001 From: Mike DuRussel Date: Wed, 30 Oct 2024 04:00:20 -0400 Subject: [PATCH 3/9] [artifactory] Add the ability to set `signedUrlExpirySeconds` to google providers (#1858) --- stable/artifactory/CHANGELOG.md | 1 + stable/artifactory/files/binarystore.xml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/stable/artifactory/CHANGELOG.md b/stable/artifactory/CHANGELOG.md index aeba9bc88..cb4d78123 100644 --- a/stable/artifactory/CHANGELOG.md +++ b/stable/artifactory/CHANGELOG.md @@ -17,6 +17,7 @@ All changes to this chart will be documented in this file. `access.extraEnvironmentVariables` * Updating the example link for downloading the DB driver * Added Binary Provider recommendations +* Added `signedUrlExpirySeconds` option to artifactory.persistence.type of `google-storage`, `google-storage-v2`, and `google-storage-v2-direct` ## [107.89.0] - June 7, 2024 * Fix the indentation of the commented-out sections in the values.yaml file diff --git a/stable/artifactory/files/binarystore.xml b/stable/artifactory/files/binarystore.xml index e396e0a41..543f8d542 100644 --- a/stable/artifactory/files/binarystore.xml +++ b/stable/artifactory/files/binarystore.xml @@ -179,6 +179,9 @@ {{ .Values.artifactory.persistence.googleStorage.bucketName }} {{ .Values.artifactory.persistence.googleStorage.path }} {{ .Values.artifactory.persistence.googleStorage.bucketExists }} + {{- if .Values.artifactory.persistence.googleStorage.signedUrlExpirySeconds }} + {{ .Values.artifactory.persistence.googleStorage.signedUrlExpirySeconds }} + {{- end }} {{- end }} From 5134ac5ae1c195398b517cd527e77f06bd3ef498 Mon Sep 17 00:00:00 2001 From: Koen Torfs Date: Wed, 30 Oct 2024 09:03:58 +0100 Subject: [PATCH 4/9] artifactory - Fix for ClusterIP type service with external ingress offloading (#1906) --- stable/artifactory/CHANGELOG.md | 7 +- stable/artifactory/values.yaml | 127 ++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 3 deletions(-) diff --git a/stable/artifactory/CHANGELOG.md b/stable/artifactory/CHANGELOG.md index cb4d78123..b9c4002e3 100644 --- a/stable/artifactory/CHANGELOG.md +++ b/stable/artifactory/CHANGELOG.md @@ -18,6 +18,7 @@ All changes to this chart will be documented in this file. * Updating the example link for downloading the DB driver * Added Binary Provider recommendations * Added `signedUrlExpirySeconds` option to artifactory.persistence.type of `google-storage`, `google-storage-v2`, and `google-storage-v2-direct` +* Support for SSL offload HTTPS proto override in Nginx service(ClusterIP) layer. Introduced `nginx.service.ssloffloadForceHttps` field with boolean type. ## [107.89.0] - June 7, 2024 * Fix the indentation of the commented-out sections in the values.yaml file @@ -40,7 +41,7 @@ All changes to this chart will be documented in this file. * Added support for `global.verisons.initContainers` to override `initContainers.image.tag` * Fixed an issue with extraSystemYaml merge * **IMPORTANT** -* Renamed `artifactory.setSecurityContext` to `artifactory.podSecurityContext` +* Renamed `artifactory.setSecurityContext` to `artifactory.podSecurityContext` * Renamed `artifactory.uid` to `artifactory.podSecurityContext.runAsUser` * Renamed `artifactory.gid` to `artifactory.podSecurityContext.runAsGroup` and `artifactory.podSecurityContext.fsGroup` * Renamed `artifactory.fsGroupChangePolicy` to `artifactory.podSecurityContext.fsGroupChangePolicy` @@ -164,7 +165,7 @@ All changes to this chart will be documented in this file. ## [107.58.0] - Mar 23, 2023 * Updated postgresql multi-arch tag version to `13.10.0-debian-11-r14` * Removed obselete remove-lost-found initContainer` -* Added env JF_SHARED_NODE_HAENABLED under frontend when running in the container split mode +* Added env JF_SHARED_NODE_HAENABLED under frontend when running in the container split mode ## [107.57.0] - Mar 02, 2023 * Updated initContainerImage and logger image to `ubi9/ubi-minimal:9.1.0.1793` @@ -382,7 +383,7 @@ All changes to this chart will be documented in this file. ## [12.0.0] - April 22, 2021 * **Breaking change:** -* Increased default postgresql persistence size to `200Gi` +* Increased default postgresql persistence size to `200Gi` * Update postgresql tag version to `13.2.0-debian-10-r55` * Update postgresql chart version to `10.3.18` in chart.yaml - [10.x Upgrade Notes](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#to-1000) * If this is a new deployment or you already use an external database (`postgresql.enabled=false`), these changes **do not affect you**! diff --git a/stable/artifactory/values.yaml b/stable/artifactory/values.yaml index 15f5de112..669769ca5 100644 --- a/stable/artifactory/values.yaml +++ b/stable/artifactory/values.yaml @@ -1464,6 +1464,131 @@ nginx: ## The nginx main conf was moved to files/nginx-main-conf.yaml. This key is commented out to keep support for the old configuration # mainConf: | + {{- if .Values.nginx.logs.stdout }} + access_log /dev/stdout timing; + {{- else -}} + access_log {{ .Values.nginx.persistence.mountPath }}/logs/access.log timing; + {{- end }} + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; + + } + artifactoryConf: | + {{- if .Values.nginx.https.enabled }} + ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; + ssl_certificate {{ .Values.nginx.persistence.mountPath }}/ssl/tls.crt; + ssl_certificate_key {{ .Values.nginx.persistence.mountPath }}/ssl/tls.key; + ssl_session_cache shared:SSL:1m; + ssl_prefer_server_ciphers on; + {{- end }} + ## server configuration + server { + {{- if .Values.nginx.internalPortHttps }} + {{- if .Values.nginx.singleStackIPv6Cluster }} + listen [::]:{{ .Values.nginx.internalPortHttps }} ssl; + {{- else -}} + listen {{ .Values.nginx.internalPortHttps }} ssl; + {{- end }} + {{- else -}} + {{- if .Values.nginx.https.enabled }} + {{- if .Values.nginx.singleStackIPv6Cluster }} + listen [::]:{{ .Values.nginx.https.internalPort }} ssl; + {{- else -}} + listen {{ .Values.nginx.https.internalPort }} ssl; + {{- end }} + {{- end }} + {{- end }} + {{- if .Values.nginx.internalPortHttp }} + {{- if .Values.nginx.singleStackIPv6Cluster }} + listen [::]:{{ .Values.nginx.internalPortHttp }}; + {{- else -}} + listen {{ .Values.nginx.internalPortHttp }}; + {{- end }} + {{- else -}} + {{- if .Values.nginx.http.enabled }} + {{- if .Values.nginx.singleStackIPv6Cluster }} + listen [::]:{{ .Values.nginx.http.internalPort }}; + {{- else -}} + listen {{ .Values.nginx.http.internalPort }}; + {{- end }} + {{- end }} + {{- end }} + server_name ~(?.+)\.{{ include "artifactory.fullname" . }} {{ include "artifactory.fullname" . }} + {{- range .Values.ingress.hosts -}} + {{- if contains "." . -}} + {{ "" | indent 0 }} ~(?.+)\.{{ . }} + {{- end -}} + {{- end -}}; + + if ($http_x_forwarded_proto = '') { + set $http_x_forwarded_proto $scheme; + } + set $host_port {{ .Values.nginx.https.externalPort }}; + if ( $scheme = "http" ) { + set $host_port {{ .Values.nginx.http.externalPort }}; + } + ## Application specific logs + ## access_log /var/log/nginx/artifactory-access.log timing; + ## error_log /var/log/nginx/artifactory-error.log; + rewrite ^/artifactory/?$ / redirect; + if ( $repo != "" ) { + rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2 break; + } + chunked_transfer_encoding on; + client_max_body_size 0; + + location / { + proxy_read_timeout 900; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + proxy_pass {{ include "artifactory.scheme" . }}://{{ include "artifactory.fullname" . }}:{{ .Values.artifactory.externalPort }}/; + {{- if .Values.nginx.service.ssloffload}} + {{- if .Values.nginx.service.ssloffloadForceHttps}} + proxy_set_header X-JFrog-Override-Base-Url https://$host; + proxy_set_header X-Forwarded-Proto https; + {{- else }} + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + {{- end }} + {{- else }} + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$host_port; + proxy_set_header X-Forwarded-Port $server_port; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + {{- end }} + proxy_set_header Host $http_host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + {{- if .Values.nginx.disableProxyBuffering}} + proxy_http_version 1.1; + proxy_request_buffering off; + proxy_buffering off; + {{- end }} + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + location /artifactory/ { + if ( $request_uri ~ ^/artifactory/(.*)$ ) { + proxy_pass http://{{ include "artifactory.fullname" . }}:{{ .Values.artifactory.externalArtifactoryPort }}/artifactory/$1; + } + proxy_pass http://{{ include "artifactory.fullname" . }}:{{ .Values.artifactory.externalArtifactoryPort }}/artifactory/; + } + location /pipelines/ { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $http_host; + {{- if .Values.router.tlsEnabled }} + proxy_pass https://{{ include "artifactory.fullname" . }}:{{ .Values.router.internalPort }}; + {{- else }} + proxy_pass http://{{ include "artifactory.fullname" . }}:{{ .Values.router.internalPort }}; + {{- end }} + } + } + } ## The nginx artifactory conf was moved to files/nginx-artifactory-conf.yaml. This key is commented out to keep support for the old configuration # artifactoryConf: | customInitContainers: "" @@ -1478,6 +1603,8 @@ nginx: ## For minikube, set this to NodePort, elsewhere use LoadBalancer type: LoadBalancer ssloffload: false + ## @param service.ssloffloadForceHttps Override http_x_forwarded_proto flag for external ingress (optional, likely OpenShift specific for ClusterIP based nginx service config) + ssloffloadForceHttps: false ## @param service.ipFamilyPolicy Controller Service ipFamilyPolicy (optional, cloud specific) ## This can be either SingleStack, PreferDualStack or RequireDualStack ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services From f43e0fe0c409dbb663e3c62742c27ac010a183f6 Mon Sep 17 00:00:00 2001 From: Swathi Ravindranath <43350767+yellowplane13@users.noreply.github.com> Date: Wed, 30 Oct 2024 03:10:09 -0500 Subject: [PATCH 5/9] [artifactory-ha] Add Annotations to Primary Artifactory Service and Resources to Nginx Deployment (#1862) --- .../artifactory-ha/templates/artifactory-primary-service.yaml | 4 ++++ stable/artifactory-ha/templates/nginx-deployment.yaml | 2 ++ stable/artifactory-ha/values.yaml | 1 + 3 files changed, 7 insertions(+) diff --git a/stable/artifactory-ha/templates/artifactory-primary-service.yaml b/stable/artifactory-ha/templates/artifactory-primary-service.yaml index 2b7ecb5af..1bd2ebb8c 100644 --- a/stable/artifactory-ha/templates/artifactory-primary-service.yaml +++ b/stable/artifactory-ha/templates/artifactory-primary-service.yaml @@ -14,6 +14,10 @@ metadata: {{- with .Values.artifactory.primary.labels }} {{ toYaml . | indent 4 }} {{- end }} +{{- with .Values.artifactory.primary.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} spec: # Statically setting service type to ClusterIP since this is an internal only service type: ClusterIP diff --git a/stable/artifactory-ha/templates/nginx-deployment.yaml b/stable/artifactory-ha/templates/nginx-deployment.yaml index d43689b8c..5584dccaa 100644 --- a/stable/artifactory-ha/templates/nginx-deployment.yaml +++ b/stable/artifactory-ha/templates/nginx-deployment.yaml @@ -81,6 +81,8 @@ spec: volumeMounts: - mountPath: {{ .Values.nginx.persistence.mountPath | quote }} name: nginx-volume + resources: +{{ toYaml .Values.initContainers.resources | indent 10 }} containers: - name: {{ .Values.nginx.name }} image: {{ include "artifactory-ha.getImageInfoByValue" (list . "nginx") }} diff --git a/stable/artifactory-ha/values.yaml b/stable/artifactory-ha/values.yaml index 47f6de4e8..4107c070b 100644 --- a/stable/artifactory-ha/values.yaml +++ b/stable/artifactory-ha/values.yaml @@ -940,6 +940,7 @@ artifactory: ## preStartCommand specific to the primary node, to be run after artifactory.preStartCommand # preStartCommand: labels: {} + annotations: {} persistence: ## Set existingClaim to true or false ## If true, you must prepare a PVC with the name e.g `volume-myrelease-artifactory-ha-primary-0` From d10faeca691ab8a3384cd2a0230ac449968294fc Mon Sep 17 00:00:00 2001 From: amithk Date: Wed, 30 Oct 2024 14:06:04 +0530 Subject: [PATCH 6/9] [artifactory] 7.98.7 release --- stable/artifactory-cpp-ce/CHANGELOG.md | 2 +- stable/artifactory-cpp-ce/Chart.yaml | 6 +- stable/artifactory-cpp-ce/values.yaml | 4 +- stable/artifactory-ha/CHANGELOG.md | 32 ++- stable/artifactory-ha/Chart.yaml | 8 +- stable/artifactory-ha/README.md | 4 +- stable/artifactory-ha/files/binarystore.xml | 5 + .../files/nginx-artifactory-conf.yaml | 12 +- stable/artifactory-ha/files/system.yaml | 13 +- .../artifactory-2xlarge-extra-config.yaml | 44 ---- .../sizing/artifactory-2xlarge.yaml | 49 ++++- .../artifactory-large-extra-config.yaml | 44 ---- .../sizing/artifactory-large.yaml | 51 ++++- .../artifactory-medium-extra-config.yaml | 45 ---- .../sizing/artifactory-medium.yaml | 49 ++++- .../artifactory-small-extra-config.yaml | 43 ---- .../sizing/artifactory-small.yaml | 48 ++++- .../artifactory-xlarge-extra-config.yaml | 42 ---- .../sizing/artifactory-xlarge.yaml | 50 ++++- .../artifactory-xsmall-extra-config.yaml | 43 ---- .../sizing/artifactory-xsmall.yaml | 50 ++++- stable/artifactory-ha/templates/_helpers.tpl | 26 +++ .../templates/artifactory-license-secret.yaml | 2 +- .../artifactory-node-statefulset.yaml | 18 +- .../artifactory-primary-statefulset.yaml | 67 ++++-- .../templates/artifactory-service-grpc.yaml | 49 +++++ .../templates/artifactory-service.yaml | 2 + .../templates/ingress-grpc.yaml | 80 +++++++ .../templates/nginx-deployment.yaml | 2 - .../templates/nginx-service.yaml | 2 +- stable/artifactory-ha/values.yaml | 77 ++++++- stable/artifactory-jcr/CHANGELOG.md | 2 +- stable/artifactory-jcr/Chart.yaml | 6 +- stable/artifactory-jcr/values.yaml | 4 +- stable/artifactory-oss/CHANGELOG.md | 2 +- stable/artifactory-oss/Chart.yaml | 6 +- stable/artifactory-oss/values.yaml | 4 +- stable/artifactory/CHANGELOG.md | 33 ++- stable/artifactory/Chart.yaml | 4 +- stable/artifactory/README.md | 3 +- stable/artifactory/files/binarystore.xml | 4 +- .../files/nginx-artifactory-conf.yaml | 12 +- stable/artifactory/files/system.yaml | 13 +- .../artifactory-2xlarge-extra-config.yaml | 41 ---- .../sizing/artifactory-2xlarge.yaml | 50 ++++- .../artifactory-large-extra-config.yaml | 41 ---- .../artifactory/sizing/artifactory-large.yaml | 48 ++++- .../artifactory-medium-extra-config.yaml | 41 ---- .../sizing/artifactory-medium.yaml | 48 ++++- .../artifactory-small-extra-config.yaml | 41 ---- .../artifactory/sizing/artifactory-small.yaml | 46 +++- .../artifactory-xlarge-extra-config.yaml | 41 ---- .../sizing/artifactory-xlarge.yaml | 48 ++++- .../artifactory-xsmall-extra-config.yaml | 42 ---- .../sizing/artifactory-xsmall.yaml | 47 ++++- stable/artifactory/templates/_helpers.tpl | 16 ++ .../templates/artifactory-license-secret.yaml | 2 +- .../templates/artifactory-service-grpc.yaml | 44 ++++ .../templates/artifactory-service.yaml | 2 + .../templates/artifactory-statefulset.yaml | 41 +++- .../artifactory/templates/ingress-grpc.yaml | 80 +++++++ .../artifactory/templates/nginx-service.yaml | 2 +- stable/artifactory/values.yaml | 199 ++++++------------ 63 files changed, 1178 insertions(+), 804 deletions(-) delete mode 100644 stable/artifactory-ha/sizing/artifactory-2xlarge-extra-config.yaml delete mode 100644 stable/artifactory-ha/sizing/artifactory-large-extra-config.yaml delete mode 100644 stable/artifactory-ha/sizing/artifactory-medium-extra-config.yaml delete mode 100644 stable/artifactory-ha/sizing/artifactory-small-extra-config.yaml delete mode 100644 stable/artifactory-ha/sizing/artifactory-xlarge-extra-config.yaml delete mode 100644 stable/artifactory-ha/sizing/artifactory-xsmall-extra-config.yaml create mode 100644 stable/artifactory-ha/templates/artifactory-service-grpc.yaml create mode 100644 stable/artifactory-ha/templates/ingress-grpc.yaml delete mode 100644 stable/artifactory/sizing/artifactory-2xlarge-extra-config.yaml delete mode 100644 stable/artifactory/sizing/artifactory-large-extra-config.yaml delete mode 100644 stable/artifactory/sizing/artifactory-medium-extra-config.yaml delete mode 100644 stable/artifactory/sizing/artifactory-small-extra-config.yaml delete mode 100644 stable/artifactory/sizing/artifactory-xlarge-extra-config.yaml delete mode 100644 stable/artifactory/sizing/artifactory-xsmall-extra-config.yaml create mode 100644 stable/artifactory/templates/artifactory-service-grpc.yaml create mode 100644 stable/artifactory/templates/ingress-grpc.yaml diff --git a/stable/artifactory-cpp-ce/CHANGELOG.md b/stable/artifactory-cpp-ce/CHANGELOG.md index 47a527436..13c5c1b53 100644 --- a/stable/artifactory-cpp-ce/CHANGELOG.md +++ b/stable/artifactory-cpp-ce/CHANGELOG.md @@ -1,7 +1,7 @@ # JFrog Artifactory CE for C++ Chart Changelog All changes to this chart will be documented in this file -## [107.90.15] - Feb 20, 2024 +## [107.98.7] - Feb 20, 2024 * Updated `artifactory.installerInfo` content ## [107.80.0] - Feb 1, 2024 diff --git a/stable/artifactory-cpp-ce/Chart.yaml b/stable/artifactory-cpp-ce/Chart.yaml index 709f8b811..f44ea5414 100644 --- a/stable/artifactory-cpp-ce/Chart.yaml +++ b/stable/artifactory-cpp-ce/Chart.yaml @@ -1,9 +1,9 @@ apiVersion: v2 -appVersion: 7.90.15 +appVersion: 7.98.7 dependencies: - name: artifactory repository: file://charts/artifactory - version: 107.90.15 + version: 107.98.7 description: JFrog Artifactory CE for C++ home: https://www.jfrog.com/artifactory/ icon: https://raw.githubusercontent.com/jfrog/charts/master/stable/artifactory-cpp-ce/logo/conan.png @@ -21,4 +21,4 @@ name: artifactory-cpp-ce sources: - https://github.com/jfrog/charts type: application -version: 107.90.15 +version: 107.98.7 diff --git a/stable/artifactory-cpp-ce/values.yaml b/stable/artifactory-cpp-ce/values.yaml index 20d9ee86a..1ca0a1538 100644 --- a/stable/artifactory-cpp-ce/values.yaml +++ b/stable/artifactory-cpp-ce/values.yaml @@ -69,7 +69,7 @@ postgresql: enabled: true router: image: - tag: 7.118.3 + tag: 7.135.1 initContainers: image: - tag: 9.4.949.1716471857 + tag: 9.4.1227 diff --git a/stable/artifactory-ha/CHANGELOG.md b/stable/artifactory-ha/CHANGELOG.md index 6804030dc..0f22a72f7 100644 --- a/stable/artifactory-ha/CHANGELOG.md +++ b/stable/artifactory-ha/CHANGELOG.md @@ -1,5 +1,33 @@ # JFrog Artifactory-ha Chart Changelog -All changes to this chart will be documented in this file. +All changes to this chart will be documented in this file + +## [107.98.7] - Oct 02, 2024 +* Add support for `extraEnvironmentVariables` on filebeat Sidecar [GH-1377](https://github.com/jfrog/charts/pull/1377) +* Support for SSL offload HTTPS proto override in Nginx service (ClusterIP, LoadBalancer) layer. Introduced `nginx.service.ssloffloadForceHttps` field with boolean type. [GH-1906](https://github.com/jfrog/charts/pull/1906) +* Enable Access workers integration when artifactory.worker.enabled is true +* Added `signedUrlExpirySeconds` option to artifactory.persistence.type of `google-storage`, `google-storage-v2`, and `google-storage-v2-direct` [GH-1858](https://github.com/jfrog/charts/pull/1858) +* Added support to bootstrap jfconnect custom certs to jfconnect trusted directory + +## [107.96.0] - Sep 18, 2024 +* Merged Artifactory sizing templates to a single file per size +* Added metadata and observability standalone image support + +## [107.95.0] - Aug 26, 2024 +* Adding missing annotations to primary Artifactory Service [GH-1862](https://github.com/jfrog/charts/pull/1862) + +## [107.94.0] - Aug 14, 2024 +* Fixed #Expose rtfs port only when it is enabled + +## [107.93.0] - Aug 9, 2024 +* Added support for worker via `artifactory.worker.enabled` flag +* Fixed creation of duplicate objects in statefulSet + +## [107.92.0] - July 31, 2024 +* Updating the example link for downloading the DB driver +* Adding dedicated ingress and service path for GRPC protocol + +## [107.91.0] - July 18, 2024 +* Remove X-JFrog-Override-Base-Url port when using default `443/80` ports ## [107.90.15] - July 18, 2024 * Fixed #adding colon in image registry which breaks deployment [GH-1892](https://github.com/jfrog/charts/pull/1892) @@ -15,9 +43,7 @@ All changes to this chart will be documented in this file. `access.javaOpts.other` `access.resources` `access.extraEnvironmentVariables` -* Updating the example link for downloading the DB driver * Added Binary Provider recommendations -* Add support for EnvironmentVaraiables on Filebeat Sidecar ## [107.89.0] - May 30, 2024 * Fix the indentation of the commented-out sections in the values.yaml file diff --git a/stable/artifactory-ha/Chart.yaml b/stable/artifactory-ha/Chart.yaml index cf12ad5c6..2511a8e6c 100644 --- a/stable/artifactory-ha/Chart.yaml +++ b/stable/artifactory-ha/Chart.yaml @@ -1,7 +1,9 @@ annotations: - artifactoryServiceVersion: 7.90.21 + artifactoryServiceVersion: 7.98.6 + metadataVersion: 7.90.0 + observabilityVersion: 1.31.5 apiVersion: v2 -appVersion: 7.90.15 +appVersion: 7.98.7 dependencies: - condition: postgresql.enabled name: postgresql @@ -23,4 +25,4 @@ name: artifactory-ha sources: - https://github.com/jfrog/charts type: application -version: 107.90.15 +version: 107.98.7 diff --git a/stable/artifactory-ha/README.md b/stable/artifactory-ha/README.md index 49155926e..e0ef54016 100644 --- a/stable/artifactory-ha/README.md +++ b/stable/artifactory-ha/README.md @@ -14,7 +14,7 @@ Below you will find the basic instructions for installing, uninstalling, and del ## Chart Details This chart will do the following: -* Deploy Artifactory highly available cluster. 1 primary node and 2 member nodes. +* Deploy Artifactory highly available cluster. 3 primary nodes. * Deploy a PostgreSQL database **NOTE:** For production grade installations it is recommended to use an external PostgreSQL * Deploy an Nginx server @@ -44,7 +44,7 @@ helm upgrade --install artifactory-ha jfrog/artifactory-ha --namespace artifacto To apply the chart with recommended sizing configurations : For small configurations : ```bash -helm upgrade --install artifactory-ha jfrog/artifactory-ha -f sizing/artifactory-small-extra-config.yaml -f sizing/artifactory-small.yaml --namespace artifactory-ha --create-namespace +helm upgrade --install artifactory-ha jfrog/artifactory-ha -f sizing/artifactory-small.yaml --namespace artifactory-ha --create-namespace ``` ## Uninstalling Artifactory diff --git a/stable/artifactory-ha/files/binarystore.xml b/stable/artifactory-ha/files/binarystore.xml index 0e7bc5af0..fca04f08a 100644 --- a/stable/artifactory-ha/files/binarystore.xml +++ b/stable/artifactory-ha/files/binarystore.xml @@ -198,6 +198,11 @@ {{ .Values.artifactory.persistence.googleStorage.bucketName }} {{ .Values.artifactory.persistence.googleStorage.path }} {{ .Values.artifactory.persistence.googleStorage.bucketExists }} + {{- if .Values.artifactory.persistence.googleStorage.signedUrlExpirySeconds }} + true + {{- else }} + false + {{- end }} {{- end }} diff --git a/stable/artifactory-ha/files/nginx-artifactory-conf.yaml b/stable/artifactory-ha/files/nginx-artifactory-conf.yaml index 89a8baa9b..4671d483c 100644 --- a/stable/artifactory-ha/files/nginx-artifactory-conf.yaml +++ b/stable/artifactory-ha/files/nginx-artifactory-conf.yaml @@ -63,12 +63,22 @@ location / { proxy_cookie_path ~*^/.* /; proxy_pass {{ include "artifactory-ha.scheme" . }}://{{ include "artifactory-ha.fullname" . }}:{{ .Values.artifactory.externalPort }}/; {{- if .Values.nginx.service.ssloffload}} + {{- if .Values.nginx.service.ssloffloadForceHttps}} + proxy_set_header X-JFrog-Override-Base-Url https://$host; + proxy_set_header X-Forwarded-Proto https; + {{- else }} + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + {{- end }} + {{- else if or (eq (int .Values.nginx.https.internalPort) 80) (eq (int .Values.nginx.https.externalPort) 443)}} proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host; + proxy_set_header X-Forwarded-Port $server_port; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; {{- else }} proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$host_port; proxy_set_header X-Forwarded-Port $server_port; - {{- end }} proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + {{- end }} proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; {{- if .Values.nginx.disableProxyBuffering}} diff --git a/stable/artifactory-ha/files/system.yaml b/stable/artifactory-ha/files/system.yaml index 3a1d93269..5cac766d5 100644 --- a/stable/artifactory-ha/files/system.yaml +++ b/stable/artifactory-ha/files/system.yaml @@ -2,10 +2,14 @@ router: serviceRegistry: insecure: {{ .Values.router.serviceRegistry.insecure }} shared: -{{- if .Values.artifactory.coldStorage.enabled }} +{{- if .Values.artifactory.coldStorage.enabled }} jfrogColdStorage: coldInstanceEnabled: true {{- end }} +{{- if .Values.artifactory.worker.enabled }} + featureToggler: + worker: true +{{- end }} {{ tpl (include "artifactory.metrics" .) . }} logging: consoleLog: @@ -13,6 +17,9 @@ shared: extraJavaOpts: > -Dartifactory.graceful.shutdown.max.request.duration.millis={{ mul .Values.artifactory.terminationGracePeriodSeconds 1000 }} -Dartifactory.access.client.max.connections={{ .Values.access.tomcat.connector.maxThreads }} +{{- if .Values.artifactory.worker.enabled }} + -Dartifactory.workers.addon.support=true +{{- end }} {{- with .Values.artifactory.primary.javaOpts }} {{- if .corePoolSize }} -Dartifactory.async.corePoolSize={{ .corePoolSize }} @@ -107,6 +114,10 @@ access: username: "{{ .Values.access.database.user }}" password: "{{ .Values.access.database.password }}" {{- end }} +{{- if .Values.artifactory.worker.enabled }} + worker: + enabled: true +{{- end }} {{- if .Values.mc.enabled }} mc: enabled: true diff --git a/stable/artifactory-ha/sizing/artifactory-2xlarge-extra-config.yaml b/stable/artifactory-ha/sizing/artifactory-2xlarge-extra-config.yaml deleted file mode 100644 index 6afc491dc..000000000 --- a/stable/artifactory-ha/sizing/artifactory-2xlarge-extra-config.yaml +++ /dev/null @@ -1,44 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - primary: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=200 - -Dartifactory.async.poolMaxQueueSize=100000 - -Dartifactory.http.client.max.total.connections=150 - -Dartifactory.http.client.max.connections.per.route=150 - -Dartifactory.access.client.max.connections=200 - -Dartifactory.metadata.event.operator.threads=5 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=1048576 - -XX:MaxDirectMemorySize=1024m - - tomcat: - connector: - maxThreads: 800 - extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 200 - -access: - tomcat: - connector: - maxThreads: 200 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - - database: - maxOpenConnections: 200 - -metadata: - database: - maxOpenConnections: 200 - diff --git a/stable/artifactory-ha/sizing/artifactory-2xlarge.yaml b/stable/artifactory-ha/sizing/artifactory-2xlarge.yaml index 02cf7f94e..a6915d470 100644 --- a/stable/artifactory-ha/sizing/artifactory-2xlarge.yaml +++ b/stable/artifactory-ha/sizing/artifactory-2xlarge.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The 2xlarge sizing # This size is intended for very large organizations. It can be increased with adding replicas -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: primary: @@ -21,22 +23,42 @@ artifactory: # cpu: "20" memory: 24Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=200 + -Dartifactory.async.poolMaxQueueSize=100000 + -Dartifactory.http.client.max.total.connections=150 + -Dartifactory.http.client.max.connections.per.route=150 + -Dartifactory.access.client.max.connections=200 + -Dartifactory.metadata.event.operator.threads=5 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=1048576 + -XX:MaxDirectMemorySize=1024m + + tomcat: + connector: + maxThreads: 800 + extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 200 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "16" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" router: resources: requests: - cpu: "1" - memory: 1Gi - limits: - # cpu: "6" + cpu: "2" memory: 2Gi + limits: + # cpu: "12" + memory: 4Gi frontend: resources: @@ -48,6 +70,8 @@ frontend: memory: 1Gi metadata: + database: + maxOpenConnections: 200 resources: requests: cpu: "1" @@ -66,6 +90,15 @@ event: memory: 500Mi access: + tomcat: + connector: + maxThreads: 200 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 200 resources: requests: cpu: 1 diff --git a/stable/artifactory-ha/sizing/artifactory-large-extra-config.yaml b/stable/artifactory-ha/sizing/artifactory-large-extra-config.yaml deleted file mode 100644 index fac24ad68..000000000 --- a/stable/artifactory-ha/sizing/artifactory-large-extra-config.yaml +++ /dev/null @@ -1,44 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - primary: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=65 - -Dartifactory.async.corePoolSize=80 - -Dartifactory.async.poolMaxQueueSize=20000 - -Dartifactory.http.client.max.total.connections=100 - -Dartifactory.http.client.max.connections.per.route=100 - -Dartifactory.access.client.max.connections=125 - -Dartifactory.metadata.event.operator.threads=4 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=524288 - -XX:MaxDirectMemorySize=512m - - tomcat: - connector: - maxThreads: 500 - extraConfig: 'acceptCount="800" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 100 - -access: - tomcat: - connector: - maxThreads: 125 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - - database: - maxOpenConnections: 100 - -metadata: - database: - maxOpenConnections: 100 - diff --git a/stable/artifactory-ha/sizing/artifactory-large.yaml b/stable/artifactory-ha/sizing/artifactory-large.yaml index 504edf1ed..63a8c6ce5 100644 --- a/stable/artifactory-ha/sizing/artifactory-large.yaml +++ b/stable/artifactory-ha/sizing/artifactory-large.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The large sizing -# This size is intended for large organizations. It can be increased with adding replicas or moving to the xlarge sizing -############################################################## +# This size is intended for large organizations. It can be increased with adding replicas or moving to the large sizing +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: primary: @@ -21,15 +23,44 @@ artifactory: # cpu: "14" memory: 12Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=65 + -Dartifactory.async.corePoolSize=80 + -Dartifactory.async.poolMaxQueueSize=20000 + -Dartifactory.http.client.max.total.connections=100 + -Dartifactory.http.client.max.connections.per.route=100 + -Dartifactory.access.client.max.connections=125 + -Dartifactory.metadata.event.operator.threads=4 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=524288 + -XX:MaxDirectMemorySize=512m + + tomcat: + connector: + maxThreads: 500 + extraConfig: 'acceptCount="800" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 100 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "8" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" access: + tomcat: + connector: + maxThreads: 125 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 100 resources: requests: cpu: 1 @@ -41,11 +72,11 @@ access: router: resources: requests: - cpu: 200m - memory: 400Mi + cpu: 400m + memory: 800Mi limits: - # cpu: "4" - memory: 1Gi + # cpu: "8" + memory: 2Gi frontend: resources: @@ -57,6 +88,8 @@ frontend: memory: 1Gi metadata: + database: + maxOpenConnections: 100 resources: requests: cpu: 200m diff --git a/stable/artifactory-ha/sizing/artifactory-medium-extra-config.yaml b/stable/artifactory-ha/sizing/artifactory-medium-extra-config.yaml deleted file mode 100644 index b2b20b198..000000000 --- a/stable/artifactory-ha/sizing/artifactory-medium-extra-config.yaml +++ /dev/null @@ -1,45 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - primary: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=40 - -Dartifactory.async.poolMaxQueueSize=10000 - -Dartifactory.http.client.max.total.connections=50 - -Dartifactory.http.client.max.connections.per.route=50 - -Dartifactory.access.client.max.connections=75 - -Dartifactory.metadata.event.operator.threads=3 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=262144 - -XX:MaxDirectMemorySize=256m - - tomcat: - connector: - maxThreads: 300 - extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 50 - -access: - tomcat: - connector: - maxThreads: 75 - - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - - database: - maxOpenConnections: 50 - -metadata: - database: - maxOpenConnections: 50 - diff --git a/stable/artifactory-ha/sizing/artifactory-medium.yaml b/stable/artifactory-ha/sizing/artifactory-medium.yaml index 93b79788d..89f9c9e46 100644 --- a/stable/artifactory-ha/sizing/artifactory-medium.yaml +++ b/stable/artifactory-ha/sizing/artifactory-medium.yaml @@ -1,7 +1,9 @@ -############################################################## +#################################################################################### # The medium sizing # This size is just 2 replicas of the small size. Vertical sizing of all services is not changed -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +#################################################################################### splitServicesToContainers: true artifactory: primary: @@ -21,22 +23,42 @@ artifactory: # cpu: "10" memory: 5Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=40 + -Dartifactory.async.poolMaxQueueSize=10000 + -Dartifactory.http.client.max.total.connections=50 + -Dartifactory.http.client.max.connections.per.route=50 + -Dartifactory.access.client.max.connections=75 + -Dartifactory.metadata.event.operator.threads=3 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=262144 + -XX:MaxDirectMemorySize=256m + + tomcat: + connector: + maxThreads: 300 + extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 50 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "2" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" router: resources: requests: - cpu: 100m - memory: 250Mi - limits: - # cpu: "1" + cpu: 200m memory: 500Mi + limits: + # cpu: "2" + memory: 1Gi frontend: resources: @@ -48,6 +70,8 @@ frontend: memory: 250Mi metadata: + database: + maxOpenConnections: 50 resources: requests: cpu: 100m @@ -66,6 +90,15 @@ event: memory: 250Mi access: + tomcat: + connector: + maxThreads: 75 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 50 resources: requests: cpu: 1 diff --git a/stable/artifactory-ha/sizing/artifactory-small-extra-config.yaml b/stable/artifactory-ha/sizing/artifactory-small-extra-config.yaml deleted file mode 100644 index e8329f1a3..000000000 --- a/stable/artifactory-ha/sizing/artifactory-small-extra-config.yaml +++ /dev/null @@ -1,43 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - primary: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=40 - -Dartifactory.async.poolMaxQueueSize=10000 - -Dartifactory.http.client.max.total.connections=50 - -Dartifactory.http.client.max.connections.per.route=50 - -Dartifactory.access.client.max.connections=75 - -Dartifactory.metadata.event.operator.threads=3 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=262144 - -XX:MaxDirectMemorySize=256m - - tomcat: - connector: - maxThreads: 300 - extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 50 - -access: - tomcat: - connector: - maxThreads: 75 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 50 - -metadata: - database: - maxOpenConnections: 50 - diff --git a/stable/artifactory-ha/sizing/artifactory-small.yaml b/stable/artifactory-ha/sizing/artifactory-small.yaml index b75a22323..454f159e5 100644 --- a/stable/artifactory-ha/sizing/artifactory-small.yaml +++ b/stable/artifactory-ha/sizing/artifactory-small.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The small sizing # This is the size recommended for running Artifactory for small teams -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: primary: @@ -21,24 +23,52 @@ artifactory: # cpu: "10" memory: 5Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=40 + -Dartifactory.async.poolMaxQueueSize=10000 + -Dartifactory.http.client.max.total.connections=50 + -Dartifactory.http.client.max.connections.per.route=50 + -Dartifactory.access.client.max.connections=75 + -Dartifactory.metadata.event.operator.threads=3 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=262144 + -XX:MaxDirectMemorySize=256m + tomcat: + connector: + maxThreads: 300 + extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 50 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "2" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" router: resources: requests: - cpu: 100m - memory: 250Mi - limits: - # cpu: "1" + cpu: 200m memory: 500Mi + limits: + # cpu: "2" + memory: 1Gi access: + tomcat: + connector: + maxThreads: 75 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 50 resources: requests: cpu: 500m @@ -57,6 +87,8 @@ frontend: memory: 250Mi metadata: + database: + maxOpenConnections: 50 resources: requests: cpu: 100m diff --git a/stable/artifactory-ha/sizing/artifactory-xlarge-extra-config.yaml b/stable/artifactory-ha/sizing/artifactory-xlarge-extra-config.yaml deleted file mode 100644 index 8d04850ad..000000000 --- a/stable/artifactory-ha/sizing/artifactory-xlarge-extra-config.yaml +++ /dev/null @@ -1,42 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - primary: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=65 - -Dartifactory.async.corePoolSize=160 - -Dartifactory.async.poolMaxQueueSize=50000 - -Dartifactory.http.client.max.total.connections=150 - -Dartifactory.http.client.max.connections.per.route=150 - -Dartifactory.access.client.max.connections=150 - -Dartifactory.metadata.event.operator.threads=5 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=1048576 - -XX:MaxDirectMemorySize=1024m - tomcat: - connector: - maxThreads: 600 - extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 150 - -access: - tomcat: - connector: - maxThreads: 150 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 150 - -metadata: - database: - maxOpenConnections: 150 - diff --git a/stable/artifactory-ha/sizing/artifactory-xlarge.yaml b/stable/artifactory-ha/sizing/artifactory-xlarge.yaml index 550bd051d..f2fe6e952 100644 --- a/stable/artifactory-ha/sizing/artifactory-xlarge.yaml +++ b/stable/artifactory-ha/sizing/artifactory-xlarge.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The xlarge sizing # This size is intended for very large organizations. It can be increased with adding replicas -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: primary: @@ -9,7 +11,6 @@ artifactory: # Count should be equal or above the total number of licenses available for artifactory. replicaCount: 4 - # Require multiple Artifactory pods to run on separate nodes podAntiAffinity: type: "hard" @@ -21,15 +22,44 @@ artifactory: # cpu: "14" memory: 16Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=65 + -Dartifactory.async.corePoolSize=160 + -Dartifactory.async.poolMaxQueueSize=50000 + -Dartifactory.http.client.max.total.connections=150 + -Dartifactory.http.client.max.connections.per.route=150 + -Dartifactory.access.client.max.connections=150 + -Dartifactory.metadata.event.operator.threads=5 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=1048576 + -XX:MaxDirectMemorySize=1024m + tomcat: + connector: + maxThreads: 600 + extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 150 + # Require multiple Artifactory pods to run on separate nodes + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "16" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" access: + tomcat: + connector: + maxThreads: 150 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 150 resources: requests: cpu: 1 @@ -41,11 +71,11 @@ access: router: resources: requests: - cpu: 200m - memory: 500Mi - limits: - # cpu: "4" + cpu: 400m memory: 1Gi + limits: + # cpu: "8" + memory: 2Gi frontend: resources: @@ -57,6 +87,8 @@ frontend: memory: 1Gi metadata: + database: + maxOpenConnections: 150 resources: requests: cpu: 200m diff --git a/stable/artifactory-ha/sizing/artifactory-xsmall-extra-config.yaml b/stable/artifactory-ha/sizing/artifactory-xsmall-extra-config.yaml deleted file mode 100644 index 1371e87b8..000000000 --- a/stable/artifactory-ha/sizing/artifactory-xsmall-extra-config.yaml +++ /dev/null @@ -1,43 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - primary: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=10 - -Dartifactory.async.poolMaxQueueSize=2000 - -Dartifactory.http.client.max.total.connections=20 - -Dartifactory.http.client.max.connections.per.route=20 - -Dartifactory.access.client.max.connections=15 - -Dartifactory.metadata.event.operator.threads=2 - -XX:MaxMetaspaceSize=400m - -XX:CompressedClassSpaceSize=96m - -Djdk.nio.maxCachedBufferSize=131072 - -XX:MaxDirectMemorySize=128m - tomcat: - connector: - maxThreads: 50 - extraConfig: 'acceptCount="200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 15 - -access: - tomcat: - connector: - maxThreads: 15 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 15 - -metadata: - database: - maxOpenConnections: 15 - diff --git a/stable/artifactory-ha/sizing/artifactory-xsmall.yaml b/stable/artifactory-ha/sizing/artifactory-xsmall.yaml index 3f7b07138..c89a87a54 100644 --- a/stable/artifactory-ha/sizing/artifactory-xsmall.yaml +++ b/stable/artifactory-ha/sizing/artifactory-xsmall.yaml @@ -1,7 +1,10 @@ -############################################################## +############################################################################################## + # The xsmall sizing # This is the minimum size recommended for running Artifactory -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: primary: @@ -21,15 +24,44 @@ artifactory: # cpu: "10" memory: 4Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=10 + -Dartifactory.async.poolMaxQueueSize=2000 + -Dartifactory.http.client.max.total.connections=20 + -Dartifactory.http.client.max.connections.per.route=20 + -Dartifactory.access.client.max.connections=15 + -Dartifactory.metadata.event.operator.threads=2 + -XX:MaxMetaspaceSize=400m + -XX:CompressedClassSpaceSize=96m + -Djdk.nio.maxCachedBufferSize=131072 + -XX:MaxDirectMemorySize=128m + tomcat: + connector: + maxThreads: 50 + extraConfig: 'acceptCount="200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 15 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "2" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" access: + tomcat: + connector: + maxThreads: 15 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 15 resources: requests: cpu: 500m @@ -41,11 +73,11 @@ access: router: resources: requests: - cpu: 50m - memory: 100Mi + cpu: 100m + memory: 200Mi limits: - # cpu: "1" - memory: 500Mi + # cpu: "2" + memory: 1Gi frontend: resources: @@ -57,6 +89,8 @@ frontend: memory: 250Mi metadata: + database: + maxOpenConnections: 15 resources: requests: cpu: 50m diff --git a/stable/artifactory-ha/templates/_helpers.tpl b/stable/artifactory-ha/templates/_helpers.tpl index d6fb229fe..ec9ba34df 100644 --- a/stable/artifactory-ha/templates/_helpers.tpl +++ b/stable/artifactory-ha/templates/_helpers.tpl @@ -295,6 +295,16 @@ Return the proper artifactory chart image names {{- else -}} {{- $tag = default $dot.Chart.AppVersion (index $dot.Values $indexReference "image" "tag") | toString -}} {{- end -}} +{{- if and (eq $indexReference "metadata") (hasKey $dot.Values.metadata "standaloneImageEnabled") }} + {{- if default false $dot.Values.metadata.standaloneImageEnabled }} + {{- $tag = default $dot.Chart.Annotations.metadataVersion (index $dot.Values $indexReference "image" "tag") | toString -}} + {{- end -}} +{{- end -}} +{{- if and (eq $indexReference "observability") (hasKey $dot.Values.observability "standaloneImageEnabled") }} + {{- if default false $dot.Values.observability.standaloneImageEnabled }} + {{- $tag = default $dot.Chart.Annotations.observabilityVersion (index $dot.Values $indexReference "image" "tag") | toString -}} + {{- end -}} +{{- end -}} {{- if $dot.Values.global }} {{- if and $dot.Values.splitServicesToContainers $dot.Values.global.versions.router (eq $indexReference "router") }} {{- $tag = $dot.Values.global.versions.router | toString -}} @@ -560,4 +570,20 @@ Resolve nginx hosts value {{- end -}} {{- end -}} {{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified grpc ingress name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "artifactory.ingressGrpc.fullname" -}} +{{- printf "%s-%s" (include "artifactory-ha.fullname" .) .Values.ingressGrpc.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified grpc service name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "artifactory.serviceGrpc.fullname" -}} +{{- printf "%s-%s" (include "artifactory-ha.fullname" .) .Values.artifactory.serviceGrpc.name | trunc 63 | trimSuffix "-" -}} {{- end -}} \ No newline at end of file diff --git a/stable/artifactory-ha/templates/artifactory-license-secret.yaml b/stable/artifactory-ha/templates/artifactory-license-secret.yaml index 73f900863..0018fa044 100644 --- a/stable/artifactory-ha/templates/artifactory-license-secret.yaml +++ b/stable/artifactory-ha/templates/artifactory-license-secret.yaml @@ -1,4 +1,4 @@ -{{ if and (not .Values.artifactory.unifiedSecretInstallation) (not .Values.artifactory.license.secret) (not .Values.artifactory.license.licenseKey) }} +{{ if and (not .Values.artifactory.unifiedSecretInstallation) (not .Values.artifactory.license.secret) }} {{- with .Values.artifactory.license.licenseKey }} apiVersion: v1 kind: Secret diff --git a/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml b/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml index 1b0973110..7d2f583a8 100644 --- a/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml +++ b/stable/artifactory-ha/templates/artifactory-node-statefulset.yaml @@ -169,6 +169,9 @@ spec: {{- if .Values.access.customCertificatesSecretName }} echo "Load custom certificates from database"; {{- end }} + {{- if .Values.jfconnect.customCertificatesSecretName }} + echo "Load custom certificates from database"; + {{- end }} {{- if or .Values.artifactory.masterKey .Values.global.masterKey .Values.artifactory.masterKeySecretName .Values.global.masterKeySecretName }} echo "Copy masterKey to {{ .Values.artifactory.persistence.mountPath }}/etc/security"; mkdir -p {{ .Values.artifactory.persistence.mountPath }}/etc/security; @@ -449,9 +452,6 @@ spec: {{- with .Values.router.extraEnvironmentVariables }} {{ tpl (toYaml .) $ | indent 8 }} {{- end }} - ports: - - name: http - containerPort: {{ .Values.router.internalPort }} volumeMounts: - name: volume mountPath: {{ .Values.router.persistence.mountPath | quote }} @@ -817,9 +817,11 @@ spec: {{- with .Values.federation.extraEnvironmentVariables }} {{ tpl (toYaml .) $ | indent 8 }} {{- end }} + {{- if .Values.federation.enabled }} ports: - containerPort: {{ .Values.federation.internalPort }} name: http-rtfs + {{- end }} volumeMounts: - name: volume mountPath: {{ .Values.artifactory.persistence.mountPath | quote }} @@ -1187,8 +1189,10 @@ spec: name: http - containerPort: {{ .Values.artifactory.internalArtifactoryPort }} name: http-internal + {{- if .Values.federation.enabled }} - containerPort: {{ .Values.federation.internalPort }} name: http-rtfs + {{- end }} {{- if .Values.artifactory.node.javaOpts.jmx.enabled }} - containerPort: {{ .Values.artifactory.node.javaOpts.jmx.port }} name: tcp-jmx @@ -1350,6 +1354,10 @@ spec: - "-e" - "-E" - "http.enabled=true" + env: +{{- with .Values.filebeat.extraEnvironmentVariables }} +{{ tpl (toYaml .) $ | indent 10 }} +{{- end }} volumeMounts: - name: filebeat-config mountPath: /usr/share/filebeat/filebeat.yml @@ -1357,10 +1365,6 @@ spec: subPath: filebeat.yml - name: volume mountPath: "{{ .Values.artifactory.persistence.mountPath }}" - env: -{{- with .Values.filebeat.EnvironmentVariables }} -{{ tpl (toYaml .) $ | indent 10 }} -{{- end }} livenessProbe: {{ toYaml .Values.filebeat.livenessProbe | indent 10 }} readinessProbe: diff --git a/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml b/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml index e629724fe..8da5de94c 100644 --- a/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml +++ b/stable/artifactory-ha/templates/artifactory-primary-statefulset.yaml @@ -221,6 +221,14 @@ spec: cp -fv /tmp/etc/tls.crt {{ .Values.artifactory.persistence.mountPath }}/bootstrap/etc/access/keys/ca.crt; cp -fv /tmp/etc/tls.key {{ .Values.artifactory.persistence.mountPath }}/bootstrap/etc/access/keys/ca.private.key; {{- end }} + {{- if .Values.jfconnect.customCertificatesSecretName }} + echo "Copying custom certificates to {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys"; + mkdir -p {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys; + cp -fv /tmp/etc/tls.crt {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + cp -fv /tmp/etc/tls.cer {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + cp -fv /tmp/etc/tls.pem {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + cp -fv /tmp/etc/tls.key {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + {{- end }} {{- if or .Values.artifactory.joinKey .Values.global.joinKey .Values.artifactory.joinKeySecretName .Values.global.joinKeySecretName }} echo "Copy joinKey to {{ .Values.artifactory.persistence.mountPath }}/bootstrap/access/etc/security"; mkdir -p {{ .Values.artifactory.persistence.mountPath }}/bootstrap/access/etc/security; @@ -270,7 +278,7 @@ spec: {{- end }} key: master-key {{- end }} - + ######################## Volume Mounts For copy-system-configurations ########################## volumeMounts: - name: volume @@ -320,6 +328,21 @@ spec: subPath: tls.key {{- end }} + {{- if .Values.jfconnect.customCertificatesSecretName }} + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.crt" + subPath: tls.crt + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.pem" + subPath: tls.pem + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.cer" + subPath: tls.cer + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.key" + subPath: tls.key + {{- end }} + {{- if or .Values.artifactory.customCertificates.enabled .Values.global.customCertificates.enabled }} - name: copy-custom-certificates image: {{ include "artifactory-ha.getImageInfoByValue" (list . "initContainers") }} @@ -561,9 +584,6 @@ spec: {{- with .Values.router.extraEnvironmentVariables }} {{ tpl (toYaml .) $ | indent 8 }} {{- end }} - ports: - - name: http - containerPort: {{ .Values.router.internalPort }} volumeMounts: - name: volume mountPath: {{ .Values.router.persistence.mountPath | quote }} @@ -728,8 +748,11 @@ spec: command: - '/bin/bash' - '-c' - - > - exec /opt/jfrog/artifactory/app/metadata/bin/jf-metadata start + {{- if default false .Values.metadata.standaloneImageEnabled }} + - exec /opt/jfrog/metadata/app/metadata/bin/jf-metadata + {{- else }} + - exec /opt/jfrog/artifactory/app/metadata/bin/jf-metadata start + {{- end }} {{- with .Values.metadata.lifecycle }} lifecycle: {{ toYaml . | indent 10 }} @@ -798,7 +821,11 @@ spec: {{ tpl (include "artifactory-ha.customVolumeMounts" .) . | indent 8 }} {{- end }} - name: volume + {{- if default false .Values.metadata.standaloneImageEnabled }} + mountPath: {{ .Values.metadata.persistence.mountPath | quote }} + {{- else }} mountPath: {{ .Values.artifactory.persistence.mountPath | quote }} + {{- end }} resources: {{ toYaml .Values.metadata.resources | indent 10 }} {{- if .Values.metadata.startupProbe.enabled }} @@ -911,9 +938,11 @@ spec: {{- with .Values.federation.extraEnvironmentVariables }} {{ tpl (toYaml .) $ | indent 8 }} {{- end }} + {{- if .Values.federation.enabled }} ports: - containerPort: {{ .Values.federation.internalPort }} name: http-rtfs + {{- end }} volumeMounts: - name: volume mountPath: {{ .Values.artifactory.persistence.mountPath | quote }} @@ -938,8 +967,11 @@ spec: command: - '/bin/bash' - '-c' - - > - exec /opt/jfrog/artifactory/app/observability/bin/jf-observability start + {{- if default false .Values.observability.standaloneImageEnabled }} + - exec /opt/jfrog/observability/app/bin/entrypoint-observability.sh + {{- else }} + - exec /opt/jfrog/artifactory/app/observability/bin/jf-observability start + {{- end }} {{- with .Values.observability.lifecycle }} lifecycle: {{ toYaml . | indent 10 }} @@ -954,7 +986,11 @@ spec: {{- end }} volumeMounts: - name: volume + {{- if default false .Values.observability.standaloneImageEnabled }} + mountPath: {{ .Values.observability.persistence.mountPath | quote }} + {{- else }} mountPath: {{ .Values.artifactory.persistence.mountPath | quote }} + {{- end }} resources: {{ toYaml .Values.observability.resources | indent 10 }} {{- if .Values.observability.startupProbe.enabled }} @@ -1288,8 +1324,10 @@ spec: name: http - containerPort: {{ .Values.artifactory.internalArtifactoryPort }} name: http-internal + {{- if .Values.federation.enabled }} - containerPort: {{ .Values.federation.internalPort }} name: http-rtfs + {{- end }} {{- if .Values.artifactory.primary.javaOpts.jmx.enabled }} - containerPort: {{ .Values.artifactory.primary.javaOpts.jmx.port }} name: tcp-jmx @@ -1461,6 +1499,10 @@ spec: - "-e" - "-E" - "http.enabled=true" + env: +{{- with .Values.filebeat.extraEnvironmentVariables }} +{{ tpl (toYaml .) $ | indent 10 }} +{{- end }} volumeMounts: - name: filebeat-config mountPath: /usr/share/filebeat/filebeat.yml @@ -1468,10 +1510,6 @@ spec: subPath: filebeat.yml - name: volume mountPath: "{{ .Values.artifactory.persistence.mountPath }}" - env: -{{- with .Values.filebeat.EnvironmentVariables }} -{{ tpl (toYaml .) $ | indent 10 }} -{{- end }} livenessProbe: {{ toYaml .Values.filebeat.livenessProbe | indent 10 }} readinessProbe: @@ -1547,6 +1585,11 @@ spec: secret: secretName: {{ .Values.access.customCertificatesSecretName }} {{- end }} + {{- if .Values.jfconnect.customCertificatesSecretName }} + - name: jfconnect-certs + secret: + secretName: {{ .Values.jfconnect.customCertificatesSecretName }} + {{- end }} {{- if .Values.systemYamlOverride.existingSecret }} - name: systemyaml secret: diff --git a/stable/artifactory-ha/templates/artifactory-service-grpc.yaml b/stable/artifactory-ha/templates/artifactory-service-grpc.yaml new file mode 100644 index 000000000..a2f1b9233 --- /dev/null +++ b/stable/artifactory-ha/templates/artifactory-service-grpc.yaml @@ -0,0 +1,49 @@ +{{- if .Values.ingressGrpc.enabled -}} +# Service for GRPC communication. +apiVersion: v1 +kind: Service +metadata: + name: {{ template "artifactory.serviceGrpc.fullname" . }} + labels: + app: {{ template "artifactory-ha.name" . }} + chart: {{ template "artifactory-ha.chart" . }} + component: {{ .Values.artifactory.name }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + {{- with .Values.artifactory.node.labels }} +{{ toYaml .| indent 4 }} + {{- end }} +{{- if .Values.artifactory.serviceGrpc.annotations }} + annotations: +{{ toYaml .Values.artifactory.serviceGrpc.annotations | indent 4 }} +{{- end }} +spec: + {{- if .Values.artifactory.serviceGrpc.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.artifactory.serviceGrpc.ipFamilyPolicy }} + {{- end }} + {{- if not (empty .Values.artifactory.serviceGrpc.ipFamilies)}} + ipFamilies: {{- toYaml .Values.artifactory.serviceGrpc.ipFamilies | nindent 4 }} + {{- end }} + type: {{ .Values.artifactory.serviceGrpc.type }} + {{- if and (eq .Values.artifactory.serviceGrpc.type "ClusterIP") .Values.artifactory.serviceGrpc.clusterIP }} + clusterIP: {{ .Values.artifactory.serviceGrpc.clusterIP }} + {{- end }} + {{- if .Values.artifactory.serviceGrpc.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.artifactory.serviceGrpc.loadBalancerSourceRanges | indent 4 }} + {{- end }} + ports: + - port: {{ .Values.artifactory.externalPort }} + targetPort: {{ .Values.artifactory.internalPort }} + protocol: TCP + name: http-router + selector: +{{- if eq (int .Values.artifactory.node.replicaCount) 0 }} + role: {{ template "artifactory-ha.primary.name" . }} +{{- else if eq .Values.artifactory.serviceGrpc.pool "members" }} + role: {{ template "artifactory-ha.node.name" . }} +{{- end }} + app: {{ template "artifactory-ha.name" . }} + component: "{{ .Values.artifactory.name }}" + release: {{ .Release.Name }} +{{- end -}} \ No newline at end of file diff --git a/stable/artifactory-ha/templates/artifactory-service.yaml b/stable/artifactory-ha/templates/artifactory-service.yaml index 0912beae0..2739f7a5a 100644 --- a/stable/artifactory-ha/templates/artifactory-service.yaml +++ b/stable/artifactory-ha/templates/artifactory-service.yaml @@ -36,10 +36,12 @@ spec: targetPort: {{ .Values.artifactory.internalPort }} protocol: TCP name: http-router + {{- if .Values.federation.enabled }} - port: {{ .Values.federation.internalPort }} targetPort: {{ .Values.federation.internalPort }} protocol: TCP name: http-rtfs + {{- end }} {{- if .Values.artifactory.ssh.enabled }} - port: {{ .Values.artifactory.ssh.externalPort }} targetPort: {{ .Values.artifactory.ssh.internalPort }} diff --git a/stable/artifactory-ha/templates/ingress-grpc.yaml b/stable/artifactory-ha/templates/ingress-grpc.yaml new file mode 100644 index 000000000..eaa5a54e0 --- /dev/null +++ b/stable/artifactory-ha/templates/ingress-grpc.yaml @@ -0,0 +1,80 @@ +{{- if .Values.ingressGrpc.enabled -}} +{{- $serviceName := include "artifactory.serviceGrpc.fullname" . -}} +{{- $servicePort := .Values.artifactory.externalPort -}} +{{- $ingressName := include "artifactory.ingressGrpc.fullname" . -}} +{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }} +apiVersion: networking.k8s.io/v1 +{{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +apiVersion: networking.k8s.io/v1beta1 +{{- else }} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $ingressName }} + labels: + app: {{ template "artifactory-ha.name" . }} + chart: {{ template "artifactory-ha.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.ingressGrpc.labels }} +{{ .Values.ingressGrpc.labels | toYaml | trimSuffix "\n"| indent 4 -}} +{{- end}} +{{- if .Values.ingressGrpc.annotations }} + annotations: +{{ .Values.ingressGrpc.annotations | toYaml | trimSuffix "\n" | indent 4 -}} +{{- end }} +spec: + {{- if and .Values.ingressGrpc.className (semverCompare ">=1.18.0-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingressGrpc.className }} + {{- end }} + {{- if .Values.ingressGrpc.defaultBackend.enabled }} + {{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }} + defaultBackend: + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} + rules: +{{- if .Values.ingressGrpc.hosts }} + {{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }} + {{- range $host := .Values.ingressGrpc.hosts }} + - host: {{ $host | quote }} + http: + paths: + - path: {{ $.Values.ingressGrpc.grpcPath }} + pathType: ImplementationSpecific + backend: + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- end }} + {{- else }} + {{- range $host := .Values.ingressGrpc.hosts }} + - host: {{ $host | quote }} + http: + paths: + - path: {{ $.Values.ingressGrpc.grpcPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} +{{- end -}} + {{- with .Values.ingressGrpc.additionalRules }} +{{ tpl . $ | indent 2 }} + {{- end }} + + {{- if .Values.ingressGrpc.tls }} + tls: +{{ toYaml .Values.ingressGrpc.tls | indent 4 }} + {{- end -}} + +{{- end -}} diff --git a/stable/artifactory-ha/templates/nginx-deployment.yaml b/stable/artifactory-ha/templates/nginx-deployment.yaml index 5584dccaa..d43689b8c 100644 --- a/stable/artifactory-ha/templates/nginx-deployment.yaml +++ b/stable/artifactory-ha/templates/nginx-deployment.yaml @@ -81,8 +81,6 @@ spec: volumeMounts: - mountPath: {{ .Values.nginx.persistence.mountPath | quote }} name: nginx-volume - resources: -{{ toYaml .Values.initContainers.resources | indent 10 }} containers: - name: {{ .Values.nginx.name }} image: {{ include "artifactory-ha.getImageInfoByValue" (list . "nginx") }} diff --git a/stable/artifactory-ha/templates/nginx-service.yaml b/stable/artifactory-ha/templates/nginx-service.yaml index 4f3bb58a1..604831cfe 100644 --- a/stable/artifactory-ha/templates/nginx-service.yaml +++ b/stable/artifactory-ha/templates/nginx-service.yaml @@ -64,7 +64,7 @@ spec: {{- if .Values.nginx.https }} {{- if or .Values.nginx.https.enabled .Values.nginx.service.ssloffload }} - port: {{ .Values.nginx.https.externalPort }} - {{- if .Values.nginx.service.ssloffload }} + {{- if and .Values.nginx.service.ssloffload (not .Values.nginx.service.ssloffloadForceHttps) }} targetPort: {{ .Values.nginx.http.internalPort }} {{- else }} targetPort: {{ .Values.nginx.https.internalPort}} diff --git a/stable/artifactory-ha/values.yaml b/stable/artifactory-ha/values.yaml index 4107c070b..c6dbec234 100644 --- a/stable/artifactory-ha/values.yaml +++ b/stable/artifactory-ha/values.yaml @@ -46,7 +46,7 @@ initContainers: image: registry: releases-docker.jfrog.io repository: ubi9/ubi-minimal - tag: 9.4.949.1716471857 + tag: 9.4.1227 pullPolicy: IfNotPresent resources: requests: @@ -116,7 +116,6 @@ ingress: rtfsPath: /artifactory/service/rtfs/ className: "" annotations: {} - # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" # nginx.ingress.kubernetes.io/proxy-body-size: "0" labels: {} @@ -134,6 +133,34 @@ ingress: disableRouterBypass: false ## Allows to add custom ingress customIngress: "" +## There is a need to separate HTTP1.1 traffic from gRPC (HTTP2) to benefit +## 1. Use the Nginx keepalive for HTTP1.1 +## 2. Keep gRPC over the HTTP2 connections only +ingressGrpc: + enabled: false + name: grpc + defaultBackend: + enabled: true + ## Used to create an Ingress record. + hosts: [] + grpcPath: /com.jfrog + className: "" + ## For supporting GRPC protocol traffic sent to the backend it is necessary to change the backend protocol + ## Example: nginx.ingress.kubernetes.io/backend-protocol: GRPCS + annotations: {} + # kubernetes.io/tls-acme: "true" + # nginx.ingress.kubernetes.io/proxy-body-size: "0" + labels: {} + # traffic-type: external + # traffic-type: internal + tls: [] + ## Secrets must be manually created in the namespace. + # - secretName: chart-example-tls + # hosts: + # - artifactory.domain.example + + ## Additional ingress rules + additionalRules: [] networkpolicy: [] # Allows all ingress and egress # - name: artifactory @@ -255,7 +282,7 @@ router: image: registry: releases-docker.jfrog.io repository: jfrog/router - tag: 7.118.3 + tag: 7.135.1 pullPolicy: IfNotPresent serviceRegistry: ## Service registry (Access) TLS verification skipped if enabled @@ -397,6 +424,10 @@ artifactory: ## Refer - https://jfrog.com/help/r/jfrog-platform-administration-documentation/setting-up-cold-artifact-storage coldStorage: enabled: false + ## Support for workers + ## set 'worker.enabled' to 'true' to enable artifactory addon that executes workers on artifactory events + worker: + enabled: false ## This directory is intended for use with NFS eventual configuration for HA ## When enabling this section, The system.yaml will include haDataDir section. ## The location of Artifactory Data directory and Artifactory Filestore will be modified accordingly and will be shared among all nodes. @@ -849,6 +880,7 @@ artifactory: bucketExists: false useInstanceCredentials: false enableSignedUrlRedirect: false + # signedUrlExpirySeconds: false ## For artifactory.persistence.type aws-s3-v3, s3-storage-v3-direct, s3-storage-v3-archive awsS3V3: testConnection: false @@ -913,6 +945,33 @@ artifactory: pool: members ## If the type is NodePort you can set a fixed port # nodePort: 32082 + serviceGrpc: + name: grpc + type: ClusterIP + ## @param service.ipFamilyPolicy Controller Service ipFamilyPolicy (optional, cloud specific) + ## This can be either SingleStack, PreferDualStack or RequireDualStack + ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ## + ipFamilyPolicy: "" + ## @param service.ipFamilies Controller Service ipFamilies (optional, cloud specific) + ## This can be either ["IPv4"], ["IPv6"], ["IPv4", "IPv6"] or ["IPv6", "IPv4"] + ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ## + ipFamilies: [] + ## For supporting whitelist on the Artifactory service (useful if setting service.type=LoadBalancer) + ## Set this to a list of IP CIDR ranges + ## Example: loadBalancerSourceRanges: ['10.10.10.5/32', '10.11.10.5/32'] + ## or pass from helm command line + ## Example: helm install ... --set nginx.service.loadBalancerSourceRanges='{10.10.10.5/32,10.11.10.5/32}' + loadBalancerSourceRanges: [] + annotations: {} + ## Which nodes in the cluster should be in the external load balancer pool (have external traffic routed to them) + ## Supported pool values + ## members + ## all + pool: members + ## If the type is NodePort you can set a fixed port + # nodePort: 32082 statefulset: annotations: {} ssh: @@ -1367,6 +1426,10 @@ jfconnect: # exec: # command: ["/bin/sh","-c","echo Hello from the preStop handler"] + ## You can use a pre-existing secret by specifying customCertificatesSecretName + ## Example : Create a tls secret using `kubectl create secret tls --cert=tls.crt --key=tls.key` + # customCertificatesSecretName: + ## The following settings are to configure the frequency of the liveness and startup probes when splitServicesToContainers set to true livenessProbe: enabled: true @@ -1626,6 +1689,10 @@ nginx: ## For minikube, set this to NodePort, elsewhere use LoadBalancer type: LoadBalancer ssloffload: false + ## @param service.ssloffloadForceHttps Only enabled when service.ssloffload is set to True. + ## Force all requests from NGINX to the upstream server are over HTTPS, even when SSL offloading is enabled. + ## This is useful in environments where internal traffic must remain secure with https only. + ssloffloadForceHttps: false ## @param service.ipFamilyPolicy Controller Service ipFamilyPolicy (optional, cloud specific) ## This can be either SingleStack, PreferDualStack or RequireDualStack ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services @@ -1784,7 +1851,6 @@ filebeat: initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 5 - EnvironmentVariables: {} resources: {} # requests: # memory: "100Mi" @@ -1812,6 +1878,9 @@ filebeat: output: logstash: hosts: ["{{ .Values.filebeat.logstashUrl }}"] + extraEnvironmentVariables: {} + # - name: MY_ENV_VAR + # value: "" ## Allows to add additional kubernetes resources ## Use --- as a separator between multiple resources ## For an example, refer - https://github.com/jfrog/log-analytics-prometheus/blob/master/helm/artifactory-ha-values.yaml diff --git a/stable/artifactory-jcr/CHANGELOG.md b/stable/artifactory-jcr/CHANGELOG.md index e078ddd06..9d3a2d71d 100644 --- a/stable/artifactory-jcr/CHANGELOG.md +++ b/stable/artifactory-jcr/CHANGELOG.md @@ -1,7 +1,7 @@ # JFrog Container Registry Chart Changelog All changes to this chart will be documented in this file. -## [107.90.15] - Feb 20, 2024 +## [107.98.7] - Feb 20, 2024 * Updated `artifactory.installerInfo` content ## [107.80.0] - Feb 1, 2024 diff --git a/stable/artifactory-jcr/Chart.yaml b/stable/artifactory-jcr/Chart.yaml index b2db7ce67..9427485f6 100644 --- a/stable/artifactory-jcr/Chart.yaml +++ b/stable/artifactory-jcr/Chart.yaml @@ -1,9 +1,9 @@ apiVersion: v2 -appVersion: 7.90.15 +appVersion: 7.98.7 dependencies: - name: artifactory repository: file://charts/artifactory - version: 107.90.15 + version: 107.98.7 description: JFrog Container Registry home: https://jfrog.com/container-registry/ icon: https://raw.githubusercontent.com/jfrog/charts/master/stable/artifactory-jcr/logo/jcr-logo.png @@ -22,4 +22,4 @@ name: artifactory-jcr sources: - https://github.com/jfrog/charts type: application -version: 107.90.15 +version: 107.98.7 diff --git a/stable/artifactory-jcr/values.yaml b/stable/artifactory-jcr/values.yaml index a96b4f7d2..d1e4702b6 100644 --- a/stable/artifactory-jcr/values.yaml +++ b/stable/artifactory-jcr/values.yaml @@ -69,7 +69,7 @@ postgresql: enabled: true router: image: - tag: 7.118.3 + tag: 7.135.1 initContainers: image: - tag: 9.4.949.1716471857 + tag: 9.4.1227 diff --git a/stable/artifactory-oss/CHANGELOG.md b/stable/artifactory-oss/CHANGELOG.md index f89d246e5..6bc5fbddc 100644 --- a/stable/artifactory-oss/CHANGELOG.md +++ b/stable/artifactory-oss/CHANGELOG.md @@ -1,7 +1,7 @@ # JFrog Artifactory OSS Chart Changelog All changes to this chart will be documented in this file -## [107.90.15] - Feb 20, 2024 +## [107.98.7] - Feb 20, 2024 * Updated `artifactory.installerInfo` content ## [107.80.0] - Feb 1, 2024 diff --git a/stable/artifactory-oss/Chart.yaml b/stable/artifactory-oss/Chart.yaml index c81caff01..1807a0f05 100644 --- a/stable/artifactory-oss/Chart.yaml +++ b/stable/artifactory-oss/Chart.yaml @@ -1,9 +1,9 @@ apiVersion: v2 -appVersion: 7.90.15 +appVersion: 7.98.7 dependencies: - name: artifactory repository: file://charts/artifactory - version: 107.90.15 + version: 107.98.7 description: JFrog Artifactory OSS home: https://www.jfrog.com/artifactory/ icon: https://raw.githubusercontent.com/jfrog/charts/master/stable/artifactory/logo/artifactory-logo.png @@ -20,4 +20,4 @@ name: artifactory-oss sources: - https://github.com/jfrog/charts type: application -version: 107.90.15 +version: 107.98.7 diff --git a/stable/artifactory-oss/values.yaml b/stable/artifactory-oss/values.yaml index 986dbc5b5..c035d7ebc 100644 --- a/stable/artifactory-oss/values.yaml +++ b/stable/artifactory-oss/values.yaml @@ -69,7 +69,7 @@ postgresql: enabled: true router: image: - tag: 7.118.3 + tag: 7.135.1 initContainers: image: - tag: 9.4.949.1716471857 + tag: 9.4.1227 diff --git a/stable/artifactory/CHANGELOG.md b/stable/artifactory/CHANGELOG.md index b9c4002e3..b7aaca364 100644 --- a/stable/artifactory/CHANGELOG.md +++ b/stable/artifactory/CHANGELOG.md @@ -1,6 +1,30 @@ # JFrog Artifactory Chart Changelog All changes to this chart will be documented in this file. +## [107.98.7] - Oct 02, 2024 +* Add support for `extraEnvironmentVariables` on filebeat Sidecar [GH-1377](https://github.com/jfrog/charts/pull/1377) +* Support for SSL offload HTTPS proto override in Nginx service (ClusterIP, LoadBalancer) layer. Introduced `nginx.service.ssloffloadForceHttps` field with boolean type. [GH-1906](https://github.com/jfrog/charts/pull/1906) +* Enable Access workers integration when artifactory.worker.enabled is true +* Added `signedUrlExpirySeconds` option to artifactory.persistence.type of `google-storage`, `google-storage-v2`, and `google-storage-v2-direct` [GH-1858](https://github.com/jfrog/charts/pull/1858) +* Added support to bootstrap jfconnect custom certs to jfconnect trusted directory + +## [107.96.0] - Sep 10, 2024 +* Merged Artifactory sizing templates to a single file per size + +## [107.94.0] - Aug 14, 2024 +* Fixed #Expose rtfs port only when it is enabled + +## [107.93.0] - Aug 9, 2024 +* Added support for worker via `artifactory.worker.enabled` flag +* Fixed creation of duplicate objects in statefulSet + +## [107.92.0] - July 31, 2024 +* Updating the example link for downloading the DB driver +* Adding dedicated ingress and service path for GRPC protocol + +## [107.91.0] - July 18, 2024 +* Remove X-JFrog-Override-Base-Url port when using default `443/80` ports + ## [107.90.15] - July 18, 2024 * Fixed #adding colon in image registry which breaks deployment [GH-1892](https://github.com/jfrog/charts/pull/1892) * Added new `nginx.hosts` to use Nginx server_name directive instead of `ingress.hosts` @@ -15,10 +39,7 @@ All changes to this chart will be documented in this file. `access.javaOpts.other` `access.resources` `access.extraEnvironmentVariables` -* Updating the example link for downloading the DB driver * Added Binary Provider recommendations -* Added `signedUrlExpirySeconds` option to artifactory.persistence.type of `google-storage`, `google-storage-v2`, and `google-storage-v2-direct` -* Support for SSL offload HTTPS proto override in Nginx service(ClusterIP) layer. Introduced `nginx.service.ssloffloadForceHttps` field with boolean type. ## [107.89.0] - June 7, 2024 * Fix the indentation of the commented-out sections in the values.yaml file @@ -41,7 +62,7 @@ All changes to this chart will be documented in this file. * Added support for `global.verisons.initContainers` to override `initContainers.image.tag` * Fixed an issue with extraSystemYaml merge * **IMPORTANT** -* Renamed `artifactory.setSecurityContext` to `artifactory.podSecurityContext` +* Renamed `artifactory.setSecurityContext` to `artifactory.podSecurityContext` * Renamed `artifactory.uid` to `artifactory.podSecurityContext.runAsUser` * Renamed `artifactory.gid` to `artifactory.podSecurityContext.runAsGroup` and `artifactory.podSecurityContext.fsGroup` * Renamed `artifactory.fsGroupChangePolicy` to `artifactory.podSecurityContext.fsGroupChangePolicy` @@ -165,7 +186,7 @@ All changes to this chart will be documented in this file. ## [107.58.0] - Mar 23, 2023 * Updated postgresql multi-arch tag version to `13.10.0-debian-11-r14` * Removed obselete remove-lost-found initContainer` -* Added env JF_SHARED_NODE_HAENABLED under frontend when running in the container split mode +* Added env JF_SHARED_NODE_HAENABLED under frontend when running in the container split mode ## [107.57.0] - Mar 02, 2023 * Updated initContainerImage and logger image to `ubi9/ubi-minimal:9.1.0.1793` @@ -383,7 +404,7 @@ All changes to this chart will be documented in this file. ## [12.0.0] - April 22, 2021 * **Breaking change:** -* Increased default postgresql persistence size to `200Gi` +* Increased default postgresql persistence size to `200Gi` * Update postgresql tag version to `13.2.0-debian-10-r55` * Update postgresql chart version to `10.3.18` in chart.yaml - [10.x Upgrade Notes](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#to-1000) * If this is a new deployment or you already use an external database (`postgresql.enabled=false`), these changes **do not affect you**! diff --git a/stable/artifactory/Chart.yaml b/stable/artifactory/Chart.yaml index 2d73d0a6e..7ba8a6f1e 100644 --- a/stable/artifactory/Chart.yaml +++ b/stable/artifactory/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 7.90.15 +appVersion: 7.98.7 dependencies: - condition: postgresql.enabled name: postgresql @@ -21,4 +21,4 @@ name: artifactory sources: - https://github.com/jfrog/charts type: application -version: 107.90.15 +version: 107.98.7 diff --git a/stable/artifactory/README.md b/stable/artifactory/README.md index da3304ee5..783101786 100644 --- a/stable/artifactory/README.md +++ b/stable/artifactory/README.md @@ -32,10 +32,11 @@ helm upgrade --install artifactory jfrog/artifactory --namespace artifactory --c ``` ### Apply Sizing configurations to the Chart +Note that sizings with more than one replica require an enterprise license for HA . Refer [here](https://jfrog.com/help/r/jfrog-installation-setup-documentation/high-availability) To apply the chart with recommended sizing configurations : For small configurations : ```bash -helm upgrade --install artifactory jfrog/artifactory -f sizing/artifactory-small-extra-config.yaml -f sizing/artifactory-small.yaml --namespace artifactory --create-namespace +helm upgrade --install artifactory jfrog/artifactory -f sizing/artifactory-small.yaml --namespace artifactory --create-namespace ``` ## Uninstalling Artifactory diff --git a/stable/artifactory/files/binarystore.xml b/stable/artifactory/files/binarystore.xml index 543f8d542..b02ac8ad5 100644 --- a/stable/artifactory/files/binarystore.xml +++ b/stable/artifactory/files/binarystore.xml @@ -180,7 +180,9 @@ {{ .Values.artifactory.persistence.googleStorage.path }} {{ .Values.artifactory.persistence.googleStorage.bucketExists }} {{- if .Values.artifactory.persistence.googleStorage.signedUrlExpirySeconds }} - {{ .Values.artifactory.persistence.googleStorage.signedUrlExpirySeconds }} + true + {{- else }} + false {{- end }} diff --git a/stable/artifactory/files/nginx-artifactory-conf.yaml b/stable/artifactory/files/nginx-artifactory-conf.yaml index 8ee5e53dd..1ddd6c33a 100644 --- a/stable/artifactory/files/nginx-artifactory-conf.yaml +++ b/stable/artifactory/files/nginx-artifactory-conf.yaml @@ -63,12 +63,22 @@ location / { proxy_cookie_path ~*^/.* /; proxy_pass {{ include "artifactory.scheme" . }}://{{ include "artifactory.fullname" . }}:{{ .Values.artifactory.externalPort }}/; {{- if .Values.nginx.service.ssloffload}} + {{- if .Values.nginx.service.ssloffloadForceHttps}} + proxy_set_header X-JFrog-Override-Base-Url https://$host; + proxy_set_header X-Forwarded-Proto https; + {{- else }} + proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + {{- end }} + {{- else if or (eq (int .Values.nginx.https.internalPort) 80) (eq (int .Values.nginx.https.externalPort) 443)}} proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host; + proxy_set_header X-Forwarded-Port $server_port; + proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; {{- else }} proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$host_port; proxy_set_header X-Forwarded-Port $server_port; - {{- end }} proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; + {{- end }} proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; {{- if .Values.nginx.disableProxyBuffering}} diff --git a/stable/artifactory/files/system.yaml b/stable/artifactory/files/system.yaml index 053207fd0..fecc70714 100644 --- a/stable/artifactory/files/system.yaml +++ b/stable/artifactory/files/system.yaml @@ -2,10 +2,14 @@ router: serviceRegistry: insecure: {{ .Values.router.serviceRegistry.insecure }} shared: -{{- if .Values.artifactory.coldStorage.enabled }} +{{- if .Values.artifactory.coldStorage.enabled }} jfrogColdStorage: coldInstanceEnabled: true {{- end }} +{{- if .Values.artifactory.worker.enabled }} + featureToggler: + worker: true +{{- end }} {{ tpl (include "artifactory.metrics" .) . }} logging: consoleLog: @@ -13,6 +17,9 @@ shared: extraJavaOpts: > -Dartifactory.graceful.shutdown.max.request.duration.millis={{ mul .Values.artifactory.terminationGracePeriodSeconds 1000 }} -Dartifactory.access.client.max.connections={{ .Values.access.tomcat.connector.maxThreads }} +{{- if .Values.artifactory.worker.enabled }} + -Dartifactory.workers.addon.support=true +{{- end }} {{- with .Values.artifactory.javaOpts }} {{- if .corePoolSize }} -Dartifactory.async.corePoolSize={{ .corePoolSize }} @@ -101,6 +108,10 @@ access: maxThreads: {{ .Values.access.tomcat.connector.maxThreads }} sendReasonPhrase: {{ .Values.access.tomcat.connector.sendReasonPhrase }} extraConfig: {{ .Values.access.tomcat.connector.extraConfig }} +{{- if .Values.artifactory.worker.enabled }} + worker: + enabled: true +{{- end }} {{- if .Values.mc.enabled }} mc: enabled: true diff --git a/stable/artifactory/sizing/artifactory-2xlarge-extra-config.yaml b/stable/artifactory/sizing/artifactory-2xlarge-extra-config.yaml deleted file mode 100644 index 7bccf330d..000000000 --- a/stable/artifactory/sizing/artifactory-2xlarge-extra-config.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=200 - -Dartifactory.async.poolMaxQueueSize=100000 - -Dartifactory.http.client.max.total.connections=150 - -Dartifactory.http.client.max.connections.per.route=150 - -Dartifactory.access.client.max.connections=200 - -Dartifactory.metadata.event.operator.threads=5 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=1048576 - -XX:MaxDirectMemorySize=1024m - tomcat: - connector: - maxThreads: 800 - extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 200 - -access: - tomcat: - connector: - maxThreads: 200 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 200 - -metadata: - database: - maxOpenConnections: 200 - diff --git a/stable/artifactory/sizing/artifactory-2xlarge.yaml b/stable/artifactory/sizing/artifactory-2xlarge.yaml index be477939b..e3f9a3442 100644 --- a/stable/artifactory/sizing/artifactory-2xlarge.yaml +++ b/stable/artifactory/sizing/artifactory-2xlarge.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The 2xlarge sizing # This size is intended for very large organizations. It can be increased with adding replicas -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: # Enterprise and above licenses are required for setting replicaCount greater than 1. @@ -23,12 +25,40 @@ artifactory: extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "16" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=200 + -Dartifactory.async.poolMaxQueueSize=100000 + -Dartifactory.http.client.max.total.connections=150 + -Dartifactory.http.client.max.connections.per.route=150 + -Dartifactory.access.client.max.connections=200 + -Dartifactory.metadata.event.operator.threads=5 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=1048576 + -XX:MaxDirectMemorySize=1024m + tomcat: + connector: + maxThreads: 800 + extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 200 + access: + tomcat: + connector: + maxThreads: 200 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 200 resources: requests: cpu: 1 @@ -40,11 +70,11 @@ access: router: resources: requests: - cpu: "1" - memory: 1Gi - limits: - # cpu: "6" + cpu: "2" memory: 2Gi + limits: + # cpu: "12" + memory: 4Gi frontend: resources: @@ -56,6 +86,8 @@ frontend: memory: 1Gi metadata: + database: + maxOpenConnections: 200 resources: requests: cpu: "1" @@ -123,4 +155,4 @@ postgresql: cpu: "64" limits: memory: 256Gi - # cpu: "128" \ No newline at end of file + # cpu: "128" diff --git a/stable/artifactory/sizing/artifactory-large-extra-config.yaml b/stable/artifactory/sizing/artifactory-large-extra-config.yaml deleted file mode 100644 index d97a85c9f..000000000 --- a/stable/artifactory/sizing/artifactory-large-extra-config.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=65 - -Dartifactory.async.corePoolSize=80 - -Dartifactory.async.poolMaxQueueSize=20000 - -Dartifactory.http.client.max.total.connections=100 - -Dartifactory.http.client.max.connections.per.route=100 - -Dartifactory.access.client.max.connections=125 - -Dartifactory.metadata.event.operator.threads=4 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=524288 - -XX:MaxDirectMemorySize=512m - tomcat: - connector: - maxThreads: 500 - extraConfig: 'acceptCount="800" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 100 - -access: - tomcat: - connector: - maxThreads: 125 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 100 - -metadata: - database: - maxOpenConnections: 100 - diff --git a/stable/artifactory/sizing/artifactory-large.yaml b/stable/artifactory/sizing/artifactory-large.yaml index 80326a8e4..ec52b6077 100644 --- a/stable/artifactory/sizing/artifactory-large.yaml +++ b/stable/artifactory/sizing/artifactory-large.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The large sizing # This size is intended for large organizations. It can be increased with adding replicas or moving to the xlarge sizing -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: # Enterprise and above licenses are required for setting replicaCount greater than 1. @@ -20,15 +22,43 @@ artifactory: # cpu: "14" memory: 12Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=65 + -Dartifactory.async.corePoolSize=80 + -Dartifactory.async.poolMaxQueueSize=20000 + -Dartifactory.http.client.max.total.connections=100 + -Dartifactory.http.client.max.connections.per.route=100 + -Dartifactory.access.client.max.connections=125 + -Dartifactory.metadata.event.operator.threads=4 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=524288 + -XX:MaxDirectMemorySize=512m + tomcat: + connector: + maxThreads: 500 + extraConfig: 'acceptCount="800" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 100 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "8" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" access: + tomcat: + connector: + maxThreads: 125 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 100 resources: requests: cpu: 1 @@ -40,11 +70,11 @@ access: router: resources: requests: - cpu: 200m - memory: 400Mi + cpu: 400m + memory: 800Mi limits: - # cpu: "4" - memory: 1Gi + # cpu: "8" + memory: 2Gi frontend: resources: @@ -56,6 +86,8 @@ frontend: memory: 1Gi metadata: + database: + maxOpenConnections: 100 resources: requests: cpu: 200m diff --git a/stable/artifactory/sizing/artifactory-medium-extra-config.yaml b/stable/artifactory/sizing/artifactory-medium-extra-config.yaml deleted file mode 100644 index 1c294c043..000000000 --- a/stable/artifactory/sizing/artifactory-medium-extra-config.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=40 - -Dartifactory.async.poolMaxQueueSize=10000 - -Dartifactory.http.client.max.total.connections=50 - -Dartifactory.http.client.max.connections.per.route=50 - -Dartifactory.access.client.max.connections=75 - -Dartifactory.metadata.event.operator.threads=3 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=262144 - -XX:MaxDirectMemorySize=256m - tomcat: - connector: - maxThreads: 300 - extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 50 - -access: - tomcat: - connector: - maxThreads: 75 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 50 - -metadata: - database: - maxOpenConnections: 50 - diff --git a/stable/artifactory/sizing/artifactory-medium.yaml b/stable/artifactory/sizing/artifactory-medium.yaml index 8b7215041..16045600d 100644 --- a/stable/artifactory/sizing/artifactory-medium.yaml +++ b/stable/artifactory/sizing/artifactory-medium.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The medium sizing # This size is just 2 replicas of the small size. Vertical sizing of all services is not changed -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: # Enterprise and above licenses are required for setting replicaCount greater than 1. @@ -20,15 +22,43 @@ artifactory: # cpu: "10" memory: 5Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=40 + -Dartifactory.async.poolMaxQueueSize=10000 + -Dartifactory.http.client.max.total.connections=50 + -Dartifactory.http.client.max.connections.per.route=50 + -Dartifactory.access.client.max.connections=75 + -Dartifactory.metadata.event.operator.threads=3 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=262144 + -XX:MaxDirectMemorySize=256m + tomcat: + connector: + maxThreads: 300 + extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 50 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "2" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" access: + tomcat: + connector: + maxThreads: 75 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 50 resources: requests: cpu: 500m @@ -40,11 +70,11 @@ access: router: resources: requests: - cpu: 100m - memory: 250Mi - limits: - # cpu: "1" + cpu: 200m memory: 500Mi + limits: + # cpu: "2" + memory: 1Gi frontend: resources: @@ -56,6 +86,8 @@ frontend: memory: 250Mi metadata: + database: + maxOpenConnections: 50 resources: requests: cpu: 100m diff --git a/stable/artifactory/sizing/artifactory-small-extra-config.yaml b/stable/artifactory/sizing/artifactory-small-extra-config.yaml deleted file mode 100644 index 1c294c043..000000000 --- a/stable/artifactory/sizing/artifactory-small-extra-config.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=40 - -Dartifactory.async.poolMaxQueueSize=10000 - -Dartifactory.http.client.max.total.connections=50 - -Dartifactory.http.client.max.connections.per.route=50 - -Dartifactory.access.client.max.connections=75 - -Dartifactory.metadata.event.operator.threads=3 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=262144 - -XX:MaxDirectMemorySize=256m - tomcat: - connector: - maxThreads: 300 - extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 50 - -access: - tomcat: - connector: - maxThreads: 75 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 50 - -metadata: - database: - maxOpenConnections: 50 - diff --git a/stable/artifactory/sizing/artifactory-small.yaml b/stable/artifactory/sizing/artifactory-small.yaml index eb8d7239d..9593936e9 100644 --- a/stable/artifactory/sizing/artifactory-small.yaml +++ b/stable/artifactory/sizing/artifactory-small.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The small sizing # This is the size recommended for running Artifactory for small teams -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: # Enterprise and above licenses are required for setting replicaCount greater than 1. @@ -20,6 +22,27 @@ artifactory: # cpu: "10" memory: 5Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=40 + -Dartifactory.async.poolMaxQueueSize=10000 + -Dartifactory.http.client.max.total.connections=50 + -Dartifactory.http.client.max.connections.per.route=50 + -Dartifactory.access.client.max.connections=75 + -Dartifactory.metadata.event.operator.threads=3 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=262144 + -XX:MaxDirectMemorySize=256m + tomcat: + connector: + maxThreads: 300 + extraConfig: 'acceptCount="600" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 50 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "2" @@ -27,6 +50,15 @@ artifactory: value: "true" access: + tomcat: + connector: + maxThreads: 75 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 50 resources: requests: cpu: 500m @@ -38,11 +70,11 @@ access: router: resources: requests: - cpu: 100m - memory: 250Mi - limits: - # cpu: "1" + cpu: 200m memory: 500Mi + limits: + # cpu: "2" + memory: 1Gi frontend: resources: @@ -54,6 +86,8 @@ frontend: memory: 250Mi metadata: + database: + maxOpenConnections: 50 resources: requests: cpu: 100m diff --git a/stable/artifactory/sizing/artifactory-xlarge-extra-config.yaml b/stable/artifactory/sizing/artifactory-xlarge-extra-config.yaml deleted file mode 100644 index 00e6099f2..000000000 --- a/stable/artifactory/sizing/artifactory-xlarge-extra-config.yaml +++ /dev/null @@ -1,41 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=65 - -Dartifactory.async.corePoolSize=160 - -Dartifactory.async.poolMaxQueueSize=50000 - -Dartifactory.http.client.max.total.connections=150 - -Dartifactory.http.client.max.connections.per.route=150 - -Dartifactory.access.client.max.connections=150 - -Dartifactory.metadata.event.operator.threads=5 - -XX:MaxMetaspaceSize=512m - -Djdk.nio.maxCachedBufferSize=1048576 - -XX:MaxDirectMemorySize=1024m - tomcat: - connector: - maxThreads: 600 - extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 150 - -access: - tomcat: - connector: - maxThreads: 150 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 150 - -metadata: - database: - maxOpenConnections: 150 - diff --git a/stable/artifactory/sizing/artifactory-xlarge.yaml b/stable/artifactory/sizing/artifactory-xlarge.yaml index e77152ee1..92f9f317b 100644 --- a/stable/artifactory/sizing/artifactory-xlarge.yaml +++ b/stable/artifactory/sizing/artifactory-xlarge.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The xlarge sizing # This size is intended for very large organizations. It can be increased with adding replicas -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: # Enterprise and above licenses are required for setting replicaCount greater than 1. @@ -20,15 +22,43 @@ artifactory: # cpu: "14" memory: 16Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=65 + -Dartifactory.async.corePoolSize=160 + -Dartifactory.async.poolMaxQueueSize=50000 + -Dartifactory.http.client.max.total.connections=150 + -Dartifactory.http.client.max.connections.per.route=150 + -Dartifactory.access.client.max.connections=150 + -Dartifactory.metadata.event.operator.threads=5 + -XX:MaxMetaspaceSize=512m + -Djdk.nio.maxCachedBufferSize=1048576 + -XX:MaxDirectMemorySize=1024m + tomcat: + connector: + maxThreads: 600 + extraConfig: 'acceptCount="1200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 150 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "16" - - name : JF_SHARED_NODE_HAENABLED - value: "true" - name: SKIP_WAIT_FOR_EXTERNAL_DB value: "true" access: + tomcat: + connector: + maxThreads: 150 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 150 resources: requests: cpu: 500m @@ -40,11 +70,11 @@ access: router: resources: requests: - cpu: 200m - memory: 500Mi - limits: - # cpu: "4" + cpu: 400m memory: 1Gi + limits: + # cpu: "8" + memory: 2Gi frontend: resources: @@ -56,6 +86,8 @@ frontend: memory: 1Gi metadata: + database: + maxOpenConnections: 150 resources: requests: cpu: 200m diff --git a/stable/artifactory/sizing/artifactory-xsmall-extra-config.yaml b/stable/artifactory/sizing/artifactory-xsmall-extra-config.yaml deleted file mode 100644 index 39709b691..000000000 --- a/stable/artifactory/sizing/artifactory-xsmall-extra-config.yaml +++ /dev/null @@ -1,42 +0,0 @@ -#################################################################################### -# [WARNING] The configuration mentioned in this file are taken inside system.yaml -# hence this configuration will be overridden when enabling systemYamlOverride -#################################################################################### -artifactory: - javaOpts: - other: > - -XX:InitialRAMPercentage=40 - -XX:MaxRAMPercentage=70 - -Dartifactory.async.corePoolSize=10 - -Dartifactory.async.poolMaxQueueSize=2000 - -Dartifactory.http.client.max.total.connections=20 - -Dartifactory.http.client.max.connections.per.route=20 - -Dartifactory.access.client.max.connections=15 - -Dartifactory.metadata.event.operator.threads=2 - -XX:MaxMetaspaceSize=400m - -XX:CompressedClassSpaceSize=96m - -Djdk.nio.maxCachedBufferSize=131072 - -XX:MaxDirectMemorySize=128m - tomcat: - connector: - maxThreads: 50 - extraConfig: 'acceptCount="200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' - - database: - maxOpenConnections: 15 - -access: - tomcat: - connector: - maxThreads: 15 - javaOpts: - other: > - -XX:InitialRAMPercentage=20 - -XX:MaxRAMPercentage=60 - database: - maxOpenConnections: 15 - -metadata: - database: - maxOpenConnections: 15 - diff --git a/stable/artifactory/sizing/artifactory-xsmall.yaml b/stable/artifactory/sizing/artifactory-xsmall.yaml index 246f830a0..cc61f12e8 100644 --- a/stable/artifactory/sizing/artifactory-xsmall.yaml +++ b/stable/artifactory/sizing/artifactory-xsmall.yaml @@ -1,7 +1,9 @@ -############################################################## +############################################################################################## # The xsmall sizing # This is the minimum size recommended for running Artifactory -############################################################## +# [WARNING] Some of the the configuration mentioned in this file are taken inside system.yaml +# hence this configuration will be overridden when enabling systemYamlOverride +############################################################################################## splitServicesToContainers: true artifactory: # Enterprise and above licenses are required for setting replicaCount greater than 1. @@ -20,6 +22,28 @@ artifactory: # cpu: "10" memory: 4Gi + javaOpts: + other: > + -XX:InitialRAMPercentage=40 + -XX:MaxRAMPercentage=70 + -Dartifactory.async.corePoolSize=10 + -Dartifactory.async.poolMaxQueueSize=2000 + -Dartifactory.http.client.max.total.connections=20 + -Dartifactory.http.client.max.connections.per.route=20 + -Dartifactory.access.client.max.connections=15 + -Dartifactory.metadata.event.operator.threads=2 + -XX:MaxMetaspaceSize=400m + -XX:CompressedClassSpaceSize=96m + -Djdk.nio.maxCachedBufferSize=131072 + -XX:MaxDirectMemorySize=128m + tomcat: + connector: + maxThreads: 50 + extraConfig: 'acceptCount="200" acceptorThreadCount="2" compression="off" connectionLinger="-1" connectionTimeout="120000" enableLookups="false"' + + database: + maxOpenConnections: 15 + extraEnvironmentVariables: - name: MALLOC_ARENA_MAX value: "2" @@ -27,6 +51,15 @@ artifactory: value: "true" access: + tomcat: + connector: + maxThreads: 15 + javaOpts: + other: > + -XX:InitialRAMPercentage=20 + -XX:MaxRAMPercentage=60 + database: + maxOpenConnections: 15 resources: requests: cpu: 500m @@ -38,11 +71,11 @@ access: router: resources: requests: - cpu: 50m - memory: 100Mi + cpu: 100m + memory: 200Mi limits: - # cpu: "1" - memory: 500Mi + # cpu: "2" + memory: 1Gi frontend: resources: @@ -54,6 +87,8 @@ frontend: memory: 250Mi metadata: + database: + maxOpenConnections: 15 resources: requests: cpu: 50m diff --git a/stable/artifactory/templates/_helpers.tpl b/stable/artifactory/templates/_helpers.tpl index 7cea041f7..8e517e000 100644 --- a/stable/artifactory/templates/_helpers.tpl +++ b/stable/artifactory/templates/_helpers.tpl @@ -525,4 +525,20 @@ Resolve nginx hosts value {{- end -}} {{- end -}} {{- end -}} +{{- end -}} + +{{/* +Create a default fully qualified grpc ingress name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "artifactory.ingressGrpc.fullname" -}} +{{- printf "%s-%s" (include "artifactory.fullname" .) .Values.ingressGrpc.name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified grpc service name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "artifactory.serviceGrpc.fullname" -}} +{{- printf "%s-%s" (include "artifactory.fullname" .) .Values.artifactory.serviceGrpc.name | trunc 63 | trimSuffix "-" -}} {{- end -}} \ No newline at end of file diff --git a/stable/artifactory/templates/artifactory-license-secret.yaml b/stable/artifactory/templates/artifactory-license-secret.yaml index ba83aaf24..dda734033 100644 --- a/stable/artifactory/templates/artifactory-license-secret.yaml +++ b/stable/artifactory/templates/artifactory-license-secret.yaml @@ -1,4 +1,4 @@ -{{ if and (not .Values.artifactory.unifiedSecretInstallation) (not .Values.artifactory.license.secret) (not .Values.artifactory.license.licenseKey) }} +{{ if and (not .Values.artifactory.unifiedSecretInstallation) (not .Values.artifactory.license.secret) }} {{- with .Values.artifactory.license.licenseKey }} apiVersion: v1 kind: Secret diff --git a/stable/artifactory/templates/artifactory-service-grpc.yaml b/stable/artifactory/templates/artifactory-service-grpc.yaml new file mode 100644 index 000000000..b40e94c5f --- /dev/null +++ b/stable/artifactory/templates/artifactory-service-grpc.yaml @@ -0,0 +1,44 @@ +{{- if .Values.ingressGrpc.enabled -}} +# Service for GRPC communication. +apiVersion: v1 +kind: Service +metadata: + name: {{ template "artifactory.serviceGrpc.fullname" . }} + labels: + app: {{ template "artifactory.name" . }} + chart: {{ template "artifactory.chart" . }} + component: {{ .Values.artifactory.name }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + {{- with .Values.artifactory.labels }} +{{ toYaml . | indent 4 }} + {{- end }} +{{- if .Values.artifactory.serviceGrpc.annotations }} + annotations: +{{ toYaml .Values.artifactory.serviceGrpc.annotations | indent 4 }} +{{- end }} +spec: + {{- if .Values.artifactory.serviceGrpc.ipFamilyPolicy }} + ipFamilyPolicy: {{ .Values.artifactory.serviceGrpc.ipFamilyPolicy }} + {{- end }} + {{- if not (empty .Values.artifactory.serviceGrpc.ipFamilies)}} + ipFamilies: {{- toYaml .Values.artifactory.serviceGrpc.ipFamilies | nindent 4 }} + {{- end }} + type: {{ .Values.artifactory.serviceGrpc.type }} +{{- if .Values.artifactory.serviceGrpc.loadBalancerSourceRanges }} + loadBalancerSourceRanges: +{{ toYaml .Values.artifactory.serviceGrpc.loadBalancerSourceRanges | indent 4 }} +{{- end }} + ports: + - port: {{ .Values.artifactory.externalPort }} + targetPort: {{ .Values.artifactory.internalPort }} + {{- if .Values.artifactory.nodePort }} + nodePort: {{ .Values.artifactory.nodePort }} + {{- end }} + protocol: TCP + name: http-router + selector: + app: {{ template "artifactory.name" . }} + component: "{{ .Values.artifactory.name }}" + release: {{ .Release.Name }} +{{- end -}} \ No newline at end of file diff --git a/stable/artifactory/templates/artifactory-service.yaml b/stable/artifactory/templates/artifactory-service.yaml index ab8f9d6ce..c0558ba87 100644 --- a/stable/artifactory/templates/artifactory-service.yaml +++ b/stable/artifactory/templates/artifactory-service.yaml @@ -35,10 +35,12 @@ spec: {{- end }} protocol: TCP name: http-router + {{- if .Values.federation.enabled }} - port: {{ .Values.federation.internalPort }} targetPort: {{ .Values.federation.internalPort }} protocol: TCP name: http-rtfs + {{- end }} - port: {{ .Values.artifactory.externalArtifactoryPort }} targetPort: {{ .Values.artifactory.internalArtifactoryPort }} protocol: TCP diff --git a/stable/artifactory/templates/artifactory-statefulset.yaml b/stable/artifactory/templates/artifactory-statefulset.yaml index c149d86d6..718cd562e 100644 --- a/stable/artifactory/templates/artifactory-statefulset.yaml +++ b/stable/artifactory/templates/artifactory-statefulset.yaml @@ -204,6 +204,14 @@ spec: cp -fv /tmp/etc/tls.crt {{ .Values.artifactory.persistence.mountPath }}/bootstrap/etc/access/keys/ca.crt; cp -fv /tmp/etc/tls.key {{ .Values.artifactory.persistence.mountPath }}/bootstrap/etc/access/keys/ca.private.key; {{- end }} + {{- if .Values.jfconnect.customCertificatesSecretName }} + echo "Copying custom certificates to {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys"; + mkdir -p {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys; + cp -fv /tmp/etc/tls.crt {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + cp -fv /tmp/etc/tls.cer {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + cp -fv /tmp/etc/tls.pem {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + cp -fv /tmp/etc/tls.key {{ .Values.artifactory.persistence.mountPath }}/bootstrap/jfconnect/etc/keys/; + {{- end }} {{- if or .Values.artifactory.joinKey .Values.global.joinKey .Values.artifactory.joinKeySecretName .Values.global.joinKeySecretName }} echo "Copy joinKey to {{ .Values.artifactory.persistence.mountPath }}/bootstrap/access/etc/security"; mkdir -p {{ .Values.artifactory.persistence.mountPath }}/bootstrap/access/etc/security; @@ -299,6 +307,21 @@ spec: subPath: tls.key {{- end }} + {{- if .Values.jfconnect.customCertificatesSecretName }} + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.crt" + subPath: tls.crt + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.pem" + subPath: tls.pem + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.cer" + subPath: tls.cer + - name: jfconnect-certs + mountPath: "/tmp/etc/tls.key" + subPath: tls.key + {{- end }} + {{- if or .Values.artifactory.customCertificates.enabled .Values.global.customCertificates.enabled }} - name: copy-custom-certificates image: {{ include "artifactory.getImageInfoByValue" (list . "initContainers") }} @@ -526,9 +549,6 @@ spec: {{- with .Values.router.extraEnvironmentVariables }} {{ tpl (toYaml .) $ | indent 8 }} {{- end }} - ports: - - name: http - containerPort: {{ .Values.router.internalPort }} volumeMounts: - name: artifactory-volume mountPath: {{ .Values.router.persistence.mountPath | quote }} @@ -1011,9 +1031,11 @@ spec: {{- with .Values.federation.extraEnvironmentVariables }} {{ tpl (toYaml .) $ | indent 8 }} {{- end }} + {{- if .Values.federation.enabled }} ports: - containerPort: {{ .Values.federation.internalPort }} name: http-rtfs + {{- end }} volumeMounts: - name: artifactory-volume mountPath: {{ .Values.artifactory.persistence.mountPath | quote }} @@ -1216,8 +1238,10 @@ spec: name: http - containerPort: {{ .Values.artifactory.internalArtifactoryPort }} name: http-internal + {{- if .Values.federation.enabled }} - containerPort: {{ .Values.federation.internalPort }} name: http-rtfs + {{- end }} {{- if .Values.artifactory.javaOpts.jmx.enabled }} - containerPort: {{ .Values.artifactory.javaOpts.jmx.port }} name: tcp-jmx @@ -1370,6 +1394,10 @@ spec: - "-e" - "-E" - "http.enabled=true" + env: +{{- with .Values.filebeat.extraEnvironmentVariables }} +{{ tpl (toYaml .) $ | indent 10 }} +{{- end }} volumeMounts: - name: filebeat-config mountPath: /usr/share/filebeat/filebeat.yml @@ -1456,6 +1484,13 @@ spec: secretName: {{ .Values.access.customCertificatesSecretName }} {{- end }} + # jfconnect-certs secrets + {{- if .Values.jfconnect.customCertificatesSecretName }} + - name: jfconnect-certs + secret: + secretName: {{ .Values.jfconnect.customCertificatesSecretName }} + {{- end }} + # system yaml {{- if .Values.systemYamlOverride.existingSecret }} - name: systemyaml diff --git a/stable/artifactory/templates/ingress-grpc.yaml b/stable/artifactory/templates/ingress-grpc.yaml new file mode 100644 index 000000000..b68026297 --- /dev/null +++ b/stable/artifactory/templates/ingress-grpc.yaml @@ -0,0 +1,80 @@ +{{- if .Values.ingressGrpc.enabled -}} +{{- $serviceName := include "artifactory.serviceGrpc.fullname" . -}} +{{- $servicePort := .Values.artifactory.externalPort -}} +{{- $ingressName := include "artifactory.ingressGrpc.fullname" . -}} +{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }} +apiVersion: networking.k8s.io/v1 +{{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }} +apiVersion: networking.k8s.io/v1beta1 +{{- else }} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $ingressName }} + labels: + app: {{ template "artifactory.name" . }} + chart: {{ template "artifactory.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- if .Values.ingressGrpc.labels }} +{{ .Values.ingressGrpc.labels | toYaml | trimSuffix "\n"| indent 4 -}} +{{- end}} +{{- if .Values.ingressGrpc.annotations }} + annotations: +{{ .Values.ingressGrpc.annotations | toYaml | trimSuffix "\n" | indent 4 -}} +{{- end }} +spec: + {{- if and .Values.ingressGrpc.className (semverCompare ">=1.18.0-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingressGrpc.className }} + {{- end }} + {{- if .Values.ingressGrpc.defaultBackend.enabled }} + {{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }} + defaultBackend: + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- else }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} + rules: +{{- if .Values.ingressGrpc.hosts }} + {{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" }} + {{- range $host := .Values.ingressGrpc.hosts }} + - host: {{ $host | quote }} + http: + paths: + - path: {{ $.Values.ingressGrpc.grpcPath }} + pathType: ImplementationSpecific + backend: + service: + name: {{ $serviceName }} + port: + number: {{ $servicePort }} + {{- end }} + {{- else }} + {{- range $host := .Values.ingressGrpc.hosts }} + - host: {{ $host | quote }} + http: + paths: + - path: {{ $.Values.ingressGrpc.grpcPath }} + backend: + serviceName: {{ $serviceName }} + servicePort: {{ $servicePort }} + {{- end }} + {{- end }} +{{- end -}} + {{- with .Values.ingressGrpc.additionalRules }} +{{ tpl . $ | indent 2 }} + {{- end }} + + {{- if .Values.ingressGrpc.tls }} + tls: +{{ toYaml .Values.ingressGrpc.tls | indent 4 }} + {{- end -}} + +{{- end -}} diff --git a/stable/artifactory/templates/nginx-service.yaml b/stable/artifactory/templates/nginx-service.yaml index 7204d9f46..29fb9132d 100644 --- a/stable/artifactory/templates/nginx-service.yaml +++ b/stable/artifactory/templates/nginx-service.yaml @@ -58,7 +58,7 @@ spec: {{- if .Values.nginx.https }} {{- if or .Values.nginx.https.enabled .Values.nginx.service.ssloffload }} - port: {{ .Values.nginx.https.externalPort }} - {{- if .Values.nginx.service.ssloffload }} + {{- if and .Values.nginx.service.ssloffload (not .Values.nginx.service.ssloffloadForceHttps) }} targetPort: {{ .Values.nginx.http.internalPort }} {{- else }} targetPort: {{ .Values.nginx.https.internalPort}} diff --git a/stable/artifactory/values.yaml b/stable/artifactory/values.yaml index 669769ca5..98817a91c 100644 --- a/stable/artifactory/values.yaml +++ b/stable/artifactory/values.yaml @@ -47,7 +47,7 @@ initContainers: image: registry: releases-docker.jfrog.io repository: ubi9/ubi-minimal - tag: 9.4.949.1716471857 + tag: 9.4.1227 pullPolicy: IfNotPresent resources: requests: @@ -117,7 +117,6 @@ ingress: rtfsPath: /artifactory/service/rtfs/ className: "" annotations: {} - # kubernetes.io/ingress.class: nginx # nginx.ingress.kubernetes.io/configuration-snippet: | # proxy_pass_header Server; # proxy_set_header X-JFrog-Override-Base-Url https://; @@ -138,6 +137,37 @@ ingress: disableRouterBypass: false ## Allows to add custom ingress customIngress: "" +## There is a need to separate HTTP1.1 traffic from gRPC (HTTP2) to benefit +## 1. Use the Nginx keepalive for HTTP1.1 +## 2. Keep gRPC over the HTTP2 connections only +ingressGrpc: + enabled: false + name: grpc + defaultBackend: + enabled: true + ## Used to create an Ingress record. + hosts: [] + grpcPath: /com.jfrog + className: "" + ## For supporting GRPC protocol traffic sent to the backend it is necessary to change the backend protocol + ## Example: nginx.ingress.kubernetes.io/backend-protocol: GRPCS + annotations: {} + # nginx.ingress.kubernetes.io/configuration-snippet: | + # proxy_pass_header Server; + # proxy_set_header X-JFrog-Override-Base-Url https://; + # kubernetes.io/tls-acme: "true" + # nginx.ingress.kubernetes.io/proxy-body-size: "0" + labels: {} + # traffic-type: external + # traffic-type: internal + tls: [] + ## Secrets must be manually created in the namespace. + # - secretName: chart-example-tls + # hosts: + # - artifactory.domain.example + + ## Additional ingress rules + additionalRules: [] networkpolicy: [] ## Allows all ingress and egress # - name: artifactory @@ -198,7 +228,7 @@ router: image: registry: releases-docker.jfrog.io repository: jfrog/router - tag: 7.118.3 + tag: 7.135.1 pullPolicy: IfNotPresent serviceRegistry: ## Service registry (Access) TLS verification skipped if enabled @@ -357,6 +387,10 @@ artifactory: ## Refer - https://jfrog.com/help/r/jfrog-platform-administration-documentation/setting-up-cold-artifact-storage coldStorage: enabled: false + ## Support for workers + ## set 'worker.enabled' to 'true' to enable artifactory addon that executes workers on artifactory events + worker: + enabled: false ## This directory is intended for use with NFS eventual configuration for HA haDataDir: enabled: false @@ -654,6 +688,28 @@ artifactory: annotations: {} ## If the type is NodePort you can set a fixed port # nodePort: 32082 + serviceGrpc: + name: grpc + type: ClusterIP + ## @param service.ipFamilyPolicy Controller Service ipFamilyPolicy (optional, cloud specific) + ## This can be either SingleStack, PreferDualStack or RequireDualStack + ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ## + ipFamilyPolicy: "" + ## @param service.ipFamilies Controller Service ipFamilies (optional, cloud specific) + ## This can be either ["IPv4"], ["IPv6"], ["IPv4", "IPv6"] or ["IPv6", "IPv4"] + ## ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services + ## + ipFamilies: [] + ## For supporting whitelist on the Artifactory service (useful if setting service.type=LoadBalancer) + ## Set this to a list of IP CIDR ranges + ## Example: loadBalancerSourceRanges: ['10.10.10.5/32', '10.11.10.5/32'] + ## or pass from helm command line + ## Example: helm install ... --set nginx.service.loadBalancerSourceRanges='{10.10.10.5/32,10.11.10.5/32}' + loadBalancerSourceRanges: [] + annotations: {} + ## If the type is NodePort you can set a fixed port + # nodePort: 32082 statefulset: annotations: {} ## IMPORTANT: If overriding artifactory.internalPort: @@ -811,6 +867,7 @@ artifactory: bucketExists: false useInstanceCredentials: false enableSignedUrlRedirect: false + # signedUrlExpirySeconds: false ## For artifactory.persistence.type aws-s3-v3, s3-storage-v3-direct, cluster-s3-storage-v3, s3-storage-v3-archive awsS3V3: testConnection: false @@ -1224,6 +1281,10 @@ jfconnect: # exec: # command: ["/bin/sh","-c","echo Hello from the preStop handler"] + ## You can use a pre-existing secret by specifying customCertificatesSecretName + ## Example : Create a tls secret using `kubectl create secret tls --cert=tls.crt --key=tls.key` + # customCertificatesSecretName: + ## The following settings are to configure the frequency of the liveness and startup probes when splitServicesToContainers set to true livenessProbe: enabled: true @@ -1464,131 +1525,6 @@ nginx: ## The nginx main conf was moved to files/nginx-main-conf.yaml. This key is commented out to keep support for the old configuration # mainConf: | - {{- if .Values.nginx.logs.stdout }} - access_log /dev/stdout timing; - {{- else -}} - access_log {{ .Values.nginx.persistence.mountPath }}/logs/access.log timing; - {{- end }} - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - include /etc/nginx/conf.d/*.conf; - - } - artifactoryConf: | - {{- if .Values.nginx.https.enabled }} - ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; - ssl_certificate {{ .Values.nginx.persistence.mountPath }}/ssl/tls.crt; - ssl_certificate_key {{ .Values.nginx.persistence.mountPath }}/ssl/tls.key; - ssl_session_cache shared:SSL:1m; - ssl_prefer_server_ciphers on; - {{- end }} - ## server configuration - server { - {{- if .Values.nginx.internalPortHttps }} - {{- if .Values.nginx.singleStackIPv6Cluster }} - listen [::]:{{ .Values.nginx.internalPortHttps }} ssl; - {{- else -}} - listen {{ .Values.nginx.internalPortHttps }} ssl; - {{- end }} - {{- else -}} - {{- if .Values.nginx.https.enabled }} - {{- if .Values.nginx.singleStackIPv6Cluster }} - listen [::]:{{ .Values.nginx.https.internalPort }} ssl; - {{- else -}} - listen {{ .Values.nginx.https.internalPort }} ssl; - {{- end }} - {{- end }} - {{- end }} - {{- if .Values.nginx.internalPortHttp }} - {{- if .Values.nginx.singleStackIPv6Cluster }} - listen [::]:{{ .Values.nginx.internalPortHttp }}; - {{- else -}} - listen {{ .Values.nginx.internalPortHttp }}; - {{- end }} - {{- else -}} - {{- if .Values.nginx.http.enabled }} - {{- if .Values.nginx.singleStackIPv6Cluster }} - listen [::]:{{ .Values.nginx.http.internalPort }}; - {{- else -}} - listen {{ .Values.nginx.http.internalPort }}; - {{- end }} - {{- end }} - {{- end }} - server_name ~(?.+)\.{{ include "artifactory.fullname" . }} {{ include "artifactory.fullname" . }} - {{- range .Values.ingress.hosts -}} - {{- if contains "." . -}} - {{ "" | indent 0 }} ~(?.+)\.{{ . }} - {{- end -}} - {{- end -}}; - - if ($http_x_forwarded_proto = '') { - set $http_x_forwarded_proto $scheme; - } - set $host_port {{ .Values.nginx.https.externalPort }}; - if ( $scheme = "http" ) { - set $host_port {{ .Values.nginx.http.externalPort }}; - } - ## Application specific logs - ## access_log /var/log/nginx/artifactory-access.log timing; - ## error_log /var/log/nginx/artifactory-error.log; - rewrite ^/artifactory/?$ / redirect; - if ( $repo != "" ) { - rewrite ^/(v1|v2)/(.*) /artifactory/api/docker/$repo/$1/$2 break; - } - chunked_transfer_encoding on; - client_max_body_size 0; - - location / { - proxy_read_timeout 900; - proxy_pass_header Server; - proxy_cookie_path ~*^/.* /; - proxy_pass {{ include "artifactory.scheme" . }}://{{ include "artifactory.fullname" . }}:{{ .Values.artifactory.externalPort }}/; - {{- if .Values.nginx.service.ssloffload}} - {{- if .Values.nginx.service.ssloffloadForceHttps}} - proxy_set_header X-JFrog-Override-Base-Url https://$host; - proxy_set_header X-Forwarded-Proto https; - {{- else }} - proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host; - proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; - {{- end }} - {{- else }} - proxy_set_header X-JFrog-Override-Base-Url $http_x_forwarded_proto://$host:$host_port; - proxy_set_header X-Forwarded-Port $server_port; - proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; - {{- end }} - proxy_set_header Host $http_host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - {{- if .Values.nginx.disableProxyBuffering}} - proxy_http_version 1.1; - proxy_request_buffering off; - proxy_buffering off; - {{- end }} - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - location /artifactory/ { - if ( $request_uri ~ ^/artifactory/(.*)$ ) { - proxy_pass http://{{ include "artifactory.fullname" . }}:{{ .Values.artifactory.externalArtifactoryPort }}/artifactory/$1; - } - proxy_pass http://{{ include "artifactory.fullname" . }}:{{ .Values.artifactory.externalArtifactoryPort }}/artifactory/; - } - location /pipelines/ { - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $http_host; - {{- if .Values.router.tlsEnabled }} - proxy_pass https://{{ include "artifactory.fullname" . }}:{{ .Values.router.internalPort }}; - {{- else }} - proxy_pass http://{{ include "artifactory.fullname" . }}:{{ .Values.router.internalPort }}; - {{- end }} - } - } - } ## The nginx artifactory conf was moved to files/nginx-artifactory-conf.yaml. This key is commented out to keep support for the old configuration # artifactoryConf: | customInitContainers: "" @@ -1603,7 +1539,9 @@ nginx: ## For minikube, set this to NodePort, elsewhere use LoadBalancer type: LoadBalancer ssloffload: false - ## @param service.ssloffloadForceHttps Override http_x_forwarded_proto flag for external ingress (optional, likely OpenShift specific for ClusterIP based nginx service config) + ## @param service.ssloffloadForceHttps Only enabled when service.ssloffload is set to True. + ## Force all requests from NGINX to the upstream server are over HTTPS, even when SSL offloading is enabled. + ## This is useful in environments where internal traffic must remain secure with https only. ssloffloadForceHttps: false ## @param service.ipFamilyPolicy Controller Service ipFamilyPolicy (optional, cloud specific) ## This can be either SingleStack, PreferDualStack or RequireDualStack @@ -1852,6 +1790,9 @@ filebeat: output: logstash: hosts: ["{{ .Values.filebeat.logstashUrl }}"] + extraEnvironmentVariables: {} + # - name: MY_ENV_VAR + # value: "s" ## Allows to add additional kubernetes resources ## Use --- as a separator between multiple resources ## For an example, refer - https://github.com/jfrog/log-analytics-prometheus/blob/master/helm/artifactory-values.yaml From b22b3dfb141b15c20ed98a93e9bc90fe00e3cfa6 Mon Sep 17 00:00:00 2001 From: amithk Date: Wed, 30 Oct 2024 14:10:35 +0530 Subject: [PATCH 7/9] [distribution] 2.27.2 release --- stable/distribution/CHANGELOG.md | 7 ++++++- stable/distribution/Chart.yaml | 4 ++-- stable/distribution/README.md | 2 +- .../distribution/logo/distribution-logo.png | Bin 7743 -> 75397 bytes ...ion-large.yaml => distribution-large.yaml} | 0 ...n-medium.yaml => distribution-medium.yaml} | 0 stable/distribution/templates/_helpers.tpl | 8 ++++++++ .../templates/distribution-statefulset.yaml | 1 + stable/distribution/values.yaml | 6 +++--- 9 files changed, 21 insertions(+), 7 deletions(-) rename stable/distribution/sizing/{distrubution-large.yaml => distribution-large.yaml} (100%) rename stable/distribution/sizing/{distrubution-medium.yaml => distribution-medium.yaml} (100%) diff --git a/stable/distribution/CHANGELOG.md b/stable/distribution/CHANGELOG.md index 83a4cc913..d00b48ff5 100644 --- a/stable/distribution/CHANGELOG.md +++ b/stable/distribution/CHANGELOG.md @@ -1,8 +1,13 @@ # JFrog Distribution Chart Changelog All changes to this project chart be documented in this file. -## [102.26.1] - May 29, 2024 +## [102.27.2] - Oct 02, 2024 +* Adding distribution service with http-router port [GH-1872](https://github.com/jfrog/charts/pull/1872) + +## [102.26.1] - June 20, 2024 * Fix the indentation of the commented-out sections in the values.yaml file +* Fixed #adding colon in image registry which breaks deployment [GH-1892](https://github.com/jfrog/charts/pull/1892) +* Fixed sizing file names ## [102.25.0] - May 16, 2024 * Update postgresql tag version to `15.6.0-debian-12-r5` diff --git a/stable/distribution/Chart.yaml b/stable/distribution/Chart.yaml index 748544019..683fbe727 100644 --- a/stable/distribution/Chart.yaml +++ b/stable/distribution/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 2.26.1 +appVersion: 2.27.2 dependencies: - condition: postgresql.enabled name: postgresql @@ -19,4 +19,4 @@ name: distribution sources: - https://github.com/jfrog/charts type: application -version: 102.26.1 +version: 102.27.2 diff --git a/stable/distribution/README.md b/stable/distribution/README.md index dfede37f5..ece79d4f3 100644 --- a/stable/distribution/README.md +++ b/stable/distribution/README.md @@ -1,6 +1,6 @@ # JFrog Distribution Helm Chart -**IMPORTANT!** Our Helm Chart docs have moved to our main documentation site. Below you will find the basic instructions for installing Distribution. For all other information, refer to [Installing Distribution](https://www.jfrog.com/confluence/display/JFROG/Installing+Distribution). +**IMPORTANT!** Our Helm Chart docs have moved to our main documentation site. Below you will find the basic instructions for installing Distribution. For all other information, refer to [Installing Distribution](https://jfrog.com/help/r/jfrog-installation-setup-documentation/installing-distribution). ## Prerequisites Details * Kubernetes 1.19+ diff --git a/stable/distribution/logo/distribution-logo.png b/stable/distribution/logo/distribution-logo.png index e0aa134d6b7e53ca5f027c67070553d7dd236f23..315f5c1dd4e96d4736f3d7ae82a2686b89dbc8c3 100644 GIT binary patch literal 75397 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 W5t8-R+uAIGKh6ER`x5tB-1r~Acf_y& literal 7743 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 Date: Wed, 30 Oct 2024 14:13:55 +0530 Subject: [PATCH 8/9] [worker] 1.95.1 release --- stable/worker/CHANGELOG.md | 44 ++ stable/worker/Chart.lock | 6 + stable/worker/Chart.yaml | 10 + stable/worker/ci/custom-probes-values.yaml | 85 +++ stable/worker/ci/default-values.yaml | 2 + stable/worker/ci/global-section-values.yaml | 110 +++ stable/worker/ci/keda-values.yaml | 4 + stable/worker/ci/loggers-values.yaml | 25 + stable/worker/ci/test-values.yaml | 627 ++++++++++++++++ stable/worker/files/system.yaml | 143 ++++ stable/worker/templates/NOTES.txt | 22 + stable/worker/templates/_helpers.tpl | 238 +++++++ .../worker/templates/_system-yaml-render.tpl | 5 + stable/worker/templates/deployment.yaml | 426 +++++++++++ .../worker/templates/filebeat-configmap.yaml | 14 + stable/worker/templates/hpa.yaml | 34 + stable/worker/templates/ingress.yaml | 42 ++ stable/worker/templates/kedascaledobject.yaml | 47 ++ stable/worker/templates/logger-configmap.yaml | 63 ++ stable/worker/templates/secrets.yaml | 27 + stable/worker/templates/service.yaml | 29 + stable/worker/templates/serviceaccount.yaml | 15 + stable/worker/templates/servicemonitor.yaml | 56 ++ stable/worker/templates/system-yaml.yaml | 19 + .../worker/templates/worker-configmaps.yaml | 13 + stable/worker/values.yaml | 669 ++++++++++++++++++ 26 files changed, 2775 insertions(+) create mode 100644 stable/worker/CHANGELOG.md create mode 100644 stable/worker/Chart.lock create mode 100644 stable/worker/Chart.yaml create mode 100644 stable/worker/ci/custom-probes-values.yaml create mode 100644 stable/worker/ci/default-values.yaml create mode 100644 stable/worker/ci/global-section-values.yaml create mode 100644 stable/worker/ci/keda-values.yaml create mode 100644 stable/worker/ci/loggers-values.yaml create mode 100644 stable/worker/ci/test-values.yaml create mode 100644 stable/worker/files/system.yaml create mode 100644 stable/worker/templates/NOTES.txt create mode 100644 stable/worker/templates/_helpers.tpl create mode 100644 stable/worker/templates/_system-yaml-render.tpl create mode 100644 stable/worker/templates/deployment.yaml create mode 100644 stable/worker/templates/filebeat-configmap.yaml create mode 100644 stable/worker/templates/hpa.yaml create mode 100644 stable/worker/templates/ingress.yaml create mode 100644 stable/worker/templates/kedascaledobject.yaml create mode 100644 stable/worker/templates/logger-configmap.yaml create mode 100644 stable/worker/templates/secrets.yaml create mode 100644 stable/worker/templates/service.yaml create mode 100644 stable/worker/templates/serviceaccount.yaml create mode 100644 stable/worker/templates/servicemonitor.yaml create mode 100644 stable/worker/templates/system-yaml.yaml create mode 100644 stable/worker/templates/worker-configmaps.yaml create mode 100644 stable/worker/values.yaml diff --git a/stable/worker/CHANGELOG.md b/stable/worker/CHANGELOG.md new file mode 100644 index 000000000..0e18c12a6 --- /dev/null +++ b/stable/worker/CHANGELOG.md @@ -0,0 +1,44 @@ +# JFrog Worker Chart Changelog +All changes to this chart will be documented in this file + +## [101.95.1] - Sep 27, 2024 +* Upgraded Observability version to 1.31.4 + +## [101.89.0] - Sep 02, 2024 +* Added ability to provide `extraSystemYaml` configuration in values.yaml which will merge with the existing system yaml when `systemYamlOverride` is not given + +## [101.86.0] - Aug 28, 2024 +* Adjusted deployment for self-hosted release + +## [101.42.0] - Dec 15, 2023 +* Changed service monitor selector + +## [101.29.0] - Sep 05, 2023 +* Changed service monitor name and namespace + +## [101.13.0] - May 03, 2023 +* Adjusted KEDA autoscaling parameters + +## [101.12.0] - April 27, 2023 +* Removed busybox dependency +* Updated jfrog-common dep to `0.0.6` + +## [101.5.0] - March 6, 2023 +* Adjusted KEDA autoscaling parameters + +## [101.4.0] - February 21, 2023 +* Adjusted paths to new Worker service Docker base image +* Updated initContainers image to ubi9/ubi-minimal:9.1.0.1760 + +## [101.3.0] - February 15, 2023 +* Aligned pod labels and annotations with other deployments + +## [101.0.0] - January 17, 2023 +* Renamed service and chart from Platform Extension to Worker + +## [101.1.0] - January 06, 2023 +* Refactored helm chart +* Added support for providing system.yaml configuration for containers in values.yaml + +## [101.0.0] - January 03, 2023 +* Initial release \ No newline at end of file diff --git a/stable/worker/Chart.lock b/stable/worker/Chart.lock new file mode 100644 index 000000000..98d4b200d --- /dev/null +++ b/stable/worker/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: jfrog-common + repository: https://charts.jfrog.io/ + version: 0.0.8 +digest: sha256:b2b072c3bbd0f031b8ee3abfbbad770ed3fc8f38ad3a87238639a5b4a1f9341c +generated: "2024-07-25T00:08:46.576137295Z" diff --git a/stable/worker/Chart.yaml b/stable/worker/Chart.yaml new file mode 100644 index 000000000..e2a3ecb6c --- /dev/null +++ b/stable/worker/Chart.yaml @@ -0,0 +1,10 @@ +apiVersion: v2 +appVersion: 1.95.1 +dependencies: +- name: jfrog-common + repository: https://charts.jfrog.io/ + version: 0.0.8 +description: A Helm chart for Kubernetes +name: worker +type: application +version: 101.95.1 diff --git a/stable/worker/ci/custom-probes-values.yaml b/stable/worker/ci/custom-probes-values.yaml new file mode 100644 index 000000000..1c8d47293 --- /dev/null +++ b/stable/worker/ci/custom-probes-values.yaml @@ -0,0 +1,85 @@ +## Artifactory URL. Mandatory +jfrogUrl: "http://artifactory-local:8082" + +router: + customLivenessProbe: + exec: + command: + - sh + - -c + - curl -s -k --fail --max-time 120 http://localhost:8046/router/api/v1/system/liveness + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 120 + failureThreshold: 10 + successThreshold: 1 + + customReadinessProbe: + exec: + command: + - sh + - -c + - curl -s -k --fail --max-time 120 http://localhost:8046/router/api/v1/system/readiness + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 120 + failureThreshold: 10 + successThreshold: 1 + + customStartupProbe: + exec: + command: + - sh + - -c + - curl -s -k --fail --max-time 120 http://localhost:8046/router/api/v1/system/readiness + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 120 + failureThreshold: 10 + successThreshold: 1 + +## Worker custom liveness probe configuration +customLivenessProbe: + httpGet: + path: /api/v1/system/liveness + port: 8098 + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 120 + failureThreshold: 10 + successThreshold: 1 + +## Worker custom readiness probe configuration +customReadinessProbe: + httpGet: + path: /api/v1/system/readiness + port: 8098 + initialDelaySeconds: 0 + periodSeconds: 5 + timeoutSeconds: 120 + failureThreshold: 10 + successThreshold: 1 + +observability: + customLivenessProbe: + exec: + command: + - sh + - -c + - curl --fail --max-time 120 http://localhost:8036/api/v1/system/liveness + initialDelaySeconds: 0 + failureThreshold: 5 + timeoutSeconds: 120 + periodSeconds: 10 + successThreshold: 1 + + customStartupProbe: + exec: + command: + - sh + - -c + - curl --fail --max-time 120 http://localhost:8036/api/v1/system/readiness + initialDelaySeconds: 30 + failureThreshold: 90 + periodSeconds: 5 + timeoutSeconds: 120 diff --git a/stable/worker/ci/default-values.yaml b/stable/worker/ci/default-values.yaml new file mode 100644 index 000000000..7c75015e9 --- /dev/null +++ b/stable/worker/ci/default-values.yaml @@ -0,0 +1,2 @@ +# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml. +jfrogUrl: "http://artifactory-local:8082" diff --git a/stable/worker/ci/global-section-values.yaml b/stable/worker/ci/global-section-values.yaml new file mode 100644 index 000000000..f232a5433 --- /dev/null +++ b/stable/worker/ci/global-section-values.yaml @@ -0,0 +1,110 @@ +requests: + memory: "1Gi" + cpu: "1" +limits: + memory: "3Gi" + cpu: "2" +autoscaling: + kind: "hpa" +global: + masterKey: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB + joinKey: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE + jfrogUrl: "http://artifactory-local:8082" + versions: + worker: 1.77.0 + customVolumes: | + - name: custom-volume-global + emptyDir: + sizeLimit: 100Mi + customVolumeMounts: | + - name: custom-volume-global + mountPath: "/scriptsglobal" + customInitContainers: | + - name: "custom-init-global" + image: {{ template "initContainers.image" $ }} + imagePullPolicy: {{ $.Values.initContainers.image.pullPolicy | quote }} + command: + - 'sh' + - '-c' + - 'touch /opt/jfrog/worker/var/init-global' + volumeMounts: + - mountPath: "/opt/jfrog/worker/var" + name: data + customSidecarContainers: | + - name: "sidecar-list-global" + image: {{ template "initContainers.image" $ }} + imagePullPolicy: {{ $.Values.initContainers.image.pullPolicy | quote }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - NET_RAW + command: ["sh","-c","echo 'Sidecar is running in global' >> /scriptsglobal/sidecar.txt; cat /scriptsglobal/sidecar.txt; while true; do sleep 30; done"] + volumeMounts: + - mountPath: "/scriptsglobal" + name: custom-volume-global + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "100m" + +common: + customVolumes: | + - name: custom-volume-local + emptyDir: + sizeLimit: 100Mi + customVolumeMounts: | + - name: custom-volume-local + mountPath: "/scriptslocal" + customInitContainers: | + - name: "custom-init-local" + image: {{ template "initContainers.image" $ }} + imagePullPolicy: {{ $.Values.initContainers.image.pullPolicy | quote }} + command: + - 'sh' + - '-c' + - 'touch /opt/jfrog/worker/var/init-local' + volumeMounts: + - mountPath: "/opt/jfrog/worker/var" + name: data + customSidecarContainers: | + - name: "sidecar-list-local" + image: {{ template "initContainers.image" $ }} + imagePullPolicy: {{ $.Values.initContainers.image.pullPolicy | quote }} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - NET_RAW + command: ["sh","-c","echo 'Sidecar is running in local' >> /scriptslocal/sidecar.txt; cat /scriptslocal/sidecar.txt; while true; do sleep 30; done"] + volumeMounts: + - mountPath: "/scriptslocal" + name: custom-volume-local + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "100m" + +router: + resources: + requests: + memory: "100Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "1" + +observability: + resources: + requests: + memory: "100Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "1" diff --git a/stable/worker/ci/keda-values.yaml b/stable/worker/ci/keda-values.yaml new file mode 100644 index 000000000..9d2f92c6f --- /dev/null +++ b/stable/worker/ci/keda-values.yaml @@ -0,0 +1,4 @@ +autoscaling: + enabled: true + kind: "keda" +jfrogUrl: "http://artifactory-local:8082" diff --git a/stable/worker/ci/loggers-values.yaml b/stable/worker/ci/loggers-values.yaml new file mode 100644 index 000000000..10c72d6ea --- /dev/null +++ b/stable/worker/ci/loggers-values.yaml @@ -0,0 +1,25 @@ +jfrogUrl: "http://artifactory-local:8082" +loggers: + - router-request.log + - router-service.log + - router-traefik.log + - worker-service.log + - worker-request.log + +router: + resources: + requests: + memory: "100Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "1" + +observability: + resources: + requests: + memory: "100Mi" + cpu: "100m" + limits: + memory: "1Gi" + cpu: "1" diff --git a/stable/worker/ci/test-values.yaml b/stable/worker/ci/test-values.yaml new file mode 100644 index 000000000..8665604cb --- /dev/null +++ b/stable/worker/ci/test-values.yaml @@ -0,0 +1,627 @@ +# Default values for worker. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + # imageRegistry: "" + imagePullSecrets: + - regcred + + ## Worker service requires a unique master key. + ## You can generate one with the command: "openssl rand -hex 32" + ## An initial one is auto generated on first startup. + # masterKey: "" + + ## Alternatively, you can use a pre-existing secret with a key + ## called "master-key" by specifying "masterKeySecretName" + # masterKeySecretName: "" + + ## Join Key to connect other services to Artifactory + ## IMPORTANT: Setting this value overrides the existing joinKey + joinKey: "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE" + + ## Alternatively, you can use a pre-existing secret with a key + ## called "join-key" by specifying "joinKeySecretName" + masterKey: "1111111111111111111111111111111111111111111111111111111111111111" + + ## Note: tags customInitContainers,customVolumes,customVolumeMounts,customSidecarContainers can be used both from global and application level simultaneously + # customVolumes: | + + # customVolumeMounts: | + + # customInitContainers: | + + # customSidecarContainers: | + + ## certificates added to this secret will be copied to $JFROG_HOME/worker/var/data/router/keys/trusted directory + # customCertificates: + # enabled: false + # certificateSecretName: + + ## Applies to Worker pods + nodeSelector: + kubernetes.io/hostname: kind-singletenant-control-plane + +jfrogUrl: "http://artifactory-local:8082" + +## Number of replicas used when autoscaling is disabled +replicaCount: 1 + +## Worker image +image: + registry: entplus.jfrog.io + pullSecrets: + - "regcred" + repository: dev-feature-wks-1019-docker-virtual/jfrog/worker + tag: feature-WKS-1019-13 + # pullPolicy: IfNotPresent + +## String to partially override worker.name template (will maintain the release name) +nameOverride: "workername" +## String to fully override worker.fullname template +fullnameOverride: "workerfullname" + +## Specify common probes parameters +probes: + timeoutSeconds: 110 + +## Service Account +## Ref: https://kubernetes.io/docs/admin/service-accounts-admin/ +## +serviceAccount: + # Specifies whether a service account should be created + create: false + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +## Annotations added to Worker pods +podAnnotations: + custom: myworker + +## Disable podSecurityContext for openshift +podSecurityContext: + enabled: true + fsGroup: 1131 + runAsUser: 1131 + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## Disable securityContext for openshift +securityContext: + enabled: true + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: + - NET_RAW + +## Set sleep in order to keep service responding while k8s is removing it from network +lifecycle: + preStopSleepSeconds: 5 + +## Worker service configuration +service: + type: ClusterIP + port: 8098 + grpcPort: 8099 + nodePort: 30000 + productHome: /opt/jfrog/worker + +## Worker service ingress configuration +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + grpcReadTimeout: 43200s + grpcSendTimeout: 43200s + clientBodyTimeout: 43200s + +## Worker container resources +resources: + limits: + cpu: 1 + memory: 512Mi + requests: + cpu: 100m + memory: 512Mi + +## Autoscaling configuration for Worker deployment +autoscaling: + ## Enable autoscaling for Worker deployment + enabled: false + ## Type of autoscaler. Possible values: + ## - "keda" + ## ref: https://keda.sh/ + ## - "hpa" + ## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ + kind: "keda" + minReplicas: 1 + maxReplicas: 10 + pollingInterval: 30 + cooldownPeriod: 300 + # targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + keda: + threshold: '3' + query: sum(avg_over_time(jfwks_execution_processing_count{service="{{ .Release.Name }}", namespace="{{ .Release.Namespace }}"}[1m])) + metricType: AverageValue + +## @param serviceMonitor Declaratively specifies how groups of Kubernetes services should be monitored. +## Ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md +serviceMonitor: + targetPort: 8082 + enabled: false + interval: 60s + scrapeTimeout: 15s + kubePromApp: "" + kubePromFullName: "" + namespaceSelector: + any: true + +## Applies to worker pods +# nodeSelector: {} + +## Applies to worker pods +# tolerations: [] + +## Applies to worker pods +# affinity: {} + +## Extra environment variables that can be used to tune worker service to your needs. +## Uncomment and set value as needed +extraEnvironmentVariables: + - name: MY_ENV_VAR + value: "4" + + +router: + name: router + image: + registry: entplus.jfrog.io + repository: jfrog-docker/jfrog/router + tag: 7.118.0 + # imagePullPolicy: IfNotPresent + serviceRegistry: + ## Service registry (Access) TLS verification skipped if enabled + insecure: true + url: http://tenant1-artifactory:8082 + grpcUrl: tenant1-artifactory:8082 + internalPort: 8046 + externalPort: 8082 + tlsEnabled: false + + ## Extra environment variables that can be used to tune router to your needs. + ## Uncomment and set value as needed + extraEnvironmentVariables: + - name: MY_ENV_VAR + value: "5" + + # resources: + # requests: {} + # memory: "100Mi" + # cpu: "100m" + # limits: {} + # memory: "1Gi" + # cpu: "1" + + ## Add custom volumesMounts + customVolumeMounts: | + - name: custom-script + mountPath: /scripts/router-script.sh + subPath: script.sh + + livenessProbe: + enabled: true + config: | + exec: + command: + - sh + - -c + - curl -s -k --fail --max-time {{ .Values.probes.timeoutSeconds }} {{ include "worker.scheme" . }}://localhost:{{ .Values.router.internalPort }}/router/api/v1/system/liveness + initialDelaySeconds: {{ if semverCompare "/systemyaml' + volumeMounts: + - mountPath: "/opt/jfrog/worker/var" + name: data + + ## Add custom sidecar containers + ## - The provided example uses a custom volume (customVolumes) + customSidecarContainers: | + - name: "sidecar-list-etc" + image: {{ template "initContainers.image" $ }} + imagePullPolicy: {{ $.Values.initContainers.image.pullPolicy | quote }} + securityContext: + runAsNonRoot: false + allowPrivilegeEscalation: false + capabilities: + drop: + - NET_RAW + command: + - 'sh' + - '-c' + - 'sh /scripts/script.sh' + volumeMounts: + - mountPath: "/opt/jfrog/worker/var" + name: data + - mountPath: "/scripts/script.sh" + name: custom-script + subPath: script.sh + resources: + requests: + memory: "32Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "100m" + +## certificates added to this secret will be copied to $JFROG_HOME/worker/var/data/router/keys/trusted directory +customCertificates: + enabled: true + certificateSecretName: platformcert + +## Adding entries to a Pod's /etc/hosts file +## For an example, refer - https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases +hostAliases: + - ip: "100.64.0.1" + hostnames: + - "webhook.site" + +## Worker liveness probe configuration +livenessProbe: + enabled: true + config: | + httpGet: + path: /api/v1/system/liveness + port: {{ .Values.service.port }} + initialDelaySeconds: {{ if semverCompare " + echo "Copy system.yaml to /opt/jfrog/worker/var/etc"; + mkdir -p /opt/jfrog/worker/var/etc; + {{- if .Values.systemYamlOverride.existingSecret }} + cp -fv /tmp/etc/{{ .Values.systemYamlOverride.dataKey }} /opt/jfrog/worker/var/etc/system.yaml; + {{- else }} + cp -fv /tmp/etc/system.yaml /opt/jfrog/worker/var/etc/system.yaml; + {{- end }} + echo "Remove /opt/jfrog/worker/var/lost+found folder if exists"; + rm -rfv /opt/jfrog/worker/var/lost+found; + mkdir -p /opt/jfrog/worker/var/data/worker/usage; + volumeMounts: + - name: data + mountPath: "/opt/jfrog/worker/var" + - name: systemyaml + {{- if .Values.systemYamlOverride.existingSecret }} + mountPath: "/tmp/etc/{{.Values.systemYamlOverride.dataKey}}" + subPath: {{ .Values.systemYamlOverride.dataKey }} + {{- else }} + mountPath: "/tmp/etc/system.yaml" + subPath: system.yaml + {{- end }} + {{- if or .Values.customCertificates.enabled .Values.global.customCertificates.enabled }} + - name: copy-custom-certificates + image: {{ template "initContainers.image" . }} + imagePullPolicy: {{ .Values.initContainers.image.pullPolicy | quote }} + {{- if .Values.securityContext.enabled }} + securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + {{- if .Values.initContainers.resources }} + resources: {{- toYaml .Values.initContainers.resources | nindent 12 }} + {{- end }} + command: + - 'bash' + - '-c' + - > +{{ include "worker.copyCustomCerts" . | indent 14 }} + volumeMounts: + - name: data + mountPath: "/opt/jfrog/worker/var" + - name: ca-certs + mountPath: "/tmp/certs" + {{- end }} + {{- if or .Values.common.customInitContainers .Values.global.customInitContainers }} +{{ tpl (include "worker.customInitContainers" .) . | indent 8 }} + {{- end }} + {{- if .Values.hostAliases }} + hostAliases: +{{ toYaml .Values.hostAliases | indent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- if .Values.securityContext.enabled }} + securityContext: {{- omit .Values.securityContext "enabled" | toYaml | nindent 12 }} + {{- end }} + image: {{ template "worker.image" . }} + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + - name: grpc + containerPort: {{ .Values.service.grpcPort }} + protocol: TCP + {{- if .Values.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.readinessProbe "enabled") "context" $) | nindent 12 }} + initialDelaySeconds: {{ if semverCompare " User Management > Settings > Connection details" (include "worker.jfrogUrl" .)) .) .Values.router.serviceRegistry.url }}/access" + - name: JF_ROUTER_SERVICEREGISTRY_GRPCADDRESS + value: "{{ default (include "worker.jfrogUrlHost" .) .Values.router.serviceRegistry.grpcUrl }}" + - name: JF_SHARED_NODE_ID + valueFrom: + fieldRef: + fieldPath: metadata.name + {{- if not .Values.systemYamlOverride.existingSecret }} + - name: JF_SHARED_SECURITY_JOINKEY + valueFrom: + secretKeyRef: + name: {{ include "worker.joinKeySecretName" . }} + key: join-key + optional: true + - name: JF_SHARED_SECURITY_MASTERKEY + valueFrom: + secretKeyRef: + name: {{ include "worker.masterKeySecretName" . }} + key: master-key + optional: true + {{- end }} + +{{- with .Values.router.extraEnvironmentVariables }} +{{ tpl (toYaml .) $ | indent 12 }} +{{- end }} + ports: + - name: http + containerPort: {{ .Values.router.internalPort }} + - name: http-router + containerPort: {{ .Values.router.externalPort }} + resources: +{{ toYaml .Values.router.resources | indent 12 }} + {{- if .Values.router.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.router.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.router.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.router.startupProbe "enabled") "context" $) | nindent 12 }} + timeoutSeconds: {{ .Values.probes.timeoutSeconds }} + exec: + command: + - sh + - -c + - curl -s -k --fail --max-time {{ .Values.probes.timeoutSeconds }} {{ include "worker.scheme" . }}://localhost:{{ .Values.router.internalPort }}/router/api/v1/system/readiness + {{- end }} + {{- if .Values.router.customReadinessProbe }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.router.customReadinessProbe "context" $) | nindent 12 }} + {{- else if .Values.router.readinessProbe.enabled }} + readinessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.router.readinessProbe "enabled") "context" $) | nindent 12 }} + timeoutSeconds: {{ .Values.probes.timeoutSeconds }} + initialDelaySeconds: {{ if semverCompare " + {{- with .Values.common.preStartCommand }} + echo "Running custom common preStartCommand command"; + {{ tpl . $ }}; + {{- end }} + exec /opt/jfrog/observability/app/bin/entrypoint-observability.sh; + {{- with .Values.observability.lifecycle }} + lifecycle: +{{ toYaml . | indent 12 }} + {{- end }} + volumeMounts: + - name: data + mountPath: "{{ .Values.observability.persistence.mountPath }}" + resources: +{{ toYaml .Values.observability.resources | indent 12 }} + {{- if .Values.observability.customStartupProbe }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" .Values.observability.customStartupProbe "context" $) | nindent 12 }} + {{- else if .Values.observability.startupProbe.enabled }} + startupProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.observability.startupProbe "enabled") "context" $) | nindent 12 }} + timeoutSeconds: {{ .Values.probes.timeoutSeconds }} + exec: + command: + - sh + - -c + - curl --fail --max-time {{ .Values.probes.timeoutSeconds }} http://localhost:{{ .Values.observability.internalPort }}/api/v1/system/readiness + {{- end }} + {{- if .Values.observability.customLivenessProbe }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" .Values.observability.customLivenessProbe "context" $) | nindent 12 }} + {{- else if .Values.observability.livenessProbe.enabled }} + livenessProbe: {{- include "common.tplvalues.render" (dict "value" (omit .Values.observability.livenessProbe "enabled") "context" $) | nindent 12 }} + initialDelaySeconds: {{ if semverCompare "/dev/null) + + # Wait for the log file + while [ -z "${LOG_FILE}" ]; do + sleep 1 + LOG_FILE=$(ls -1t ./${LOG_PREFIX}.log 2>/dev/null) + done + + echo "Log file ${LOG_FILE} is ready!" + + # Get inode number + INODE_ID=$(ls -i ${LOG_FILE}) + + # echo "Tailing ${LOG_FILE}" + tail -F ${LOG_FILE} & + PID=$! + + # Loop forever to see if a new log was created + while true; do + # Check inode number + NEW_INODE_ID=$(ls -i ${LOG_FILE}) + + # If inode number changed, this means log was rotated and need to start a new tail + if [ "${INODE_ID}" != "${NEW_INODE_ID}" ]; then + kill -9 ${PID} 2>/dev/null + INODE_ID="${NEW_INODE_ID}" + + # Start a new tail + tail -F ${LOG_FILE} & + PID=$! + fi + sleep 1 + done + +{{- end }} diff --git a/stable/worker/templates/secrets.yaml b/stable/worker/templates/secrets.yaml new file mode 100644 index 000000000..fa1dcc421 --- /dev/null +++ b/stable/worker/templates/secrets.yaml @@ -0,0 +1,27 @@ +{{- if not .Values.systemYamlOverride.existingSecret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "worker.fullname" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- with .Values.labels }} +{{ toYaml . | indent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +data: + {{- if or .Values.masterKey .Values.global.masterKey }} + {{- if not (or .Values.masterKeySecretName .Values.global.masterKeySecretName) }} + master-key: {{ include "worker.masterKey" . | b64enc | quote }} + {{- end }} + {{- end }} + {{- if or .Values.joinKey .Values.global.joinKey }} + {{- if not (or .Values.joinKeySecretName .Values.global.joinKeySecretName) }} + join-key: {{ include "worker.joinKey" . | b64enc | quote }} + {{- end }} + {{- end }} +{{- end }} diff --git a/stable/worker/templates/service.yaml b/stable/worker/templates/service.yaml new file mode 100644 index 000000000..93199eea8 --- /dev/null +++ b/stable/worker/templates/service.yaml @@ -0,0 +1,29 @@ +# this service is for rest LB : nginx will redirect traffic directly to it +apiVersion: v1 +kind: Service +metadata: + name: {{ include "worker.fullname" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- with .Values.labels }} +{{ toYaml . | indent 4 }} + {{- end }} + metricsName: worker + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - name: http-router + port: {{ .Values.router.externalPort }} + targetPort: {{ .Values.router.externalPort }} + {{- if .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + protocol: TCP + - name: http-router-in + port: {{ .Values.router.internalPort }} + targetPort: {{ .Values.router.internalPort }} + protocol: TCP + selector: {{ include "common.labels.matchLabels" . | nindent 4 }} diff --git a/stable/worker/templates/serviceaccount.yaml b/stable/worker/templates/serviceaccount.yaml new file mode 100644 index 000000000..0efb39928 --- /dev/null +++ b/stable/worker/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "worker.serviceAccountName" . }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- with .Values.labels }} +{{ toYaml . | indent 4 }} + {{- end }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/stable/worker/templates/servicemonitor.yaml b/stable/worker/templates/servicemonitor.yaml new file mode 100644 index 000000000..4f0397ea9 --- /dev/null +++ b/stable/worker/templates/servicemonitor.yaml @@ -0,0 +1,56 @@ +{{- if .Values.serviceMonitor.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + namespace: {{ .Values.serviceMonitor.kubePromFullName }} + name: {{ printf "%s-worker-service-monitor" .Release.Namespace | quote }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- with .Values.labels }} +{{ toYaml . | indent 4 }} + {{- end }} + app: {{ .Values.serviceMonitor.kubePromApp }} + release: {{ .Values.serviceMonitor.kubePromFullName }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} + +spec: + endpoints: + - path: /worker/api/v1/metrics + {{- if .Values.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.serviceMonitor.bearerTokenFile }} + {{- else }} + bearerTokenSecret: + key: token + name: {{ .Values.serviceMonitor.tokenName }} + {{- end }} + honorLabels: true + interval: {{ .Values.serviceMonitor.interval }} + scheme: {{ .Values.serviceMonitor.scheme }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + targetPort: {{ .Values.serviceMonitor.targetPort }} + tlsConfig: + insecureSkipVerify: true + - path: /router/api/v1/metrics + {{- if .Values.serviceMonitor.bearerTokenFile }} + bearerTokenFile: {{ .Values.serviceMonitor.bearerTokenFile }} + {{- else }} + bearerTokenSecret: + key: token + name: {{ .Values.serviceMonitor.tokenName }} + {{- end }} + honorLabels: true + interval: {{ .Values.serviceMonitor.interval }} + scheme: {{ .Values.serviceMonitor.scheme }} + scrapeTimeout: {{ .Values.serviceMonitor.scrapeTimeout }} + targetPort: {{ .Values.serviceMonitor.targetPort }} + tlsConfig: + insecureSkipVerify: true + jobLabel: worker-metrics-monitor + namespaceSelector: +{{ toYaml .Values.serviceMonitor.namespaceSelector | indent 4 }} + selector: + matchLabels: + metricsName: worker +{{- end }} diff --git a/stable/worker/templates/system-yaml.yaml b/stable/worker/templates/system-yaml.yaml new file mode 100644 index 000000000..553295e43 --- /dev/null +++ b/stable/worker/templates/system-yaml.yaml @@ -0,0 +1,19 @@ +{{- if not .Values.systemYamlOverride.existingSecret}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "worker.fullname" . }}-systemyaml + namespace: {{ .Release.Namespace | quote }} + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- with .Values.labels }} +{{ toYaml . | indent 4 }} + {{- end }} + {{- if .Values.commonAnnotations }} + annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} + {{- end }} +type: Opaque +stringData: + system.yaml: | +{{ include "worker.finalSystemYaml" . | nindent 4 }} +{{- end }} diff --git a/stable/worker/templates/worker-configmaps.yaml b/stable/worker/templates/worker-configmaps.yaml new file mode 100644 index 000000000..2061ed10a --- /dev/null +++ b/stable/worker/templates/worker-configmaps.yaml @@ -0,0 +1,13 @@ +{{ if .Values.common.configMaps }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "worker.fullname" . }}-configmaps + labels: + {{- include "common.labels.standard" . | nindent 4 }} + {{- with .Values.labels }} +{{ toYaml . | indent 4 }} + {{- end }} +data: +{{ tpl .Values.common.configMaps . | indent 2 }} +{{ end -}} diff --git a/stable/worker/values.yaml b/stable/worker/values.yaml new file mode 100644 index 000000000..1bdb4a45f --- /dev/null +++ b/stable/worker/values.yaml @@ -0,0 +1,669 @@ +# Default values for worker. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +global: + ## Image registry to pull docker images from + imageRegistry: "" + ## Secrets used to pull images from private registries + imagePullSecrets: [] + + ## Chart.AppVersion can be overridden using global.versions.worker or image tags + ## Note: Order of preference is 1) global.versions 2) image tags 3) Chart.AppVersion + versions: {} + + ## Artifactory URL + # jfrogUrl: "" + ## Worker service requires a unique master key. + ## You can generate one with the command: "openssl rand -hex 32" + ## An initial one is auto generated on first startup. + # masterKey: "" + + ## Alternatively, you can use a pre-existing secret with a key + ## called "master-key" by specifying "masterKeySecretName" + # masterKeySecretName: "" + + ## Join Key to connect other services to Artifactory + ## IMPORTANT: Setting this value overrides the existing joinKey + # joinKey: "" + + ## Alternatively, you can use a pre-existing secret with a key + ## called "join-key" by specifying "joinKeySecretName" + # joinKeySecretName: "" + + ## Note: tags customInitContainers,customVolumes,customVolumeMounts,customSidecarContainers can be used both from global and application level simultaneously + # customVolumes: | + + # customVolumeMounts: | + + # customInitContainers: | + + # customSidecarContainers: | + + ## certificates added to this secret will be copied to $JFROG_HOME/worker/var/data/router/keys/trusted directory + customCertificates: + enabled: false + # certificateSecretName: + + ## Applies to Worker pods + nodeSelector: {} + +## Artifactory URL. Mandatory +jfrogUrl: + +## Number of replicas used when autoscaling is disabled +replicaCount: 1 + +## Worker image +image: + registry: releases-docker.jfrog.io + repository: jfrog/worker + pullPolicy: IfNotPresent + +## String to partially override worker.name template (will maintain the release name) +nameOverride: "" +## String to fully override worker.fullname template +fullnameOverride: "" + +## Specify common probes parameters +probes: + timeoutSeconds: 120 + +## Service Account +## Ref: https://kubernetes.io/docs/admin/service-accounts-admin/ +## +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +## Annotations added to Worker pods +podAnnotations: {} + +## Disable podSecurityContext for openshift +podSecurityContext: + enabled: true + fsGroup: 1131 + runAsUser: 1131 + +## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container +## Disable securityContext for openshift +securityContext: + enabled: true + runAsNonRoot: true + allowPrivilegeEscalation: false + capabilities: + drop: + - NET_RAW + +## Set sleep in order to keep service responding while k8s is removing it from network +lifecycle: + preStopSleepSeconds: 15 + +## Worker service configuration +service: + type: ClusterIP + port: 8098 + grpcPort: 8099 + ## If the type is NodePort you can set a fixed port + # nodePort: 30000 + productHome: /opt/jfrog/worker + +## Worker service ingress configuration +ingress: + enabled: false + className: "" + grpcReadTimeout: 43200s + grpcSendTimeout: 43200s + clientBodyTimeout: 43200s + backendTls: false + backendPortName: http-router + + +## Worker container resources +resources: + limits: + cpu: 2 + memory: 1536Mi + requests: + cpu: 2 + memory: 1536Mi + +## Autoscaling configuration for Worker deployment +autoscaling: + ## Enable autoscaling for Worker deployment + enabled: true + ## Type of autoscaler. Possible values: + ## - "keda" + ## ref: https://keda.sh/ + ## - "hpa" + ## ref: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/ + kind: "hpa" + minReplicas: 1 + maxReplicas: 10 + pollingInterval: 30 + cooldownPeriod: 300 + # targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + keda: + threshold: '3' + query: sum(avg_over_time(jfwks_execution_processing_count{service="{{ .Release.Name }}", namespace="{{ .Release.Namespace }}"}[1m])) + metricType: AverageValue + prometheusServerAddress: http://prometheus-server.monitoring.svc.cluster.local:9090 + +## @param serviceMonitor Declaratively specifies how groups of Kubernetes services should be monitored. +## Ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md +serviceMonitor: + scheme: http + targetPort: 8082 + enabled: false + interval: 60s + scrapeTimeout: 15s + kubePromApp: "" + kubePromFullName: "" + namespaceSelector: + any: true + +## Applies to worker pods +nodeSelector: {} + +## Applies to worker pods +tolerations: [] + +## Applies to worker pods +affinity: {} + +## Extra environment variables that can be used to tune worker service to your needs. +## Uncomment and set value as needed +extraEnvironmentVariables: +# - name: MY_ENV_VAR +# value: "" + + +router: + name: router + image: + registry: releases-docker.jfrog.io + repository: jfrog/router + tag: 7.129.0 + imagePullPolicy: IfNotPresent + serviceRegistry: + ## Service registry (Access) TLS verification skipped if enabled + insecure: false + ## Service registry URL and gRPC URL use jfrogUrl by default. Override if needed + # url: https://workersvc-artifactory:8082 + # grpcUrl: workersvc-artifactory:8082 + internalPort: 8046 + externalPort: 8082 + tlsEnabled: false + + ## Extra environment variables that can be used to tune router to your needs. + ## Uncomment and set value as needed + extraEnvironmentVariables: + # - name: MY_ENV_VAR + # value: "" + + resources: + requests: {} + # memory: "100Mi" + # cpu: "100m" + limits: {} + # memory: "1Gi" + # cpu: "1" + + ## Add custom volumesMounts + customVolumeMounts: | + # - name: custom-script + # mountPath: /scripts/script.sh + # subPath: script.sh + + # customLivenessProbe: + # exec: + # command: + # - sh + # - -c + # - curl -s -k --fail --max-time 120 http://localhost:8046/router/api/v1/system/liveness + # initialDelaySeconds: 0 + # periodSeconds: 5 + # timeoutSeconds: 120 + # failureThreshold: 10 + # successThreshold: 1 + + livenessProbe: + enabled: true + periodSeconds: 5 + failureThreshold: 10 + successThreshold: 1 + + # customReadinessProbe: + # exec: + # command: + # - sh + # - -c + # - curl -s -k --fail --max-time 120 http://localhost:8046/router/api/v1/system/readiness + # initialDelaySeconds: 0 + # periodSeconds: 5 + # timeoutSeconds: 120 + # failureThreshold: 10 + # successThreshold: 1 + + readinessProbe: + enabled: true + periodSeconds: 5 + failureThreshold: 10 + successThreshold: 1 + + # customStartupProbe: + # exec: + # command: + # - sh + # - -c + # - curl -s -k --fail --max-time 120 http://localhost:8046/router/api/v1/system/readiness + # initialDelaySeconds: 0 + # periodSeconds: 5 + # timeoutSeconds: 120 + # failureThreshold: 10 + # successThreshold: 1 + + startupProbe: + enabled: true + initialDelaySeconds: 0 + failureThreshold: 60 + periodSeconds: 5 + persistence: + mountPath: "/var/opt/jfrog/router" + +## @section Init Container Parameters +## + +## Init Container parameters + +initContainers: + ## @param volumePermissions.enabled Enable init container that changes the owner and group of the persistent volume(s) mountpoint to `runAsUser:fsGroup` + ## + ## @param initContainers.image.registry Init container volume-permissions image registry + ## @param initContainers.image.repository Init container volume-permissions image repository + ## @param initContainers.image.tag Init container volume-permissions image tag + ## @param initContainers.image.pullPolicy Init container volume-permissions image pull policy + ## @param initContainers.image.pullSecrets Specify docker-registry secret names as an array + ## + image: + registry: releases-docker.jfrog.io + repository: ubi9/ubi-minimal + tag: 9.4.949.1716471857 + ## Specify a imagePullPolicy + ## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent' + ## ref: https://kubernetes.io/docs/user-guide/images/#pre-pulling-images + ## + pullPolicy: IfNotPresent + ## Optionally specify an array of imagePullSecrets (secrets must be manually created in the namespace) + ## ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ + ## Example: + ## pullSecrets: + ## - myRegistryKeySecretName + ## + pullSecrets: [] + ## Init Container resource requests and limits + ## ref: https://kubernetes.io/docs/user-guide/compute-resources/ + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + ## @param volumePermissions.resources.limits Init container volume-permissions resource limits + ## @param volumePermissions.resources.requests Init container volume-permissions resource requests + ## + resources: + ## Example: + ## limits: + ## cpu: 100m + ## memory: 128Mi + ## + limits: {} + ## Examples: + ## requests: + ## cpu: 100m + ## memory: 128Mi + ## + requests: {} + +## a unique master key. +## You can generate one with the command: "openssl rand -hex 32" +## An initial one is auto generated by Artifactory on first startup. +masterKey: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +## Alternatively, you can use a pre-existing secret with a key called master-key by specifying masterKeySecretName +masterKeySecretName: "" + +## Join Key to connect other services to Artifactory +## IMPORTANT: Setting this value overrides the existing joinKey +## IMPORTANT: You should NOT use the example joinKey for a production deployment! +joinKey: EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +## Alternatively, you can use a pre-existing secret with a key called join-key by specifying joinKeySecretName +joinKeySecretName: "" + +## System YAML entries now reside under files/system.yaml. +## You can provide the specific values that you want to add or override under 'extraSystemYaml'. +## For example: +## extraSystemYaml: +## shared: +## node: +## id: my-instance +## The entries provided under 'extraSystemYaml' are merged with files/system.yaml to create the final system.yaml. +## If you have already provided system.yaml under, 'systemYaml', the values in that entry take precedence over files/system.yaml +## You can modify specific entries with your own value under `extraSystemYaml`, The values under extraSystemYaml overrides the values under 'systemYaml' and files/system.yaml +extraSystemYaml: {} + +## systemYaml is intentionally commented and the previous content has been moved under files/system.yaml. +## You have to add the all entries of the system.yaml file here, and it overrides the values in files/system.yaml. +# systemYaml: + +## worker systemYaml override +## This is for advanced usecases where users wants to provide their own systemYaml for configuring worker +## Note: This will override existing (default) .Values.systemYaml in values.yaml +## Alternatively, systemYaml can be overidden via customInitContainers using external sources like vaults, external repositories etc. Please refer customInitContainer section below for an example. +## Note: Order of preference is 1) customInitContainers 2) systemYamlOverride existingSecret 3) default systemYaml in values.yaml +systemYamlOverride: + ## You can use a pre-existing secret by specifying existingSecret + existingSecret: "" + ## The dataKey should be the name of the secret data key created. + dataKey: + +## @param commonAnnotations Annotations to add to all deployed objects +## +commonAnnotations: {} + +## @param podLabels integration Pod labels. Evaluated as a template +## Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +## +podLabels: {} + +## Worker deployment labels +labels: {} + +common: + ## Spread Worker pods evenly across your nodes or some other topology + topologySpreadConstraints: [] + # - maxSkew: 1 + # topologyKey: kubernetes.io/hostname + # whenUnsatisfiable: DoNotSchedule + # labelSelector: + # matchLabels: + # app: '{{ template "worker.name" . }}' + # role: '{{ template "worker.name" . }}' + # release: "{{ .Release.Name }}" + + ## Custom command to run before microservice startup. Runs BEFORE any microservice-specific preStartCommand + preStartCommand: + + ## Add custom volumes + customVolumes: | + # - name: custom-script + # configMap: + # name: custom-script + + ## Add custom volumesMounts + customVolumeMounts: | + # - name: custom-script + # mountPath: /scripts/script.sh + # subPath: script.sh + + ## Add any list of configmaps to worker + configMaps: | + # posthook-start.sh: |- + # echo "This is a post start script" + # posthook-end.sh: |- + # echo "This is a post end script" + + ## Add custom init containers execution after predefined init containers + customInitContainers: | + # - name: "custom-systemyaml-setup" + # image: {{ template "initContainers.image" $ }} + # imagePullPolicy: {{ $.Values.initContainers.image.pullPolicy | quote }} + # securityContext: + # runAsNonRoot: true + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - NET_RAW + # command: + # - 'sh' + # - '-c' + # - 'curl -o /opt/jfrog/worker/var/etc/system.yaml https:///systemyaml' + # volumeMounts: + # - mountPath: "/opt/jfrog/worker/var" + # name: data + + ## Add custom sidecar containers + ## - The provided example uses a custom volume (customVolumes) + customSidecarContainers: | + # - name: "sidecar-list-etc" + # image: {{ template "initContainers.image" $ }} + # imagePullPolicy: {{ $.Values.initContainers.image.pullPolicy | quote }} + # securityContext: + # runAsNonRoot: true + # allowPrivilegeEscalation: false + # capabilities: + # drop: + # - NET_RAW + # command: + # - 'sh' + # - '-c' + # - 'sh /scripts/script.sh' + # volumeMounts: + # - mountPath: "/opt/jfrog/worker/var" + # name: data + # - mountPath: "/scripts/script.sh" + # name: custom-script + # subPath: script.sh + # resources: + # requests: + # memory: "32Mi" + # cpu: "50m" + # limits: + # memory: "128Mi" + # cpu: "100m" + +## certificates added to this secret will be copied to $JFROG_HOME/worker/var/data/router/keys/trusted directory +customCertificates: + enabled: false + # certificateSecretName: + +## Adding entries to a Pod's /etc/hosts file +## For an example, refer - https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases +hostAliases: [] + # - ip: "127.0.0.1" + # hostnames: + # - "foo.local" + # - "bar.local" + # - ip: "10.1.2.3" + # hostnames: + # - "foo.remote" + # - "bar.remote" + +## Worker liveness probe configuration +livenessProbe: + enabled: true + periodSeconds: 5 + failureThreshold: 10 + successThreshold: 1 + +## Worker custom liveness probe configuration +# customLivenessProbe: +# httpGet: +# path: /api/v1/system/liveness +# port: 8098 +# initialDelaySeconds: 0 +# periodSeconds: 5 +# timeoutSeconds: 120 +# failureThreshold: 10 +# successThreshold: 1 + + +## Worker readiness probe configuration +readinessProbe: + enabled: true + periodSeconds: 5 + failureThreshold: 10 + successThreshold: 1 + +## Worker custom readiness probe configuration +# customReadinessProbe: +# httpGet: +# path: /api/v1/system/readiness +# port: 8098 +# initialDelaySeconds: 0 +# periodSeconds: 5 +# timeoutSeconds: 120 +# failureThreshold: 10 +# successThreshold: 1 + +## Add any of the loggers to a sidecar if you want to be able to see them with kubectl logs or a log collector in your k8s cluster +loggers: [] + # - router-request.log + # - router-service.log + # - router-traefik.log + # - worker-service.log + # - worker-request.log + +## Loggers containers resources +loggersResources: {} + # requests: + # memory: "64Mi" + # cpu: "25m" + # limits: + # memory: "128Mi" + # cpu: "50m" + +## Filebeat Sidecar container +## The provided filebeat configuration is for Worker logs. It assumes you have a logstash installed and configured properly. +filebeat: + enabled: false + name: worker-filebeat + image: + repository: docker.elastic.co/beats/filebeat + version: 7.17.24 + pullPolicy: IfNotPresent + logstashUrl: "logstash:5044" + + terminationGracePeriod: 10 + + livenessProbe: + exec: + command: + - sh + - -c + - | + #!/usr/bin/env bash -e + curl --fail 127.0.0.1:5066 + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + + readinessProbe: + exec: + command: + - sh + - -c + - | + #!/usr/bin/env bash -e + filebeat test output + failureThreshold: 3 + initialDelaySeconds: 10 + periodSeconds: 10 + timeoutSeconds: 5 + + resources: {} + # requests: + # memory: "100Mi" + # cpu: "100m" + # limits: + # memory: "100Mi" + # cpu: "100m" + + filebeatYml: | + logging.level: info + path.data: /opt/jfrog/worker/var/log/filebeat + name: worker-filebeat + queue.spool: + file: + permissions: 0760 + filebeat.inputs: + - type: log + enabled: true + close_eof: ${CLOSE:false} + paths: + - /opt/jfrog/worker/var/log/*.log + fields: + service: "jfwks" + log_type: "worker" + output: + logstash: + hosts: ["{{ .Values.filebeat.logstashUrl }}"] + +observability: + enabled: true + name: observability + image: + registry: releases-docker.jfrog.io + repository: jfrog/observability + tag: 1.31.4 + pullPolicy: IfNotPresent + internalPort: 8036 + resources: {} + # requests: + # memory: "100Mi" + # cpu: "100m" + # limits: + # memory: "1Gi" + # cpu: "1" + + ## Add lifecycle hooks for the observability pod + lifecycle: {} + # postStart: + # exec: + # command: ["/bin/sh", "-c", "echo Hello from the observability postStart handler > /usr/share/message"] + # preStop: + # exec: + # command: ["/bin/sh", "-c", "echo Hello from the observability preStart handler > /usr/share/message"] + + # customLivenessProbe: + # exec: + # command: + # - sh + # - -c + # - curl --fail --max-time 120 http://localhost:8036/api/v1/system/liveness + # initialDelaySeconds: 0 + # failureThreshold: 5 + # timeoutSeconds: 120 + # periodSeconds: 10 + # successThreshold: 1 + + livenessProbe: + enabled: true + failureThreshold: 5 + periodSeconds: 10 + successThreshold: 1 + + # customStartupProbe: + # exec: + # command: + # - sh + # - -c + # - curl --fail --max-time 120 http://localhost:8036/api/v1/system/readiness + # initialDelaySeconds: 30 + # failureThreshold: 90 + # periodSeconds: 5 + # timeoutSeconds: 120 + + startupProbe: + enabled: true + initialDelaySeconds: 30 + failureThreshold: 90 + periodSeconds: 5 + + persistence: + mountPath: "/var/opt/jfrog/observability" From 3cdcf1125695135c9d302f15b722e4298c0d1466 Mon Sep 17 00:00:00 2001 From: amithk Date: Wed, 30 Oct 2024 14:16:23 +0530 Subject: [PATCH 9/9] [jfrog-platform] 10.20.0 release --- stable/jfrog-platform/CHANGELOG.md | 8 ++++++++ stable/jfrog-platform/Chart.lock | 11 +++++++---- stable/jfrog-platform/Chart.yaml | 13 +++++++++---- stable/jfrog-platform/templates/_helpers.tpl | 2 +- stable/jfrog-platform/values.yaml | 10 +++++++--- 5 files changed, 32 insertions(+), 12 deletions(-) diff --git a/stable/jfrog-platform/CHANGELOG.md b/stable/jfrog-platform/CHANGELOG.md index 851b51353..f9def9ece 100644 --- a/stable/jfrog-platform/CHANGELOG.md +++ b/stable/jfrog-platform/CHANGELOG.md @@ -1,6 +1,14 @@ # JFrog Platform Chart Changelog (GA releases only) All changes to this chart will be documented in this file. +## [10.20.0] - Oct 29, 2024 +* **IMPORTANT** +* Added new dependency chart `worker` which is disabled by default and set `worker.enabled: true` to enable it. More info [here](https://jfrog.com/help/r/jfrog-installation-setup-documentation/installing-jfrog-worker) +* Commented `global.versions.router` to enable latest router version to picked from corresponding products +* Update dependency artifactory chart version to 107.98.7 +* Update dependency distribution chart version to 102.27.2 +* Update dependency worker chart version to 101.95.1 + ## [10.19.7] - Oct 23, 2024 * Added podSecurityContext and containerSecurityContext for pre-upgrade-check migration hook container. [GH-1929](https://github.com/jfrog/charts/pull/1929) * Update dependency artifactory chart version to 107.90.15 diff --git a/stable/jfrog-platform/Chart.lock b/stable/jfrog-platform/Chart.lock index a493eeb01..67d2c4161 100644 --- a/stable/jfrog-platform/Chart.lock +++ b/stable/jfrog-platform/Chart.lock @@ -7,18 +7,21 @@ dependencies: version: 11.9.3 - name: artifactory repository: https://charts.jfrog.io/ - version: 107.90.15 + version: 107.98.7 - name: xray repository: https://charts.jfrog.io/ version: 103.104.18 - name: distribution repository: https://charts.jfrog.io/ - version: 102.26.1 + version: 102.27.2 - name: insight repository: https://charts.jfrog.io/ version: 101.16.7 - name: pipelines repository: https://charts.jfrog.io/ version: 101.59.7 -digest: sha256:b2d758a515ff07dd7f9778800680a86f7ff5f1c1fcce531eeb0fd53d75847c77 -generated: "2024-10-23T12:31:23.797688+05:30" +- name: worker + repository: https://charts.jfrog.io/ + version: 101.95.1 +digest: sha256:2fb3be33472a516a0de2dc53a2cf93bd5d93a504f866c811749b7081780c7c6a +generated: "2024-10-30T07:32:40.338187+05:30" diff --git a/stable/jfrog-platform/Chart.yaml b/stable/jfrog-platform/Chart.yaml index a0c3b133f..a16262dd1 100644 --- a/stable/jfrog-platform/Chart.yaml +++ b/stable/jfrog-platform/Chart.yaml @@ -1,5 +1,5 @@ apiVersion: v2 -appVersion: 7.90.15 +appVersion: 7.98.7 dependencies: - condition: postgresql.enabled name: postgresql @@ -12,7 +12,7 @@ dependencies: - condition: artifactory.enabled name: artifactory repository: https://charts.jfrog.io/ - version: 107.90.15 + version: 107.98.7 - condition: xray.enabled name: xray repository: https://charts.jfrog.io/ @@ -20,7 +20,7 @@ dependencies: - condition: distribution.enabled name: distribution repository: https://charts.jfrog.io/ - version: 102.26.1 + version: 102.27.2 - condition: insight.enabled name: insight repository: https://charts.jfrog.io/ @@ -29,6 +29,10 @@ dependencies: name: pipelines repository: https://charts.jfrog.io/ version: 101.59.7 +- condition: worker.enabled + name: worker + repository: https://charts.jfrog.io/ + version: 101.95.1 description: The Helm chart for JFrog Platform (Universal, hybrid, end-to-end DevOps automation) home: https://jfrog.com/platform/ @@ -42,6 +46,7 @@ keywords: - pipelines - jfrog - devops +- worker kubeVersion: '>= 1.19.0-0' maintainers: - email: installers@jfrog.com @@ -50,4 +55,4 @@ name: jfrog-platform sources: - https://github.com/jfrog/charts type: application -version: 10.19.7 +version: 10.20.0 diff --git a/stable/jfrog-platform/templates/_helpers.tpl b/stable/jfrog-platform/templates/_helpers.tpl index 026edba4d..2ae2ad3f0 100644 --- a/stable/jfrog-platform/templates/_helpers.tpl +++ b/stable/jfrog-platform/templates/_helpers.tpl @@ -162,7 +162,7 @@ Custom init container for Postgres setup {{- end }} - name: CHART_NAME value: {{ .Chart.Name }} - {{- else }} + {{- else if not (eq .Chart.Name "worker") }} env: - name: PGUSERNAME {{- if .Values.global.database.secrets.adminUsername }} diff --git a/stable/jfrog-platform/values.yaml b/stable/jfrog-platform/values.yaml index 0ccabb3e7..7331bf9da 100644 --- a/stable/jfrog-platform/values.yaml +++ b/stable/jfrog-platform/values.yaml @@ -26,8 +26,8 @@ global: ## Chart.AppVersion for each product can be overidden using global.versions. ## For example : For artifactory, using global.versions.artifactory ## Note: Order of preference is 1) global.versions 2) .Values.artifactory.image.tag 3) Chart.AppVersion - versions: - router: 7.124.1 + versions: {} + # router: # artifactory: # xray: # distribution: @@ -232,7 +232,7 @@ rabbitmq: artifactory: enabled: true unifiedUpgradeAllowed: true - installerInfo: '{"productId":"Helm_JFrogPlatform/{{ printf "10.19.7-%s" .Chart.AppVersion }}","features":[{"featureId":"Platform/{{ printf "%s-%s" "kubernetes" .Capabilities.KubeVersion.Version }}"},{"featureId":"Database/{{ .Values.database.type }}"},{"featureId":"Nginx_Enabled/{{ .Values.nginx.enabled }}"},{"featureId":"ArtifactoryPersistence_Type/{{ .Values.artifactory.persistence.type }}"},{"featureId":"SplitServicesToContainers_Enabled/{{ .Values.splitServicesToContainers }}"},{"featureId":"Filebeat_Enabled/{{ .Values.filebeat.enabled }}"},{"featureId":"ReplicaCount/{{ .Values.artifactory.replicaCount }}"}]}' + installerInfo: '{"productId":"Helm_JFrogPlatform/{{ printf "10.20.0-%s" .Chart.AppVersion }}","features":[{"featureId":"Platform/{{ printf "%s-%s" "kubernetes" .Capabilities.KubeVersion.Version }}"},{"featureId":"Database/{{ .Values.database.type }}"},{"featureId":"Nginx_Enabled/{{ .Values.nginx.enabled }}"},{"featureId":"ArtifactoryPersistence_Type/{{ .Values.artifactory.persistence.type }}"},{"featureId":"SplitServicesToContainers_Enabled/{{ .Values.splitServicesToContainers }}"},{"featureId":"Filebeat_Enabled/{{ .Values.filebeat.enabled }}"},{"featureId":"ReplicaCount/{{ .Values.artifactory.replicaCount }}"}]}' postgresql: enabled: false waitForDatabase: false @@ -247,6 +247,8 @@ artifactory: mc: enabled: false artifactory: + worker: + enabled: '{{ .Values.worker.enabled }}' unifiedSecretInstallation: true ## unifiedSecretPrependReleaseName Set this flag to false if unifiedSecret should not be created with prepended. unifiedSecretPrependReleaseName: true @@ -350,6 +352,8 @@ pipelines: root_vhost_name: pipelinesRoot protocol: amqp +worker: + enabled: false preUpgradeHook: ## This is required to be performed to check if existing products like distribution, insight and pipelines already exists