feat(infrastructure): add cloudflare, argocd

This commit is contained in:
2025-09-22 18:51:52 +02:00
parent ec3017929e
commit 5de64c5b1f
19 changed files with 340 additions and 23 deletions

View File

@@ -12,6 +12,10 @@ terraform {
source = "hashicorp/kubernetes" source = "hashicorp/kubernetes"
version = "2.38.0" version = "2.38.0"
} }
kustomization = {
source = "kbst/kustomization"
version = "0.9.6"
}
} }
} }
@@ -23,6 +27,9 @@ provider "kubectl" {
config_path = "./kubeconfig" config_path = "./kubeconfig"
} }
provider "kustomization" {
kubeconfig_path = "./kubeconfig"
}
provider "helm" { provider "helm" {
kubernetes = { kubernetes = {
@@ -30,6 +37,10 @@ provider "helm" {
} }
} }
module "storage" {
source = "${path.module}/modules/storage"
}
module "loadbalancer" { module "loadbalancer" {
source = "${path.module}/modules/metallb" source = "${path.module}/modules/metallb"
depends_on = [module.storage] depends_on = [module.storage]
@@ -37,10 +48,25 @@ module "loadbalancer" {
metallb_ip_range = var.metallb_ip_range metallb_ip_range = var.metallb_ip_range
} }
module "cert-manager" {
source = "${path.module}/modules/cert-manager"
}
module "cloudflare" {
source = "${path.module}/modules/cloudflare"
depends_on = [module.cert-manager]
cloudflare_api_token = var.cloudflare_api_token
cloudflare_tunnel_name = var.cloudflare_tunnel_name
cloudflare_email = var.cloudflare_email
cloudflare_domain = var.cloudflare_domain
cloudflare_account_id = var.cloudflare_account_id
}
module "database" { module "database" {
source = "${path.module}/modules/maxscale" source = "${path.module}/modules/maxscale"
depends_on = [ module.storage, module.loadbalancer ] depends_on = [module.storage, module.loadbalancer, module.cloudflare]
mariadb_password = var.mariadb_password mariadb_password = var.mariadb_password
mariadb_root_password = var.mariadb_root_password mariadb_root_password = var.mariadb_root_password
@@ -54,8 +80,13 @@ module "database" {
secondary_ip = var.metallb_secondary_ip secondary_ip = var.metallb_secondary_ip
phpmyadmin_enabled = var.phpmyadmin_enabled phpmyadmin_enabled = var.phpmyadmin_enabled
cloudflare_domain = var.cloudflare_domain
} }
module "storage" { module "argocd" {
source = "${path.module}/modules/storage" source = "${path.module}/modules/argocd"
depends_on = [module.storage, module.loadbalancer, module.cloudflare]
argocd_admin_password = var.argocd_admin_password
cloudflare_domain = var.cloudflare_domain
} }

View File

@@ -0,0 +1,14 @@
apiVersion: networking.cfargotunnel.com/v1alpha1
kind: TunnelBinding
metadata:
name: argocd-tunnel-binding
namespace: argocd
subjects:
- name: argocd-server
spec:
target: https://argocd-server.argocd.svc.cluster.local
fqdn: argocd.${base_domain}
noTlsVerify: true
tunnelRef:
kind: ClusterTunnel
name: cluster-tunnel

View File

@@ -0,0 +1,43 @@
terraform {
required_providers {
kubectl = {
source = "gavinbunney/kubectl"
version = "1.19.0"
}
helm = {
source = "hashicorp/helm"
version = "3.0.2"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.38.0"
}
}
}
resource "kubernetes_namespace" "argocd" {
metadata {
name = "argocd"
}
}
resource "helm_release" "argocd" {
name = "argocd"
namespace = "argocd"
repository = "https://argoproj.github.io/argo-helm"
chart = "argo-cd"
depends_on = [kubernetes_namespace.argocd]
set = [
{ name = "configs.secret.argocdServerAdminPassword", value = bcrypt(var.argocd_admin_password) },
]
}
resource "kubectl_manifest" "argocd-tunnel-bind" {
depends_on = [helm_release.argocd]
yaml_body = templatefile("${path.module}/argocd-ui.yaml", {
base_domain = var.cloudflare_domain
})
}

View File

@@ -0,0 +1,12 @@
variable "argocd_admin_password" {
type = string
nullable = false
sensitive = true
description = "ArgoCD admin password"
}
variable "cloudflare_domain" {
type = string
default = "Base cloudflare domain, e.g. example.com"
nullable = false
}

View File

@@ -0,0 +1,30 @@
terraform {
required_providers {
kubectl = {
source = "gavinbunney/kubectl"
version = "1.19.0"
}
helm = {
source = "hashicorp/helm"
version = "3.0.2"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.38.0"
}
}
}
resource "helm_release" "cert_manager" {
name = "cert-manager"
repository = "https://charts.jetstack.io"
chart = "cert-manager"
version = "v1.14.4"
namespace = "cert-manager"
create_namespace = true
set = [{
name = "installCRDs"
value = "true"
}]
}

View File

@@ -0,0 +1,12 @@
apiVersion: networking.cfargotunnel.com/v1alpha2
kind: ClusterTunnel
metadata:
name: cluster-tunnel # The ClusterTunnel Custom Resource Name
spec:
newTunnel:
name: ${cloudflare_tunnel_name} # Name of your new tunnel on Cloudflare
cloudflare:
email: ${cloudflare_email}
domain: ${cloudflare_domain}
secret: cloudflare-secrets
accountId: ${cloudflare_account_id}

View File

@@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: cloudflare-operator-system
resources:
- https://github.com/adyanth/cloudflare-operator.git/config/default?ref=v0.13.1

View File

@@ -0,0 +1,50 @@
terraform {
required_providers {
kubectl = {
source = "gavinbunney/kubectl"
version = "1.19.0"
}
helm = {
source = "hashicorp/helm"
version = "3.0.2"
}
kubernetes = {
source = "hashicorp/kubernetes"
version = "2.38.0"
}
kustomization = {
source = "kbst/kustomization"
version = "0.9.6"
}
}
}
data "kustomization" "cloudflare-kustomization" {
path = "${path.module}/kustomization"
}
resource "kustomization_resource" "cloudflare" {
provider = kustomization
for_each = data.kustomization.cloudflare-kustomization.ids
manifest = data.kustomization.cloudflare-kustomization.manifests[each.key]
}
resource "kubectl_manifest" "cloudflare-api-token" {
yaml_body = templatefile("${path.module}/secret.yaml", {
cloudflare_api_token = var.cloudflare_api_token
})
}
resource "kubectl_manifest" "cloudflare-tunnel" {
yaml_body = templatefile("${path.module}/cluster-tunnel.yaml", {
cloudflare_tunnel_name = var.cloudflare_tunnel_name
cloudflare_email = var.cloudflare_email
cloudflare_domain = var.cloudflare_domain
cloudflare_account_id = var.cloudflare_account_id
})
depends_on = [kustomization_resource.cloudflare]
}

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: cloudflare-secrets
namespace: cloudflare-operator-system
type: Opaque
stringData:
CLOUDFLARE_API_TOKEN: "${cloudflare_api_token}"

View File

@@ -0,0 +1,30 @@
variable "cloudflare_api_token" {
type = string
description = "Cloudflare API token"
sensitive = true
nullable = false
}
variable "cloudflare_tunnel_name" {
type = string
description = "Cloudflare Tunnel Name"
default = "tofu-tunnel"
nullable = false
}
variable "cloudflare_email" {
type = string
description = "Cloudflare Email"
nullable = false
}
variable "cloudflare_domain" {
type = string
description = "Cloudflare Domain"
nullable = false
}
variable "cloudflare_account_id" {
type = string
description = "Cloudflare Account ID"
nullable = false
}

View File

@@ -1,4 +1,4 @@
apiVersion: v2 apiVersion: v2
name: maxscale-helm name: maxscale-helm
version: 0.1.9 version: 1.0.2
description: Helm chart for MaxScale related Kubernetes manifests description: Helm chart for MaxScale related Kubernetes manifests

View File

@@ -0,0 +1,14 @@
apiVersion: networking.cfargotunnel.com/v1alpha1
kind: TunnelBinding
metadata:
name: maxscale-tunnel-binding
namespace: mariadb-operator
subjects:
- name: mariadb-repl-maxscale
spec:
target: https://mariadb-repl-maxscale-internal.mariadb-operator.svc.cluster.local:8989
fqdn: maxscale.{{ .Values.base_domain }}
noTlsVerify: true
tunnelRef:
kind: ClusterTunnel
name: cluster-tunnel

View File

@@ -10,23 +10,23 @@ data:
echo " echo "
/* Maximum number of databases displayed on one page */ /* Maximum number of databases displayed on one page */
$cfg['MaxDbList'] = 300; \$cfg['MaxDbList'] = 300;
$cfg['MaxNavigationItems'] = 300; \$cfg['MaxNavigationItems'] = 300;
/* Additional servers */ /* Additional servers */
$servers = [ \$servers = [
{{- range $i, $e := until (int (3)) }} {{- range $i, $e := until (int (3)) }}
'mariadb-repl-{{ $i }}', 'mariadb-repl-{{ $i }}',
{{- end }} {{- end }}
]; ];
foreach ($servers as $server) { foreach (\$servers as \$server) {
$i++; \$i++;
/* Authentication type */ /* Authentication type */
$cfg['Servers'][$i]['auth_type'] = 'cookie'; \$cfg['Servers'][\$i]['auth_type'] = 'cookie';
/* Server parameters */ /* Server parameters */
$cfg['Servers'][$i]['host'] = $server; \$cfg['Servers'][\$i]['host'] = \$server;
$cfg['Servers'][$i]['port'] = '3306'; \$cfg['Servers'][\$i]['port'] = '3306';
$cfg['Servers'][$i]['compress'] = false; \$cfg['Servers'][\$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = false; \$cfg['Servers'][\$i]['AllowNoPassword'] = false;
} }
" >> /opt/bitnami/phpmyadmin/config.inc.php " >> /opt/bitnami/phpmyadmin/config.inc.php
{{- end }} {{- end }}

View File

@@ -0,0 +1,14 @@
apiVersion: networking.cfargotunnel.com/v1alpha1
kind: TunnelBinding
metadata:
name: phpmyadmin-tunnel-binding
namespace: mariadb-operator
subjects:
- name: mariadb-repl-maxscale
spec:
target: http://phpmyadmin.mariadb-operator.svc.cluster.local:8080
fqdn: mysql.{{ .Values.base_domain }}
noTlsVerify: true
tunnelRef:
kind: ClusterTunnel
name: cluster-tunnel

View File

@@ -13,3 +13,5 @@ metallb:
phpmyadmin: phpmyadmin:
enabled: true enabled: true
base_domain: example.com

View File

@@ -58,7 +58,7 @@ resource "helm_release" "mariadb-operator" {
resource "helm_release" "maxscale_helm" { resource "helm_release" "maxscale_helm" {
name = "maxscale-helm" name = "maxscale-helm"
chart = "${path.module}/charts/maxscale-helm" chart = "${path.module}/charts/maxscale-helm"
version = "0.1.9" version = "1.0.2"
depends_on = [ helm_release.mariadb-operator-crds, kubectl_manifest.secrets ] depends_on = [ helm_release.mariadb-operator-crds, kubectl_manifest.secrets ]
timeout = 3600 timeout = 3600
@@ -70,5 +70,6 @@ resource "helm_release" "maxscale_helm" {
{ name = "metallb.primary_ip", value = var.primary_ip }, { name = "metallb.primary_ip", value = var.primary_ip },
{ name = "metallb.secondary_ip", value = var.secondary_ip }, { name = "metallb.secondary_ip", value = var.secondary_ip },
{ name = "phpmyadmin.enabled", value = tostring(var.phpmyadmin_enabled) }, { name = "phpmyadmin.enabled", value = tostring(var.phpmyadmin_enabled) },
{ name = "base_domain", value = var.cloudflare_domain }
] ]
} }

View File

@@ -50,3 +50,9 @@ variable "mariadb_user_password" {
type = string type = string
sensitive = true sensitive = true
} }
variable "cloudflare_domain" {
type = string
default = "Base cloudflare domain, e.g. example.com"
nullable = false
}

View File

@@ -20,3 +20,10 @@ metallb_secondary_ip = "10.80.0.131"
# phpMyAdmin toggle # phpMyAdmin toggle
phpmyadmin_enabled = true phpmyadmin_enabled = true
cloudflare_account_id = "CHANGE_ME"
cloudflare_api_token = "CHANGE_ME"
cloudflare_email = "CHANGE_ME"
cloudflare_tunnel_name = "CHANGE_ME"
cloudflare_domain = "CHANGE_ME"

View File

@@ -63,3 +63,41 @@ variable "mariadb_user_password" {
sensitive = true sensitive = true
nullable = false nullable = false
} }
variable "cloudflare_api_token" {
type = string
description = "Cloudflare API token"
sensitive = true
nullable = false
}
variable "cloudflare_tunnel_name" {
type = string
description = "Cloudflare Tunnel Name"
default = "cluster-tunnel"
nullable = false
}
variable "cloudflare_email" {
type = string
description = "Cloudflare Email"
nullable = false
}
variable "cloudflare_domain" {
type = string
description = "Cloudflare Domain"
nullable = false
}
variable "cloudflare_account_id" {
type = string
description = "Cloudflare Account ID"
nullable = false
}
variable "argocd_admin_password" {
type = string
nullable = false
sensitive = true
description = "ArgoCD admin password"
}