资源编排配合实例自定义数据,实现RDS自动创建与恢复

本文涉及的产品
对象存储 OSS,20GB 3个月
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
简介: 背景不少客户需要批量部署系统他们希望ROS不仅能帮助他们自动部署底层PAAS与IAAS资源还能够省去安装软件链接数据库导入数据库文件的动作。而ROS能完美结合ECS的自定义数据自定义镜像RDS Web API最大化减少人肉工作。

背景:不少客户需要批量部署系统,他们希望ROS不仅能帮助他们自动部署底层PAAS与IAAS资源,还能够省去安装软件,链接数据库,导入数据库文件的动作。而ROS能完美结合ECS的自定义数据,自定义镜像,RDS Web API,最大化减少人肉工作。

 

前提条件

a.拥有可用的OSS空间(Bucket),且与创建的RDS同一个Region

b.RDS具有访问OSS的权限(也可通过ROS授权)

c.了解ROS,可通过ROS控制台创建模板和资源

 

步骤概览:

a.创建ECS自定义镜像,镜像内包含自己的应用软件

b.将需要备份恢复的数据库.bak(本文以SQLServer为例)文件上传到OSS空间

c.编写ROS的模板,自动创建所需资源,创建顺序如下VPC>Vswitch>SecurityGroup>RDS>ECS,ECS创建成功后会自动执行ROS模板里面编写的自定义数据,连接数据库,并且将OSS中的备份文件恢复到RDS里面。

 

步骤详解:

1.创建自定义镜像

1.1创建一个ECS实例,部署好所需的软件,除了安装客户业务所需要的软件之外,为了实现自动的备份,减少配置工作,也需要安装一些阿里云SDK

1.1.1安装python

请根据Python官网的引导安装合适的Python版本,推荐安装2.7.10。

1.1.2安装完毕后,查看Python版本。

如果你是Windows操作系统:

执行C:\>c:\Python27\python.exe -V查看Python版本,如果输出内容为:Python 2.7.10表明您已成功安装了Python 2.7.10版本。

如果提示不是内部或外部命令, 请检查配置Path环境变量,增加Python的安装路径和pip命令的目录,如下图所示:

b615bf53c9494c98f89efc38490c4f862a69285f

如果你是Mac/Linux/Unix操作系统:

执行$ python -V查看Python版本,如果输出内容为:Python 2.7.10表明您已成功安装了Python 2.7.10版本。

 

1.1.3安装SDK依赖包

使用pip安装或者git clone源码安装,任选其一。

  Pip安装


pip install aliyun-python-sdk-rds

pip install oss2

   源码安装

# git 克隆openapi

git clone https://github.com/aliyun/aliyun-openapi-python-sdk.git

# 安装阿里云 SDK 核心库

cd aliyun-python-sdk-core

python setup.py install

# 安装阿里云 RDS SDK

cd aliyun-python-sdk-rds

python setup.py install

# git 克隆OSS SDK

git clone https://github.com/aliyun/aliyun-oss-python-sdk.git

cd aliyun-oss-python-sdk

# 安装OSS2

python setup.py install
  1.1.4 下载备份恢复的.py执行脚本

下载实例级别迁移上云脚本RDSSQLCreateMigrateTasksBatchly.py,下载地址:单击下载。保存在目录中,本次假设保存在C盘。

 1.2控制台中将上一步骤设置好的ECS生成自定义镜像,详细参考创建自定义镜像

注意:自定义镜像属于Region,不能跨Region直接读取,如果需要跨账号或跨Region使用,请参考共享镜像

1.2.1 记录自定义镜像的ID与所在的Region

 

2.将备份文件,即数据库.bak文件上传到对应的OSS Bucket上(本次以SQLServer为例),并且记录下对应的OSSd的Endpoint和url地址

 

3.编写ROS的模板

3.1前两个步骤已经将基本的环境准备好,现在就需要编写ROS模板,让ROS自动创建所需资源,然后通过ROS给ECS指派的自定义数据,自动运行.py的备份脚本,

 

3.2在执行RDSSQLCreateMigrateTasksBatchly.py文件时,需要了解使用说明,如下


~/Downloads/RDSSQLCreateMigrateTasksBatchly.py -k <access_key_id> -s <access_key_secret> -i <rds_instance_id> -e <oss_endpoint> -b <oss_bucket> -d <directory>


参数说明:

参数

说明

access_key_id

阿里云账号对应的access key id

access_key_secret

阿里云账号对应的access key secret

rds_instance_id

RDS SQL Server目标实例ID

oss_endpoint

