cultivacore-api — Helm Chart v1.0.0

Kubernetes · GKE · Node.js API · CULTIVA IA — generado con skill andamiaje-charts-helm

✓ chart v1.0.0 app v2.3.1 Helm 3 · K8s ≥1.25 GKE · eu-west1
Chart
v1.0.0
cultivacore-api
App version
2.3.1
Node.js 18 · Express
Archivos template
9
+ 4 values files
Dependencias
2
PostgreSQL 15 + Redis 7
Arquitectura del despliegue
Internet
🌐 DNS
Ingress
🔒 TLS/NGINX
Service · ClusterIP
cultivacore-api
Deployment (HPA)
3–15 pods
Dep. PostgreSQL
🐘 pg 15

Dep. Redis
⚡ redis 7
cultivacore-api/Chart.yaml YAML
# Chart metadata — Helm 3+ (apiVersion: v2)
apiVersion: v2
name: cultivacore-api
description: Helm chart para la API de agentes de IA de CULTIVA IA
type: application
version: 1.0.0         # version del chart (SemVer)
appVersion: "2.3.1"    # version de la aplicacion Node.js

keywords:
  - ai-api
  - marketing-automation
  - backend
  - cultivaia

home: https://cultivaia.com
sources:
  - https://github.com/cultivaia/cultivacore-api

maintainers:
  - name: DevOps · CULTIVA IA
    email: devops@cultivaia.com
    url: https://github.com/cultivaia

kubeVersion: ">=1.25.0"

dependencies:
  - name: postgresql
    version: "12.12.10"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
    tags:
      - database

  - name: redis
    version: "18.6.1"
    repository: "https://charts.bitnami.com/bitnami"
    condition: redis.enabled
    tags:
      - cache

annotations:
  artifacthub.io/license: MIT
  artifacthub.io/maintainers: |
    - user: cultivaia-devops
cultivacore-api/values.yaml — defaults YAML
# -------------------------------------------------------------------
# cultivacore-api — valores por defecto (base)
# Sobreescribe con values-dev/staging/prod.yaml segun entorno
# -------------------------------------------------------------------

# Numero de replicas base
replicaCount: 2

image:
  repository: eu.gcr.io/cultivaia/cultivacore-api
  tag: ""           # vacio = usa .Chart.AppVersion (2.3.1)
  pullPolicy: IfNotPresent

imagePullSecrets:
  - name: gcr-pullsecret

nameOverride: ""
fullnameOverride: ""

serviceAccount:
  create: true
  annotations:
    # Workload Identity (GKE)
    iam.gke.io/gcp-service-account: cultivacore@cultivaia.iam.gserviceaccount.com
  name: ""

podAnnotations:
  prometheus.io/scrape: "true"
  prometheus.io/port: "9100"

podSecurityContext:
  runAsNonRoot: true
  runAsUser: 1001
  fsGroup: 1001

securityContext:
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true
  capabilities:
    drop: ["ALL"]

service:
  type: ClusterIP
  port: 80
  targetPort: 3000

ingress:
  enabled: false
  className: nginx
  annotations: {}
  hosts:
    - host: api.cultivaia.local
      paths:
        - path: /
          pathType: Prefix
  tls: []

resources:
  requests:
    memory: "128Mi"
    cpu: "100m"
  limits:
    memory: "256Mi"
    cpu: "250m"

autoscaling:
  enabled: false
  minReplicas: 2
  maxReplicas: 10
  targetCPUUtilizationPercentage: 70

# Variables de entorno (no secretas)
env:
  - name: NODE_ENV
    value: "development"
  - name: PORT
    value: "3000"
  - name: LOG_LEVEL
    value: "debug"
  - name: REDIS_URL
    value: "redis://cultivacore-api-redis-master:6379"

# Variables secretas (referenciadas desde Secret)
secretEnv:
  - name: DATABASE_URL
    secretName: cultivacore-api-secrets
    secretKey: database-url
  - name: OPENAI_API_KEY
    secretName: cultivacore-api-secrets
    secretKey: openai-api-key

