Terraform all resources, update encryption scheme, add ingress
This commit is contained in:
parent
b34b075d10
commit
3b85d6e85b
20 changed files with 731 additions and 970 deletions
37
terraform/argocd.tf
Normal file
37
terraform/argocd.tf
Normal 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
15
terraform/dns.tf
Normal 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
112
terraform/main.tf
Normal 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
19
terraform/namespaces.tf
Normal 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
23
terraform/network.tf
Normal 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
7
terraform/outputs.tf
Normal 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"
|
||||
}
|
||||
56
terraform/security_group.tf
Normal file
56
terraform/security_group.tf
Normal 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}"
|
||||
}
|
||||
}
|
||||
1
terraform/terraform.tfvars
Normal file
1
terraform/terraform.tfvars
Normal file
|
|
@ -0,0 +1 @@
|
|||
hosted_zone_id = "Z068835512G0ZQJ9SJGOI"
|
||||
5
terraform/terraform.tfvars.example
Normal file
5
terraform/terraform.tfvars.example
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
hosted_zone_id = "Z068835512G0ZQJ9SJGOI"
|
||||
domain = "dumpnet.chat"
|
||||
dns_records = [
|
||||
"argocd",
|
||||
]
|
||||
35
terraform/variables.tf
Normal file
35
terraform/variables.tf
Normal 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
45
terraform/versions.tf
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue