Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AKS, GitHub Actions, Terraform, Documentation updates #15

Merged
merged 5 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 70 additions & 46 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,62 +1,86 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:

jobs:
terraform:
name: 'Terraform'
terraform-fmt-check:
if: github.event_name == 'pull_request'
defaults:
run:
working-directory: "./Terraform-AZURE-Services-Creation/AKS"
name: Terraform
environment: production
runs-on: ubuntu-latest
permissions:
contents: write
env:
ARM_CLIENT_ID: ${{ secrets.AZURE_AD_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZURE_AD_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZURE_AD_TENANT_ID }}
TF_VERSION: 1.5.7
runs-on: ubuntu-latest
environment: production

# Use the Bash shell regardless whether the GitHub Actions runner is ubuntu-latest, macos-latest, or windows-latest
defaults:
run:
shell: bash

tf_resource_group_name: "thomasthorntoncloud"
tf_storage_account_name: "thomasthorntontfstate"
tf_state_container: "devopsthehardwaygithub"
tf_state_key: "terraform.tfstate"
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout
- name: Checkout Code
uses: actions/checkout@v4

- name: 'Terraform Format'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: ${{ env.TF_VERSION }}
tf_actions_subcommand: 'fmt'
tf_actions_working_dir: "./Terraform-AZURE-Services-Creation/AKS"

- name: 'Terraform Init'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: ${{ env.TF_VERSION }}
tf_actions_subcommand: 'init'
tf_actions_working_dir: "./Terraform-AZURE-Services-Creation/AKS"

- name: 'Terraform Validate'
uses: hashicorp/terraform-github-actions@master

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
tf_actions_version: ${{ env.TF_VERSION }}
tf_actions_subcommand: 'validate'
tf_actions_working_dir: "./Terraform-AZURE-Services-Creation/AKS"

- name: 'Terraform Plan'
uses: hashicorp/terraform-github-actions@master
terraform_version: 1.7.4
terraform_wrapper: true

- name: Terraform Init
id: init
run: terraform init
env:
ARM_CLIENT_ID: ${{ secrets.AZURE_AD_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZURE_AD_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZURE_AD_TENANT_ID }}
working-directory: "./Terraform-AZURE-Services-Creation/AKS"

- name: Terraform Fmt
id: fmt
run: terraform fmt
working-directory: "./Terraform-AZURE-Services-Creation/AKS"

- name: Auto Commit Changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
tf_actions_version: ${{ env.TF_VERSION }}
tf_actions_subcommand: 'plan'
tf_actions_working_dir: "./Terraform-AZURE-Services-Creation/AKS"

- name: Terraform Apply
commit_message: "Terraform fmt"
file_pattern: "*.tf *.tfvars"
commit_user_name: "github-actions[bot]"

- name: Terraform Plan
id: plan
run: terraform plan -no-color -input=false
env:
ARM_CLIENT_ID: ${{ secrets.AZURE_AD_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZURE_AD_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZURE_AD_TENANT_ID }}
DEPLOYMENT_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
working-directory: "./Terraform-AZURE-Services-Creation/AKS"
continue-on-error: false

