Nouvelles Chroniques d'Amethyste

Penser au Sens, pas au Verbe

Scale up/down d’une base SQL Azure par code

Poster un commentaire

Il existe diverses circonstances pour lesquelles on a besoin de rescaler dynamiquement une base SQL Azure. Dans mon cas je devais lancer un script SSIS très impactant d’où le besoin de passer momentanément à un tiers de facturation assurant plus de DTU.

Il existe 4 méthodes:

  1. Script T-SQL
  2. Api REST
  3. SDK .Net
  4. PowerShell

Je vais examiner ces méthodes dans cet article, mais remarquez tout de même que dans les coulisses, le SDK appelle les Api REST comme Fiddler vous le confirmera aisément. Pour moi il s’agit donc de la même méthode.

Avant de commencer, je vous encourage comme toujours à ne pas me faire confiance et tester vous même le code proposé, mais faites TRES attention à certaines choses:

2016-11-11_00-21-55

 

Une base SQL ca peut être très cher, n’oubliez donc pas de redescendre le tiers dès que possible!

Pour tester il faudra une base SQL Azure:

2016-11-13_10-59-21

On peut utiliser un serveur existant ou bien en créer un spécifique, c’est ce que j’ai fait.

Notez le groupe de ressources scalingdemo, le serveur est serverscaling et la base basescaling.

Par défaut la base est en S0.

Script T-SQL

Il est possible de passer par exemple en version S1 avec le code suivant:

ALTER DATABASE <MABASE> Modify (SERVICE_OBJECTIVE = ‘S1’)

Vous pouvez ensuite suivre le déroulement des opérations en surveillant la valeur de SERVICE_OBJECTIVE:

SELECT DATABASEPROPERTYEX(<MABASE>, ‘ServiceObjective’)

Ou un peu plus complet:

SELECT @@VERSION AS AzureVersion,
DATABASEPROPERTYEX(DB_NAME(), ‘Edition’) AS AzureEdition,
COALESCE(DATABASEPROPERTYEX(DB_NAME(), ‘ServiceObjective’), ‘N/A in v11’) AS AzureTier

 

2016-11-13_11-24-42

 

Plusieurs remarques.

  • La méthode ne marche que pour les bases en V12, concrètement des éditions comme Web ou Business ne sont pas supportées.
  • La documentation T-SQL intéressante:

https://msdn.microsoft.com/fr-fr/library/ms174269.aspx

  • le login doit être dbmanager

 

La commande SQL rend la main immédiatement, mais cela ne signifie pas que la base a basculée. Lors de mes essais j’ai même constaté qu’il ne suffit pas que ServiceObjective soit à S1 pour que la base soit prête, il y a apparemment une latence que je ne sais pas expliquer.

Je ne suis pas parvenu à surmonter le problème avec une solution purement SQL.

Je pense que l’on pourrai compléter la requête en récupérant une référence vers la ressource SQL Server et en surveillant son état. Je n’ai pas essayé parce que les méthodes suivantes me semblent à tout prendre plus simple car elle font nativement le boulot!

Api REST

Je mentionne cette méthode pour l’exhaustivité, mais ce n’est probablement pas celle que vous préfèrerez. Je ne propose d’ailleurs pas de démo. Le SDK ou PowerShell est un choix plus praticable je trouve.

 

Voici les liens intéressants:

Etat de la base:

https://msdn.microsoft.com/en-us/library/azure/mt643935.aspx

Update de la base:

https://msdn.microsoft.com/en-us/library/azure/mt163685.aspx

 

Et un exemple en C# qui montre comment appeler une api REST Azure:

http://rickrainey.com/2013/10/17/calling-azure-service-management-rest-apis-from-c/

Je vais en rester là pour cette solution.

SDK .Net

Comment faire

C’est la solution que je conseille car de loin la plus simple.

On a besoin d’installer deux packages Nuget encore en preview. Par exemple depuis la console:

Install-Package Microsoft.Azure.Management.Sql –Pre
Install-Package Microsoft.Azure.Management.ResourceManager –Pre

 

Notre première étape consiste à obtenir un SqlManagementClient. C’est la classe qui va nous permettre d’accéder et de modifier la base SQL Azure.


