diff --git a/Chart.yaml b/Chart.yaml index 6d6c683..e4c9c4b 100644 --- a/Chart.yaml +++ b/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: private-ai description: A Helm chart that deploys the Private AI deidentification solution -version: 1.6.0 +version: 1.7.0 # This is the default version deployed by the chart. # However, this is simply a label - if you wish to change the version, update your values.yaml diff --git a/README.md b/README.md index 6b85c0a..0d9e198 100644 --- a/README.md +++ b/README.md @@ -21,15 +21,15 @@ kubectl create namespace private-ai # Create a secret with your docker credentials from the customer portal kubectl -n private-ai create secret docker-registry crprivateaiprod-creds \ - --docker-server=crprivateaiprod.azurecr.io \ - --docker-username=USERNAME \ - --docker-password=PASSWORD + --docker-server=crprivateaiprod.azurecr.io \ + --docker-username=USERNAME \ + --docker-password=PASSWORD # Login to the helm registry with your docker credentials helm registry login crprivateaiprod.azurecr.io # Create a custom values file for your specific installation -helm show values oci://crprivateaiprod.azurecr.io/helm/private-ai:1.6.0 > values.custom.yaml +helm show values oci://crprivateaiprod.azurecr.io/helm/private-ai:1.7.0 > values.custom.yaml # Copy your license.json file contents and paste them into the license.data section of the values.custom.yaml file with single quotes surrounding, as per below license: @@ -40,7 +40,7 @@ helm upgrade --install \ private-ai oci://crprivateaiprod.azurecr.io/helm/private-ai \ --namespace private-ai \ -f values.custom.yaml \ - --version 1.6.0 + --version 1.7.0 ``` ## Testing @@ -109,7 +109,7 @@ helm upgrade --install \ private-ai oci://crprivateaiprod.azurecr.io/helm/private-ai \ --namespace private-ai \ -f values.custom.yaml \ - --version 1.6.0 + --version 1.7.0 ``` ### External Secrets Operator @@ -269,11 +269,14 @@ Update your values.custom.yaml file to enable the external secrets operator, and externalsecrets: enabled: true ... +``` +Proceed with installing the helm chart +```console # Proceed with installing / upgrading private-ai via helm into the private-ai namespace helm upgrade --install \ private-ai oci://crprivateaiprod.azurecr.io/helm/private-ai \ --namespace private-ai \ -f values.custom.yaml \ - --version 1.6.0 + --version 1.7.0 ``` diff --git a/templates/deployment.yaml b/templates/deployment.yaml index 796a6fc..9bdf721 100644 --- a/templates/deployment.yaml +++ b/templates/deployment.yaml @@ -5,13 +5,13 @@ metadata: labels: {{- include "private-ai.labels" . | nindent 4 }} spec: - replicas: {{ .Values.replicaCount }} + replicas: {{ .Values.deployment.replicaCount }} selector: matchLabels: {{- include "private-ai.selectorLabels" . | nindent 6 }} template: metadata: - {{- with .Values.podAnnotations }} + {{- with .Values.deployment.podAnnotations }} annotations: {{- toYaml . | nindent 8 }} {{- end }} @@ -22,33 +22,33 @@ spec: {{- if .Values.externalsecrets.enabled }} - name: {{ .Values.externalsecrets.dockercredential.name }} {{- else }} - - name: {{ .Values.imagePullSecrets.name }} + - name: {{ .Values.deployment.imagePullSecrets.name }} {{- end }} containers: - name: {{ .Chart.Name }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - {{- if or .Values.limits.enabled .Values.requests.enabled .Values.gpuEnabled }} + image: "{{ .Values.deployment.image.repository }}:{{ .Values.deployment.image.tag | default .Chart.AppVersion }}" + {{- if or .Values.deployment.limits.enabled .Values.deployment.requests.enabled .Values.deployment.gpuEnabled }} resources: - {{- if or .Values.limits.enabled .Values.gpuEnabled }} + {{- if or .Values.deployment.limits.enabled .Values.deployment.gpuEnabled }} limits: - {{- if .Values.gpuEnabled }} + {{- if .Values.deployment.gpuEnabled }} nvidia.com/gpu: 1 {{- end }} - memory: {{ .Values.limits.memory }} - cpu: {{ .Values.limits.cpu }} + memory: {{ .Values.deployment.limits.memory }} + cpu: {{ .Values.deployment.limits.cpu }} {{- end }} - {{- if .Values.requests.enabled}} + {{- if .Values.deployment.requests.enabled}} requests: - memory: {{ .Values.requests.memory }} - cpu: {{ .Values.requests.cpu }} + memory: {{ .Values.deployment.requests.memory }} + cpu: {{ .Values.deployment.requests.cpu }} {{- end }} {{- end }} - imagePullPolicy: {{ .Values.image.pullPolicy }} + imagePullPolicy: {{ .Values.deployment.image.pullPolicy }} ports: - name: http containerPort: {{ .Values.service.targetPort }} protocol: TCP - {{- with .Values.envVars }} + {{- with .Values.deployment.envVars }} env: {{- toYaml . | nindent 12 }} {{- end }} @@ -61,80 +61,93 @@ spec: {{- end }} optional: true volumeMounts: - - name: {{ .Values.license.volumeMount }} + - name: {{ .Values.deployment.license.volumeMount }} mountPath: /app/license - {{- if .Values.gpuEnabled }} + {{- if .Values.deployment.additionalMounts.enabled }} + {{- with .Values.deployment.additionalMounts.volumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + {{- if .Values.deployment.gpuEnabled }} - name: dshm-volume mountPath: /dev/shm {{- end }} - {{- if .Values.livenessProbe.enabled }} + {{- if .Values.deployment.livenessProbe.enabled }} livenessProbe: httpGet: path: /healthz port: {{ .Values.service.targetPort }} - periodSeconds: {{ .Values.livenessProbe.periodSeconds }} - initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} - timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + scheme: {{ .Values.deployment.livenessProbe.scheme }} + periodSeconds: {{ .Values.deployment.livenessProbe.periodSeconds }} + initialDelaySeconds: {{ .Values.deployment.livenessProbe.initialDelaySeconds }} + timeoutSeconds: {{ .Values.deployment.livenessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.deployment.livenessProbe.failureThreshold }} {{- end }} - {{- if .Values.startupProbe.enabled }} + {{- if .Values.deployment.startupProbe.enabled }} startupProbe: httpGet: path: /healthz port: {{ .Values.service.targetPort }} - periodSeconds: {{ .Values.startupProbe.periodSeconds }} - initialDelaySeconds: {{ .Values.startupProbe.initialDelaySeconds }} - timeoutSeconds: {{ .Values.startupProbe.timeoutSeconds }} - failureThreshold: {{ .Values.startupProbe.failureThreshold }} + scheme: {{ .Values.deployment.startupProbe.scheme }} + periodSeconds: {{ .Values.deployment.startupProbe.periodSeconds }} + initialDelaySeconds: {{ .Values.deployment.startupProbe.initialDelaySeconds }} + timeoutSeconds: {{ .Values.deployment.startupProbe.timeoutSeconds }} + failureThreshold: {{ .Values.deployment.startupProbe.failureThreshold }} {{- end }} - {{- if .Values.readinessProbe.enabled }} + {{- if .Values.deployment.readinessProbe.enabled }} readinessProbe: httpGet: path: /healthz port: {{ .Values.service.targetPort }} - periodSeconds: {{ .Values.readinessProbe.periodSeconds }} - initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }} - timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }} - failureThreshold: {{ .Values.readinessProbe.failureThreshold }} + scheme: {{ .Values.deployment.readinessProbe.scheme }} + periodSeconds: {{ .Values.deployment.readinessProbe.periodSeconds }} + initialDelaySeconds: {{ .Values.deployment.readinessProbe.initialDelaySeconds }} + timeoutSeconds: {{ .Values.deployment.readinessProbe.timeoutSeconds }} + failureThreshold: {{ .Values.deployment.readinessProbe.failureThreshold }} {{- end }} volumes: - - name: {{ .Values.license.volumeMount }} + - name: {{ .Values.deployment.license.volumeMount }} secret: {{- if .Values.externalsecrets.enabled }} secretName: {{ .Values.externalsecrets.license.name }} {{- else }} - secretName: {{ .Values.license.name }} + secretName: {{ .Values.deployment.license.name }} {{- end }} - {{- if .Values.gpuEnabled }} + {{- if .Values.deployment.additionalMounts.enabled }} + {{- with .Values.deployment.additionalMounts.volumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- end }} + {{- if .Values.deployment.gpuEnabled }} - name: dshm-volume emptyDir: medium: Memory {{- end }} affinity: - {{- if .Values.nodeAffinity.enabled}} - {{- with .Values.nodeAffinity.values}} + {{- if .Values.deployment.nodeAffinity.enabled}} + {{- with .Values.deployment.nodeAffinity.values}} nodeAffinity: {{- toYaml . | nindent 10 }} {{- end }} {{- end }} - {{- if .Values.podAntiAffinity.enabled}} - {{- with .Values.podAntiAffinity.values}} + {{- if .Values.deployment.podAntiAffinity.enabled}} + {{- with .Values.deployment.podAntiAffinity.values}} podAntiAffinity: {{- toYaml . | nindent 10 }} {{- end }} {{- end }} - {{- if .Values.topologySpreadConstraints.enabled}} - {{- with .Values.topologySpreadConstraints.values}} + {{- if .Values.deployment.topologySpreadConstraints.enabled}} + {{- with .Values.deployment.topologySpreadConstraints.values}} topologySpreadConstraints: {{- toYaml . | nindent 8 }} {{- end }} {{- end }} - {{- if .Values.tolerations.enabled}} - {{- with .Values.tolerations.values}} + {{- if .Values.deployment.tolerations.enabled}} + {{- with .Values.deployment.tolerations.values}} tolerations: {{- toYaml . | nindent 8 }} {{- end }} diff --git a/templates/external-secrets-operator/docker-creds-external-secret.yaml b/templates/external-secrets-operator/docker-creds-external-secret.yaml index 99d50d9..be0b45e 100644 --- a/templates/external-secrets-operator/docker-creds-external-secret.yaml +++ b/templates/external-secrets-operator/docker-creds-external-secret.yaml @@ -2,7 +2,7 @@ apiVersion: external-secrets.io/v1 kind: ExternalSecret metadata: - name: {{ .Values.imagePullSecrets.name }} + name: {{ .Values.externalsecrets.dockercredential.name }} {{- with .Values.externalsecrets.dockercredential.annotations }} annotations: {{- toYaml . | nindent 4 }} @@ -15,7 +15,7 @@ spec: kind: SecretStore refreshInterval: {{ .Values.externalsecrets.dockercredential.refreshInterval }} target: - name: {{ .Values.imagePullSecrets.name }} + name: {{ .Values.externalsecrets.dockercredential.name }} template: type: kubernetes.io/dockerconfigjson data: diff --git a/templates/license-secret.yaml b/templates/license-secret.yaml index 5d42f92..de53543 100644 --- a/templates/license-secret.yaml +++ b/templates/license-secret.yaml @@ -2,8 +2,8 @@ apiVersion: v1 kind: Secret metadata: - name: {{ .Values.license.name }} - {{- with .Values.license.annotations }} + name: {{ .Values.deployment.license.name }} + {{- with .Values.deployment.license.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} @@ -11,5 +11,5 @@ metadata: {{- include "private-ai.labels" . | nindent 4 }} data: license.json: |- -{{- .Values.license.data | b64enc | nindent 4 }} +{{- .Values.deployment.license.data | b64enc | nindent 4 }} {{- end }} diff --git a/values.yaml b/values.yaml index 90b3fc8..4d9cff3 100644 --- a/values.yaml +++ b/values.yaml @@ -1,37 +1,176 @@ # Select a cloud provider. Must be one of "Azure", "AWS", or "Other" cloudProvider: "Azure" -# Sets the number of replicas for the Private AI deployment -replicaCount: 1 - -image: - repository: "crprivateaiprod.azurecr.io/deid" - pullPolicy: "IfNotPresent" - # Can be a direct version tag / container flavour (i.e. 4.0.4-cpu-text) OR a 'latest' tag (i.e. cpu, cpu-text, gpu, gpu-text) - # It is recommended to pin to a specific version for production environments - tag: "4.2.2-cpu" - -# Change this to true if you have a cluster that has nodes with Nvidia GPUs available and would like to run the GPU container -gpuEnabled: false - -# This secret will store your docker pull credentials. You can obtain these from the customer portal -# If you enable the External Secrets Operator, this section will be ignored -imagePullSecrets: - name: "crprivateaiprod-creds" - # Override the default name of the application, used in the helper script to populate things like selector labels nameOverride: "" # Override the full name of the application fullnameOverride: "" -# Add custom pod annotations to the deployment -podAnnotations: {} -# Example annotations -# podAnnotations: -# annotation-key1: "annotation-value1" -# annotation-key2: "annotation-value1" +# This section contains all information related to the Private AI deployment +deployment: + # Sets the number of replicas for the Private AI deployment + replicaCount: 1 + + image: + repository: "crprivateaiprod.azurecr.io/deid" + pullPolicy: "IfNotPresent" + # Can be a direct version tag / container flavour (i.e. 4.0.4-cpu-text) OR a 'latest' tag (i.e. cpu, cpu-text, gpu, gpu-text) + # It is recommended to pin to a specific version for production environments + tag: "4.2.2-cpu" + + # Change this to true if you have a cluster that has nodes with Nvidia GPUs available and would like to run the GPU container + gpuEnabled: false + + # This secret will store your docker pull credentials. You can obtain these from the customer portal + # If you enable the External Secrets Operator, this section will be ignored + imagePullSecrets: + name: "crprivateaiprod-creds" + + # This section contains optional secret mounts for the deployment + additionalMounts: + enabled: false + volumeMounts: + - name: "mount-name" + mountPath: "/mount/path" + volumes: + - name: "mount-name" + secret: + secretName: "mount-secret" + + # Add custom pod annotations to the deployment + podAnnotations: {} + # Example annotations + # podAnnotations: + # annotation-key1: "annotation-value1" + # annotation-key2: "annotation-value1" + + # Settings for the Private AI license file + license: + # If you enable the External Secrets Operator, this section will be ignored + # Sets the name of the license secret object + name: "pai-license" + # Add optional annotations for the license secret. For more details see https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + annotations: {} + # Example annotations + # annotations: + # annotation-key1: "annotation-value1" + # annotation-key2: "annotation-value2" + volumeMount: "license-volume" + # If you use the External Secrets Operator, you can ignore this setting as the license file will be populated via a secret + data: 'Override with your license data. See readme for more details' + + # Enter any environment variables for your deployment. You can find the list at https://docs.private-ai.com/environment-variables/ + envVars: [] + # Example environment variables: + # envVars: + # - name: "PAI_DISABLE_RAM_CHECK" + # value: "true" -# Add kubrernetes service configuration for the deployment + # These are the values for liveness, startup and readiness probes. + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#probe-v1-core + livenessProbe: + enabled: false + scheme: "HTTP" + initialDelaySeconds: 60 + periodSeconds: 60 + failureThreshold: 30 + timeoutSeconds: 1 + startupProbe: + # Note: You should expect to see warnings for startup probe failures in the pod events until the container starts + enabled: true + scheme: "HTTP" + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 23 + timeoutSeconds: 1 + readinessProbe: + enabled: true + scheme: "HTTP" + initialDelaySeconds: 60 + periodSeconds: 20 + failureThreshold: 3 + timeoutSeconds: 1 + + # These are the values for the affinity + # https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volumenodeaffinity-v1-core + nodeAffinity: + enabled: false + values: {} + # Use the following to example to attempt to schedule nodes first on nodes with the label "private-ai-spot" + # and after on nodes with the label "private-ai" + # values: + # preferredDuringSchedulingIgnoredDuringExecution: + # - preference: + # matchExpressions: + # - key: "nodetype" + # operator: "In" + # values: + # - "private-ai" + # weight: 1 + # - preference: + # matchExpressions: + # - key: "nodetype" + # operator: "In" + # values: + # - "private-ai-spot" + # weight: 100 + + podAntiAffinity: + enabled: false + values: {} + # Recommended configuration to ensure only one Private AI container is scheduled per node: + # values: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchExpressions: + # - key: "app.kubernetes.io/name" + # operator: "In" + # values: + # - "private-ai" + # - key: "app.kubernetes.io/instance" + # operator: "In" + # values: + # - "private-ai" + # topologyKey: "kubernetes.io/hostname" + + topologySpreadConstraints: + enabled: false + values: [] + # Use the following if you would like to spread your pods evenly across your infrastructure zones + # values: + # - labelSelector: + # matchLabels: + # app.kubernetes.io/name: "private-ai" + # app.kubernetes.io/instance: "private-ai" + # matchLabelKeys: + # - "pod-template-hash" + # maxSkew: 1 + # topologyKey: "topology.kubernetes.io/zone" + # whenUnsatisfiable: "ScheduleAnyway" + + tolerations: + enabled: false + values: [] + # Use the following if you have added a taint to your nodes of app=private-ai + # values: + # - key: app + # operator: "Equal" + # value: "private-ai" + # effect: "NoSchedule" + + # There are the values for requests and limits + # https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits + limits: + enabled: false + memory: "12Gi" + cpu: "4" + + requests: + enabled: false + memory: "8Gi" + cpu: "3" + +# This section contains configuration for the kubernetes service for the deployment service: # Set the type for the service type: "LoadBalancer" @@ -48,129 +187,6 @@ service: # annotations: # service.beta.kubernetes.io/aws-load-balancer-internal: "true" -# These are the values for liveness, startup and readiness probes. -# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#probe-v1-core -livenessProbe: - enabled: false - initialDelaySeconds: 60 - periodSeconds: 60 - failureThreshold: 30 - timeoutSeconds: 1 -startupProbe: - # Note: You should expect to see warnings for startup probe failures in the pod events until the container starts - enabled: true - initialDelaySeconds: 5 - periodSeconds: 5 - failureThreshold: 23 - timeoutSeconds: 1 -readinessProbe: - enabled: true - initialDelaySeconds: 60 - periodSeconds: 20 - failureThreshold: 3 - timeoutSeconds: 1 - -# These are the values for the affinity -# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#volumenodeaffinity-v1-core -nodeAffinity: - enabled: false - values: {} -# Use the following to example to attempt to schedule nodes first on nodes with the label "private-ai-spot" -# and after on nodes with the label "private-ai" - # values: - # preferredDuringSchedulingIgnoredDuringExecution: - # - preference: - # matchExpressions: - # - key: "nodetype" - # operator: "In" - # values: - # - "private-ai" - # weight: 1 - # - preference: - # matchExpressions: - # - key: "nodetype" - # operator: "In" - # values: - # - "private-ai-spot" - # weight: 100 - -podAntiAffinity: - enabled: false - values: {} -# Recommended configuration to ensure only one Private AI container is scheduled per node: - # values: - # requiredDuringSchedulingIgnoredDuringExecution: - # - labelSelector: - # matchExpressions: - # - key: "app.kubernetes.io/name" - # operator: "In" - # values: - # - "private-ai" - # - key: "app.kubernetes.io/instance" - # operator: "In" - # values: - # - "private-ai" - # topologyKey: "kubernetes.io/hostname" - -topologySpreadConstraints: - enabled: false - values: [] -# Use the following if you would like to spread your pods evenly across your infrastructure zones - # values: - # - labelSelector: - # matchLabels: - # app.kubernetes.io/name: "private-ai" - # app.kubernetes.io/instance: "private-ai" - # matchLabelKeys: - # - "pod-template-hash" - # maxSkew: 1 - # topologyKey: "topology.kubernetes.io/zone" - # whenUnsatisfiable: "ScheduleAnyway" - -tolerations: - enabled: false - values: [] -# Use the following if you have added a taint to your nodes of app=private-ai - # values: - # - key: app - # operator: "Equal" - # value: "private-ai" - # effect: "NoSchedule" - -# There are the values for requests and limits -# https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits -limits: - enabled: false - memory: "12Gi" - cpu: "4" - -requests: - enabled: false - memory: "8Gi" - cpu: "3" - -# Settings for the Private AI license file -license: - # If you enable the External Secrets Operator, this section will be ignored - # Sets the name of the license secret object - name: "pai-license" - # Add optional annotations for the license secret. For more details see https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ - annotations: {} - # Example annotations - # annotations: - # annotation-key1: "annotation-value1" - # annotation-key2: "annotation-value2" - volumeMount: "license-volume" - # If you use the External Secrets Operator, you can ignore this setting as the license file will be populated via a secret - data: 'Override with your license data. See readme for more details' - -# Enter any environment variables for your deployment. You can find the list at https://docs.private-ai.com/environment-variables/ -envVars: [] -# Example environment variables: -# envVars: -# - name: "PAI_DISABLE_RAM_CHECK" -# value: "true" - # Configuration options for adding a kubernetes secret # This secret will be added to the environment variable for the Private AI deployment # If you use the External Secrets Operator, this section will be ignored