备份文件所在的OSS Bucket endpoint地址,获取方法请参见OSS Endpoint错误中截图

oss_bucket

备份文件所在的OSS Bucket名字

directory

OSS Bucket中,备份文件所在的目录,如果是根目录,请传入“/”

 

因此,在ROS中,除了oss_bucket和directory是指定的,其他参数均可通过ROS的Fn::GetAtt函数获得,

因此,对应的ECS的自定义数据Userdata如下


"UserData": {

          "Fn::Join": [

            "",

            [

              "[powershell]",

              "\n",

              "$keyid=",

              {

                "Fn::GetAtt": [

                   "RamAK",

                  "AccessKeyId"

                ]

              },

              "\n",

              "$keysec=",

              {

                "Fn::GetAtt": [

                  "RamAK",

                  "AccessKeySecret"

                ]

              },

              "\n",

              "$rdsid=",

              {

                "Fn::GetAtt": [

                  "LYDatabase",

                  "DBInstanceId"

                ]

              },

              "\n",

              "python C:\\RDSSQLCreateMigrateTasksBatchly.py -k '$keyid -s '$keysec -i '$rdsid -e oss_endpoint -b oss_bucket -d directory"

            ]

          ]

        }
如下为userdata最终执行的示例:

 


python ~/Downloads/RDSSQLCreateMigrateTasksBatchly.py -k LTAIQazXKPRwwErT -s BMkIUhroubQOLpOMqfA09IKlqp4G2k -i rm-2zesz5774ud8s71i5 -e oss-cn-beijing.aliyuncs.com -b atp-test-on-ecs -d Migration/OPENAPIDemo


 

注意:上面执行所需要的Accesskey ID和Accesskey Secret均为RAM账号,无法使用主账号,所以如果您在阿里云的主账号下运行,请先创建一个RAM账号,并赋予RDS的完整管理权限,创建RAM账号与赋予RDS权限语句如下


