What is best strategy to group servers in Azure Deployment Groups - azure

I have 4 target env Dev,QA,UAT and PROD
Each envs has 3 Azure VM , Web , API and Database
Should I Create
4 Deployment Groups Dev, QA, UAT and PROD and Add 3 targets in each of these 4 deployement groups and Tag those targets as Web, API and Database ?
Or Create 3 Deployment Groups Web , API and Database and add 4 targets in each group and tag is as Dev,QA,UAT and PROD ?
Or create 4 Environments (Dev,QA,UAT and PROD ) and add 3 resources in every env.
Note :
Not to mention , every env will have different connection-strings
If I already added one VM as a target in deployment group , I can not add it as a resource in environment
I want to use same release pipeline to deploy to Dev --> QA --> UAT --> PROD in stages with approval. Basically build once and deploy to multiple envs.

You cannot use environments with the classic release pipelines. So option 3 is out. However the described option would be valid if you used YAML pipelines to deploy your application.
Out of options 1 and 2, You should the first one because it has less room for errors and the production environment is better protected. You could also use 12 groups (one for each combination), but the additional effort is probably not worth it.
This would also follow the Microsoft recommendation.
Deployment groups represent the physical environments; for example, "Dev", "Test", or "Production" environment.
[...]
Enable you to use machine tags to limit deployment to specific sets of target servers.

Related

Environments are not automatically created in Azure Devops when declared in yaml pipeline config

I'm new to Azure Devops. I would like to have devops pipeline environments to be created automatically during pipeline flow. So the 5th line below should create environment if it does not exist:
- deployment: Deploy
displayName: Deploy job
pool:
vmImage: $(vmImageName)
environment: 'production'
Instead I'm getting:
What am I missing?
To automate environment creation I could also use Terraform but this time I cannot find terraform resource config responsible for that.
I had a similar problem and found that the documentation lists some possible reasons for why this can happen:
Quote from learn.microsoft.com:
Q: Why am I getting error "Job XXXX: Environment XXXX could not be
found. The environment does not exist or has not been authorized for
use"?
A: These are some of the possible reasons of the failure:
When you author a YAML pipeline and refer to an environment that does not exist
in the YAML file, Azure Pipelines automatically creates the
environment in some cases:
You use the YAML pipeline creation wizard in the Azure Pipelines web
experience and refer to an environment that hasn't been created yet.
You update the YAML file using the Azure Pipelines web editor and save
the pipeline after adding a reference to an environment that does not
exist.
In the following flows, Azure Pipelines does not have
information about the user creating the environment: you update the
YAML file using another external code editor, add a reference to an
environment that does not exist, and then cause a manual or continuous
integration pipeline to be triggered. In this case, Azure Pipelines
does not know about the user. Previously, we handled this case by
adding all the project contributors to the administrator role of the
environment. Any member of the project could then change these
permissions and prevent others from accessing the environment.
If you are using runtime parameters for creating the environment, it
will fail as these parameters are expanded at run time. Environment
creation happens at compile time, so we have to use variables to
create the environment.
A user with stakeholder access level cannot create the environment as
stakeholders do not access to repository.
In our case, the problem was using runtime parameters for creating the environment.
You have the environment name 'production' hardcoded, so your problem might be related to one of the other cases.

Azure DevOps dynamic Release Pipeline creation

I am currently planning on a type of multi-tenant system, were different resource groups with a set of AppServices are deployed for customers via ARM Templates. Hence, each customer has its own Resource Group and set of AppServices. Currently we use Azure DevOps to deploy to a set of AppServices used for Development and Quality Assurance before it gets to Production. I am now trying to incorporate DevOps into the mix, automating a pipeline creation of some sort... (it would be a copy of an existing pipeline but only changing the Target AppServices). Which is were my question comes from, Is there a way to dynamically create or edit a Release pipeline to add the deployment of those new AppServices, without the need of manually edit or create a pipeline an adding those newly created AppServices, I was thinking something around the lines of being able to copy a yaml file template then replacing the necessary info to point to those AppServices after they have been created, but I am not totally sure where could I store the new yaml file so that it is picked up by Azure DevOps, or how could I would accomplish these, with the main idea being that all of this continues to be part of an automated process (if possible).
Thanks a lot for any help, any suggestion is appreciated.
EDIT:
The question is not about how to Deploy an ARM Template through the DevOps release pipeline (I plan on using a PowerShell Script/REST API to accomplish that), instead, is about when the AppServices Resources are created, I need to deploy code to those newly created AppServices and also update that code when necessary (Hopefully through a Release Pipeline), somehow generate a new release pipeline each time I deploy a new set of Resources. So that, when there is a new update, I could easily have that pipeline triggered and that set if AppServices can be updated (created as part of the automation process "dynamically"). (I Already have a similar pipeline that deploys to a "static" set of AppServices).
This is possible as you eluded to with YAML Pipelines. Based upon the scenario you have subscribed each repository would have it's own pipeline.yml file that will define the trigger, pool etc. It would also reference a repository that will house your yaml template.
The template would accept whichever parameters you may required (resource group, app service name, etc...) The triggering pipeline associated with each repository would pass this information leveraging the teamplate.
By doing this CI/CD can be set up to trigger on the individual pipelines and deploy the appropriate code all while leveraging the same YAML template.
The repository reference would be similar to:
resources:
repositories:
- repository: YAMLTemplates
type: git
name: OrginazationName/YAML Project Name
With the call to the template being similar to:
- template: azure-ARM-template.yml#YAMLTemplate
parameters:
appServiceName: 'AppServiceName'
resourceGroupName: 'ResourceGroupName'
UPDATE
At a high level the YAML pipeline would consist of the following. If all App Services are similar as stated and ARM Templates are similar this how it could be constructed and triggered based on a folder path:
Build necessary artifacts
Publish Pipeline
Deploy Azure Resource Group Task
Deploy App Settings Task (if applicable)
Deploy App Service
Release the deployment pieces for each environment in appropriate stages to help alleviate the amount of copying and pasting each of the above tasks can be part of a template either individually at a task, combination of tasks, or all in one. This would allow for defining the YAML once and referencing it and including app specific components as needed as parameters to the templates.

