{"id":14957811,"url":"https://github.com/mathieubuisson/psaksdeployment","last_synced_at":"2025-10-24T12:30:54.771Z","repository":{"id":88662443,"uuid":"159701975","full_name":"MathieuBuisson/PSAksDeployment","owner":"MathieuBuisson","description":"PowerShell tooling to automate the deployment of Azure Kubernetes (AKS) clusters","archived":false,"fork":false,"pushed_at":"2019-09-06T11:09:50.000Z","size":95,"stargazers_count":19,"open_issues_count":1,"forks_count":8,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-01-31T01:11:24.665Z","etag":null,"topics":["azure","kubernetes","kubernetes-setup","terraform","terraform-configurations"],"latest_commit_sha":null,"homepage":null,"language":"PowerShell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MathieuBuisson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-29T17:16:32.000Z","updated_at":"2023-03-26T16:17:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"1dbfef71-82a9-4360-8a25-ca908bb2e0a7","html_url":"https://github.com/MathieuBuisson/PSAksDeployment","commit_stats":{"total_commits":85,"total_committers":5,"mean_commits":17.0,"dds":"0.11764705882352944","last_synced_commit":"a6d99bd3d84838e9eed2a28213d2dca8141bbbc3"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathieuBuisson%2FPSAksDeployment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathieuBuisson%2FPSAksDeployment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathieuBuisson%2FPSAksDeployment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MathieuBuisson%2FPSAksDeployment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MathieuBuisson","download_url":"https://codeload.github.com/MathieuBuisson/PSAksDeployment/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237964492,"owners_count":19394410,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure","kubernetes","kubernetes-setup","terraform","terraform-configurations"],"created_at":"2024-09-24T13:15:39.156Z","updated_at":"2025-10-24T12:30:54.436Z","avatar_url":"https://github.com/MathieuBuisson.png","language":"PowerShell","readme":"# PSAksDeployment\n\n## Overview\n\n[![Build Status](https://dev.azure.com/mathieubuisson/PSAksDeployment/_apis/build/status/MathieuBuisson.PSAksDeployment)](https://dev.azure.com/mathieubuisson/PSAksDeployment/_build/latest?definitionId=12) [![PS Gallery](https://img.shields.io/powershellgallery/v/PSAksDeployment.svg?style=plastic\u0026label=PowerShell%20Gallery\u0026colorB=blue)](https://www.powershellgallery.com/packages/PSAksDeployment/)\n\n**[Azure Kubernetes Service](https://azure.microsoft.com/en-us/services/kubernetes-service/)** (AKS) makes provisioning **[Kubernetes](https://kubernetes.io/)** clusters very easy, in a \"Hello World!\" kind of way.\n\nBut deploying a **production-ready** Kubernetes cluster requires additonal components and considerations :\n  - Monitoring (with metrics and logs)\n  - [Kubectl](https://kubernetes.io/docs/reference/kubectl) configuration\n  - How to deploy resources ([Helm](https://helm.sh/) and Tiller)\n  - Routing requests from the outside world to services in the cluster (ingress controller)\n  - Issuing and managing TLS certificates for ingress controller(s)\n\nPSAksDeployment is a **PowerShell** module which facilitates all of the above by provisioning and configuring extra resources, in addition to the Azure AKS resource.\n\nIt is an opinionated implementation, in the sense that :\n  - Log aggregation and querying is done with **[Azure Monitor](https://azure.microsoft.com/en-us/services/monitor/)** (with Log Analytics)\n  - The metrics collection/querying/alerting solution is **[Prometheus](https://prometheus.io/)**\n  - The metrics charting/graphing/dashboard solution is **[Grafana](https://grafana.com/)**\n  - The ingress controller is **[NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/)**\n  - Management Kubernetes resources are deployed into a \"management\" namespace\n  - The solution to manage TLS certificates is **[cert-manager](https://github.com/jetstack/cert-manager)** (with Let's Encrypt)\n  - The ingress controller TLS certificate is propagated to other namespaces (including namespaces created at a later point), to allow ingresses in any namespace to use it, using a custom tool : **[secret-propagator](https://github.com/MathieuBuisson/PSAksDeployment/tree/master/PSAksDeployment/Assets/secret-propagator)**\n\n\n## Requirements\n\nTo use PSAksDeployment, you need :\n  - Windows PowerShell 5.1\n  - [.Net Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework-runtime) (required by the \"Az\" PowerShell modules)\n\nAll other prerequisites can be installed by running `Install-PSAksPrerequisites`, for example :\n\n```powershell\nInstall-PSAksPrerequisites -InstallationFolder 'C:\\Tools'\n```\n\nThis installs the following (if they are not already installed) :\n  - [Az PowerShell modules](https://docs.microsoft.com/en-us/powershell/azure/install-az-ps) (PSAksDeployment is not compatible with the legacy AzureRM modules)\n  - [Terraform](https://www.terraform.io/)\n  - [Kubectl](https://kubernetes.io/docs/reference/kubectl)\n  - [Helm](https://helm.sh/)\n\nIt also adds the specified installation folder to your `PATH` environment variable (if not already in the `PATH`).\n\n## Installation\n\n### From the PowerShell Gallery\n\nThe easiest and preferred way to install PSAksDeployment is via the [PowerShell Gallery](https://www.powershellgallery.com/).\n\nRun the following command to install PSAksDeployment and its dependencies (\"Az\" PowerShell modules) :\n\n```powershell\nInstall-Module -Name 'PSAksDeployment' -Repository 'PSGallery'\n```\n\n### From Github\n\nAs an alternative, you can clone this repository to a location on your system and copy the `PSAksDeployment` subfolder into :\n`C:\\Program Files\\WindowsPowerShell\\Modules\\`.\n\n**NOTE :** In this case, you need to install the Azure PowerShell modules yourself, like so :\n```powershell\nInstall-Module -Name 'Az.Profile', 'Az.Resources', 'Az.Aks' -Repository 'PSGallery'\n```\n\n## Getting Started\n\n### Deploying a new AKS cluster\n\nThis is the purpose of `Invoke-PSAksDeployment`.\n\nIt deploys the following :\n  - an **[Azure Kubernetes Service](https://azure.microsoft.com/en-us/services/kubernetes-service/)** (AKS) instance\n  - an Azure Log Analytics workspace with the ContainerInsights solution\n  - a Public IP address for the ingress controller\n  - a \"management\" namespace\n  - Tiller\n  - **[NGINX Ingress Controller](https://kubernetes.github.io/ingress-nginx/)**\n  - **[cert-manager](https://github.com/jetstack/cert-manager)**\n  - a TLS certificate (to support HTTPS ingresses)\n  - **[secret-propagator](https://github.com/MathieuBuisson/PSAksDeployment/tree/master/PSAksDeployment/Assets/secret-propagator)**\n  - **[Prometheus](https://prometheus.io/)** (HA setup for the server component)\n  - **[Grafana](https://grafana.com/)**\n\nIt primarily acts as an input validation and orchestration layer. Under the hood, most of the work is done by applying **[Terraform](https://www.terraform.io/)** configurations.\n\nDue to the nature of what it does, `Invoke-PSAksDeployment` takes a large number of parameters :\n\n```powershell\nPS C:\\\u003e Import-Module -Name 'PSAksDeployment'\nPS C:\\\u003e (Get-Command -Name 'Invoke-PSAksDeployment').Parameters.Keys\nServicePrincipalID\nServicePrincipalSecret\nAzureTenantID\nSubscription\nClusterName\nClusterLocation\nLogAnalyticsWorkspaceLocation\nKubernetesVersion\nNodeCount\nNodeSize\nOSDiskSizeGB\nMaxPodsPerNode\nEnvironment\nLetsEncryptEmail\nTerraformOutputFolder\nConfigPath\n```\n\nYou may be wondering :  \n\u003e What are these for ?  \nWhich ones are mandatory ?  \nWhat is the default value ?  \nWhat are the possible values ?  \n\nYou can get this information via the cmdlet help, for example :\n\n```powershell\nPS C:\\\u003e Get-Help 'Invoke-PSAksDeployment' -Parameter 'ServicePrincipalID'\n\n-ServicePrincipalID \u003cString\u003e\n    The application ID of the Service Principal used by Terraform (and the AKS cluster) to access Azure.\n\n    Required?                    true\n    Position?                    1\n    Default value\n    Accept pipeline input?       false\n    Accept wildcard characters?  false\n```\n\nDoing this for each parameter can be tedious, so there is another way to specify all inputs to `Invoke-PSAksDeployment` : a configuration file.\n\n`New-PSAksDeploymentConfig` scaffolds this configuration file, with helpful information for each parameter :\n  - a description\n  - the data type\n  - valid values\n  - the default value\n\nHere is an example :\n\n```powershell\nPS C:\\\u003e $ScaffoldParams = @{\n\u003e\u003e     ServicePrincipalID     = '29x1ecd3-190f-42c9-8660-088f69d121zn'\n\u003e\u003e     ServicePrincipalSecret = 'tsWpRr6/YCxNyh8efMvjWbe5JoOiOw03xR1o9S5CLhZ='\n\u003e\u003e     AzureTenantID          = '96v3b174-9c1p-4a5e-9177-18c3bccc87cb'\n\u003e\u003e     Subscription           = 'DevOps'\n\u003e\u003e     ClusterLocation        = 'North Europe'\n\u003e\u003e     Path                   = '.\\TestScaffold.psd1'\n\u003e\u003e }\nPS C:\\\u003e New-PSAksDeploymentConfig @ScaffoldParams\n```\n\nHere is what the generated file looks like :\n\n```powershell\nPS C:\\\u003e Get-Content .\\TestScaffold.psd1\n@{\n    \u003c#\n    The name of the Azure subscription where the AKS instance (and other Azure resources) will be deployed.\n    Type : String\n    Valid values : \"DevOps\", \"ANY OTHER SUBSCRIPTION WHICH CAN BE ACCESSED BY THE SERVICE PRINCIPAL\"\n    #\u003e\n    Subscription = \"\"\n\n    \u003c#\n    The Azure region where the AKS cluster (and other Azure resources) will be deployed.\n    Type : String\n    Valid values : \"East US\", \"West Europe\", \"Central US\", \"Canada Central\", \"Canada East\", \"UK South\", \"West US\", \"West US 2\", \"Australia East\", \"North Europe\", \"Japan East\", \"East US 2\", \"Southeast Asia\", \"UK West\", \"South India\", \"East Asia\"\n    #\u003e\n    ClusterLocation = \"\"\n\n    \u003c#\n    The Azure region where the Log Analytics workspace will be deployed.\n    This might not be possible to provision the Log Analytics workspace in the same region as the AKS cluster, because Log Analytics is available in a limited set of regions.\n    Type : String\n    Valid values : \"East US\", \"West Europe\", \"Southeast Asia\", \"Australia Southeast\", \"West Central US\", \"Japan East\", \"UK South\", \"Central India\", \"Canada Central\"\n    #\u003e\n    LogAnalyticsWorkspaceLocation = \"\"\n\n    \u003c#\n    The application ID of the Service Principal used by Terraform (and the AKS cluster) to access Azure.\n    Type : String\n    Valid values :\n    #\u003e\n    ServicePrincipalID = \"\"\n\n    \u003c#\n    The password of the Service Principal used by Terraform (and the AKS cluster) to access Azure.\n    Type : String\n    Valid values :\n    #\u003e\n    ServicePrincipalSecret = \"\"\n\n    \u003c#\n    The ID of the Azure AD tenant where the Terraform Service Principal (and the target subscription) live.\n    Type : String\n    Valid values :\n    #\u003e\n    AzureTenantID = \"\"\n\n    \u003c#\n    The name of the AKS cluster.\n    The name of the resource group and the cluster DNS prefix are derived from this value.\n    Type : String\n    Valid values : The name can contain only letters, numbers, and hyphens. The name must start with a letter and must end with a letter or a number.\n    #\u003e\n    ClusterName = \"\"\n\n    \u003c#\n    The version of Kubernetes software running in the AKS Cluster.\n    Type : String\n    Valid values : \"1.9.11\", \"1.10.12\", \"1.10.13\", \"1.11.8\", \"1.11.9\", \"1.12.6\", \"1.12.7\", \"1.13.10\"\n    #\u003e\n    KubernetesVersion = \"1.13.10\"\n\n    \u003c#\n    The number of worker nodes in the AKS cluster.\n    Type : Int32\n    Valid values : Between 1 and 100.\n    #\u003e\n    NodeCount = 3\n  ...\n\n}\n```\n(Output cut for brevity)\n\nNow, you can populate/adjust values in the file to your needs and feed it to `Invoke-PSAksDeployment`, like so :\n\n```powershell\nPS C:\\\u003e Invoke-PSAksDeployment -ConfigPath '.\\TestScaffold.psd1'\n```\n\nSit back and relax, the overall deployment takes around 20-25 minutes.\n\nWhen it completes, **Kubernetes** management tools are ready to work with your new cluster.  \nFor example, you can list the deployments in the \"management\" namespace :\n\n```powershell\nPS C:\\\u003e kubectl get deployment -n management\nNAMESPACE     NAME                            DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE\nmanagement    cert-manager                    1         1         1            1           5m\nmanagement    nginx-ingress-controller        2         2         2            2           11m\nmanagement    nginx-ingress-default-backend   1         1         1            1           11m\nmanagement    secret-propagator               1         1         1            1           3m\n```\n\nOr list all Helm releases :\n\n```powershell\nPS C:\\\u003e helm ls\nNAME                 REVISION    UPDATED                       STATUS         CHART                   APP VERSION   NAMESPACE\ncert-manager         1           Sun Dec  9 18:49:40 2018      DEPLOYED       cert-manager-v0.5.2     v0.5.2        management\ncluster-issuer       1           Sun Dec  9 18:49:51 2018      DEPLOYED       cluster-issuer-0.1.0    1.0           default\nnginx-ingress        1           Sun Dec  9 18:43:16 2018      DEPLOYED       nginx-ingress-1.0.1     0.21.0        management\nsecret-propagator    1           Sun Dec  9 18:51:40 2018      DEPLOYED       secret-propagator-0.1.0 1.0           management\n```\n\nTo open the **Prometheus** web interface, run the following commands :\n\n```powershell\nPS C:\\\u003e $PromSvcPort = kubectl get svc prometheus-server -n management -o jsonpath=\"{.spec.ports[?(@.name=='http')].port}\"\nPS C:\\\u003e kubectl -n management port-forward svc/prometheus-server 9090:$PromSvcPort\nPS C:\\\u003e start \"http://localhost:9090\"\n```\n\nTo login to **Grafana** web interface, we first need to get the `admin` account password :\n\n```powershell\nPS C:\\\u003e $Base64Passwd = kubectl get secret grafana -n management -o jsonpath=\"{.data.admin-password}\"\nPS C:\\\u003e [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Base64Passwd))\n```\n\nTo access the **Grafana** web interface, run the following :\n\n```powershell\nPS C:\\\u003e $GrafanaSvcName = kubectl get svc -n management -l \"app=grafana\" -o jsonpath=\"{.items[0].metadata.name}\"\nPS C:\\\u003e $GrafanaSvcPort = kubectl get svc $GrafanaSvcName -n management -o jsonpath=\"{.spec.ports[0].port}\"\nPS C:\\\u003e kubectl -n management port-forward svc/$GrafanaSvcName 3000:$GrafanaSvcPort\nPS C:\\\u003e start \"http://localhost:3000\"\n```\n\nYou can now login with username `admin` and the password obtained in the previous step.  \n\n### Deleting the AKS cluster (and all associated resources)\n\nAn AKS cluster deployed with `Invoke-PSAksDeployment` may need to be later deprovisioned.\n\nIn this case, the cmdlet `Remove-PSAksDeployment` automates tearing down the Azure Kubernetes Service instance and all associated resources, to stop incurring any Azure charges.\n\nHere is an example usage :\n\n```powershell\nPS C:\\\u003e $DestroyParams = @{\n\u003e\u003e     ServicePrincipalID     = '29x1ecd3-190f-42c9-8660-088f69d121zn'\n\u003e\u003e     ServicePrincipalSecret = 'tsWpRr6/YCxNyh8efMvjWbe5JoOiOw03xR1o9S5CLhZ='\n\u003e\u003e     AzureTenantID          = '96v3b174-9c1p-4a5e-9177-18c3bccc87cb'\n\u003e\u003e     Subscription           = 'DevOps'\n\u003e\u003e     ClusterName            = 'docs-cluster'\n\u003e\u003e }\nPS C:\\\u003e Remove-PSAksDeployment @DestroyParams\n```\n\n## Contributing to PSAksDeployment\n\nYou are welcome to contribute to this project. There are many ways you can contribute :\n\n1. Submit a **[bug report](https://github.com/MathieuBuisson/PSAksDeployment/issues/new?template=Bug_report.md)**.\n2. Submit a fix for an issue.\n3. Submit a **[feature request](https://github.com/MathieuBuisson/PSAksDeployment/issues/new?template=Feature_request.md)**.\n4. Submit test cases.\n5. Tell others about the project.\n6. Tell the developers how much you appreciate the project !\n\nFor more information on how to contribute to PSAksDeployment, please refer to the **[contributing guidelines](https://github.com/MathieuBuisson/PSAksDeployment/blob/master/.github/CONTRIBUTING.md)** document.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathieubuisson%2Fpsaksdeployment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmathieubuisson%2Fpsaksdeployment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmathieubuisson%2Fpsaksdeployment/lists"}