Skip to content

swh/production: Deploy a read-only storage backed by cassandra and AWS for content

Vincent Sellier requested to merge production-cassandra-ro-storage into production
  • Create an ingress to expose it from internet
  • Add an obstorage configuration using AWS as main backend and falling back to local and azure
  • Update the winery replayers to use this storage configuration, it should reduce the not found contents

Related to swh/infra/sysadm-environment#5199 (closed)

helm diff
[swh] Comparing changes between branches production and production-cassandra-ro-storage (per environment)...
Your branch is up to date with 'origin/production'.
[swh] Generate config in production branch for environment staging, namespace swh...
[swh] Generate config in production branch for environment staging, namespace swh-cassandra...
[swh] Generate config in production branch for environment staging, namespace swh-cassandra-next-version...
[swh] Generate config in production-cassandra-ro-storage branch for environment staging...
[swh] Generate config in production-cassandra-ro-storage branch for environment staging...
[swh] Generate config in production-cassandra-ro-storage branch for environment staging...
Your branch is up to date with 'origin/production'.
[swh] Generate config in production branch for environment production, namespace swh...
[swh] Generate config in production branch for environment production, namespace swh-cassandra...
[swh] Generate config in production branch for environment production, namespace swh-cassandra-next-version...
[swh] Generate config in production-cassandra-ro-storage branch for environment production...
[swh] Generate config in production-cassandra-ro-storage branch for environment production...
[swh] Generate config in production-cassandra-ro-storage branch for environment production...


------------- diff for environment staging namespace swh -------------

No differences


------------- diff for environment staging namespace swh-cassandra -------------

No differences


------------- diff for environment staging namespace swh-cassandra-next-version -------------

No differences


------------- diff for environment production namespace swh -------------

--- /tmp/swh-chart.swh.Zq94ItCp/production-swh.before	2024-01-10 09:50:57.535644367 +0100
+++ /tmp/swh-chart.swh.Zq94ItCp/production-swh.after	2024-01-10 09:50:58.475647273 +0100
@@ -5063,20 +5063,90 @@
           cls: http
           compression: gzip
           timeout: 120
           url: https://softwareheritage.s3.amazonaws.com/content/
       - cls: filtered
         filters_conf:
         - type: readonly
         storage_conf:
           cls: remote
           url: http://objstorage-read-only-rpc-ingress
+      - cls: filtered
+        filters_conf:
+        - type: readonly
+        storage_conf:
+          accounts:
+            "0":
+              account_name: ${ACCOUNT_NAME_0}
+              api_secret_key: ${API_SECRET_KEY_0}
+              container_name: contents
+            "1":
+              account_name: ${ACCOUNT_NAME_1}
+              api_secret_key: ${API_SECRET_KEY_1}
+              container_name: contents
+            "2":
+              account_name: ${ACCOUNT_NAME_2}
+              api_secret_key: ${API_SECRET_KEY_2}
+              container_name: contents
+            "3":
+              account_name: ${ACCOUNT_NAME_3}
+              api_secret_key: ${API_SECRET_KEY_3}
+              container_name: contents
+            "4":
+              account_name: ${ACCOUNT_NAME_4}
+              api_secret_key: ${API_SECRET_KEY_4}
+              container_name: contents
+            "5":
+              account_name: ${ACCOUNT_NAME_5}
+              api_secret_key: ${API_SECRET_KEY_5}
+              container_name: contents
+            "6":
+              account_name: ${ACCOUNT_NAME_6}
+              api_secret_key: ${API_SECRET_KEY_6}
+              container_name: contents
+            "7":
+              account_name: ${ACCOUNT_NAME_7}
+              api_secret_key: ${API_SECRET_KEY_7}
+              container_name: contents
+            "8":
+              account_name: ${ACCOUNT_NAME_8}
+              api_secret_key: ${API_SECRET_KEY_8}
+              container_name: contents
+            "9":
+              account_name: ${ACCOUNT_NAME_9}
+              api_secret_key: ${API_SECRET_KEY_9}
+              container_name: contents
+            a:
+              account_name: ${ACCOUNT_NAME_10}
+              api_secret_key: ${API_SECRET_KEY_10}
+              container_name: contents
+            b:
+              account_name: ${ACCOUNT_NAME_11}
+              api_secret_key: ${API_SECRET_KEY_11}
+              container_name: contents
+            c:
+              account_name: ${ACCOUNT_NAME_12}
+              api_secret_key: ${API_SECRET_KEY_12}
+              container_name: contents
+            d:
+              account_name: ${ACCOUNT_NAME_13}
+              api_secret_key: ${API_SECRET_KEY_13}
+              container_name: contents
+            e:
+              account_name: ${ACCOUNT_NAME_14}
+              api_secret_key: ${API_SECRET_KEY_14}
+              container_name: contents
+            f:
+              account_name: ${ACCOUNT_NAME_15}
+              api_secret_key: ${API_SECRET_KEY_15}
+              container_name: contents
+          cls: azure-prefixed
     objstorage_dst:
       cls: remote
       url: http://gloin001.internal.cea.swh.network
     journal_client:
       brokers:
         - kafka1.internal.softwareheritage.org:9094
         - kafka2.internal.softwareheritage.org:9094
         - kafka3.internal.softwareheritage.org:9094
         - kafka4.internal.softwareheritage.org:9094
       auto_offset_reset: earliest
