-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add customizeable liveness/readiness/startup probe endpoints (#1363)
* add customizeable liveness/readiness/startup probe endpoints * package updates * typofix * typofix * use startupProbe * restore apollo-health endpoint * restore apollo-health endpoint * cleanup
- Loading branch information
Showing
19 changed files
with
1,251 additions
and
939 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/** | ||
* Copyright 2024 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const PROBE_DEFAULT_IMPL = require( './probe-default.js' ); | ||
const PROBE_CUSTOM_IMPL = require( process.env.PROBE_IMPL || './probe-none.js' ); | ||
|
||
/* | ||
Return an impl for each of the probe types: | ||
Get the default probe payload. | ||
If default probe impl throws an error, throw an error. | ||
If module specified by PROBE_IMPL implements a probe, get the custom probe payload. | ||
If custom probe impl throws an error, throw an error. | ||
Return the custom payload, or the default payload if there is none. | ||
*/ | ||
const PROBE_IMPL = { | ||
getStartupPayload: async function( context ) { | ||
const method = 'getStartupPayload'; | ||
const defaultPayload = await PROBE_DEFAULT_IMPL[method](context); | ||
if( !Object.prototype.hasOwnProperty.call(PROBE_CUSTOM_IMPL, method) ) { | ||
return( PROBE_DEFAULT_IMPL[method](context) ); | ||
} | ||
return defaultPayload; | ||
}, | ||
getReadinessPayload: async function( context ) { | ||
const method = 'getReadinessPayload'; | ||
const defaultPayload = await PROBE_DEFAULT_IMPL[method](context); | ||
if( !Object.prototype.hasOwnProperty.call(PROBE_CUSTOM_IMPL, method) ) { | ||
return( PROBE_DEFAULT_IMPL[method](context) ); | ||
} | ||
return defaultPayload; | ||
}, | ||
getLivenessPayload: async function( context ) { | ||
const method = 'getLivenessPayload'; | ||
const defaultPayload = await PROBE_DEFAULT_IMPL[method](context); | ||
if( !Object.prototype.hasOwnProperty.call(PROBE_CUSTOM_IMPL, method) ) { | ||
return( PROBE_DEFAULT_IMPL[method](context) ); | ||
} | ||
return defaultPayload; | ||
} | ||
}; | ||
|
||
module.exports = PROBE_IMPL; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/** | ||
* Copyright 2024 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
const Models = require('../../apollo/models'); | ||
const { GraphqlPubSub } = require('../../apollo/subscription'); | ||
const pubSub = GraphqlPubSub.getInstance(); | ||
const timeInterval = 300000; //5 mintues | ||
|
||
let STARTUP_COMPLETE = false; | ||
async function getStartupPayload() { | ||
if( !STARTUP_COMPLETE ) { | ||
throw new Error('startup incomplete'); | ||
} | ||
return('startup probe successful'); | ||
} | ||
|
||
async function getReadinessPayload() { | ||
return('readiness probe successful'); | ||
} | ||
|
||
async function getLivenessPayload() { | ||
// does a db call to make sure we didnt disconnect | ||
try { | ||
await Models.models.Organization.findOne({}); | ||
} catch (err) { | ||
throw new Error(`Razeedash-api liveness probe failed due to a mongo connection issue: ${err.message}`); | ||
} | ||
|
||
// TODO: not real pub-sub liveness test yet, will add later | ||
if (pubSub.initRetries > 5) { | ||
// if the remote redis is not ready after 5 initial retries, then | ||
// it is better to restart this pod, return 500 error | ||
throw new Error('Razeedash-api liveness probe failed due to Redis pubsub connection issue, please check logs'); | ||
} | ||
|
||
if (pubSub.lastPubSubMessage !== null && Date.now()- pubSub.lastPubSubMessage.time > timeInterval) { | ||
// check if the most recent message received is within ${timeInterval/60000} minitue | ||
throw new Error(`Razeedash-api is down, haven't received any published messages within ${timeInterval/60000} minutes, please check logs`); | ||
} | ||
} | ||
|
||
// Called from app/index.js when server is ready to receive traffic | ||
function setStartupComplete(b) { | ||
STARTUP_COMPLETE = b; | ||
} | ||
|
||
module.exports = { getLivenessPayload, getReadinessPayload, getStartupPayload, setStartupComplete }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Copyright 2024 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
// empty implementation to be used if PROBE_IMPL is not specified | ||
|
||
module.exports = {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
* Copyright 2024 IBM Corp. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
|
||
/* | ||
This sample shows how the startup/liveness/readiness probes can be customized by providing a | ||
module that exports three functions: | ||
- getStartupPayload | ||
- getReadinessPayload | ||
- getLivenessPayload | ||
In each case, the function should return a payload string (not used by kubernetes, but can | ||
be informative), or throw an error that explains why the probe should be failed. | ||
In this sample: | ||
- Return failure for startup probe for 60s, then success | ||
- Return success for readiness probe for 5 minutes, then failure | ||
- Always return success for liveness probe | ||
To use this sample, `export PROBE_IMPL=./probe-sample` before starting the server. | ||
*/ | ||
|
||
const START_TIME = Date.now(); | ||
|
||
async function getStartupPayload(req) { | ||
const method = 'getStartupPayload'; | ||
req.log.warn( {req_id: req.id}, `${method} using SAMPLE implementation, should only happen during dev/test` ); | ||
|
||
if( Date.Now() - START_TIME < 60*1000 ) { | ||
throw new Error('startup probe failing for first 60 seconds'); | ||
} | ||
return('startup probe passing after 60 seconds'); | ||
} | ||
|
||
async function getReadinessPayload(req) { | ||
const method = 'getReadinessPayload'; | ||
req.log.warn( {req_id: req.id}, `${method} using SAMPLE implementation, should only happen during dev/test` ); | ||
|
||
if( Date.Now() - START_TIME < 5*60*1000 ) { | ||
return('readiness probe passing for first 5 minutes'); | ||
} | ||
throw new Error('readiness probe failing after 5 minutes'); | ||
} | ||
|
||
async function getLivenessPayload(req) { | ||
const method = 'getLivenessPayload'; | ||
req.log.warn( {req_id: req.id}, `${method} using SAMPLE implementation, should only happen during dev/test` ); | ||
|
||
return('liveness probe passing'); | ||
} | ||
|
||
module.exports = { getLivenessPayload, getReadinessPayload, getStartupPayload }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.