diff --git a/deploy/helm/cassandra/helm/values.yaml b/deploy/helm/cassandra/helm/values.yaml index 95e650aa2..548905001 100644 --- a/deploy/helm/cassandra/helm/values.yaml +++ b/deploy/helm/cassandra/helm/values.yaml @@ -189,7 +189,7 @@ cassandra: # repository: must be supplied in additional values registry: "" repository: "" - tag: 0.11.0 + tag: 0.16.0 pullPolicy: Always dbUser: diff --git a/deploy/helm/event-ledger/Chart.yaml b/deploy/helm/event-ledger/Chart.yaml new file mode 100644 index 000000000..c48f09267 --- /dev/null +++ b/deploy/helm/event-ledger/Chart.yaml @@ -0,0 +1,24 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v2 +name: helm-nvcf-event-ledger +description: A Helm chart for NVCF Event Ledger deployment + +type: application + +version: 0.0.0 # autoversioning enabled via release pipeline + +appVersion: "0.10.2" diff --git a/deploy/helm/event-ledger/README.md b/deploy/helm/event-ledger/README.md new file mode 100644 index 000000000..325e00cc4 --- /dev/null +++ b/deploy/helm/event-ledger/README.md @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Event Ledger Helm Chart + +Helm chart for deploying the event-ledger service in a self-managed NVCF stack. + +## Prerequisites + +- Helm 3.x +- OpenBao (Vault) with the `22_setup_event-ledger.sh` migration applied (`nvcf-openbao-migrations` >= `0.18.0`). This migration provisions the JWT auth role, the secret paths that the Vault Agent sidecar reads, and the ServiceAccount binding. +- Cassandra with the `event_ledger` keyspace created by the `nvcf-cassandra-migrations` image (`>= 0.16.0`). +- An api-keys-api policy evaluator reachable at the address configured in `eventLedger.config.auth.policy.policy-evaluator-addr`. + +## Image settings + +`eventLedger.image.registry` and `eventLedger.image.repository` are required and have no defaults. Supply them at install time: + +```yaml +eventLedger: + image: + registry: + repository: +``` + +`appVersion` in `Chart.yaml` tracks the image tag used in `values.yaml`. Update both together when bumping the image. + +## Namespace and service name + +`eventLedger.fullnameOverride` defaults to `event-ledger`. This fixes the in-cluster DNS name to `event-ledger..svc.cluster.local:8080` regardless of the Helm release name, matching the service contract defined in the SADD (section 3.1). Do not change this unless the rest of the stack is updated to match. + +The namespace defaults to the Helm release namespace. Set `eventLedger.namespace` to override. + +## Override points + +- `eventLedger.image.registry` and `eventLedger.image.repository`: required, no defaults +- `eventLedger.replicaCount`: defaults to 1 +- `eventLedger.resources`: defaults are conservative; tune for your environment +- `eventLedger.config.database.cassandra.hosts`: defaults to `localhost`; set to the Cassandra service address in your stack +- `eventLedger.config.auth.policy.policy-evaluator-addr`: set to the api-keys-api address in your stack + +## API Keys policy evaluator + +In self-managed deployments, `EVENT_LEDGER_SELF_MANAGED=true` is set by default. This makes the service call the api-keys-api evaluation endpoint without a bearer token (the endpoint has no pre-authorize in self-managed mode). Set `eventLedger.config.auth.policy.policy-evaluator-addr` to the api-keys-api address. + +## Metrics + +Prometheus metrics are exposed on port 8081 at `/metrics`. The internal service port is always `8081`. To enable scraping, configure your Prometheus instance to scrape `event-ledger..svc.cluster.local:8081/metrics`. + +## Install example + +```bash +helm install event-ledger deploy/helm/event-ledger \ + --namespace event-ledger-system \ + --values deploy/helm/event-ledger/values.yaml \ + --set eventLedger.image.registry= \ + --set eventLedger.image.repository= \ + --wait +``` diff --git a/deploy/helm/event-ledger/files/secrets.json.tmpl b/deploy/helm/event-ledger/files/secrets.json.tmpl new file mode 100644 index 000000000..767b2d84b --- /dev/null +++ b/deploy/helm/event-ledger/files/secrets.json.tmpl @@ -0,0 +1,7 @@ +{{- with secret "services/event-ledger/kv/data/cassandra/creds" }} +{ + "username": {{ .Data.data.username | toJSON }}, + "password": {{ .Data.data.password | toJSON }}, + "policy-bearer-token": "self-managed" +} +{{- end }} diff --git a/deploy/helm/event-ledger/templates/NOTES.txt b/deploy/helm/event-ledger/templates/NOTES.txt new file mode 100644 index 000000000..987d3803a --- /dev/null +++ b/deploy/helm/event-ledger/templates/NOTES.txt @@ -0,0 +1,15 @@ +Event Ledger has been deployed. + +Service DNS (in-cluster): + {{ include "nvcf-event-ledger.fullname" . }}.{{ include "nvcf-event-ledger.namespace" . }}.svc.cluster.local:8080 + +Health check: + kubectl -n {{ include "nvcf-event-ledger.namespace" . }} port-forward svc/{{ include "nvcf-event-ledger.fullname" . }} 8080 + curl http://localhost:8080/health + +Metrics (Prometheus): + event-ledger.{{ include "nvcf-event-ledger.namespace" . }}.svc.cluster.local:8081 + +The Vault Agent sidecar injects /vault/secrets/secrets.json at pod start. +If the pod is stuck in Init:CrashLoopBackOff, check the Vault Agent sidecar +logs — the OpenBao role or secret path is likely missing from the migration. diff --git a/deploy/helm/event-ledger/templates/_helpers.tpl b/deploy/helm/event-ledger/templates/_helpers.tpl new file mode 100644 index 000000000..89a8d03f6 --- /dev/null +++ b/deploy/helm/event-ledger/templates/_helpers.tpl @@ -0,0 +1,146 @@ +{{/* +SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/}} + +{{/* +Expand the name of the chart. + +Defaults to the literal "event-ledger" rather than .Chart.Name so the +runtime service identity (resource names, selectors, container name) stays +stable and matches the in-cluster DNS contract (event-ledger.nvcf.svc), +independent of the OCI chart package name. Override via +.Values.eventLedger.nameOverride. +*/}} +{{- define "nvcf-event-ledger.name" -}} +{{- default "event-ledger" .Values.eventLedger.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "nvcf-event-ledger.fullname" -}} +{{- if .Values.eventLedger.fullnameOverride }} +{{- .Values.eventLedger.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default "event-ledger" .Values.eventLedger.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Allow the release namespace to be overridden via .Values.eventLedger.namespace, +falling back to .Release.Namespace. +*/}} +{{- define "nvcf-event-ledger.namespace" -}} +{{- default .Release.Namespace .Values.eventLedger.namespace -}} +{{- end -}} + +{{/* +Derive the full image reference. Fails the render if either image.registry +or image.repository is missing so the chart cannot install a default/invalid +image. +*/}} +{{- define "nvcf-event-ledger.image" -}} +{{- $registry := required "A valid image registry (.Values.eventLedger.image.registry) is required!" .Values.eventLedger.image.registry -}} +{{- $repository := required "A valid image repository (.Values.eventLedger.image.repository) is required!" .Values.eventLedger.image.repository -}} +{{- $name := .Values.eventLedger.image.name | default "event-ledger" -}} +{{- $tag := .Values.eventLedger.image.tag | default .Chart.AppVersion -}} +{{- printf "%s/%s/%s:%s" $registry $repository $name $tag -}} +{{- end -}} + +{{/* +OpenBao projected service-account token helpers. These four helpers define +the chart-owned contract for the Vault Agent Kubernetes auto-auth token volume. +Use these in annotations and the workload template instead of repeating literals. +*/}} +{{- define "nvcf-event-ledger.openbaoTokenVolumeName" -}} +openbao-token +{{- end -}} + +{{- define "nvcf-event-ledger.openbaoTokenMountPath" -}} +/var/run/secrets/openbao +{{- end -}} + +{{- define "nvcf-event-ledger.openbaoTokenFileName" -}} +token +{{- end -}} + +{{- define "nvcf-event-ledger.openbaoTokenPath" -}} +{{- printf "%s/%s" (include "nvcf-event-ledger.openbaoTokenMountPath" .) (include "nvcf-event-ledger.openbaoTokenFileName" .) -}} +{{- end -}} + +{{/* +Hashicorp Vault Agent Injector annotations. Always rendered onto the pod +so the injector mints /vault/secrets/secrets.json at pod start from the +OpenBao secret paths. The template content is rendered into a ConfigMap by +templates/configmap-vault-agent-template.yaml and mounted into the pod at +/vault/config/templates. +*/}} +{{- define "nvcf-event-ledger.vaultAnnotations" -}} +{{- $role := required "A valid Vault auth role (.Values.eventLedger.vault.role) is required!" .Values.eventLedger.vault.role -}} +vault.hashicorp.com/agent-inject: "true" +vault.hashicorp.com/role: {{ $role | quote }} +vault.hashicorp.com/auth-path: {{ .Values.eventLedger.vault.jwtAuthPath | default "auth/jwt" | quote }} +vault.hashicorp.com/agent-service-account-token-volume-name: {{ include "nvcf-event-ledger.openbaoTokenVolumeName" . | quote }} +vault.hashicorp.com/auth-config-token-path: {{ include "nvcf-event-ledger.openbaoTokenPath" . | quote }} +vault.hashicorp.com/agent-copy-volume-mounts: {{ include "nvcf-event-ledger.fullname" . | quote }} +vault.hashicorp.com/agent-inject-template-file-secrets.json: "/vault/config/templates/secrets.json.tmpl" +vault.hashicorp.com/secret-volume-path: "/vault/secrets" +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "nvcf-event-ledger.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "nvcf-event-ledger.labels" -}} +helm.sh/chart: {{ include "nvcf-event-ledger.chart" . }} +{{ include "nvcf-event-ledger.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "nvcf-event-ledger.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nvcf-event-ledger.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "nvcf-event-ledger.serviceAccountName" -}} +{{- if .Values.eventLedger.serviceAccount.create }} +{{- default (include "nvcf-event-ledger.fullname" .) .Values.eventLedger.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.eventLedger.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/deploy/helm/event-ledger/templates/configmap-app.yaml b/deploy/helm/event-ledger/templates/configmap-app.yaml new file mode 100644 index 000000000..dbf6ebbbe --- /dev/null +++ b/deploy/helm/event-ledger/templates/configmap-app.yaml @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "nvcf-event-ledger.fullname" . }}-app-config + namespace: {{ include "nvcf-event-ledger.namespace" . }} + labels: + {{- include "nvcf-event-ledger.labels" . | nindent 4 }} +data: + # Application YAML config mounted at /etc/event-ledger/config.yaml. + # The container reads it via EVENT_LEDGER_CONFIG env var (see deployment.yaml). + # Credentials (username, password, policy-bearer-token) are not here; + # they are injected by Vault Agent into /vault/secrets/secrets.json. + config.yaml: | + {{- toYaml .Values.eventLedger.config | nindent 4 }} diff --git a/deploy/helm/event-ledger/templates/configmap-vault-agent-template.yaml b/deploy/helm/event-ledger/templates/configmap-vault-agent-template.yaml new file mode 100644 index 000000000..f928abc14 --- /dev/null +++ b/deploy/helm/event-ledger/templates/configmap-vault-agent-template.yaml @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "nvcf-event-ledger.fullname" . }}-vault-agent-tpl + namespace: {{ include "nvcf-event-ledger.namespace" . }} + labels: + {{- include "nvcf-event-ledger.labels" . | nindent 4 }} +data: + # Vault Agent template rendered into /vault/secrets/secrets.json on pod start. + # The service reads username/password for Cassandra and policy-bearer-token + # for the api-keys-api policy evaluator from this file (run_service.go). + # Secret paths match what 22_setup_event-ledger.sh provisions in OpenBao. + secrets.json.tmpl: | + {{- .Files.Get "files/secrets.json.tmpl" | nindent 4 }} diff --git a/deploy/helm/event-ledger/templates/deployment.yaml b/deploy/helm/event-ledger/templates/deployment.yaml new file mode 100644 index 000000000..2e5c24053 --- /dev/null +++ b/deploy/helm/event-ledger/templates/deployment.yaml @@ -0,0 +1,125 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "nvcf-event-ledger.fullname" . }} + namespace: {{ include "nvcf-event-ledger.namespace" . }} + labels: + {{- include "nvcf-event-ledger.labels" . | nindent 4 }} +spec: + {{- if not .Values.eventLedger.autoscaling.enabled }} + replicas: {{ .Values.eventLedger.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "nvcf-event-ledger.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + {{- include "nvcf-event-ledger.vaultAnnotations" . | nindent 8 }} + checksum/config-app: {{ toYaml .Values.eventLedger.config | sha256sum }} + checksum/vault-agent-template: {{ .Files.Get "files/secrets.json.tmpl" | sha256sum }} + {{- with .Values.eventLedger.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "nvcf-event-ledger.selectorLabels" . | nindent 8 }} + {{- with .Values.eventLedger.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.eventLedger.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "nvcf-event-ledger.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.eventLedger.podSecurityContext | nindent 8 }} + volumes: + - name: vault-config-templates + configMap: + name: {{ include "nvcf-event-ledger.fullname" . }}-vault-agent-tpl + items: + - key: secrets.json.tmpl + path: secrets.json.tmpl + - name: app-config + configMap: + name: {{ include "nvcf-event-ledger.fullname" . }}-app-config + items: + - key: config.yaml + path: config.yaml + - name: {{ include "nvcf-event-ledger.openbaoTokenVolumeName" . }} + projected: + sources: + - serviceAccountToken: + audience: {{ .Values.eventLedger.vault.audience | quote }} + expirationSeconds: 3600 + path: {{ include "nvcf-event-ledger.openbaoTokenFileName" . }} + {{- with .Values.eventLedger.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ include "nvcf-event-ledger.fullname" . }} + securityContext: + {{- toYaml .Values.eventLedger.securityContext | nindent 12 }} + image: {{ include "nvcf-event-ledger.image" . | quote }} + imagePullPolicy: {{ .Values.eventLedger.image.pullPolicy }} + volumeMounts: + - name: vault-config-templates + mountPath: /vault/config/templates + readOnly: true + - name: app-config + mountPath: /etc/event-ledger + readOnly: true + - name: {{ include "nvcf-event-ledger.openbaoTokenVolumeName" . }} + mountPath: {{ include "nvcf-event-ledger.openbaoTokenMountPath" . }} + readOnly: true + {{- with .Values.eventLedger.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + env: + # Point the service at the mounted config file. + - name: EVENT_LEDGER_CONFIG + value: /etc/event-ledger/config.yaml + {{- range $key, $value := .Values.eventLedger.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + ports: + {{- range .Values.eventLedger.ports }} + - name: {{ .name }} + containerPort: {{ .containerPort }} + protocol: {{ .protocol }} + {{- end }} + livenessProbe: + {{- toYaml .Values.eventLedger.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.eventLedger.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.eventLedger.resources | nindent 12 }} + {{- with .Values.eventLedger.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.eventLedger.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.eventLedger.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/deploy/helm/event-ledger/templates/hpa.yaml b/deploy/helm/event-ledger/templates/hpa.yaml new file mode 100644 index 000000000..de7543628 --- /dev/null +++ b/deploy/helm/event-ledger/templates/hpa.yaml @@ -0,0 +1,52 @@ +{{/* +SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/}} + +{{- if .Values.eventLedger.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "nvcf-event-ledger.fullname" . }} + namespace: {{ include "nvcf-event-ledger.namespace" . }} + labels: + {{- include "nvcf-event-ledger.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "nvcf-event-ledger.fullname" . }} + minReplicas: {{ .Values.eventLedger.autoscaling.minReplicas }} + maxReplicas: {{ .Values.eventLedger.autoscaling.maxReplicas }} + {{- if or .Values.eventLedger.autoscaling.targetCPUUtilizationPercentage .Values.eventLedger.autoscaling.targetMemoryUtilizationPercentage }} + metrics: + {{- if .Values.eventLedger.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.eventLedger.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.eventLedger.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.eventLedger.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} + {{- end }} +{{- end }} diff --git a/deploy/helm/event-ledger/templates/service.yaml b/deploy/helm/event-ledger/templates/service.yaml new file mode 100644 index 000000000..9418fad98 --- /dev/null +++ b/deploy/helm/event-ledger/templates/service.yaml @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: Service +metadata: + name: {{ include "nvcf-event-ledger.fullname" . }} + namespace: {{ include "nvcf-event-ledger.namespace" . }} + labels: + {{- include "nvcf-event-ledger.labels" . | nindent 4 }} +spec: + type: {{ .Values.eventLedger.service.type }} + ports: + {{- range .Values.eventLedger.service.ports }} + - port: {{ .port }} + targetPort: {{ .targetPort }} + protocol: {{ .protocol }} + name: {{ .name }} + {{- end }} + selector: + {{- include "nvcf-event-ledger.selectorLabels" . | nindent 4 }} diff --git a/deploy/helm/event-ledger/templates/serviceaccount.yaml b/deploy/helm/event-ledger/templates/serviceaccount.yaml new file mode 100644 index 000000000..6899781d4 --- /dev/null +++ b/deploy/helm/event-ledger/templates/serviceaccount.yaml @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +{{- if .Values.eventLedger.serviceAccount.create }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "nvcf-event-ledger.serviceAccountName" . }} + namespace: {{ include "nvcf-event-ledger.namespace" . }} + labels: + {{- include "nvcf-event-ledger.labels" . | nindent 4 }} + {{- with .Values.eventLedger.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.eventLedger.serviceAccount.automount }} +{{- end }} diff --git a/deploy/helm/event-ledger/templates/validation.yaml b/deploy/helm/event-ledger/templates/validation.yaml new file mode 100644 index 000000000..4c0d86a74 --- /dev/null +++ b/deploy/helm/event-ledger/templates/validation.yaml @@ -0,0 +1,36 @@ +{{/* +SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +SPDX-License-Identifier: Apache-2.0 + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/}} + +{{/* +Validation template for required runtime configuration. +Fails the render if any required value is missing so the chart cannot +install into a state that will only fail at runtime. +*/}} + +{{- if not .Values.eventLedger.config.auth.policy.policy_evaluator_addr }} +{{- if not (index .Values.eventLedger.config.auth.policy "policy-evaluator-addr") }} + {{- fail "eventLedger.config.auth.policy.policy-evaluator-addr is required" }} +{{- end }} +{{- end }} + +{{- if not (index .Values.eventLedger.config.auth "jwk-set-url") }} + {{- fail "eventLedger.config.auth.jwk-set-url is required" }} +{{- end }} + +{{- if false }} +# This template is used only for validation and produces no output. +{{- end }} diff --git a/deploy/helm/event-ledger/values.yaml b/deploy/helm/event-ledger/values.yaml new file mode 100644 index 000000000..5a43574c6 --- /dev/null +++ b/deploy/helm/event-ledger/values.yaml @@ -0,0 +1,185 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Default values for the nvcf-event-ledger chart. All service-owned keys live +# under the eventLedger root so the chart's value API is namespaced and will +# not collide with values from other releases when this chart is composed +# into the self-hosted stack. +eventLedger: + + # Namespace to deploy the resources. If empty, the release namespace is used. + namespace: "" + + # Override the runtime service identity (resource names / selectors / + # container name). Defaults to "event-ledger" so the Service DNS + # (event-ledger..svc) matches the contract defined in the SADD + # (section 3.1), independent of the chart package name or release name. + nameOverride: "" + fullnameOverride: "event-ledger" + + replicaCount: 1 + + image: + registry: "" + repository: "" + # Image name is chart-owned and appended to registry/repository. + name: "nvcf-event-ledger" + pullPolicy: IfNotPresent + tag: "0.10.2" + + imagePullSecrets: [] + + serviceAccount: + create: true + automount: false + annotations: {} + # ServiceAccount name must match the JWT auth role provisioned by the + # nvcf-openbao-migrations 22_setup_event-ledger migration. The Vault Agent + # Injector will not authenticate the pod to OpenBao unless the SA name + # matches the role's bound subject. + name: "event-ledger" + + podAnnotations: {} + podLabels: {} + + podSecurityContext: {} + securityContext: + allowPrivilegeEscalation: false + runAsNonRoot: true + capabilities: + drop: + - ALL + + service: + type: ClusterIP + ports: + - name: api-port + port: 8080 + targetPort: 8080 + protocol: TCP + - name: metrics + port: 8081 + targetPort: 8081 + protocol: TCP + + resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 250m + memory: 256Mi + + livenessProbe: + httpGet: + path: /health + port: api-port + readinessProbe: + httpGet: + path: /health + port: api-port + + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 3 + targetCPUUtilizationPercentage: 80 + + # Hashicorp Vault Agent Injector wiring. The chart always renders the + # vault.hashicorp.com/* pod annotations so the injector mints + # /vault/secrets/secrets.json at pod start from the OpenBao secret paths. + # The pod's ServiceAccount must be bound to a JWT auth role in OpenBao + # provisioned by the nvcf-openbao-migrations event-ledger migration. + vault: + role: "event-ledger" + jwtAuthPath: "auth/jwt" + # audience must match the JWT auth role's bound_audiences in OpenBao, + # which the 22_setup_event-ledger migration sets to the internal OpenBao URL. + audience: "http://openbao-server.vault-system.svc.cluster.local:8200" + + extraVolumes: [] + extraVolumeMounts: [] + + nodeSelector: {} + tolerations: [] + affinity: {} + + ports: + - name: api-port + containerPort: 8080 + protocol: TCP + - name: metrics + containerPort: 8081 + protocol: TCP + + # Environment variables passed to the container. + env: + # Tracing is opt-in. Leave empty to disable; set to an OTLP collector + # endpoint to enable. + OTEL_EXPORTER_OTLP_ENDPOINT: "" + EVENT_LEDGER_SELF_MANAGED: "true" + + # Application configuration rendered into /etc/event-ledger/config.yaml. + # Credentials (username, password, policy-bearer-token) are not set here; + # they are injected at runtime by Vault Agent into /vault/secrets/secrets.json + # and loaded by the service on startup (cfg.SecretsPath default). + config: + auth: + enabled: true + # Use the "policy" provider in self-managed so external read requests + # are validated against api-keys-api (section 3.3 of the SADD). + provider: "policy" + # JWKS endpoint for event-ledger's own JWT engine in OpenBao. + # SIS, NVCA, and NVCF-API sign tokens against this engine; event-ledger + # fetches these public keys to verify their inbound requests. + jwk-set-url: "http://openbao-server.vault-system.svc.cluster.local:8200/v1/services/event-ledger/jwt/jwks" + cache-refresh-interval: 900 + policy: + namespace: "event-ledger" + policy-fqdn: "apikey.allow" + # In-cluster address of the api-keys-api policy evaluator. + policy-evaluator-addr: "http://api-keys.api-keys.svc.cluster.local:8080" + subject-field: "subject" + # api-keys-api expects "apiKey" (not "starfleetApiKey") per SADD §3.3. + api-key-field: "apiKey" + database: + provider: "cassandra" + cassandra: + hosts: + - "cassandra.cassandra-system.svc.cluster.local" + port: 9042 + keyspace: "event_ledger" + consistency: "LOCAL_QUORUM" + num-conns: 2 + insecure-skip-verify: false + service: + api-port: 8080 + internal-port: 8081 + # V1 and V2 endpoints are disabled in self-hosted per SADD §3.4. + deprecate-endpoints: true + publisher: + # CloudEvents (Kratos) is not available in self-managed; disable it. + cloudevents: + enabled: false + batched: + queue-size: 100000 + batch-size: 1000 + batch-interval-seconds: 10 + logging: + level: "info" + zap-configuration: "production" + telemetry: + servicename: "event-ledger-api" + environmentname: "self-managed" diff --git a/deploy/helm/openbao/helm/values.yaml b/deploy/helm/openbao/helm/values.yaml index 0dd537f07..c4dba4558 100644 --- a/deploy/helm/openbao/helm/values.yaml +++ b/deploy/helm/openbao/helm/values.yaml @@ -46,7 +46,7 @@ openbao: image: registry: "" repository: "" - tag: 0.16.2 + tag: 0.18.0 pullPolicy: IfNotPresent issuerDiscovery: enabled: false