Saltar a contenido

HTG Iris API

The Iris API is the backend of the new ERP for HTG Express.

TL;DR

helm repo add htg https://charts.htg.example
helm install infra-iris-api htg/infra-iris-api

Introduction

This chart bootstraps a HTG Iris API deployment on a Kubernetes cluster using the Helm package manager.

Prerequisites

  • Kubernetes 1.20+
  • Helm 3.2.0+
  • PV provisioner support in the underlying infrastructure
  • KEDA 2.0+ (optional, for worker autoscaling)

Installing the chart

To install the chart with the release name infra-iris-api:

helm install infra-iris-api oci://registry-1.docker.io/htg/infra-iris-api

The command deploys HTG Iris API on the Kubernetes cluster in the default configuration. The Parameters section lists the parameters that can be configured during installation.

Tip: List all releases using helm list

Uninstalling the chart

To uninstall/delete the infra-iris-api deployment:

helm delete infra-iris-api

The command removes all the Kubernetes components associated with the chart and deletes the release.

Parameters

Global parameters

Name Description Value
nameOverride String to partially override common.names.fullname ""
fullnameOverride String to fully override common.names.fullname ""

Common parameters

Name Description Value
replicaCount Number of container replicas 1
strategy Pods replacement strategy type {}
podLabels Extra labels for pods {}
podAnnotations Annotations for pods {}
podSecurityContext Security context for pods {}
imagePullSecrets Image pull secrets for the application container []

Application image parameters

Name Description Value
image.repository Application image repository ""
image.tag Application image tag ""
image.pullPolicy Image pull policy "IfNotPresent"

ECR configuration parameters

Name Description Value
ecr.enabled Enable ECR integration false
ecr.serviceAccount.annotations ECR ServiceAccount annotations {}

Application configuration parameters

Name Description Value
configuration.additionalConfigMaps Dynamic ConfigMaps generation configuration {}
configuration.php PHP custom configuration {}
configuration.phpFpm.maxChildren Number of child processes in static pool "1"
configuration.phpFpm.maxRequests Number of requests per child before respawning "500"
configuration.phpFpm.port Port to listen on for PHP-FPM 9000

Container ports parameters

Name Description Value
containerPorts List of container ports to enable [{"name": "php-fpm", "containerPort": 9000, "protocol": "TCP"}]

Probes parameters

Name Description Value
readinessProbe.enabled Enable readiness probe "true"
readinessProbe.failureThreshold Failure threshold for readiness probe "5"
readinessProbe.initialDelaySeconds Initial delay for readiness probe "10"
readinessProbe.periodSeconds Period for readiness probe "10"
readinessProbe.port Port for readiness probe "9000"
readinessProbe.successThreshold Success threshold for readiness probe "1"
readinessProbe.timeoutSeconds Timeout for readiness probe "1"
livenessProbe.enabled Enable liveness probe "true"
livenessProbe.failureThreshold Failure threshold for liveness probe "5"
livenessProbe.initialDelaySeconds Initial delay for liveness probe "10"
livenessProbe.periodSeconds Period for liveness probe "10"
livenessProbe.port Port for liveness probe "9000"
livenessProbe.successThreshold Success threshold for liveness probe "1"
livenessProbe.timeoutSeconds Timeout for liveness probe "1"
customLivenessProbe Custom liveness probe configuration {}
customReadinessProbe Custom readiness probe configuration {}

Resources parameters

Name Description Value
resources Resource requests and limits for application {}
securityContext Security context for application container {}
extraVolumeMounts Extra volume mounts for application container []

NGINX parameters

Name Description Value
nginx.image.repository NGINX image repository "nginx"
nginx.image.tag NGINX image tag "stable"
nginx.image.pullPolicy NGINX image pull policy "IfNotPresent"
nginx.resources Resource requests and limits for NGINX {}
nginx.securityContext Security context for NGINX container {}
nginx.extraVolumeMounts Extra volume mounts for NGINX container []

PHP-FPM exporter parameters

Name Description Value
phpFpmExporter.enabled Enable PHP-FPM metrics exporter "true"
phpFpmExporter.image.repository PHP-FPM Exporter image repository "hipages/php-fpm_exporter"
phpFpmExporter.image.tag PHP-FPM Exporter image tag "v2.2"
phpFpmExporter.image.pullPolicy PHP-FPM Exporter image pull policy "IfNotPresent"
phpFpmExporter.resources Resource requests and limits for PHP-FPM exporter {}
phpFpmExporter.securityContext Security context for PHP-FPM exporter {}

