Skip to content

PATTERN Cited by 1 source

Static site via ingress proxy to S3 website

Problem

You need to serve a static site (engineering blog, docs site, marketing page) with a custom domain and TLS. The textbook AWS answer is CloudFront distribution fronting an S3 bucket, which gives you global edge caching, ACM-issued cert, automatic HTTP/2, and WAF integration. But CloudFront is another piece of infrastructure to provision, monitor, and own — and you already operate a Kubernetes platform with a capable L7 proxy, ACM automation, and DNS automation.

Solution

Wire the Kubernetes Ingress platform to the S3 website endpoint. Provision the S3 bucket via CloudFormation with WebsiteConfiguration (IndexDocument, ErrorDocument) and AccessControl: PublicRead. This exposes the bucket at http://<BUCKET>.s3-website.<REGION>.amazonaws.com — HTTP-only, no custom domain.

Create a Kubernetes Ingress with:

  • host: pointing at the public domain (e.g. engineering.zalando.com).
  • A proxy-specific annotation that proxies all traffic to the bucket's website endpoint and adds gzip compression (the S3 website endpoint does not compress). In Zalando's stack this is Skipper's route DSL:
annotations:
  zalando.org/skipper-routes: |
    redirect_app_default: * -> compress() -> setDynamicBackendUrl("http://<BUCKET>.s3-website.<REGION>.amazonaws.com") -> <dynamic>;

The result: TLS-terminated, HTTP/2-upgraded, gzip-compressed, auto-DNS'd static site serving from S3 — with zero net-new infrastructure beyond the Ingress manifest itself.

Applicability

  • You already operate a Kubernetes platform with an L7 ingress proxy (Skipper, Envoy, nginx, Traefik, Contour…) that has filters for response-body rewriting or compression.
  • You have Ingress-driven cert/DNS automation (External DNS + cert-manager or the Kubernetes Ingress Controller for AWS).
  • Traffic is low enough that origin-only serving (no edge caching beyond what the CDN-less ALB provides) is fine — blog / internal docs / runbook sites sized in single-digit req/s.
  • Your observability / auth / WAF stack is already plumbed through the ingress tier and you want one fewer place where that configuration diverges.

Not applicable

  • High-traffic or geo-distributed audiences — you need real CloudFront (or Cloudflare / Fastly) for edge caching and latency near the user. This pattern serves every request from one region.
  • Private/authenticated static content — the S3 website endpoint requires PublicRead. For gated content use CloudFront + OAC (Origin Access Control), or serve from a private REST-API bucket with signed requests proxied through the ingress.
  • DDoS / L4 rate-limiting requirements — CloudFront / a CDN absorbs this at the edge; ALB + ingress pods have finite capacity.

Seen in

Last updated · 476 distilled / 1,218 read