web: Add optional auto-scaling to the deployment
This adds the auto-scaling part required in the reference task.
make swh-helm-diff
make swh-helm-diff
./helm-diff.sh swh
[swh] Comparing changes between branches production and web-add-autoscaling...
Switched to branch 'production'
Your branch is up to date with 'origin/production'.
[swh] Generate config in production branch for swh/values/default.yaml...
[swh] Generate config in production branch for swh/values/minikube.yaml...
[swh] Generate config in production branch for swh/values/production-cassandra.yaml...
[swh] Generate config in production branch for swh/values/production.yaml...
[swh] Generate config in production branch for swh/values/staging-cassandra.yaml...
[swh] Generate config in production branch for swh/values/staging.yaml...
Switched to branch 'web-add-autoscaling'
[swh] Generate config in web-add-autoscaling branch for swh/values/default.yaml...
[swh] Generate config in web-add-autoscaling branch for swh/values/minikube.yaml...
[swh] Generate config in web-add-autoscaling branch for swh/values/production-cassandra.yaml...
[swh] Generate config in web-add-autoscaling branch for swh/values/production.yaml...
[swh] Generate config in web-add-autoscaling branch for swh/values/staging-cassandra.yaml...
[swh] Generate config in web-add-autoscaling branch for swh/values/staging.yaml...
------------- diff for swh/values/default.yaml -------------
No differences
------------- diff for swh/values/minikube.yaml -------------
--- /tmp/swh-chart.swh.9h65qILO/minikube.yaml.before 2023-10-05 15:57:38.620596181 +0200
+++ /tmp/swh-chart.swh.9h65qILO/minikube.yaml.after 2023-10-05 15:57:39.804597623 +0200
@@ -160,20 +160,102 @@
if [ -e "${DB_VERSION}" ]; then
echo "Unable to find the code version"
exit 1
fi
if [ "$DB_VERSION" -ne "$CODE_VERSION" ]; then
echo "code and DB versions are different. Blocking the deployment"
exit 1
fi
---
+# Source: swh/templates/web/configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ namespace: swh
+ name: web-configuration-template
+data:
+ config.yml.template: |
+ storage:
+ cls: remote
+ url: http://fake-storage.i.s.s.n:8002
+ search:
+ cls: remote
+ url: http://fake-search.i.s.s.n:5005
+ scheduler:
+ cls: remote
+ url: http://fake-scheduler.i.s.s.n:5008
+ vault:
+ cls: remote
+ url: http://fake-vault.i.s.s.n:5006
+ counters_backend: swh-counters
+ counters:
+ cls: remote
+ url: http://fake-counters.i.s.s.n:5006
+
+ secret_key: ${DJANGO_SECRET_KEY}
+ production_db:
+
+ host: db1.i.s.s.n
+ port: 5432
+ name: swh-web
+ user: swh-web
+ password: ${POSTGRESQL_PASSWORD}
+ throttling:
+ cache_uri: fake-memcached:11211
+ scopes:
+ swh_api:
+ exempted_networks:
+ - 10.100.100.0/24
+ - 127.0.0.0/8
+ - 192.168.100.0/24
+ - 192.168.102.0/24
+ limiter_rate:
+ default: 120/h
+ swh_api_origin_search:
+ limiter_rate:
+ default: 120/h
+ add_forge_now:
+ email_address: add-forge-now@webapp.s.s.n
+ allowed_hosts:
+ - webapp.internal.minikube
+ content_display_max_size: 5242880
+ debug: false
+ deposit:
+ private_api_password: ${DEPOSIT_PASSWORD}
+ private_api_url: https://deposit-rp.i.s.s.n/1/private/
+ private_api_user: ${DEPOSIT_USERNAME}
+ give:
+ public_key: ${GIVE_PUBLIC_KEY}
+ token: ${GIVE_PRIVATE_TOKEN}
+ history_counters_url: http://counters0.i.s.s.n:5011/counters_history/history.json
+ instance_name: webapp.internal.minikube
+ keycloak:
+ realm_name: SwhMinikube
+ server_url: https://auth.s.o/auth/
+ matomo: {}
+ search_config:
+ metadata_backend: swh-indexer-storage
+ swh_extra_django_apps:
+ - swh.web.add_forge_now
+ - swh.web.archive_coverage
+ - swh.web.badges
+ - swh.web.banners
+ - swh.web.deposit
+ - swh.web.inbound_email
+ - swh.web.jslicenses
+ - swh.web.mailmap
+ - swh.web.metrics
+ - swh.web.save_code_now
+ - swh.web.save_origin_webhooks
+ - swh.web.vault
+---
# Source: swh/charts/keda/templates/crds/crd-clustertriggerauthentications.yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.12.0
labels:
app.kubernetes.io/name: keda-operator
helm.sh/chart: keda-2.11.0
app.kubernetes.io/component: operator
@@ -9744,20 +9826,38 @@
app: prometheus-statsd-exporter
ports:
- name: statsd
port: 9125
targetPort: 9125
protocol: UDP
- name: http
port: 9102
targetPort: 9102
---
+# Source: swh/templates/web/service.yaml
+apiVersion: v1
+kind: Service
+metadata:
+ name: web
+ namespace: swh
+spec:
+ type: ClusterIP
+ selector:
+ app: web
+ ports:
+ - port: 5004
+ targetPort: 5004
+ name: webapp
+ - port: 80
+ targetPort: 80
+ name: webstatic
+---
# Source: swh/charts/keda/templates/manager/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: keda-operator
namespace: default
annotations:
{}
labels:
app: keda-operator
@@ -10118,20 +10218,276 @@
volumeMounts:
- name: config
mountPath: /etc/prometheus/statsd-mapping.yml
subPath: config.yml
readOnly: true
volumes:
- name: config
configMap:
name: prometheus-statsd-exporter
---
+# Source: swh/templates/web/deployment.yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ namespace: swh
+ name: web
+ labels:
+ app: web
+spec:
+ revisionHistoryLimit: 2
+ selector:
+ matchLabels:
+ app: web
+ strategy:
+ type: RollingUpdate
+ rollingUpdate:
+ maxSurge: 1
+ template:
+ metadata:
+ labels:
+ app: web
+ annotations:
+ checksum/config: 2bc485166c625fe75ceed8935e23f86458bd321c45758e1b8c60499586bc2740
+ spec:
+ affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: swh/web
+ operator: In
+ values:
+ - "true"
+ priorityClassName: swh-frontend-rpc
+
+ initContainers:
+ - name: prepare-configuration
+ image: debian:bullseye
+ imagePullPolicy: IfNotPresent
+ command:
+ - /bin/bash
+ args:
+ - -c
+ - eval echo "\"$(</etc/swh/configuration-template/config.yml.template)\"" > /etc/swh/config.yml
+ env:
+
+ - name: POSTGRESQL_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: swh-postgresql-web-secret
+ key: postgres-swh-web-password
+ # 'name' secret must exist & include that ^ key
+ optional: false
+
+ - name: DJANGO_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: webapp-django-secrets
+ key: webapp-django-secret-key
+ # 'name' secret must exist & include that ^ key
+ optional: false
+
+
+ - name: DEPOSIT_PASSWORD
+ valueFrom:
+ secretKeyRef:
+ name: deposit-secrets
+ key: password
+ # 'name' secret must exist & include that ^ key
+ optional: false
+ - name: DEPOSIT_USERNAME
+ valueFrom:
+ secretKeyRef:
+ name: deposit-secrets
+ key: username
+ # 'name' secret must exist & include that ^ key
+ optional: false
+
+
+ - name: GIVE_PRIVATE_TOKEN
+ valueFrom:
+ secretKeyRef:
+ name: web-give-secrets
+ key: private-token
+ # 'name' secret must exist & include that ^ key
+ optional: false
+ - name: GIVE_PUBLIC_KEY
+ valueFrom:
+ secretKeyRef:
+ name: web-give-secrets
+ key: public-key
+ # 'name' secret must exist & include that ^ key
+ optional: false
+
+ volumeMounts:
+ - name: configuration
+ mountPath: /etc/swh
+ - name: configuration-template
+ mountPath: /etc/swh/configuration-template
+ - name: prepare-static
+ image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231004.3
+ imagePullPolicy: IfNotPresent
+ command:
+ - /bin/bash
+ args:
+ - -c
+ - cp -r $PWD/.local/share/swh/web/static/ /usr/share/swh/web/static/
+ volumeMounts:
+ - name: static
+ mountPath: /usr/share/swh/web/static
+ containers:
+ - name: web
+ resources:
+ requests:
+ memory: 50Mi
+ cpu: 50m
+ image: container-registry.softwareheritage.org/swh/infra/swh-apps/web:20231004.3
+ imagePullPolicy: IfNotPresent
+ ports:
+ - containerPort: 5004
+ name: webapp
+ readinessProbe:
+ httpGet:
+ path: /
+ port: webapp
+ httpHeaders:
+ - name: Host
+ value:
+ initialDelaySeconds: 5
+ failureThreshold: 30
+ periodSeconds: 10
+ timeoutSeconds: 30
+ livenessProbe:
+ httpGet:
+ path: /
+ port: webapp
+ httpHeaders:
+ - name: Host
+ value:
+ initialDelaySeconds: 3
+ periodSeconds: 10
+ timeoutSeconds: 30
+ command:
+ - /bin/bash
+ args:
+ - -c
+ - /opt/swh/entrypoint.sh
+ env:
+ - name: STATSD_HOST
+ value: prometheus-statsd-exporter
+ - name: STATSD_PORT
+ value: "9125"
+ - name: LOG_LEVEL
+ value: "INFO"
+ - name: SWH_CONFIG_FILENAME
+ value: /etc/swh/config.yml
+
+ - name: DJANGO_SECRET_KEY
+ valueFrom:
+ secretKeyRef:
+ name: webapp-django-secrets
+ key: webapp-django-secret-key
+ # 'name' secret must exist & include that ^ key
+ optional: false
+
+ volumeMounts:
+ - name: configuration
+ mountPath: /etc/swh
+ readOnly: true
+ - name: nginx
+ resources:
+ requests:
+ memory: 50Mi
+ cpu: 50m
+ image: nginx:bullseye
+ imagePullPolicy: IfNotPresent
+ ports:
+ - containerPort: 80
+ name: webstatic
+ readinessProbe:
+ httpGet:
+ path: static/robots.txt
+ port: webstatic
+ initialDelaySeconds: 5
+ failureThreshold: 30
+ periodSeconds: 10
+ livenessProbe:
+ httpGet:
+ path: static/robots.txt
+ port: webstatic
+ initialDelaySeconds: 3
+ periodSeconds: 10
+ volumeMounts:
+ - name: static
+ mountPath: /usr/share/nginx/html
+ volumes:
+ - name: configuration
+ emptyDir: {}
+ - name: configuration-template
+ configMap:
+ name: web-configuration-template
+ items:
+ - key: "config.yml.template"
+ path: "config.yml.template"
+ - name: static
+ emptyDir: {}
+---
+# Source: swh/templates/web/autoscaling.yaml
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+ namespace: swh
+ name: web
+ labels:
+ app: web
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: web
+ minReplicas: 1
+ maxReplicas: 2
+ metrics:
+ - type: Resource
+ resource:
+ name: cpu
+ target:
+ type: Utilization
+ averageUtilization: 50
+---
+# Source: swh/templates/web/ingress.yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ namespace: swh
+ name: swh-web-ingress
+spec:
+ rules:
+ - http:
+ paths:
+ - path: /
+ pathType: Prefix
+ backend:
+ service:
+ name: web
+ port:
+ number: 5004
+ - path: /static
+ pathType: Prefix
+ backend:
+ service:
+ name: web
+ port:
+ number: 80
+ host:
+---
# Source: swh/charts/keda/templates/metrics-server/apiservice.yaml
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
annotations:
labels:
app.kubernetes.io/name: v1beta1.external.metrics.k8s.io
helm.sh/chart: keda-2.11.0
app.kubernetes.io/component: operator
app.kubernetes.io/managed-by: Helm
------------- diff for swh/values/production-cassandra.yaml -------------
--- /tmp/swh-chart.swh.9h65qILO/production-cassandra.yaml.before 2023-10-05 15:57:38.808596410 +0200
+++ /tmp/swh-chart.swh.9h65qILO/production-cassandra.yaml.after 2023-10-05 15:57:39.956597808 +0200
@@ -12645,21 +12645,20 @@
# Source: swh/templates/web/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: swh-cassandra
name: web
labels:
app: web
spec:
revisionHistoryLimit: 2
- replicas: 2
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
template:
metadata:
labels:
@@ -12842,20 +12841,43 @@
emptyDir: {}
- name: configuration-template
configMap:
name: web-configuration-template
items:
- key: "config.yml.template"
path: "config.yml.template"
- name: static
emptyDir: {}
---
+# Source: swh/templates/web/autoscaling.yaml
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+ namespace: swh-cassandra
+ name: web
+ labels:
+ app: web
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: web
+ minReplicas: 2
+ maxReplicas: 4
+ metrics:
+ - type: Resource
+ resource:
+ name: cpu
+ target:
+ type: Utilization
+ averageUtilization: 50
+---
# Source: swh/templates/graphql/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: swh-cassandra
name: graphql-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
------------- diff for swh/values/production.yaml -------------
No differences
------------- diff for swh/values/staging-cassandra.yaml -------------
--- /tmp/swh-chart.swh.9h65qILO/staging-cassandra.yaml.before 2023-10-05 15:57:39.276596979 +0200
+++ /tmp/swh-chart.swh.9h65qILO/staging-cassandra.yaml.after 2023-10-05 15:57:40.436598393 +0200
@@ -19450,21 +19450,20 @@
# Source: swh/templates/web/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: swh-cassandra
name: web
labels:
app: web
spec:
revisionHistoryLimit: 2
- replicas: 2
selector:
matchLabels:
app: web
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
template:
metadata:
labels:
@@ -19670,20 +19669,43 @@
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 150
---
+# Source: swh/templates/web/autoscaling.yaml
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+ namespace: swh-cassandra
+ name: web
+ labels:
+ app: web
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: web
+ minReplicas: 2
+ maxReplicas: 3
+ metrics:
+ - type: Resource
+ resource:
+ name: cpu
+ target:
+ type: Utilization
+ averageUtilization: 50
+---
# Source: swh/templates/graphql/ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: swh-cassandra
name: graphql-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
------------- diff for swh/values/staging.yaml -------------
No differences