diff --git a/plugins/contrib/kontinuous.yaml b/plugins/contrib/kontinuous.yaml index 468eee290..6b880ceaf 100644 --- a/plugins/contrib/kontinuous.yaml +++ b/plugins/contrib/kontinuous.yaml @@ -33,6 +33,8 @@ patches: enabled: false privateImages: enabled: false + zeroDowntimeReadiness: + enabled: false validators: rancherProjectId: diff --git a/plugins/contrib/patches/70-zero-downtime-readiness.js b/plugins/contrib/patches/70-zero-downtime-readiness.js new file mode 100644 index 000000000..909ea65ef --- /dev/null +++ b/plugins/contrib/patches/70-zero-downtime-readiness.js @@ -0,0 +1,86 @@ +module.exports = function updateDeploymentManifests(manifests, options = {}) { + // Set default values for options if not provided + const { + initialDelaySeconds = 5, + periodSeconds = 5, + gracefulShutdownSeconds = 30, // Default graceful shutdown time + disableAnnotation = "kontinuous/plugin.zeroDowntimeHandled", + } = options + + manifests.forEach((manifest) => { + // Check if the resource is a Deployment and doesn't have the disable annotation + if ( + manifest.kind === "Deployment" && + (!manifest.metadata.annotations || + manifest.metadata.annotations[disableAnnotation] !== "true") + ) { + // Ensure metadata, spec, and template sections exist + manifest.metadata.annotations = manifest.metadata.annotations || {} + manifest.spec = manifest.spec || {} + manifest.spec.template = manifest.spec.template || {} + manifest.spec.template.spec = manifest.spec.template.spec || { + containers: [], + volumes: [], + } + + // Setup the postStart and preStop lifecycle hooks and readiness probe + manifest.spec.template.spec.containers.forEach((container) => { + // Setup lifecycle hooks + container.lifecycle = { + postStart: { + exec: { + // Command to create the readiness file + command: [ + "sh", + "-c", + "touch /var/run/readiness-check/readiness-file", + ], + }, + }, + preStop: { + exec: { + // Adding a sleep of gracefulShutdownSeconds before removing the readiness file + command: [ + "sh", + "-c", + `sleep ${gracefulShutdownSeconds}; rm -f /var/run/readiness-check/readiness-file`, + ], + }, + }, + } + + // Setup readiness probe + container.readinessProbe = { + exec: { + command: ["cat", "/var/run/readiness-check/readiness-file"], + }, + initialDelaySeconds, + periodSeconds, + } + + // Define a unique and precise mount path + const mountPath = "/var/run/readiness-check" + const uniqueVolumeName = "readiness-check-volume" + container.volumeMounts = container.volumeMounts || [] + container.volumeMounts.push({ + name: uniqueVolumeName, + mountPath, + }) + }) + + // Ensure the volume does not conflict and is added to the pod spec + if ( + !manifest.spec.template.spec.volumes.some( + (v) => v.name === "readiness-check-volume" + ) + ) { + manifest.spec.template.spec.volumes.push({ + name: "readiness-check-volume", + emptyDir: {}, + }) + } + } + }) + + return manifests +} diff --git a/plugins/fabrique/kontinuous.yaml b/plugins/fabrique/kontinuous.yaml index 67ff053f5..97b56ce23 100644 --- a/plugins/fabrique/kontinuous.yaml +++ b/plugins/fabrique/kontinuous.yaml @@ -21,6 +21,9 @@ dependencies: buildkitSvcCount: 6 patches: + zeroDowntimeReadiness: + # enabled: true + enabled: false certs: enabled: true options: