Sentinel is a lightweight service that automatically updates DNS records when container orchestration leadership changes. It ensures high availability by pointing your domain to the current leader node.
- 🔄 Automatic DNS failover for Docker Swarm and Kubernetes clusters
- 🔍 Real-time monitoring of leader changes
- 🌐 DNS record updates
- 🔒 Secure and lightweight (built on scratch container)
- 🚀 Easy to deploy and configure
Sentinel runs on manager/control plane nodes in your cluster. It:
- Monitors orchestration events for leadership changes
- Updates the DNS record to point to the leader node's IP when changes occur
This project is designed for low-budget environments where virtual IPs are unavailable or when you want to avoid dependencies on third-party load balancers.
Failover time depends on your DNS record TTL, making this solution less suitable for applications requiring zero downtime.
- INWX
- Bunny DNS
Feel free to create a pull request to add more providers.
- Account for one of the supported DNS providers
- A DNS zone (
SENTINEL_DOMAIN
) - An A or AAAA record in the zone (
SENTINEL_RECORD
)
For Docker Swarm:
- Docker Swarm cluster with at least one manager node
For Kubernetes:
- Kubernetes cluster with at least one control plane node
- Create a Docker secret for the INWX password
echo "mySecurePassword123" | docker secret create inwx_password -
- Copy the docker-compose.yml file from
deployment/docker-swarm
folder and adjust it to your needs - Deploy as a stack to your Swarm cluster:
docker stack deploy -c docker-compose.yml sentinel
- Copy and adjust the files from the
deployment/kubernetes
folder. - Deploy via
kubectl apply
- Create a Kubernetes secret for the INWX credentials (optional)
kubectl create secret generic sentinel-inwx-credentials \
--namespace sentinel \
--from-literal=username="myusername" \
--from-literal=password="mySecurePassword123" \
--dry-run=client -o yaml | kubectl apply -f -
- Create a Kubernetes secret for the Bunny DNS credentials (optional)
kubectl create secret generic sentinel-bunny-credentials \
--namespace sentinel \
--from-literal=api_key="my-api-key" \
--dry-run=client -o yaml | kubectl apply -f
Environment Variable | Description | Default |
---|---|---|
SENTINEL_DOMAIN |
Domain name | example.com |
SENTINEL_RECORD |
Record name (subdomain) | lb |
SENTINEL_LOG_LEVEL |
Logging level (DEBUG, INFO, ERROR) | INFO |
SENTINEL_ORCHESTRATION |
Orchestration platform (swarm/kubernetes) | swarm |
SENTINEL_DNS_PROVIDER |
Name of DNS provider (inwx/bunny) | inwx |
SENTINEL_INWX_USER |
INWX username | required, if dns provider is inwx |
SENTINEL_INWX_PASSWORD |
INWX password | required, if dns provider is inwx |
SENTINEL_BUNNY_API_KEY |
Bunny API key | required, if dns provider is bunny |
Docker Swarm
Run the following command on each node to set the "public_ip" label:
PUBLIC_IP=$(curl -s https://api.ipify.org) \
NODE_ID=$(docker info --format '{{.Swarm.NodeID}}') ; \
docker node update --label-add public_ip=$PUBLIC_IP $NODE_ID
To verify that the label was set correctly, run:
docker node inspect $NODE_ID --format '{{ index .Spec.Labels "public_ip" }}'
Kubernetes
Without setting a label the first external IP address of the node is used.
If you want to set it to something else you can run the following command on each node to set the "public_ip" label (replace mynode
with your node name)
PUBLIC_IP=$(curl -s https://api.ipify.org) \
kubectl label nodes mynode public_ip=$PUBLIC_IP
# Copy and adjust to fit your setup
cp .env.dist .env
# Start development environment
make dev
# View logs
make dev-logs
# Start in detached mode
make dev-detach
# Clean up
make clean
# Build Docker image
make build
Sentinel is built with Go and designed to be lightweight and reliable:
- Zero dependencies: Built on scratch container
- Minimal footprint: Small binary size and memory usage
- Resilient: Automatically reconnects if Docker API connection is lost
- Secure: No shell or unnecessary components in the container
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.