chore: adjustments for k8s deployment (#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
This commit is contained in:
Jennifer Richards 2024-06-14 11:28:14 -03:00 committed by GitHub
parent bdc4b618bb
commit c1941df7e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 171 additions and 144 deletions

View file

@ -5,6 +5,14 @@
echo "Running Datatracker checks..." echo "Running Datatracker checks..."
./ietf/manage.py check ./ietf/manage.py check
if ! ietf/manage.py migrate --skip-checks --check ; then
echo "Unapplied migrations found, waiting to start..."
sleep 5
while ! ietf/manage.py migrate --skip-checks --check ; do
sleep 5
done
fi
cleanup () { cleanup () {
# Cleanly terminate the celery app by sending it a TERM, then waiting for it to exit. # Cleanly terminate the celery app by sending it a TERM, then waiting for it to exit.
if [[ -n "${celery_pid}" ]]; then if [[ -n "${celery_pid}" ]]; then

View file

@ -4,14 +4,29 @@ echo "Running Datatracker checks..."
./ietf/manage.py check ./ietf/manage.py check
echo "Running Datatracker migrations..." echo "Running Datatracker migrations..."
./ietf/manage.py migrate --settings=settings_local ./ietf/manage.py migrate --skip-checks --settings=settings_local
echo "Starting Datatracker..." echo "Starting Datatracker..."
# trap TERM and shut down gunicorn
cleanup () {
if [[ -n "${gunicorn_pid}" ]]; then
echo "Terminating gunicorn..."
kill -TERM "${gunicorn_pid}"
wait "${gunicorn_pid}"
fi
}
trap 'trap "" TERM; cleanup' TERM
# start gunicorn in the background so we can trap the TERM signal
gunicorn \ gunicorn \
--workers "${DATATRACKER_GUNICORN_WORKERS:-9}" \ --workers "${DATATRACKER_GUNICORN_WORKERS:-9}" \
--max-requests "${DATATRACKER_GUNICORN_MAX_REQUESTS:-32768}" \ --max-requests "${DATATRACKER_GUNICORN_MAX_REQUESTS:-32768}" \
--timeout "${DATATRACKER_GUNICORN_TIMEOUT:-180}" \ --timeout "${DATATRACKER_GUNICORN_TIMEOUT:-180}" \
--bind :8000 \ --bind :8000 \
--log-level "${DATATRACKER_GUNICORN_LOG_LEVEL:-info}" \ --log-level "${DATATRACKER_GUNICORN_LOG_LEVEL:-info}" \
ietf.wsgi:application ${DATATRACKER_GUNICORN_EXTRA_ARGS} \
ietf.wsgi:application &
gunicorn_pid=$!
wait "${gunicorn_pid}"

View file

@ -1,61 +1,63 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: beat name: beat
spec: labels:
replicas: 1 deleteBeforeUpgrade: yes
revisionHistoryLimit: 2 spec:
selector: replicas: 1
matchLabels: revisionHistoryLimit: 2
app: beat selector:
strategy: matchLabels:
type: Recreate app: beat
template: strategy:
metadata: type: Recreate
labels: template:
app: beat metadata:
spec: labels:
securityContext: app: beat
runAsNonRoot: true spec:
containers: securityContext:
- name: beat runAsNonRoot: true
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG" containers:
imagePullPolicy: Always - name: beat
ports: image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
- containerPort: 8000 imagePullPolicy: Always
name: http ports:
protocol: TCP - containerPort: 8000
volumeMounts: name: http
- name: dt-vol protocol: TCP
mountPath: /a volumeMounts:
- name: dt-tmp - name: dt-vol
mountPath: /tmp mountPath: /a
- name: dt-cfg - name: dt-tmp
mountPath: /workspace/ietf/settings_local.py mountPath: /tmp
subPath: settings_local.py - name: dt-cfg
env: mountPath: /workspace/ietf/settings_local.py
- name: "CONTAINER_ROLE" subPath: settings_local.py
value: "beat" env:
envFrom: - name: "CONTAINER_ROLE"
- configMapRef: value: "beat"
name: django-config envFrom:
securityContext: - configMapRef:
allowPrivilegeEscalation: false name: django-config
capabilities: securityContext:
drop: allowPrivilegeEscalation: false
- ALL capabilities:
readOnlyRootFilesystem: true drop:
runAsUser: 1000 - ALL
runAsGroup: 1000 readOnlyRootFilesystem: true
volumes: runAsUser: 1000
# To be overriden with the actual shared volume runAsGroup: 1000
- name: dt-vol volumes:
- name: dt-tmp # To be overriden with the actual shared volume
emptyDir: - name: dt-vol
sizeLimit: "2Gi" - name: dt-tmp
- name: dt-cfg emptyDir:
configMap: sizeLimit: "2Gi"
name: files-cfgmap - name: dt-cfg
dnsPolicy: ClusterFirst configMap:
restartPolicy: Always name: files-cfgmap
terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 600

View file

@ -1,80 +1,82 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: celery name: celery
spec: labels:
replicas: 1 deleteBeforeUpgrade: yes
revisionHistoryLimit: 2 spec:
selector: replicas: 1
matchLabels: revisionHistoryLimit: 2
app: celery selector:
strategy: matchLabels:
type: Recreate app: celery
template: strategy:
metadata: type: Recreate
labels: template:
app: celery metadata:
spec: labels:
securityContext: app: celery
runAsNonRoot: true spec:
containers: securityContext:
# ----------------------------------------------------- runAsNonRoot: true
# ScoutAPM Container containers:
# ----------------------------------------------------- # -----------------------------------------------------
- name: scoutapm # ScoutAPM Container
image: "scoutapp/scoutapm:version-1.4.0" # -----------------------------------------------------
imagePullPolicy: IfNotPresent - name: scoutapm
livenessProbe: image: "scoutapp/scoutapm:version-1.4.0"
exec: imagePullPolicy: IfNotPresent
command: livenessProbe:
- "sh" exec:
- "-c" command:
- "./core-agent probe --tcp 0.0.0.0:6590 | grep -q 'Agent found'" - "sh"
securityContext: - "-c"
readOnlyRootFilesystem: true - "./core-agent probe --tcp 0.0.0.0:6590 | grep -q 'Agent found'"
runAsUser: 65534 # "nobody" user by default securityContext:
runAsGroup: 65534 # "nogroup" group by default readOnlyRootFilesystem: true
# ----------------------------------------------------- runAsUser: 65534 # "nobody" user by default
# Celery Container runAsGroup: 65534 # "nogroup" group by default
# ----------------------------------------------------- # -----------------------------------------------------
- name: celery # Celery Container
image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG" # -----------------------------------------------------
imagePullPolicy: Always - name: celery
ports: image: "ghcr.io/ietf-tools/datatracker:$APP_IMAGE_TAG"
- containerPort: 8000 imagePullPolicy: Always
name: http ports:
protocol: TCP - containerPort: 8000
volumeMounts: name: http
- name: dt-vol protocol: TCP
mountPath: /a volumeMounts:
- name: dt-tmp - name: dt-vol
mountPath: /tmp mountPath: /a
- name: dt-cfg - name: dt-tmp
mountPath: /workspace/ietf/settings_local.py mountPath: /tmp
subPath: settings_local.py - name: dt-cfg
env: mountPath: /workspace/ietf/settings_local.py
- name: "CONTAINER_ROLE" subPath: settings_local.py
value: "celery" env:
envFrom: - name: "CONTAINER_ROLE"
- configMapRef: value: "celery"
name: django-config envFrom:
securityContext: - configMapRef:
allowPrivilegeEscalation: false name: django-config
capabilities: securityContext:
drop: allowPrivilegeEscalation: false
- ALL capabilities:
readOnlyRootFilesystem: true drop:
runAsUser: 1000 - ALL
runAsGroup: 1000 readOnlyRootFilesystem: true
volumes: runAsUser: 1000
# To be overriden with the actual shared volume runAsGroup: 1000
- name: dt-vol volumes:
- name: dt-tmp # To be overriden with the actual shared volume
emptyDir: - name: dt-vol
sizeLimit: "2Gi" - name: dt-tmp
- name: dt-cfg emptyDir:
configMap: sizeLimit: "2Gi"
name: files-cfgmap - name: dt-cfg
dnsPolicy: ClusterFirst configMap:
restartPolicy: Always name: files-cfgmap
terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst
restartPolicy: Always
terminationGracePeriodSeconds: 600

View file

@ -77,7 +77,7 @@ spec:
name: files-cfgmap name: files-cfgmap
dnsPolicy: ClusterFirst dnsPolicy: ClusterFirst
restartPolicy: Always restartPolicy: Always
terminationGracePeriodSeconds: 30 terminationGracePeriodSeconds: 60
--- ---
apiVersion: v1 apiVersion: v1
kind: Service kind: Service