- name: Terraform Apply
id: apply
run: terraform apply -auto-approve -input=false
if: github.ref == 'refs/heads/main'
uses: hashicorp/terraform-github-actions@master
with:
tf_actions_version: ${{ env.TF_VERSION }}
tf_actions_subcommand: 'apply'
tf_actions_working_dir: "./Terraform-AZURE-Services-Creation/AKS"
env:
ARM_CLIENT_ID: ${{ secrets.AZURE_AD_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZURE_AD_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZURE_AD_TENANT_ID }}
working-directory: "./Terraform-AZURE-Services-Creation/AKS"
continue-on-error: false
8 changes: 4 additions & 4 deletions Azure/1-Configure-Terraform-Remote-Storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The purpose of this lab is to create the location that will store the remote Ter
## Create Blob Storage location for Terraform State file
1. Edit the [variables](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/blob/main/Azure/create-terraform-storage.sh#L3-L4)
2. Run the script `./create-terraform-storage.sh`
3. The script will create
- Azure Resource Group
- Azure Storage Account
- Azure Blob storage location within Azure Storage Account
3. The script will:
- Create an Azure Resource Group
- Set up an Azure Storage Account
- Establish an Azure Blob storage location within the Azure Storage Account
10 changes: 5 additions & 5 deletions Docker/1-Create-Docker-Image.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ Now that the Docker image is created, you can run the container locally just to
1. To run the Docker container, run the following command:
`docker run -tid uberapp`

- `t` stands for a TTY console
- `i` stands for interactive
- `d` stands for detach so your terminal isn't directly connected to the Docker container
- `t` enables a TTY console.
- `i` enables an interactive session.
- `d` detaches the terminal from the Docker container.

2. To confirm the Docker container is running, run the following command:
2. Confirm that the Docker container is running by running the following command:
`docker container ls`

You should now see the container running.
You should now see the container running successfully.
4 changes: 4 additions & 0 deletions Docker/2-Push Image To ACR.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

The ACR repo will be where you store the Docker image that you created on your local computer in step 1.

Ensure to replace `devopsthehardwayacr` with your ACR name and `v1` with the appropriate version tag if needed.


## Log Into The ECR Repository
1. Log in to ACR with Azure CLI
`az acr login --name devopsthehardwayacr`
Expand All @@ -14,3 +17,4 @@ The ACR repo will be where you store the Docker image that you created on your l
## Push The Docker Image To ACR
1. Push the Docker image to ACR
`docker push devopsthehardwayacr.azurecr.io/uberapp:v1`

42 changes: 20 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DevOps-The-Hard-Way-Azure

This tutorial contains a full, real-world solution for setting up an environment that is using DevOps technologies and practices for deploying apps and cloud services/cloud infrastructure to Azure.
Welcome to the DevOps-The-Hard-Way-Azure tutorial! This comprehensive guide provides a real-world solution for implementing DevOps practices and technologies to deploy applications and cloud services/infrastructure on Microsoft Azure.

The repository contains free labs, documentation, diagrams, and docs for setting up an entire workflow and DevOps environment from a real-world perspective in Azure.

Expand All @@ -9,8 +9,9 @@ The scenario that you're currently facing is you work in an organization that is

You're brought in to the company and team to make things more modern so the organization can not only succeed, but stay ahead of their competition. Management now understands the needs and complexity that comes with staying ahead of their competition and they know that they need to. Otherwise, the organization will fall...


## DevOps Solution
The solution is to deploy the Uber API for the sign-up page. Currently this solution is sitting on a bunch of baremetal, but it's time to sprinkle a little DevOps on it.
The solution is to deploy the Uber API for the sign-up page. Currently this solution is sitting on a bunch of baremetal, but it's time to sprinkle a little DevOps on it. Although we won't be coding the application itself, we'll cover the deployment process using DevOps tools and methodologies.

![](images/uber.png)

Expand All @@ -21,26 +22,16 @@ As a DevOps Engineer, you're more or less (most likely) not writing the app, but
https://github.com/AdminTurnedDevOps/Python-Sample-Application

## Technology Details
You will be using the following technologies and platforms to set up a DevOps environment.

1. Azure
- Azure will be used to host the application, cloud infrastructure, and any other services we may need to ensure the Uber app is deployed properly.
2. GitHub
- To store the application and infrastructure/automation code
3. Python
- Python will be used for the Uber app (it is written in Python) and some automation efforts that aren't in Terraform.
4. Terraform
- Create an Azure ACR repository with Terraform
- Create an AKS cluster
5. Docker
- Create a Docker image
- Store the Docker image in Azure ACR
6. Kubernetes
- To run the Docker image that's created for the containerized Uber app. Kubernetes, in this case, AKS, will be used to orchestrate the container.
7. CI/CD
- Use GitHub Action to create an AKS cluster
8. Automated testing
- Testing Terraform code with Checkov
Get ready to utilise a range of cutting-edge technologies and platforms to establish your DevOps environment:

1. Azure: Hosts the application, cloud infrastructure, and necessary services.
2. GitHub: Stores application and infrastructure/automation code.
3. Python: Powers the Uber application and some automation tasks.
4. Terraform: Orchestrates Azure resources, including Azure Container Registry (ACR) and Azure Kubernetes Service (AKS).
5. Docker: Creates containerized images for the Uber app and stores them in Azure ACR.
6. Kubernetes: Orchestrates Docker containers, with AKS managing our Kubernetes clusters.
7. CI/CD: Automates deployment using GitHub Actions.
8. Automated Testing: Ensures Terraform code integrity using Checkov.

## Labs
1. [Prerequisites](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/blob/main/prerequisites.md)
Expand All @@ -67,3 +58,10 @@ In this scenario, the Terraform State file will be stored in remote state locati
- [Install And Run Checkov](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/blob/main/Terraform-Static-Code-Analysis/1-Checkov-For-Terraform.md)
6. CICD - The purpose of this section is to automatically create an AKS cluster with CICD using GitHub Actions
- [Create a GitHub Actions CICD pipeline](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/blob/main/Terraform-AZURE-Services-Creation/5-Run-CICD-For-AKS-Cluster.md)

## Conclusion
By following this tutorial, you'll not only deploy an example app on Azure but also gain valuable insights into modern DevOps practices and tools.

Let's embark on this journey to transform your organization into a lean, agile, and competitive force in the digital landscape. Happy deploying! 🚀🔧


4 changes: 3 additions & 1 deletion Terraform-AZURE-Services-Creation/1-Create-ACR.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# Create an Azure Container Registry Repository

Before proceeding, ensure that the values in the terraform.tfvars file are accurate for your environment. You may need to customize these values to match your specific configuration.

In this lab you will create a repository to store the Docker image that you created for the Uber app.

## Create the ACR Terraform Configuration

1. You can find the Terraform configuration for Azure Container Registry (ACR) [here](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/tree/main/Terraform-AZURE-Services-Creation/ACR). The Terraform configuration files are used to create a repository in Azure Container Registry (ACR).

The Terraform `main.tf` will do a few things:
The Terraform `acr.tf` will:
- Use a Terraform backend to store the `.tfstate` in an Azure Storage Account
- Use the `uksouth` region, but feel free to change that if you'd like
- Use the `azurerm_resource_group` Terraform resource to create a new Resource Group.
Expand Down
22 changes: 19 additions & 3 deletions Terraform-AZURE-Services-Creation/2-Create-VNET.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,33 @@
# Create an Azure VNET

In this lab you will create a Virtual Network (VNET) that will be used to deploy your AKS instance into
Before proceeding, ensure that the values in the terraform.tfvars file are accurate for your environment. You may need to customize these values to match your specific configuration.

In this lab you will:
- Create a Virtual Network (VNET) that will be used to deploy your AKS instance into
- Create a Network Security Group (NSG) and assign to the relevant subnets
- Create an Azure Application Gateway for Containers and associate it with the VNET

## Create the Azure VNET Terraform Configuration

1. You can find the Terraform configuration for Azure Virtual Network [here](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/tree/main/Terraform-AZURE-Services-Creation/VNET). The Terraform configuration files are used to create an Azure Vitual Network.

The Terraform `main.tf` will do a few things:
The Terraform `vnet.tf` will:
- Use a Terraform backend to store the `.tfstate` in an Azure Storage Account
- Use the `azurerm_virtual_network` Terraform resource to create a VNET.
- Use the `azurerm_subnet` Terraform resource to create relevant subnets.
- Use the `uksouth` region, but feel free to change that if you'd like

2. Create the VNET by running the following:
The Terraform `nsg.tf` will:
- Use the `azurerm_network_security_group` Terraform resource to create a NSG.
- Use the `azurerm_subnet_network_security_group_association` Terraform resource to associate the NSG to the relevant subnets.

The Terraform `alb.tf` will:
- Use the `azurerm_application_load_balancer` Terraform resource to create an Azure Application Gateway for Containers.
- Use the `azurerm_application_load_balancer_subnet_association` Terraform resource to associate the Azure Application Gateway with the VNET.
- Use the `azurerm_application_load_balancer_frontend` Terraform resource to create a frontend for the Azure Application Gateway.


2. Create the VNET, NSG & Azure Application Gateway for Containers by running the following:
- `terraform init` - To initialize the working directory and pull down the provider
- `terraform plan` - To go through a "check" and confirm the configurations are valid
- `terraform apply` - To create the resource
5 changes: 4 additions & 1 deletion Terraform-AZURE-Services-Creation/3-Create-Log-Analytics.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
# Create an Azure Log Analytics Workspace

Before proceeding, ensure that the values in the terraform.tfvars file are accurate for your environment. You may need to customize these values to match your specific configuration.

In this lab you will create a Log Analytics workspace that will be used to view container insights of your AKS Cluster

## Create the Log Analytics Workspace Terraform Configuration

1. You can find the Terraform configuration for Log Analytics [here](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/tree/main/Terraform-AZURE-Services-Creation/Log-Analytics). The Terraform configuration files are used to create the Log Analytiocs workspace.

The Terraform `main.tf` will do a few things:
The Terraform `la.tf` will:
- Use a Terraform backend to store the `.tfstate` in an Azure Storage Account
- Use the `azurerm_log_analytics_workspace` Terraform resource to create a Log Analytics workspace.
- Use the `azurerm_log_analytics_solution` Terraform resource to enable the Log Analytics solution ContainerInsights.
- Use the `uksouth` region, but feel free to change that if you'd like
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Create An AKS Cluster and IAM Roles

Before proceeding, ensure that the values in the terraform.tfvars file are accurate for your environment. You may need to customize these values to match your specific configuration.

In this lab you will create:
- The AKS cluster
- The appropriate IAM roles for AKS
Expand All @@ -8,11 +10,19 @@ In this lab you will create:

1. You can find the Terraform configuration for AKS [here](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/tree/main/Terraform-AZURE-Services-Creation/AKS). The Terraform configuration files are used to create an AKS cluster and IAM Role/Policy for AKS.

The Terraform `main.tf` will do a few things:
The Terraform `aks.tf` will:
- Use the `azurerm_kubernetes_cluster` Terraform resource to AKS Cluster
- Use the `azurerm_role_assignment` Terraform resource to create the two neccessary role assignments
- Use the `uksouth` region, but feel free to change that if you'd like

The Terraform `managed_identity.tf` will:
- Use the `azurerm_user_assigned_identity` Terraform resource to create a user assigned identity as part of the Azure Application Gateway for Containers setup
- Use the `azurerm_federated_identity_credential` Terraform resource to create a federated identity credential as part of the Azure Application Gateway for Containers setup

The Terraform `rbac.tf` will:
- Use the `azurerm_role_assignment` Terraform resource to create the necessary role assignments for the AKS cluster
- Use the `azurerm_role_definition` Terraform resource to create the necessary role definitions for the AKS cluster

2. In line 8 of `terraform.tfvars` replace the actual Azure AD Group ID you noted down [earlier](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/blob/main/Azure/2-Create-Azure-AD-Group-AKS-Admins.md)

3. Create the bucket by running the following:
Expand Down
10 changes: 6 additions & 4 deletions Terraform-AZURE-Services-Creation/5-Run-CICD-For-AKS-Cluster.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Create AKS Cluster With CICD

Before proceeding, ensure that the values in the terraform.tfvars file are accurate for your environment. You may need to customize these values to match your specific configuration.

In this lab, you'll learn how to create an AKS cluster using GitHub Actions. The code can be found [here](https://github.com/thomast1906/DevOps-The-Hard-Way-Azure/tree/main/Terraform-AZURE-Services-Creation/AKS)


Expand Down Expand Up @@ -33,16 +35,16 @@ Now that the secrets are created, it's time to create the pipeline.

1. Under the GitHub repository, click on the **Actions** tab
2. You will see a workflow already called `CI`
3. Select `CI` workflow and then select `Run workflow` `from` main branch
3. Select `CI` workflow and then select `Run workflow` `from` main branch (Also note, the pipeline is configured to run also during a Pull Request and or a Push to the main branch)

The pipeline does a few things:
- On line 4, you'll see `workflow_dispatch`, which means the pipeline won't automatically run unless you kick it off. You can of course change this to have the pipeline automatically run if you, for example, push code to the `dev` or `main` branch.
- On line 10, you'll see `workflow_dispatch`, which means the pipeline won't automatically run unless you kick it off. You can of course change this to have the pipeline automatically run if you, for example, push code to the `dev` or `main` branch.
- The code is checked-out
- Authentication occurs to Azure
- Terraform is set up
- Terraform format occurs
- Terraform format occurs & formats incorrect terraform, then pushes back into the branch
- Terraform init occurs
- Terraform plan occurs
- Terraform apply occurs

4. Run the pipeline and watch as the pipeline automatically creates the AKS cluster
4. Run the pipeline and watch as the pipeline automatically create the AKS cluster
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ resource "azurerm_resource_group" "acr_resource_group" {
}

resource "azurerm_container_registry" "acr" {
name = "${var.name}acr"
name = "${var.name}tamopsacracr"
resource_group_name = azurerm_resource_group.acr_resource_group.name
location = azurerm_resource_group.acr_resource_group.location
sku = "Standard"
Expand Down
Loading