refactor(structure): move to 7project dir

This commit is contained in:
2025-10-05 01:30:55 +02:00
parent 291305c2e5
commit d58d553945
111 changed files with 6638 additions and 36 deletions

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,39 @@
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]
}
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
spec:
newTunnel:
name: ${cloudflare_tunnel_name}
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

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

View File

@@ -0,0 +1,179 @@
apiVersion: k8s.mariadb.com/v1alpha1
kind: MariaDB
metadata:
name: mariadb-repl
namespace: mariadb-operator
spec:
rootPasswordSecretKeyRef:
name: mariadb-secret
key: root-password
username: mariadb
passwordSecretKeyRef:
name: mariadb-secret
key: password
database: mariadb
storage:
size: 5Gi
storageClassName: longhorn
resizeInUseVolumes: true
waitForVolumeResize: true
volumeClaimTemplate:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: longhorn
replicas: 3
replicasAllowEvenNumber: true
podSpec:
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
seccompProfile:
type: RuntimeDefault
maxScale:
enabled: true
kubernetesService:
type: LoadBalancer
metadata:
annotations:
metallb.universe.tf/loadBalancerIPs: {{ .Values.metallb.maxscale_ip | default "" | quote }}
connection:
secretName: mxs-repl-conn
port: 3306
metrics:
enabled: true
serviceMonitor:
enabled: true
interval: 30s
scrapeTimeout: 10s
prometheusRelease: kube-prometheus-stack
jobLabel: mariadb-monitoring
tls:
enabled: true
replication:
enabled: true
primary:
podIndex: 0
automaticFailover: true
replica:
waitPoint: AfterSync
gtid: CurrentPos
replPasswordSecretKeyRef:
name: mariadb-secret
key: password
connectionTimeout: 10s
connectionRetries: 10
syncTimeout: 10s
syncBinlog: 1
probesEnabled: true
service:
type: LoadBalancer
metadata:
annotations:
metallb.universe.tf/loadBalancerIPs: {{ .Values.metallb.service_ip | default "" | quote }}
connection:
secretName: mariadb-repl-conn
secretTemplate:
key: dsn
primaryService:
type: LoadBalancer
metadata:
annotations:
metallb.universe.tf/loadBalancerIPs: {{ .Values.metallb.primary_ip | default "" | quote }}
primaryConnection:
secretName: mariadb-repl-conn-primary
secretTemplate:
key: dsn
secondaryService:
type: LoadBalancer
metadata:
annotations:
metallb.universe.tf/loadBalancerIPs: {{ .Values.metallb.secondary_ip | default "" | quote }}
secondaryConnection:
secretName: mariadb-repl-conn-secondary
secretTemplate:
key: dsn
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- mariadb-repl
topologyKey: kubernetes.io/hostname
tolerations:
- key: "k8s.mariadb.com/ha"
operator: "Exists"
effect: "NoSchedule"
podDisruptionBudget:
maxUnavailable: 33%
updateStrategy:
type: ReplicasFirstPrimaryLast
myCnf: |
[mariadb]
bind-address=*
default_storage_engine=InnoDB
binlog_format=row
innodb_autoinc_lock_mode=2
innodb_buffer_pool_size=1024M
max_allowed_packet=256M
#timeZone: Europe/Prague
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 1Gi
livenessProbe:
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 5
readinessProbe:
initialDelaySeconds: 20
periodSeconds: 5
timeoutSeconds: 5
metrics:
enabled: true
serviceMonitor:
enabled: true
interval: 30s
scrapeTimeout: 10s
prometheusRelease: kube-prometheus-stack
jobLabel: mariadb-monitoring
tls:
enabled: true
required: true
suspend: false

View File

@@ -0,0 +1,18 @@
apiVersion: k8s.mariadb.com/v1alpha1
kind: Grant
metadata:
name: grant
spec:
mariaDbRef:
name: mariadb-repl
namespace: mariadb-operator
waitForIt: false
privileges:
- "ALL PRIVILEGES"
database: "*"
table: "*"
username: {{ .Values.user.name | default "user" }}
grantOption: true
host: {{ .Values.user.host | default "%" | quote }}
requeueInterval: 30s
retryInterval: 5s

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: mariadb-repl-0
namespace: mariadb-operator
spec:
selector:
app.kubernetes.io/instance: mariadb-repl
app.kubernetes.io/name: mariadb
statefulset.kubernetes.io/pod-name: mariadb-repl-0
ports:
- name: mariadb
port: 3306
targetPort: 3306
protocol: TCP
type: ClusterIP

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: mariadb-repl-1
namespace: mariadb-operator
spec:
selector:
app.kubernetes.io/instance: mariadb-repl
app.kubernetes.io/name: mariadb
statefulset.kubernetes.io/pod-name: mariadb-repl-1
ports:
- name: mariadb
port: 3306
targetPort: 3306
protocol: TCP
type: ClusterIP

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: mariadb-repl-2
namespace: mariadb-operator
spec:
selector:
app.kubernetes.io/instance: mariadb-repl
app.kubernetes.io/name: mariadb
statefulset.kubernetes.io/pod-name: mariadb-repl-2
ports:
- name: mariadb
port: 3306
targetPort: 3306
protocol: TCP
type: ClusterIP

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

@@ -0,0 +1,32 @@
{{- if (.Values.phpmyadmin.enabled | default true) }}
apiVersion: v1
kind: ConfigMap
metadata:
name: phpmyadmin-config
namespace: mariadb-operator
data:
hosts-init-script.sh: |-
#!/bin/bash
echo "
/* Maximum number of databases displayed on one page */
\$cfg['MaxDbList'] = 300;
\$cfg['MaxNavigationItems'] = 300;
/* Additional servers */
\$servers = [
{{- range $i, $e := until (int (3)) }}
'mariadb-repl-{{ $i }}',
{{- end }}
];
foreach (\$servers as \$server) {
\$i++;
/* Authentication type */
\$cfg['Servers'][\$i]['auth_type'] = 'cookie';
/* Server parameters */
\$cfg['Servers'][\$i]['host'] = \$server;
\$cfg['Servers'][\$i]['port'] = '3306';
\$cfg['Servers'][\$i]['compress'] = false;
\$cfg['Servers'][\$i]['AllowNoPassword'] = false;
}
" >> /opt/bitnami/phpmyadmin/config.inc.php
{{- end }}

View File

@@ -0,0 +1,76 @@
{{- if (.Values.phpmyadmin.enabled | default true) }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: phpmyadmin
namespace: mariadb-operator
labels:
app: phpmyadmin
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: phpmyadmin
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: phpmyadmin
spec:
containers:
- env:
- name: DATABASE_ENABLE_SSL
value: "yes"
- name: DATABASE_HOST
value: "mariadb-repl"
- name: DATABASE_PORT_NUMBER
value: "3306"
- name: PHPMYADMIN_ALLOW_NO_PASSWORD
value: "false"
image: "bitnamilegacy/phpmyadmin:5.2.2"
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: http
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: phpmyadmin
ports:
- containerPort: 8080
name: http
protocol: TCP
- containerPort: 8443
name: https
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: http
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
volumeMounts:
- mountPath: /docker-entrypoint-init.d/hosts-init-script.sh
name: config
subPath: hosts-init-script.sh
ip: 127.0.0.1
restartPolicy: Always
volumes:
- configMap:
defaultMode: 511
name: phpmyadmin-config
optional: false
name: config
{{- end }}

View File

@@ -0,0 +1,18 @@
{{- if (.Values.phpmyadmin.enabled | default true) }}
apiVersion: v1
kind: Service
metadata:
name: "phpmyadmin"
namespace: {{ .Values.namespace | default "mariadb-operator" | quote }}
labels:
app: "phpmyadmin"
spec:
clusterIP: None
ports:
- name: http
port: {{ .Values.phpmyadmin.servicePort | default 8080 }}
protocol: TCP
targetPort: {{ .Values.phpmyadmin.servicePort | default 8080 }}
selector:
app: "phpmyadmin"
{{- 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

@@ -0,0 +1,16 @@
apiVersion: k8s.mariadb.com/v1alpha1
kind: User
metadata:
name: mariadb-user
namespace: mariadb-operator
spec:
mariaDbRef:
name: mariadb-repl
namespace: mariadb-operator
waitForIt: false
host: {{ .Values.user.host | default "%" | quote }}
name: {{ .Values.user.name | default "user" }}
passwordPlugin: {}
passwordSecretKeyRef:
key: user-password
name: mariadb-secret

View File

@@ -0,0 +1,17 @@
# Default values for maxscale-helm.
# This file can be used to override manifest parameters.
user:
name: user
host: "%"
metallb:
maxscale_ip: ""
service_ip: ""
primary_ip: ""
secondary_ip: ""
phpmyadmin:
enabled: true
base_domain: example.com

View File

@@ -0,0 +1,75 @@
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" "mariadb-operator" {
metadata {
name = "mariadb-operator"
}
}
locals {
mariadb_secret_yaml = templatefile("${path.module}/mariadb-secret.yaml", {
password = var.mariadb_password
user_password = var.mariadb_user_password
root_password = var.mariadb_root_password
})
}
resource "kubectl_manifest" "secrets" {
yaml_body = local.mariadb_secret_yaml
depends_on = [ kubernetes_namespace.mariadb-operator ]
}
resource "helm_release" "mariadb-operator-crds" {
name = "mariadb-operator-crds"
repository = "https://helm.mariadb.com/mariadb-operator"
chart = "mariadb-operator-crds"
namespace = "mariadb-operator"
version = "25.8.4"
depends_on = [ kubectl_manifest.secrets ]
timeout = 3600
}
resource "helm_release" "mariadb-operator" {
name = "mariadb-operator"
repository = "https://helm.mariadb.com/mariadb-operator"
chart = "mariadb-operator"
depends_on = [ helm_release.mariadb-operator-crds, kubectl_manifest.secrets ]
namespace = "mariadb-operator"
timeout = 3600
}
resource "helm_release" "maxscale_helm" {
name = "maxscale-helm"
chart = "${path.module}/charts/maxscale-helm"
version = "1.0.7"
depends_on = [ helm_release.mariadb-operator-crds, kubectl_manifest.secrets ]
timeout = 3600
set = [
{ name = "user.name", value = var.mariadb_user_name },
{ name = "user.host", value = var.mariadb_user_host },
{ name = "metallb.maxscale_ip", value = var.maxscale_ip },
{ name = "metallb.service_ip", value = var.service_ip },
{ name = "metallb.primary_ip", value = var.primary_ip },
{ name = "metallb.secondary_ip", value = var.secondary_ip },
{ name = "phpmyadmin.enabled", value = tostring(var.phpmyadmin_enabled) },
{ name = "base_domain", value = var.cloudflare_domain }
]
}

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: Secret
metadata:
name: mariadb-secret
namespace: mariadb-operator
labels:
k8s.mariadb.com/watch: ""
stringData:
password: ${password}
user-password: ${user_password}
root-password: ${root_password}

View File

@@ -0,0 +1,58 @@
variable "mariadb_password" {
description = "Password for standard MariaDB users (stored in Secret). Keep secure."
type = string
sensitive = true
}
variable "mariadb_root_password" {
description = "Root password for MariaDB (stored in Secret). Keep secure."
type = string
sensitive = true
}
variable "mariadb_user_name" {
description = "Application username to create and grant privileges to"
type = string
}
variable "mariadb_user_host" {
description = "Host (wildcard or specific) for the application user"
type = string
}
variable "maxscale_ip" {
description = "MetalLB IP for MaxScale service"
type = string
}
variable "service_ip" {
description = "MetalLB IP for general MariaDB service"
type = string
}
variable "primary_ip" {
description = "MetalLB IP for MariaDB primary service"
type = string
}
variable "secondary_ip" {
description = "MetalLB IP for MariaDB secondary service"
type = string
}
variable "phpmyadmin_enabled" {
description = "Whether to deploy phpMyAdmin auxiliary components"
type = bool
}
variable "mariadb_user_password" {
description = "Password for the application MariaDB user"
type = string
sensitive = true
}
variable "cloudflare_domain" {
type = string
default = "Base cloudflare domain, e.g. example.com"
nullable = false
}

View File

@@ -0,0 +1,70 @@
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" "metallb-system" {
metadata {
name = "metallb-system"
labels = {
"pod-security.kubernetes.io/enforce" = "privileged"
}
}
}
resource "helm_release" "metallb" {
depends_on = [ kubernetes_namespace.metallb-system ]
name = "metallb"
repository = "https://metallb.github.io/metallb"
chart = "metallb"
namespace = "metallb-system"
version = "0.14.9"
timeout = 3600
}
resource "kubectl_manifest" "metallb_pool" {
depends_on = [ helm_release.metallb ]
yaml_body = yamlencode({
apiVersion = "metallb.io/v1beta1"
kind = "IPAddressPool"
metadata = {
name = "metallb-pool"
namespace = "metallb-system"
}
spec = {
addresses = [var.metallb_ip_range]
}
})
}
resource "kubectl_manifest" "metallb_l2_advertisement" {
depends_on = [ kubectl_manifest.metallb_pool ]
yaml_body = yamlencode({
apiVersion = "metallb.io/v1beta1"
kind = "L2Advertisement"
metadata = {
name = "l2-advertisement"
namespace = "metallb-system"
}
spec = {
ipAddressPools = ["metallb-pool"]
}
})
}

View File

@@ -0,0 +1,4 @@
variable "metallb_ip_range" {
description = "IP address range for MetalLB address pool"
type = string
}

View File

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

View File

@@ -0,0 +1,66 @@
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"
}
time = {
source = "hashicorp/time"
version = "0.13.1"
}
}
}
# Create namespace for monitoring
resource "kubernetes_namespace" "monitoring" {
metadata {
name = "monitoring"
labels = {
"pod-security.kubernetes.io/enforce" = "privileged"
}
}
}
# Deploy kube-prometheus-stack
resource "helm_release" "kube_prometheus_stack" {
name = "kube-prometheus-stack"
repository = "https://prometheus-community.github.io/helm-charts"
chart = "kube-prometheus-stack"
namespace = kubernetes_namespace.monitoring.metadata[0].name
version = "67.2.1" # Check for latest version
# Wait for CRDs to be created
wait = true
timeout = 600
force_update = false
recreate_pods = false
# Reference the values file
values = [
file("${path.module}/values.yaml")
]
depends_on = [
kubernetes_namespace.monitoring
]
}
resource "kubectl_manifest" "argocd-tunnel-bind" {
depends_on = [helm_release.kube_prometheus_stack]
yaml_body = templatefile("${path.module}/grafana-ui.yaml", {
base_domain = var.cloudflare_domain
})
}

View File

@@ -0,0 +1,189 @@
# Prometheus configuration
prometheus:
prometheusSpec:
retention: 30d
retentionSize: "45GB"
# Storage configuration
storageSpec:
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 50Gi
# storageClassName: "your-storage-class" # Uncomment and specify if needed
# Resource limits
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
cpu: 2000m
memory: 4Gi
# Scrape interval
scrapeInterval: 30s
evaluationInterval: 30s
# Service configuration
service:
type: ClusterIP
port: 9090
# Ingress (disabled by default)
ingress:
enabled: false
# ingressClassName: nginx
# hosts:
# - prometheus.example.com
# tls:
# - secretName: prometheus-tls
# hosts:
# - prometheus.example.com
# Grafana configuration
grafana:
enabled: true
# Admin credentials
adminPassword: "admin" # CHANGE THIS IN PRODUCTION!
# Persistence
persistence:
enabled: true
size: 10Gi
# storageClassName: "your-storage-class" # Uncomment and specify if needed
# Resource limits
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
# Service configuration
service:
type: ClusterIP
port: 80
# Ingress (disabled by default)
ingress:
enabled: false
# ingressClassName: nginx
# hosts:
# - grafana.example.com
# tls:
# - secretName: grafana-tls
# hosts:
# - grafana.example.com
# Default dashboards
defaultDashboardsEnabled: true
defaultDashboardsTimezone: Europe/Prague
# Alertmanager configuration
alertmanager:
enabled: true
alertmanagerSpec:
# Storage configuration
storage:
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
# storageClassName: "your-storage-class" # Uncomment and specify if needed
# Resource limits
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
# Service configuration
service:
type: ClusterIP
port: 9093
# Ingress (disabled by default)
ingress:
enabled: false
# ingressClassName: nginx
# hosts:
# - alertmanager.example.com
# tls:
# - secretName: alertmanager-tls
# hosts:
# - alertmanager.example.com
# Alertmanager configuration
config:
global:
resolve_timeout: 5m
route:
group_by: [ 'alertname', 'cluster', 'service' ]
group_wait: 10s
group_interval: 10s
repeat_interval: 12h
receiver: 'null'
routes:
- match:
alertname: Watchdog
receiver: 'null'
receivers:
- name: 'null'
# Add your receivers here (email, slack, pagerduty, etc.)
# - name: 'slack'
# slack_configs:
# - api_url: 'YOUR_SLACK_WEBHOOK_URL'
# channel: '#alerts'
# title: '{{ range .Alerts }}{{ .Annotations.summary }}\n{{ end }}'
# text: '{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}'
# Node Exporter
nodeExporter:
enabled: true
# Kube State Metrics
kubeStateMetrics:
enabled: true
# Prometheus Operator
prometheusOperator:
enabled: true
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
# Service Monitors
# Automatically discover and monitor services with appropriate labels
prometheus-node-exporter:
prometheus:
monitor:
enabled: true
# Additional ServiceMonitors can be defined here
# additionalServiceMonitors: []
# Global settings
global:
rbac:
create: true

