Skip to main content
Version: v0.15

Gateway

The Gateway custom resource is the platform-level entry point. A single Gateway object reconciles into a complete runtime stack: a Deployment running Goma Gateway, a Service exposing it, a ConfigMap holding its static configuration, and — when enabled — an HorizontalPodAutoscaler and the goma-k8s-provider sidecar that hot-reloads Route and Middleware changes.

  • API group: gateway.jkaninda.dev
  • Version: v1alpha1
  • Kind: Gateway

How it works​

When a Gateway is applied, the operator creates the following resources, all named after the Gateway:

ResourcePurpose
DeploymentRuns the gateway container (and the goma-k8s-provider sidecar by default).
ServiceExposes container ports 8080 (HTTP) and 8443 (HTTPS). Configurable via spec.service.
ConfigMapHolds the static portion of the gateway config.
HorizontalPodAutoscalerCreated when spec.autoScaling.enabled: true.

The container always listens on 8080 and 8443. The Service ports are independent — set spec.service.httpPort: 80 and httpsPort: 443 for Ingress-style exposure on standard ports.

Minimal example​

The smallest valid Gateway. Defaults are sensible: a single replica, ClusterIP Service, and the K8s provider sidecar enabled.

apiVersion: gateway.jkaninda.dev/v1alpha1
kind: Gateway
metadata:
name: gateway
namespace: default
spec:
image: jkaninda/goma-gateway:latest
replicas: 1
server:
logLevel: info

Exposing the gateway​

The spec.service block controls how the gateway is reached from outside the cluster.

LoadBalancer (cloud)​

spec:
replicas: 2
service:
type: LoadBalancer
httpPort: 80
httpsPort: 443
externalTrafficPolicy: Local # preserve client source IPs
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: nlb

NodePort (bare metal / dev)​

spec:
service:
type: NodePort
httpPort: 8080
httpsPort: 8443
httpNodePort: 30080
httpsNodePort: 30443

Ingress in front​

Leave the Service as the default ClusterIP and route to it from your existing Ingress controller. Ports remain 8080 / 8443.

TLS​

Goma Gateway supports two TLS strategies, which can be combined.

1. Bring-your-own certificates​

Reference one or more Kubernetes TLS secrets (type: kubernetes.io/tls) in spec.server.tls:

spec:
server:
tls:
- secretName: example-com-tls
- secretName: api-example-com-tls

2. Built-in ACME / Let's Encrypt​

Enable the gateway's certificate manager and issue certs automatically.

HTTP-01 (gateway must be publicly reachable on port 80):

spec:
service:
type: LoadBalancer
httpPort: 80
httpsPort: 443
certManager:
provider: acme
acme:
email: ops@example.com
termsAccepted: true
challengeType: http-01
# For testing, switch to staging to avoid rate limits:
# directoryUrl: https://acme-staging-v02.api.letsencrypt.org/directory

DNS-01 (required for wildcard certs, no public ingress needed):

apiVersion: v1
kind: Secret
metadata:
name: cloudflare-credentials
type: Opaque
stringData:
apiToken: REPLACE_ME
---
apiVersion: gateway.jkaninda.dev/v1alpha1
kind: Gateway
metadata:
name: gateway-wildcard
spec:
certManager:
provider: acme
acme:
email: ops@example.com
termsAccepted: true
challengeType: dns-01
dnsProvider: cloudflare
credentialsSecret: cloudflare-credentials

Scaling​

Static replicas​

spec:
replicas: 3

Horizontal Pod Autoscaler​

Requires the metrics-server to be installed in the cluster.

spec:
replicas: 2
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1
memory: 512Mi
autoScaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80

Shared state with Redis​

When running multiple replicas, Redis lets stateful middlewares (rate limiting, ACME store coordination) share state across pods.

apiVersion: v1
kind: Secret
metadata:
name: redis-auth
type: Opaque
stringData:
password: changeme
---
apiVersion: gateway.jkaninda.dev/v1alpha1
kind: Gateway
metadata:
name: gateway
spec:
replicas: 3
server:
redis:
addr: redis.default.svc.cluster.local:6379
password: changeme

Observability​

Prometheus metrics are off by default. Enable and optionally protect them:

spec:
server:
monitoring:
enableMetrics: true
metricsPath: /metrics
visitorTTL: 5m
host: metrics.internal.example.com # restrict by Host header
middleware:
metrics:
- metrics-basic-auth # protect /metrics with a Middleware CR

/healthz and /readyz are always enabled — the operator wires them to the pod's liveness and readiness probes.

Dynamic configuration providers​

By default the operator injects the goma-k8s-provider sidecar, which watches Route and Middleware CRs and hot-reloads them into the gateway. You can disable it (in which case routes are delivered through the static ConfigMap, requiring a pod restart on changes) or use HTTP / Git providers instead.

spec:
providers:
kubernetes:
enabled: true # default
image: jkaninda/goma-k8s-provider:latest
http:
enabled: false
endpoint: https://config.example.com/goma.yaml
interval: 60s
git:
enabled: false
url: https://github.com/example/gateway-config.git
branch: main
path: config
interval: 60s
auth:
type: token
secretName: git-credentials

Spec reference​

FieldTypeDescription
imagestringGateway container image. Default: jkaninda/goma-gateway:latest.
replicasint32Number of gateway pods (ignored when autoScaling.enabled: true).
imagePullSecrets[]LocalObjectReferenceSecrets used to pull the gateway image.
resourcesResourceRequirementsCPU/memory requests and limits for the gateway container.
affinitycorev1.AffinityPod scheduling constraints.
autoScalingobjectHPA configuration (see below).
serverobjectServer runtime configuration (see below).
serviceobjectKubernetes Service exposure (see below).
certManagerobjectBuilt-in ACME / Let's Encrypt certificate manager.
providersobjectDynamic configuration providers (Kubernetes sidecar, HTTP, Git).

spec.server​

FieldTypeDefaultDescription
logLevelenuminfoOne of info, debug, trace, off.
timeouts.readint30Read timeout in seconds.
timeouts.writeint60Write timeout in seconds.
timeouts.idleint90Idle timeout in seconds.
tls[].secretNamestring—Name of a kubernetes.io/tls Secret.
redis.addrstring—Redis host:port.
redis.passwordstring—Redis password (consider using a Secret).
monitoring.enableMetricsboolfalseExpose Prometheus metrics.
monitoring.metricsPathstring/metricsPath of the metrics endpoint.
monitoring.visitorTTLstring5mHow long a visitor counts towards the real-time visitors gauge.
monitoring.hoststring—Restrict metrics endpoints to this Host header.
monitoring.middleware.metrics[]string—Middleware CR names applied to /metrics.
networking.dnsCache.ttlint300DNS cache TTL in seconds.
networking.dnsCache.clearOnReloadboolfalseFlush the local DNS cache after the routes are reloaded (auto-reload / config changes).
networking.dnsCache.resolver[]string—Custom DNS server addresses (e.g. 1.1.1.1, 8.8.8.8:53). Empty uses the system resolver. Applied at startup.
networking.transport.maxIdleConnsint512Max idle connections.
networking.transport.maxIdleConnsPerHostint256Max idle connections per host.
networking.transport.maxConnsPerHostint256Max total connections per host.
reload.enabledboolfalseExpose the token-protected on-demand config reload endpoint.
reload.pathstring/gateway/reloadPath of the reload endpoint.
reload.tokenstring—Bearer token required (Authorization: Bearer <token>). Prefer the GOMA_RELOAD_TOKEN env var.
reload.hoststring—Restrict the reload endpoint to this Host header.

On-demand reload. These fields expose a token-protected endpoint that reloads the gateway configuration immediately. See On-Demand Reload in the User Manual for the endpoint path, request format, and response codes.

spec.service​

FieldTypeDefaultDescription
typeenumClusterIPClusterIP, NodePort, or LoadBalancer.
httpPortint328080Service-level HTTP port. Set to 80 for Ingress-style exposure.
httpsPortint328443Service-level HTTPS port. Set to 443 for Ingress-style exposure.
httpNodePortint32—NodePort for HTTP (type: NodePort only).
httpsNodePortint32—NodePort for HTTPS (type: NodePort only).
loadBalancerIPstring—Request a specific static IP (cloud-dependent).
loadBalancerSourceRanges[]string—Restrict access to specific CIDRs.
loadBalancerClassstring—Select a specific LB implementation (e.g. service.k8s.aws/nlb).
externalTrafficPolicyenumClusterCluster or Local (Local preserves client source IPs).
sessionAffinityenumNoneNone or ClientIP.
annotationsmap—Merged onto the Service (use for cloud LB tuning).
labelsmap—Merged onto the Service.
ipFamilyPolicyenum—SingleStack, PreferDualStack, or RequireDualStack.
ipFamilies[]string—List of IP families: IPv4, IPv6.

spec.certManager​

FieldTypeDefaultDescription
providerenumacmeCurrently only acme is supported.
acme.emailstring—Required. Contact email for the ACME account.
acme.directoryUrlstringLet's Encrypt prodACME directory endpoint.
acme.termsAcceptedbooltrueAcceptance of the ACME provider's ToS.
acme.challengeTypeenumhttp-01http-01 or dns-01 (use dns-01 for wildcards).
acme.dnsProviderstring—DNS-01 provider (e.g. cloudflare, route53).
acme.credentialsSecretstring—Secret name containing DNS provider credentials.

spec.autoScaling​

FieldTypeDefaultDescription
enabledboolfalseWhether the HPA is created.
minReplicasint321Lower bound.
maxReplicasint3210Upper bound.
targetCPUUtilizationPercentageint32—Target average CPU.
targetMemoryUtilizationPercentageint32—Target average memory.

spec.providers​

FieldTypeDescription
kubernetes.enabledboolEnables the goma-k8s-provider sidecar (default: true).
kubernetes.imagestringSidecar image. Default: jkaninda/goma-k8s-provider:latest.
http.enabledboolEnables a remote HTTP provider.
http.endpointstringURL of the remote config.
http.intervalstringPull interval (e.g. 60s).
http.headersSecretstringSecret with header values referenced via ${VAR}.
git.enabledboolEnables the Git provider.
git.urlstringRepository URL.
git.branchstringBranch to check out.
git.pathstringSubdirectory inside the repo.
git.authobjecttype (token/basic/ssh) and secretName.

Status​

kubectl get gateway shows the address (when a LoadBalancer is provisioned), replica counts, and route count:

NAME TYPE ADDRESS REPLICAS READY ROUTES AGE
gateway LoadBalancer 34.120.10.42 3 3 5 4m

Inspect full conditions with:

kubectl describe gateway gateway