apiVersion: troubleshoot.sh/v1beta3
kind: Preflight
metadata:
  name: example
spec:
  analyzers:
    - clusterVersion:
        outcomes:
          - fail:
              when: "< 1.20.0"
              message: This application requires at least Kubernetes 1.20.0, and recommends 1.22.0.
              uri: https://www.kubernetes.io
          - warn:
              when: "< 1.22.0"
              message: Your cluster meets the minimum version of Kubernetes, but we recommend you update to 1.22.0 or later.
              uri: https://kubernetes.io
          - pass:
              when: ">= 1.22.0"
              message: Your cluster meets the recommended and required versions of Kubernetes.
      docString: |
        Title: Kubernetes Control Plane Requirements
        Requirement:
          - Version:
            - Minimum: 1.20.0
            - Recommended: 1.22.0
        These version targets ensure that required APIs and default behaviors are
        available and patched. Moving below the minimum commonly removes GA APIs
        (e.g., apps/v1 workloads, storage and ingress v1 APIs), changes admission
        defaults, and lacks critical CVE fixes. Running at or above the recommended
        version matches what is exercised most extensively in CI and receives the
        best operational guidance for upgrades and incident response.
    - customResourceDefinition:
        checkName: Ingress
        customResourceDefinitionName: ingressroutes.contour.heptio.com
        outcomes:
          - fail:
              message: Contour ingress not found!
          - pass:
              message: Contour ingress found!
      docString: |
        Title: Required CRDs and Ingress Capabilities
        Requirement:
          - Ingress Controller: Contour
          - CRD must be present:
            - Group: heptio.com
            - Kind: IngressRoute
            - Version: v1beta1 or later served version
        The ingress layer terminates TLS and routes external traffic to Services.
        Contour relies on the IngressRoute CRD to express host/path routing, TLS
        configuration, and policy. If the CRD is not installed and served by the
        API server, Contour cannot reconcile desired state, leaving routes
        unconfigured and traffic unreachable.
    - containerRuntime:
        outcomes:
          - pass:
              when: "== containerd"
              message: containerd container runtime was found.
          - fail:
              message: Did not find containerd container runtime.
      docString: |
        Title: Container Runtime Requirements
        Requirement:
          - Runtime: containerd (CRI)
          - Kubelet cgroup driver: systemd
          - CRI socket path: /run/containerd/containerd.sock
        containerd (via the CRI) is the supported runtime for predictable container
        lifecycle management. On modern distros (cgroup v2), kubelet and the OS must
        both use the systemd cgroup driver to avoid resource accounting mismatches
        that lead to unexpected OOMKills and throttling. The CRI socket path must
        match kubelet configuration so the node can start and manage pods.
    - storageClass:
        checkName: Required storage classes
        storageClassName: "default"
        outcomes:
          - fail:
              message: Could not find a storage class called default.
          - pass:
              message: All good on storage classes
      docString: |
        Title: Default Storage Class Requirements
        Requirement:
          - Storage Class: default
          - Provisioner: Must support dynamic provisioning
          - Access Modes: ReadWriteOnce minimum
        A default storage class enables automatic persistent volume provisioning
        for StatefulSets and PVC-backed workloads. Without it, pods requiring
        persistent storage will remain in Pending state, unable to schedule.
        The storage class must support at least ReadWriteOnce access mode for
        single-pod workloads like databases and file servers.
    - distribution:
        outcomes:
          - fail:
              when: "== docker-desktop"
              message: The application does not support Docker Desktop Clusters
          - fail:
              when: "== microk8s"
              message: The application does not support Microk8s Clusters
          - fail:
              when: "== minikube"
              message: The application does not support Minikube Clusters
          - pass:
              when: "== eks"
              message: EKS is a supported distribution
          - pass:
              when: "== gke"
              message: GKE is a supported distribution
          - pass:
              when: "== aks"
              message: AKS is a supported distribution
          - pass:
              when: "== kurl"
              message: KURL is a supported distribution
          - pass:
              when: "== digitalocean"
              message: DigitalOcean is a supported distribution
          - pass:
              when: "== rke2"
              message: RKE2 is a supported distribution
          - pass:
              when: "== k3s"
              message: K3S is a supported distribution
          - pass:
              when: "== oke"
              message: OKE is a supported distribution
          - pass:
              when: "== kind"
              message: Kind is a supported distribution
          - warn:
              message: Unable to determine the distribution of Kubernetes
      docString: |
        Title: Supported Kubernetes Distributions
        Requirement:
          - Production distributions: EKS, GKE, AKS, KURL, RKE2, K3S, DigitalOcean, OKE
          - Development distributions: Kind (testing only)
          - Unsupported: Docker Desktop, Microk8s, Minikube
        This application requires production-grade Kubernetes distributions that
        provide enterprise features like proper networking, storage integration,
        and security policies. Development-focused distributions lack the stability,
        performance characteristics, and operational tooling needed for reliable
        application deployment and management.
    - nodeResources:
        checkName: Must have at least 3 nodes in the cluster, with 5 recommended
        outcomes:
        - fail:
            when: "count() < 3"
            message: This application requires at least 3 nodes.
            uri: https://kurl.sh/docs/install-with-kurl/adding-nodes
        - warn:
            when: "count() < 5"
            message: This application recommends at last 5 nodes.
            uri: https://kurl.sh/docs/install-with-kurl/adding-nodes
        - pass:
            message: This cluster has enough nodes.
      docString: |
        Title: Cluster Node Count Requirements
        Requirement:
          - Minimum: 3 nodes
          - Recommended: 5 nodes
          - High Availability: Odd number for quorum
        A minimum of 3 nodes ensures basic high availability and allows for
        rolling updates without service interruption. The recommended 5 nodes
        provide better resource distribution, fault tolerance, and maintenance
        windows. Odd numbers are preferred for etcd quorum and leader election
        in distributed components.
    - nodeResources:
        checkName: Every node in the cluster must have at least 8 GB of memory, with 32 GB recommended
        outcomes:
        - fail:
            when: "min(memoryCapacity) < 8Gi"
            message: All nodes must have at least 8 GB of memory.
            uri: https://kurl.sh/docs/install-with-kurl/system-requirements
        - warn:
            when: "min(memoryCapacity) < 32Gi"
            message: All nodes are recommended to have at least 32 GB of memory.
            uri: https://kurl.sh/docs/install-with-kurl/system-requirements
        - pass:
            message: All nodes have at least 32 GB of memory.
      docString: |
        Title: Node Memory Requirements
        Requirement:
          - Minimum: 8 GB per node
          - Recommended: 32 GB per node
          - Reserved: ~2 GB for system processes
        Each node requires sufficient memory for the kubelet, container runtime,
        system processes, and application workloads. The 8 GB minimum accounts
        for Kubernetes overhead and basic application needs. The 32 GB recommendation
        provides headroom for memory-intensive workloads, caching, and prevents
        OOMKills during traffic spikes or batch processing.
    - nodeResources:
        checkName: Total CPU Cores in the cluster is 4 or greater
        outcomes:
          - fail:
              when: "sum(cpuCapacity) < 4"
              message: The cluster must contain at least 4 cores
              uri: https://kurl.sh/docs/install-with-kurl/system-requirements
          - pass:
              message: There are at least 4 cores in the cluster
      docString: |
        Title: Cluster CPU Requirements
        Requirement:
          - Minimum: 4 total CPU cores across all nodes
          - Distribution: At least 1 core per node recommended
          - Architecture: x86_64 or arm64
        The cluster needs sufficient CPU capacity for Kubernetes control plane
        components, system daemons, and application workloads. 4 cores minimum
        ensures basic functionality, but distribution across multiple nodes
        provides better scheduling flexibility and fault tolerance than
        concentrating all cores on a single node.
    - nodeResources:
        checkName: Every node in the cluster must have at least 40 GB of ephemeral storage, with 100 GB recommended
        outcomes:
        - fail:
            when: "min(ephemeralStorageCapacity) < 40Gi"
            message: All nodes must have at least 40 GB of ephemeral storage.
            uri: https://kurl.sh/docs/install-with-kurl/system-requirements
        - warn:
            when: "min(ephemeralStorageCapacity) < 100Gi"
            message: All nodes are recommended to have at least 100 GB of ephemeral storage.
            uri: https://kurl.sh/docs/install-with-kurl/system-requirements
        - pass:
            message: All nodes have at least 100 GB of ephemeral storage.
      docString: |
        Title: Node Ephemeral Storage Requirements
        Requirement:
          - Minimum: 40 GB per node
          - Recommended: 100 GB per node
          - Usage: Container images, logs, temporary files
        Ephemeral storage houses container images, pod logs, and temporary
        files created by running containers. The 40 GB minimum covers basic
        Kubernetes components and small applications. The 100 GB recommendation
        accommodates larger container images, extensive logging, and temporary
        data processing without triggering evictions due to disk pressure.