Volume parameters

Name Description Value
extraVolumes Extra volumes for pods []

Scheduling parameters

Name Description Value
affinity Affinity for pod assignment {}
nodeSelector Node labels for pod assignment {}
tolerations Tolerations for pod assignment []

ServiceAccount parameters

Name Description Value
serviceAccount.create Create ServiceAccount true
serviceAccount.automount Automount ServiceAccount token true
serviceAccount.annotations ServiceAccount annotations {}
serviceAccount.name ServiceAccount name ""

Service parameters

Name Description Value
service.type Service type ClusterIP
service.port Service port 80

Autoscaling parameters

Name Description Value
autoscaling.enabled Enable autoscaling "false"
autoscaling.minReplicas Minimum number of replicas "1"
autoscaling.maxReplicas Maximum number of replicas "10"
autoscaling.targets.cpu CPU target for autoscaling ""
autoscaling.targets.phpFpmProcessUtilization PHP-FPM process utilization target ""

Ingress parameters

Name Description Value
ingress.enabled Enable ingress false
ingress.className Ingress class name ""
ingress.annotations Ingress annotations {}
ingress.hosts Ingress hosts configuration [{"host": "chart-example.local", "paths": [{"path": "/", "pathType": "ImplementationSpecific"}]}]
ingress.tls Ingress TLS configuration []

External secrets parameters

Name Description Value
externalSecrets.secretStores SecretStore or ClusterSecretStore definitions []
externalSecrets.secrets ExternalSecrets configuration []

Storage parameters

Name Description Value
storage.storageClasses List of StorageClass definitions to create []
storage.persistentVolumeClaims List of PVC definitions to create []

Jobs parameters

Name Description Value
jobs List of jobs to create []

Workers parameters

Name Description Value
workers List of worker deployments to create []

Worker autoscaling parameters (per worker)

Name Description Value
workers[].autoscaling.enabled Enable KEDA autoscaling for this worker false
workers[].autoscaling.minReplicaCount Minimum replicas (0 allows scale-to-zero) 0
workers[].autoscaling.maxReplicaCount Maximum replicas 10
workers[].autoscaling.pollingInterval Seconds between Redis queue checks 30
workers[].autoscaling.cooldownPeriod Seconds to wait before scaling down 300
workers[].autoscaling.trigger.address Redis server address (host:port) ""
workers[].autoscaling.trigger.databaseIndex Redis database index "0"
workers[].autoscaling.trigger.listName Redis list/queue name to monitor ""
workers[].autoscaling.trigger.listLength Message threshold to trigger scaling "5"
workers[].autoscaling.trigger.auth.secretName K8s secret with Redis credentials (optional) ""
workers[].autoscaling.trigger.auth.passwordKey Key in secret containing password "REDIS_PASSWORD"

Configuration and installation details

External secrets configuration

This chart supports integration with External Secrets Operator for managing secrets from external secret stores like AWS Secrets Manager, HashiCorp Vault, etc.

Example AWS Secrets Manager configuration:

externalSecrets:
  secretStores:
    - name: "aws-secrets-manager-store"
      provider:
        aws:
          service: "SecretsManager"
          region: "us-east-1"
          auth:
            jwt:
              serviceAccountRef:
                name: "my-app-sa"
  secrets:
    - name: "app-secrets"
      secretStoreRef:
        name: "aws-secrets-manager-store"
      data:
        - secretKey: "DATABASE_PASSWORD"
          remoteRef:
            key: "prod/app/database"
            property: "password"

Storage configuration

PersistentVolumeClaim creation

Create PVCs dynamically for your application storage needs:

storage:
  persistentVolumeClaims:
    - name: "uploads"
      spec:
        accessModes:
          - "ReadWriteMany"
        storageClassName: "efs-shared"
        resources:
          requests:
            storage: "10Gi"

Jobs configuration

Create Kubernetes Jobs for tasks like database migrations:

jobs:
  - name: "migrations"
    enabled: true
    command: ["bash", "-c"]
    args:
      - |
        php artisan migrate --force
    activeDeadlineSeconds: 300
    backoffLimit: 3
    annotations:
      "argocd.argoproj.io/hook": "PreSync"
      "argocd.argoproj.io/hook-delete-policy": "HookSucceeded"

Workers configuration

Create Laravel queue workers as separate deployments for processing background jobs:

