infrastructure/modules/cluster/main.tf

302 lines
8.4 KiB
Terraform
Raw Normal View History

2024-07-08 20:27:08 +00:00
locals {
cluster_api_domain = "${var.cluster.api.subdomain}.${var.cluster.domain}"
cluster_endpoint = "https://${local.cluster_api_domain}:${var.cluster.api.port}"
2024-07-08 20:27:08 +00:00
2024-07-13 22:17:47 +00:00
podSubnets = [
"10.200.0.0/16",
2024-07-22 20:31:48 +00:00
#"fd9b:5314:fc70::/64",
2024-07-13 22:17:47 +00:00
]
serviceSubnets = [
"10.201.0.0/16",
2024-07-22 20:31:48 +00:00
#"fd9b:5314:fc71::/108",
2024-07-13 22:17:47 +00:00
]
# Nodes will use IPs from this subnets
# for communication between each other.
tailscaleSubnets = [
"100.64.0.0/10",
"fd7a:115c:a1e0::/96"
]
talos_controlplane_config = {
2024-07-20 11:09:30 +00:00
machine : {
features : {
rbac : true
apidCheckExtKeyUsage : true
kubernetesTalosAPIAccess : {
enabled : true
allowedRoles : [
"os:reader"
]
allowedKubernetesNamespaces : [
"kube-system"
]
}
}
}
cluster : {
etcd : {
2024-07-19 20:48:07 +00:00
advertisedSubnets : local.tailscaleSubnets
listenSubnets : local.tailscaleSubnets
}
allowSchedulingOnControlPlanes : var.allow_scheduling_on_control_planes,
apiServer : {
extraArgs : {
"oidc-issuer-url" : "https://id.tjo.space/application/o/k8stjocloud/",
"oidc-client-id" : "HAI6rW0EWtgmSPGKAJ3XXzubQTUut2GMeTRS2spg",
"oidc-username-claim" : "sub",
"oidc-username-prefix" : "oidc:",
"oidc-groups-claim" : "groups",
"oidc-groups-prefix" : "oidc:groups:",
}
}
inlineManifests : [
{
2024-07-20 11:09:30 +00:00
name : "proxmox-cloud-controller-manager"
contents : data.helm_template.proxmox-ccm.manifest
},
{
name : "talos-cloud-controller-manager"
contents : data.helm_template.talos-ccm.manifest
},
{
name : "promxmox-csi-plugin"
contents : data.helm_template.proxmox-csi.manifest
},
{
name : "gateway-api-crds"
2024-07-21 10:27:40 +00:00
contents : file("${path.module}/manifests/gateway-api.crds.yaml")
2024-07-20 11:09:30 +00:00
},
{
name : "metrics-server"
contents : file("${path.module}/manifests/metrics-server.yaml")
},
{
name : "cilium"
contents : data.helm_template.cilium.manifest
},
{
name : "oidc-admins"
contents : <<-EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: id-tjo-space:admins
subjects:
- kind: Group
name: oidc:groups:k8s.tjo.cloud admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
EOF
},
]
}
2024-07-08 20:27:08 +00:00
}
talos_worker_config = {
cluster : {
2024-07-20 11:09:30 +00:00
externalCloudProvider : {
enabled : true
}
controlPlane : {
endpoint : local.cluster_endpoint
localAPIServerPort : var.cluster.api.port
}
network : {
cni : {
name : "none"
2024-07-08 20:27:08 +00:00
}
podSubnets : local.podSubnets
serviceSubnets : local.serviceSubnets
}
proxy : {
disabled : true
2024-07-08 20:27:08 +00:00
}
}
machine = {
kubelet = {
nodeIP : {
validSubnets : local.tailscaleSubnets
}
extraArgs : {
rotate-server-certificates : true
2024-07-20 11:09:30 +00:00
cloud-provider : "external"
2024-07-08 20:27:08 +00:00
}
}
install = {
image = "factory.talos.dev/installer/${var.talos.schematic_id}:${var.talos.version}"
disk = "/dev/vda"
}
2024-07-08 20:27:08 +00:00
}
}
2024-07-19 20:48:07 +00:00
talos_node_config = {
for k, node in local.nodes_with_address : k => [
yamlencode({
machine = {
network = {
hostname = node.name
}
nodeLabels = {
2024-07-22 20:31:48 +00:00
"k8s.tjo.cloud/public" = node.public ? "true" : "false"
2024-07-19 20:48:07 +00:00
"k8s.tjo.cloud/host" = node.host
"k8s.tjo.cloud/proxmox" = var.proxmox.name
2024-07-21 10:27:40 +00:00
}
2024-07-23 18:42:22 +00:00
sysctls = {
"net.ipv4.ip_forward" = "1"
"net.ipv6.conf.all.forwarding" = "1"
}
2024-07-19 20:48:07 +00:00
}
}),
yamlencode(
{
apiVersion : "v1alpha1"
kind : "ExtensionServiceConfig"
name : "tailscale"
environment : [
"TS_AUTHKEY=${var.tailscale_authkey}",
"TS_HOSTNAME=${node.name}",
2024-07-23 18:42:22 +00:00
"TS_ROUTES=${join(",", local.podSubnets)},${join(",", local.serviceSubnets)}",
"TS_EXTRA_ARGS=--accept-routes --snat-subnet-routes",
2024-07-19 20:48:07 +00:00
]
})
]
}
2024-07-08 20:27:08 +00:00
}
resource "digitalocean_record" "controlplane-A" {
for_each = { for k, node in local.nodes_with_address : k => node if node.type == "controlplane" }
2024-07-08 20:27:08 +00:00
2024-07-14 10:19:37 +00:00
domain = var.cluster.domain
2024-07-08 20:27:08 +00:00
type = "A"
name = var.cluster.api.subdomain
value = each.value.ipv4
2024-07-08 20:27:08 +00:00
ttl = 30
}
resource "digitalocean_record" "controlplane-AAAA" {
for_each = { for k, node in local.nodes_with_address : k => node if node.type == "controlplane" }
2024-07-08 20:27:08 +00:00
2024-07-14 10:19:37 +00:00
domain = var.cluster.domain
2024-07-08 20:27:08 +00:00
type = "AAAA"
name = var.cluster.api.subdomain
value = each.value.ipv6
2024-07-08 20:27:08 +00:00
ttl = 30
}
2024-07-19 20:48:07 +00:00
resource "talos_machine_secrets" "this" {
talos_version = var.talos.version
}
2024-07-08 20:27:08 +00:00
data "talos_machine_configuration" "controlplane" {
2024-07-14 10:19:37 +00:00
cluster_name = var.cluster.name
2024-07-08 20:27:08 +00:00
machine_type = "controlplane"
cluster_endpoint = local.cluster_endpoint
machine_secrets = talos_machine_secrets.this.machine_secrets
talos_version = var.talos.version
kubernetes_version = var.talos.kubernetes
2024-07-13 22:17:47 +00:00
2024-07-08 20:27:08 +00:00
depends_on = [
digitalocean_record.controlplane-A,
digitalocean_record.controlplane-AAAA,
]
}
data "talos_machine_configuration" "worker" {
2024-07-14 10:19:37 +00:00
cluster_name = var.cluster.name
2024-07-08 20:27:08 +00:00
machine_type = "worker"
cluster_endpoint = local.cluster_endpoint
machine_secrets = talos_machine_secrets.this.machine_secrets
talos_version = var.talos.version
kubernetes_version = var.talos.kubernetes
2024-07-13 22:17:47 +00:00
2024-07-08 20:27:08 +00:00
depends_on = [
digitalocean_record.controlplane-A,
digitalocean_record.controlplane-AAAA
]
}
2024-07-10 21:13:36 +00:00
resource "talos_machine_configuration_apply" "controlplane" {
for_each = { for k, v in local.nodes_with_address : k => v if v.type == "controlplane" }
2024-07-08 20:27:08 +00:00
client_configuration = talos_machine_secrets.this.client_configuration
2024-07-10 21:13:36 +00:00
machine_configuration_input = data.talos_machine_configuration.controlplane.machine_configuration
2024-07-08 20:27:08 +00:00
node = each.value.name
endpoint = each.value.ipv4
2024-07-08 20:27:08 +00:00
2024-07-14 10:19:37 +00:00
apply_mode = "reboot"
2024-07-10 21:13:36 +00:00
2024-07-19 20:48:07 +00:00
config_patches = concat(
[
yamlencode(local.talos_worker_config),
yamlencode(local.talos_controlplane_config)
],
local.talos_node_config[each.key]
)
2024-07-10 21:13:36 +00:00
}
resource "talos_machine_configuration_apply" "worker" {
for_each = { for k, v in local.nodes_with_address : k => v if v.type == "worker" }
client_configuration = talos_machine_secrets.this.client_configuration
machine_configuration_input = data.talos_machine_configuration.worker.machine_configuration
node = each.value.name
endpoint = each.value.ipv4
2024-07-10 21:13:36 +00:00
2024-07-14 10:19:37 +00:00
apply_mode = "reboot"
2024-07-10 21:13:36 +00:00
2024-07-19 20:48:07 +00:00
config_patches = concat(
[
yamlencode(local.talos_worker_config)
],
local.talos_node_config[each.key]
)
2024-07-08 20:27:08 +00:00
}
resource "talos_machine_bootstrap" "this" {
depends_on = [
2024-07-10 21:13:36 +00:00
talos_machine_configuration_apply.controlplane,
talos_machine_configuration_apply.worker
2024-07-08 20:27:08 +00:00
]
node = local.first_controlplane_node.name
endpoint = local.first_controlplane_node.ipv4
2024-07-08 20:27:08 +00:00
client_configuration = talos_machine_secrets.this.client_configuration
}
data "talos_cluster_kubeconfig" "this" {
depends_on = [
talos_machine_bootstrap.this
]
client_configuration = talos_machine_secrets.this.client_configuration
node = local.first_controlplane_node.ipv4
2024-07-08 20:27:08 +00:00
}
2024-07-19 20:48:07 +00:00
resource "local_file" "kubeconfig" {
content = data.talos_cluster_kubeconfig.this.kubeconfig_raw
filename = "${path.root}/admin.kubeconfig"
}
data "talos_client_configuration" "this" {
count = length(values({ for k, v in local.nodes_with_address : k => v if v.type == "controlplane" })) > 0 ? 1 : 0
cluster_name = var.cluster.name
client_configuration = talos_machine_secrets.this.client_configuration
endpoints = values({ for k, v in local.nodes_with_address : k => v if v.type == "controlplane" })[*].ipv4
}
resource "local_file" "talosconfig" {
count = length(values({ for k, v in local.nodes : k => v if v.type == "controlplane" })) > 0 ? 1 : 0
content = nonsensitive(data.talos_client_configuration.this[0].talos_config)
filename = "${path.root}/admin.talosconfig"
}