Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Thomas Perelle committed Feb 8, 2021
1 parent dba4c20 commit 691cc32
Show file tree
Hide file tree
Showing 7 changed files with 505 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# EditorConfig is awesome: https://EditorConfig.org

root = true

[**]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
170 changes: 170 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Created by https://www.gitignore.io/api/macos,terraform,terragrunt,virtualenv,intellij+all
# Edit at https://www.gitignore.io/?templates=macos,terraform,terragrunt,virtualenv,intellij+all

### Intellij+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf

# Generated files
.idea/**/contentModel.xml

# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml

# Gradle
.idea/**/gradle.xml
.idea/**/libraries

# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr

# CMake
cmake-build-*/

# Mongo Explorer plugin
.idea/**/mongoSettings.xml

# File-based project format
*.iws

# IntelliJ
out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties

# Editor-based Rest Client
.idea/httpRequests

# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser

### Intellij+all Patch ###
# Ignores the whole .idea folder and all .iml files
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360

.idea/

# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023

*.iml
modules.xml
.idea/misc.xml
*.ipr

# Sonarlint plugin
.idea/sonarlint

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Terraform ###
# Local .terraform directories
**/.terraform/*
**/.terraform.lock.hcl

# .tfstate files
*.tfstate
*.tfstate.*

# Crash log files
crash.log

# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*

### Terragrunt ###
# terragrunt cache directories
**/.terragrunt-cache/*

### VirtualEnv ###
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
.Python
pyvenv.cfg
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
pip-selfcheck.json
env.sh

**/.temp/*kube_config

# End of https://www.gitignore.io/api/macos,terraform,terragrunt,virtualenv,intellij+all
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Hub and spoke AKS

This project contains sources to build an hub and spoke infrastructure on Azure with multiple AKS environments.

## Architecture overview

The archirecture is built on an [hub and spoke network topology](https://docs.microsoft.com/en-us/azure/architecture/reference-architectures/hybrid-networking/hub-spoke?tabs=cli).

## Requirements

### Tools

These tools must be present in your environment to execute the different stacks of the project:

- [Git](https://git-scm.com/downloads)
- [Python 3.7](https://www.python.org/downloads/release/python-370/)
- [Azure CLI 2.18.0](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli)
- [Terraform 0.14.5](https://www.terraform.io/downloads.html)
- [kubectl 1.20.1](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [helm 3.2.1](https://helm.sh/docs/intro/install/)

> You can build a Docker base image including all these requirements in order to guarantee that all team members and your CI tool use exactly the same environment to work with the project.
### Service principal for Terraform

[Setup Service Principal for Terraform](docs/tf_azure_authent.md)

### Backend

Terraform needs a shared storage to store state files.
In Azure, stores the state as a Blob with the given Key within the Blob Container within the Blob Storage Account. This backend also supports state locking and consistency checking via native capabilities of Azure Blob Storage.

[Create the terraform backend if it doesn't already exists](docs/tf_backend.md)

## Deployment

### Infrastructure

The infrastructure is divided in two different terraform stacks containing resources which will have different lifecycle:

- [`aks`](terraform/aks/README.md):
- implements an AKS environment
- use terraform workspace to manage multiple environments with their specificities
- [`hub`](terraform/hub/README.md): implements the hub containing cross environment components
145 changes: 145 additions & 0 deletions docs/tf_azure_authent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Terraform authentication for Azure

Terraform needs to be authenticated in order to interact with Azure resources.

## Authentication methods

Microsoft Azure offers a few authentication methods that allow Terraform to deploy resources, and one of them is an SP account.

The reason an SP account is better than other methods is that we don’t need to log in to Azure before running Terraform.

With the other methods (Azure CLI, or Cloud Shell), we need to login to Azure using az login or Cloud Shell.

## Creating a Service Principal using the Azure CLI

Firstly, login to the Azure CLI using:

```bash
$ az login
```

Once logged in - it's possible to list the Subscriptions associated with the account via:

```bash
$ az account list
```

The output (similar to below) will display one or more Subscriptions - with the id field being the subscription_id field referenced above.

```json
[
{
"cloudName": "AzureCloud",
"id": "00000000-0000-0000-0000-000000000000",
"isDefault": true,
"name": "PAYG Subscription",
"state": "Enabled",
"tenantId": "00000000-0000-0000-0000-000000000000",
"user": {
"name": "[email protected]",
"type": "user"
}
}
]
```

Should you have more than one Subscription, you can specify the Subscription to use via the following command:

```bash
$ az account set --subscription="00000000-0000-0000-0000-000000000000"
```

We can now create the Service Principal which will have permissions to manage resources in the specified Subscription using the following command:

```bash
$ az ad sp create-for-rbac --name="service_terraform" --role="Owner" --scopes="/subscriptions/00000000-0000-0000-0000-000000000000"
```

> The `Owner` role is necessary in order terraform will be able to assign roles on resources it will create.
This command will output 5 values:

```json
{
"appId": "00000000-0000-0000-0000-000000000000",
"displayName": "service_terraform",
"name": "http://azure-cli-2017-06-05-10-41-15",
"password": "0000-0000-0000-0000-000000000000",
"tenant": "00000000-0000-0000-0000-000000000000"
}
```

Finally, it's possible to test these values work as expected by first logging in:

```bash
$ az login --service-principal -u CLIENT_ID -p CLIENT_SECRET --tenant TENANT_ID
```

Once logged in as the Service Principal - we should be able to list the VM sizes by specifying an Azure region, for example here we use the West US region:

```bash
$ az vm list-sizes --location francecentral
```

Finally, since we're logged into the Azure CLI as a Service Principal we recommend logging out of the Azure CLI (but you can instead log in using your user account):

```bash
$ az logout
```

## Configuring the Service Principal in Terraform

As we've obtained the credentials for this Service Principal - it's possible to configure them in a few different ways but it is important to avoid storing them in source code.
We prefer storing the credentials as Environment Variables, for example:

```bash
$ export ARM_CLIENT_ID="00000000-0000-0000-0000-000000000000"
$ export ARM_CLIENT_SECRET="00000000-0000-0000-0000-000000000000"
$ export ARM_SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"
$ export ARM_TENANT_ID="00000000-0000-0000-0000-000000000000"
```

These values map to the Terraform variables like so:

- appId is the client_id defined above.
- password is the client_secret defined above.
- tenant is the tenant_id defined above.

> You can create your own `env.sh` script at the root of the project. Take example upon the model [env.sh.example](../env.sh.example).
## Add Azure AD permissions

Terraform needs to create Azure AD applications and Service Principals.
So we need to add the role `Global Administrator` to the Terraform Service Principal `service_terraform`.

## Check Terraform works

You can create a `provider.tf` file:

```hcl
terraform {
required_providers {
azurerm = {
source = "azurerm"
version = "= 2.45.1"
}
azuread = {
source = "azuread"
version = "= 1.3.0"
}
}
}
provider "azurerm" {
features {}
}
```

And try some Terraform commands:

```bash
$ terraform init
$ terraform plan
```

You will be sure of the correct functioning when you will create resources of different types with the providers `azurerm` and `azuread`.
Loading

0 comments on commit 691cc32

Please sign in to comment.