github.com/openshift/installer@v1.4.17/docs/user/openstack/image-registry-storage-swift.md (about) 1 # Migrate the Image Registry from Cinder to Swift 2 3 This document describes: 4 * [Migrating existing images to a new Swift container](#migrate-the-images-from-the-volume-to-swift) 5 * [Setting Swift as the Image Registry backend](#switch-to-swift-as-the-image-registry-storage-backend) 6 * [Aborting the migration to return to the volume backend](#abort-the-migration-and-return-to-the-volume-backend) 7 8 The persistent volume backend does not support multiple replicas by default, 9 because they typically only allow one read-write client at once. Object storage 10 does allow for multiple Image Registry replicas. 11 12 The migration as described only incur minimal downtime; however, the registry 13 will be set to read-only mode during data migration. 14 15 ## Migrate the images from the volume to Swift 16 17 As the first step, create the Swift container that will consitute the new Image 18 Registry backend. In order for it to be garbage-collected by the OpenShift 19 installer in case of `destroy`, it has to have a specific name and specific 20 properties (the suffix "aaa" here is arbitrary): 21 22 ```shell 23 infrastructure_name="$(oc get infrastructure/cluster -o jsonpath='{.status.infrastructureName}')" 24 container_name="${infrastructure_name}-image-registry-aaa" 25 openstack container create "$container_name" 26 openstack container set --property Name="$container_name" --property Openshiftclusterid="$infrastructure_name" "$container_name" 27 ``` 28 29 Then, build the container image that will perform the migration from within the 30 cluster. 31 32 The container will mount two volumes: 33 * one volume with the OpenStack credentials 34 * the current Image Registry storage, mounted read-only mode. 35 36 The example below reads the credentials and makes them available to the Swift 37 client. Then the Swift client moves data from the registry volume to the new 38 Swift container. 39 40 Build and upload the image to a registry your OpenShift instance has access to. 41 It can also be OpenShift's Image Registry itself. We will use 42 `quay.io/shiftstack/image-registry-migrator:v1` in our example. 43 44 ```Containerfile 45 # Containerfile 46 FROM registry.access.redhat.com/ubi9/ubi:latest 47 48 RUN dnf -y install python3-pip jq 49 50 RUN pip install python-keystoneclient python-swiftclient yq 51 52 RUN true \ 53 && echo $'export OS_AUTH_URL="$(yq -r \'.clouds.openstack.auth.auth_url // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 54 && echo $'export OS_IDENTITY_API_VERSION="$(yq -r \'.clouds.openstack.identity_api_version // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 55 && echo $'export OS_REGION_NAME="$(yq -r \'.clouds.openstack.region_name // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 56 && echo $'export OS_AUTH_TYPE="$(yq -r \'.clouds.openstack.auth_type // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 57 && echo $'' >> /migrate.sh \ 58 && echo $'if [ "$OS_AUTH_TYPE" == "v3applicationcredential" ]; then' >> /migrate.sh \ 59 && echo $' export OS_APPLICATION_CREDENTIAL_ID="$(yq -r \'.clouds.openstack.auth.application_credential_id // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 60 && echo $' export OS_APPLICATION_CREDENTIAL_NAME="$(yq -r \'.clouds.openstack.auth.application_credential_name // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 61 && echo $' export OS_APPLICATION_CREDENTIAL_SECRET="$(yq -r \'.clouds.openstack.auth.application_credential_secret // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 62 && echo $'else' >> /migrate.sh \ 63 && echo $' export OS_USERNAME="$(yq -r \'.clouds.openstack.auth.username // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 64 && echo $' export OS_PASSWORD="$(yq -r \'.clouds.openstack.auth.password // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 65 && echo $' export OS_USER_DOMAIN_NAME="$(yq -r \'.clouds.openstack.auth.user_domain_name // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 66 && echo $' export OS_PROJECT_ID="$(yq -r \'.clouds.openstack.auth.project_id // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 67 && echo $' export OS_PROJECT_NAME="$(yq -r \'.clouds.openstack.auth.project_name // empty\' /etc/openstack/clouds.yaml)"' >> /migrate.sh \ 68 && echo $'fi' >> /migrate.sh \ 69 && echo $'' >> /migrate.sh \ 70 && echo $'swift upload "$REGISTRY_STORAGE_SWIFT_CONTAINER" /files' >> /migrate.sh \ 71 && chmod +x /migrate.sh 72 73 CMD [ "/migrate.sh" ] 74 ``` 75 76 Here is the definition of the pod that will run the container. Replace the 77 example image name `quay.io/shiftstack/image-registry-migrator:v1` in the last 78 line with your own image. Also replace `openshift-lrgv9-image-registry-aaa` 79 with the `$container_name` above: 80 81 ```yaml 82 # image-migration-pod.yaml 83 kind: Pod 84 apiVersion: v1 85 metadata: 86 name: image-registry-migration 87 namespace: openshift-image-registry 88 labels: 89 app: image-registry-migration 90 annotations: 91 openshift.io/scc: anyuid 92 spec: 93 volumes: 94 - name: old-registry 95 persistentVolumeClaim: 96 claimName: image-registry-storage 97 - name: openstack 98 secret: 99 secretName: installer-cloud-credentials 100 restartPolicy: OnFailure 101 serviceAccountName: default 102 terminationGracePeriodSeconds: 30 103 containers: 104 - name: migrate-ir 105 imagePullPolicy: Always 106 volumeMounts: 107 - name: old-registry 108 readOnly: true 109 mountPath: /files 110 - name: openstack 111 mountPath: "/etc/openstack" 112 readOnly: true 113 image: quay.io/shiftstack/image-registry-migrator:v1 114 env: 115 - name: REGISTRY_STORAGE_SWIFT_CONTAINER 116 value: openshift-lrgv9-image-registry-aaa 117 ``` 118 119 **In order to avoid corruption of existing data during the migration, switch 120 the Image Registry to read-only mode.** Note that this action restarts the one 121 Image Registry replica available at this point; this means a brief downtime. 122 123 ```shell 124 oc patch configs.imageregistry.operator.openshift.io/cluster -p '{"spec":{"readOnly":true}}' --type=merge 125 ``` 126 127 Now run the container in your cluster: 128 129 ```shell 130 oc apply -f image-migration-pod.yaml 131 ``` 132 133 Check for any errors: 134 135 ```shell 136 oc -n openshift-image-registry get pod image-registry-migration 137 ``` 138 139 When its status is `Completed`, the pod can be removed: 140 141 ```shell 142 oc -n openshift-image-registry delete pod image-registry-migration 143 ``` 144 145 ## Switch to Swift as the Image Registry storage backend 146 147 This command sets Swift as the image-registry backend and sets two replicas, as 148 Swift allows concurrent access to its resources. Replace 149 `openshift-lrgv9-image-registry-aaa` with the `$container_name` above: 150 151 ```shell 152 oc patch configs.imageregistry.operator.openshift.io/cluster \ 153 --type='json' \ 154 --patch='[ 155 {"op": "replace", "path": "/spec/rolloutStrategy", "value": "RollingUpdate"}, 156 {"op": "replace", "path": "/spec/replicas", "value": 2}, 157 {"op": "replace", "path": "/spec/storage", "value": {"managementState": "Managed", "swift": {"container": "openshift-lrgv9-image-registry-aaa"}}} 158 ]' 159 ``` 160 161 Wait for the operator to recreate the image-registry instances. 162 163 ```shell 164 oc wait --for=condition=Progressing=false clusteroperator/image-registry --timeout=5m 165 ``` 166 167 After the operation is complete and successful, re-enable write operations as 168 needed: 169 170 ```shell 171 oc patch configs.imageregistry.operator.openshift.io/cluster -p '{"spec":{"readOnly":false}}' --type=merge 172 ``` 173 174 After the successful migration of all images has been confirmed, the old volume 175 claim can be released: 176 177 ```shell 178 oc -n openshift-image-registry delete pvc image-registry-storage 179 ``` 180 181 ## Abort the migration and return to the volume backend 182 183 This command rolls back to the previous volume backend. Use it to return to a 184 stable state if a successful migration can't be confirmed. 185 186 ```shell 187 oc patch configs.imageregistry.operator.openshift.io/cluster \ 188 --type='json' \ 189 --patch='[ 190 {"op": "replace", "path": "/spec/rolloutStrategy", "value": "Recreate"}, 191 {"op": "replace", "path": "/spec/replicas", "value": 1}, 192 {"op": "replace", "path": "/spec/storage", "value": {"managementState": "Unmanaged", "pvc": {"claim":"image-registry-storage"}}} 193 ]' 194 ```