In azure devops: how can I inject my pipeline variables as appsettings when deploying a docker container to azure?

I'm having trouble setting my appsettings in a deployed docker container on azure.
My setup:
I have a .NET core app
My build pipeline builds a docker image and pushes it to my container registry on azure.
My release pipeline pulls the image based on a tag and deploys it to an azure web app.
I need to deploy the image to multiple environments. Every environment has different appsettings. I defined the variables in my pipeline "variables tab":
And I need to send these to my azure so they can be used.
When I manually add them it works, but i want to extract them from my variables, so I only have to add them once. (see screenshot 1)
Edit: The screenshot above works. But this is not what I'm looking for. As I'd have to edit the appsettings pipeline each time I add or remove a new appsetting. Also I believe that removing an appsetting here will just leave it on the deployed environment.
I'm deploying an existing docker image, so i'm unable to edit the appsetting.json file. I also won't make different docker files for each environment.
Is there a way to achieve this? How can I extract / list the variables defined in my pipeline as docker variables or appsettings?
You can define pipeline variables in your pipeline and have them attached to a specific scope (read stage) or the release scope (applied to all stages).
E.g. I have a variable defined as EnvironmentConnectionString which is defined in two scopes:
Scope Test: "EnvironmentConnectionString = server=test-db; ...."
Scope QA: "EnvironmentConnectionString = server=qa-db;..."
Score Release: "logging_flag=enabled"
Then you can set this up in your "Application and Configuration Settings" like
- ConnectionString $(EnvironmentConnectionString)
- Logging $(logging_flag)
Note the $(variable name) syntax for using these variables
When the different stages of the pipeline run, they automatically pick up the values specific to the stage and apply to azure app settings.
You can have different variable groups for different stages. These Variable Groups should have same variables defined with different values.
For example: The Dev Variable Group and Release group both have variables Port, RequestTimeout... The Port in Dev is 4999 while the Port in Release could be 5000. We can link these groups to specific Stage scope, Dev variable group for Dev stage and Release group for Release stage.
[![enter image description here][1]][1]
Make sure all your stages have same settings like this, and then the variables with be replaced with correspondings values for different scopes.
Update:
Each stage in the pipeline is independent, they represent different environments. So we have to define the settings of stage or settings of the tasks within the stages one by one. We have to define the appsettings input one by one.
[1]: https://i.stack.imgur.com/ukbjs.png

ARM template link to refactor template values

Summary: We have Below mentioned release pipelines
1. Release1 -This pipeline will create resources like Application insights, App service plan, Key vault. (ARM files -azuredeploy.json and azuredeployparameters.json)
2. Release2 Pipeline: This pipeline will create resources like App service/Function App using Release1 components like Application insights, App service plan, Key vault. (ARM files -azuredeploy.json and azuredeployparameters.json)
We have multiple micro services In Release2 pipelines,
Environments like Dev, QA, Test .
Each environment has separate resource group.
azuredeployparameters.json all values are same for all services except webapp name.
Issue:If we want change or update any value in all azuredeployparameters.json files in all Release2 pipeline services, We are updating manually.
Kindly suggest the solution on below:
Can we link all our release2 azuredeployparameters.json files to one centralized azuredeployparameters.json file.
If we modify centralized azuredeployparameters.json file, it should update all azuredeployparameters.json files in all release 2 services.
You can put your azuredeployparameters.json in your central/main repo. And if you use release pipelines for instance, you should create build for your central repo and publish azuredeployparameters.json as artifact. You can later use this artifacts in any release pipeline you want. So you can get it Release1 and Release2.
If you use build pipelines also to deploy, you can use multiple repos and get source code (in release 1) from your central repo and repo dedicated to this release. In the same way you have this file available.
If you want to customize file a bit in Relese pipeline you can tokenize you azuredeployparameters.json file and replace those tokens in release. Here you have extension for this.

How to deploy to a single selected target in an Azure Devops Deployment Group

Is there a way how to select a single target and perform a deployment against it in an Azure devops Deployment Group Release Task?
E.g: In a web servers deployment group a deployment of, say a certificate failed against a single machine. I 'd like to now deploy this certificate only on that target. How can I do as such?
For this issue, you can specify the tag of the target machine in the Required tags field.
The tags you assign allow you to limit deployment to specific servers when the deployment group is used in a Deployment group job. Tags are each limited to 256 characters, but there is no limit to the number of tags you can use. For details,please refer to this document.
Or you can disable other targets in the Deployment pools of organization setting. This can disable deployment to this target.
There is a workaround to the case, you can also use conditioning option in the release task.
Step1 : Create Pipeline variable which contain the server name you wanna deploy.
Step2 : Add a custom condition on the task.
and(succeeded(), contains(variables['IncludeServers'],variables['Agent.MachineName']))
Step 3: Add as many server you wanna add in the pipeline variable
Result:

Resources