简体   繁体   English

参数化 Azure 数据工厂中的连接(ARM 模板)

[英]Parameterize connections in Azure data factory (ARM templates)

I am trying to setup an Azure Data Factory in a CI/CD setup.我正在尝试在 CI/CD 设置中设置 Azure 数据工厂。 I followed Microsoft's best practices ( https://docs.microsoft.com/en-us/azure/data-factory/continuous-integration-deployment ).我遵循了 Microsoft 的最佳实践( https://docs.microsoft.com/en-us/azure/data-factory/continuous-integration-deployment )。

I have 4 environments (dev, test, UAT, PRD)我有 4 个环境(开发、测试、UAT、PRD)

In short what I have done:简而言之,我做了什么:

  • Create an Azure data factory and link it to my Azure DevOps repo on DEV environment创建一个 Azure 数据工厂并将其链接到我在 DEV 环境中的 Azure DevOps 存储库

  • Create an Azure data factory on the other environments (test, UAT and PRD), but do NOT link it to DevOps.在其他环境(测试、UAT 和 PRD)上创建 Azure 数据工厂,但不要将其链接到 DevOps。 Instead, pipelines are released on these data factories using ARM templates and release pipelines in Azure DevOps.而是使用 ARM 模板在这些数据工厂上发布管道,并在 Azure DevOps 中发布管道。

  • I have parameterized all necessary parts to be able to overwrite the settings in each of my environments.我已经参数化了所有必要的部分,以便能够覆盖我每个环境中的设置。

At this moment, I am able to succesfully deploy to my other environments, however, the linkedservice to my database on azure is not working.此时,我能够成功部署到我的其他环境,但是,我在 azure 上的数据库的链接服务无法正常工作。 I have parameterized everything, like Microsoft suggests, but when I export my linkedservice to an ARM template, it uses a connection string instead of my parameterized settings.我已经参数化了一切,就像微软建议的那样,但是当我将我的链接服务导出到 ARM 模板时,它使用连接字符串而不是我的参数化设置。

Below is a picture of my settings in the Azure Data Factory portal:下面是我在 Azure 数据工厂门户中的设置图片:daf 设置

When I try to export this to ARM templates, I get the following:当我尝试将其导出到 ARM 模板时,我得到以下信息:

{
            "name": "[concat(parameters('factoryName'), '/database')]",
            "type": "Microsoft.DataFactory/factories/linkedServices",
            "apiVersion": "2018-06-01",
            "properties": {
                "parameters": {
                    "sqlServerUrl": {
                        "type": "string"
                    },
                    "databaseName": {
                        "type": "string"
                    },
                    "sqlPwd": {
                        "type": "string"
                    },
                    "sqlAdminUsername": {
                        "type": "string"
                    }
                },
                "annotations": [],
                "type": "AzureSqlDatabase",
                "typeProperties": {
                    "connectionString": {
                        "type": "SecureString",
                        "value": "[parameters('database_connectionString')]"
                    }
                }
            },
            "dependsOn": []
        },

The problem with this ARM templates is that it does not use the parameters to create the connection string, but it uses the connection string parameter database_connectionString (the connection string is by default always parameterized by Azure, so I cannot remove this parameter).这个ARM模板的问题在于它没有使用参数来创建连接字符串,而是使用连接字符串参数database_connectionString(默认情况下连接字符串总是由Azure参数化,所以我不能删除这个参数)。

When the release pipeline uses this template, the connectionstring is not filled in (only the parameters are filled in) and hence, the connection to the database fails.发布管道使用此模板时,没有填写连接字符串(仅填写参数),因此与数据库的连接失败。 How should you setup the connection so that you can automatically (without human interaction) deploy to all environments by only changing the parameters?您应该如何设置连接,以便您只需更改参数即可自动(无需人工交互)部署到所有环境?

I do not want to change the ARM templates coming from Azure Data Factory, because this requires human interaction我不想更改来自 Azure 数据工厂的 ARM 模板,因为这需要人工交互

One of the other answers provided is a valid way using override parameters.提供的其他答案之一是使用覆盖参数的有效方法。 This answer will provide a different answer as well as some more context on how to define the SQL connections and how to utilize and implement some of the updates made with Key Vault and Data Factory Integration.此答案将提供不同的答案以及有关如何定义 SQL 连接以及如何利用和实施通过 Key Vault 和数据工厂集成所做的一些更新的更多上下文。

If using an on prem connection to SQL the conenction string will look like:如果使用本地连接到 SQL,则连接字符串将如下所示:

"Server={serverName};Database={databaseName};User ID={domain}\{userName};Password={password};Integrated Security=True;" 

The quotes are required and can be passed in as an override parameter.引号是必需的,可以作为覆盖参数传入。

If using an Azure Database or even using Key Vault look to add Managed Identity which Data Factory Supports by including this in your ARM template如果使用 Azure 数据库甚至使用 Key Vault,请通过将其包含在 ARM 模板中来添加数据工厂支持托管标识

 "identity": {
        "type": "SystemAssigned"
    }

