Exposing Applications to the Internet¶
This guide explains how to expose your application running in the cluster to the public internet securely.
Conceptual Overview
This is a practical, step-by-step guide. For a deeper understanding of the
underlying Kubernetes resources like Services and Ingress, please see
the Networking in
Kubernetes
documentation.
The platform provides an ingress stack built on modern, cloud-native tools:
- Ingress Controller: Contour is used to
manage incoming traffic. It supports the standard
IngressandGateway APIresources, as well as its own customHTTPProxyresource. - Automatic TLS Certificates: cert-manager is integrated to automatically provision and renew TLS certificates from Let's Encrypt, enabling HTTPS by default.
- Automatic DNS Records: ExternalDNS automatically creates DNS A-records for your services, pointing your hostname to the cluster's public IP address.
This guide will walk you through the recommended methods of using HTTPProxy or
the modern Kubernetes Gateway API to expose your service with secure,
automated HTTPS.
Recommended Method: Secure HTTPS with HTTPProxy¶
This is a standard, recommended workflow for exposing any web-based application. It involves creating two resources: one to request the TLS certificate, and one to configure the traffic routing.
Step 1: Request a TLS Certificate¶
First, create a Certificate resource. This tells cert-manager to obtain a TLS
certificate from Let's Encrypt for your domain and store it in a Kubernetes
Secret.
# my-app-certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: my-app-tls-cert
spec:
# The name of the Kubernetes Secret where the certificate will be stored.
# This is what your HTTPProxy will reference.
secretName: my-app-tls-secret
# The domain name for your application.
dnsNames:
- my-app.your-domain.com
# References the platform's pre-configured Let's Encrypt issuer.
issuerRef:
name: letsencrypt-cluster-issuer
kind: ClusterIssuer
Step 2: Create an HTTPProxy Resource¶
Next, create an HTTPProxy resource. This tells the Contour ingress controller
how to route traffic for your domain, where to send it, and which TLS secret to
use for HTTPS.
# my-app-httpproxy.yaml
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: my-app-httpproxy
spec:
virtualhost:
# This must match one of the dnsNames from your Certificate resource.
fqdn: my-app.your-domain.com
tls:
# This must match the secretName from your Certificate resource.
secretName: my-app-tls-secret
routes:
- conditions:
- prefix: / # Route all traffic from the root path.
services:
- name: my-app-service # The name of your application's Service.
port: 8080 # The port number of your Service.
When you deploy these two resources, the following happens automatically:
- ExternalDNS creates a DNS record for
my-app.your-domain.com. - Cert-manager validates that it controls the DNS and gets a certificate from Let's Encrypt.
- Cert-manager saves the certificate and key in a
Secretnamedmy-app-tls-secret. - Contour detects the
HTTPProxyand theSecret, and begins serving encrypted traffic for your domain.
Step 3: Allow Ingress Traffic to Your Pod¶
Finally, ensure your application's pod has the correct label to allow the ingress controller to send traffic to it. This is a mandatory security requirement.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
metadata:
labels:
# This label is required to allow traffic from the ingress controller.
netic.dk/network-ingress: "contour"
# ... rest of your pod spec
Modern Method: Secure HTTPS with Gateway API¶
As a modern alternative to Ingress and HTTPProxy, the platform fully
supports the official Kubernetes Gateway
API. This is a powerful, standardized, and
expressive API for managing traffic routing. It separates the responsibility of
the cluster operator (who manages the Gateway) from the application developer
(who manages HTTPRoute resources).
Separation of Roles
You do not need to create the Gateway resource yourself. The platform team
manages the Gateway as a piece of shared infrastructure, which represents
the central, secure entry point to the cluster.
Your responsibility is simply to create an HTTPRoute to tell the existing
Gateway how to route traffic to your specific application.
This method involves creating a single HTTPRoute resource. TLS is handled
automatically at the Gateway level.
Step 1: Create an HTTPRoute Resource¶
The HTTPRoute resource defines how to match and route traffic from the
Gateway to your backend Service.
# my-app-httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app-httproute
spec:
# This section attaches your route to the platform-provided Gateway.
parentRefs:
- name: contour
namespace: projectcontour
kind: Gateway
# The domain name for your application.
# ExternalDNS will automatically create a record for this.
hostnames:
- "my-app.your-domain.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: my-app-service
port: 8080
When you deploy this resource, the following happens automatically:
- ExternalDNS creates a DNS record for
my-app.your-domain.com. - The
Gatewayresource is already configured with a TLS listener.cert-managermonitors it, sees your new hostname, and automatically provisions a TLS certificate for it. - Contour configures its underlying Envoy proxy to route traffic for
my-app.your-domain.comto your service, with HTTPS enabled.
Step 2: Allow Ingress Traffic to Your Pod¶
Just like with HTTPProxy, you must label your pod to allow the ingress
controller to send traffic to it.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
metadata:
labels:
# This label is required to allow traffic from the ingress controller.
netic.dk/network-ingress: "contour"
# ... rest of your pod spec
Advanced Configurations with HTTPProxy¶
HTTPProxy makes advanced configurations simple and declarative without needing
complex annotations.
Enabling WebSockets¶
To enable WebSockets for a specific route, add the enableWebsockets: true
field to the route.
spec:
# ... virtualhost config
routes:
- conditions:
- prefix: / # Enable websockets for the root path
services:
- name: my-websocket-service
port: 8080
enableWebsockets: true
Enabling gRPC¶
To route gRPC traffic, simply specify h2c or h2 (for TLS) as the protocol on
your service. Contour will handle the rest.
spec:
# ... virtualhost config (with TLS for h2)
routes:
- conditions:
- prefix: /
services:
- name: my-grpc-service
port: 9000
protocol: h2 # Use 'h2' for gRPC over TLS
Alternative Method: Using the Standard Ingress Resource¶
Legacy Method
While the standard Kubernetes Ingress resource is supported, we recommend
using HTTPProxy or Gateway API for their superior features, safety, and
validation. The following examples are provided for reference.
When using the Ingress resource, cert-manager is controlled via
annotations directly on the Ingress object, and a separate Certificate
resource is not needed.
Minimal HTTP Ingress¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress-http
spec:
rules:
- host: my-app.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
name: http
Minimal HTTPS Ingress¶
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress-https
annotations:
# Tell cert-manager to use the letsencrypt issuer for this ingress.
cert-manager.io/cluster-issuer: letsencrypt
spec:
tls:
- hosts:
- my-app.your-domain.com
# cert-manager will create/update a secret with this name.
secretName: my-app-tls-secret-from-ingress
rules:
- host: my-app.your-domain.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
name: http