This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Installation

Install Krkn Operator using Helm

Krkn Operator documentation v1.1.0; captured October 13, 2026 from website commit 3b059252814d83dc2ff56caa6031603229ed9cdf.

    Installation Admin

    Deploy Krkn Operator on Kubernetes or OpenShift using Helm.

    Upgrade from 1.0.x to 1.1.0

    Upgrade an existing Helm release in place. The 1.1.x chart includes hooks that preserve existing custom resources while the operator updates their Custom Resource Definitions (CRDs) and migrates legacy run fields. Upgrading from 1.0.x to 1.1.x with helm upgrade does not require deleting CRDs or recreating runs, and is designed to preserve existing run data. Back up your configuration before upgrading.

    1. Confirm the release name and namespace, and save the current Helm values for reference:

      # Set these to your existing installation.
      RELEASE_NAME=krkn-operator
      RELEASE_NAMESPACE=krkn-operator-system
      helm list --namespace "$RELEASE_NAMESPACE"
      helm get values "$RELEASE_NAME" --namespace "$RELEASE_NAMESPACE" -o yaml > krkn-operator-values-backup.yaml
      
    2. Upgrade the existing release to chart version 1.1.0, retaining its configured values:

      helm upgrade "$RELEASE_NAME" oci://quay.io/krkn-chaos/charts/krkn-operator \
        --version 1.1.0 \
        --namespace "$RELEASE_NAMESPACE" \
        --reuse-values \
        --wait \
        --timeout 10m
      
    3. Check the release and operator pods:

      helm status "$RELEASE_NAME" --namespace "$RELEASE_NAMESPACE"
      kubectl get pods -n "$RELEASE_NAMESPACE" -l app.kubernetes.io/name=krkn-operator
      

    During the upgrade, a pre-upgrade hook saves legacy run fields and pauses run reconciliation. After the new operator starts, a post-upgrade hook updates the CRDs, completes the run migration, and resumes reconciliation. Helm does not upgrade files in a chart’s crds/ directory by itself; the operator’s upgrade hooks handle that step. While the migration guard exists in the release namespace, scenario and graph run creation and mutation requests return HTTP 503. The hook jobs have a six-minute deadline. If a hook fails, the guard remains active: inspect the hook logs, fix the reported cause, then retry the same helm upgrade command. The hooks resume from saved migration annotations. For an individually blocked run, restore its missing current-API scenario or graph identity and, for private scenarios, its registry name before retrying. Do not remove the guard to bypass an incomplete migration.


    Prerequisites

    • Kubernetes 1.19+ or OpenShift 4.x
    • Helm 3.0+

    Quick Start

    Helm chart version for this release: 1.1.0

    helm install krkn-operator oci://quay.io/krkn-chaos/charts/krkn-operator \
      --version 1.1.0 \
      --namespace krkn-operator-system \
      --create-namespace
    

    Verify:

    kubectl get pods -n krkn-operator-system -l app.kubernetes.io/name=krkn-operator
    

    Access the console (local):

    kubectl port-forward -n krkn-operator-system svc/krkn-operator-console 3000:3000
    

    Production Installation

    Choose the method that matches your environment:

    MethodExternal Access
    KubernetesGateway API (recommended) or Ingress
    OpenShiftRoutes (native)

    Install with a custom values.yaml:

    helm install krkn-operator oci://quay.io/krkn-chaos/charts/krkn-operator \
      --version 1.1.0 \
      --namespace krkn-operator-system \
      --create-namespace \
      -f values.yaml
    

    Kubernetes with Gateway API

    console:
      enabled: true
      gateway:
        enabled: true
        gatewayName: krkn-gateway
        hostname: krkn.example.com
        path: /
        pathType: PathPrefix
    

    Kubernetes with Ingress

    console:
      enabled: true
      ingress:
        enabled: true
        className: nginx
        hostname: krkn.example.com
        tls:
          - secretName: krkn-tls
            hosts:
              - krkn.example.com
    

    OpenShift with Routes

    console:
      enabled: true
      route:
        enabled: true
        hostname: krkn.apps.cluster.example.com
        tls:
          enabled: true
          termination: edge
          insecureEdgeTerminationPolicy: Redirect
    

    OCM/ACM Integration

    Enable automatic cluster discovery through Open Cluster Management (OCM) or Red Hat Advanced Cluster Management (ACM):

    See the OCM/ACM Compatibility page for tested versions.

    helm install krkn-operator oci://quay.io/krkn-chaos/charts/krkn-operator \
      --version 1.1.0 \
      --namespace krkn-operator-system \
      --create-namespace \
      --set acm.enabled=true
    

    Uninstall

    helm uninstall krkn-operator --namespace krkn-operator-system
    

    Complete values.yaml Reference

    Click to expand the full values.yaml reference
    # Default values for krkn-operator
    # This is a YAML-formatted file.
    
    ## Global settings
    global:
      # Namespace where to install (if empty, uses Release.Namespace)
      namespaceOverride: ""
    ## Images configuration
    # NOTE: Tags are automatically updated during release by CI/CD workflow
    # - Operator & Data Provider: match the release tag (e.g., v0.4.3-beta)
    # - ACM: frozen to latest stable ACM tag at release time
    # - Console: frozen to latest stable Console tag at release time
    # Local development: uses :latest tags for all components
    images:
      operator:
        image: krkn-chaos.docker.scarf.sh/krkn-chaos/krkn-operator:v1.1.0-rc7
        pullPolicy: IfNotPresent
      dataProvider:
        image: krkn-chaos.docker.scarf.sh/krkn-chaos/krkn-operator-data-provider:v1.1.0-rc7
        pullPolicy: IfNotPresent
      acm:
        image: krkn-chaos.docker.scarf.sh/krkn-chaos/krkn-operator-acm:v1.1.0-rc3
        pullPolicy: IfNotPresent
      console:
        image: krkn-chaos.docker.scarf.sh/krkn-chaos/krkn-operator-console:v1.1.0-rc8
        pullPolicy: IfNotPresent
      pullSecrets: []
      # - name: my-registry-secret
    ## Authentication & Security
    auth:
      # JWT secret for token signing (base64 encoded)
      # If empty, a random one is generated by Helm
      # To provide your own: echo -n "your-secret-key" | base64
      jwtSecret: ""
      # JWT token expiry in hours (default: 24)
      # Passed to operator as JWT_EXPIRY_HOURS environment variable
      jwtExpiryHours: 24
      # Trusted reverse-proxy / load-balancer networks (comma-separated CIDRs).
      # Passed to the operator as the TRUSTED_PROXY_CIDRS environment variable.
      #
      # The auth endpoints (/api/v1/auth/register, /login, /is-registered) are
      # rate-limited per client IP. When the operator sits behind an ingress,
      # reverse proxy, or load balancer, the direct connection address is the
      # proxy's, so every client would share a single rate-limit bucket. Setting
      # this to the proxy network(s) makes the operator read the real client IP
      # from the X-Forwarded-For / X-Real-IP headers — but ONLY when the request
      # actually arrives from one of these CIDRs.
      #
      # Leave empty (default) when the operator is reached directly: forwarding
      # headers are then ignored and the connection address is used, so clients
      # cannot spoof the rate-limit key. Only set this if you trust the listed
      # networks to set the forwarding headers correctly.
      #
      # Example: "10.0.0.0/8,192.168.0.0/16"
      trustedProxyCIDRs: ""
      # WebSocket Origin enforcement (comma-separated list of allowed origins).
      # Passed to the operator as the WEBSOCKET_ALLOWED_ORIGINS environment variable.
      #
      # There IS an optional Origin-based access control for WebSocket upgrades
      # (cluster terminal, live log streaming), but it is OPT-IN and OFF by default:
      #
      #   - Empty (default): all origins are accepted. This is safe because
      #     WebSocket connections authenticate with a JWT sent in the
      #     Sec-WebSocket-Protocol subprotocol (not browser cookies), so cross-site
      #     WebSocket hijacking (CSWSH) is not exploitable — a malicious page cannot
      #     read the origin-scoped token and therefore cannot connect.
      #   - Non-empty: enables enforcement. Only same-origin requests and the listed
      #     origins may open WebSocket connections. Use this as optional
      #     defense-in-depth when you want to pin the allowed browser origins.
      #
      # Note: enabling enforcement can reject legitimate traffic behind proxies that
      # rewrite the Host header, so only turn it on if you understand your ingress.
      #
      # Example: "https://console.example.com,http://localhost:3000"
      websocketAllowedOrigins: ""
    ## Core Operator
    operator:
      enabled: true
      replicaCount: 1
      olmBootstrap: false
      olmOpenShift: false
      resources:
        requests:
          cpu: 100m
          memory: 128Mi
        limits:
          cpu: 500m
          memory: 512Mi
      # Data provider sidecar resources
      dataProvider:
        resources:
          requests:
            cpu: 50m
            memory: 128Mi
          limits:
            cpu: 200m
            memory: 256Mi
      service:
        type: ClusterIP
        port: 8080
        grpcPort: 50051
      logging:
        level: info # debug, info, warn, error
        format: json # json or text
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      nodeSelector: {}
      tolerations: []
      affinity: {}
      extraEnv: []
    ## ACM Integration (optional)
    acm:
      enabled: false
      replicaCount: 1
      resources:
        requests:
          cpu: 100m
          memory: 128Mi
        limits:
          cpu: 500m
          memory: 512Mi
      service:
        type: ClusterIP
        port: 8080
        grpcPort: 50051
      config:
        # Secret name for ACM managed clusters (must exist - created by OpenShift ACM)
        secretName: "application-manager"
      logging:
        level: info
        format: json
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      nodeSelector: {}
      tolerations: []
      affinity: {}
      extraEnv: []
    ## Console (web UI)
    console:
      enabled: true
      replicaCount: 1
      resources:
        requests:
          cpu: 50m
          memory: 64Mi
        limits:
          cpu: 200m
          memory: 256Mi
      service:
        type: ClusterIP
        port: 3000
        # NodePort (only used if type: NodePort)
        nodePort: 30080
      # Ingress configuration (Kubernetes - legacy)
      ingress:
        enabled: false
        className: "nginx"
        hostname: "krkn-operator.example.com"
        hosts: [] # Legacy list of host/path mappings; takes precedence when non-empty.
        tls:
          enabled: false
          secretName: "" # If empty, uses hostname to generate name
        # Annotations (for cert-manager, AWS ALB, etc.)
        annotations: {}
        # cert-manager.io/cluster-issuer: letsencrypt-prod
        # kubernetes.io/ingress.class: alb
      # Gateway API configuration (Kubernetes - recommended)
      # Requires Gateway API CRDs installed in the cluster
      # See: https://gateway-api.sigs.k8s.io/
      gateway:
        enabled: false
        # Name of the existing Gateway resource to attach to
        gatewayName: "krkn-gateway"
        # Namespace of the Gateway (if different from release namespace)
        # Leave empty to use the same namespace
        gatewayNamespace: ""
        # Optional: Listener/Section name on the Gateway to attach to
        # Useful when Gateway has multiple listeners
        sectionName: ""
        # Hostname for the HTTPRoute
        hostname: "krkn-operator.example.com"
        # Path configuration
        path: "/"
        pathType: "PathPrefix" # PathPrefix, Exact, or ImplementationSpecific
        # Annotations for the HTTPRoute resource
        annotations: {}
      # OpenShift Route configuration
      route:
        enabled: false
        # Leave empty to let OpenShift generate the Route hostname. Set this
        # explicitly only when the cluster has a configured DNS name for it.
        hostname: ""
        host: "" # Legacy hostname fallback.
        tls:
          enabled: true
          termination: edge # edge, passthrough, reencrypt
          insecureEdgeTerminationPolicy: Redirect
        annotations: {}
      logging:
        level: info
        format: json
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      nodeSelector: {}
      tolerations: []
      affinity: {}
      extraEnv: []
    ## RBAC
    rbac:
      create: true
      # OLM creates the scenario-runner resources during bootstrap because the
      # ServiceAccount namespace is chosen at installation time.
      scenarioRunner:
        create: true
    ## ServiceAccount
    serviceAccount:
      create: true
      name: ""
      annotations: {}
    ## CRDs
    crds:
      # Keep CRDs on chart uninstall
      keep: true
    ## Monitoring (optional)
    monitoring:
      enabled: false # SAFE DEFAULT for Kind/Minikube
      service:
        port: 8443
        annotations: {}
      serviceMonitor:
        enabled: false
        interval: 30s
        scrapeTimeout: 10s
        labels: {}
    ## Network Policy (optional)
    networkPolicy:
      enabled: false
      ingress: []
      egress: []
    ## Update strategy
    updateStrategy:
      type: RollingUpdate
      rollingUpdate:
        maxUnavailable: 0
        maxSurge: 1
    ## Pod disruption budget (for HA)
    podDisruptionBudget:
      enabled: false
      minAvailable: 1
    ## Common labels/annotations
    commonLabels: {}
    commonAnnotations: {}
    ## Name overrides
    nameOverride: ""
    fullnameOverride: ""