mirror of
https://github.com/lukaszraczylo/rpi-home-cluster-setup.git
synced 2026-10-17 01:17:50 +00:00
Home K8S setup
This commit is contained in:
@@ -0,0 +1 @@
|
||||
**.terraform
|
||||
@@ -0,0 +1,22 @@
|
||||
ADDITIONAL_ARGS=-var 'traefik_api_key=$(TRAEFIK_API_KEY)' -var "github_user=$(GH_USER)" -var "github_pat=$(GH_TOKEN)"
|
||||
|
||||
apply:
|
||||
cd infrastructure; terraform apply $(ADDITIONAL_ARGS) -auto-approve -var-file ../variables.tfvars
|
||||
|
||||
plan:
|
||||
cd infrastructure; terraform plan $(ADDITIONAL_ARGS) -var-file ../variables.tfvars
|
||||
|
||||
destroy:
|
||||
cd infrastructure; terraform destroy $(ADDITIONAL_ARGS) -var-file ../variables.tfvars
|
||||
|
||||
refresh:
|
||||
cd infrastructure; terraform refresh $(ADDITIONAL_ARGS) -var-file ../variables.tfvars
|
||||
|
||||
init:
|
||||
cd infrastructure; rm -fr .terraform; terraform init
|
||||
|
||||
import:
|
||||
cd infrastructure; terraform import $(ADDITIONAL_ARGS) -var-file ../variables.tfvars $(ARGS)
|
||||
|
||||
lint:
|
||||
terraform fmt -recursive infrastructure/
|
||||
@@ -0,0 +1,231 @@
|
||||
resource "kubernetes_storage_class" "adguard_nfs" {
|
||||
metadata {
|
||||
name = "nfs-adguard"
|
||||
}
|
||||
storage_provisioner = "local"
|
||||
reclaim_policy = "Retain"
|
||||
allow_volume_expansion = true
|
||||
volume_binding_mode = "Immediate"
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "adguard_ns" {
|
||||
metadata {
|
||||
name = "adguard"
|
||||
labels = {
|
||||
app = "adguard"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_ingress" "adguard_ingress" {
|
||||
metadata {
|
||||
name = "traefik-adguard"
|
||||
annotations = {
|
||||
"kubernetes.io/ingress.class" : "traefik"
|
||||
}
|
||||
namespace = kubernetes_namespace.adguard_ns.metadata.0.name
|
||||
}
|
||||
|
||||
spec {
|
||||
rule {
|
||||
host = "adguard.local"
|
||||
http {
|
||||
path {
|
||||
path = "/"
|
||||
backend {
|
||||
service_name = kubernetes_service.adguard_svc.metadata.0.name
|
||||
service_port = "adguard-http"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "adguard_svc" {
|
||||
depends_on = [kubernetes_config_map.metallb_cfg_map]
|
||||
metadata {
|
||||
namespace = kubernetes_namespace.adguard_ns.metadata.0.name
|
||||
name = "adguard-fwd"
|
||||
annotations = {
|
||||
"metallb.universe.tf/address-pool" : "default"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
port {
|
||||
name = "adguard-dns-tcp"
|
||||
port = 53
|
||||
target_port = 53
|
||||
}
|
||||
port {
|
||||
name = "adguard-dns-tls"
|
||||
port = 853
|
||||
target_port = 853
|
||||
}
|
||||
port {
|
||||
name = "adguard-http"
|
||||
port = 8080
|
||||
target_port = 8080
|
||||
}
|
||||
port {
|
||||
name = "adguard-init"
|
||||
port = 3000
|
||||
target_port = 3000
|
||||
}
|
||||
load_balancer_ip = "${var.network_subnet}.${var.adguard_catchall_host}"
|
||||
selector = {
|
||||
"app" : "adguard"
|
||||
}
|
||||
session_affinity = "ClientIP"
|
||||
type = "LoadBalancer"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "adguard_udp_svc" {
|
||||
depends_on = [kubernetes_config_map.metallb_cfg_map]
|
||||
metadata {
|
||||
namespace = kubernetes_namespace.adguard_ns.metadata.0.name
|
||||
name = "adguard-fwd-udp"
|
||||
annotations = {
|
||||
"metallb.universe.tf/address-pool" : "default"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
port {
|
||||
name = "adguard-dns-udp"
|
||||
port = 53
|
||||
target_port = 53
|
||||
protocol = "UDP"
|
||||
}
|
||||
load_balancer_ip = "${var.network_subnet}.${var.adguard_host}"
|
||||
selector = {
|
||||
"app" : "adguard"
|
||||
}
|
||||
type = "LoadBalancer"
|
||||
session_affinity = "ClientIP"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_persistent_volume" "adguard_shared_nfs" {
|
||||
metadata {
|
||||
name = "adguard-pv"
|
||||
labels = {
|
||||
name = "type"
|
||||
value = "local"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
capacity = {
|
||||
storage = "2Gi"
|
||||
}
|
||||
storage_class_name = kubernetes_storage_class.adguard_nfs.metadata.0.name
|
||||
access_modes = ["ReadWriteMany"]
|
||||
persistent_volume_source {
|
||||
host_path {
|
||||
path = var.nfs_adguard_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_persistent_volume_claim" "adguard_shared_nfs_claim" {
|
||||
metadata {
|
||||
name = "adguard-pvc"
|
||||
namespace = kubernetes_namespace.adguard_ns.metadata.0.name
|
||||
}
|
||||
spec {
|
||||
storage_class_name = kubernetes_storage_class.adguard_nfs.metadata.0.name
|
||||
access_modes = ["ReadWriteMany"]
|
||||
resources {
|
||||
requests = {
|
||||
storage = "2Gi"
|
||||
}
|
||||
}
|
||||
volume_name = kubernetes_persistent_volume.adguard_shared_nfs.metadata.0.name
|
||||
}
|
||||
}
|
||||
|
||||
## adguard deployment
|
||||
|
||||
resource "kubernetes_deployment" "adguard" {
|
||||
depends_on = [kubernetes_persistent_volume_claim.adguard_shared_nfs_claim]
|
||||
metadata {
|
||||
name = "adguard"
|
||||
labels = {
|
||||
app = "adguard"
|
||||
}
|
||||
namespace = kubernetes_namespace.adguard_ns.metadata.0.name
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "adguard"
|
||||
}
|
||||
}
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "adguard"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
volume {
|
||||
name = "adguard-v-nfs"
|
||||
persistent_volume_claim {
|
||||
claim_name = kubernetes_persistent_volume_claim.adguard_shared_nfs_claim.metadata.0.name
|
||||
}
|
||||
}
|
||||
container {
|
||||
name = "adguard"
|
||||
image = "adguard/adguardhome:arm64-edge"
|
||||
port {
|
||||
container_port = 53
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 53
|
||||
protocol = "UDP"
|
||||
}
|
||||
port {
|
||||
container_port = 853
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 3000
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 8080
|
||||
protocol = "TCP"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/opt/adguardhome/work"
|
||||
sub_path = "work-k8s"
|
||||
name = "adguard-v-nfs"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/opt/adguardhome/conf"
|
||||
sub_path = "conf-k8s"
|
||||
name = "adguard-v-nfs"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "null_resource" "adguard_crd" {
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = create
|
||||
command = "kubectl apply -f ./static/crd-adguard-traefik-udp-53.yaml"
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = destroy
|
||||
command = "kubectl delete -f ./static/crd-adguard-traefik-udp-53.yaml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
## Install metrics server
|
||||
module "dashboard_metrics" {
|
||||
depends_on = [kubernetes_service.traefik_svc]
|
||||
source = "./modules/dashboard-metrics"
|
||||
}
|
||||
|
||||
## Install dashboard
|
||||
resource "helm_release" "k8s_dashboard" {
|
||||
name = "k8s-dashboard"
|
||||
namespace = "default"
|
||||
repository = "https://kubernetes.github.io/dashboard/"
|
||||
chart = "kubernetes-dashboard"
|
||||
|
||||
set {
|
||||
name = "protocolHttp"
|
||||
value = "true"
|
||||
}
|
||||
set {
|
||||
name = "ingress.enabled"
|
||||
value = "false"
|
||||
}
|
||||
set {
|
||||
name = "rbac.create"
|
||||
value = "true"
|
||||
}
|
||||
set {
|
||||
name = "serviceAccount.create"
|
||||
value = "true"
|
||||
}
|
||||
set {
|
||||
name = "service.externalPort"
|
||||
value = "1337"
|
||||
}
|
||||
set {
|
||||
name = "networkPolicy.enabled"
|
||||
value = "true"
|
||||
}
|
||||
set {
|
||||
name = "podLabels.app"
|
||||
value = "k8s-dashboard"
|
||||
}
|
||||
set {
|
||||
name = "metrics-server.enabled"
|
||||
value = "false"
|
||||
}
|
||||
set {
|
||||
name = "metricsScraper.enabled"
|
||||
value = "true"
|
||||
}
|
||||
set {
|
||||
name = "metricsScraper.image.repository"
|
||||
value = "kubernetesui/metrics-scraper-arm"
|
||||
}
|
||||
set {
|
||||
name = "metricsScraper.image.tag"
|
||||
value = "latest"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_cluster_role_binding" "k8s_dashboard_role" {
|
||||
metadata {
|
||||
name = "kubernetes-dashboard"
|
||||
}
|
||||
role_ref {
|
||||
api_group = "rbac.authorization.k8s.io"
|
||||
kind = "ClusterRole"
|
||||
name = "cluster-admin"
|
||||
}
|
||||
subject {
|
||||
kind = "ServiceAccount"
|
||||
name = "k8s-dashboard-kubernetes-dashboard"
|
||||
namespace = "default"
|
||||
}
|
||||
}
|
||||
|
||||
# Commented out as traffic runs via traefik anyway.
|
||||
|
||||
# resource "kubernetes_service" "k8s_dashboard_svc" {
|
||||
# depends_on = [ kubernetes_config_map.metallb_cfg_map ]
|
||||
# metadata {
|
||||
# namespace = "default"
|
||||
# name = "dashboard"
|
||||
# annotations = {
|
||||
# "metallb.universe.tf/address-pool": "default"
|
||||
# }
|
||||
# }
|
||||
# spec {
|
||||
# port {
|
||||
# port = 80
|
||||
# target_port = 9090
|
||||
# }
|
||||
# load_balancer_ip = "192.168.50.200"
|
||||
# selector = {
|
||||
# "app.kubernetes.io/instance": "k8s-dashboard"
|
||||
# }
|
||||
# type = "LoadBalancer"
|
||||
# }
|
||||
# }
|
||||
|
||||
resource "kubernetes_ingress" "traefik_dashboard_routing" {
|
||||
metadata {
|
||||
name = "traefik-k8s-dashboard"
|
||||
annotations = {
|
||||
"kubernetes.io/ingress.class" : "traefik"
|
||||
}
|
||||
namespace = "default"
|
||||
}
|
||||
|
||||
spec {
|
||||
rule {
|
||||
host = "k8s.local"
|
||||
http {
|
||||
path {
|
||||
path = "/"
|
||||
backend {
|
||||
service_name = "k8s-dashboard-kubernetes-dashboard"
|
||||
service_port = 1337
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
provider "kubernetes" {
|
||||
config_path = "~/.kube/config"
|
||||
config_context = "home-k8s"
|
||||
}
|
||||
|
||||
provider "helm" {
|
||||
kubernetes {
|
||||
config_path = "~/.kube/config"
|
||||
config_context = "home-k8s"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
|
||||
|
||||
resource "null_resource" "metrics_server" {
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = create
|
||||
command = "kubectl apply -f ./static/metrics-server.yaml"
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = destroy
|
||||
command = "kubectl delete -f ./static/metrics-server.yaml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
# kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
|
||||
|
||||
resource "null_resource" "flannel_networking" {
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = create
|
||||
command = "kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml"
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = destroy
|
||||
command = "kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
resource "null_resource" "metallb_networking" {
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = create
|
||||
command = "kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/main/manifests/metallb.yaml; kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e \"s/strictARP: false/strictARP: true/\" | kubectl apply -f - -n kube-system"
|
||||
}
|
||||
|
||||
provisioner "local-exec" {
|
||||
when = destroy
|
||||
command = "kubectl delete -f https://raw.githubusercontent.com/metallb/metallb/main/manifests/metallb.yaml"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
# Basic networking
|
||||
|
||||
module "networking_flannel" {
|
||||
source = "./modules/networking-flannel"
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "metallb_system" {
|
||||
metadata {
|
||||
name = "metallb-system"
|
||||
labels = {
|
||||
app = "metallb"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module "networking_metallb" {
|
||||
depends_on = [kubernetes_namespace.metallb_system]
|
||||
source = "./modules/networking-metallb"
|
||||
}
|
||||
|
||||
resource "random_string" "metallb_secret_string" {
|
||||
length = 128
|
||||
special = false
|
||||
}
|
||||
|
||||
resource "kubernetes_secret" "metallb_secret" {
|
||||
type = "generic"
|
||||
metadata {
|
||||
name = "memberlist"
|
||||
namespace = "metallb-system"
|
||||
}
|
||||
data = {
|
||||
secretkey = base64encode(random_string.metallb_secret_string.result)
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "metallb_cfg_map" {
|
||||
metadata {
|
||||
name = "config"
|
||||
namespace = "metallb-system"
|
||||
}
|
||||
|
||||
data = {
|
||||
config = <<CFGMAP
|
||||
address-pools:
|
||||
- name: default
|
||||
protocol: layer2
|
||||
addresses:
|
||||
- ${var.network_subnet}.200-${var.network_subnet}.250
|
||||
CFGMAP
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
# resource "null_resource" "prometheus_pv" {
|
||||
|
||||
# provisioner "local-exec" {
|
||||
# when = create
|
||||
# command = "kubectl apply -f static/prometheus-pv.yaml"
|
||||
# }
|
||||
|
||||
# provisioner "local-exec" {
|
||||
# when = destroy
|
||||
# command = "kubectl delete -f static/prometheus-pv.yaml"
|
||||
# }
|
||||
# }
|
||||
|
||||
resource "helm_release" "prometheus" {
|
||||
# depends_on = [ null_resource.prometheus_pv ]
|
||||
name = "prometheus"
|
||||
namespace = "default"
|
||||
chart = "kube-prometheus-stack"
|
||||
repository = "https://prometheus-community.github.io/helm-charts"
|
||||
wait = false
|
||||
# set {
|
||||
# name = "kube-state-metrics.image.repository"
|
||||
# value = "carlosedp/kube-state-metrics"
|
||||
# }
|
||||
|
||||
# set {
|
||||
# name = "kube-state-metrics.image.tag"
|
||||
# value = "v1.9.6"
|
||||
# }
|
||||
}
|
||||
|
||||
resource "null_resource" "prometheus_patch" {
|
||||
depends_on = [helm_release.prometheus]
|
||||
provisioner "local-exec" {
|
||||
when = create
|
||||
command = <<EOF
|
||||
kubectl patch ds prometheus-prometheus-node-exporter --type json -p '[{"op": "remove", "path" : "/spec/template/spec/containers/0/volumeMounts/2/mountPropagation"}]' || true
|
||||
EOF
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_ingress" "traefik_grafana_routing" {
|
||||
metadata {
|
||||
name = "traefik-k8s-grafana"
|
||||
annotations = {
|
||||
"kubernetes.io/ingress.class" : "traefik"
|
||||
}
|
||||
namespace = "default"
|
||||
}
|
||||
|
||||
spec {
|
||||
rule {
|
||||
host = "grafana.local"
|
||||
http {
|
||||
path {
|
||||
path = "/"
|
||||
backend {
|
||||
service_name = "prometheus-grafana"
|
||||
service_port = 80
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRouteUDP
|
||||
metadata:
|
||||
name: adguard-traefik-udp
|
||||
namespace: adguard
|
||||
|
||||
spec:
|
||||
entryPoints:
|
||||
- dnsentry
|
||||
routes:
|
||||
- match: HostSNI(`*`)
|
||||
services:
|
||||
- name: adguard-fwd-udp
|
||||
port: 53
|
||||
protocol: "UDP"
|
||||
@@ -0,0 +1,188 @@
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: metrics-server
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
rbac.authorization.k8s.io/aggregate-to-admin: "true"
|
||||
rbac.authorization.k8s.io/aggregate-to-edit: "true"
|
||||
rbac.authorization.k8s.io/aggregate-to-view: "true"
|
||||
name: system:aggregated-metrics-reader
|
||||
rules:
|
||||
- apiGroups:
|
||||
- metrics.k8s.io
|
||||
resources:
|
||||
- pods
|
||||
- nodes
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: system:metrics-server
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- pods
|
||||
- nodes
|
||||
- nodes/stats
|
||||
- namespaces
|
||||
- configmaps
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: metrics-server-auth-reader
|
||||
namespace: kube-system
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: extension-apiserver-authentication-reader
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: metrics-server
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: metrics-server:system:auth-delegator
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:auth-delegator
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: metrics-server
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: system:metrics-server
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: system:metrics-server
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: metrics-server
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: metrics-server
|
||||
namespace: kube-system
|
||||
spec:
|
||||
ports:
|
||||
- name: https
|
||||
port: 443
|
||||
protocol: TCP
|
||||
targetPort: https
|
||||
selector:
|
||||
k8s-app: metrics-server
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: metrics-server
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: metrics-server
|
||||
strategy:
|
||||
rollingUpdate:
|
||||
maxUnavailable: 0
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
spec:
|
||||
containers:
|
||||
- args:
|
||||
- --cert-dir=/tmp
|
||||
- --secure-port=4443
|
||||
- --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
|
||||
- --kubelet-use-node-status-port
|
||||
- --kubelet-insecure-tls
|
||||
- --authorization-always-allow-paths=/livez,/readyz
|
||||
image: k8s.gcr.io/metrics-server/metrics-server:v0.4.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /livez
|
||||
port: https
|
||||
scheme: HTTPS
|
||||
periodSeconds: 10
|
||||
name: metrics-server
|
||||
ports:
|
||||
- containerPort: 4443
|
||||
name: https
|
||||
protocol: TCP
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /readyz
|
||||
port: https
|
||||
scheme: HTTPS
|
||||
periodSeconds: 10
|
||||
securityContext:
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
volumeMounts:
|
||||
- mountPath: /tmp
|
||||
name: tmp-dir
|
||||
nodeSelector:
|
||||
kubernetes.io/os: linux
|
||||
priorityClassName: system-cluster-critical
|
||||
serviceAccountName: metrics-server
|
||||
volumes:
|
||||
- emptyDir: {}
|
||||
name: tmp-dir
|
||||
---
|
||||
apiVersion: apiregistration.k8s.io/v1
|
||||
kind: APIService
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: metrics-server
|
||||
name: v1beta1.metrics.k8s.io
|
||||
spec:
|
||||
group: metrics.k8s.io
|
||||
groupPriorityMinimum: 100
|
||||
insecureSkipTLSVerify: true
|
||||
service:
|
||||
name: metrics-server
|
||||
namespace: kube-system
|
||||
version: v1beta1
|
||||
versionPriority: 100
|
||||
@@ -0,0 +1,63 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
annotations:
|
||||
finalizers:
|
||||
- kubernetes.io/pv-protection
|
||||
name: prometheus-server
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
capacity:
|
||||
storage: 8Gi
|
||||
claimRef:
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
name: prometheus-server
|
||||
namespace: monitoring
|
||||
local:
|
||||
path: /data/localstorage/prometheus-server
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- pi-worker
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: local-storage
|
||||
volumeMode: Filesystem
|
||||
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
annotations:
|
||||
finalizers:
|
||||
- kubernetes.io/pv-protection
|
||||
name: prometheus-alertmanager
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
capacity:
|
||||
storage: 2Gi
|
||||
claimRef:
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
name: prometheus-alertmanager
|
||||
namespace: monitoring
|
||||
local:
|
||||
path: /data/localstorage/prometheus-alertmanager
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- pi-worker
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: local-storage
|
||||
volumeMode: Filesystem
|
||||
@@ -0,0 +1,4 @@
|
||||
providers:
|
||||
file:
|
||||
filename: /custom-data/traefik-config.yaml
|
||||
kubernetesIngress: {}
|
||||
@@ -0,0 +1,22 @@
|
||||
# Activate Pilot integration
|
||||
pilot:
|
||||
enabled: true
|
||||
token: "${traefik_api_key_value}"
|
||||
|
||||
additionalArguments:
|
||||
# - --entryPoints.tcpentry.address=:3333/tcp
|
||||
# - --entryPoints.udpentry.address=:3333/udp
|
||||
- --entryPoints.dnsentry.address=:53/udp
|
||||
- --providers.file.filename=/custom-data/traefik-config.yaml
|
||||
- --providers.file.watch=true
|
||||
- --providers.kubernetesingress=true
|
||||
- --metrics.prometheus=true
|
||||
- --metrics.prometheus.entryPoint=metrics
|
||||
- --metrics.prometheus.addServicesLabels=true
|
||||
- --metrics.prometheus.addEntryPointsLabels=true
|
||||
- --entryPoints.metrics.address=:8082
|
||||
|
||||
volumes:
|
||||
- mountPath: /custom-data
|
||||
name: traefik-config
|
||||
type: configMap
|
||||
@@ -0,0 +1,196 @@
|
||||
resource "kubernetes_storage_class" "torrent_nfs" {
|
||||
metadata {
|
||||
name = "nfs-torrent"
|
||||
}
|
||||
storage_provisioner = "local"
|
||||
reclaim_policy = "Retain"
|
||||
allow_volume_expansion = true
|
||||
volume_binding_mode = "Immediate"
|
||||
}
|
||||
|
||||
resource "kubernetes_namespace" "torrent_ns" {
|
||||
metadata {
|
||||
name = "torrent"
|
||||
labels = {
|
||||
app = "torrent"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_ingress" "torrent_ingress" {
|
||||
metadata {
|
||||
name = "traefik-k8s"
|
||||
annotations = {
|
||||
"kubernetes.io/ingress.class" : "traefik"
|
||||
}
|
||||
namespace = kubernetes_namespace.torrent_ns.metadata.0.name
|
||||
}
|
||||
|
||||
spec {
|
||||
rule {
|
||||
host = "torrent.local"
|
||||
http {
|
||||
path {
|
||||
path = "/"
|
||||
backend {
|
||||
service_name = kubernetes_service.torrent_svc.metadata.0.name
|
||||
service_port = 3000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "torrent_svc" {
|
||||
depends_on = [kubernetes_config_map.metallb_cfg_map]
|
||||
metadata {
|
||||
namespace = kubernetes_namespace.torrent_ns.metadata.0.name
|
||||
name = "torrent-fwd"
|
||||
annotations = {
|
||||
"metallb.universe.tf/address-pool" : "default"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
port {
|
||||
name = "torrent-rpc"
|
||||
port = 5000
|
||||
target_port = 5000
|
||||
}
|
||||
port {
|
||||
name = "torrent-tcp"
|
||||
port = 23340
|
||||
target_port = 23340
|
||||
}
|
||||
port {
|
||||
name = "torrent-http"
|
||||
port = 3000
|
||||
target_port = 3000
|
||||
}
|
||||
load_balancer_ip = "${var.network_subnet}.${var.rtorrent_rpc_host}"
|
||||
selector = {
|
||||
"app" : "torrent"
|
||||
}
|
||||
type = "LoadBalancer"
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_persistent_volume" "torrent_shared_nfs" {
|
||||
metadata {
|
||||
name = "torrent-pv"
|
||||
labels = {
|
||||
name = "type"
|
||||
value = "local"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
capacity = {
|
||||
storage = "8Ti"
|
||||
}
|
||||
storage_class_name = kubernetes_storage_class.torrent_nfs.metadata.0.name
|
||||
access_modes = ["ReadWriteMany"]
|
||||
persistent_volume_source {
|
||||
host_path {
|
||||
path = var.nfs_torrent_path
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_persistent_volume_claim" "torrent_shared_nfs_claim" {
|
||||
metadata {
|
||||
name = "torrent-pvc"
|
||||
namespace = kubernetes_namespace.torrent_ns.metadata.0.name
|
||||
}
|
||||
spec {
|
||||
storage_class_name = kubernetes_storage_class.torrent_nfs.metadata.0.name
|
||||
access_modes = ["ReadWriteMany"]
|
||||
resources {
|
||||
requests = {
|
||||
storage = "8Ti"
|
||||
}
|
||||
}
|
||||
volume_name = kubernetes_persistent_volume.torrent_shared_nfs.metadata.0.name
|
||||
}
|
||||
}
|
||||
|
||||
## rTorrent deployment
|
||||
|
||||
resource "kubernetes_deployment" "flood-torrent" {
|
||||
depends_on = [kubernetes_persistent_volume_claim.torrent_shared_nfs_claim]
|
||||
metadata {
|
||||
name = "flood-torrent"
|
||||
labels = {
|
||||
app = "torrent"
|
||||
}
|
||||
namespace = kubernetes_namespace.torrent_ns.metadata.0.name
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
selector {
|
||||
match_labels = {
|
||||
app = "torrent"
|
||||
}
|
||||
}
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
app = "torrent"
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
volume {
|
||||
name = "torrent-v-nfs"
|
||||
persistent_volume_claim {
|
||||
claim_name = kubernetes_persistent_volume_claim.torrent_shared_nfs_claim.metadata.0.name
|
||||
}
|
||||
}
|
||||
container {
|
||||
name = "flood-torrent"
|
||||
image = "ghcr.io/lukaszraczylo/flood:1.2292.7"
|
||||
env {
|
||||
name = "FLOOD_DISABLE_AUTH"
|
||||
value = "true"
|
||||
}
|
||||
args = ["--rthost", "${var.network_subnet}.${var.rtorrent_rpc_host}",
|
||||
"--rtport", "5000", "-e", "HOME=/config", "--auth", "none", "-d", "/config/flood",
|
||||
"--allowedpath", "/config",
|
||||
"--allowedpath", "/data",
|
||||
"--rtorrent", "--rtconfig", "/data/rtorrent/.rtorrent.rc"]
|
||||
port {
|
||||
container_port = 3000
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 5000
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 23340
|
||||
protocol = "TCP"
|
||||
}
|
||||
port {
|
||||
container_port = 23340
|
||||
protocol = "UDP"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/data"
|
||||
name = "torrent-v-nfs"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/mnt/storage/torrent/downloaded"
|
||||
sub_path = "downloaded"
|
||||
name = "torrent-v-nfs"
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/config"
|
||||
sub_path = "flood"
|
||||
name = "torrent-v-nfs"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
resource "helm_release" "traefik" {
|
||||
# depends_on = [ helm_release.prometheus ]
|
||||
name = "traefik"
|
||||
namespace = "default"
|
||||
chart = "traefik/traefik"
|
||||
|
||||
set {
|
||||
name = "deployment.replicas"
|
||||
value = "2"
|
||||
}
|
||||
|
||||
set {
|
||||
name = "service.spec.loadBalancerIP"
|
||||
value = "${var.network_subnet}.234"
|
||||
}
|
||||
|
||||
values = [
|
||||
templatefile("static/traefik-static-config.tmpl", { traefik_api_key_value = var.traefik_api_key })
|
||||
]
|
||||
}
|
||||
|
||||
resource "kubernetes_config_map" "traefic_cfg_map" {
|
||||
metadata {
|
||||
name = "traefik-config"
|
||||
namespace = "default"
|
||||
}
|
||||
data = {
|
||||
"traefik-config.yaml" = file("static/traefik-cfg.yaml")
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_service" "traefik_svc" {
|
||||
depends_on = [kubernetes_config_map.metallb_cfg_map, helm_release.traefik]
|
||||
metadata {
|
||||
namespace = "default"
|
||||
name = "traefik-dashboard"
|
||||
annotations = {
|
||||
"metallb.universe.tf/address-pool" : "default"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
port {
|
||||
port = 80
|
||||
target_port = 9000
|
||||
}
|
||||
selector = {
|
||||
"app.kubernetes.io/instance" : "traefik"
|
||||
}
|
||||
type = "LoadBalancer"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
variable "network_subnet" {}
|
||||
variable "rtorrent_rpc_host" {}
|
||||
variable "nfs_torrent_path" {}
|
||||
variable "nfs_adguard_path" {}
|
||||
variable "adguard_host" {}
|
||||
variable "adguard_catchall_host" {}
|
||||
variable "traefik_api_key" {}
|
||||
variable "github_user" {}
|
||||
variable "github_pat" {}
|
||||
@@ -0,0 +1,30 @@
|
||||
terraform {
|
||||
required_version = ">= 0.13"
|
||||
|
||||
required_providers {
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.0.2"
|
||||
}
|
||||
|
||||
http = {
|
||||
source = "hashicorp/http"
|
||||
version = "~> 2.1.0"
|
||||
}
|
||||
|
||||
helm = {
|
||||
source = "hashicorp/helm"
|
||||
version = "~> 2.0.3"
|
||||
}
|
||||
|
||||
null = {
|
||||
source = "hashicorp/null"
|
||||
version = "~> 3.1.0"
|
||||
}
|
||||
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "~> 3.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
# Variables used for barebone kubernetes setup
|
||||
network_subnet = "192.168.50"
|
||||
rtorrent_rpc_host = "245"
|
||||
adguard_host = "240"
|
||||
adguard_catchall_host = "249"
|
||||
|
||||
nfs_torrent_path = "/mnt/drobo-storage/docker-volumes/torrent"
|
||||
nfs_adguard_path = "/mnt/drobo-storage/docker-volumes/adguard"
|
||||
|
||||
# ENV variable: TRAEFIK_API_KEY sets traefik_api_key
|
||||
# ENV variable: GH_USER, GH_PAT for authentication with private containers
|
||||
Reference in New Issue
Block a user