View File

@@ -0,0 +1,5 @@
variable "cloudflare_domain" {
type = string
default = "Base cloudflare domain, e.g. example.com"
nullable = false
}

View File

@@ -0,0 +1,81 @@
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"
}
time = {
source = "hashicorp/time"
version = "0.13.1"
}
}
}
# Define the Helm release for RabbitMQ.
# This resource will install the RabbitMQ chart from the Bitnami repository.
resource "helm_release" "rabbitmq" {
# The name of the release in Kubernetes.
name = "rabbitmq"
# The repository where the chart is located.
repository = "https://charts.bitnami.com/bitnami"
# The name of the chart to deploy.
chart = "rabbitmq"
# The version of the chart to deploy. It's best practice to pin the version.
version = "14.4.1"
# The Kubernetes namespace to deploy into.
# If the namespace doesn't exist, you can create it with a kubernetes_namespace resource.
namespace = "rabbitmq"
create_namespace = true
# Override default chart values.
# This is where you customize your RabbitMQ deployment.
set = [
{
name = "auth.username"
value = "admin"
},
{
name = "auth.password"
value = var.rabbitmq-password
},
{
name = "persistence.enabled"
value = "true"
},
{
name = "replicaCount"
value = "1"
},
{
name = "podAntiAffinityPreset"
value = "soft"
},
{
name = "image.repository"
value = "bitnamilegacy/rabbitmq"
},
]
}
resource "kubectl_manifest" "rabbitmq_ui" {
yaml_body = templatefile("${path.module}/rabbit-ui.yaml", {
base_domain = var.base_domain
})
depends_on = [helm_release.rabbitmq]
}

