Skip to content

Commit

Permalink
Refactor cm-service helm chart
Browse files Browse the repository at this point in the history
cm-service: Add vault-secrets template

cm-service: Add preinstall hook for db migration

cm-service: configure butler

cm-service: configure htcondor
  • Loading branch information
tcjennings committed Feb 18, 2025
1 parent 74f9820 commit 903c891
Show file tree
Hide file tree
Showing 20 changed files with 422 additions and 304 deletions.
4 changes: 2 additions & 2 deletions applications/cm-service/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
apiVersion: v2
appVersion: 0.1.2
appVersion: 0.2.0
description: Campaign Management for Rubin Data Release Production
name: cm-service
sources:
- https://github.com/lsst-dm/cm-service
- https://github.com/lsst-dm/cm-service
type: application
version: 1.0.0
46 changes: 28 additions & 18 deletions applications/cm-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,39 @@ Campaign Management for Rubin Data Release Production

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| config.databaseEcho | bool | `false` | Whether to echo SQLAlchemy generated SQL to the log |
| config.butler.repositories | object | `{}` | A mapping of butler repository names to their URIs that will be known to the service. |
| config.butler.storage | string | `"1Gi"` | Minimum storage requested in the butler remote area PVC |
| config.butler.storageClassName | string | `nil` | If specified, name of storage class requested in butler remote area PVC |
| config.butler.subPath | string | `nil` | If specified, sub-path within bound PV to be mounted as butler remote area |
| config.db.echo | bool | `false` | Whether to echo SQLAlchemy generated SQL to the log |
| config.db.hostname | string | `""` | Name of the database host |
| config.db.name | string | `"cmservice"` | Name of the database to use for the application |
| config.db.port | int | `5432` | Port number of the database host |
| config.db.username | string | `"cmservice"` | Name of the database user to use for the application |
| config.htcondor.collectorHost | string | `nil` | Name of an htcondor collector host |
| config.htcondor.fsRemoteDir.storage | string | `"1Gi"` | Minimum storage requested in the condor fs-remote PVC |
| config.htcondor.fsRemoteDir.storageClassName | string | `nil` | If specified, name of storage class requested for condor fs-remote PVC |
| config.htcondor.fsRemoteDir.subPath | string | `nil` | If specified, sub-path within bound PV to be mounted as condor fs-remote |
| config.htcondor.scheddHost | string | `nil` | If specified, name of an htcondor schedd host |
| config.logLevel | string | `"INFO"` | Logging level (`DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`) |
| config.logProfile | string | `"production"` | Logging profile (`production` for JSON, `development` for human-friendly) |
| config.outputVolume.storage | string | `"1Gi"` | Minimum storage requested in service output area PVC |
| config.outputVolume.storageClassName | string | `nil` | If specified, name of storage class requested in service output area PVC |
| config.outputVolume.subPath | string | `nil` | If specified, sub-path within bound PV to be mounted at service output area |
| config.pathPrefix | string | `"/cm-service/v1"` | URL path prefix |
| config.pathPrefix | string | `"/cm-service"` | URL path prefix |
| daemon.affinity | object | `{}` | Affinity rules for the daemon pods |
| daemon.image.pullPolicy | string | `"IfNotPresent"` | Pull policy for the daemon image |
| daemon.image.repository | string | `"ghcr.io/lsst-dm/cm-daemon"` | Image to use for daemon containers |
| daemon.image.tag | string | The appVersion of the chart | Tag of daemon image to use |
| daemon.nodeSelector | object | `{}` | Node selection rules for the daemon pods |
| daemon.podAnnotations | object | `{}` | Annotations for the daemon pods |
| daemon.replicaCount | int | `1` | Number of daemon pods to start |
| daemon.resources | object | See `values.yaml` | Resource limits and requests for the daemon pods |
| daemon.tolerations | list | `[]` | Tolerations for the daemon pods |
| frontend.affinity | object | `{}` | Affinity rules for the frontend pods |
| frontend.image.pullPolicy | string | `"IfNotPresent"` | Pull policy for the frontend image |
| frontend.image.repository | string | `"ghcr.io/lsst-dm/cm-service"` | Image to use for frontend containers |
| frontend.image.tag | string | The appVersion of the chart | Tag of frontend image to use |
| frontend.nodeSelector | object | `{}` | Node selector rules for the frontend pods |
| frontend.podAnnotations | object | `{}` | Annotations for the frontend pods |
| frontend.replicaCount | int | `1` | Number of frontend pods to start |
Expand All @@ -30,19 +55,4 @@ Campaign Management for Rubin Data Release Production
| image.repository | string | `"ghcr.io/lsst-dm/cm-service"` | Image to use for frontend containers |
| image.tag | string | The appVersion of the chart | Tag of frontend image to use |
| ingress.annotations | object | `{}` | Additional annotations for the frontend ingress rule |
| worker.affinity | object | `{}` | Affinity rules for the worker pods |
| worker.htcondor.config.contents | string | `nil` | If specified, contents of htcondor config file to be injected into worker containers |
| worker.htcondor.config.mountPath | string | `nil` | If specified, location for htcondor config file to be injected into worker containers |
| worker.htcondor.fsRemoteDir.storage | string | `"1Gi"` | Minimum storage requested in the condor remote area PVC |
| worker.htcondor.fsRemoteDir.storageClassName | string | `nil` | If specified, name of storage class requested in condor remote area PVC |
| worker.htcondor.fsRemoteDir.subPath | string | `nil` | If specified, sub-path within bound PV to be mounted as condor remote area |
| worker.htcondor.scheddAddress.contents | string | `nil` | If specified, location for htcondor schedd address file to be injected into worker pods |
| worker.htcondor.scheddAddress.mountPath | string | `nil` | If specified, contents of htcondor schedd address file to be injected into worker pods |
| worker.image.pullPolicy | string | `"IfNotPresent"` | Pull policy for the worker image |
| worker.image.repository | string | `"ghcr.io/lsst-dm/cm-service-worker"` | Image to use for worker containers |
| worker.image.tag | string | The appVersion of the chart | Tag of worker image to use |
| worker.nodeSelector | object | `{}` | Node selection rules for the worker pods |
| worker.podAnnotations | object | `{}` | Annotations for the worker pods |
| worker.replicaCount | int | `1` | Number of worker pods to start |
| worker.resources | object | See `values.yaml` | Resource limits and requests for the worker pods |
| worker.tolerations | list | `[]` | Tolerations for the worker pods |
| internalDB | bool | `false` | Whether to use the internal (phalanx) database |
16 changes: 8 additions & 8 deletions applications/cm-service/secrets.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
postgres-password:
description: >-
Password used to authenticate cm-service to its internal cnpg Postgres
server, deployed as part of the same Argo CD application. This secret can be
changed at any time, but the cm-service deployments will then have to be
restarted to pick up the new value.
generate:
type: password
# the database password has been generated in the postgres application; copy
# the secret from there if `internalDB` is set.
internalDatabasePassword:
description: "Password for the internal phalanx postgres database"
if: internalDB
copy:
application: postgres
key: cmservice_password
12 changes: 6 additions & 6 deletions applications/cm-service/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "cm-service.chart" -}}
{{- define "application.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "cm-service.labels" -}}
helm.sh/chart: {{ include "cm-service.chart" . }}
{{ include "cm-service.selectorLabels" . }}
{{- define "application.labels" -}}
helm.sh/chart: {{ include "application.chart" . }}
{{ include "application.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
Expand All @@ -20,7 +20,7 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
{{/*
Selector labels
*/}}
{{- define "cm-service.selectorLabels" -}}
app.kubernetes.io/name: "cm-service"
{{- define "application.selectorLabels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: "cm-service"
name: {{ .Chart.Name }}-server
labels:
{{- include "cm-service.labels" . | nindent 4 }}
{{- include "application.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.frontend.replicaCount }}
revisionHistoryLimit: 2
selector:
matchLabels:
{{- include "cm-service.selectorLabels" . | nindent 6 }}
{{- include "application.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: "frontend"
template:
metadata:
Expand All @@ -17,7 +18,7 @@ spec:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "cm-service.selectorLabels" . | nindent 8 }}
{{- include "application.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: "frontend"
spec:
{{- with .Values.frontend.affinity }}
Expand All @@ -26,23 +27,18 @@ spec:
{{- end }}
automountServiceAccountToken: false
containers:
- name: "cm-service"
- name: {{ .Chart.Name }}
envFrom:
- configMapRef:
name: {{ .Chart.Name }}-env
env:
- name: CM_DATABASE_PASSWORD
- name: BUTLER__MOCK
value: "1"
- name: DB__PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
- name: CM_URL_PREFIX
value: {{ .Values.config.pathPrefix | quote }}
- name: CM_DATABASE_URL
value: "postgresql://cm-service@cm-service-pg-rw/cm-service"
- name: CM_DATABASE_ECHO
value: {{ .Values.config.databaseEcho | quote }}
- name: CM_LOG_PROFILE
value: {{ .Values.config.logProfile | quote }}
- name: CM_LOG_LEVEL
value: {{ .Values.config.logLevel | quote }}
name: cm-service
key: internalDatabasePassword
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
Expand All @@ -51,7 +47,7 @@ spec:
protocol: "TCP"
readinessProbe:
httpGet:
path: "/"
path: "/healthz"
port: "http"
resources:
{{- toYaml .Values.frontend.resources | nindent 12 }}
Expand All @@ -61,16 +57,17 @@ spec:
drop:
- "all"
readOnlyRootFilesystem: true
# TODO: we hopefully do not actually need this mounted on the API
volumeMounts:
- mountPath: "/output"
{{- with .Values.config.outputVolume }}
- mountPath: {{ .mountPath }}
name: "output-volume"
{{- with .Values.config.outputVolume.subPath }}
subPath: {{ . }}
{{- end }}
subPath: {{ .subPath }}
{{- end }}
volumes:
- name: output-volume
persistentVolumeClaim:
claimName: cm-service-output
claimName: {{ .Chart.Name }}-output
{{- with .Values.frontend.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
Expand Down
39 changes: 39 additions & 0 deletions applications/cm-service/templates/configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Chart.Name }}-env"
labels:
{{- include "application.labels" . | nindent 4 }}
data:
ASGI__PREFIX: {{ .Values.config.pathPrefix | quote }}
{{- with .Values.config.db }}
DB__URL: "postgresql://{{ .username }}@{{ .hostname }}:{{ .port }}/{{ .name }}"
DB__ECHO: {{ .echo | quote }}
{{- end }}
LOGGING__PROFILE: {{ .Values.config.logProfile | quote }}
LOGGING__LEVEL: {{ .Values.config.logLevel | quote }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Chart.Name }}-butler-env"
labels:
{{- include "application.labels" . | nindent 4 }}
data:
DAF_BUTLER_REPOSITORIES: {{ toJson .Values.config.butler.repositories | quote }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Chart.Name }}-htcondor-env"
labels:
{{- include "application.labels" . | nindent 4 }}
data:
DAEMON__allocate_resources: "1"
HTCONDOR__schedd_host: {{ .Values.config.htcondor.scheddHost }}
HTCONDOR__collector_host: {{ .Values.config.htcondor.collectorHost }}
HTCONDOR__condor_home: /opt/htcondor
HTCONDOR__condor_submit_bin: /opt/htcondor/bin/condor_submit
HTCONDOR__condor_q_bin: /opt/htcondor/bin/condor_q
HTCONDOR__working_directory: /sdf/group/rubin/{{ .Values.config.outputVolume.subPath }}
HTCONDOR__fs_remote_dir: /sdf/group/rubin/services/htcondor/shared
11 changes: 11 additions & 0 deletions applications/cm-service/templates/daemon-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Chart.Name }}-config-daemon"
labels:
{{- include "application.labels" . | nindent 4 }}
data:
{{- with .Values.config.htcondor.config }}
config: |
{{- .contents | nindent 4 }}
{{- end }}
121 changes: 121 additions & 0 deletions applications/cm-service/templates/daemon-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Chart.Name }}-daemon
labels:
{{- include "application.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.daemon.replicaCount }}
revisionHistoryLimit: 2
selector:
matchLabels:
{{- include "application.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: "daemon"
template:
metadata:
annotations:
{{- with .Values.daemon.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "application.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: "daemon"
spec:
securityContext:
runAsUser: 17951
runAsGroup: 1126
fsGroup: 1126
runAsNonRoot: true
{{- with .Values.daemon.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
automountServiceAccountToken: false
containers:
- name: "{{ .Chart.Name }}-daemon"
image: "{{ .Values.daemon.image.repository }}:{{ .Values.daemon.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.daemon.image.pullPolicy }}
ports:
- name: "http"
containerPort: 8080
protocol: "TCP"
readinessProbe:
httpGet:
path: "/healthz"
port: "http"
livenessProbe:
httpGet:
path: "/healthz"
port: "http"
envFrom:
- configMapRef:
name: {{ .Chart.Name }}-env
- configMapRef:
name: {{ .Chart.Name }}-butler-env
- configMapRef:
name: {{ .Chart.Name }}-htcondor-env
env:
- name: BUTLER__AUTHENTICATION_FILE
value: "/var/run/secrets/db-auth.yaml"
- name: DB__PASSWORD
valueFrom:
secretKeyRef:
name: cm-service
key: internalDatabasePassword
resources:
{{- toYaml .Values.daemon.resources | nindent 12 }}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- "all"
readOnlyRootFilesystem: true
volumeMounts:
{{- with .Values.config.outputVolume }}
- mountPath: {{ .mountPath }}
name: output-volume
subPath: {{ .subPath }}
{{- end }}
{{- with .Values.config.butler }}
- mountPath: {{ .mountPath }}
name: butler-repo-volume
subPath: {{ .subPath }}
{{- end }}
- mountPath: "/tmp"
name: "tmp-volume"
{{- with .Values.config.htcondor.fsRemoteDir }}
- mountPath: {{ .mountPath }}
name: condor-remote-volume
subPath: {{ .subPath }}
{{- end }}
- name: butler-registry-volume
mountPath: "/var/run/secrets"
readonly: true
volumes:
- name: output-volume
persistentVolumeClaim:
claimName: {{ .Chart.Name }}-output
- name: butler-repo-volume
persistentVolumeClaim:
claimName: {{ .Chart.Name }}-butler
- name: tmp-volume
emptyDir:
sizeLimit: 500Mi
- name: condor-remote-volume
persistentVolumeClaim:
claimName: {{ $.Chart.Name }}-htcondor
- name: butler-registry-volume
secret:
secretName: cm-service-butler
items:
- key: butler-registry
path: db-auth.yaml
mode: 0600
{{- with .Values.daemon.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.daemon.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
Loading

0 comments on commit 903c891

Please sign in to comment.