Skip to content

Commit 97b9711

Browse files
authored
Merge pull request #142 from dasmeta/DMVP-7517-default-wait-5-second-before-termination
DMVP-7517: have default preStop lifecycle rule with 5 seconds sleep/await to allow standard web apps have graceful shutdown
2 parents 1de83d9 + fc0dc51 commit 97b9711

File tree

8 files changed

+224
-30
lines changed

8 files changed

+224
-30
lines changed

charts/base/Chart.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ type: application
1515
# This is the chart version. This version number should be incremented each time you make changes
1616
# to the chart and its templates, including the app version.
1717
# Versions are expected to follow Semantic Versioning (https://semver.org/)
18-
version: 0.3.7
18+
version: 0.3.8
1919

2020
# This is the version number of the application being deployed. This version number should be
2121
# incremented each time you make changes to the application. Versions are not expected to
2222
# follow Semantic Versioning. They should reflect the version the application is using.
2323
# It is recommended to use it with quotes.
24-
appVersion: "0.3.7"
24+
appVersion: "0.3.8"

charts/base/README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,11 +725,22 @@ rolloutStrategy:
725725
namespace: ingress-nginx
726726
```
727727
728-
## Deprecations and incompatible changes
728+
## Deprecations and incompatible changes and release important notes
729729
730730
### Deprecations
731731
- 0.3.0: `deployment` option is deprecated and all underlying fields are now available as top level variables, so that `deployment.volumes` moved to `volumes`, `deployment.additionalvolumeMounts` to `additionalVolumeMounts` and `deployment.lifecycle` to `lifecycle`
732732
- 0.3.0: for mounting volume to extra container use `container: <extra-container-name>` or `container: [<extra-container-name>]` instead of `container: extra` config in new `volumes` listing.
733733

734734
### incompatible changes
735735
- 0.3.0: the `extraContainer.deployment.volumes` field have been removed, use `volumes` field with `container: <extra-container-name>` for having volume mounted to extra container
736+
737+
### release important notes
738+
- Version 0.3.8:
739+
This release introduces a new feature that enhances the robustness of pod termination by implementing a default preStop lifecycle hook.
740+
- Default preStop Hook: Version 0.3.8 introduces the `defaultLifecycle` variable, which, by default, automatically configures a preStop hook with a `sleep 5` command.
741+
- Graceful Pod Termination: This 5-second delay before container shutdown provides sufficient time for the pod's IP address to be unregistered from service target lists. This proactive measure minimizes the occurrence of failed HTTP requests during pod termination, leading to improved application stability and user experience.
742+
- sleep Command Dependency: While the absence of the sleep command within a container's operating system will prevent the 5-second delay from functioning, but will not produce any additional issues, it is strongly recommended to include or install the sleep utility in your container images to ensure the intended graceful termination behavior.
743+
- Custom preStop Configurations: If your containers already have custom `preStop` lifecycle configurations defined, these existing configurations will take precedence, effectively overriding the default configuration introduced in this release. However, to benefit from the graceful termination feature, it is advisable to incorporate a sleep 5 command within your custom `preStop` configurations.
744+
- Scope of Default Configuration: The default `preStop` configuration is applied uniformly to all containers within a pod, including the main application container and all extra containers.
745+
- Default Timeout Considerations: The default 5-second sleep duration has been determined through testing on standard web applications within an EKS cluster and is generally sufficient for facilitating a graceful shutdown. However, applications with longer request processing times (exceeding 2 seconds) may require an increased timeout value. You can adjust this by defining custom `preStop` configurations with a longer sleep duration.
746+
- Disabling the Default Configuration: The default `preStop` hook can be easily disabled by setting the Helm chart value `defaultLifecycle.enabled=false`.

charts/base/templates/deployment.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{{ $baseFullName := (include "base.fullname" .) }}
22
{{ $volumes := (coalesce .Values.volumes (.Values.deployment).volumes) }}
33
{{ $additionalVolumeMounts := (coalesce .Values.additionalVolumeMounts (.Values.deployment).additionalvolumeMounts) }}
4-
{{ $lifecycle := (coalesce .Values.lifecycle (.Values.deployment).lifecycle) }}
4+
{{ $defaultLifecycle := ternary (unset (deepCopy .Values.defaultLifecycle) "enabled" ) (dict) .Values.defaultLifecycle.enabled }}
5+
{{ $lifecycle := merge (coalesce .Values.lifecycle (.Values.deployment).lifecycle) $defaultLifecycle }}
56
apiVersion: apps/v1
67
kind: Deployment
78
metadata:
@@ -300,9 +301,9 @@ spec:
300301
{{- toYaml $extraContainer.additionalVolumeMounts | nindent 12 }}
301302
{{- end }}
302303
{{- end }}
303-
{{- if (coalesce $extraContainer.lifecycle ($extraContainer.deployment).lifecycle) }}
304+
{{- if (merge (coalesce $extraContainer.lifecycle ($extraContainer.deployment).lifecycle) $defaultLifecycle) }}
304305
lifecycle:
305-
{{- toYaml (coalesce $extraContainer.lifecycle ($extraContainer.deployment).lifecycle) | nindent 12 }}
306+
{{- toYaml (merge (coalesce $extraContainer.lifecycle ($extraContainer.deployment).lifecycle) $defaultLifecycle) | nindent 12 }}
306307
{{- end }}
307308
{{- end }}
308309
{{- end }}

charts/base/values.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,16 @@ pdb:
318318
minAvailable: 1
319319
pdbName:
320320

321+
# the default lifecycle rule to apply which allows to have some kind of graceful shutdown by waiting/sleep for 5 seconds, even if there is no sleep command in os this will not produce issues and container will get shuted down
322+
defaultLifecycle:
323+
enabled: true # whether this default is enabled, by default it is enabled but can be disabled if needed by setting this to false
324+
preStop:
325+
exec:
326+
command:
327+
- sh
328+
- -c
329+
- sleep 5 # the sleep interval can vary for app, if you still get issues at pod termination consider increasing it little by little to get optimal one for you, based on tests the 5 seconds seems suitable for standard web app on eks to get the pod IP removed from service targets and to finish active client requests/connections to not have failed request at pod termination
330+
321331
serviceMonitor:
322332
enabled: false
323333
interval: 30s

examples/base/basic.yaml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# helm diff upgrade --install -n localhost basic ./charts/base/ -f ./examples/base/basic.yaml
2+
3+
image:
4+
repository: mendhak/http-https-echo
5+
tag: 34
6+
7+
containerPort: 8080
8+
9+
config:
10+
ROLLOUT_TRIGGER_VERSION: "8"
11+
12+
service:
13+
enabled: true
14+
type: ClusterIP
15+
16+
autoscaling:
17+
enabled: true
18+
minReplicas: 1
19+
maxReplicas: 5
20+
targetCPUUtilizationPercentage: 99
21+
22+
pdb:
23+
enabled: true
24+
minAvailable: 1
25+
26+
readinessProbe:
27+
initialDelaySeconds: 5
28+
failureThreshold: 1
29+
httpGet:
30+
path: /health
31+
port: http
32+
livenessProbe:
33+
initialDelaySeconds: 5
34+
failureThreshold: 3
35+
httpGet:
36+
path: /health
37+
port: http
38+
resources:
39+
requests:
40+
cpu: 100m
41+
42+
setIngressClassByField: true
43+
ingress:
44+
enabled: true
45+
class: nginx
46+
hosts:
47+
- host: http-echo-basic.localhost
48+
paths:
49+
- path: "/ping"

examples/base/with-canary-deployment/canary-with-manual-approval.yaml

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -98,46 +98,52 @@ rolloutStrategy:
9898
# const cookieVersion = "canaryNewWebsite"; // the cookie name which defines the version of website that user should see
9999
# const cookieSwitchSource = "canarySwitchSource"; // this cookie allows to keep in browser if user have been switched automatically to new/old website version or manually(by button click)
100100
# const cookieAutoSwitchPercent = "canaryAutoSwitchPercent"; // we store this data in cookie to have the data in user/client browser that this were been proceeded by this percent of auto switch
101-
# const cookieDefaultExpire = "expires=Mon, 14 Jul 2025 07:58:08 GMT"; // by default this expire date will be set on cookies, it is about 3 months, this is for auto cleanup of above 3 used cookies after this period
101+
# const cookieDefaultExpire = "expires=Mon, 14 Jul 2025 07:58:08 UTC"; // by default this expire date will be set on cookies, it is about 3 months, this is for auto cleanup of above 3 used cookies after this period
102102
# const removeCookieExpire = "expires=Thu, 01 Jan 1970 00:00:00 UTC"; // this back-day expire date for cookies is just for cleanup/remove of cookies
103103
# let cookies = [];
104104
# switch(action) {
105105
# case "switch-auto":
106106
# if ( !document.cookie.includes(`${cookieSwitchSource}=manual`) // we do auto switch for ones who do not change to new/old manually
107107
# && (!document.cookie.includes(`${cookieVersion}=`) // if this is first load
108-
# || !document.cookie.includes(`${cookieAutoSwitchPercent}=${newVersionAutoSwitchUsersPercent}`)) // or if percent changed
108+
# || (!document.cookie.includes(`${cookieAutoSwitchPercent}=${newVersionAutoSwitchUsersPercent}`) && !document.cookie.includes(`${cookieVersion}=always`))) // or if percent changed and user is not using new version of website
109109
# ) {
110110
# cookies = [
111-
# `${cookieSwitchSource}=auto`,
112-
# `${cookieAutoSwitchPercent}=${newVersionAutoSwitchUsersPercent}`
111+
# `${cookieSwitchSource}=auto; ${cookieDefaultExpire}`,
112+
# `${cookieAutoSwitchPercent}=${newVersionAutoSwitchUsersPercent}; ${cookieDefaultExpire}`
113113
# ];
114114
# if ((Math.floor(Math.random() * 100) + 1) < newVersionAutoSwitchUsersPercent) {
115-
# cookies.push(`${cookieVersion}=always`);
115+
# cookies.push(`${cookieVersion}=always; ${cookieDefaultExpire}`);
116116
# } else {
117-
# cookies.push(`${cookieVersion}=no`);
117+
# cookies.push(`${cookieVersion}=no; ${cookieDefaultExpire}`);
118118
# }
119119
# }
120120
# break;
121121
# case "switch-to-new-manual":
122-
# cookies = [
123-
# `${cookieVersion}=always; ${cookieDefaultExpire}`,
124-
# `${cookieSwitchSource}=manual; ${cookieDefaultExpire}`,
125-
# `${cookieAutoSwitchPercent}=r; ${removeCookieExpire}`
126-
# ];
122+
# if (!document.cookie.includes(`${cookieVersion}=always`)) { // if this cookies were not been set yet
123+
# cookies = [
124+
# `${cookieVersion}=always; ${cookieDefaultExpire}`,
125+
# `${cookieSwitchSource}=manual; ${cookieDefaultExpire}`,
126+
# `${cookieAutoSwitchPercent}=r; ${removeCookieExpire}`
127+
# ];
128+
# }
127129
# break;
128130
# case "switch-to-old-manual":
129-
# cookies = [
130-
# `${cookieVersion}=no; ${cookieDefaultExpire}`,
131-
# `${cookieSwitchSource}=manual; ${cookieDefaultExpire}`,
132-
# `${cookieAutoSwitchPercent}=r; ${removeCookieExpire}`
133-
# ];
131+
# if (!document.cookie.includes(`${cookieVersion}=no`)) { // if this cookies were not been set yet
132+
# cookies = [
133+
# `${cookieVersion}=no; ${cookieDefaultExpire}`,
134+
# `${cookieSwitchSource}=manual; ${cookieDefaultExpire}`,
135+
# `${cookieAutoSwitchPercent}=r; ${removeCookieExpire}`
136+
# ];
137+
# }
134138
# break;
135139
# case "reset":
136-
# cookies = [
137-
# `${cookieVersion}=r; ${removeCookieExpire}`,
138-
# `${cookieSwitchSource}=r; ${removeCookieExpire}`,
139-
# `${cookieAutoSwitchPercent}=r; ${removeCookieExpire}`
140-
# ];
140+
# if (document.cookie.includes(`${cookieVersion}=`)) { // if this cookies were been set
141+
# cookies = [
142+
# `${cookieVersion}=r; ${removeCookieExpire}`,
143+
# `${cookieSwitchSource}=r; ${removeCookieExpire}`,
144+
# `${cookieAutoSwitchPercent}=r; ${removeCookieExpire}`
145+
# ];
146+
# }
141147
# break;
142148
# default:
143149
# console.log("undefined action");
@@ -155,7 +161,7 @@ rolloutStrategy:
155161
# }
156162

157163
# const switchButton = document.createElement("button");
158-
# switchButton.style.cssText = "position: fixed;z-index: 999;top: 1px";
164+
# switchButton.style.cssText = "position: fixed;z-index: 999;bottom: 1px; right: 1px; color: black; background: white; border: 3px solid black; padding: 1px 6px;";
159165
# switchButton.innerHTML = isWebsiteNewVersion() ? "Switch to old UI" : "Switch to New UI";
160166
# switchButton.onclick = function () {
161167
# if (isWebsiteNewVersion()) {
@@ -167,6 +173,6 @@ rolloutStrategy:
167173

168174
# document.body.appendChild(switchButton);
169175
# }
170-
# canaryAction("switch-auto"); // possible values "switch-auto", "reset", "switch-to-new-manual" and "switch-to-old-manual"
171-
# createSwitchButton(); // place/crate a switch button in UI for manual switching(should be seen bottom left corner)
176+
# document.location.href.includes("staging-canary") && canaryAction("switch-auto"); // possible values "switch-auto", "reset", "switch-to-new-manual" and "switch-to-old-manual"
177+
# document.location.href.includes("staging-canary") && createSwitchButton(); // place/crate a switch button in UI for manual switching(should be seen bottom left corner)
172178
# ```
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# helm diff upgrade --install -n localhost with-extra-container ./charts/base/ -f ./examples/base/with-extra-container.yaml
2+
3+
image:
4+
repository: mendhak/http-https-echo
5+
tag: 34
6+
7+
containerPort: 8080
8+
9+
config:
10+
ROLLOUT_TRIGGER_VERSION: "8"
11+
12+
service:
13+
enabled: true
14+
type: ClusterIP
15+
16+
autoscaling:
17+
enabled: true
18+
minReplicas: 1
19+
maxReplicas: 5
20+
targetCPUUtilizationPercentage: 99
21+
22+
pdb:
23+
enabled: true
24+
minAvailable: 1
25+
26+
readinessProbe:
27+
initialDelaySeconds: 5
28+
failureThreshold: 1
29+
httpGet:
30+
path: /health
31+
port: http
32+
livenessProbe:
33+
initialDelaySeconds: 5
34+
failureThreshold: 3
35+
httpGet:
36+
path: /health
37+
port: http
38+
resources:
39+
requests:
40+
cpu: 100m
41+
42+
setIngressClassByField: true
43+
ingress:
44+
enabled: true
45+
class: nginx
46+
hosts:
47+
- host: with-extra-container.localhost
48+
paths:
49+
- path: "/ping"
50+
51+
extraContainer:
52+
- name: extra-http-echo
53+
containerPort: 8081
54+
service:
55+
enabled: true
56+
image:
57+
repository: mendhak/http-https-echo
58+
tag: 33
59+
extraEnv:
60+
HTTP_PORT: 8180
61+
HTTPS_PORT: 8543

