Gatus is a health dashboard that gives you the ability to monitor your services using HTTP, ICMP, TCP, and even DNS queries as well as evaluate the result of said queries by using a list of conditions on values like the status code, the response time, the certificate expiration, the body and many others. The icing on top is that each of these health checks can be paired with alerting via Slack, PagerDuty, Discord, Twilio and more.
In this guide, we will configure Gatus as a health dashboard tool using Kubernetes.
Checkout How to install and configure Gatus for health check monitoring Using Docker Compose.
# Prerequisites
- You have a cluster running with access to create resources
- You have kubectl installed locally
I assume that you have a kubernetes cluster up and running with kubectl setup on your workstation. If not please checkout these guides:
- How to set up Kubernetes Cluster on Ubuntu 20.04 with kubeadm and CRI-O
- How to set up Kubernetes Cluster on Debian 11 with kubeadm and CRI-O
- How to Setup a Kubernetes Cluster with K3S in Rocky Linux 8
- How to use Terraform to create a vpc network and a GKE in GCP
- How to Set up Prometheus Node exporter in Kubernetes
Latest Gatus is available as a docker image in its official docker hub account. We will use that image for the setup.
# Setting up Kubernetes Manifests
Once you have the prerequisites in place, we can create kubernetes resource manifests.
# Namespace
In Kubernetes, a namespace provides a mechanism for isolating groups of resources within a single cluster. Names of resources need to be unique within a namespace, but not across namespaces. Namespace-based scoping is applicable only for namespaced objects (e.g. Deployments, Services, etc) and not for cluster-wide objects (e.g. StorageClass, Nodes, PersistentVolumes, etc).
Let us create a namespace for our gatus resources. Save the following in namespace.yaml
:
---
apiVersion: v1
kind: Namespace
metadata:
name: gatus
Then execute the following command to create a new namespace named gatus.
kubectl apply -f namespace.yaml
# Create a Config Map To Externalize Gatus Configurations
All configurations for Gatus are part ofconfig.yaml
file that defines the endpoints to be monitored and the alert channels. This config file will be specified when starting the application.
A ConfigMap is an API object used to store non-confidential data in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or as configuration files in a volume. We sill specify our configfile map as a configmap and pass to the deployment as a configuration file in volume.
Create a file called config-map.yaml
and add the following file contents:
apiVersion: v1
kind: ConfigMap
metadata:
labels:
app.kubernetes.io/instance: gatus
app.kubernetes.io/name: gatus
name: gatus-config
data:
config.yaml: |-
alerting:
slack:
webhook-url: "https://hooks.slack.com/services/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"
default-alert:
enabled: true
description: "Health check failed"
send-on-resolved: true
failure-threshold: 3
success-threshold: 2
endpoints:
- name: Application One
url: https://app-one.citizix.co/healthz
interval: 30s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 1000"
alerts:
- type: slack
failure-threshold: 3
success-threshold: 2
- name: Application Two
url: https://app-two.citizix.co/healthz
interval: 30s
conditions:
- "[STATUS] == 200"
- "[RESPONSE_TIME] < 1000"
alerts:
- type: slack
failure-threshold: 3
success-threshold: 2
storage:
type: postgres
path: "postgres://user:password@db0.dbs.com:5432/gatus?sslmode=disable"
In the above defined configurations, we are defining slack webhook for alert notifications when thresholds defined trigger an error. We are also defining two endpoints for app one and app two. Finally we are persisting the data in postgres.
Execute the following command to create the config map in Kubernetes.
kubectl create -f config-map.yaml
# Create a Gatus Deployment
A Deployment provides declarative updates for Pods and ReplicaSets. You describe a desired state in a Deployment, and the Deployment Controller changes the actual state to the desired state at a controlled rate. You can define Deployments to create new ReplicaSets, or to remove existing Deployments and adopt all their resources with new Deployments.
In our case, we will use the docker-hub provided image and mounting the predefined configmap as a volume mounted in /config
.
Save the following content to deployment.yaml
.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: gatus
labels:
app: gatus
spec:
replicas: 1
selector:
matchLabels:
app: gatus
template:
metadata:
labels:
app: gatus
spec:
containers:
- name: gatus
image: twinproduction/gatus:latest
ports:
- containerPort: 8080
name: http
protocol: TCP
volumeMounts:
- name: gatus-config
mountPath: /config
volumes:
- name: gatus-config
configMap:
defaultMode: 420
name: gatus-config
Create a deployment on monitoring namespace using the above file.
kubectl create -f deployment.yaml
You can check the created deployment using the following command.
kubectl get deployments --namespace=gatus
kubectl get pods --namespace=gatus
# Connecting To Gatus Dashboard
You can view the deployed Gatus dashboard in three different ways.
- Using Kubectl port forwarding
- Exposing the Gatus deployment as a service with NodePort or a Load Balancer.
- Adding an Ingress object if you have an Ingress controller deployed.
# Using Kubectl port forwarding
Using kubectl port forwarding, you can access a pod from your local workstation using a selected port on your localhost
. This method is primarily used for debugging purposes.
First, get the Gatus pod name.
kubectl get pods --namespace=gatus
The output will look like the following.
➜ kubectl get pods --namespace=gatus NAME READY STATUS RESTARTS AGE gatus-b8895b7b-bpmfn 1/1 Running 0 30m
Execute the following command with your pod name to access Gatus from localhost port 8080.
Note: Replace gatus-b8895b7b-bpmfn with your pod name.
kubectl port-forward gatus-b8895b7b-bpmfn 8080:8080 -n gatus
Now, if you access http://localhost:8080
on your browser, you will get the Gatus home page.
# Exposing Gatus as a Service [NodePort & LoadBalancer]
To access the Gatus dashboard over a IP
or a DNS
name, you need to expose it as a Kubernetes service.
Create a file namedservice.yaml
and copy the following contents. We will expose Gatus on all kubernetes node IP’s on port 40000
.
Note: If you are on AWS, Azure, or Google Cloud, You can use Loadbalancer type, which will create a load balancer and automatically points it to the Kubernetes service endpoint.
--- apiVersion: v1 kind: Service metadata: name: gatus labels: app: gatus namespace: gatus spec: selector: app: gatus type: NodePort ports: - name: gatus protocol: TCP port: 8080 targetPort: http nodePort: 40000
Create the service using the following command.
kubectl create -f service.yaml --namespace=gatus
Once created, you can access the Gatus dashboard using any of the Kubernetes nodes IP on port 40000
. If you are on the cloud, make sure you have the right firewall rules to access port 40000
from your workstation.
# Exposing Gatus Using Ingress
If you have an existing ingress controller setup, you can create an ingress object to route the Gatus DNS to the Gatus backend service.
Also, you can add SSL for Gatus in the ingress layer. You can refer to the Kubernetes ingress TLS/SSL Certificate guide for more details.
Here is a sample ingress object.
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx labels: app.kubernetes.io/instance: gatus app.kubernetes.io/name: gatus name: gatus namespace: gatus spec: rules: - host: gatus.citizix.com http: paths: - backend: service: name: gatus port: number: 8080 path: / pathType: ImplementationSpecific
# Using Kustomize
Kustomize introduces a template-free way to customize application configuration that simplifies the use of off-the-shelf applications. Now, built into kubectl
as apply -k
.
In our case, to avoid multiple kubectl apply -f <filename>
we can use kustomize to define all the resources then apply as one. Save the following as kustomization.yaml
.
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: gatus
resources:
- namespace.yaml
- configmap.yaml
- deployment.yaml
- service.yaml
- ingress.yaml
Then apply using this command:
➜ kubectl apply -k .
namespace/gatus unchanged
configmap/gatus-config unchanged
service/gatus unchanged
deployment.apps/gatus unchanged
ingress.networking.k8s.io/gatus unchanged
# Conclusion
In this article, we learnt how to set up Gatus on Kubernetes.