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.
- 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.
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
--- 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 of
config.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:[email protected]: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
Save the following content to
--- 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 named
service.yaml and copy the following contents. We will expose Gatus on all kubernetes node IP’s on port
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
Kustomize introduces a template-free way to customize application configuration that simplifies the use of off-the-shelf applications. Now, built into
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
--- 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
In this article, we learnt how to set up Gatus on Kubernetes.