Skip to content

Commit

Permalink
feat: add health probes for kubernetes
Browse files Browse the repository at this point in the history
  • Loading branch information
amille44420 committed Jan 7, 2022
1 parent 12d253c commit 8df6d7f
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 4 deletions.
11 changes: 11 additions & 0 deletions charts/app/templates/deployment-server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ spec:
{{- with .Values.app.pods.extraEnvs }}
{{- toYaml . | nindent 12 }}
{{- end }}
livenessProbe:
httpGet:
port: 3000
path: /healthChecks/live
scheme: HTTP
readinessProbe:
initialDelaySeconds: 1
httpGet:
port: 3000
path: /healthChecks/ready
scheme: HTTP
ports:
- name: http
containerPort: 3000
Expand Down
15 changes: 11 additions & 4 deletions src/server/core/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getDatabaseContext, migrate } from '../database';
import { setup as startWorker } from '../queues';
import config from './config';
import createWebServer from './createWebServer';
import { updateStatus, HealthStatus } from './health';
import { initializeSentry } from './sentry';

export const startServerCommand = async () => {
Expand All @@ -11,13 +12,19 @@ export const startServerCommand = async () => {
initializeSentry({ app: expressServer });

httpServer.listen(config.port, () => {
updateStatus(HealthStatus.Running);
console.info(chalk.cyan('Server listening'));
});

return () =>
new Promise(resolve => {
httpServer.close(resolve);
});
return () => {
updateStatus(HealthStatus.Stopping);

return new Promise(resolve => {
setTimeout(() => {
httpServer.close(resolve);
}, 10000);
}).then(() => updateStatus(HealthStatus.Stopped));
};
};

export const startWorkerCommand = () => {
Expand Down
4 changes: 4 additions & 0 deletions src/server/core/createWebServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SubscriptionServer } from 'subscriptions-transport-ws';
import schema from '../schema';
import createContext, { Context, RootDocument } from '../schema/context';
import config from './config';
import { createHealthRouter } from './health';
import setupPrometheusMetrics, { ApolloMetricsPlugin } from './prometheus';
import { expressRateLimiter } from './rateLimiter';
import renderApplication from './renderApplication';
Expand Down Expand Up @@ -125,6 +126,9 @@ const createWebServer = async (): Promise<WebServerCreation> => {
// update cache policy
expressServer.use(disableCaching);

// health endpoints
expressServer.use('/healthChecks', createHealthRouter());

// serve graphql API
expressServer.use(
'/graphql',
Expand Down
65 changes: 65 additions & 0 deletions src/server/core/health.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Router } from 'express';

export enum HealthStatus {
Starting,
Running,
Stopping,
Stopped,
}

let currentStatus = HealthStatus.Starting;

const statusLabels = new Map<number, string>([
[HealthStatus.Starting, 'Starting'],
[HealthStatus.Running, 'Up'],
[HealthStatus.Stopped, 'Stopped'],
[HealthStatus.Stopping, 'Stopping'],
]);

export const createHealthRouter = () => {
// @ts-ignore
const router = new Router();

router.get('/ready', (req, res) => {
switch (currentStatus) {
case HealthStatus.Running:
res.status(200).send(statusLabels[HealthStatus.Running]);
break;

default:
res.status(503).send(statusLabels[currentStatus]);
break;
}
});

router.get('/live', (req, res) => {
switch (currentStatus) {
case HealthStatus.Starting:
case HealthStatus.Running:
res.status(200).send(statusLabels[currentStatus]);
break;

default:
res.status(503).send(statusLabels[currentStatus]);
break;
}
});

router.get('/health', (req, res) => {
switch (currentStatus) {
case HealthStatus.Running:
res.status(200).send(statusLabels[HealthStatus.Running]);
break;

default:
res.status(503).send(statusLabels[currentStatus]);
break;
}
});

return router;
};

export const updateStatus = (nextStatus: HealthStatus) => {
currentStatus = nextStatus;
};

0 comments on commit 8df6d7f

Please sign in to comment.