This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can trysigning in orchanging directories.
Access to this page requires authorization. You can trychanging directories.
In this tutorial, you set up a CI/CD solution usingGitOps with Flux v2 and Azure Arc-enabled Kubernetes or Azure Kubernetes Service (AKS) clusters. Using the sample Azure Vote app, you can:
dev andstage environments.If you don't have an Azure subscription, create afree account before you begin.
Complete theprevious tutorial to learn how to deploy GitOps for your CI/CD environment.
Understand thebenefits and architecture of this feature.
Verify you have:
Install the latest versions of these Azure Arc-enabled Kubernetes and Kubernetes Configuration CLI extensions:
az extension add --name connectedk8saz extension add --name k8s-configurationOr to update these extensions to the latest version, run the following commands:
az extension update --name connectedk8saz extension update --name k8s-configurationEnable your Kubernetes cluster to pull images from your Azure Container Registry. If it's private, authentication is required.
Integrate an existing Azure Container Registry with existing AKS clusters using the following command:
az aks update -n arc-cicd-cluster -g myResourceGroup --attach-acr arc-demo-acrTo connect non-AKS and local clusters to your Azure Container Registry, create an image pull secret. Kubernetes uses image pull secrets to store information needed to authenticate your registry.
Create an image pull secret with the followingkubectl command. Repeat for both thedev andstage namespaces.
kubectl create secret docker-registry <secret-name> \ --namespace <namespace> \ --docker-server=<container-registry-name>.azurecr.io \ --docker-username=<service-principal-ID> \ --docker-password=<service-principal-password>To avoid having to set an imagePullSecret for every Pod, consider adding the imagePullSecret to the Service account in thedev andstage namespaces. For more information, see theKubernetes tutorial.
Depending on the CI/CD orchestrator you prefer, you can proceed with instructions either for Azure DevOps or for GitHub.
This tutorial assumes familiarity with Azure DevOps, Azure Repos and Pipelines, and Azure CLI.
Make sure to complete the following steps first:
Import anapplication repository and aGitOps repository into Azure Repos. For this tutorial, use the following example repositories:
arc-cicd-demo-src application repository
arc-cicd-demo-srcarc-cicd-demo-gitops GitOps repository
arc-cicd-demo-gitopsLearn more aboutimporting Git repositories.
Note
Importing and using two separate repositories for application and GitOps repositories can improve security and simplicity. The application and GitOps repositories' permissions and visibility can be tuned individually.For example, the cluster administrator may not find the changes in application code relevant to the desired state of the cluster. Conversely, an application developer doesn't need to know the specific parameters for each environment - a set of test values that provide coverage for the parameters may be sufficient.
To continuously deploy your app, connect the GitOps repository to your cluster using GitOps. Yourarc-cicd-demo-gitops GitOps repository contains the basic resources to get your app up and running on yourarc-cicd-cluster cluster.
The initial GitOps repository contains only amanifest that creates thedev andstage namespaces corresponding to the deployment environments.
The GitOps connection that you create automatically syncs the manifests in the manifest directory and updates the cluster state.
The CI/CD workflow populates the manifest directory with extra manifests to deploy the app.
Create a new GitOps connection to your newly importedarc-cicd-demo-gitops repository in Azure Repos.
az k8s-configuration flux create \ --name cluster-config \ --cluster-name arc-cicd-cluster \ --namespace flux-system \ --resource-group myResourceGroup \ -u https://dev.azure.com/<Your organization>/<Your project>/_git/arc-cicd-demo-gitops \ --https-user <Azure Repos username> \ --https-key <Azure Repos PAT token> \ --scope cluster \ --cluster-type connectedClusters \ --branch master \ --kustomization name=cluster-config prune=true path=arc-cicd-cluster/manifestsTip
For an AKS cluster (rather than an Arc-enabled cluster), use-cluster-type managedClusters.
Check the state of the deployment in Azure portal.
dev andstage namespaces created in your cluster.cluster-config is created on theGitOps tab.Now that you synced a GitOps connection, you need to import the CI/CD pipelines that create the manifests.
The application repository contains a.pipeline folder with pipelines used for PRs, CI, and CD. Import and rename the three pipelines provided in the sample repository:
| Pipeline file name | Description |
|---|---|
.pipelines/az-vote-pr-pipeline.yaml | The application PR pipeline, namedarc-cicd-demo-src PR |
.pipelines/az-vote-ci-pipeline.yaml | The application CI pipeline, namedarc-cicd-demo-src CI |
.pipelines/az-vote-cd-pipeline.yaml | The application CD pipeline, namedarc-cicd-demo-src CD |
During the CI process, you deploy your application containers to a registry. Start by creating anAzure service connection:
The CD pipeline manipulates pull requests (PRs) in the GitOps repository, which requires a service connection. To configure this connection:
Generic type.https://dev.azure.com/<Your organization>/<Your project>/_apis/git/repositories/arc-cicd-demo-gitopsAdd GitOps Connector repository to Helm repositories:
helm repo add gitops-connector https://azure.github.io/gitops-connector/Install the connector to the cluster:
helm upgrade -i gitops-connector gitops-connector/gitops-connector \ --namespace flux-system \ --set gitRepositoryType=AZDO \ --set ciCdOrchestratorType=AZDO \ --set gitOpsOperatorType=FLUX \ --set azdoGitOpsRepoName=arc-cicd-demo-gitops \ --set azdoOrgUrl=https://dev.azure.com/<Your organization>/<Your project> \ --set gitOpsAppURL=https://dev.azure.com/<Your organization>/<Your project>/_git/arc-cicd-demo-gitops \ --set orchestratorPAT=<Azure Repos PAT token>Note
Azure Repos PAT token should haveBuild: Read & execute andCode: Full permissions.
Configure Flux to send notifications to GitOps connector:
cat <<EOF | kubectl apply -f -apiVersion: notification.toolkit.fluxcd.io/v1beta2kind: Alertmetadata: name: gitops-connector namespace: flux-systemspec: eventSeverity: info eventSources: - kind: GitRepository name: cluster-config - kind: Kustomization name: cluster-config-cluster-config providerRef: name: gitops-connector---apiVersion: notification.toolkit.fluxcd.io/v1beta2kind: Providermetadata: name: gitops-connector namespace: flux-systemspec: type: generic address: http://gitops-connector:8080/gitopsphaseEOFFor details about installation, see theGitOps Connector repository.
Create avariable group namedaz-vote-app-dev. Set the following values:
| Variable | Value |
|---|---|
AZURE_SUBSCRIPTION | (your Azure Service Connection, which should bearc-demo-acr from earlier in the tutorial) |
AZ_ACR_NAME | Azure ACR name, for example arc-demo-acr |
ENVIRONMENT_NAME | Dev |
MANIFESTS_BRANCH | master |
MANIFESTS_REPO | arc-cicd-demo-gitops |
ORGANIZATION_NAME | Name of Azure DevOps organization |
PROJECT_NAME | Name of GitOps project in Azure DevOps |
REPO_URL | Full URL for GitOps repository |
SRC_FOLDER | azure-vote |
TARGET_CLUSTER | arc-cicd-cluster |
TARGET_NAMESPACE | dev |
VOTE_APP_TITLE | Voting Application |
AKS_RESOURCE_GROUP | AKS Resource group. Needed for automated testing. |
AKS_NAME | AKS Name. Needed for automated testing. |
Clone theaz-vote-app-dev variable group.
Change the name toaz-vote-app-stage.
Ensure the following values for the corresponding variables:
| Variable | Value |
|---|---|
ENVIRONMENT_NAME | Stage |
TARGET_NAMESPACE | stage |
You're now ready to deploy to thedev andstage environments.
In your Azure DevOps project, createDev andStage environments. For details, seeCreate and target environments.
The CD pipeline uses the security token of the running build to authenticate to the GitOps repository. More permissions are needed for the pipeline to create a new branch, push changes, and create PRs. To enable these permissions:
<Project Name> Build Service (<Organization Name>) andProject Collection Build Service (<Organization Name>) (use search if you don't see them), and allowContribute,Contribute to pull requests, andCreate branch.For more information, seeGrant version control permissions to the build service andManage build service account permissions.
With the CI and CD pipelines created, run the CI pipeline to deploy the app for the first time.
During the initial CI pipeline run, if you see a resource authorization error in reading the service connection name, do the following:
The CI pipeline:
During the initial CD pipeline run, you need to give the pipeline access to the GitOps repository. SelectView when prompted that the pipeline needs permission to access a resource. Then, selectPermit to grant permission to use the GitOps repository for the current and future runs of the pipeline.
The successful CI pipeline run triggers the CD pipeline to complete the deployment process. You deploy to each environment incrementally.
Tip
If the CD pipeline does not automatically trigger:
.pipelines/az-vote-cd-pipeline.yamlarc-cicd-demo-src CI.Once the template and manifest changes to the GitOps repository are generated, the CD pipeline creates a commit, pushes it, and creates a PR for approval.
Find the PR created by the pipeline to the GitOps repository.
Verify the changes to the GitOps repository. You should see:
If everything looks good, approve and complete the PR.
After a few minutes, Flux picks up the change and starts the deployment.
Monitor thegit commit status on theCommit history tab. Once it issucceeded, the CD pipeline starts automated testing.
Forward the port locally usingkubectl and ensure the app works correctly using:
kubectl port-forward -n dev svc/azure-vote-front 8080:80View the Azure Vote app in your browser athttp://localhost:8080/.
Vote for your favorites and get ready to make some changes to the app.
Upon app deployment, you can make changes to the code or templates, but you can also unintentionally put the cluster into a bad state.
If the dev environment reveals a break after deployment, enabling environment approvals helps keep the problem from later environments.
For more information, seeDefine approval and checks.
Next time the CD pipeline runs, the pipeline will pause after the GitOps PR creation. Verify that the change is properly synced and passes basic functionality. Approve the check from the pipeline to let the change flow to the next environment.
With this baseline set of templates and manifests representing the state on the cluster, you make a small change to the app.
In thearc-cicd-demo-src repository, editazure-vote/src/azure-vote-front/config_file.cfg file.
Since "Cats vs Dogs" isn't getting enough votes, change it to "Tabs vs Spaces" to drive up the vote count.
Commit the change in a new branch, push it, and create a pull request. This sequence of steps is the typical developer flow that starts the CI/CD lifecycle.
The PR pipeline is the first line of defense against a faulty change. Usual application code quality checks include linting and static analysis. From a GitOps perspective, you also need to assure the same quality for the resulting infrastructure to be deployed.
The application's Dockerfile and Helm charts can use linting in a similar way to the application.
Errors found during linting range from incorrectly formatted YAML files, to best practice suggestions, such as setting CPU and Memory limits for your application.
Note
To get the best coverage from Helm linting in a real application, substitute values that are reasonably similar to values that would be used in a real environment.
Errors found during pipeline execution appear in the test results section of the run. From here, you can:
The pipeline run finishes, confirming the quality of the application code and the template that deploys it. You can now approve and complete the PR. The CI runs again, regenerating the templates and manifests, before triggering the CD pipeline.
Tip
In a real environment, be sure to set branch policies to ensure the PR passes your quality checks. For more information, seeBranch policies and settings.
A successful CI pipeline run triggers the CD pipeline to complete the deployment process. This time, the pipeline requires you to approve each deployment environment.
dev environment.kubectl and ensure the app works correctly using:kubectl port-forward -n dev svc/azure-vote-front 8080:80http://localhost:8080/ and verify the voting choices have changed to Tabs vs Spaces.stage environment.The deployment is now complete.
For a detailed overview of all the steps and techniques implemented in the CI/CD workflows used in this tutorial, see theAzure DevOps GitOps Flow diagram.
This tutorial assumes familiarity with GitHub, GitHub Actions.
Fork anapplication repository and aGitOps repository. For this tutorial, use the following example repositories:
arc-cicd-demo-src application repository
arc-cicd-demo-gitops GitOps repository
To continuously deploy your app, connect the application repository to your cluster using GitOps. Yourarc-cicd-demo-gitops GitOps repository contains the basic resources to get your app up and running on yourarc-cicd-cluster cluster.
The initial GitOps repository contains only amanifest that creates thedev andstage namespaces corresponding to the deployment environments.
The GitOps connection that you create automatically:
The CI/CD workflow populates the manifest directory with extra manifests to deploy the app.
Create a new GitOps connection to your newly forkedarc-cicd-demo-gitops repository in GitHub.
az k8s-configuration flux create \ --name cluster-config \ --cluster-name arc-cicd-cluster \ --namespace cluster-config \ --resource-group myResourceGroup \ -u https://github.com/<Your organization>/arc-cicd-demo-gitops.git \ --https-user <Azure Repos username> \ --https-key <Azure Repos PAT token> \ --scope cluster \ --cluster-type connectedClusters \ --branch master \ --kustomization name=cluster-config prune=true path=arc-cicd-cluster/manifestsCheck the state of the deployment in Azure portal.
dev andstage namespaces created in your cluster.Add GitOps Connector repository to Helm repositories:
helm repo add gitops-connector https://azure.github.io/gitops-connector/Install the connector to the cluster:
helm upgrade -i gitops-connector gitops-connector/gitops-connector \ --namespace flux-system \ --set gitRepositoryType=GITHUB \ --set ciCdOrchestratorType=GITHUB \ --set gitOpsOperatorType=FLUX \ --set gitHubGitOpsRepoName=arc-cicd-demo-src \ --set gitHubGitOpsManifestsRepoName=arc-cicd-demo-gitops \ --set gitHubOrgUrl=https://api.github.com/repos/<Your organization> \ --set gitOpsAppURL=https://github.com/<Your organization>/arc-cicd-demo-gitops/commit \ --set orchestratorPAT=<GitHub PAT token>Configure Flux to send notifications to GitOps connector:
cat <<EOF | kubectl apply -f -apiVersion: notification.toolkit.fluxcd.io/v1beta2kind: Alertmetadata: name: gitops-connector namespace: flux-systemspec: eventSeverity: info eventSources: - kind: GitRepository name: cluster-config - kind: Kustomization name: cluster-config-cluster-config providerRef: name: gitops-connector---apiVersion: notification.toolkit.fluxcd.io/v1beta2kind: Providermetadata: name: gitops-connector namespace: flux-systemspec: type: generic address: http://gitops-connector:8080/gitopsphaseEOFFor the details on installation, refer to theGitOps Connector repository.
The next step is to create GitHub repository and environment secrets.
Use the following values for your GitHub repository secrets:
| Secret | Value |
|---|---|
AZURE_CREDENTIALS | Credentials for Azure in the following format {"clientId":"GUID","clientSecret":"GUID","subscriptionId":"GUID","tenantId":"GUID"} |
AZ_ACR_NAME | Azure ACR name, for example arc-demo-acr |
MANIFESTS_BRANCH | master |
MANIFESTS_FOLDER | arc-cicd-cluster |
MANIFESTS_REPO | https://github.com/your-organization/arc-cicd-demo-gitops |
VOTE_APP_TITLE | Voting Application |
AKS_RESOURCE_GROUP | AKS Resource group. Needed for automated testing. |
AKS_NAME | AKS Name. Needed for automated testing. |
PAT | GitHub PAT token with the permission to PR to the GitOps repository |
az-vote-app-dev environment with the following secrets:| Secret | Value |
|---|---|
ENVIRONMENT_NAME | Dev |
TARGET_NAMESPACE | dev |
az-vote-app-stage environment with the following secrets:| Secret | Value |
|---|---|
ENVIRONMENT_NAME | Stage |
TARGET_NAMESPACE | stage |
You're now ready to deploy to thedev andstage environments.
To start the CI/CD Dev workflow, change the source code. In the application repository, update values in.azure-vote/src/azure-vote-front/config_file.cfg file and push the changes to the repository.
The CI/CD Dev workflow:
Once these steps are completed:
Find the PR created by the pipeline to the GitOps repository.
Verify the changes to the GitOps repository. You should see:
If everything looks good, approve and complete the PR.
After a few minutes, Flux picks up the change and starts the deployment.
Monitor thegit commit status on the Commit history tab. Once it issucceeded, theCD Stage workflow starts.
Forward the port locally usingkubectl and ensure the app works correctly using:
kubectl port-forward -n dev svc/azure-vote-front 8080:80View the Azure Vote app in your browser athttp://localhost:8080/.
Vote for your favorites and get ready to make some changes to the app.
The CD Stage workflow starts automatically once Flux successfully deploys the application to dev environment and notifies GitHub actions via GitOps Connector.
The CD Stage workflow:
Once the manifests PR to the Stage environment is merged and Flux successfully applies all the changes, the Git commit status is updated in the GitOps repository. The deployment is now complete.
For a detailed overview of all the steps and techniques implemented in the CI/CD workflows used in this tutorial, see theGitHub GitOps Flow diagram.
If you're not going to continue to use this application, delete any resources with the following steps:
Delete the Azure Arc GitOps configuration connection:
az k8s-configuration flux delete \ --name cluster-config \ --cluster-name arc-cicd-cluster \ --resource-group myResourceGroup \ -t connectedClusters --yesDelete GitOps Connector:
helm uninstall gitops-connector -n flux-systemkubectl delete alerts.notification.toolkit.fluxcd.io gitops-connector -n flux-systemkubectl delete providers.notification.toolkit.fluxcd.io gitops-connector -n flux-systemIn this tutorial, you set up a full CI/CD workflow that implements DevOps from application development through deployment. Changes to the app automatically trigger validation and deployment, gated by manual approvals.
Advance to our conceptual article to learn more about GitOps and configurations with Azure Arc-enabled Kubernetes.
Was this page helpful?
Need help with this topic?
Want to try using Ask Learn to clarify or guide you through this topic?
Was this page helpful?
Want to try using Ask Learn to clarify or guide you through this topic?