RUNBOOK – Backup Red Hat Quay (Operator + rclone)
RUNBOOK – Backup Red Hat Quay (Operator + rclone)
1. Placeholder
export QUAY_NAMESPACE=registryoc get quayregistry -Aexport QUAY_REGISTRY_NAME=$(oc get quayregistry -n $QUAY_NAMESPACE -o jsonpath='{.items[0].metadata.name}')export QUAY_OPERATOR_NAMESPACE=$(oc get pods -A | awk '/quay-operator/ {print $1; exit}')export QUAY_POD_NAME=$(oc get pod -n $QUAY_NAMESPACE -l app=quay -o jsonpath='{.items[0].metadata.name}')export POSTGRES_POD_NAME=$(oc get pod -n $QUAY_NAMESPACE -l quay-component=postgres -o jsonpath='{.items[0].metadata.name}')export DB_NAME=$(oc exec -n $QUAY_NAMESPACE $QUAY_POD_NAME -- grep '^DB_URI' /conf/stack/config.yaml | awk -F"/" '{print $4}')2. Backup configurazione
oc get quayregistry $QUAY_REGISTRY_NAME -n $QUAY_NAMESPACE -o yaml > quay-registry.yamlyq -i ' del( .status, .metadata.creationTimestamp, .metadata.finalizers, .metadata.generation, .metadata.resourceVersion, .metadata.uid, .metadata.annotations."kubectl.kubernetes.io/last-applied-configuration" )' quay-registry.yaml
oc get secret -n $QUAY_NAMESPACE ${QUAY_REGISTRY_NAME}-quay-registry-managed-secret-keys -o yaml > managed_secret_keys.yamlyq -i ' .metadata |= { "name": .name, "namespace": .namespace }' managed_secret_keys.yaml
oc get secret -n $QUAY_NAMESPACE $(oc get quayregistry $QUAY_REGISTRY_NAME -n $QUAY_NAMESPACE -o jsonpath='{.spec.configBundleSecret}') -o yaml > config-bundle.yamloc exec -n $QUAY_NAMESPACE $QUAY_POD_NAME -- cat /conf/stack/config.yaml > quay_config.yaml3. Scale down
Impostare repliche a 0 per quay / mirror / clair (Operator ≥ 3.7)
oc patch quayregistry registry -n ns --type=merge -p 'spec: components: - kind: horizontalpodautoscaler managed: false - kind: quay managed: true overrides: replicas: 0 - kind: clair managed: true overrides: replicas: 0 - kind: mirror managed: true overrides: replicas: 0'4. Backup database
oc exec -n $QUAY_NAMESPACE $POSTGRES_POD_NAME -- pg_dump -C $DB_NAME > quay-db-backup.sql5. Backup blob con rclone
export AWS_ACCESS_KEY_ID=$(oc get secret -l app=noobaa -n $QUAY_NAMESPACE -o jsonpath='{.items[0].data.AWS_ACCESS_KEY_ID}' | base64 -d)export AWS_SECRET_ACCESS_KEY=$(oc get secret -l app=noobaa -n $QUAY_NAMESPACE -o jsonpath='{.items[0].data.AWS_SECRET_ACCESS_KEY}' | base64 -d)export S3_ENDPOINT=https://$(oc get route s3 -n openshift-storage -o jsonpath='{.spec.host}')export BUCKET_NAME=$(oc get cm -l app=noobaa -n $QUAY_NAMESPACE -o jsonpath='{.items[0].data.BUCKET_NAME}')
rclone config create quay-noobaa s3 provider Other env_auth false access_key_id $AWS_ACCESS_KEY_ID secret_access_key $AWS_SECRET_ACCESS_KEY endpoint $S3_ENDPOINT region us-east-1
mkdir -p blobsrclone sync quay-noobaa:$BUCKET_NAME blobs --progress --checksum --no-check-certificate6. Scale up e verifica
oc wait quayregistry $QUAY_REGISTRY_NAME --for=condition=Available=true -n $QUAY_NAMESPACEBackup completato
Runbook — Modifica configurazione LDAP in Red Hat Quay su OpenShift
Obiettivo
Modificare la configurazione LDAP di Red Hat Quay installato su OpenShift tramite Quay Operator.
Nel deployment Operator-based, la configurazione di Quay è contenuta nel file:
config.yamlIl file config.yaml è salvato dentro una Kubernetes/OpenShift Secret referenziata dalla CR:
QuayRegistry.spec.configBundleSecretIl metodo consigliato è:
- individuare la
QuayRegistry; - recuperare il
configBundleSecretattuale; - estrarre il
config.yaml; - modificarlo;
- creare una nuova Secret;
- patchare la
QuayRegistryper usare la nuova Secret; - verificare redeploy e login LDAP;
- in caso di problema, fare rollback alla Secret precedente.
Prerequisiti
Eseguire i comandi da una macchina dove sia disponibile oc e dove si sia già loggati al cluster:
oc whoamioc whoami --show-serverVerificare di avere permessi sul namespace dove è installato Quay:
oc get quayregistry -A1. Individuare namespace e nome della QuayRegistry
oc get quayregistry -AEsempio output:
NAMESPACE NAMEquay quay-registryImpostare le variabili:
NS=quayQR=quay-registryVerificare:
oc get quayregistry "$QR" -n "$NS" -o yaml2. Recuperare il configBundleSecret attuale
SECRET=$(oc get quayregistry "$QR" -n "$NS" -o jsonpath='{.spec.configBundleSecret}')echo "$SECRET"Verificare che la Secret esista:
oc get secret "$SECRET" -n "$NS"Verificare che contenga config.yaml:
oc get secret "$SECRET" -n "$NS" -o jsonpath='{.data}' | jq keysOutput atteso, indicativamente:
[ "config.yaml"]3. Estrarre il config.yaml attuale
Creare una directory di lavoro:
mkdir -p ~/quay-ldap-changecd ~/quay-ldap-changeEstrarre il file config.yaml dalla Secret:
oc get secret "$SECRET" -n "$NS" \ -o jsonpath='{.data.config\.yaml}' | base64 -d > config.yamlCreare backup locale:
cp config.yaml config.yaml.backup.$(date +%Y%m%d-%H%M%S)Verificare il contenuto:
less config.yaml4. Modificare il config.yaml
Aprire il file:
vi config.yamlLa configurazione LDAP deve contenere o aggiornare parametri simili ai seguenti.
Esempio LDAP semplice
AUTHENTICATION_TYPE: LDAP
LDAP_URI: "ldap://ldap.example.local"LDAP_BASE_DN: - dc=example - dc=localLDAP_USER_RDN: - ou=UsersLDAP_UID_ATTR: uidLDAP_EMAIL_ATTR: mailLDAP_ADMIN_DN: "cn=quay-bind,ou=ServiceAccounts,dc=example,dc=local"LDAP_ADMIN_PASSWD: "password-bind-ldap"LDAP_ALLOW_INSECURE_FALLBACK: falseLDAP_USER_FILTER: "(memberOf=cn=quay-users,ou=Groups,dc=example,dc=local)"Esempio LDAPS
AUTHENTICATION_TYPE: LDAP
LDAP_URI: "ldaps://ldap.example.local"LDAP_BASE_DN: - dc=example - dc=localLDAP_USER_RDN: - ou=UsersLDAP_UID_ATTR: uidLDAP_EMAIL_ATTR: mailLDAP_ADMIN_DN: "cn=quay-bind,ou=ServiceAccounts,dc=example,dc=local"LDAP_ADMIN_PASSWD: "password-bind-ldap"LDAP_ALLOW_INSECURE_FALLBACK: falseLDAP_USER_FILTER: "(memberOf=cn=quay-users,ou=Groups,dc=example,dc=local)"5. Validare il file YAML
Metodo con Python:
python3 - <<'PY'import yamlwith open("config.yaml") as f: yaml.safe_load(f)print("YAML OK")PYSe il modulo yaml non è disponibile, usare Ruby:
ruby -e "require 'yaml'; YAML.load_file('config.yaml'); puts 'YAML OK'"In alternativa, se disponibile:
yq e '.' config.yaml >/dev/null && echo "YAML OK"6. Creare una nuova Secret con il config.yaml modificato
Consigliato: creare una nuova Secret invece di modificare direttamente quella esistente.
In questo modo il rollback è immediato.
NEW_SECRET="${QR}-config-bundle-ldap-$(date +%Y%m%d%H%M%S)"
oc create secret generic "$NEW_SECRET" \ -n "$NS" \ --from-file=config.yaml=./config.yamlVerificare:
oc get secret "$NEW_SECRET" -n "$NS"Verificare che la Secret contenga il config.yaml:
oc get secret "$NEW_SECRET" -n "$NS" -o jsonpath='{.data}' | jq keys7. Patch della QuayRegistry
Applicare la nuova Secret alla QuayRegistry:
oc patch quayregistry "$QR" -n "$NS" --type=merge \ -p "{\"spec\":{\"configBundleSecret\":\"$NEW_SECRET\"}}"Verificare che la CR punti alla nuova Secret:
oc get quayregistry "$QR" -n "$NS" \ -o jsonpath='{.spec.configBundleSecret}{"\n"}'Output atteso:
quay-registry-config-bundle-ldap-YYYYMMDDHHMMSS8. Monitorare il redeploy
Monitorare i pod:
oc get pods -n "$NS" -wIn un altro terminale, controllare lo stato della QuayRegistry:
oc get quayregistry "$QR" -n "$NS" -o yaml | \ egrep -i "phase|message|condition|configBundleSecret" -A3 -B3Controllare i Deployment Quay:
oc get deploy -n "$NS" | grep -i quayIndividuare il deployment applicativo:
APP_DEPLOY=$(oc get deploy -n "$NS" -o name | grep quay-app | head -1)echo "$APP_DEPLOY"Leggere i log:
oc logs -n "$NS" "$APP_DEPLOY" --tail=200Filtrare eventuali errori LDAP/autenticazione:
oc logs -n "$NS" "$APP_DEPLOY" --tail=500 | \ egrep -i "ldap|auth|bind|user|error|invalid|failed"9. Test login LDAP
Dopo il redeploy:
- aprire la UI di Quay;
- provare login con un utente LDAP autorizzato;
- verificare eventuali errori nei log.
Comando utile durante il test:
oc logs -n "$NS" "$APP_DEPLOY" --tail=500 | \ egrep -i "ldap|auth|bind|user|error|invalid|failed"10. Rollback immediato
Se il login LDAP non funziona o Quay presenta problemi, tornare alla Secret precedente.
La variabile $SECRET contiene il vecchio configBundleSecret, recuperato all’inizio.
oc patch quayregistry "$QR" -n "$NS" --type=merge \ -p "{\"spec\":{\"configBundleSecret\":\"$SECRET\"}}"Verificare:
oc get quayregistry "$QR" -n "$NS" \ -o jsonpath='{.spec.configBundleSecret}{"\n"}'Monitorare il redeploy:
oc get pods -n "$NS" -wControllare log:
oc logs -n "$NS" "$APP_DEPLOY" --tail=30011. Script unico operativo
Cambiare solo
NSeQRall’inizio.
#!/usr/bin/env bashset -euo pipefail
# ============================================================# Modifica LDAP Red Hat Quay via Quay Operator# ============================================================
NS=quayQR=quay-registry
echo "[INFO] Namespace Quay: $NS"echo "[INFO] QuayRegistry: $QR"
echo "[INFO] Recupero configBundleSecret attuale..."SECRET=$(oc get quayregistry "$QR" -n "$NS" -o jsonpath='{.spec.configBundleSecret}')
if [[ -z "$SECRET" ]]; then echo "[ERROR] Impossibile recuperare spec.configBundleSecret dalla QuayRegistry $QR nel namespace $NS" exit 1fi
echo "[INFO] Current configBundleSecret: $SECRET"
WORKDIR="$HOME/quay-ldap-change"mkdir -p "$WORKDIR"cd "$WORKDIR"
echo "[INFO] Estraggo config.yaml..."oc get secret "$SECRET" -n "$NS" \ -o jsonpath='{.data.config\.yaml}' | base64 -d > config.yaml
BACKUP_FILE="config.yaml.backup.$(date +%Y%m%d-%H%M%S)"cp config.yaml "$BACKUP_FILE"
echo "[INFO] Backup creato: $WORKDIR/$BACKUP_FILE"echo "[INFO] Modifica ora il file config.yaml"echo
vi config.yaml
echo "[INFO] Validazione YAML..."
if command -v python3 >/dev/null 2>&1; then python3 - <<'PY'import yamlwith open("config.yaml") as f: yaml.safe_load(f)print("YAML OK")PYelif command -v ruby >/dev/null 2>&1; then ruby -e "require 'yaml'; YAML.load_file('config.yaml'); puts 'YAML OK'"elif command -v yq >/dev/null 2>&1; then yq e '.' config.yaml >/dev/null && echo "YAML OK"else echo "[WARN] Nessun validatore YAML trovato tra python3/ruby/yq. Procedo senza validazione automatica."fi
NEW_SECRET="${QR}-config-bundle-ldap-$(date +%Y%m%d%H%M%S)"
echo "[INFO] Creo nuova Secret: $NEW_SECRET"
oc create secret generic "$NEW_SECRET" \ -n "$NS" \ --from-file=config.yaml=./config.yaml
echo "[INFO] Patch QuayRegistry con nuova Secret..."
oc patch quayregistry "$QR" -n "$NS" --type=merge \ -p "{\"spec\":{\"configBundleSecret\":\"$NEW_SECRET\"}}"
echo "[INFO] Nuovo configBundleSecret applicato:"oc get quayregistry "$QR" -n "$NS" \ -o jsonpath='{.spec.configBundleSecret}{"\n"}'
echoecho "[INFO] Pod Quay:"oc get pods -n "$NS"
echoecho "[INFO] Per monitorare il redeploy:"echo "oc get pods -n $NS -w"
echoecho "[INFO] Per rollback:"echo "oc patch quayregistry $QR -n $NS --type=merge -p '{\"spec\":{\"configBundleSecret\":\"$SECRET\"}}'"12. Comandi rapidi di troubleshooting
Vedere la Secret attualmente usata
oc get quayregistry "$QR" -n "$NS" \ -o jsonpath='{.spec.configBundleSecret}{"\n"}'Estrarre e vedere il config.yaml attivo
ACTIVE_SECRET=$(oc get quayregistry "$QR" -n "$NS" -o jsonpath='{.spec.configBundleSecret}')
oc get secret "$ACTIVE_SECRET" -n "$NS" \ -o jsonpath='{.data.config\.yaml}' | base64 -d | lessCercare solo la parte LDAP
ACTIVE_SECRET=$(oc get quayregistry "$QR" -n "$NS" -o jsonpath='{.spec.configBundleSecret}')
oc get secret "$ACTIVE_SECRET" -n "$NS" \ -o jsonpath='{.data.config\.yaml}' | base64 -d | \ egrep -i "AUTHENTICATION_TYPE|LDAP_"Controllare i pod Quay
oc get pods -n "$NS" -o wideControllare deployment Quay
oc get deploy -n "$NS" | grep -i quayControllare log applicativi
APP_DEPLOY=$(oc get deploy -n "$NS" -o name | grep quay-app | head -1)
oc logs -n "$NS" "$APP_DEPLOY" --tail=300Cercare errori LDAP
oc logs -n "$NS" "$APP_DEPLOY" --tail=500 | \ egrep -i "ldap|auth|bind|user|error|invalid|failed"13. Note operative importanti
Non modificare i pod direttamente
Non modificare file dentro i pod Quay, perché:
- i pod possono essere ricreati;
- la configurazione è gestita dall’Operator;
- la sorgente corretta è il
configBundleSecret.
Preferire nuova Secret invece di edit della Secret esistente
È possibile modificare direttamente la Secret, ma è più sicuro creare una nuova Secret e patchare la QuayRegistry.
Vantaggi:
- rollback immediato;
- storico più chiaro;
- minore rischio operativo.
Attenzione a utenti locali già esistenti
Se Quay aveva già utenti locali e si passa ad autenticazione LDAP, verificare eventuali conflitti di username.
Attenzione a LDAPS e CA
Se si usa ldaps://, verificare che Quay si fidi della CA del server LDAP/AD.
In caso di CA custom, potrebbe essere necessario aggiungere la CA nel bundle di configurazione, in base alla configurazione già presente del registry.
14. Riferimenti utili
- Red Hat Quay Operator su OpenShift:
- Configurazione Red Hat Quay:
- Project Quay documentation: