- 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.
159 lines
4.6 KiB
Markdown
159 lines
4.6 KiB
Markdown
# 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).
|
|
|
|
```yaml
|
|
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.
|
|
|
|
```yaml
|
|
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
|
|
```
|
|
|
|
#### Option B: Automated via cert-manager (Recommended)
|
|
|
|
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.
|
|
|
|
```yaml
|
|
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`:
|
|
|
|
```yaml
|
|
# ⚠️ 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:
|
|
|
|
```yaml
|
|
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: {}
|
|
```
|
|
|
|
3. **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:
|
|
|
|
```yaml
|
|
annotations:
|
|
route.openshift.io/termination: edge # or passthrough / reencrypt
|
|
```
|
|
|
|
This annotation is ignored on non-OpenShift clusters and is safe to include unconditionally.
|