티스토리 뷰
67. Redgate SQL 변경 자동화 및 Azure DevOps를 사용하여 데이터베이스 변경 사항 배포 1편
zerobig-k8s 2021. 1. 18. 07:58<참조> https://www.azuredevopslabs.com/labs/vstsextend/redgate/
이 랩은 확인 및 정리할 내용이 다소 많아 2편에 걸쳐 분리하여 포스팅 하고자 한다. 먼저 1편을 정리한다. |
개요
데이터베이스 DevOps 완전히 개발되었다. DevOps의 성공적인 구현에 기여할 수있는 핵심 기술 관행으로 간주되어 데이터베이스 병목 현상을 제거하고 릴리스를 더 빠르고 쉽게 할 수 있다. 조직이 DevOps를 구현하지 못하게하는 일반적인 차단기는 데이터베이스이다. 고유한 요구 사항이 있으며 종종 애플리케이션 개발에 사용되는 것과 완전히 다른 개발 프로세스를 따른다. 여기에서 Redgate SQL Change Automation은 Redgate SQL Change Automation을 사용하여 Visual Studio에서 개발, 소스 제어 및 안전한 자동화 된 SQL Server 및 Azure SQL 데이터베이스 배포를 지원한다.
Redgate SQL Change Automation은 Visual Studio 내부의 마이그레이션 우선 데이터베이스 개발 및 배포 도구로, DevOps 프로세스를 SQL Server 데이터베이스로 확장하여 다음을 수행 할 수 있다.
- 데이터베이스가 병목 현상으로 인해 가치를 신속하게 제공하지 못하도록 방지
- 정밀성 및 제어력을 가지고 데이베이스 변경 배포 자동화
- 단일 진실 공급원(single source of truth)을 위한 애플리케이션 변경과 함께 데이터베이스 변경 관리
- Azure DevOps 및 TFS를 포함한 기존 빌드 및 릴리스 도구와 통합
이 랩에서 다루는 것
이번 랩에서 다음을 살펴 볼 것이다.
1. Ansible 및 Azure 파이프 라인을 사용하여 클라우드에서 인프라 배포를 자동화하는 방법
2. 애플리케이션 변경과 함께 SQL Server 데이터베이스 변경 배포를 자동화하는 방법
시작하기 전에
1. Azure DevOps 계정이 필요합니다. 계정이 없는 경우 여기에서 무료로 등록 할 수 있다.
2. Redgate SQL Change Automation 확장이 설치된 Visual Studio Enterprise 2017 또는 2019가 필요하다.
그리고 다음 확장은 Azure DevOps 조직에 설치해야 한다.
3. Azure Portal에서 Azure Cloud Shell을 시작하고 Bash를 선택한다.
4. Azure Web App을 생성한다.
4.1 리소스 그룹을 만든다. <region>을 선택한 지역 (예 : koreacentral)으로 바꾼다.
rgName = redgatesql-demo-rg kim@Azure:~$ loc=koreacentral az group create --name $rgName --location $loc |
kim@Azure:~$ rgName=redgatesql-demo-rg
kim@Azure:~$ loc=koreacentral
kim@Azure:~$
kim@Azure:~$ az group create --name $rgName --location $loc
{
"id": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg",
"location": "koreacentral",
"managedBy": null,
"name": "redgatesql-demo-rg",
"properties": {
"provisioningState": "Succeeded"
},
"tags": null,
"type": "Microsoft.Resources/resourceGroups"
}
4.2 App Service 계획을 만든다.
az appservice plan create --resource-group $rgName --name MyPlan --sku S1 |
kim@Azure:~$ az appservice plan create --resource-group $rgName --name MyPlan --sku S1
{- Finished ..
"freeOfferExpirationTime": null,
"geoRegion": "Korea Central",
"hostingEnvironmentProfile": null,
"hyperV": false,
"id": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg/providers/Microsoft.Web/serverfarms/MyPlan",
"isSpot": false,
"isXenon": false,
"kind": "app",
"location": "koreacentral",
"maximumElasticWorkerCount": 1,
"maximumNumberOfWorkers": 0,
"name": "MyPlan",
"numberOfSites": 0,
"perSiteScaling": false,
"provisioningState": "Succeeded",
"reserved": false,
"resourceGroup": "redgatesql-demo-rg",
"sku": {
"capabilities": null,
"capacity": 1,
"family": "S",
"locations": null,
"name": "S1",
"size": "S1",
"skuCapacity": null,
"tier": "Standard"
},
"spotExpirationTime": null,
"status": "Ready",
"subscription": "1199b626-xxxx-xxxx-xxxx-0caba7859ee88",
"tags": null,
"targetWorkerCount": 0,
"targetWorkerSizeId": 0,
"type": "Microsoft.Web/serverfarms",
"workerTierName": null
}
4.3 고유한 앱 이름으로 웹앱을 만든다.
az webapp create --resource-group $rgName --plan MyPlan --name MyUniqueAppName |
kim@Azure:~$ az webapp create --resource-group $rgName --plan MyPlan --name zerowa4redgate
{- Finished ..
"availabilityState": "Normal",
"clientAffinityEnabled": true,
"clientCertEnabled": false,
"clientCertExclusionPaths": null,
"cloningInfo": null,
"containerSize": 0,
"dailyMemoryTimeQuota": 0,
"defaultHostName": "zerowa4redgate.azurewebsites.net",
"enabled": true,
"enabledHostNames": [
"zerowa4redgate.azurewebsites.net",
"zerowa4redgate.scm.azurewebsites.net"
],
"ftpPublishingUrl": "ftp://waws-prod-se1-001.ftp.azurewebsites.windows.net/site/wwwroot",
"hostNameSslStates": [
{
"hostType": "Standard",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "zerowa4redgate.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
},
{
"hostType": "Repository",
"ipBasedSslResult": null,
"ipBasedSslState": "NotConfigured",
"name": "zerowa4redgate.scm.azurewebsites.net",
"sslState": "Disabled",
"thumbprint": null,
"toUpdate": null,
"toUpdateIpBasedSsl": null,
"virtualIp": null
}
],
"hostNames": [
"zerowa4redgate.azurewebsites.net"
],
"hostNamesDisabled": false,
"hostingEnvironmentProfile": null,
"httpsOnly": false,
"hyperV": false,
"id": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg/providers/Microsoft.Web/sites/zerowa4redgate",
"identity": null,
"inProgressOperationId": null,
"isDefaultContainer": null,
"isXenon": false,
"kind": "app",
"lastModifiedTimeUtc": "2021-01-16T00:24:11.250000",
"location": "Korea Central",
"maxNumberOfWorkers": null,
"name": "zerowa4redgate",
"outboundIpAddresses": "52.231.32.121,52.231.32.122,52.231.32.123,52.231.32.124",
"possibleOutboundIpAddresses": "52.231.32.121,52.231.32.122,52.231.32.123,52.231.32.124,52.231.90.246,20.41.74.214,20.41.73.5,20.41.73.65,20.41.73.185,52.231.32.120,52.231.18.128",
"redundancyMode": "None",
"repositorySiteName": "zerowa4redgate",
"reserved": false,
"resourceGroup": "redgatesql-demo-rg",
"scmSiteAlsoStopped": false,
"serverFarmId": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg/providers/Microsoft.Web/serverfarms/MyPlan",
"siteConfig": {
"acrUseManagedIdentityCreds": false,
"acrUserManagedIdentityId": null,
"alwaysOn": null,
"apiDefinition": null,
"apiManagementConfig": null,
"appCommandLine": null,
"appSettings": null,
"autoHealEnabled": null,
"autoHealRules": null,
"autoSwapSlotName": null,
"azureMonitorLogCategories": null,
"azureStorageAccounts": null,
"connectionStrings": null,
"cors": null,
"customAppPoolIdentityAdminState": null,
"customAppPoolIdentityTenantState": null,
"defaultDocuments": null,
"detailedErrorLoggingEnabled": null,
"documentRoot": null,
"experiments": null,
"fileChangeAuditEnabled": null,
"ftpsState": null,
"functionAppScaleLimit": null,
"functionsRuntimeScaleMonitoringEnabled": null,
"handlerMappings": null,
"healthCheckPath": null,
"http20Enabled": null,
"httpLoggingEnabled": null,
"ipSecurityRestrictions": [
{
"action": "Allow",
"description": "Allow all access",
"ipAddress": "Any",
"name": "Allow all",
"priority": 1,
"subnetMask": null,
"subnetTrafficTag": null,
"tag": null,
"vnetSubnetResourceId": null,
"vnetTrafficTag": null
}
],
"javaContainer": null,
"javaContainerVersion": null,
"javaVersion": null,
"limits": null,
"linuxFxVersion": null,
"loadBalancing": null,
"localMySqlEnabled": null,
"logsDirectorySizeLimit": null,
"machineKey": null,
"managedPipelineMode": null,
"managedServiceIdentityId": null,
"metadata": null,
"minTlsVersion": null,
"minimumElasticInstanceCount": 0,
"netFrameworkVersion": null,
"nodeVersion": null,
"numberOfWorkers": null,
"phpVersion": null,
"powerShellVersion": null,
"preWarmedInstanceCount": null,
"publishingPassword": null,
"publishingUsername": null,
"push": null,
"pythonVersion": null,
"remoteDebuggingEnabled": null,
"remoteDebuggingVersion": null,
"requestTracingEnabled": null,
"requestTracingExpirationTime": null,
"routingRules": null,
"runtimeADUser": null,
"runtimeADUserPassword": null,
"scmIpSecurityRestrictions": [
{
"action": "Allow",
"description": "Allow all access",
"ipAddress": "Any",
"name": "Allow all",
"priority": 1,
"subnetMask": null,
"subnetTrafficTag": null,
"tag": null,
"vnetSubnetResourceId": null,
"vnetTrafficTag": null
}
],
"scmIpSecurityRestrictionsUseMain": null,
"scmMinTlsVersion": null,
"scmType": null,
"tracingOptions": null,
"use32BitWorkerProcess": null,
"virtualApplications": null,
"vnetName": null,
"vnetPrivatePortsCount": null,
"vnetRouteAllEnabled": null,
"webSocketsEnabled": null,
"websiteTimeZone": null,
"winAuthAdminState": null,
"winAuthTenantState": null,
"windowsFxVersion": null,
"xManagedServiceIdentityId": null
},
"slotSwapStatus": null,
"state": "Running",
"suspendedTill": null,
"tags": null,
"targetSwapSlot": null,
"trafficManagerHostNames": null,
"type": "Microsoft.Web/sites",
"usageState": "Normal"
}
5. Azure SQL 서버 및 데이터베이스를 만든다.
5.1 Azure SQL server를 만든다.
az sql server create -l $loc -g $rgName -n <unique-sqlserver-name> -u sqladmin -p P2ssw0rd1234 |
kim@Azure:~$ az sql server create -l $loc -g $rgName -n zerosql4redgate -u sqladmin -p P2ssw0rd1234
{- Finished ..
"administratorLogin": "sqladmin",
"administratorLoginPassword": null,
"fullyQualifiedDomainName": "zerosql4redgate.database.windows.net",
"id": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg/providers/Microsoft.Sql/servers/zerosql4redgate",
"identity": null,
"kind": "v12.0",
"location": "koreacentral",
"minimalTlsVersion": null,
"name": "zerosql4redgate",
"privateEndpointConnections": [],
"publicNetworkAccess": "Enabled",
"resourceGroup": "redgatesql-demo-rg",
"state": "Ready",
"tags": null,
"type": "Microsoft.Sql/servers",
"version": "12.0"
}
중요 : 고유한 SQL 서버 이름을 입력한다. Azure SQL Server 이름은 UPPER / Camel 대소문자 명명 규칙을 지원하지 않으므로 SQL Server Name 필드 값에 소문자를 사용합니다.
5.2 pul-dev 및 pul-prod라는 두 개의 데이터베이스를 만든다.
az sql db create -g $rgName -s <unique-sqlserver-name> -n pul-dev --service-objective S0 |
kim@Azure:~$ az sql db create -g $rgName -s zerosql4redgate -n pul-dev --service-objective S0
{- Finished ..
"autoPauseDelay": null,
"backupStorageRedundancy": "Geo",
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"collation": "SQL_Latin1_General_CP1_CI_AS",
"createMode": null,
"creationDate": "2021-01-16T00:29:17.447000+00:00",
"currentServiceObjectiveName": "S0",
"currentSku": {
"capacity": 10,
"family": null,
"name": "Standard",
"size": null,
"tier": "Standard"
},
"databaseId": "bc8e1be7-7abe-44a7-92f0-edbc2f5bcfe3",
"defaultSecondaryLocation": "koreasouth",
"earliestRestoreDate": "2021-01-16T00:59:17.447000+00:00",
"edition": "Standard",
"elasticPoolId": null,
"elasticPoolName": null,
"failoverGroupId": null,
"id": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg/providers/Microsoft.Sql/servers/zerosql4redgate/databases/pul-dev",
"kind": "v12.0,user",
"licenseType": null,
"location": "koreacentral",
"longTermRetentionBackupResourceId": null,
"managedBy": null,
"maxLogSizeBytes": null,
"maxSizeBytes": 268435456000,
"minCapacity": null,
"name": "pul-dev",
"pausedDate": null,
"readReplicaCount": 0,
"readScale": "Disabled",
"recoverableDatabaseId": null,
"recoveryServicesRecoveryPointId": null,
"requestedServiceObjectiveName": "S0",
"resourceGroup": "redgatesql-demo-rg",
"restorableDroppedDatabaseId": null,
"restorePointInTime": null,
"resumedDate": null,
"sampleName": null,
"sku": {
"capacity": 10,
"family": null,
"name": "Standard",
"size": null,
"tier": "Standard"
},
"sourceDatabaseDeletionDate": null,
"sourceDatabaseId": null,
"status": "Online",
"tags": null,
"type": "Microsoft.Sql/servers/databases",
"zoneRedundant": false
}
az sql db create -g $rgName -s <unique-sqlserver-name> -n pul-prod --service-objective S0 |
kim@Azure:~$ az sql db create -g $rgName -s zerosql4redgate -n pul-prod --service-objective S0
{- Finished ..
"autoPauseDelay": null,
"backupStorageRedundancy": "Geo",
"catalogCollation": "SQL_Latin1_General_CP1_CI_AS",
"collation": "SQL_Latin1_General_CP1_CI_AS",
"createMode": null,
"creationDate": "2021-01-16T00:30:40.120000+00:00",
"currentServiceObjectiveName": "S0",
"currentSku": {
"capacity": 10,
"family": null,
"name": "Standard",
"size": null,
"tier": "Standard"
},
"databaseId": "5ea5dfee-9178-406e-ae6b-1909c5b8e688",
"defaultSecondaryLocation": "koreasouth",
"earliestRestoreDate": "2021-01-16T01:00:40.120000+00:00",
"edition": "Standard",
"elasticPoolId": null,
"elasticPoolName": null,
"failoverGroupId": null,
"id": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg/providers/Microsoft.Sql/servers/zerosql4redgate/databases/pul-prod",
"kind": "v12.0,user",
"licenseType": null,
"location": "koreacentral",
"longTermRetentionBackupResourceId": null,
"managedBy": null,
"maxLogSizeBytes": null,
"maxSizeBytes": 268435456000,
"minCapacity": null,
"name": "pul-prod",
"pausedDate": null,
"readReplicaCount": 0,
"readScale": "Disabled",
"recoverableDatabaseId": null,
"recoveryServicesRecoveryPointId": null,
"requestedServiceObjectiveName": "S0",
"resourceGroup": "redgatesql-demo-rg",
"restorableDroppedDatabaseId": null,
"restorePointInTime": null,
"resumedDate": null,
"sampleName": null,
"sku": {
"capacity": 10,
"family": null,
"name": "Standard",
"size": null,
"tier": "Standard"
},
"sourceDatabaseDeletionDate": null,
"sourceDatabaseId": null,
"status": "Online",
"tags": null,
"type": "Microsoft.Sql/servers/databases",
"zoneRedundant": false
}
5.3 Azure 서비스에서 액세스를 허용하는 SQL Server에 대한 방화벽 규칙을 만든다.
az sql server firewall-rule create --resource-group $rgName --server <your-sqlserver-name> --name AllowAllAzureIps --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0 |
kim@Azure:~$ az sql server firewall-rule create --resource-group $rgName --server zerosql4redgate --name AllowAllAzureIps --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0
{
"endIpAddress": "0.0.0.0",
"id": "/subscriptions/1199b626-xxxx-xxxx-xxxx-0caba7859ee88/resourceGroups/redgatesql-demo-rg/providers/Microsoft.Sql/servers/zerosql4redgate/firewallRules/AllowAllAzureIps",
"kind": "v12.0",
"location": "Korea Central",
"name": "AllowAllAzureIps",
"resourceGroup": "redgatesql-demo-rg",
"startIpAddress": "0.0.0.0",
"type": "Microsoft.Sql/servers/firewallRules"
}
6. 초기 데이터베이스 스키마를 pul-dev 및 pul-prod 데이터베이스로 가져 오겠다. 이 데이터베이스는 다음 실습에서 만들 SQL 변경 자동화 프로젝트의 시작점으로 사용된다.
7. Azure 리소스에서 pul-dev SQL 데이터베이스를 선택한다. 왼쪽 메뉴에서 Query editor (preview)를 찾아 선택한다. 데이터베이스를 만드는데 사용된 서버 관리자 계정의 사용자 ID와 암호를 입력한다. OK를 선택한다.
8. 다음 창에서 여기에서 스크립트를 복사하고 query 창에 붙여 넣는다. Run을 클릭한다. 이 스크립트는 애플리케이션에 필요한 초기 데이터베이스 스키마를 생성한다.
Query succeeded: Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 93Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0Affected rows: 0
9. pul-prod 데이터베이스에 대해 동일한 단계를 반복한다.
실습 1 : Redgate SQL 변경 자동화 프로젝트 PartsUnlimited 솔루션에 추가
여기서는 기존 PartsUnlimited 애플리케이션 솔루션에서 SQL 변경 자동화 프로젝트를 생성하여 애플리케이션과 함께 데이터베이스 변경을 관리된다. 이 SQL 변경 자동화 프로젝트에는 데이터베이스의 상태와 해당 상태에 도달하는 방법을 설명하는 스크립트 세트가 포함된다.
1. 이 실습에서는 전제조건 섹션에서 과제 1 및 2를 완료해야한다.
2. 이제 SQL 변경 자동화 프로젝트를 만든다. 솔루션을 마우스 오른쪽 단추로 클릭하고 Add –> New Project를 선택한다.
3. Add New Project 창에서 SQL을 검색한다. SQL Change Automation Project 템플릿을 선택하고 Next를 클릭하여 프로젝트를 만든다.
4. Configure your new project에서 프로젝트 이름을 PartsUnlimitedDatabase로 입력하고 Create를 클릭한다.
Set up a new SQL Change Automation Project 마법사에서 Get started를 클릭한다.
5. Database connections 마법사의 개발에서 Specify connection을 선택한다.
결과 창에서 Azure의 pul-dev 데이터베이스를 찾아 선택한다. OK를 클릭한다.
6. 이제 Deployment Target 섹션에서 Specify Connection을 선택하고 pul-prod Azure SQL 데이터베이스를 선택한다.
7. Database connections 마법사에서 Next를 선택하고 다음 창에서 Create Baseline을 클릭하여 프로젝트 생성을 완료한다.
베이스라인 스키마를 생성하기 위해 배포 대상의 스키마를 읽는다. 이렇게 해도 배포 대상을 수정하지 않는다.
8. 이제 솔루션에 추가 된 데이터베이스 프로젝트와 SQL Change Automation Edition 창을 볼 수 있다.
SQL 변경 자동화 프로젝트는 배포 대상의 현재 스키마 인 베이스라인 스키마를 나타내는 마이그레이션 스크립트를 자동으로 생성한다. 1.0.0-Baseline 및 1.1.0-Changes라는 두 개의 폴더도 생성된다. 베이스라인 스키마 마이그레이션 스크립트는 1.0.0-Baseline 폴더에 자동으로 배치되며 프로젝트 배포를 클릭하여 베이스라인 스키마를 샌드 박스 개발 환경에 배포 할 수 있다. 그런 다음 1.1.0-Changes에 배치 될 개발 환경을 변경할 수 있다.
(Client 서비스는 별도로 가이드에 따라 설치 진행한다.)
주의 : 지금 바로 2편으로 이어 실습을 하지 않는 경우라면, 위에서 생성한 Database 등의 리소스를 제거하여 과금 발생에 주의한다.
2편에서 계속
'Azure와 함께 하는 DevOps' 카테고리의 다른 글
69. SonarCloud로 코드 품질 지속적으로 향상 1편 (0) | 2021.02.01 |
---|---|
68. Redgate SQL 변경 자동화 및 Azure DevOps를 사용하여 데이터베이스 변경 사항 배포 2편 (0) | 2021.01.25 |
66. Ansible 및 Azure Pipelines을 사용하여 클라우드에서 인프라 배포 자동화 (0) | 2021.01.11 |
65. AKS에 멀티 컨테이너 애플리케이션 배포하기 (0) | 2021.01.04 |
64. Azure 파이프라인의 Selenium 테스트 자동화 (0) | 2020.12.28 |