@@ -14989,21 +15059,21 @@
   strategy:
     type: RollingUpdate
     rollingUpdate:
       maxSurge: 1
   template:
     metadata:
       labels:
         app: objstorage-replayer-winery
       annotations:
         # Force a rollout upgrade if the configuration changes
-        checksum/config: ffd28337ea97519f06adef7eb049f052906c6148ce209a2db0d72d7cfd618bf1
+        checksum/config: 7bcc6d39d30a8a3b47994ca50ce5581f3f044d0def3c3f6715a1ee42b4fcc5bd
     spec:
       affinity:
         
         nodeAffinity:
           requiredDuringSchedulingIgnoredDuringExecution:
             nodeSelectorTerms:
             - matchExpressions:
               - key: swh/replayer
                 operator: In
                 values:
@@ -15026,20 +15096,244 @@
                 optional: false
           - name: BROKER_USER_PASSWORD
             valueFrom:
               secretKeyRef:
                 name: swh-archive-broker-secret
                 key: BROKER_USER_PASSWORD
                 # 'name' secret must exist & include that ^ key
                 optional: false
             
           
+          - name: ACCOUNT_NAME_0
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 0_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_1
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 1_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_10
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 10_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_11
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 11_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_12
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 12_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_13
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 13_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_14
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 14_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_15
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 15_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_2
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 2_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_3
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 3_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_4
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 4_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_5
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 5_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_6
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 6_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_7
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 7_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_8
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 8_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_9
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 9_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_0
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 0_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_1
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 1_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_10
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 10_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_11
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 11_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_12
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 12_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_13
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 13_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_14
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 14_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_15
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 15_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_2
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 2_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_3
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 3_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_4
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 4_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_5
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 5_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_6
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 6_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_7
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 7_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_8
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 8_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_9
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 9_api_secret_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: config-utils
             mountPath: /entrypoints
             readOnly: true


------------- diff for environment production namespace swh-cassandra -------------

--- /tmp/swh-chart.swh.Zq94ItCp/production-swh-cassandra.before	2024-01-10 09:50:57.787645146 +0100
+++ /tmp/swh-chart.swh.Zq94ItCp/production-swh-cassandra.after	2024-01-10 09:50:58.767648175 +0100
@@ -1097,20 +1097,139 @@
                 api_secret_key: ${API_SECRET_KEY_15}
                 container_name: contents
             cls: azure-prefixed
         - cls: filtered
           filters_conf:
           - type: readonly
           storage_conf:
             cls: remote
             url: http://objstorage.internal.softwareheritage.org:5003/
 ---