TokenCloudCredentials tokenCloudCredentials = new TokenCloudCredentials(subscriptionId, token);
SqlManagementClient sqlMgmtClient = new SqlManagementClient(tokenCloudCredentials);

  • Token est un jeton d’authentification obtenu auprès d’Azure AD soit via un certificat, soit via un Id et un secret
    Vous trouverez en bibliographie des exemple pour les construire
  • SubscriptionId est l’id de la souscription dans laquelle la base est déployée. Ce pourra être un paramètre de déploiement de l’application, mais il est possible de l’obtenir dynamiquement avec Microsoft.Azure.Management.ResourceManager.SubscriptionClient

Maintenant que nous somme armés, on attaque les choses sérieuses.

// Récupère le serveur qui héberge la base
Server currentServer = sqlMgmtClient.Servers.Get(resourceGroupName, serverName).Server;
 
// Paramètre pour mettre à jour la base
DatabaseCreateOrUpdateParameters newDatabaseParameters = new DatabaseCreateOrUpdateParameters()
{
   Location = currentServer.Location,
   Properties = new DatabaseCreateOrUpdateProperties()
   {
      CreateMode = DatabaseCreateMode.Default,
      RequestedServiceObjectiveName = targetTiers
   }
};

DatabaseCreateOrUpdateResponse dbResponse = sqlMgmtClient.Databases.CreateOrUpdate(resourceGroupName, 
                    serverName, databaseName, newDatabaseParameters);

 

On récupère une instance de Server qui est une classe proxy pour le serveur cible, celui qui héberge la base que l’on souhaite scaler. On a donc besoin du groupe de ressource dans lequel il est déployé (on utilise une interface ARM ne l’oublions pas) et du nom du serveur que l’on récupère par exemple dans la chaîne de connexion.

DatabaseCreateOrUpdateParameters  est une classe qui va décrire tout ce qui est nécessaire pour créer ou mettre à jour une base de données. Ici on fait une mise à jour et c’est le paramètre RequestedServiceObjectiveName  qui va nous intéresser. On lui passe la nouvelle valeur du tiers de facturation, par exemple P4.

La dernière ligne ne présente pas de difficultés particulière. On appelle CreateOrUpdate. Le nom de la base de données se trouve lui aussi dans la chaîne de connexion.

Notez qu’il existe CreateOrUpdateAsync.

 

La méthode se termine une fois la bascule terminée. On a pas besoin de surveiller des états.

Sécurité

Pour que les choses marchent bien, il faudra accorder au principal qui se connecte la permission: Microsoft.Sql/servers/databases/write

2016-11-11_00-32-05

Une solution possible est par exemple de créer un RBAC, un rôle personnalisé qui n’a que cette permission.

https://azure.microsoft.com/en-us/documentation/articles/role-based-access-built-in-roles/#sql-db-contributor

 

PowerShell

Le travail n’est pas particulièrement difficile puisqu’il tient en une seule ligne:

cls
 
Login-AzureRmAccount
 
 
$NewEdition =  'Standard'
$NewPricingTier =  'S1'
 
$ressourceGroupName='scalingdemo'
$sqlServerName = 'serverscaling'
$sqlDatabaseName = 'basescaling'
 
Set-AzureRmSqlDatabase -DatabaseName $sqlDatabaseName `
   -ServerName $sqlServerName `
   -ResourceGroupName $ressourceGroupName `
   -Edition $NewEdition `
   -RequestedServiceObjectiveName $NewPricingTier

Si vous avez plusieurs subscriptions vous devrez peut être lancer quelque chose comme:

Set-AzureRmContext -SubscriptionId

 

La commande Set-AzureRmSqlDatabase est utilisée pour modifier les propriétés de la base de données pour la faire passer en S1. La méthode attend que la bascule soit complète pour rendre la main.

Dans les coulisses

C’est un exercice intéressant de lancer les deux dernières méthodes avec Fiddler activé. On voit que dans les coulisses c’est l’API REST qui est à la manœuvre.

On lance le scaling:

2016-11-13_11-37-34

On attend la fin de l’exécution:

2016-11-13_11-39-56

Et une fois terminé, la réponse change:

2016-11-13_11-41-43

 

Bibliographie

Publicités

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s