View File

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

View File

@@ -0,0 +1,11 @@
variable "base_domain" {
type = string # The type of the variable, in this case a string
nullable = false # Description of what this variable represents
}
variable "rabbitmq-password" {
type = string
nullable = false
sensitive = true
description = "Admin password for RabbitMQ user"
}

View File

@@ -0,0 +1,68 @@
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"
}
time = {
source = "hashicorp/time"
version = "0.13.1"
}
}
}
resource "helm_release" "redis_operator" {
name = "redis-operator"
repository = "https://ot-container-kit.github.io/helm-charts/"
chart = "redis-operator"
namespace = "ot-operators"
create_namespace = true
}
resource "kubectl_manifest" "replication" {
yaml_body = templatefile("${path.module}/replication.yaml", {})
depends_on = [helm_release.redis_operator]
}
resource "kubectl_manifest" "sentinel" {
yaml_body = templatefile("${path.module}/sentinel.yaml", {})
depends_on = [kubectl_manifest.replication]
}
resource "helm_release" "redisinsight_gui" {
name = "redisinsight-gui"
repository = "https://mrnim94.github.io/redisinsight/"
chart = "redisinsight"
namespace = "ot-operators"
create_namespace = false
version = "1.3.1" # ověř verzi podle ArtifactHub / podle toho koho chceš použít
depends_on = [kubectl_manifest.sentinel]
# případně values
# values = [file("${path.module}/values-redisinsight.yaml")]
set = [{
#name = "persistence.storageClassName"
#value = "longhorn"
name = "persistence.enabled"
value = "false"
}]
}
resource "kubectl_manifest" "redis-ui" {
yaml_body = templatefile("${path.module}/redis-ui.yaml", {
base_domain = var.cloudflare_base_domain
})
}

View File

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

View File

@@ -0,0 +1,28 @@
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisReplication
metadata:
name: redis-replication
namespace: ot-operators
spec:
clusterSize: 3
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
kubernetesConfig:
image: quay.io/opstree/redis:v8.2.1
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 101m
memory: 128Mi
limits:
cpu: 101m
memory: 128Mi
storage:
volumeClaimTemplate:
spec:
storageClassName: longhorn
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 5Gi

View File

@@ -0,0 +1,22 @@
apiVersion: redis.redis.opstreelabs.in/v1beta2
kind: RedisSentinel
metadata:
name: redis-sentinel
namespace: ot-operators
spec:
clusterSize: 3
podSecurityContext:
runAsUser: 1000
fsGroup: 1000
redisSentinelConfig:
redisReplicationName : redis-replication
kubernetesConfig:
image: quay.io/opstree/redis-sentinel:v8.2.1
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 101m
memory: 128Mi
limits:
cpu: 101m
memory: 128Mi

View File

@@ -0,0 +1,5 @@
variable "cloudflare_base_domain" {
type = string
description = "Base domain for Cloudflare DNS records"
nullable = false
}

View File

@@ -0,0 +1,35 @@
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" "longhorn-system" {
metadata {
name = "longhorn-system"
labels = {
"pod-security.kubernetes.io/enforce" = "privileged"
}
}
}
resource "helm_release" "longhorn" {
depends_on = [ kubernetes_namespace.longhorn-system ]
name = "longhorn"
repository = "https://charts.longhorn.io/"
chart = "longhorn"
namespace = "longhorn-system"
version = "1.9.1"
timeout = 3600
}