{

  "ROSTemplateFormatVersion": "2015-09-01",

  "Description": "",

  "Parameters": {

    "UserName": {

      "AllowedPattern": "^[a-zA-Z0-9.@-_]+$",

      "ConstraintDescription": "[1, 64]. Consist of lowercase letter, number, '@', '.', '_' or '-'",

      "Default":"lionel",

      "Description": "The name of sub account",

      "Type": "String"

    },

    "Password": {

      "ConstraintDescription": "[8, 30] Consist of uppercase letter, lowercase letter and number.",

      "Description": "The login password of sub account",

      "MaxLength": 32,

      "MinLength": 8,

      "Default":"lionelpassword",

      "Confirm": true,

      "Type": "String"

    }

  },

  "Mappings": {},

  "Conditions": {},

  "Resources": {

    "RamAK": {

      "Properties": {

        "UserName": {

          "Fn::GetAtt": [

            "RamUser",

            "UserName"

          ]

        }

      },

      "Type": "ALIYUN::RAM::AccessKey"

    },

    "RamUser": {

      "Properties": {

        "LoginProfile": {

          "Password": {

            "Ref": "Password"

          },

          "PasswordResetRequired": false

        },

        "UserName": {

          "Ref": "UserName"

        }

      },

      "Type": "ALIYUN::RAM::User"

},

"RDSfullaccessPolicy": {

         "Type": "ALIYUN::RAM::ManagedPolicy",

         "Properties": {

           "Description":  "Description",

           "PolicyName":"AliyunRDSfullacessPolicy",

           "PolicyDocument":  {

               "Version": "1",

               "Statement":[{

                   "Action":

                    [ "rds:*"]

                   ,

                   "Resource": ["*"],

                   "Effect": "Allow"

                 },

                 {

                     "Action":

                       ["dms:*LoginDatabase"]

                     ,

                     "Resource": ["acs:rds:*:*:*"],

                     "Effect": "Allow"

                   }

               ]

             },

           "Users":  [ { "Ref": "RamUser" } ]

         }

       }


 

3.3若要RDS能读取OSS里面的.bak备份文件,则需要给RDS授权读取OSS,可以通过在控制台手动赋予权限,亦可以通过ROS自动化实现,实现Json语言如下


"Policy": {

   "Type": "ALIYUN::RAM::ManagedPolicy",

   "Properties": {

     "Description": "Description",

     "PolicyName": "AliyunRDSImportPolicy",

     "PolicyDocument": {

       "Version": "1",

       "Statement": [

         {

           "Action": [

             "oss:GetObject",

             "oss:GetBucketLocation"

           ],

           "Resource": [

             "*"

           ],

           "Effect": "Allow"

         }

       ]

     },

     "Roles": [

       {

         "Ref": "ImportRole"

       }

     ]

   }

 },

 "ImportRole": {

  "Type": "ALIYUN::RAM::Role",

  "Properties": {

    "RoleName": "AliyunRDSImportRole",

    "Description": "RDS import",

    "AssumeRolePolicyDocument": {

      "Version": "1",

      "Statement": [

        {

          "Action": "sts:AssumeRole",

          "Effect": "Allow",

          "Principal": {

            "Service": [

              "rds.aliyuncs.com"

            ]

          }

        }

      ]

    }

  }

}


 

3.4因为ECS里面的.py脚本需要在RDS彻底创建成功后才能执行,所以要通过ROS DependsOn参数,让ECS在RDS生成后创建


"Server": {

      "Type": "ALIYUN::ECS::Instance",

      "DependsOn": [

        "LYDatabase"

      ],

      "Properties": {

        "IoOptimized": "optimized",

        "ZoneId": "cn-shenzhen-b",

        "SystemDiskSize": "100",

        "InstanceChargeType": "PostPaid",

        "SecurityGroupId": {

          "Ref": "ServerSecurityGroup"

        },

        "VSwitchId": {

          "Ref": "ServerSwitch"

        },

        "Period": 1,

        "SystemDiskCategory": "cloud_efficiency",

        "InternetChargeType": "PayByTraffic",

        "InternetMaxBandwidthOut": 1,

        "VpcId": {

          "Ref": "ALIYUN-ECS-VPC1"

        },

        "InternetMaxBandwidthIn": 200,

        "ImageId": "m-bp19l9u9broshpsresc9",

        "InstanceType": "ecs.sn1ne.xlarge",

        "AllocatePublicIP": true,

        "HostName": "lyServer",

        "Password": "lypass!@#",

"UserData": {}


 

4.总结:通过如上的过程即可实现数据库的自动部署和自动备份恢复,完成的ROS代码参考如下。


{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Description": "",
  "Parameters": {
    "UserName": {
      "AllowedPattern": "^[a-zA-Z0-9.@-_]+$",
      "ConstraintDescription": "[1, 64]. Consist of lowercase letter, number, '@', '.', '_' or '-'",
      "Default":"lionel",
      "Description": "The name of sub account",
      "Type": "String"
    },
    "Password": {
      "ConstraintDescription": "[8, 30] Consist of uppercase letter, lowercase letter and number.",
      "Description": "The login password of sub account",
      "MaxLength": 32,
      "MinLength": 8,
      "Default":"lionelpassword",
      "Confirm": true,
      "Type": "String"
    }
  },
  "Mappings": {},
  "Conditions": {},
  "Resources": {
    "RamAK": {
      "Properties": {
        "UserName": {
          "Fn::GetAtt": [
            "RamUser",
            "UserName"
          ]
        }
      },
      "Type": "ALIYUN::RAM::AccessKey"
    },
    "RamUser": {
      "Properties": {
        "LoginProfile": {
          "Password": {
            "Ref": "Password"
          },
          "PasswordResetRequired": false
        },
        "UserName": {
          "Ref": "UserName"
        }
      },
      "Type": "ALIYUN::RAM::User"
    },
    "ImportRole": {
      "Type": "ALIYUN::RAM::Role",
      "Properties": {
        "RoleName": "AliyunRDSImportRole",
        "Description": "RDS import",
        "AssumeRolePolicyDocument":{
           "Version": "1",
            "Statement": [{
              "Effect": "Allow",
              "Principal": {
                "Service": [ "rds.aliyuncs.com"]
              },
                "Action": "sts:AssumeRole"
              }]
            }
       }
    },
    "Policy": {
         "Type": "ALIYUN::RAM::ManagedPolicy",
         "Properties": {
           "Description":  "Description",
           "PolicyName":"AliyunRDSImportPolicy",
           "PolicyDocument":  {
               "Version": "1",
               "Statement":[{
                   "Action": [
                     "oss:GetObject",
                     "oss:GetBucketLocation"
                   ],
                   "Resource": ["*"],
                   "Effect": "Allow"
                 }]
             },
           "Roles":  [ { "Ref": "ImportRole" } ]
         }
       },
    "RDSfullaccessPolicy": {
         "Type": "ALIYUN::RAM::ManagedPolicy",
         "Properties": {
           "Description":  "Description",
           "PolicyName":"AliyunRDSfullacessPolicy",
           "PolicyDocument":  {
               "Version": "1",
               "Statement":[{
                   "Action":
                    [ "rds:*"]
                   ,
                   "Resource": ["*"],
                   "Effect": "Allow"
                 },
                 {
                     "Action":
                       ["dms:*LoginDatabase"]
                     ,
                     "Resource": ["acs:rds:*:*:*"],
                     "Effect": "Allow"
                   }
               ]
             },
           "Users":  [ { "Ref": "RamUser" } ]
         }
       },
    "ALIYUN-ECS-VPC1": {
      "Metadata": {
        "GraphicId": "RosGraphicElement-1"
      },
      "Type": "ALIYUN::ECS::VPC",
      "Properties": {
        "CidrBlock": "172.16.0.0/12"
      }
    },
    "ServerSecurityGroup": {
      "Type": "ALIYUN::ECS::SecurityGroup",
      "Properties": {
        "VpcId": {
          "Ref": "ALIYUN-ECS-VPC1"
        },
        "SecurityGroupIngress": [
          {
            "SourceGroupOwnerId": "",
            "SourceCidrIp": "0.0.0.0/0",
            "PortRange": "80/80",
            "SecurityGroupId": "mySecurityGroup",
            "NicType": "internet",
            "SourceGroupOwnerAccount": "",
            "Priority": 1,
            "SourceGroupId": "",
            "Policy": "accept",
            "IpProtocol": "tcp"
          },
          {
            "SourceGroupOwnerId": "",
            "SourceCidrIp": "0.0.0.0/0",
            "PortRange": "3389/3389",
            "SecurityGroupId": "mySecurityGroup",
            "NicType": "internet",
            "SourceGroupOwnerAccount": "",
            "Priority": 1,
            "SourceGroupId": "",
            "Policy": "accept",
            "IpProtocol": "tcp"
          },
          {
            "SourceGroupOwnerId": "",
            "SourceCidrIp": "0.0.0.0/0",
            "PortRange": "443/443",
            "SecurityGroupId": "mySecurityGroup",
            "NicType": "internet",
            "SourceGroupOwnerAccount": "",
            "Priority": 1,
            "SourceGroupId": "",
            "Policy": "accept",
            "IpProtocol": "tcp"
          }
        ]
      }
    },
    "ServerSwitch": {
      "Type": "ALIYUN::ECS::VSwitch",
      "Properties": {
        "VpcId": {
          "Ref": "ALIYUN-ECS-VPC1"
        },
        "CidrBlock": "172.16.1.0/24",
        "ZoneId": "cn-shenzhen-a"
      }
    },
    "LYDatabase": {
      "Type": "ALIYUN::RDS::DBInstance",
      "Properties": {
        "MasterUsername": "lyadmin",
        "MasterUserPassword": "lypasswrd",
        "Engine": "SQLServer",
        "EngineVersion": "2016_web",
        "MasterUserType":"Super",
        "VpcId": {
          "Ref": "ALIYUN-ECS-VPC1"
        },
        "ZoneId": "cn-shenzhen-a",
        "DBInstanceNetType": "Intranet",
        "DBInstanceClass": "mssql.x2.medium.w1",
        "SecurityIPList": "0.0.0.0/0",
        "DBInstanceStorage": "20",
        "VSwitchId": {
          "Ref": "ServerSwitch"
        },
        "ConnectionMode": "Performance",
        "PreferredBackupTime": "00:00Z-01:00Z",
        "BackupRetentionPeriod": 7,
        "PreferredBackupPeriod": [
          "Sunday"
        ]
      }
    },
    "Server": {
      "Type": "ALIYUN::ECS::Instance",
      "DependsOn": [
        "LYDatabase"
      ],
      "Properties": {
        "SystemDiskCategory": "cloud_efficiency",
        "IoOptimized": "optimized",
        "InternetChargeType": "PayByTraffic",
        "VpcId": {
          "Ref": "ALIYUN-ECS-VPC1"
        },
        "HostName": "Server",
        "ImageId": "win2016_64_dtc_1607_zh-cn_40G_alibase_20170915.vhd",
        "InstanceChargeType": "PostPaid",
        "VSwitchId": {
          "Ref": "ServerSwitch"
        },
        "Password": "Ly1pass!@#",
        "InstanceType": "ecs.n4.large",
        "SystemDiskSize": "40",
        "ZoneId": "cn-shenzhen-a",
        "InternetMaxBandwidthOut": 1,
        "InternetMaxBandwidthIn": 200,
        "UserData": {
          "Fn::Join": [
            "",
            [
              "[powershell]",
              "\n",
              "$keyid=",
              {
                "Fn::GetAtt": [
                   "RamAK",
                  "AccessKeyId"
                ]
              },
              "\n",
              "$keysec=",
              {
                "Fn::GetAtt": [
                  "RamAK",
                  "AccessKeySecret"
                ]
              },
              "\n",
              "$rdsid=",
              {
                "Fn::GetAtt": [
                  "LYDatabase",
                  "DBInstanceId"
                ]
              },
              "\n",
              "python C:\\RDSSQLCreateMigrateTasksBatchly.py -k '$keyid -s '$keysec -i '$rdsid -e oss_endpoint -b oss_bucket -d directory"
            ]
          ]
        },
        "SecurityGroupId": {
          "Ref": "ServerSecurityGroup"
        },
        "Period": 1,
        "AllocatePublicIP": true
      }
    }
  },
  "Outputs": {}
}



相关实践学习
2分钟自动化部署人生模拟器
本场景将带你借助云效流水线Flow实现人生模拟器小游戏的自动化部署
7天玩转云服务器
云服务器ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,可降低 IT 成本,提升运维效率。本课程手把手带你了解ECS、掌握基本操作、动手实操快照管理、镜像管理等。了解产品详情:&nbsp;https://www.aliyun.com/product/ecs
相关文章
|
25天前
|
安全 关系型数据库 MySQL
如何将数据从MySQL同步到其他系统
【10月更文挑战第17天】如何将数据从MySQL同步到其他系统
144 0
|
1月前
|
SQL 前端开发 关系型数据库
全表数据核对 ,行数据核对,列数据核对,Mysql 8.0 实例(sample database classicmodels _No.3 )
全表数据核对 ,行数据核对,列数据核对,Mysql 8.0 实例(sample database classicmodels _No.3 )
46 0
全表数据核对 ,行数据核对,列数据核对,Mysql 8.0 实例(sample database classicmodels _No.3 )
|
7天前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
本文介绍了MySQL InnoDB存储引擎中的数据文件和重做日志文件。数据文件包括`.ibd`和`ibdata`文件,用于存放InnoDB数据和索引。重做日志文件(redo log)确保数据的可靠性和事务的持久性,其大小和路径可由相关参数配置。文章还提供了视频讲解和示例代码。
113 11
【赵渝强老师】MySQL InnoDB的数据文件与重做日志文件
|
7天前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
在项目中,为了解决Redis与Mysql的数据一致性问题,我们采用了多种策略:对于低一致性要求的数据,不做特别处理;时效性数据通过设置缓存过期时间来减少不一致风险;高一致性但时效性要求不高的数据,利用MQ异步同步确保最终一致性;而对一致性和时效性都有高要求的数据,则采用分布式事务(如Seata TCC模式)来保障。
40 14
|
10天前
|
SQL 前端开发 关系型数据库
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
SpringBoot使用mysql查询昨天、今天、过去一周、过去半年、过去一年数据
41 9
|
22天前
|
SQL Java 关系型数据库
java连接mysql查询数据(基础版,无框架)
【10月更文挑战第12天】该示例展示了如何使用Java通过JDBC连接MySQL数据库并查询数据。首先在项目中引入`mysql-connector-java`依赖,然后通过`JdbcUtil`类中的`main`方法实现数据库连接、执行SQL查询及结果处理,最后关闭相关资源。
|
18天前
|
SQL 关系型数据库 MySQL
定时任务频繁插入数据导致锁表问题 -> 查询mysql进程
定时任务频繁插入数据导致锁表问题 -> 查询mysql进程
38 1
|
19天前
|
SQL 关系型数据库 MySQL
mysql数据误删后的数据回滚
【11月更文挑战第1天】本文介绍了四种恢复误删数据的方法:1. 使用事务回滚,通过 `pymysql` 库在 Python 中实现;2. 使用备份恢复,通过 `mysqldump` 命令备份和恢复数据;3. 使用二进制日志恢复,通过 `mysqlbinlog` 工具恢复特定位置的事件;4. 使用延迟复制从副本恢复,通过停止和重启从库复制来恢复数据。每种方法都有详细的步骤和示例代码。
|
7天前
|
关系型数据库 MySQL 数据库
【赵渝强老师】启动与关闭MySQL数据库实例
MySQL数据库安装完成后,可以通过命令脚本启动、查看状态、配置开机自启、查看自启列表及关闭数据库。本文提供了详细的操作步骤和示例代码,并附有视频讲解。
|
30天前
|
存储 关系型数据库 MySQL
mysql 8.0 的 建表 和八种 建表引擎实例
mysql 8.0 的 建表 和八种 建表引擎实例
20 0

推荐镜像

更多