workers:
  - name: "default-worker"
    enabled: true
    replicaCount: 2
    command: ["php"]
    args:
      - |
        artisan queue:work --sleep=3 --tries=3 --max-time=3600 --memory=512
    resources:
      limits:
        cpu: "500m"
        memory: "512Mi"
      requests:
        cpu: "100m"
        memory: "128Mi"
    env:
      - name: "QUEUE_CONNECTION"
        value: "redis"

Workers autoscaling with KEDA

Enable event-driven autoscaling for workers based on queue length using KEDA.

Prerequisites: KEDA must be installed in the cluster before enabling worker autoscaling.

Basic autoscaling configuration:

workers:
  - name: "default"
    enabled: true
    command: ["php"]
    args:
      - artisan queue:work --queue=default --sleep=3 --tries=3
    resources:
      requests:
        cpu: "100m"
        memory: "128Mi"
    autoscaling:
      enabled: true
      minReplicaCount: 1          # Keep at least 1 replica running
      maxReplicaCount: 10
      pollingInterval: 15         # Check queue every 15 seconds
      cooldownPeriod: 180         # Wait 3 minutes before scaling down
      trigger:
        address: "redis:6379"
        databaseIndex: "0"
        listName: "queues:default"
        listLength: "10"          # Scale up when queue has more than 10 messages
        auth:
          secretName: "app-secrets"
          passwordKey: "REDIS_PASSWORD"

Scale to zero configuration:

workers:
  - name: "notifications"
    enabled: true
    command: ["php"]
    args:
      - artisan queue:work --queue=notifications
    autoscaling:
      enabled: true
      minReplicaCount: 0          # Scale to zero when queue is empty
      maxReplicaCount: 5
      pollingInterval: 30
      cooldownPeriod: 300
      trigger:
        address: "redis:6379"
        listName: "queues:notifications"
        listLength: "5"
        auth:
          secretName: "app-secrets"
          passwordKey: "REDIS_PASSWORD"

Note: With minReplicaCount: 0, the first message may take up to pollingInterval seconds to be processed while KEDA scales up the first pod.

Redis without authentication:

workers:
  - name: "default"
    enabled: true
    command: ["php"]
    args:
      - artisan queue:work --queue=default
    autoscaling:
      enabled: true
      minReplicaCount: 1
      maxReplicaCount: 10
      trigger:
        address: "redis:6379"
        databaseIndex: "2"
        listName: "queues:default"
        listLength: "10"
        # No auth section needed for Redis without password

Multiple workers with different Redis instances:

Each worker can connect to a different Redis instance or database:

workers:
  - name: "emails"
    enabled: true
    command: ["php"]
    args:
      - artisan queue:work --queue=emails
    autoscaling:
      enabled: true
      minReplicaCount: 1
      maxReplicaCount: 20
      trigger:
        address: "redis-primary:6379"
        databaseIndex: "0"
        listName: "queues:emails"
        listLength: "10"
        auth:
          secretName: "redis-primary-secret"
          passwordKey: "REDIS_PASSWORD"

  - name: "external-api"
    enabled: true
    command: ["php"]
    args:
      - artisan queue:work --queue=external
    autoscaling:
      enabled: true
      minReplicaCount: 0
      maxReplicaCount: 5
      trigger:
        address: "redis-secondary:6379"
        databaseIndex: "2"
        listName: "queues:external"
        listLength: "5"
        auth:
          secretName: "redis-secondary-secret"
          passwordKey: "PASSWORD"

Configuration management

Additional configmaps

Create custom ConfigMaps for your application:

configuration:
  additionalConfigMaps:
    app:
      APP_NAME: "htg-iris"
      APP_ENV: "production"
    cache:
      REDIS_HOST: "redis.example.com"
      REDIS_PORT: "6379"

PHP configuration

Customize PHP settings:

configuration:
  php:
    date.timezone: "Europe/Madrid"
    memory_limit: "1024M"
    post_max_size: "100M"
    opcache.max_accelerated_files: "60000"

PHP-FPM configuration

Tune PHP-FPM settings:

configuration:
  phpFpm:
    maxChildren: "10"
    maxRequests: "1000"
    port: 9000

Autoscaling

CPU-based autoscaling

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 20
  targets:
    cpu: 70

PHP-FPM process utilization autoscaling

autoscaling:
  enabled: true
  minReplicas: 2
  maxReplicas: 20
  targets:
    phpFpmProcessUtilization: 80