# Dependencia: PostgreSQL (Bitnami)
postgresql:
  enabled: true
  auth:
    database: cultivacore
    username: cultivacore
    existingSecret: cultivacore-api-secrets
    secretKeys:
      userPasswordKey: db-password
  primary:
    persistence:
      enabled: true
      size: 10Gi

# Dependencia: Redis (Bitnami)
redis:
  enabled: true
  architecture: standalone
  auth:
    enabled: false
  master:
    persistence:
      enabled: false

nodeSelector: {}
tolerations: []
affinity: {}
cultivacore-api/values-prod.yaml — produccion YAML
# -------------------------------------------------------------------
# Produccion: GKE eu-west1 · 3–15 pods · TLS · HPA activo
# helm install cultivacore-api ./cultivacore-api \
#   -f values-prod.yaml --namespace production
# -------------------------------------------------------------------

replicaCount: 5

image:
  tag: "2.3.1"          # pin explícito en prod
  pullPolicy: Always    # siempre verificar imagen

env:
  - name: NODE_ENV
    value: "production"
  - name: PORT
    value: "3000"
  - name: LOG_LEVEL
    value: "info"
  - name: REDIS_URL
    value: "redis://cultivacore-api-redis-master:6379"

ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  hosts:
    - host: api.cultivaia.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: cultivacore-api-tls
      hosts:
        - api.cultivaia.com

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "1Gi"
    cpu: "1000m"

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 15
  targetCPUUtilizationPercentage: 70

postgresql:
  enabled: true
  primary:
    persistence:
      size: 100Gi
      storageClass: premium-rwo

redis:
  architecture: replication
  master:
    persistence:
      enabled: true
      size: 8Gi

affinity:
  podAntiAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchLabels:
            app.kubernetes.io/name: cultivacore-api
        topologyKey: kubernetes.io/hostname

podAnnotations:
  prometheus.io/scrape: "true"
  prometheus.io/port: "9100"
  cluster-autoscaler.kubernetes.io/safe-to-evict: "false"
cultivacore-api/values-dev.yaml — desarrollo YAML
# Desarrollo: recursos minimos, 1 replica, sin TLS, sin HPA
# helm install cultivacore-api ./cultivacore-api \
#   -f values-dev.yaml --namespace development

replicaCount: 1

image:
  pullPolicy: Always    # agiliza ciclo dev

env:
  - name: NODE_ENV
    value: "development"
  - name: LOG_LEVEL
    value: "debug"
  - name: PORT
    value: "3000"
  - name: REDIS_URL
    value: "redis://cultivacore-api-redis-master:6379"

resources:
  requests:
    memory: "64Mi"
    cpu: "50m"
  limits:
    memory: "128Mi"
    cpu: "100m"

postgresql:
  primary:
    persistence:
      size: 2Gi

redis:
  master:
    persistence:
      enabled: false
cultivacore-api/values-staging.yaml — staging YAML
# Staging: replica del setup prod con recursos reducidos
# helm install cultivacore-api ./cultivacore-api \
#   -f values-staging.yaml --namespace staging

replicaCount: 2

env:
  - name: NODE_ENV
    value: "staging"
  - name: LOG_LEVEL
    value: "info"
  - name: PORT
    value: "3000"
  - name: REDIS_URL
    value: "redis://cultivacore-api-redis-master:6379"

ingress:
  enabled: true
  hosts:
    - host: api-staging.cultivaia.com
      paths:
        - path: /
          pathType: Prefix

resources:
  requests:
    memory: "256Mi"
    cpu: "200m"
  limits:
    memory: "512Mi"
    cpu: "500m"

autoscaling:
  enabled: false

postgresql:
  primary:
    persistence:
      size: 20Gi
