Assumptions:
- Sandpit environment implements diagnostics and logs for every solution deployed.
- Sandpit environment implements rudimentary RBAC model.
- All resources are provisioned in the same subscription.
In this example, we will seed the initial deployment locally and then deploy the environment from an Azure DevOps set of pipelines.
- VS Code
- 'Remote - Containers' Extension installed
- Docker
Go to your Azure DevOps organization (this could be an on premises organization or hosted on http://dev.azure.com), create your first project and then clone the starter repository this repository in your Azure DevOps.
This repository will be called the caf-configuration
repository in the example pipelines. In order to make things easier, you might want to rename your git repo caf-configuration
in your DevOps project.
- With your Azure DevOps REPO, click Clone.
- By generating with Git Credentials allows the project to be checked in from within a container via HTTPS
- Take the password and Azure DevOps Repo URL replace the organization name before @dev.azure.com with the password
https://<organizationname>@dev.azure.com/<organizationname>/caf-configuration/_git/caf-configuration
becomes
https://<password>@dev.azure.com/<organizationname>/caf-configuration/_git/caf-configuration
- In the terminal navigate to the folder you wish to clone to.
- Clone
git clone --branch starter https://<password>@dev.azure.com/<organizationname>/caf-configuration/_git/caf-configuration
- Ensure Docker is running
- Open the project in Visual Studio Code
- Ctrl + Shift + P and type
Remote-Containers: Reopen in Container
and select. - Project now open in container.
First step is to get the landing zones logic in the same work space, so let's clone the environment locally:
- Open a VS Code terminal
git clone --branch 2107.1 https://github.com/Azure/caf-terraform-landingzones.git /tf/caf/landingzones
# Or refresh an existing clone
cd /tf/caf/landingzones
git checkout 2107.1
git pull
Authenticate to your Azure environment using the following command:
rover login -t <tenant_name> -s <subscription_id>
Rover will echo back the subscription selected by default for your environment. If this is not the right subscription, modify it using the following command:
az account set -s <subscription_name_OR_GUID>
The deployment of an environment via pipeline always starts by deploying the DevOps fundamentals:
- Launchpad: lays the foundation for Azure components (identity, Key Vaults, state management components)
- GitOps: create the pipeline, variables to KeyVault, service connection.
- GitOps agents: the Virtual Machines running the self hosted Azure DevOps agents that will be running the Terraform landing zones from the different levels in your environment.
- Open diagnostics_destinations.tfvars, change lines 10 & 14 to match the regions you are deploying to.
- Open landingzone.tfvars. Add
prefix
just beforeregions
and update the regions to match your regions.
prefix = "<YOUR PREFIX>"
regions = {
region1 = "uksouth"
region2 = "ukwest"
}
Note:By not including prefix, random 4 character prefix will be automatically added to your resources
export environment=sandpit
rover -lz /tf/caf/landingzones/caf_launchpad \
-var-folder /tf/caf/configuration/${environment}/level0/launchpad \
-parallelism 30 \
-level level0 \
-env ${environment} \
-launchpad \
-a [plan|apply|destroy]
- Within Azure Devops Settings -> Personal Access Tokens. Click New Token.
- Name: azdo-pat-admin
- Organization: (Your Organization)
- Expiration: 30 days (can set Custom defined)
- Scopes: Full Access.
- Click Create
- Take note of the Token.
- Within Azure Devops Settings -> Personal Access Tokens. Click New Token.
- Name: azdo-pat-agent
- Organization: (Your Organization)
- Expiration: 30 days (can set Custom defined)
- Scopes: Custom defined.
- Click
Show all scopes
at the bottom. - Under
Agent Pools
tickRead & manage
- Click
- Click Create
- Take note of the Token.
Within your Azure environment from deploying Launchpad, there will be a keyvault in the form of <prefix>-kv-secrets
. Located in the <prefix>-rg-launchpad-security
resource group.
- Go to the KeyVault Secrets and update the following Secrets
AZDO-PAT_ADMIN
- Click secret named
azdo-pat-admin
- Click New Version
- Put the Token value you took note of earlier into the 'Value' field and click Create
AZDO-PAT_AGENT
- Click secret named
azdo-pat-agent
- Click New Version
- Put the Token value you took note of earlier into the 'Value' field and click Create
No customization are required to work in your environment
export environment=sandpit
rover -lz /tf/caf/landingzones/caf_solution \
-var-folder /tf/caf/configuration/${environment}/level1/gitops/gitops_connectivity \
-tfstate gitops_connectivity.tfstate \
-parallelism 30 \
-level level1 \
-env ${environment} \
-a [plan|apply|destroy]
- Open azure_devops.tfvars. Change the URL to match your Azure DevOps organization in the azure_devops, and the name you gave the project:
azure_devops = {
url = "https://dev.azure.com/change_with_your_org/"
project = "caf-configuration"
- Into the service connection object, make sure you replace the connection properties with the ones from the launchpad subscription:
service_endpoints = {
contoso_demo = {
endpoint_name = "<Name to show in DEVOPS Service Connections>"
subscription_name = "<Name of your subscription>"
subscription_id = "<Your SubscriptionID Guid>"
aad_app_key = "contoso_demo"
secret_keyvault_key = "devops"
}
}
Note: You can get your subscription ID and Name by running:
az account show
- Update the variable group
ROVER_IMAGE
to match the rover version you are running in this project. Update theLANDINGZONE_BRANCH
to match the tag/branch you pulled down in step 2. Clone the public landing zones.
variable_groups = {
global = {
name = "release-global" # changing that name requires to change it in the devops agents yaml variables group
allow_access = true
variables = {
HOME_FOLDER_USER = "vsts_azpcontainer"
ROVER_IMAGE = "aztfmod/<current rover version>"
ROVER_RUNNER = "true"
TF_CLI_ARGS = "'-no-color'"
TF_CLI_ARGS_init = ""
TF_CLI_ARGS_plan = "'-input=false'"
TF_VAR_ARGS_destroy = "'-auto-approve -refresh=false'"
ENVIRONMENT = "sandpit"
LANDINGZONE_BRANCH = "<Current Branch/Tag>"
}
}
If you didn't call the project "caf-configuration" when you imported the repo, then you will need to update all git_repo_name
lines in the azure_devops.tfvars.
- Using a find and replace, replace:
git_repo_name = "caf-configuration"
with
git_repo_name = "<Your Project Name>"
export environment=sandpit
rover -lz /tf/caf/landingzones/caf_solution/add-ons/azure_devops \
-var-folder /tf/caf/configuration/${environment}/level1/gitops/azure_devops \
-tfstate azure_devops_contoso_demo.tfstate \
-parallelism 30 \
-level level1 \
-env ${environment} \
-a [plan|apply|destroy]
- Open landingzones.tfvars.
- Within azure_devops replace all the levels
rover_version
to match the rover version you are running in this project. Change allurl
to match your Azure DevOps organization.
azure_devops = {
level0 ={
rover_version = "aztfmod/<current rover version>"
url = "https://dev.azure.com/<change_with_your_org>/"
...
level1 = {
rover_version = "aztfmod/<current rover version>"
url = "https://dev.azure.com/<change_with_your_org>/"
...
rover -lz /tf/caf/landingzones/caf_solution/add-ons/azure_devops_agent \
-var-folder /tf/caf/configuration/${environment}/level1/gitops/azure_devops_agents_vm \
-tfstate azdo-agent-levels.tfstate \
-parallelism 30 \
-level level1 \
-env ${environment} \
-a [plan|apply|destroy]
Note: First time this is deployed, you may get an error saying the Blob "devops_runtime_baremetal.sh" cannot be parsed. This seems to be a race condition, where it is trying to be read before it has fully uploaded to your storage account. Re-run the apply, it will work from now on.
First time you attempt to check code in, it might error saying you need to update the username and email of git configuration.
- Run the following command replacing with your name and email address.
git config --global user.name "<YOUR NAME>"
git config --global user.email "<YOUR EMAIL>"
Launchpad and level0 are deployed manually from the console to seed the environment, but all higher levels are deployed using pipelines as defined by the pipelines configuration.
Once the agents are deployed for all levels, you can start deploying the landing zones for the levels:
- Go into your Azure DevOps Pipelines.
- View All Pipelines
- Expand configuration you will see a plan/apply/destroy pipeline within each folder.
- full: End to End
- level 1: Foundations.
- level 2: Networking, Shared Services.
- level 3: AKS Cluster, Data and AI, App Service, etc.
When you run End to End pipeline the first time you will see an error message about trying to logged_in_user
for keyvault access policy, and that the already exists - to be managed via Terraform this resource needs to be imported into the State.
This is because when you ran it locally, it added your user account and the MSI to the keyvault. When you run in the pipeline, the current user is the MSI, and it attempts to remove the previous current user (your user account) and replace it with the MSI account. However, the MSI was already added previously, but not under the "logged_in_user" key.
- Open keyvaults.tfvars.
- Comment out all the 'logged_in_user' sections.
Replace
logged_in_user = {
# if the key is set to "logged_in_user" add the user running terraform in the keyvault policy
# More examples in /examples/keyvault
secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"]
}
With
# logged_in_user = {
# # if the key is set to "logged_in_user" add the user running terraform in the keyvault policy
# # More examples in /examples/keyvault
# secret_permissions = ["Set", "Get", "List", "Delete", "Purge", "Recover"]
# }
- Redeploy step: 3.3.5 Deploy the Azure DevOps Agents (runners)
- Check in your repo code changes back into Azure Devops.
If you would rather deploy each level separately, skip this step and continue from 5.2 Run Pipelines - Level 1
- Go into Azure Devops Pipelines
- View All Pipelines
- Expand configuration/full
- Select
end_to_end_plan
then click 'Run pipeline' - Ensure you switch the branch/tag to the name of your branch as master does not exist in this project.
- Click Run.
- Once successful, you can run the
end_to_end_apply
pipeline.
You have now successfully deployed Level 1 - 3 using pipelines, follow the remaining steps only if you wish to deploy levels separately.
- Go into Azure Devops Pipelines
- View All Pipelines
- Expand configuration/level1
- Select
caf_foundations_plan
then click 'Run pipeline' - Ensure you switch the branch/tag to the name of your branch as master does not exist in this project.
- Click Run.
- Once successful, you can run the
caf_foundations_apply
pipeline.
- Go into Azure Devops Pipelines
- View All Pipelines
- Expand configuration/level2/networking/hub
- Select
caf_networking_hub_plan
then click 'Run pipeline' - Ensure you switch the branch/tag to the name of your branch as master does not exist in this project.
- Click Run.
- Once successful, you can run the
caf_networking_hub_apply
pipeline.
- Go into Azure Devops Pipelines
- View All Pipelines
- Expand configuration/level2/shared_services
- Select
caf_shared_services_plan
then click 'Run pipeline' - Ensure you switch the branch/tag to the name of your branch as master does not exist in this project.
- Click Run.
- Once successful, you can run the
caf_shared_services_apply
pipeline.
- Go into Azure Devops Pipelines
- View All Pipelines
- Expand configuration/level3/aks
- Select
caf_aks_plan
then click 'Run pipeline' - Ensure you switch the branch/tag to the name of your branch as master does not exist in this project.
- Click Run.
- Once successful, you can run the
caf_aks_apply
pipeline.