diff --git a/kubernetes/apps/monitoring/gatus/app/config/config.yaml b/kubernetes/apps/monitoring/gatus/app/config/config.yaml new file mode 100644 index 000000000..dec58eacc --- /dev/null +++ b/kubernetes/apps/monitoring/gatus/app/config/config.yaml @@ -0,0 +1,37 @@ +--- +web: + port: ${CUSTOM_WEB_PORT} +storage: + type: postgres + path: postgres://${INIT_POSTGRES_USER}:${INIT_POSTGRES_PASS}@${INIT_POSTGRES_HOST}:5432/${INIT_POSTGRES_DBNAME}?sslmode=disable + caching: true +metrics: true +debug: false +ui: + title: Status | Gatus + header: Status +alerting: + pushover: + application-token: ${CUSTOM_PUSHOVER_APP_TOKEN} + user-key: ${CUSTOM_PUSHOVER_USER_KEY} + default-alert: + description: health-check failed + send-on-resolved: true + failure-threshold: 5 + success-threshold: 2 +connectivity: + checker: + target: 1.1.1.1:53 + interval: 1m +endpoints: + - name: status + group: external + url: https://status.${SECRET_CLUSTER_DOMAIN} + interval: 1m + client: + dns-resolver: tcp://1.1.1.1:53 + insecure: true + conditions: + - "[STATUS] == 200" + alerts: + - type: pushover diff --git a/kubernetes/apps/monitoring/gatus/app/helmrelease.yaml b/kubernetes/apps/monitoring/gatus/app/helmrelease.yaml new file mode 100644 index 000000000..cb2be37e1 --- /dev/null +++ b/kubernetes/apps/monitoring/gatus/app/helmrelease.yaml @@ -0,0 +1,126 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.devbu.io/helm.toolkit.fluxcd.io/helmrelease_v2beta1.json +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + name: gatus + namespace: monitoring +spec: + interval: 30m + chart: + spec: + chart: app-template + version: 1.5.1 + sourceRef: + kind: HelmRepository + name: bjw-s + namespace: flux-system + maxHistory: 2 + install: + createNamespace: true + remediation: + retries: 3 + upgrade: + cleanupOnFail: true + remediation: + retries: 3 + uninstall: + keepHistory: false + values: + initContainers: + 01-init-db: + image: ghcr.io/onedr0p/postgres-init:14.8 + imagePullPolicy: IfNotPresent + envFrom: &envFrom + - secretRef: + name: gatus-secret + 02-config-sync: + image: ghcr.io/kiwigrid/k8s-sidecar:1.24.6 + imagePullPolicy: IfNotPresent + env: + - { name: FOLDER, value: /config } + - { name: LABEL, value: gatus.io/enabled } + - { name: NAMESPACE, value: ALL } + - { name: RESOURCE, value: both } + - { name: UNIQUE_FILENAMES, value: "true" } + - { name: METHOD, value: LIST } + volumeMounts: + - { name: config, mountPath: /config } + controller: + annotations: + reloader.stakater.com/auto: "true" + image: + repository: ghcr.io/twin/gatus + tag: v5.4.0 + env: + TZ: ${TIMEZONE} + GATUS_CONFIG_PATH: /config + CUSTOM_WEB_PORT: &port 8080 + SECRET_CLUSTER_DOMAIN: ${SECRET_CLUSTER_DOMAIN} + envFrom: *envFrom + service: + main: + ports: + http: + port: *port + serviceMonitor: + main: + enabled: true + endpoints: + - port: http + scheme: http + path: /metrics + interval: 1m + scrapeTimeout: 10s + ingress: + main: + enabled: true + ingressClassName: nginx + annotations: + external-dns.home.arpa/enabled: "true" + hosts: + - host: &host "status.${SECRET_CLUSTER_DOMAIN}" + paths: + - path: / + pathType: Prefix + tls: + - hosts: + - *host + serviceAccount: + create: true + name: gatus + podSecurityContext: + runAsUser: 568 + runAsGroup: 568 + fsGroup: 568 + fsGroupChangePolicy: OnRootMismatch + persistence: + config: + enabled: true + type: emptyDir + config-file: + enabled: true + type: configMap + name: gatus-configmap + mountPath: /config/config.yaml + subPath: config.yaml + readOnly: true + resources: + requests: + cpu: 100m + memory: 100Mi + limits: + memory: 500Mi + sidecars: + config-sync: + image: ghcr.io/kiwigrid/k8s-sidecar:1.24.6 + imagePullPolicy: IfNotPresent + env: + - { name: FOLDER, value: /config } + - { name: LABEL, value: gatus.io/enabled } + - { name: NAMESPACE, value: ALL } + - { name: RESOURCE, value: both } + - { name: UNIQUE_FILENAMES, value: "true" } + - { name: METHOD, value: WATCH } + volumeMounts: + - { name: config, mountPath: /config } diff --git a/kubernetes/apps/monitoring/gatus/app/kustomization.yaml b/kubernetes/apps/monitoring/gatus/app/kustomization.yaml new file mode 100644 index 000000000..3c0ad293f --- /dev/null +++ b/kubernetes/apps/monitoring/gatus/app/kustomization.yaml @@ -0,0 +1,17 @@ +--- +# yaml-language-server: $schema=https://json.schemastore.org/kustomization +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: monitoring +resources: + - ./rbac.yaml + - ./helmrelease.yaml + - ./secret.sops.yaml +configMapGenerator: + - name: gatus-configmap + files: + - ./config/config.yaml +generatorOptions: + disableNameSuffixHash: true + annotations: + kustomize.toolkit.fluxcd.io/substitute: disabled diff --git a/kubernetes/apps/monitoring/gatus/app/rbac.yaml b/kubernetes/apps/monitoring/gatus/app/rbac.yaml new file mode 100644 index 000000000..0355e0351 --- /dev/null +++ b/kubernetes/apps/monitoring/gatus/app/rbac.yaml @@ -0,0 +1,35 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: gatus + namespace: monitoring + labels: + app.kubernetes.io/managed-by: Helm + annotations: + meta.helm.sh/release-name: gatus + meta.helm.sh/release-namespace: monitoring +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: gatus + namespace: monitoring +rules: + - apiGroups: [""] + resources: ["configmaps", "secrets"] + verbs: ["get", "watch", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: gatus + namespace: monitoring +roleRef: + kind: ClusterRole + name: gatus + apiGroup: rbac.authorization.k8s.io +subjects: + - kind: ServiceAccount + name: gatus + namespace: monitoring diff --git a/kubernetes/apps/monitoring/gatus/app/secret.sops.yaml b/kubernetes/apps/monitoring/gatus/app/secret.sops.yaml new file mode 100644 index 000000000..c73148e80 --- /dev/null +++ b/kubernetes/apps/monitoring/gatus/app/secret.sops.yaml @@ -0,0 +1,37 @@ +# yamllint disable +apiVersion: v1 +kind: Secret +metadata: + name: gatus-secret + namespace: default +type: Opaque +stringData: + #ENC[AES256_GCM,data:4iasPQ==,iv:j84wn0onGKCdIv/VhnRkc9WUrJcKzi15PPAaccPktMI=,tag:qZSBg8M5mq0r+dwfj910LQ==,type:comment] + CUSTOM_PUSHOVER_APP_TOKEN: ENC[AES256_GCM,data:ojqz+I3cIQraQ8b1d79R5UCOyJ9fw6WUKP8QaclG,iv:Vh85QNkt2f9N2G4lE25EuXfFbswUp9LOdPGGFhU/j4I=,tag:m0DXN5UNUSQvH3SG5BXphw==,type:str] + CUSTOM_PUSHOVER_USER_KEY: ENC[AES256_GCM,data:3Ses6r1zh2AK9GjM/RAnt4fuzX86T55gpKP4Bfh2,iv:jTeHDvE35nRE8eNYR0kORPKpdFSuGB0MbhUr6oM38Go=,tag:Km2OBE/6oFCK3Flvl8X5Wg==,type:str] + #ENC[AES256_GCM,data:SkRXz/l1EiEl5Ywk9ro=,iv:rFH21ODFH5qmPQQfutNenDgc3gGFZpkY1fa9SC95ZXU=,tag:6/LbsWB4bsaoTyS9Mvbzog==,type:comment] + INIT_POSTGRES_DBNAME: ENC[AES256_GCM,data:N+UhTeY=,iv:TtHF6zRpl+vYKJDy6aPgLuo+laVQoYdnq2th+0T3Ok0=,tag:EOT48yIZyqjoQzPVVv111A==,type:str] + INIT_POSTGRES_HOST: ENC[AES256_GCM,data:lcvnmK3SIsfTtZV9ootfzd/RMRo1sNLQ8qAkYpVFgwjHzDKMaA==,iv:YVr19WtibsOb33WiKnGSJF7DXyoAJ5F8etk7DtqDSqU=,tag:njOVD5yFmjCFezTlGQdE5A==,type:str] + INIT_POSTGRES_USER: ENC[AES256_GCM,data:NfdJfi4=,iv:4P95EsR9n4nD+nJVqXsavjoJasmdQURMHll9TAzDZiI=,tag:dTPUyxMe/qRKr+8lnpebwQ==,type:str] + INIT_POSTGRES_PASS: ENC[AES256_GCM,data:hnRc8W9HOO/n9nj+6jsGwgbTUjo=,iv:9NX9kB1zlJ4UaQ5FLpk6z9Kuit6jGaBCvgNAS6xwz70=,tag:B9Ue9UiOosM2egzSYhWC8w==,type:str] + INIT_POSTGRES_SUPER_PASS: ENC[AES256_GCM,data:naR9T7rV1zZcJ42UQesZrQ==,iv:l6UUSCWvQGRgVzM5B/W9YCqVG7v0U63BDp3ANJi2Bu0=,tag:KRRbDtBOKJJg3wQAPwlOrQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1hhurqwmfvl9m3vh3hk8urulfzcdsrep2ax2neazqt435yhpamu3qj20asg + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJaU16anJNV2pBZmxPR3h2 + bWREUnpjcTFvd05ZQ2E4VVBDdm1FL2k4WEYwCkdQSStTNWtpdjNkUW51WS9MekdC + VkpTUUFjSjY2a1JMOUtqOVh5M0JRR2sKLS0tIDRmcWpJSEVvaUp4U1lsaTZYZGNw + OGVKWU0zNUZJSFh4aFJxQWFsYm1VeFkKaDeI/hl7z0Qh8t5W39Kxu9ert1dt4xo+ + LX+MjpVqxiZNcfwROD4bkWeQSN+VsxoGOOyj4L15BlggNnlg+L7Hww== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2023-07-08T06:43:48Z" + mac: ENC[AES256_GCM,data:OAz4DxyejtZsew6tL3F8AOIsfXOJFSgtMLzRzPv7Yure9GG4hEq+pj432HC48R/o4hQw7cNicxbHPAoSJIPtjqlNZsRStnGuPE2WBfeTaHS0XZsCesKbxW8VJ4vChbB1kp9gDV05JKETsUXAFnmSchiU6SGTvxgHepjbjYodxLk=,iv:iVcKX4O2qBKBU/UVVHsufBfD9iGUbfjFgkfDCjqN0d0=,tag:ENxJhJBvRdtcpjZjWoKXGQ==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.7.3 diff --git a/kubernetes/apps/monitoring/gatus/ks.yaml b/kubernetes/apps/monitoring/gatus/ks.yaml new file mode 100644 index 000000000..01ceded41 --- /dev/null +++ b/kubernetes/apps/monitoring/gatus/ks.yaml @@ -0,0 +1,21 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.devbu.io/kustomize.toolkit.fluxcd.io/kustomization_v1.json +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: cluster-apps-gatus + namespace: flux-system + labels: + substitution.flux.home.arpa/enabled: "true" +spec: + dependsOn: + - name: cluster-apps-cloudnative-pg-cluster + path: ./kubernetes/apps/monitoring/gatus/app + prune: true + sourceRef: + kind: GitRepository + name: home-ops-kubernetes + wait: false # no flux ks dependents + interval: 30m + retryInterval: 1m + timeout: 5m diff --git a/kubernetes/apps/monitoring/kustomization.yaml b/kubernetes/apps/monitoring/kustomization.yaml index 5d261b66b..612ed89d1 100644 --- a/kubernetes/apps/monitoring/kustomization.yaml +++ b/kubernetes/apps/monitoring/kustomization.yaml @@ -6,6 +6,7 @@ resources: # Pre Flux-Kustomizations - ./namespace.yaml # Flux-Kustomizations + - ./gatus/ks.yaml - ./grafana/ks.yaml - ./kube-prometheus-stack/ks.yaml # - ./loki/ks.yaml