Chapter 6. Configuring the database 6.1. Using an existing PostgreSQL database If you are using an externally managed PostgreSQL database, you must manually enable the pg_trgm extension for a successful deployment. Important You must not use the same externally managed PostgreSQL database for both Red Hat Quay and Clair deployments. Your PostgreSQL database must also not be shared with other workloads, as it might exhaust the natural connection limit on the PostgreSQL side when connection-intensive workloads, like Red Hat Quay or Clair, contend for resources. Additionally, pgBouncer is not supported with Red Hat Quay or Clair, so it is not an option to resolve this issue. Use the following procedure to deploy an existing PostgreSQL database. Procedure Create a config.yaml file with the necessary database fields. For example: Example config.yaml file: DB_URI: postgresql://test-quay-database:postgres@test-quay-database:5432/test-quay-database Create a Secret using the configuration file: Create a QuayRegistry.yaml file which marks the postgres component as unmanaged and references the created Secret . For example: Example quayregistry.yaml file apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: configBundleSecret: config-bundle-secret components: - kind: postgres managed: false steps Continue to the following sections to deploy the registry. 6.1.1. Database configuration This section describes the database configuration fields available for Red Hat Quay deployments. 6.1.1.1. Database URI With Red Hat Quay, connection to the database is configured by using the required DB_URI field. The following table describes the DB_URI configuration field: Table 6.1. Database URI Field Type Description DB_URI (Required) String The URI for accessing the database, including any credentials. Example DB_URI field: postgresql://quayuser:quaypass@quay-server.example.com:5432/quay 6.1.1.2. Database connection arguments Optional connection arguments are configured by the DB_CONNECTION_ARGS parameter. Some of the key-value pairs defined under DB_CONNECTION_ARGS are generic, while others are database specific. The following table describes database connection arguments: Table 6.2. Database connection arguments Field Type Description DB_CONNECTION_ARGS Object Optional connection arguments for the database, such as timeouts and SSL/TLS. .autorollback Boolean Whether to use thread-local connections. Should always be true .threadlocals Boolean Whether to use auto-rollback connections. Should always be true 6.1.1.2.1. PostgreSQL SSL/TLS connection arguments With SSL/TLS, configuration depends on the database you are deploying. The following example shows a PostgreSQL SSL/TLS configuration: DB_CONNECTION_ARGS: sslmode: verify-ca sslrootcert: /path/to/cacert The sslmode option determines whether, or with, what priority a secure SSL/TLS TCP/IP connection will be negotiated with the server. There are six modes: Table 6.3. SSL/TLS options Mode Description disable Your configuration only tries non-SSL/TLS connections. allow Your configuration first tries a non-SSL/TLS connection. Upon failure, tries an SSL/TLS connection. prefer (Default) Your configuration first tries an SSL/TLS connection. Upon failure, tries a non-SSL/TLS connection. require Your configuration only tries an SSL/TLS connection. If a root CA file is present, it verifies the certificate in the same way as if verify-ca was specified. verify-ca Your configuration only tries an SSL/TLS connection, and verifies that the server certificate is issued by a trusted certificate authority (CA). verify-full Only tries an SSL/TLS connection, and verifies that the server certificate is issued by a trusted CA and that the requested server hostname matches that in the certificate. For more information on the valid arguments for PostgreSQL, see Database Connection Control Functions . 6.1.1.2.2. MySQL SSL/TLS connection arguments The following example shows a sample MySQL SSL/TLS configuration: DB_CONNECTION_ARGS: ssl: ca: /path/to/cacert Information on the valid connection arguments for MySQL is available at Connecting to the Server Using URI-Like Strings or Key-Value Pairs . 6.1.2. Using the managed PostgreSQL database With Red Hat Quay 3.9, if your database is managed by the Red Hat Quay Operator, updating from Red Hat Quay 3.8 3.9 automatically handles upgrading PostgreSQL 10 to PostgreSQL 13. Important Users with a managed database are required to upgrade their PostgreSQL database from 10 13. If your Red Hat Quay and Clair databases are managed by the Operator, the database upgrades for each component must succeed for the 3.9.0 upgrade to be successful. If either of the database upgrades fail, the entire Red Hat Quay version upgrade fails. This behavior is expected. If you do not want the Red Hat Quay Operator to upgrade your PostgreSQL deployment from PostgreSQL 10 13, you must set the PostgreSQL parameter to managed: false in your quayregistry.yaml file. For more information about setting your database to unmanaged, see Using an existing Postgres database . Important It is highly recommended that you upgrade to PostgreSQL 13. PostgreSQL 10 had its final release on November 10, 2022 and is no longer supported. For more information, see the PostgreSQL Versioning Policy . If you want your PostgreSQL database to match the same version as your Red Hat Enterprise Linux (RHEL) system, see Migrating to a RHEL 8 version of PostgreSQL for RHEL 8 or Migrating to a RHEL 9 version of PostgreSQL for RHEL 9. For more information about the Red Hat Quay 3.8 3.9 procedure, see Upgrading the Red Hat Quay Operator overview . 6.1.2.1. PostgreSQL database recommendations The Red Hat Quay team recommends the following for managing your PostgreSQL database. Database backups should be performed regularly using either the supplied tools on the PostgreSQL image or your own backup infrastructure. The Red Hat Quay Operator does not currently ensure that the PostgreSQL database is backed up. Restoring the PostgreSQL database from a backup must be done using PostgreSQL tools and procedures. Be aware that your Quay pods should not be running while the database restore is in progress. Database disk space is allocated automatically by the Red Hat Quay Operator with 50 GiB. This number represents a usable amount of storage for most small to medium Red Hat Quay installations but might not be sufficient for your use cases. Resizing the database volume is currently not handled by the Red Hat Quay Operator. 6.2. Configuring external Redis Use the content in this section to set up an external Redis deployment. 6.2.1. Using an unmanaged Redis database Use the following procedure to set up an external Redis database. Procedure Create a config.yaml file using the following Redis fields: # ... BUILDLOGS_REDIS: host: <quay-server.example.com> port: 6379 ssl: false # ... USER_EVENTS_REDIS: host: <quay-server.example.com> port: 6379 ssl: false # ... Enter the following command to create a secret using the configuration file: USD oc create secret generic --from-file config.yaml=./config.yaml config-bundle-secret Create a quayregistry.yaml file that sets the Redis component to unmanaged and references the created secret: apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: configBundleSecret: config-bundle-secret components: - kind: redis managed: false # ... Deploy the Red Hat Quay registry. Additional resources Redis configuration fields 6.2.2. Using unmanaged Horizontal Pod Autoscalers Horizontal Pod Autoscalers (HPAs) are now included with the Clair , Quay , and Mirror pods, so that they now automatically scale during load spikes. As HPA is configured by default to be managed, the number of Clair , Quay , and Mirror pods is set to two. This facilitates the avoidance of downtime when updating or reconfiguring Red Hat Quay through the Operator or during rescheduling events. Note There is a known issue when disabling the HorizontalPodAutoscaler component and attempting to edit the HPA resource itself and increase the value of the minReplicas field. When attempting this setup, Quay application pods are scaled out by the unmanaged HPA and, after 60 seconds, the replica count is reconciled by the Red Hat Quay Operator. As a result, HPA pods are continuously created and then removed by the Operator. To resolve this issue, you should upgrade your Red Hat Quay deployment to at least version 3.12.5 or 3.13.1 and then use the following example to avoid the issue. This issue will be fixed in a future version of Red Hat Quay. For more information, see PROJQUAY-6474 . 6.2.2.1. Disabling the Horizontal Pod Autoscaler To disable autoscaling or create your own HorizontalPodAutoscaler component, specify the component as unmanaged in the QuayRegistry custom resource definition. To avoid the known issue noted above, you must modify the QuayRegistry CRD object and set the replicas equal to null for the quay , clair , and mirror components. Procedure Edit the QuayRegistry CRD to include the following replicas: null for the quay component: USD oc edit quayregistry <quay_registry_name> -n <quay_namespace> apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: quay-registry namespace: quay-enterprise spec: components: - kind: horizontalpodautoscaler managed: false - kind: quay managed: true overrides: replicas: null 1 - kind: clair managed: true overrides: replicas: null - kind: mirror managed: true overrides: replicas: null # ... 1 After setting replicas: null in your QuayRegistry CRD, a new replica set might be generated because the deployment manifest of the Quay app is changed with replicas: 1 . Verification Create a customized HorizontalPodAutoscalers CRD and increase the minReplicas amount to a higher value, for exampe, 3 : kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: quay-registry-quay-app namespace: quay-enterprise spec: scaleTargetRef: kind: Deployment name: quay-registry-quay-app apiVersion: apps/v1 minReplicas: 3 maxReplicas: 20 metrics: - type: Resource resource: name: memory target: type: Utilization averageUtilization: 90 - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 90 Ensure that your QuayRegistry application successfully starts by entering the following command: USD oc get pod | grep quay-app Example output quay-registry-quay-app-5b8fd49d6b-7wvbk 1/1 Running 0 34m quay-registry-quay-app-5b8fd49d6b-jslq9 1/1 Running 0 3m42s quay-registry-quay-app-5b8fd49d6b-pskpz 1/1 Running 0 43m quay-registry-quay-app-upgrade-llctl 0/1 Completed 0 51m Ensure that your HorizontalPodAutoscalers successfully starts by entering the following command: USD oc get hpa NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE quay-registry-quay-app Deployment/quay-registry-quay-app 67%/90%, 54%/90% 3 20 3 51m 6.2.3. Disabling the Route component Use the following procedure to prevent the Red Hat Quay Operator from creating a route. Procedure Set the component as managed: false in the quayregistry.yaml file: apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: components: - kind: route managed: false Edit the config.yaml file to specify that Red Hat Quay handles SSL/TLS. For example: # ... EXTERNAL_TLS_TERMINATION: false # ... SERVER_HOSTNAME: example-registry-quay-quay-enterprise.apps.user1.example.com # ... PREFERRED_URL_SCHEME: https # ... If you do not configure the unmanaged route correctly, the following error is returned: { { "kind":"QuayRegistry", "namespace":"quay-enterprise", "name":"example-registry", "uid":"d5879ba5-cc92-406c-ba62-8b19cf56d4aa", "apiVersion":"quay.redhat.com/v1", "resourceVersion":"2418527" }, "reason":"ConfigInvalid", "message":"required component `route` marked as unmanaged, but `configBundleSecret` is missing necessary fields" } Note Disabling the default route means you are now responsible for creating a Route , Service , or Ingress in order to access the Red Hat Quay instance. Additionally, whatever DNS you use must match the SERVER_HOSTNAME in the Red Hat Quay config. 6.2.4. Disabling the monitoring component If you install the Red Hat Quay Operator in a single namespace, the monitoring component is automatically set to managed: false . Use the following reference to explicitly disable monitoring. Unmanaged monitoring apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: components: - kind: monitoring managed: false To enable monitoring in this scenario, see Enabling monitoring when the Red Hat Quay Operator is installed in a single namespace . 6.2.5. Disabling the mirroring component To disable mirroring, use the following YAML configuration: Unmanaged mirroring example YAML configuration apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: components: - kind: mirroring managed: false