+# Source: swh/templates/storage/configmap.yaml
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: swh-cassandra
+  name: storage-cassandra-readonly-configuration-template
+data:
+  config.yml.template: |
+    storage:
+      cls: pipeline
+      steps:
+      - cls: retry
+      - cls: cassandra
+        hosts:
+        - cassandra01.internal.softwareheritage.org
+        - cassandra02.internal.softwareheritage.org
+        - cassandra03.internal.softwareheritage.org
+        - cassandra04.internal.softwareheritage.org
+        - cassandra05.internal.softwareheritage.org
+        - cassandra06.internal.softwareheritage.org
+        - cassandra07.internal.softwareheritage.org
+        - cassandra08.internal.softwareheritage.org
+        - cassandra09.internal.softwareheritage.org
+        - cassandra10.internal.softwareheritage.org
+        keyspace: swh
+        consistency_level: LOCAL_QUORUM
+        auth_provider:
+          cls: cassandra.auth.PlainTextAuthProvider
+          password: ${CASSANDRA_PASSWORD}
+          username: swh-ro
+      
+        objstorage:
+          cls: multiplexer
+          objstorages:
+          - cls: filtered
+            filters_conf:
+            - type: readonly
+            storage_conf:
+              cls: http
+              compression: gzip
+              timeout: 120
+              url: https://softwareheritage.s3.amazonaws.com/content/
+          - cls: filtered
+            filters_conf:
+            - type: readonly
+            storage_conf:
+              cls: remote
+              url: http://objstorage-read-only-rpc-ingress
+          - cls: filtered
+            filters_conf:
+            - type: readonly
+            storage_conf:
+              accounts:
+                "0":
+                  account_name: ${ACCOUNT_NAME_0}
+                  api_secret_key: ${API_SECRET_KEY_0}
+                  container_name: contents
+                "1":
+                  account_name: ${ACCOUNT_NAME_1}
+                  api_secret_key: ${API_SECRET_KEY_1}
+                  container_name: contents
+                "2":
+                  account_name: ${ACCOUNT_NAME_2}
+                  api_secret_key: ${API_SECRET_KEY_2}
+                  container_name: contents
+                "3":
+                  account_name: ${ACCOUNT_NAME_3}
+                  api_secret_key: ${API_SECRET_KEY_3}
+                  container_name: contents
+                "4":
+                  account_name: ${ACCOUNT_NAME_4}
+                  api_secret_key: ${API_SECRET_KEY_4}
+                  container_name: contents
+                "5":
+                  account_name: ${ACCOUNT_NAME_5}
+                  api_secret_key: ${API_SECRET_KEY_5}
+                  container_name: contents
+                "6":
+                  account_name: ${ACCOUNT_NAME_6}
+                  api_secret_key: ${API_SECRET_KEY_6}
+                  container_name: contents
+                "7":
+                  account_name: ${ACCOUNT_NAME_7}
+                  api_secret_key: ${API_SECRET_KEY_7}
+                  container_name: contents
+                "8":
+                  account_name: ${ACCOUNT_NAME_8}
+                  api_secret_key: ${API_SECRET_KEY_8}
+                  container_name: contents
+                "9":
+                  account_name: ${ACCOUNT_NAME_9}
+                  api_secret_key: ${API_SECRET_KEY_9}
+                  container_name: contents
+                a:
+                  account_name: ${ACCOUNT_NAME_10}
+                  api_secret_key: ${API_SECRET_KEY_10}
+                  container_name: contents
+                b:
+                  account_name: ${ACCOUNT_NAME_11}
+                  api_secret_key: ${API_SECRET_KEY_11}
+                  container_name: contents
+                c:
+                  account_name: ${ACCOUNT_NAME_12}
+                  api_secret_key: ${API_SECRET_KEY_12}
+                  container_name: contents
+                d:
+                  account_name: ${ACCOUNT_NAME_13}
+                  api_secret_key: ${API_SECRET_KEY_13}
+                  container_name: contents
+                e:
+                  account_name: ${ACCOUNT_NAME_14}
+                  api_secret_key: ${API_SECRET_KEY_14}
+                  container_name: contents
+                f:
+                  account_name: ${ACCOUNT_NAME_15}
+                  api_secret_key: ${API_SECRET_KEY_15}
+                  container_name: contents
+              cls: azure-prefixed
+---
 # Source: swh/templates/toolbox/configmap.yaml
 apiVersion: v1
 kind: ConfigMap
 metadata:
   name: toolbox-scrubber-storage-template
   namespace: swh-cassandra
 data:
   config.yml.template: |
     storage:
       cls: cassandra
@@ -1630,20 +1749,35 @@
   namespace: swh-cassandra
 spec:
   type: ClusterIP
   selector:
     app: storage-cassandra
   ports:
     - port: 5002
       targetPort: 5002
       name: rpc
 ---
+# Source: swh/templates/storage/service.yaml
+apiVersion: v1
+kind: Service
+metadata:
+  name: storage-cassandra-readonly
+  namespace: swh-cassandra
+spec:
+  type: ClusterIP
+  selector:
+    app: storage-cassandra-readonly
+  ports:
+    - port: 5002
+      targetPort: 5002
+      name: rpc
+---
 # Source: swh/templates/web/service.yaml
 apiVersion: v1
 kind: Service
 metadata:
   name: web-cassandra
   namespace: swh-cassandra
 spec:
   type: ClusterIP
   selector:
     app: web-cassandra
@@ -4204,20 +4338,390 @@
             path: "config.yml.template"
       - name: database-utils
         configMap:
           name: database-utils
           defaultMode: 0555
       - name: config-utils
         configMap:
           name: config-utils
           defaultMode: 0555
 ---
+# Source: swh/templates/storage/deployment.yaml
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  namespace: swh-cassandra
+  name: storage-cassandra-readonly
+  labels:
+    app: storage-cassandra-readonly
+spec:
+  revisionHistoryLimit: 2
+  selector:
+    matchLabels:
+      app: storage-cassandra-readonly
+  strategy:
+    type: RollingUpdate
+    rollingUpdate:
+      maxSurge: 1
+  template:
+    metadata:
+      labels:
+        app: storage-cassandra-readonly
+      annotations:
+        checksum/config: 796384ef18da68b142f6ab7936ad2bd770368a255c654162748ed8f7e21692a3
+        checksum/database-utils: 367f28d8854b3b188d7a45015752b10be8e691f0c3b2a21db02501e655b932f0
+        checksum/config-utils: 6293d71ddd4a7f401d1105bc7f7590fcead5a3a0c152fe46d7d407839ea9a1d6
+    spec:
+      affinity:
+        nodeAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+            nodeSelectorTerms:
+            - matchExpressions:
+              - key: swh/storage
+                operator: In
+                values:
+                - "true"
+      priorityClassName: swh-cassandra-frontend-rpc
+      initContainers:
+        - name: prepare-configuration
+          image: container-registry.softwareheritage.org/swh/infra/swh-apps/utils:20231211.1
+          imagePullPolicy: IfNotPresent
+          command:
+          - /entrypoints/prepare-configuration.sh
+          env:
+            
+          
+          - name: ACCOUNT_NAME_0
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 0_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_1
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 1_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_10
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 10_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_11
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 11_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_12
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 12_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_13
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 13_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_14
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 14_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_15
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 15_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_2
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 2_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_3
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 3_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_4
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 4_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_5
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 5_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_6
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 6_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_7
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 7_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_8
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 8_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: ACCOUNT_NAME_9
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 9_account_name
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_0
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 0_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_1
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 1_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_10
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 10_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_11
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 11_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_12
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 12_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_13
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 13_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_14
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 14_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_15
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 15_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_2
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 2_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_3
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 3_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_4
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 4_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_5
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 5_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_6
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 6_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_7
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 7_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_8
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 8_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: API_SECRET_KEY_9
+            valueFrom:
+              secretKeyRef:
+                name: swh-objstorage-config
+                key: 9_api_secret_key
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          - name: CASSANDRA_PASSWORD
+            valueFrom:
+              secretKeyRef:
+                name: common-secrets
+                key: cassandra-swh-ro-password
+                # 'name' secret must exist & include that ^ key
+                optional: false
+          volumeMounts:
+          - name: configuration
+            mountPath: /etc/swh
+          - name: configuration-template
+            mountPath: /etc/swh/configuration-template
+          - name: config-utils
+            mountPath: /entrypoints
+            readOnly: true
+        
+        - name: init-database
+          image: container-registry.softwareheritage.org/swh/infra/swh-apps/storage:20240108.3
+          imagePullPolicy: IfNotPresent
+          command:
+          - /usr/local/bin/python3
+          args:
+          - /entrypoints/init-keyspace.py
+          volumeMounts:
+          - name: configuration
+            mountPath: /etc/swh
+            readOnly: true
+          - name: database-utils
+            mountPath: /entrypoints
+            readOnly: true
+      containers:
+        - name: storage-cassandra-readonly
+          resources:
+            requests:
+              memory: 1500Mi
+              cpu: 500m
+          image: container-registry.softwareheritage.org/swh/infra/swh-apps/storage:20240108.3
+          imagePullPolicy: IfNotPresent
+          ports:
+            - containerPort: 5002
+              name: rpc
+          readinessProbe:
+            httpGet:
+              path: /
+              port: rpc
+            initialDelaySeconds: 15
+            failureThreshold: 30
+            periodSeconds: 5
+          livenessProbe:
+            httpGet:
+              path: /
+              port: rpc
+            initialDelaySeconds: 10
+            periodSeconds: 5
+          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_SENTRY_ENVIRONMENT
+              value: production
+            - name: SWH_MAIN_PACKAGE
+              value: swh.storage
+            - name: SWH_SENTRY_DSN
+              valueFrom:
+                secretKeyRef:
+                  name: common-secrets
+                  key: storage-sentry-dsn
+                  # 'name' secret should exist & include key
+                  # if the setting doesn't exist, sentry pushes will be disabled
+                  optional: true
+            - name: SWH_SENTRY_DISABLE_LOGGING_EVENTS
+              value: "true"
+          volumeMounts:
+          - name: configuration
+            mountPath: /etc/swh
+      volumes:
+      - name: configuration
+        emptyDir: {}
+      - name: configuration-template
+        configMap:
+          name: storage-cassandra-readonly-configuration-template
+          items:
+          - key: "config.yml.template"
+            path: "config.yml.template"
+      - name: database-utils
+        configMap:
+          name: database-utils
+          defaultMode: 0555
+      - name: config-utils
+        configMap:
+          name: config-utils
+          defaultMode: 0555
+---
 # Source: swh/templates/toolbox/deployment.yaml
 apiVersion: apps/v1
 kind: Deployment
 metadata:
   name: swh-toolbox
   namespace: swh-cassandra
   labels:
     app: swh-toolbox
 spec:
   revisionHistoryLimit: 2
@@ -4560,20 +5064,43 @@
         emptyDir: {}
       - name: configuration-template
         configMap:
          name: web-cassandra-configuration-template
          items:
          - key: "config.yml.template"
            path: "config.yml.template"
       - name: static
         emptyDir: {}
 ---
+# Source: swh/templates/storage/autoscaling.yaml
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+  namespace: swh-cassandra
+  name: storage-cassandra-readonly
+  labels:
+    app: storage-cassandra-readonly
+spec:
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: storage-cassandra-readonly
+  minReplicas: 1
+  maxReplicas: 3
+  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-cassandra
   labels:
     app: web-cassandra
 spec:
   scaleTargetRef:
@@ -4606,20 +5133,63 @@
     http:
       paths:
       - path: /graphql/
         pathType: Prefix
         backend:
           service:
             name: graphql-cassandra
             port:
               number: 5013
 ---
+# Source: swh/templates/storage/ingress.yaml
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  namespace: swh-cassandra
+  name: storage-cassandra-readonly-ingress-default
+  annotations:
+    nginx.ingress.kubernetes.io/client-body-buffer-size: 128K
+    nginx.ingress.kubernetes.io/proxy-body-size: 4G
+    nginx.ingress.kubernetes.io/proxy-buffering: "on"
+    # type of authentication
+    nginx.ingress.kubernetes.io/auth-type: basic
+    # an htpasswd file in the key auth within the secret
+    nginx.ingress.kubernetes.io/auth-secret-type: auth-file
+    # name of the secret that contains the user/password definitions
+    nginx.ingress.kubernetes.io/auth-secret: swh-cassandra/ingress-storage-auth-secrets
+    # message to display with an appropriate context why the authentication is required
+    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required'
+
+spec:
+  rules:
+  - host: storage.internal.softwareheritage.org
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: storage-cassandra-readonly
+            port:
+              number: 5002
+      
+  - host: storage-cassandra-read-only-rpc-ingress
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: storage-cassandra-readonly
+            port:
+              number: 5002
+---
 # Source: swh/templates/web/ingress.yaml
 apiVersion: networking.k8s.io/v1
 kind: Ingress
 metadata:
   namespace: swh-cassandra
   name: web-cassandra-ingress-default
   annotations:
     nginx.ingress.kubernetes.io/whitelist-source-range: 10.42.0.0/16,10.43.0.0/16,127.0.0.0/8,192.168.100.0/24,192.168.101.0/24,192.168.200.0/22,192.168.50.0/24
     cert-manager.io/cluster-issuer: letsencrypt-production-gandi
     kubernetes.io/ingress.class: nginx
Edited by Vincent Sellier

Merge request reports