In First Workload we deployed the Azure Voting App using a GitOps workflow by pushing the azure-vote-all-in-one-redis.yaml
Kubernetes resource manifest file. In High level Deployment Definitions we learned that, Kubernetes resource manifests that comprise an application definition are typically very complex. These resource manifests, by their YAML nature, are typically very dense, context free, and very indentation sensitive -- making them a dangerous surface to directly edit without introducing a high risk for operational disaster.
We also learned that real world Kubernetes deployments tend to be composed of the combination of many Helm charts. Maintaining and generating various Helm charts can be a challenge and why Bedrock introduced the concept of high level definitions to meet this complexity.
In this walkthrough, we will set up an Azure DevOps pipeline that generates a resource manifest from an HLD definition for the Azure Voting App and pushes it to the Manifest Repository.
There are a few requirements to use this automation:
- Install the Bedrock Prerequisites (if they're not already installed).
- The application code and supporting repositories are hosted on
Azure Devops.
- If starting from scratch, then first create a new Azure Devops Organization, then create a project.
- A Manifest Repository inside an Azure DevOps project as instructed from A First Worklad with Bedrock.
- An HLD Repository inside the same Azure DevOps project as the manifest repository. Create a repository.
- The application will be packaged and run using container images hosted on Azure Container Registry
- The user running
bedrock
has full access to the above resources.
Note: If a user wishes to store Helm charts in the application repositories, then all repositories (application, high level definition, materialized manifests) must be in the same Azure DevOps Organization AND Project. This behavior is what Step 2 and Step 3 are doing.
Download the latest version of bedrock
from the
releases page and add it to your
PATH.
To setup a local configuration:
Generate a new Personal Access Token (PAT) to grant bedrock
permissions in the
Azure Devops Project. Please grant PAT the following permissions:
- Build (Read & execute)
- Code (Read, write, & manage)
- Variable Groups (Read, create, & manage)
For help, follow the guide.
Create a copy of bedrock-config.yaml
from the starter
template or using the interactive mode for bedrock init
command. Be sure to complete
azure_devops
section with the appropriate values.
Your azure_devops
section should look similar to this:
azure_devops:
access_token: "8w98gzilabcde6aq5insk7tt64yasprnnetlemvcc2eubzwzwqppl" # This is a Personal Access Token with permission to modify and access the HLD, manifest and infra repos. Leave this empty if project is public. Details for the PAT at: https://github.com/microsoft/bedrock-cli/blob/master/guides/project-service-management-guide.md#generating-personal-access-token
hld_repository: "https://dev.azure.com/myOrganization/myProject/_git/app-cluster-hlds" # Repository URL for your Bedrock HLDs
manifest_repository: "https://dev.azure.com/myOrganization/myProject/_git/app-cluster-manifests" # Repository URL for your materialized manifests generated by fabrikate.
infra_repository: "" # Repository URL that contains your terraform templates to be sed for scaffolding and generating infrastructure deployment templates.
org: "myOrganization" # Your AzDo Org
project: "myProject" # Your AzDo project
Note: This bedrock-config.yaml
should not be commited anywhere, as it contains
sensitive credentials. For an alternative approach on how to add secrets to bedrock-config.yaml
using environment variables, see these instructions.
Run bedrock init -f <bedrock-config.yaml>
where <bedrock-config.yaml>
the path to the
configuation file.
Note: When running bedrock init -f <bedrock-config.yaml>
, bedrock
will copy the
values from the config file and store it into local memory elsewhere. If you
wish to utilize bedrock
with another project or target, then you must rerun
bedrock init
with another configuration first OR, you may overwrite each commands
via flags.
Our next step is to onboard the repositories that support the deployment of our services:
- The high level definition repository (Step 3 from the Requirements)
- The materialized manifest repository (Step 2 from the Requirements)
This repository holds the Bedrock High Level Deployment Definition (HLD) and associated configurations.
This HLD is processed via fabrikate in Azure Devops on each change to generate Kubernetes YAML manifests that are applied to the Kubernetes cluster by Flux.
- Make sure your Bedrock config points to the HLD repo you created in Step 3 of Requirements. When you change the values in the Bedrock config, make sure you re-initialize Bedrock by running
bedrock init -f <bedrock-config.yaml>
. - Clone the repository.
- Initialize via
bedrock
, this will add the fabrikate traefik2 as the initial sample component. This can be overridden via optional flags.bedrock hld init --git-push
NOTE bedrock hld
command documentation can be found
here.
If the initialization succeeded, you will see a message similar to this:
info: Link to create PR: https://dev.azure.com/myOrganization/myProject/_git/app-cluster-hlds/pullrequestcreate?sourceRef=bedrock-hld-init&targetRef=master
This message means that we were able to generate an HLD with the default traefik2 component and all the changes were added to a new branch and are ready to be added to a Pull Request.
To verify run:
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/bedrock-hld-init
As you can see we now have a bedrock-hld-init
branch.
Go to the "Link to create a PR" that we got earlier after running the bedrock hld init --git-push
command. You will see:
If you scroll down, you will see several files were added: component.yaml
and manifest-generation.yaml
. These files contain the information for our traefik component and for the pipeline.
Click "Create" to create the PR. Then click "Complete". Finally click "Complete merge":
Your changes should now be in the master
branch. Pull the latest changes:
$ git pull origin master
remote: Azure Repos
remote: Found 1 objects to send. (3 ms)
Unpacking objects: 100% (1/1), 238 bytes | 238.00 KiB/s, done.
From ssh.dev.azure.com:v3/myOrganization/myProject/app-cluster-hlds
* branch master -> FETCH_HEAD
32b0b14..3ee2da1 master -> origin/master
Updating 32b0b14..3ee2da1
Fast-forward
.gitignore | 1 +
component.yaml | 6 ++++++
manifest-generation.yaml | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 65 insertions(+)
create mode 100644 .gitignore
create mode 100644 component.yaml
create mode 100644 manifest-generation.yaml
From here, your Bedrock workload should have the following structure:
.
├── app-cluster-manifests/
├── prod
├── traefik2
├── default-component.yaml
├── app-cluster-hlds/
├── component.yaml
├── manifest-generation.yaml
├── .gitignore
├── cluster-deployment/
├── definition.yaml
├── cluster/
├── keys/
├── gitops-ssh-key
├── gitops-ssh-key.pub
├── node-ssh-key
├── node-ssh-key.pub
├── sp/
├── sp.json
├── cluster-deployment-generated
├── cluster/
├── main.tf
├── bedrock.tfvars
├── variables.tf
Deploy a manifest generation pipeline between the high level definition repo and
the materialized manifests repo. Assuming you have configured bedrock
, you can run
this without flag parameters from your HLD repo root:
$ bedrock hld install-manifest-pipeline
You can view the newly created pipeline in your Azure DevOps project:
Once the pipeline finishes running successfully, you will see that the manifests have been generated and pushed to the app-cluster-manifests
repository:
After some time, flux will apply the changes:
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
traefik2-6f8ddc69cc-79n4g 0/1 ContainerCreating 0 8s
And we can also confirm the service is available:
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 21h
traefik2 LoadBalancer 10.0.209.68 137.135.15.52 80:31328/TCP,443:30149/TCP 19h
At this point you have:
- Set up an Azure DevOps pipeline to generate resource manifests
- Verified that changes are applied to the Kubernetes cluster