4.5. 데이터베이스를 MariaDB 인스턴스로 마이그레이션
원래 RHOSP(Red Hat OpenStack Platform) 배포에서 RHCS(Red Hat OpenShift Container Platform) 클러스터의 MariaDB 인스턴스로 데이터베이스를 마이그레이션합니다.
사전 요구 사항
- 컨트롤 플레인 MariaDB 및 RabbitMQ가 실행 중이고 다른 컨트롤 플레인 서비스가 실행되고 있지 않은지 확인합니다.
- 토폴로지별 서비스 구성을 검색합니다. 자세한 내용은 토폴로지별 서비스 구성 검색을 참조하십시오.
- RHOSP 서비스를 중지합니다. 자세한 내용은 Red Hat OpenStack Platform 서비스 중지 를 참조하십시오.
- 원래 MariaDB와 컨트롤 플레인의 MariaDB 사이에 네트워크 라우팅 기능이 있는지 확인합니다.
다음 쉘 변수를 정의합니다. 다음 예제 값을 환경에 적합한 값으로 바꿉니다.
$ STORAGE_CLASS=local-storage $ MARIADB_IMAGE=registry.redhat.io/rhoso/openstack-mariadb-rhel9:18.0 $ OSPDO_MARIADB_CLIENT_ANNOTATIONS='[{"name": "internalapi-static","ips": ["172.17.0.99/24"]}]' $ MARIADB_RUN_OVERRIDES="$OSPDO_MARIADB_CLIENT_ANNOTATIONS" $ CELLS="default"1 $ DEFAULT_CELL_NAME="cell1" $ RENAMED_CELLS="$DEFAULT_CELL_NAME" $ CHARACTER_SET=utf82 $ COLLATION=utf8_general_ci $ declare -A PODIFIED_DB_ROOT_PASSWORD $ for CELL in $(echo "super $RENAMED_CELLS"); do > PODIFIED_DB_ROOT_PASSWORD[$CELL]=$(oc get -o json secret/osp-secret | jq -r .data.DbRootPassword | base64 -d) > done $ declare -A PODIFIED_MARIADB_IP $ for CELL in $(echo "super $RENAMED_CELLS"); do > if [ "$CELL" = "super" ]; then > PODIFIED_MARIADB_IP[$CELL]=$(oc get svc --selector "mariadb/name=openstack" -ojsonpath='{.items[0].spec.clusterIP}') > else > PODIFIED_MARIADB_IP[$CELL]=$(oc get svc --selector "mariadb/name=openstack-$CELL" -ojsonpath='{.items[0].spec.clusterIP}') > fi > done $ declare -A TRIPLEO_PASSWORDS $ for CELL in $(echo $CELLS); do > if [ "$CELL" = "default" ]; then > TRIPLEO_PASSWORDS[default]="$HOME/overcloud-passwords.yaml" > else > # in a split-stack source cloud, it should take a stack-specific passwords file instead > TRIPLEO_PASSWORDS[$CELL]="$HOME/overcloud-passwords.yaml" > fi > done $ declare -A SOURCE_DB_ROOT_PASSWORD $ for CELL in $(echo $CELLS); do > SOURCE_DB_ROOT_PASSWORD[$CELL]=$(cat ${TRIPLEO_PASSWORDS[$CELL]} | grep ' MysqlRootPassword:' | awk -F ': ' '{ print $2; }') > done $ declare -A SOURCE_MARIADB_IP $ SOURCE_MARIADB_IP[default]=*<galera cluster VIP>*3 $ SOURCE_MARIADB_IP[cell1]=*<galera cell1 cluster VIP>*4 $ SOURCE_MARIADB_IP[cell2]=*<galera cell2 cluster VIP>*5 # ... $ declare -A SOURCE_GALERA_MEMBERS_DEFAULT $ SOURCE_GALERA_MEMBERS_DEFAULT=( > ["standalone.localdomain"]=172.17.0.1006 > # [...]=... > ) $ declare -A SOURCE_GALERA_MEMBERS_CELL1 $ SOURCE_GALERA_MEMBERS_CELL1=( > # ... > ) $ declare -A SOURCE_GALERA_MEMBERS_CELL2 $ SOURCE_GALERA_MEMBERS_CELL2=( > # ... > )- 1
CELLS및RENAMED_CELLS는 데이터베이스를 가져온 후 변경 사항을 나타냅니다.기본셀은DEFAULT_CELL_NAME에서 새 이름을 사용합니다. 다중 셀 채택 시나리오에서기본 셀은 원래의 기본이름도 유지할 수 있습니다.- 2
- Cryo
statACTER_SET변수 및 데이터 정렬은 소스 데이터베이스와 일치해야 합니다. 일치하지 않으면 나중에 데이터베이스 동기화의 일부로 생성되는 모든 테이블에 대해 외래 키 관계가 중단됩니다. - 3
CELLS에 정의된 각 셀에 대해SOURCE_MARIADB_IP[*]= ...에 데이터를 추가합니다. MariaDB Galera 클러스터의 셀 이름 및 VIP 주소에 대한 레코드를 제공합니다.- 4
- 을 galera cell1 클러스터의 VIP로 바꿉니다
. - 5
- 을 galera cell2 클러스터의 VIP로 교체하는
등입니다. - 6
CELLS에 정의된 각 셀에 대해SOURCE_GALERA_MEMBERS_CELL<X>에서 MariaDB Galera 클러스터 멤버와 해당 IP 주소의 이름을 추가합니다.["standalone.localdomain"]="172.17.0.100"을 실제 호스트 데이터로 교체합니다.
독립 실행형 director Operator 환경은 기본 셀만 생성합니다. 이 경우 유일한 CELLS 값이어야 합니다. DEFAULT_CELL_NAME 값은 cell1 이어야 합니다.
super 는 최상위 범위의 Nova API upcall 데이터베이스 인스턴스입니다. 슈퍼 컨덕터가 해당 데이터베이스에 연결됩니다. 후속 예에서 upcall 및 cells 데이터베이스는 osp-secret 에 정의된 것과 동일한 암호를 사용합니다. 이전 암호는 데이터 내보내기를 준비하는 데만 필요합니다.
SOURCE_MARIADB_IP값을 가져오려면 Controller 및 cellController 노드에서 puppet-generated 구성을 쿼리합니다.$ sudo grep -rI 'listen mysql' -A10 /var/lib/config-data/puppet-generated/ | grep bindSOURCE_GALERA_MEMBERS_*의 값을 가져오려면 Controller 및 cellController 노드에서 puppet-generated 구성을 쿼리합니다.$ sudo grep -rI 'listen mysql' -A10 /var/lib/config-data/puppet-generated/ | grep server소스 클라우드는 항상 셀 데이터베이스에 동일한 암호를 사용합니다. 따라서 모든 셀 스택에 동일한 암호 파일이 사용됩니다. 그러나 split-stack 토폴로지를 사용하면 각 스택에 대해 서로 다른 암호 파일을 사용할 수 있습니다.
MariaDB 채택 도우미 Pod를 준비합니다.
데이터베이스 데이터 복사에 대한 임시 볼륨 클레임 및 Pod를 생성합니다. 필요한 경우 볼륨 클레임 스토리지 요청을 편집하여 오버클라우드 데이터베이스에 충분한 공간을 제공합니다.
$ oc apply -f - <<EOF --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mariadb-data spec: storageClassName: $STORAGE_CLASS accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- apiVersion: v1 kind: Pod metadata: name: mariadb-copy-data annotations: openshift.io/scc: anyuid k8s.v1.cni.cncf.io/networks: '[{"name": internalapi-static, "ips": ["10.2.120.9/24"]}]' labels: app: adoption spec: nodeName: <$CONTROLLER_NODE> containers: - image: $MARIADB_IMAGE command: [ "sh", "-c", "sleep infinity"] name: adoption volumeMounts: - mountPath: /backup name: mariadb-data securityContext: allowPrivilegeEscalation: false capabilities: drop: ALL runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: mariadb-data persistentVolumeClaim: claimName: mariadb-data EOFPod가 준비될 때까지 기다립니다.
$ oc wait --for condition=Ready pod/mariadb-copy-data --timeout=30s
프로세스
각 셀의 Galera 데이터베이스 클러스터에 멤버가 온라인 상태이고 동기화되었는지 확인합니다.
$ for CELL in $(echo $CELLS); do > MEMBERS=SOURCE_GALERA_MEMBERS_$(echo ${CELL}|tr '[:lower:]' '[:upper:]')[@] > for i in "${!MEMBERS}"; do > echo "Checking for the database node $i WSREP status Synced" > oc rsh mariadb-copy-data mysql \ > -h "$i" -uroot -p"${SOURCE_DB_ROOT_PASSWORD[$CELL]}" \ > -e "show global status like 'wsrep_local_state_comment'" | \ > grep -qE "\bSynced\b" > done > done추가 Compute 서비스(nova) v2 셀은 전용 Galera 데이터베이스 클러스터를 실행하므로 명령은 각 셀을 확인합니다.
NOK(Not-OK) 상태의 소스 데이터베이스 수를 가져옵니다.$ for CELL in $(echo $CELLS); do > oc rsh mariadb-copy-data mysql -h "${SOURCE_MARIADB_IP[$CELL]}" -uroot -p"${SOURCE_DB_ROOT_PASSWORD[$CELL]}" -e "SHOW databases;" > endmysqlcheck에 오류가 없는지 확인합니다.$ for CELL in $(echo $CELLS); do > set +u > . ~/.source_cloud_exported_variables_$CELL > set -u > done $ test -z "$PULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK" || [ "x$PULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK" = "x " ] && echo "OK" || echo "CHECK FAILED"컨트롤 플레인 upcall 및 셀 데이터베이스에 대한 연결을 테스트합니다.
$ for CELL in $(echo "super $RENAMED_CELLS"); do > oc run mariadb-client --image $MARIADB_IMAGE -i --rm --restart=Never -- \ > mysql -rsh "${PODIFIED_MARIADB_IP[$CELL]}" -uroot -p"${PODIFIED_DB_ROOT_PASSWORD[$CELL]}" -e 'SHOW databases;' > done참고cell1부터 시작하여 나중에 가져오는 Compute 서비스를 셀 데이터베이스에서 이전 서비스 레코드를 삭제하여 슈퍼 컨덕터 아키텍처로 전환해야 합니다. 새 레코드는 Compute 서비스 운영자가 제공하는 다른 호스트 이름으로 등록됩니다. Compute 에이전트를 제외한 모든 Compute 서비스에는 내부 상태가 없으며 서비스 레코드를 안전하게 삭제할 수 있습니다. 또한 이전기본셀의 이름을DEFAULT_CELL_NAME로 변경해야합니다.원래 데이터베이스의 덤프를 생성합니다.
$ for CELL in $(echo $CELLS); do > oc rsh mariadb-copy-data << EOF > mysql -h"${SOURCE_MARIADB_IP[$CELL]}" -uroot -p"${SOURCE_DB_ROOT_PASSWORD[$CELL]}" \ > -N -e "show databases" | grep -E -v "schema|mysql|gnocchi|aodh" | \ > while read dbname; do > echo "Dumping $CELL cell \${dbname}"; > mysqldump -h"${SOURCE_MARIADB_IP[$CELL]}" -uroot -p"${SOURCE_DB_ROOT_PASSWORD[$CELL]}" \ > --single-transaction --complete-insert --skip-lock-tables --lock-tables=0 \ > "\${dbname}" > /backup/"${CELL}.\${dbname}".sql; > done > EOF > done정보 및 성능 스키마 테이블 필터링에 유의하십시오. Gnocchi는 더 이상 지표 저장소로 사용되지 않습니다.
.sql파일의 데이터베이스를 컨트롤 플레인 MariaDB로 복원합니다.$ for CELL in $(echo $CELLS); do > RCELL=$CELL > [ "$CELL" = "default" ] && RCELL=$DEFAULT_CELL_NAME > oc rsh mariadb-copy-data << EOF > declare -A db_name_map1 > db_name_map['nova']="nova_$RCELL" > db_name_map['ovs_neutron']='neutron' > db_name_map['ironic-inspector']='ironic_inspector' > declare -A db_cell_map2 > db_cell_map['nova']="nova_$DEFAULT_CELL_NAME" > db_cell_map["nova_$RCELL"]="nova_$RCELL"3 > declare -A db_server_map4 > db_server_map['default']=${PODIFIED_MARIADB_IP['super']} > db_server_map["nova"]=${PODIFIED_MARIADB_IP[$DEFAULT_CELL_NAME]} > db_server_map["nova_$RCELL"]=${PODIFIED_MARIADB_IP[$RCELL]} > declare -A db_server_password_map5 > db_server_password_map['default']=${PODIFIED_DB_ROOT_PASSWORD['super']} > db_server_password_map["nova"]=${PODIFIED_DB_ROOT_PASSWORD[$DEFAULT_CELL_NAME]} > db_server_password_map["nova_$RCELL"]=${PODIFIED_DB_ROOT_PASSWORD[$RCELL]} > cd /backup > for db_file in \$(ls ${CELL}.*.sql); do > db_name=\$(echo \${db_file} | awk -F'.' '{ print \$2; }') > [[ "$CELL" != "default" && ! -v "db_cell_map[\${db_name}]" ]] && continue > if [[ "$CELL" == "default" && -v "db_cell_map[\${db_name}]" ]] ; then > target=$DEFAULT_CELL_NAME > elif [[ "$CELL" == "default" && ! -v "db_cell_map[\${db_name}]" ]] ; then > target=super > else > target=$RCELL > fi6 > renamed_db_file="\${target}_new.\${db_name}.sql" > mv -f \${db_file} \${renamed_db_file} > if [[ -v "db_name_map[\${db_name}]" ]]; then > echo "renaming $CELL cell \${db_name} to \$target \${db_name_map[\${db_name}]}" > db_name=\${db_name_map[\${db_name}]} > fi > db_server=\${db_server_map["default"]} > if [[ -v "db_server_map[\${db_name}]" ]]; then > db_server=\${db_server_map[\${db_name}]} > fi > db_password=\${db_server_password_map['default']} > if [[ -v "db_server_password_map[\${db_name}]" ]]; then > db_password=\${db_server_password_map[\${db_name}]} > fi > echo "creating $CELL cell \${db_name} in \$target \${db_server}" > mysql -h"\${db_server}" -uroot "-p\${db_password}" -e \ > "CREATE DATABASE IF NOT EXISTS \${db_name} DEFAULT \ > CHARACTER SET ${CHARACTER_SET} DEFAULT COLLATE ${COLLATION};" > echo "importing $CELL cell \${db_name} into \$target \${db_server} from \${renamed_db_file}" > mysql -h "\${db_server}" -uroot "-p\${db_password}" "\${db_name}" < "\${renamed_db_file}" > done > if [ "$CELL" = "default" ] ; then > mysql -h "\${db_server_map['default']}" -uroot -p"\${db_server_password_map['default']}" -e \ > "update nova_api.cell_mappings set name='$DEFAULT_CELL_NAME' where name='default';" > fi > mysql -h "\${db_server_map["nova_$RCELL"]}" -uroot -p"\${db_server_password_map["nova_$RCELL"]}" -e \ > "delete from nova_${RCELL}.services where host not like '%nova_${RCELL}-%' and services.binary != 'nova-compute';" > EOF > done
검증
토폴로지별 서비스 구성과 다음 출력을 비교합니다. 자세한 내용은 토폴로지별 서비스 구성 검색을 참조하십시오.
데이터베이스를 올바르게 가져오는지 확인합니다.
$ set +u $ . ~/.source_cloud_exported_variables_default $ set -u $ dbs=$(oc exec openstack-galera-0 -c galera -- mysql -rs -uroot -p"${PODIFIED_DB_ROOT_PASSWORD['super']}" -e 'SHOW databases;') $ echo $dbs | grep -Eq '\bkeystone\b' && echo "OK" || echo "CHECK FAILED" $ echo $dbs | grep -Eq '\bneutron\b' && echo "OK" || echo "CHECK FAILED" $ echo "${PULL_OPENSTACK_CONFIGURATION_DATABASES[@]}" | grep -Eq '\bovs_neutron\b' && echo "OK" || echo "CHECK FAILED"1 $ novadb_mapped_cells=$(oc exec openstack-galera-0 -c galera -- mysql -rs -uroot -p"${PODIFIED_DB_ROOT_PASSWORD['super']}" \ > nova_api -e 'select uuid,name,transport_url,database_connection,disabled from cell_mappings;')2 $ uuidf='\S{8,}-\S{4,}-\S{4,}-\S{4,}-\S{12,}' $ default=$(printf "%s\n" "$PULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS" | sed -rn "s/^($uuidf)\s+default\b.*$/\1/p") $ difference=$(diff -ZNua \ > <(printf "%s\n" "$PULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS") \ > <(printf "%s\n" "$novadb_mapped_cells")) || true $ if [ "$DEFAULT_CELL_NAME" != "default" ]; then > printf "%s\n" "$difference" | grep -qE "^\-$default\s+default\b" && echo "OK" || echo "CHECK FAILED" > printf "%s\n" "$difference" | grep -qE "^\+$default\s+$DEFAULT_CELL_NAME\b" && echo "OK" || echo "CHECK FAILED" > [ $(grep -E "^[-\+]$uuidf" <<<"$difference" | wc -l) -eq 2 ] && echo "OK" || echo "CHECK FAILED" > else > [ "x$difference" = "x" ] && echo "OK" || echo "CHECK FAILED" > fi $ for CELL in $(echo $RENAMED_CELLS); do3 > RCELL=$CELL > [ "$CELL" = "$DEFAULT_CELL_NAME" ] && RCELL=default > set +u > . ~/.source_cloud_exported_variables_$RCELL > set -u > c1dbs=$(oc exec openstack-$CELL-galera-0 -c galera -- mysql -rs -uroot -p${PODIFIED_DB_ROOT_PASSWORD[$CELL]} -e 'SHOW databases;')4 > echo $c1dbs | grep -Eq "\bnova_${CELL}\b" && echo "OK" || echo "CHECK FAILED" > novadb_svc_records=$(oc exec openstack-$CELL-galera-0 -c galera -- mysql -rs -uroot -p${PODIFIED_DB_ROOT_PASSWORD[$CELL]} \ > nova_$CELL -e "select host from services where services.binary='nova-compute' and deleted=0 order by host asc;") > diff -Z <(echo "x$novadb_svc_records") <(echo "x${PULL_OPENSTACK_CONFIGURATION_NOVA_COMPUTE_HOSTNAMES[@]}") && echo "OK" || echo "CHECK FAILED"5 > done데이터베이스 백업이 포함된
mariadb-dataPod 및mariadb-copy-data영구 볼륨 클레임을 삭제합니다.참고삭제하기 전에 스냅샷을 생성하는 것이 좋습니다.
$ oc delete pod mariadb-copy-data $ oc delete pvc mariadb-data
사전 확인 및 사후 확인 중에 mariadb-client Pod에서 restricted:latest 보안 컨텍스트 제약 조건과 관련된 Pod 보안 경고를 반환할 수 있습니다. 이 경고는 기본 보안 컨텍스트 제약 조건으로 인해 승인 컨트롤러에서 Pod를 생성하지 못하도록 하지 않습니다. 수명이 짧은 Pod에 대한 경고가 표시되지만 기능을 방해하지는 않습니다. 자세한 내용은 Pod 보안 표준 및 경고 정보를 참조하십시오.