GOAL:
I’m using terraform to quickly and easily setup a Kubernetes cluster. I have a LoadBalancer service that should expose my blog-backend
service with a custom domain (I have already added DNS NS entries in my Cloudflare that redirects base domain to DigitalOcean’s servers).
resource "kubernetes_service" "blog-backend-lb" {
metadata {
name = "blog-backend-lb"
labels = {
app = "blog-backend"
}
annotations = {
"service.beta.kubernetes.io/do-loadbalancer-name" = "blog.mydomain.com"
"service.beta.kubernetes.io/do-loadbalancer-hostname" = "blog.mydomain.com"
}
}
spec {
type = "LoadBalancer"
selector = {
app = "blog-backend"
}
port {
port = 8080
target_port = 8080
}
}
}
PROBLEM: The service is being create properly and I can see Kubernetes picked up a domain.
However, I cannot access it unless I manually create a domain entry in the DigitalOcean dashboard: Networking -> Domains -> Add Domain -> Create Record for my subdomain redirecting to a LoadBalancer.
This is a bit cumbersome, because I want to clean everything up using terraform without touching anything by hand.
QUESTION: How can I automate it using a Terraform?
I thought about using a domain resource, but I don’t know where to get the ip address from.
resource "digitalocean_domain" "blog-backend-domain" {
name = "blog.mydomain.com"
ip_address = "<WHERE TO GET THE IP FROM?>"
}
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Accepted Answer
Ok, problem solved. When I used LoadBalancer as a service I didn’t have access to its IP from within terraform. However, when using ingress-nginx
helm chart I have the IP. Yay!
So the solution is:
# 1. Download ingress-nginx chart
resource "helm_release" "ingress-nginx" {
repository = "https://kubernetes.github.io/ingress-nginx"
chart = "ingress-nginx"
name = "ingress-nginx"
}
# 2. Add a Service with `type = "ClusterIP"`, which would expose the app to the Kubernetes cluster
resource "kubernetes_service" "blog-backend" {
metadata {
name = "blog-backend-service"
labels = {
app = "blog-backend"
}
}
spec {
type = "ClusterIP"
selector = {
app = "blog-backend"
}
port {
port = 8080
target_port = 8080
}
}
}
# 3. Create an ingress controller, which maps a domain to a service above
resource "kubernetes_ingress" "blog-backend-ingress" {
metadata {
name = "blog-backend-ingress"
annotations = {
"kubernetes.io/ingress.class" = "nginx"
}
}
spec {
rule {
host = "blog.mydomain.com"
http {
path {
backend {
service_name = "blog-backend-service"
service_port = 8080
}
path = "/"
}
}
}
}
}
# 4. Create a domain
resource "digitalocean_domain" "blog-backend-domain" {
name = "blog.mydomain.com"
}
# 5. Create a domain record, whose IP (`value`) we get from the ingress from step 3.
resource "digitalocean_record" "backend-api" {
domain = digitalocean_domain.blog-backend-domain.name
name = "@"
type = "A"
value = kubernetes_ingress.blog-backend-ingress.load_balancer_ingress[0].ip
}
The latest Terraform version has modified the way we get IP from ingress
output "load_balancer_ip" {
value = kubernetes_ingress.example.status.0.load_balancer.0.ingress.0.ip
}
So use this block
resource "digitalocean_record" "backend-api" {
domain = digitalocean_domain.blog-backend-domain.name
name = "@"
type = "A"
value = kubernetes_ingress.blog-backend-ingress.status.0.load_balancer.0.ingress.0.ip
}
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.