Skip to content

Commit c1941df

Browse files
chore: adjustments for k8s deployment (ietf-tools#7531)
* chore: handle TERM in datatracker-start.sh * chore: delay celery start if migration needed * chore: skip-checks when migrating * chore: label beat/celery as deleteBeforeUpgrade Used by the infra-k8s deployment process to flag these as needing to be shut down before a new release rolls out. * chore: increase termination grace periods
1 parent bdc4b61 commit c1941df

5 files changed

Lines changed: 171 additions & 144 deletions

File tree

dev/build/celery-start.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
echo "Running Datatracker checks..."
66
./ietf/manage.py check
77

8+
if ! ietf/manage.py migrate --skip-checks --check ; then
9+
echo "Unapplied migrations found, waiting to start..."
10+
sleep 5
11+
while ! ietf/manage.py migrate --skip-checks --check ; do
12+
sleep 5
13+
done
14+
fi
15+
816
cleanup () {
917
# Cleanly terminate the celery app by sending it a TERM, then waiting for it to exit.
1018
if [[ -n "${celery_pid}" ]]; then

dev/build/datatracker-start.sh

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,29 @@ echo "Running Datatracker checks..."
44
./ietf/manage.py check
55

66
echo "Running Datatracker migrations..."
7-
./ietf/manage.py migrate --settings=settings_local
7+
./ietf/manage.py migrate --skip-checks --settings=settings_local
88

99
echo "Starting Datatracker..."
1010

11+
# trap TERM and shut down gunicorn
12+
cleanup () {
13+
if [[ -n "${gunicorn_pid}" ]]; then
14+
echo "Terminating gunicorn..."
15+
kill -TERM "${gunicorn_pid}"
16+
wait "${gunicorn_pid}"
17+
fi
18+
}
19+
20+
trap 'trap "" TERM; cleanup' TERM
21+
22+
# start gunicorn in the background so we can trap the TERM signal
1123
gunicorn \
1224
--workers "${DATATRACKER_GUNICORN_WORKERS:-9}" \
1325
--max-requests "${DATATRACKER_GUNICORN_MAX_REQUESTS:-32768}" \
1426
--timeout "${DATATRACKER_GUNICORN_TIMEOUT:-180}" \
1527
--bind :8000 \
1628
--log-level "${DATATRACKER_GUNICORN_LOG_LEVEL:-info}" \
17-
ietf.wsgi:application
29+
${DATATRACKER_GUNICORN_EXTRA_ARGS} \
30+
ietf.wsgi:application &
31+
gunicorn_pid=$!
32+
wait "${gunicorn_pid}"

k8s/beat.yaml

Lines changed: 63 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,63 @@
1-
apiVersion: apps/v1
2-
kind: Deployment
3-
metadata:
4-
name: beat
5-
spec:
6-
replicas: 1
7-
revisionHistoryLimit: 2
8-
selector:
9-
matchLabels:
10-
app: beat
11-
strategy:
12-
type: Recreate
13-
template:
14-
metadata:
15-
labels:
16-
app: beat
17-
spec:
18-
securityContext:
19-
runAsNonRoot: true
20-
containers:
21-
- name: beat
22-
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
23-
imagePullPolicy: Always
24-
ports:
25-
- containerPort: 8000
26-
name: http
27-
protocol: TCP
28-
volumeMounts:
29-
- name: dt-vol
30-
mountPath: /a
31-
- name: dt-tmp
32-
mountPath: /tmp
33-
- name: dt-cfg
34-
mountPath: /workspace/ietf/settings_local.py
35-
subPath: settings_local.py
36-
env:
37-
- name: "CONTAINER_ROLE"
38-
value: "beat"
39-
envFrom:
40-
- configMapRef:
41-
name: django-config
42-
securityContext:
43-
allowPrivilegeEscalation: false
44-
capabilities:
45-
drop:
46-
- ALL
47-
readOnlyRootFilesystem: true
48-
runAsUser: 1000
49-
runAsGroup: 1000
50-
volumes:
51-
# To be overriden with the actual shared volume
52-
- name: dt-vol
53-
- name: dt-tmp
54-
emptyDir:
55-
sizeLimit: "2Gi"
56-
- name: dt-cfg
57-
configMap:
58-
name: files-cfgmap
59-
dnsPolicy: ClusterFirst
60-
restartPolicy: Always
61-
terminationGracePeriodSeconds: 30
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: beat
5+
labels:
6+
deleteBeforeUpgrade: yes
7+
spec:
8+
replicas: 1
9+
revisionHistoryLimit: 2
10+
selector:
11+
matchLabels:
12+
app: beat
13+
strategy:
14+
type: Recreate
15+
template:
16+
metadata:
17+
labels:
18+
app: beat
19+
spec:
20+
securityContext:
21+
runAsNonRoot: true
22+
containers:
23+
- name: beat
24+
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
25+
imagePullPolicy: Always
26+
ports:
27+
- containerPort: 8000
28+
name: http
29+
protocol: TCP
30+
volumeMounts:
31+
- name: dt-vol
32+
mountPath: /a
33+
- name: dt-tmp
34+
mountPath: /tmp
35+
- name: dt-cfg
36+
mountPath: /workspace/ietf/settings_local.py
37+
subPath: settings_local.py
38+
env:
39+
- name: "CONTAINER_ROLE"
40+
value: "beat"
41+
envFrom:
42+
- configMapRef:
43+
name: django-config
44+
securityContext:
45+
allowPrivilegeEscalation: false
46+
capabilities:
47+
drop:
48+
- ALL
49+
readOnlyRootFilesystem: true
50+
runAsUser: 1000
51+
runAsGroup: 1000
52+
volumes:
53+
# To be overriden with the actual shared volume
54+
- name: dt-vol
55+
- name: dt-tmp
56+
emptyDir:
57+
sizeLimit: "2Gi"
58+
- name: dt-cfg
59+
configMap:
60+
name: files-cfgmap
61+
dnsPolicy: ClusterFirst
62+
restartPolicy: Always
63+
terminationGracePeriodSeconds: 600

k8s/celery.yaml

Lines changed: 82 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,82 @@
1-
apiVersion: apps/v1
2-
kind: Deployment
3-
metadata:
4-
name: celery
5-
spec:
6-
replicas: 1
7-
revisionHistoryLimit: 2
8-
selector:
9-
matchLabels:
10-
app: celery
11-
strategy:
12-
type: Recreate
13-
template:
14-
metadata:
15-
labels:
16-
app: celery
17-
spec:
18-
securityContext:
19-
runAsNonRoot: true
20-
containers:
21-
# -----------------------------------------------------
22-
# ScoutAPM Container
23-
# -----------------------------------------------------
24-
- name: scoutapm
25-
image: "scoutapp/scoutapm:version-1.4.0"
26-
imagePullPolicy: IfNotPresent
27-
livenessProbe:
28-
exec:
29-
command:
30-
- "sh"
31-
- "-c"
32-
- "./core-agent probe --tcp 0.0.0.0:6590 | grep -q 'Agent found'"
33-
securityContext:
34-
readOnlyRootFilesystem: true
35-
runAsUser: 65534 # "nobody" user by default
36-
runAsGroup: 65534 # "nogroup" group by default
37-
# -----------------------------------------------------
38-
# Celery Container
39-
# -----------------------------------------------------
40-
- name: celery
41-
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
42-
imagePullPolicy: Always
43-
ports:
44-
- containerPort: 8000
45-
name: http
46-
protocol: TCP
47-
volumeMounts:
48-
- name: dt-vol
49-
mountPath: /a
50-
- name: dt-tmp
51-
mountPath: /tmp
52-
- name: dt-cfg
53-
mountPath: /workspace/ietf/settings_local.py
54-
subPath: settings_local.py
55-
env:
56-
- name: "CONTAINER_ROLE"
57-
value: "celery"
58-
envFrom:
59-
- configMapRef:
60-
name: django-config
61-
securityContext:
62-
allowPrivilegeEscalation: false
63-
capabilities:
64-
drop:
65-
- ALL
66-
readOnlyRootFilesystem: true
67-
runAsUser: 1000
68-
runAsGroup: 1000
69-
volumes:
70-
# To be overriden with the actual shared volume
71-
- name: dt-vol
72-
- name: dt-tmp
73-
emptyDir:
74-
sizeLimit: "2Gi"
75-
- name: dt-cfg
76-
configMap:
77-
name: files-cfgmap
78-
dnsPolicy: ClusterFirst
79-
restartPolicy: Always
80-
terminationGracePeriodSeconds: 30
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: celery
5+
labels:
6+
deleteBeforeUpgrade: yes
7+
spec:
8+
replicas: 1
9+
revisionHistoryLimit: 2
10+
selector:
11+
matchLabels:
12+
app: celery
13+
strategy:
14+
type: Recreate
15+
template:
16+
metadata:
17+
labels:
18+
app: celery
19+
spec:
20+
securityContext:
21+
runAsNonRoot: true
22+
containers:
23+
# -----------------------------------------------------
24+
# ScoutAPM Container
25+
# -----------------------------------------------------
26+
- name: scoutapm
27+
image: "scoutapp/scoutapm:version-1.4.0"
28+
imagePullPolicy: IfNotPresent
29+
livenessProbe:
30+
exec:
31+
command:
32+
- "sh"
33+
- "-c"
34+
- "./core-agent probe --tcp 0.0.0.0:6590 | grep -q 'Agent found'"
35+
securityContext:
36+
readOnlyRootFilesystem: true
37+
runAsUser: 65534 # "nobody" user by default
38+
runAsGroup: 65534 # "nogroup" group by default
39+
# -----------------------------------------------------
40+
# Celery Container
41+
# -----------------------------------------------------
42+
- name: celery
43+
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
44+
imagePullPolicy: Always
45+
ports:
46+
- containerPort: 8000
47+
name: http
48+
protocol: TCP
49+
volumeMounts:
50+
- name: dt-vol
51+
mountPath: /a
52+
- name: dt-tmp
53+
mountPath: /tmp
54+
- name: dt-cfg
55+
mountPath: /workspace/ietf/settings_local.py
56+
subPath: settings_local.py
57+
env:
58+
- name: "CONTAINER_ROLE"
59+
value: "celery"
60+
envFrom:
61+
- configMapRef:
62+
name: django-config
63+
securityContext:
64+
allowPrivilegeEscalation: false
65+
capabilities:
66+
drop:
67+
- ALL
68+
readOnlyRootFilesystem: true
69+
runAsUser: 1000
70+
runAsGroup: 1000
71+
volumes:
72+
# To be overriden with the actual shared volume
73+
- name: dt-vol
74+
- name: dt-tmp
75+
emptyDir:
76+
sizeLimit: "2Gi"
77+
- name: dt-cfg
78+
configMap:
79+
name: files-cfgmap
80+
dnsPolicy: ClusterFirst
81+
restartPolicy: Always
82+
terminationGracePeriodSeconds: 600

k8s/datatracker.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ spec:
7777
name: files-cfgmap
7878
dnsPolicy: ClusterFirst
7979
restartPolicy: Always
80-
terminationGracePeriodSeconds: 30
80+
terminationGracePeriodSeconds: 60
8181
---
8282
apiVersion: v1
8383
kind: Service

0 commit comments

Comments
 (0)