cultivacore-api/templates/deployment.yaml YAML · Helm
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "cultivacore-api.fullname" . }}
  labels:
    {{- include "cultivacore-api.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  revisionHistoryLimit: 5
  selector:
    matchLabels:
      {{- include "cultivacore-api.selectorLabels" . | nindent 6 }}
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      annotations:
        {{- toYaml .Values.podAnnotations | nindent 8 }}
      labels:
        {{- include "cultivacore-api.selectorLabels" . | nindent 8 }}
    spec:
      imagePullSecrets:
        {{- toYaml .Values.imagePullSecrets | nindent 8 }}
      serviceAccountName: {{ include "cultivacore-api.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.service.targetPort }}
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /health
              port: http
            initialDelaySeconds: 15
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /ready
              port: http
            initialDelaySeconds: 5
            periodSeconds: 5
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          env:
            {{- toYaml .Values.env | nindent 12 }}
            # Variables desde Secret
            {{- range .Values.secretEnv }}
            - name: {{ .name }}
              valueFrom:
                secretKeyRef:
                  name: {{ .secretName }}
                  key: {{ .secretKey }}
            {{- end }}
      affinity:
        {{- toYaml .Values.affinity | nindent 8 }}
      nodeSelector:
        {{- toYaml .Values.nodeSelector | nindent 8 }}
      tolerations:
        {{- toYaml .Values.tolerations | nindent 8 }}
cultivacore-api/templates/hpa.yaml YAML · Helm
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: {{ include "cultivacore-api.fullname" . }}
  labels:
    {{- include "cultivacore-api.labels" . | nindent 4 }}
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: {{ include "cultivacore-api.fullname" . }}
  minReplicas: {{ .Values.autoscaling.minReplicas }}
  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300   # 5 min antes de reducir
      policies:
        - type: Pods
          value: 1
          periodSeconds: 60
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
        - type: Pods
          value: 3
          periodSeconds: 60
{{- end }}
cultivacore-api/templates/pre-upgrade-migration.yaml YAML · Helm Hook
# Job de migracion de BD — se ejecuta antes de cada upgrade
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "cultivacore-api.fullname" . }}-db-migration
  labels:
    {{- include "cultivacore-api.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": pre-upgrade,pre-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
  backoffLimit: 3
  activeDeadlineSeconds: 300
  template:
    spec:
      serviceAccountName: {{ include "cultivacore-api.serviceAccountName" . }}
      restartPolicy: OnFailure
      containers:
        - name: db-migrate
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          command: ["node", "scripts/migrate.js"]
          env:
            - name: NODE_ENV
              value: {{ (index .Values.env 0).value | quote }}
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: cultivacore-api-secrets
                  key: database-url
          resources:
            requests:
              memory: "64Mi"
              cpu: "50m"
            limits:
              memory: "128Mi"
              cpu: "100m"
cultivacore-api/templates/_helpers.tpl Go Template
{{/*
Expand the name of the chart.
*/}}
{{- define "cultivacore-api.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
*/}}
{{- define "cultivacore-api.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Chart label helper
*/}}
{{- define "cultivacore-api.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "cultivacore-api.labels" -}}
helm.sh/chart: {{ include "cultivacore-api.chart" . }}
{{ include "cultivacore-api.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "cultivacore-api.selectorLabels" -}}
app.kubernetes.io/name: {{ include "cultivacore-api.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
ServiceAccount name
*/}}
{{- define "cultivacore-api.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "cultivacore-api.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Full image reference helper
*/}}
{{- define "cultivacore-api.image" -}}
{{- printf "%s:%s" .Values.image.repository (.Values.image.tag | default .Chart.AppVersion) }}
{{- end }}
cultivacore-api/templates/service.yaml YAML · Helm
apiVersion: v1
kind: Service
metadata:
  name: {{ include "cultivacore-api.fullname" . }}
  labels:
    {{- include "cultivacore-api.labels" . | nindent 4 }}
  {{- with .Values.service.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    {{- include "cultivacore-api.selectorLabels" . | nindent 4 }}
cultivacore-api/templates/ingress.yaml YAML · Helm
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "cultivacore-api.fullname" . }}
  labels:
    {{- include "cultivacore-api.labels" . | nindent 4 }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  {{- if .Values.ingress.className }}
  ingressClassName: {{ .Values.ingress.className }}
  {{- end }}
  {{- if .Values.ingress.tls }}
  tls:
    {{- range .Values.ingress.tls }}
    - hosts:
        {{- range .hosts }}
        - {{ . | quote }}
        {{- end }}
      secretName: {{ .secretName }}
    {{- end }}
  {{- end }}
  rules:
    {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
          {{- range .paths }}
          - path: {{ .path }}
            pathType: {{ .pathType }}
            backend:
              service:
                name: {{ include "cultivacore-api.fullname" $ }}
                port:
                  number: {{ $.Values.service.port }}
          {{- end }}
    {{- end }}
{{- end }}
cultivacore-api/templates/secret.yaml YAML · Helm
# Secret de ejemplo — en produccion usar External Secrets Operator
# o GCP Secret Manager con Workload Identity
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "cultivacore-api.fullname" . }}-secrets
  labels:
    {{- include "cultivacore-api.labels" . | nindent 4 }}
  annotations:
    # Evitar que helm borre el secret al desinstalar
    "helm.sh/resource-policy": keep
type: Opaque
stringData:
  # ATENCION: reemplazar con valores reales via --set o Sealed Secrets
  database-url: {{ .Values.secrets.databaseUrl | default "postgresql://cultivacore:CHANGEME@cultivacore-api-postgresql:5432/cultivacore" | quote }}
  openai-api-key: {{ .Values.secrets.openaiApiKey | default "sk-REPLACE_WITH_REAL_KEY" | quote }}
  db-password: {{ .Values.secrets.dbPassword | default "CHANGEME" | quote }}
cultivacore-api/templates/tests/test-connection.yaml YAML · Helm Test
apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "cultivacore-api.fullname" . }}-test-connection"
  labels:
    {{- include "cultivacore-api.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": test
    "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
spec:
  containers:
    - name: curl-test
      image: curlimages/curl:8.5.0
      command:
        - /bin/sh
        - -c
        - |
            set -e
            echo "Test 1: /health endpoint"
            curl -f -s http://{{ include "cultivacore-api.fullname" . }}:{{ .Values.service.port }}/health
            echo "Test 2: /ready endpoint"
            curl -f -s http://{{ include "cultivacore-api.fullname" . }}:{{ .Values.service.port }}/ready
            echo "Todos los tests pasaron"
      resources:
        requests: { memory: "16Mi", cpu: "10m" }
        limits: { memory: "32Mi", cpu: "50m" }
  restartPolicy: Never
cultivacore-api/templates/NOTES.txt Template Text
{{/* Post-install instructions shown by helm install/upgrade */}}

✅ CULTIVA IA — cultivacore-api desplegado con exito

Release:   {{ .Release.Name }}
Namespace: {{ .Release.Namespace }}
Chart:     {{ .Chart.Name }}-{{ .Chart.Version }}
App:       {{ .Chart.AppVersion }}

{{- if .Values.ingress.enabled }}
URL de acceso:
{{- range .Values.ingress.hosts }}
  https://{{ .host }}
{{- end }}
{{- else }}
Acceso via port-forward:
  kubectl port-forward svc/{{ include "cultivacore-api.fullname" . }} 3000:80 -n {{ .Release.Namespace }}
  curl http://localhost:3000/health
{{- end }}

Comandos utiles:
  helm status {{ .Release.Name }} -n {{ .Release.Namespace }}
  helm test {{ .Release.Name }} -n {{ .Release.Namespace }}
  kubectl logs -l app.kubernetes.io/name=cultivacore-api -n {{ .Release.Namespace }}

{{- if .Values.autoscaling.enabled }}
  HPA activo: {{ .Values.autoscaling.minReplicas }}–{{ .Values.autoscaling.maxReplicas }} replicas
{{- end }}
cultivacore-api/values.schema.json JSON Schema
{
  "$schema": "https://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["image", "service"],
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1,
      "description": "Numero de replicas del Deployment"
    },
    "image": {
      "type": "object",
      "required": ["repository"],
      "properties": {
        "repository": { "type": "string" },
        "tag": { "type": "string" },
        "pullPolicy": {
          "type": "string",
          "enum": ["Always", "IfNotPresent", "Never"]
        }
      }
    },
    "service": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string",
          "enum": ["ClusterIP", "NodePort", "LoadBalancer"]
        },
        "port": { "type": "integer", "minimum": 1 },
        "targetPort": { "type": "integer", "minimum": 1 }
      }
    },
    "autoscaling": {
      "type": "object",
      "properties": {
        "enabled": { "type": "boolean" },
        "minReplicas": { "type": "integer", "minimum": 1 },
        "maxReplicas": { "type": "integer", "minimum": 1 },
        "targetCPUUtilizationPercentage": {
          "type": "integer", "minimum": 1, "maximum": 100
        }
      }
    }
  }
}
cultivacore-api/.helmignore gitignore-style
# Excluir de helm package
.git/
.gitignore
.github/

# Dev
*.md
docs/
.env*
.vscode/
.idea/

# Build artifacts
*.swp
*.bak
*.tmp
*.orig

# CI/CD
.gitlab-ci.yml
.travis.yml
Makefile

# Tests locales
test/
*.test
**/__tests__/
Guia de despliegue — commandos completos BASH
## 1. Anadir repos de dependencias Bitnami
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update

## 2. Actualizar dependencias del chart
helm dependency update ./cultivacore-api

## 3. Lint — verificar sintaxis
helm lint ./cultivacore-api

## 4. Dry-run — preview sin desplegar
helm install cultivacore-api ./cultivacore-api \
  -f values-prod.yaml \
  --namespace production \
  --dry-run --debug

## 5. Instalar en PRODUCCION
helm install cultivacore-api ./cultivacore-api \
  -f values-prod.yaml \
  --namespace production \
  --create-namespace \
  --set secrets.openaiApiKey="sk-..." \
  --set secrets.dbPassword="SuperSecretPwd!" \
  --set secrets.databaseUrl="postgresql://cultivacore:SuperSecretPwd!@..." \
  --atomic --timeout 5m

## 6. Upgrade con migracion automatica
helm upgrade cultivacore-api ./cultivacore-api \
  -f values-prod.yaml \
  --namespace production \
  --atomic --timeout 10m

## 7. Verificar estado
helm status cultivacore-api -n production
kubectl get pods -n production -l app.kubernetes.io/name=cultivacore-api

## 8. Ejecutar tests Helm
helm test cultivacore-api -n production --logs

## 9. Empaquetar para distribucion
helm package ./cultivacore-api
# Genera: cultivacore-api-1.0.0.tgz

## 10. Rollback si algo falla
helm rollback cultivacore-api -n production
Comparativa de configuracion por entorno Tabla
Parametro DEV STAGING PRODUCCION
replicaCount 1 2 5
image.pullPolicy Always IfNotPresent Always
resources.requests.memory 64Mi 256Mi 512Mi
resources.requests.cpu 50m 200m 500m
resources.limits.memory 128Mi 512Mi 1Gi
autoscaling.enabled false false true
autoscaling.minReplicas 3
autoscaling.maxReplicas 15
ingress.enabled false true true
ingress.tls cultivacore-api-tls
ingress.host api.cultivaia.local api-staging.cultivaia.com api.cultivaia.com
NODE_ENV development staging production
LOG_LEVEL debug info info
postgresql.persistence.size 2Gi 20Gi 100Gi (premium-rwo)
redis.architecture standalone standalone replication
podAntiAffinity required (hostname)
Checklist de validacion pre-release Checklist
  • Chart.yaml con apiVersion v2 y semver correctohelm show chart ./cultivacore-api
  • Lint sin errores ni warnings criticoshelm lint ./cultivacore-api
  • Dependencias ancladas a version exactahelm dependency list
  • JSON Schema valida los values obligatorioshelm install --dry-run ...
  • Template rendering sin errores en los 3 entornoshelm template . -f values-prod.yaml
  • Secrets referenciados, no inline en valuesgrep -r "secretKeyRef" templates/
  • SecurityContext con runAsNonRoot=truekubectl auth can-i ...
  • Liveness y readiness probes configuradoskubectl describe pod ...
  • HPA activo en prod con politicas de scale-down conservadoraskubectl get hpa -n production
  • Hook de migracion con delete-policy y backoffLimitkubectl get jobs -n production
  • PodAntiAffinity en prod para distribucion en nodoskubectl get pod -o wide
  • Tests de conexion HTTP pasanhelm test cultivacore-api --logs
  • NOTES.txt con URL e instrucciones post-installhelm install --dry-run ...
  • Sealed Secrets o External Secrets Operator para secret.yaml en prodpendiente
  • NetworkPolicy para aislar namespace de produccionpendiente v1.1.0