Skip to content

Commit 18e2498

Browse files
committed
feat(healthchecks): add DB health check to /healthz
On boot see if the DB is connectable *before* hitting the migration step and in /healthz connect to the DB and run a simple dumb SELECT statement Note that this will cause k8s to restart the container after a few tries, if the DB is not available then it will go into a crash loop. This is the nature of the beast: http://kubernetes.io/v1.1/docs/user-guide/production-pods.html#liveness-and-readiness-probes-aka-health-checks and http://kubernetes.io/v1.1/docs/user-guide/walkthrough/k8s201.html#health-checking 'if the Kubelet discovers a failure the container is restarted.' To test deploy deis-workflow RC and then scale deis-database to 0 We will have more control over this when #251 lands Fixes #305
1 parent 3dd0e57 commit 18e2498

4 files changed

Lines changed: 47 additions & 4 deletions

File tree

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ setup-venv:
8080
@if [ ! -d venv ]; then virtualenv venv; fi
8181
venv/bin/pip install --disable-pip-version-check -q -r rootfs/requirements.txt -r rootfs/dev_requirements.txt
8282

83-
test: test-style test-unit test-functional
83+
test: test-style test-check test-unit test-functional
84+
85+
test-check:
86+
cd rootfs && python manage.py check
8487

8588
test-style:
8689
cd rootfs && flake8 --show-pep8 --show-source
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from django.core.management.base import BaseCommand
2+
from django.conf import settings
3+
import django.db
4+
import sys
5+
6+
7+
class Command(BaseCommand):
8+
"""Management command for healthchecks"""
9+
def handle(self, *args, **options):
10+
"""Ensure DB and other things are alive"""
11+
print("Checking if database is alive")
12+
try:
13+
django.db.connection.cursor()
14+
print("Database is alive!")
15+
except Exception as e:
16+
print("There was a problem connecting to the database")
17+
if settings.DEBUG:
18+
print(str(e))
19+
20+
sys.exit(1)

rootfs/api/views.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,31 @@
1919
from api import authentication, models, permissions, serializers, viewsets
2020

2121
import requests
22+
import logging
23+
24+
logger = logging.getLogger(__name__)
2225

2326

2427
class HealthCheckView(View):
25-
"""Simple health check view to determine if the server
26-
is responding to HTTP requests.
28+
"""
29+
Simple health check view to determine if the server
30+
is responding to HTTP requests and DB connection / query.
2731
"""
2832

2933
def get(self, request):
34+
try:
35+
import django.db
36+
with django.db.connection.cursor() as c:
37+
c.execute("SELECT 0")
38+
except django.db.Error as e:
39+
logger.critical("Database health check failed")
40+
logger.debug(str(e))
41+
42+
return HttpResponse(
43+
"Database health check failed",
44+
status=status.HTTP_503_SERVICE_UNAVAILABLE
45+
)
46+
3047
return HttpResponse("OK")
3148
head = get
3249

rootfs/bin/boot

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@ else
7777
addgroup deis "$(stat -c "%G" /var/run/docker.sock)"
7878
fi
7979

80-
# run an idempotent database migration
80+
echo "Health Checks:"
81+
./manage.py healthchecks
82+
83+
echo "Database Migrations:"
8184
sudo -E -u deis ./manage.py migrate --noinput
8285

8386
# spawn a gunicorn server in the background

0 commit comments

Comments
 (0)