Once this is added then the Azure SQL Database will need to have the managed identity added .添加后,Azure SQL 数据库将需要添加托管标识 This can be done via a reusable SQL Script like:这可以通过可重用的 SQL 脚本来完成,例如:

    DECLARE @rolename AS NVARCHAR(100) = 'DataFactory_User'
    DECLARE @username AS NVARCHAR(100) -- This will be the DataFactory name
    SET @username = 'DataFacotryName'

if exists(select * from sys.database_principals where name = @username and Type = 'X' or Type='E')
    BEGIN
        DECLARE @dropUserSql varchar(1000)
        SET @dropUserSql='DROP USER [' + @username + ']'
        PRINT 'Executing ' + @dropUserSql
        EXEC (@dropUserSql)
        PRINT 'Completed ' + @dropUserSql
    END

DECLARE @createUserSql varchar(1000)
SET @createUserSql='CREATE USER [' + @username + '] FROM EXTERNAL PROVIDER'
PRINT 'Executing ' + @createUserSql
EXEC (@createUserSql)
PRINT 'Completed ' + @createUserSql

I recommend dropping and recreating this user.我建议删除并重新创建此用户。 SQL recognizes the thumbprint of the Managed Identity and everytime the DataFactory is dropped and recreated a new thumbprint is created. SQL 识别托管标识的指纹,每次删除并重新创建 DataFactory 时,都会创建一个新的指纹。

In terms of leveraging Key Vault there is a LinkedService type of Key Vault that relies on the Managed Identity described above to retrieve secrets.在利用 Key Vault 方面,有一种 Key Vault 的LinkedService 类型,它依赖于上述托管标识来检索机密。

The Key Vault if deployed via ARM will need to have the access policy updated to something similar to this:如果通过 ARM 部署,Key Vault 需要将访问策略更新为类似于以下内容:

"accessPolicies": [
          {
            "tenantID": "[subscription().tenantId]",
            "objectId": "[reference(resourceId('Microsoft.DataFactory/factories/', parameters('DataFactoryName')), '2018-02-01', 'Full').identity.principalId]",
            "permissions": {
              "secrets": [
                "get"
              ],
              "keys": [
                "get"
              ],
              "certificates": [
                "import"
              ]
            },
            "dependsOn": [
              "[resourceId('Microsoft.DataFactory/factories/', parameters('DataFactoryName'))]"
            ]
          }
        ]

This snippet assumes the Key Vault and Data Factory are in the same ARM template.此代码段假定 Key Vault 和数据工厂位于同一个 ARM 模板中。 If they are not the access policy can still be accomplished via ARM by obtaining the ObjectId of the Data Factory defined Managed Identity and passing it in as the ObjectId and removing the dependsOn statement.如果它们不是,访问策略仍然可以通过 ARM 实现,方法是获取数据工厂定义的托管标识的 ObjectId 并将其作为 ObjectId 传入并删除dependsOn 语句。

Just in case you haven't found an answer or solved this:以防万一你还没有找到答案或解决这个问题:

I was in a very similar situation, I had several Azure SQL databases that were parameterized (database name), and needed to change the SQL server name in my ADF Azure Release Pipeline to swap between environments.我处于非常相似的情况,我有几个参数化的 Azure SQL 数据库(数据库名称),需要更改 ADF Azure Release Pipeline 中的 SQL 服务器名称以在环境之间交换。

I found that by inspecting the code definition of the Linked Service ({} next to it), you can get a connection string that includes any parameters that you have defined:我发现通过检查链接服务的代码定义(它旁边的 {}),您可以获得一个连接字符串,其中包含您定义的任何参数:

链接服务代码视图

连接字符串参数

I copied the value of "connectionString" and modified what I needed to (server address) and left the parameters in place, and added it to the "connectionString" override parameter in my Azure Release Pipeline, and it worked!我复制了“connectionString”的值并修改了我需要的内容(服务器地址)并保留了参数,并将其添加到我的 Azure Release Pipeline 中的“connectionString”覆盖参数中,并且它起作用了! (include the quotes!) (包括引号!)

I hope that this helps you or anyone in future suffering the same frustration/confusion.我希望这可以帮助您或将来遭受同样挫折/困惑的任何人。

I do this by using the Azure resource group deployment task in the Release.我通过使用 Release 中的Azure resource group deployment任务来执行此操作。 One of the options is Override template parameters which will allow you to do exactly what you need.选项之一是Override template parameters ,这将允许您完全按照您的需要进行操作。 You can create a space separated list of parameters to override your ARM Template and pass in a Variable您可以创建一个空格分隔的参数列表来覆盖您的 ARM 模板并传入一个变量

In your case it would be在你的情况下,它会是

-database_connectionstring $(VariableHere)

I would store the connection string in Azure KeyVault and link it to a Secure Variable Group.我会将连接字符串存储在 Azure KeyVault 中并将其链接到安全变量组。 You can also just hit the padlock on a standard variable to secure it.您也可以在标准变量上打上挂锁来保护它。

Then bind your custom variable to each Stage in your Release然后将自定义变量绑定到 Release 中的每个 Stage

Task任务在此处输入图片说明

Override覆盖在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM