Files
harmony/docs/guides/kubernetes-ingress.md
Jean-Gabriel Gill-Couture caf6f0c67b Add KVM module for managing virtual machines
- KVM module with connection configuration (local/SSH)
- VM lifecycle management (create/start/stop/destroy/delete)
- Network management (create/delete isolated virtual networks)
- Volume management (create/delete storage volumes)
- Example: OKD HA cluster deployment with OPNsense firewall
- All VMs configured for PXE boot with isolated network

The KVM module uses virsh command-line tools for management and is fully integrated with Harmony's architecture. It provides a clean Rust API for defining VMs, networks, and volumes. The example demonstrates deploying a complete OKD high-availability cluster (3 control planes, 3 workers) plus OPNsense firewall on an isolated network.
2026-03-08 08:06:10 -04:00

4.6 KiB

Ingress Resources in Harmony

Harmony generates standard Kubernetes networking.k8s.io/v1 Ingress resources. This ensures your deployments are portable across any Kubernetes distribution (vanilla K8s, OKD/OpenShift, K3s, etc.) without requiring vendor-specific configurations.

By default, Harmony does not set spec.ingressClassName. This allows the cluster's default ingress controller to automatically claim the resource, which is the correct approach for most single-controller clusters.


TLS Configurations

There are two portable TLS modes for Ingress resources. Use only these in your Harmony deployments.

1. Plain HTTP (No TLS)

Omit the tls block entirely. The Ingress serves traffic over plain HTTP. Use this for local development or when TLS is terminated elsewhere (e.g., by a service mesh or external load balancer).

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  namespace: my-ns
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app
            port:
              number: 8080

2. HTTPS with a Named TLS Secret

Provide a tls block with both hosts and a secretName. The ingress controller will use that Secret for TLS termination. The Secret must be a kubernetes.io/tls type in the same namespace as the Ingress.

There are two ways to provide this Secret.

Option A: Manual Secret

Create the TLS Secret yourself before deploying the Ingress. This is suitable when certificates are issued outside the cluster or managed by another system.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  namespace: my-ns
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app
            port:
              number: 8080
  tls:
  - hosts:
    - app.example.com
    secretName: app-example-com-tls

Add the cert-manager.io/cluster-issuer annotation to the Ingress. cert-manager will automatically perform the ACME challenge, generate the certificate, store it in the named Secret, and handle renewal. You do not create the Secret yourself.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  namespace: my-ns
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app
            port:
              number: 8080
  tls:
  - hosts:
    - app.example.com
    secretName: app-example-com-tls

If you use a namespace-scoped Issuer instead of a ClusterIssuer, replace the annotation with cert-manager.io/issuer: <name>.


Do Not Use: TLS Without secretName

Avoid TLS entries that omit secretName:

# ⚠️ Non-portable — do not use
tls:
- hosts:
  - app.example.com

Behavior for this pattern is controller-specific and not portable. On OKD/OpenShift, the ingress-to-route translation rejects it as incomplete. On other controllers, it may silently serve a self-signed fallback or fail in unpredictable ways. Harmony does not support this pattern.


Prerequisites for cert-manager

To use automated certificates (Option B above):

  1. cert-manager must be installed on the cluster.
  2. A ClusterIssuer or Issuer must exist. A typical Let's Encrypt production issuer:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: team@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-account-key
    solvers:
    - http01:
        ingress: {}
  1. DNS must already resolve to the cluster's ingress endpoint before the Ingress is created. The HTTP01 challenge requires this routing to be active.

For wildcard certificates (e.g. *.example.com), HTTP01 cannot be used — configure a DNS01 solver with credentials for your DNS provider instead.


OKD / OpenShift Notes

On OKD, standard Ingress resources are automatically translated into OpenShift Route objects. The default TLS termination mode is edge, which is correct for most HTTP applications. To control this explicitly, add:

annotations:
  route.openshift.io/termination: edge  # or passthrough / reencrypt

This annotation is ignored on non-OpenShift clusters and is safe to include unconditionally.