Terraform all resources, update encryption scheme, add ingress

This commit is contained in:
Ian Keane 2026-08-17 10:22:06 -04:00
parent b34b075d10
commit 3b85d6e85b
20 changed files with 731 additions and 970 deletions

37
terraform/argocd.tf Normal file
View file

@ -0,0 +1,37 @@
# Generate ArgoCD admin password
resource "random_password" "argocd_admin" {
length = 24
special = true
override_special = "!#$%&*()-_=+[]{}?"
}
# Store secrets in AWS Secrets Manager
resource "aws_secretsmanager_secret" "dumpnet" {
name = "dumpnet/cluster"
description = "Dumpnet cluster secrets"
}
resource "aws_secretsmanager_secret_version" "dumpnet" {
secret_id = aws_secretsmanager_secret.dumpnet.id
secret_string = jsonencode({
argocd_admin_password = random_password.argocd_admin.result
talosconfig = data.talos_client_configuration.this.talos_config
kubeconfig = talos_cluster_kubeconfig.this.kubeconfig_raw
})
}
# Install ArgoCD via Helm
resource "helm_release" "argocd" {
name = "argocd"
repository = "https://argoproj.github.io/argo-helm"
chart = "argo-cd"
namespace = "argocd"
create_namespace = true
set {
name = "configs.secret.argocdServerAdminPassword"
value = bcrypt(random_password.argocd_admin.result)
}
depends_on = [talos_cluster_kubeconfig.this]
}

15
terraform/dns.tf Normal file
View file

@ -0,0 +1,15 @@
# Route53 records - using a data source to reference the existing hosted zone
# without importing it into Terraform state
data "aws_route53_zone" "dumpnet" {
zone_id = var.hosted_zone_id
}
resource "aws_route53_record" "cluster" {
for_each = toset(var.dns_records)
zone_id = data.aws_route53_zone.dumpnet.zone_id
name = "${each.value}.${var.domain}"
type = "A"
ttl = 300
records = [aws_eip.controlplane.public_ip]
}

112
terraform/main.tf Normal file
View file

@ -0,0 +1,112 @@
# EIP - created fresh, managed by Terraform
resource "aws_eip" "controlplane" {
domain = "vpc"
tags = {
Name = "${var.cluster_name}-controlplane"
}
}
# Generate Talos machine secrets (CA, tokens, etc)
resource "talos_machine_secrets" "this" {}
data "talos_machine_configuration" "controlplane" {
cluster_name = var.cluster_name
cluster_endpoint = "https://${aws_eip.controlplane.public_ip}:6443"
machine_type = "controlplane"
machine_secrets = talos_machine_secrets.this.machine_secrets
talos_version = "v1.8.2"
kubernetes_version = "v1.31.2"
config_patches = [
yamlencode({
machine = {
certSANs = [aws_eip.controlplane.public_ip]
install = {
disk = "/dev/xvda"
grubUseUKICmdline = null
}
time = {
servers = ["169.254.169.123"]
}
}
cluster = {
apiServer = {
certSANs = [aws_eip.controlplane.public_ip]
}
allowSchedulingOnControlPlanes = true
}
})
]
}
data "talos_client_configuration" "this" {
cluster_name = var.cluster_name
client_configuration = talos_machine_secrets.this.client_configuration
endpoints = [aws_eip.controlplane.public_ip]
nodes = [aws_eip.controlplane.public_ip]
}
# Network interface (prevents auto-assign public IP)
resource "aws_network_interface" "controlplane" {
subnet_id = aws_subnet.talos.id
security_groups = [aws_security_group.talos.id]
tags = {
Name = "${var.cluster_name}-controlplane"
}
}
# Associate EIP with network interface
resource "aws_eip_association" "controlplane" {
instance_id = aws_instance.controlplane.id
allocation_id = aws_eip.controlplane.id
}
# Launch control plane instance
resource "aws_instance" "controlplane" {
ami = var.ami_id
instance_type = var.instance_type
network_interface {
network_interface_id = aws_network_interface.controlplane.id
device_index = 0
}
user_data = data.talos_machine_configuration.controlplane.machine_configuration
tags = {
Name = "${var.cluster_name}-controlplane"
}
lifecycle {
ignore_changes = [user_data]
}
}
# Apply machine configuration to the control plane node
resource "talos_machine_configuration_apply" "controlplane" {
client_configuration = talos_machine_secrets.this.client_configuration
machine_configuration_input = data.talos_machine_configuration.controlplane.machine_configuration
endpoint = aws_eip.controlplane.public_ip
node = aws_instance.controlplane.private_ip
depends_on = [aws_eip_association.controlplane]
}
# Bootstrap the cluster
resource "talos_machine_bootstrap" "this" {
client_configuration = talos_machine_secrets.this.client_configuration
endpoint = aws_eip.controlplane.public_ip
node = aws_instance.controlplane.private_ip
depends_on = [talos_machine_configuration_apply.controlplane]
}
# Retrieve kubeconfig
resource "talos_cluster_kubeconfig" "this" {
client_configuration = talos_machine_secrets.this.client_configuration
endpoint = aws_eip.controlplane.public_ip
node = aws_instance.controlplane.private_ip
depends_on = [talos_machine_bootstrap.this]
}

19
terraform/namespaces.tf Normal file
View file

@ -0,0 +1,19 @@
provider "kubernetes" {
host = "https://${aws_eip.controlplane.public_ip}:6443"
cluster_ca_certificate = base64decode(talos_cluster_kubeconfig.this.kubernetes_client_configuration.ca_certificate)
client_certificate = base64decode(talos_cluster_kubeconfig.this.kubernetes_client_configuration.client_certificate)
client_key = base64decode(talos_cluster_kubeconfig.this.kubernetes_client_configuration.client_key)
}
resource "kubernetes_namespace" "ingress_nginx" {
metadata {
name = "ingress-nginx"
labels = {
"pod-security.kubernetes.io/enforce" = "privileged"
"pod-security.kubernetes.io/audit" = "privileged"
"pod-security.kubernetes.io/warn" = "privileged"
}
}
depends_on = [talos_cluster_kubeconfig.this]
}

23
terraform/network.tf Normal file
View file

@ -0,0 +1,23 @@
resource "aws_subnet" "talos" {
vpc_id = var.vpc_id
cidr_block = "172.31.128.0/24"
availability_zone = "us-east-1c"
map_public_ip_on_launch = false
tags = {
Name = "talos-${var.cluster_name}"
}
}
resource "aws_route_table_association" "talos" {
subnet_id = aws_subnet.talos.id
route_table_id = data.aws_route_table.default.id
}
data "aws_route_table" "default" {
vpc_id = var.vpc_id
filter {
name = "association.main"
values = ["true"]
}
}

7
terraform/outputs.tf Normal file
View file

@ -0,0 +1,7 @@
output "public_ip" {
value = aws_eip.controlplane.public_ip
}
output "argocd_password_secret" {
value = "aws secretsmanager get-secret-value --secret-id dumpnet/cluster --query SecretString --output text | python3 -m json.tool"
}

View file

@ -0,0 +1,56 @@
resource "aws_security_group" "talos" {
name = "talos-${var.cluster_name}"
description = "Talos cluster security group"
vpc_id = var.vpc_id
ingress {
description = "Talos API"
from_port = 50000
to_port = 50000
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Kubernetes API"
from_port = 6443
to_port = 6443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTP"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "HTTPS"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
description = "Intra-cluster"
from_port = 0
to_port = 0
protocol = "-1"
self = true
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "talos-${var.cluster_name}"
}
}

View file

@ -0,0 +1 @@
hosted_zone_id = "Z068835512G0ZQJ9SJGOI"

View file

@ -0,0 +1,5 @@
hosted_zone_id = "Z068835512G0ZQJ9SJGOI"
domain = "dumpnet.chat"
dns_records = [
"argocd",
]

35
terraform/variables.tf Normal file
View file

@ -0,0 +1,35 @@
variable "talos_version" {
default = "v1.8.2"
}
variable "cluster_name" {
default = "dumpnet"
}
variable "instance_type" {
default = "t3.medium"
}
variable "vpc_id" {
default = "vpc-4421b439"
}
variable "ami_id" {
description = "Talos AMI ID"
default = "ami-000f1b0ad9d8ceafd"
}
variable "hosted_zone_id" {
description = "Route53 hosted zone ID for dumpnet.chat"
}
variable "domain" {
description = "Base domain for all DNS records"
default = "dumpnet.chat"
}
variable "dns_records" {
description = "List of subdomains to point at the cluster EIP"
type = list(string)
default = ["argocd"]
}

45
terraform/versions.tf Normal file
View file

@ -0,0 +1,45 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
talos = {
source = "siderolabs/talos"
version = "~> 0.3"
}
helm = {
source = "hashicorp/helm"
version = "~> 2.0"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "~> 2.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.0"
}
}
backend "s3" {
bucket = "iankeane-tfstate"
key = "dumpnet/terraform.tfstate"
region = "us-east-1"
use_lockfile = true
encrypt = true
}
}
provider "aws" {
region = "us-east-1"
}
provider "helm" {
kubernetes {
host = "https://${aws_eip.controlplane.public_ip}:6443"
cluster_ca_certificate = base64decode(talos_cluster_kubeconfig.this.kubernetes_client_configuration.ca_certificate)
client_certificate = base64decode(talos_cluster_kubeconfig.this.kubernetes_client_configuration.client_certificate)
client_key = base64decode(talos_cluster_kubeconfig.this.kubernetes_client_configuration.client_key)
}
}