diff --git a/cluster/cloudflare.tf b/cluster/cloudflare.tf new file mode 100644 index 00000000..84cd33ff --- /dev/null +++ b/cluster/cloudflare.tf @@ -0,0 +1,81 @@ +/*--- +apiVersion: v1 +kind: Secret +metadata: + name: cloudflare + namespace: traefik +type: Opaque +stringData: + api-token: XXX +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: cloudflare + namespace: traefik +spec: + acme: + server: https://acme-v02.api.letsencrypt.org/directory + email: email@example.com + privateKeySecretRef: + name: cloudflare-key + solvers: + - dns01: + cloudflare: + email: email@example.com + apiTokenSecretRef: + name: cloudflare + key: api-token + */ + +variable "cloudflare_api_token" { + type = string +} + +resource "kubernetes_secret" "cloudflare_api_token" { + metadata { + name = "cloudflare-api-token" + namespace = "traefik" + } + data = { + api-token = var.cloudflare_api_token + } + type = "Opaque" +} + +resource "kubernetes_manifest" "cert_manager_cloudflare_issuer" { + depends_on = [ + helm_release.traefik + ] + + manifest = { + "apiVersion" = "cert-manager.io/v1" + "kind" = "Issuer" + "metadata" = { + "name" = "cloudflare" + "namespace" = "traefik" + } + "spec" = { + "acme" = { + "email" = "acme@inskip.me" + "privateKeySecretRef" = { + "name" = "cloudflare-key" + } + "server" = "https://acme-v02.api.letsencrypt.org/directory" + "solvers" = [ + { + "dns01" = { + "cloudflare" = { + "apiTokenSecretRef" = { + "key" = "api-token" + "name" = "cloudflare-api-token" + } + "email" = "kat@inskip.me" + } + } + }, + ] + } + } + } +} \ No newline at end of file diff --git a/cluster/helm.tf b/cluster/helm.tf new file mode 100644 index 00000000..358cf877 --- /dev/null +++ b/cluster/helm.tf @@ -0,0 +1,8 @@ +provider "helm" { + kubernetes { + host = "https://ran.gensokyo.zone:6443" + client_certificate = var.client_certificate + client_key = var.client_key + cluster_ca_certificate = var.cluster_ca_certificate + } +} diff --git a/cluster/kubernetes.tf b/cluster/kubernetes.tf new file mode 100644 index 00000000..d258363a --- /dev/null +++ b/cluster/kubernetes.tf @@ -0,0 +1,19 @@ +variable "client_certificate" { + type = string +} + +variable "client_key" { + type = string +} + +variable "cluster_ca_certificate" { + type = string +} + + +provider "kubernetes" { + host = "https://ran.gensokyo.zone:6443" + client_certificate = var.client_certificate + client_key = var.client_key + cluster_ca_certificate = var.cluster_ca_certificate +} \ No newline at end of file diff --git a/cluster/terraform.tf b/cluster/terraform.tf new file mode 100644 index 00000000..cf54eadd --- /dev/null +++ b/cluster/terraform.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + helm = { + source = "hashicorp/helm" + version = "2.9.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "2.20.0" + } + } +} diff --git a/cluster/traefik.tf b/cluster/traefik.tf new file mode 100644 index 00000000..80d39f8e --- /dev/null +++ b/cluster/traefik.tf @@ -0,0 +1,17 @@ +resource "helm_release" "traefik" { + name = "traefik" + repository = "https://traefik.github.io/charts" + chart = "traefik" + create_namespace = true + namespace = "traefik" + + timeout = var.helm_timeout + + values = [ + yamlencode({ + deployment = { + replicas = 1 + } + }) + ] +} \ No newline at end of file diff --git a/nixos/roles/bootable.nix b/nixos/roles/bootable.nix index 9e554dda..2fa469f2 100644 --- a/nixos/roles/bootable.nix +++ b/nixos/roles/bootable.nix @@ -15,7 +15,7 @@ in { "net.core.wmem_max" = 16777216; "net.ipv4.tcp_rmem" = "4096 87380 16777216"; "net.ipv4.tcp_wmem" = "4096 65536 16777216"; - "net.ipv4.ip_forward" = "1"; + "net.ipv4.ip_forward" = mkDefault "1"; "net.ipv6.conf.all.forwarding" = "1"; }; loader = { diff --git a/nixos/roles/k8s-cluster/kubernetes.nix b/nixos/roles/k8s-cluster/kubernetes.nix index 94d0b611..fdd2ad95 100644 --- a/nixos/roles/k8s-cluster/kubernetes.nix +++ b/nixos/roles/k8s-cluster/kubernetes.nix @@ -1,13 +1,32 @@ -_: { - services.kubernetes = { - roles = ["master" "node"]; - apiserver.enable = true; - controllerManager.enable = true; - scheduler.enable = true; - addonManager.enable = true; - easyCerts = true; - addons.dns.enable = true; # CoreDNS - proxy.enable = true; - flannel.enable = true; +{pkgs, ...}: let + kubeMasterIP = "100.105.14.66"; + kubeMasterHostname = "ran.gensokyo.zone"; + kubeMasterAPIServerPort = 6443; +in { + # packages for administration tasks + environment.systemPackages = with pkgs; [ + kompose + kubectl + kubernetes + ]; + + networking = { + firewall.allowedTCPPorts = [kubeMasterAPIServerPort]; + extraHosts = "${kubeMasterIP} ${kubeMasterHostname}"; + }; + + systemd.services.etcd.preStart = ''${pkgs.writeShellScript "etcd-wait" '' + while [ ! -f /var/lib/kubernetes/secrets/etcd.pem ]; do sleep 1; done + ''}''; + + services.kubernetes = { + roles = ["master" "node"]; + addons.dns.enable = true; # CoreDNS + masterAddress = kubeMasterHostname; + apiserverAddress = "https://${kubeMasterHostname}:${toString kubeMasterAPIServerPort}"; + apiserver = { + securePort = kubeMasterAPIServerPort; + advertiseAddress = kubeMasterIP; }; -} \ No newline at end of file + }; +} diff --git a/systems/default.nix b/systems/default.nix index 1ea1d70e..92776f06 100644 --- a/systems/default.nix +++ b/systems/default.nix @@ -140,7 +140,7 @@ }; hostname = "${name}.inskip.me"; sshOpts = ["-p" "${builtins.toString (builtins.head inputs.self.nixosConfigurations.${name}.config.services.openssh.ports)}"]; - sshUser = "root"; + sshUser = "deploy"; user = "root"; autoRollback = true; magicRollback = true; diff --git a/systems/goliath.nix b/systems/goliath.nix index b3238564..5f2e96a4 100644 --- a/systems/goliath.nix +++ b/systems/goliath.nix @@ -29,6 +29,8 @@ _: let deploy-rs.deploy-rs # deployment system rnix-lsp # vscode nix extensions terraform # terraform + kubectl + k9s ]; boot.loader.systemd-boot.enable = true; diff --git a/systems/ran.nix b/systems/ran.nix index d449b536..7f53e383 100644 --- a/systems/ran.nix +++ b/systems/ran.nix @@ -8,6 +8,7 @@ _: let }: { imports = with tree.nixos.roles; [ server + k8s-cluster (modulesPath + "/profiles/qemu-guest.nix") ]; fileSystems."/" = {