Ingress¶
ingress-nginx¶
Create namespace for ingress-nginx:
resource "kubernetes_namespace" "ingress_nginx" {
metadata {
name = "ingress-nginx"
labels = {
"pod-security.kubernetes.io/enforce" = "restricted"
}
}
}
Deploy the nginx-ingress-controller Helm chart from Bitnami:
resource "helm_release" "ingress_nginx" {
name = "ingress-nginx"
namespace = kubernetes_namespace.ingress_nginx.metadata.0.name
repository = "oci://registry-1.docker.io/bitnamicharts"
chart = "nginx-ingress-controller"
version = "11.0.0"
values = [yamlencode({
# Needed so that FastAPI url_for respects https under nginx+uvicorn
# See: https://stackoverflow.com/a/66244482
proxySetHeaders = {
X-Forwarded-For = "$proxy_add_x_forwarded_for"
X-Forwarded-Proto = "$scheme"
}
publishService = {
# This MUST be enabled, otherwise Ingress resources will publish internal
# node IPs via external-dns.
enabled = true
}
})]
}
cert-manager¶
Create namespace for cert-manager:
resource "kubernetes_namespace" "cert_manager" {
metadata {
name = "cert-manager"
labels = {
"pod-security.kubernetes.io/enforce" = "restricted"
}
}
}
Deploy the cert-manager Helm chart:
# https://cert-manager.io/docs/installation/helm/
# https://github.com/cert-manager/cert-manager/blob/master/deploy/charts/cert-manager/values.yaml
resource "helm_release" "cert_manager" {
name = "cert-manager"
namespace = kubernetes_namespace.cert_manager.metadata.0.name
repository = "https://charts.jetstack.io"
chart = "cert-manager"
version = "1.14.4"
values = [yamlencode({
global = {
leaderElection = {
# kube-system is managed by Autopilot so we move the leader election
# namespace to cert-manager
namespace = kubernetes_namespace.cert_manager.metadata.0.name
}
}
})]
}
Create a SelfSigned
issuer:
resource "kubernetes_manifest" "selfsigned_issuer" {
manifest = {
apiVersion = "cert-manager.io/v1"
kind = "ClusterIssuer"
metadata = {
name = "selfsigned"
}
spec = {
selfSigned = {}
}
}
}
external-dns¶
Setting up external-dns requires a domain. This example uses CloudFlare as a provider.
Create sensitive variable for CloudFlare API token:
variable "cloudflare_api_token" {
type = string
sensitive = true
}
Add CloudFlare provider:
terraform {
required_providers {
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.26.0"
}
}
required_version = ">=1.0"
}
Add domain to locals:
locals {
domain = "example.com"
}
Set CloudFlare zone:
data "cloudflare_zone" "dyff" {
name = local.domain
}
Create namespace for external-dns:
resource "kubernetes_namespace" "external_dns" {
metadata {
name = "external-dns"
labels = {
"pod-security.kubernetes.io/enforce" = "restricted"
}
}
}
Deploy the external-dns Helm chart from Bitnami:
# https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md
# https://github.com/bitnami/charts/blob/master/bitnami/external-dns/values.yaml
resource "helm_release" "external_dns" {
name = "external-dns"
namespace = kubernetes_namespace.external_dns.metadata.0.name
repository = "oci://registry-1.docker.io/bitnamicharts"
chart = "external-dns"
version = "7.0.0"
values = [yamlencode({
domainFilters = [local.domain]
policy = "sync"
provider = "cloudflare"
# This is required to prevent the different environments from destroying
# each other's entries.
txtOwnerId = local.name
zoneIdFilters = [data.cloudflare_zone.dyff.zone_id]
cloudflare = {
proxied = true
}
})]
set_sensitive {
name = "cloudflare.apiToken"
value = var.cloudflare_api_token
}
}