Commands:
DB_URI: postgresql://test-quay-database:postgres@test-quay-database:5432/test-quay-database
kubectl create secret generic --from-file config.yaml=./config.yaml config-bundle-secret
apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: configBundleSecret: config-bundle-secret components: - kind: postgres managed: false
DB_CONNECTION_ARGS: sslmode: verify-ca sslrootcert: /path/to/cacert
DB_CONNECTION_ARGS: ssl: ca: /path/to/cacert
BUILDLOGS_REDIS: host: <quay-server.example.com> port: 6379 ssl: false USER_EVENTS_REDIS: host: <quay-server.example.com> port: 6379 ssl: false
oc create secret generic --from-file config.yaml=./config.yaml config-bundle-secret
apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: configBundleSecret: config-bundle-secret components: - kind: redis managed: false
oc edit quayregistry <quay_registry_name> -n <quay_namespace>
apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: quay-registry namespace: quay-enterprise spec: components: - kind: horizontalpodautoscaler managed: false - kind: quay managed: true overrides: replicas: null 1 - kind: clair managed: true overrides: replicas: null - kind: mirror managed: true overrides: replicas: null
kind: HorizontalPodAutoscaler apiVersion: autoscaling/v2 metadata: name: quay-registry-quay-app namespace: quay-enterprise spec: scaleTargetRef: kind: Deployment name: quay-registry-quay-app apiVersion: apps/v1 minReplicas: 3 maxReplicas: 20 metrics: - type: Resource resource: name: memory target: type: Utilization averageUtilization: 90 - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 90
oc get pod | grep quay-app
quay-registry-quay-app-5b8fd49d6b-7wvbk 1/1 Running 0 34m quay-registry-quay-app-5b8fd49d6b-jslq9 1/1 Running 0 3m42s quay-registry-quay-app-5b8fd49d6b-pskpz 1/1 Running 0 43m quay-registry-quay-app-upgrade-llctl 0/1 Completed 0 51m
oc get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE quay-registry-quay-app Deployment/quay-registry-quay-app 67%/90%, 54%/90% 3 20 3 51m
apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: components: - kind: route managed: false
EXTERNAL_TLS_TERMINATION: false SERVER_HOSTNAME: example-registry-quay-quay-enterprise.apps.user1.example.com PREFERRED_URL_SCHEME: https
{ { "kind":"QuayRegistry", "namespace":"quay-enterprise", "name":"example-registry", "uid":"d5879ba5-cc92-406c-ba62-8b19cf56d4aa", "apiVersion":"quay.redhat.com/v1", "resourceVersion":"2418527" }, "reason":"ConfigInvalid", "message":"required component `route` marked as unmanaged, but `configBundleSecret` is missing necessary fields" }
apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: components: - kind: monitoring managed: false
apiVersion: quay.redhat.com/v1 kind: QuayRegistry metadata: name: example-registry namespace: quay-enterprise spec: components: - kind: mirroring managed: false