3.5. 将数据库迁移到 MariaDB 实例
将您的数据库从原始 Red Hat OpenStack Platform (RHOSP)部署迁移到 Red Hat OpenShift Container Platform (RHOCP)集群中的 MariaDB 实例。
先决条件
- 确保 control plane MariaDB 和 RabbitMQ 正在运行,且没有其他 control plane 服务在运行。
- 检索特定于拓扑的服务配置。如需更多信息,请参阅 检索特定于拓扑的服务配置。
- 停止 RHOSP 服务。如需更多信息,请参阅 停止 Red Hat OpenStack Platform 服务。
- 确保原始 MariaDB 和 control plane 的 MariaDB 之间有网络可路由性。
定义以下 shell 变量:将以下示例值替换为您的环境的正确值:
$ STORAGE_CLASS=local-storage $ MARIADB_IMAGE=registry.redhat.io/rhoso/openstack-mariadb-rhel9:18.0 $ 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
CHARACTER_SET变量和 collation 应与源数据库匹配。如果不匹配,则以后创建的任何表的外键关系中断作为数据库同步的一部分。- 3
- 在
SOURCE_MARIADB_IP[*]= ...中为CELLS中定义的每个单元添加数据。为 MariaDB Galera 集群的单元名称和 VIP 地址提供记录。 - 4
- 使用 galera cell1 集群的 VIP 替换
。 - 5
- 使用 galera cell2 集群的 VIP 替换
,以此类推。 - 6
- 对于在
SOURCE_GALERA_MEMBER中定义的每个单元,添加 MariaDB Galera 集群成员及其 IP 地址的名称。将S_CELL<X>["standalone.localdomain"]="172.17.0.100"替换为实际主机数据。
独立 director 环境只 创建一个默认的 单元,这应该是本例中唯一的 CELLS 值。DEFAULT_CELL_NAME 值应该是 cell1。
超级 是顶级范围的 Nova API upcall 数据库实例。超级编排器连接到该数据库。在后续示例中,upcall 和 cells 数据库使用与 osp-secret 中定义的相同密码。旧密码只需要准备数据导出。
要获取
SOURCE_MARIADB_IP的值,请查询 Controller 和 CellController 节点上的 puppet 生成的配置:$ sudo grep -rI 'listen mysql' -A10 /var/lib/config-data/puppet-generated/ | grep bind要获取
SOURCE_GALERA_MEMBERS platforms的值,请查询 Controller 和 CellController 节点上的 puppet 生成的配置:$ sudo grep -rI 'listen mysql' -A10 /var/lib/config-data/puppet-generated/ | grep server源云始终对单元数据库使用相同的密码。因此,相同的密码文件用于所有单元堆栈。但是,split-stack 拓扑允许为每个堆栈使用不同的密码文件。
准备 MariaDB 的采用帮助程序 pod:
为数据库数据复制创建一个临时卷声明和 pod。如果需要,编辑卷声明存储请求,为 overcloud 数据库提供足够空间:
$ 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: internalapi labels: app: adoption spec: 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 EOF等待 pod 就绪:
$ 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;" > end检查
mysqlcheck是否没有错误:$ 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"测试到 control plane upcall 和 cells 数据库的连接:
$ 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文件恢复到 control plane 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 安全标准和警告。