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=utf8 
    2
    
    $ 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.100 
    6
    
    >   # [...]=...
    > )
    $ declare -A SOURCE_GALERA_MEMBERS_CELL1
    $ SOURCE_GALERA_MEMBERS_CELL1=(
    >   # ...
    > )
    $ declare -A SOURCE_GALERA_MEMBERS_CELL2
    $ SOURCE_GALERA_MEMBERS_CELL2=(
    >   # ...
    > )
    1
    CELLSRENAMED_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 S _CELL<X> 中定义的每个单元,添加 MariaDB Galera 集群成员及其 IP 地址的名称。将 ["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:

    1. 为数据库数据复制创建一个临时卷声明和 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
    2. 等待 pod 就绪:

      $ oc wait --for condition=Ready pod/mariadb-copy-data --timeout=30s

流程

  1. 检查每个单元中的源 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 数据库集群,因此命令会检查每个单元。

  2. 获取具有 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
  3. 检查 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"
  4. 测试到 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

  5. 创建原始数据库的转储:

    $ 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 不再用作指标存储

  6. 将数据库从 .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_map  
    1
    
    >     db_name_map['nova']="nova_$RCELL"
    >     db_name_map['ovs_neutron']='neutron'
    >     db_name_map['ironic-inspector']='ironic_inspector'
    >     declare -A db_cell_map  
    2
    
    >     db_cell_map['nova']="nova_$DEFAULT_CELL_NAME"
    >     db_cell_map["nova_$RCELL"]="nova_$RCELL"  
    3
    
    >     declare -A db_server_map  
    4
    
    >     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_map  
    5
    
    >     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
    >       fi  
    6
    
    >       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
    1
    定义在导入时要重命名的通用数据库。
    2
    定义要导入的单元数据库,以及如何重命名它们(如果需要)。
    3
    省略了导入单元的特殊 cell0 数据库,因为它的内容在采用过程中无法合并。
    4
    定义要将哪些数据库导入到哪些服务器,通常为单元专用。
    5
    定义数据库服务器的 root 密码映射。现在,您只能使用相同的密码。
    6
    分配在从 默认单元 提取数据库时将哪些数据库导入到哪些主机。

验证

将以下输出与特定于拓扑的服务配置进行比较。如需更多信息,请参阅 检索特定于拓扑的服务配置

  1. 检查数据库是否已正确导入:

    $ 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); do 
    3
    
    >   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
    1
    确保 Networking 服务(neutron)数据库从 ovs_neutron 重命名。
    2
    确保 默认单元 重命名为 $DEFAULT_CELL_NAME,并保留单元 UUID。
    3
    确保注册的 Compute 服务名称没有改变。
    4
    确保计算服务单元数据库提取到单独的数据库服务器,并从 nova 重命名为 nova_cell<X&gt;。
    5
    确保注册的 Compute 服务名称没有改变。
  2. 删除 mariadb-data pod 和 mariadb-copy-data 持久性卷声明,其中包含数据库备份:

    注意

    在删除前,请考虑为它们执行快照。

    $ oc delete pod mariadb-copy-data
    $ oc delete pvc mariadb-data
注意

在预检查和后检查过程中,mariadb-client pod 可能会返回与 restricted:latest 安全性上下文约束相关的 pod 安全警告。这个警告是因为默认安全性上下文约束,不会阻止准入控制器创建 pod。您会看到一个针对短期 pod 的警告,但它不会影响到功能。如需更多信息,请参阅关于 pod 安全标准和警告

Red Hat logoGithubredditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。 了解我们当前的更新.

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

Theme

© 2026 Red Hat
返回顶部