examples/base/with-linkerd.yaml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# helm diff upgrade --install -n localhost with-linkerd ./charts/base/ -f ./examples/base/with-linkerd.yaml
2+
3+
image:
4+
repository: mendhak/http-https-echo
5+
tag: 34
6+
7+
containerPort: 8080
8+
9+
config:
10+
ROLLOUT_TRIGGER_VERSION: "8"
11+
12+
podAnnotations:
13+
linkerd.io/inject: enabled
14+
config.linkerd.io/proxy-cpu-request: 50m
15+
config.linkerd.io/proxy-cpu-limit: 50m
16+
17+
service:
18+
enabled: true
19+
type: ClusterIP
20+
21+
autoscaling:
22+
enabled: true
23+
minReplicas: 1
24+
maxReplicas: 5
25+
targetCPUUtilizationPercentage: 99
26+
27+
pdb:
28+
enabled: true
29+
minAvailable: 1
30+
31+
readinessProbe:
32+
initialDelaySeconds: 5
33+
failureThreshold: 1
34+
httpGet:
35+
path: /health
36+
port: http
37+
livenessProbe:
38+
initialDelaySeconds: 5
39+
failureThreshold: 3
40+
httpGet:
41+
path: /health
42+
port: http
43+
resources:
44+
requests:
45+
cpu: 100m
46+
limits:
47+
cpu: 100m
48+
49+
setIngressClassByField: true
50+
ingress:
51+
enabled: true
52+
class: nginx
53+
hosts:
54+
- host: http-echo-with-linkerd.localhost
55+
paths:
56+
- path: "/ping"

0 commit comments

Comments
 (0)