From d84ff9a00e851b8e6600b0230c9fa6ff2202429b Mon Sep 17 00:00:00 2001 From: Alexander Apalikov Date: Tue, 30 Apr 2019 16:51:14 +0300 Subject: [PATCH] Add AKS terraform module Add configuration for deploying cluster and installing Agones on AKS. --- build/modules/aks/aks.tf | 115 +++++++++++ build/modules/aks/helm.tf | 193 ++++++++++++++++++ examples/terraform-submodules/aks/module.tf | 33 +++ .../gke}/module.tf | 0 .../content/en/docs/Installation/terraform.md | 54 ++++- 5 files changed, 390 insertions(+), 5 deletions(-) create mode 100644 build/modules/aks/aks.tf create mode 100644 build/modules/aks/helm.tf create mode 100644 examples/terraform-submodules/aks/module.tf rename examples/{terraform-submodule => terraform-submodules/gke}/module.tf (100%) diff --git a/build/modules/aks/aks.tf b/build/modules/aks/aks.tf new file mode 100644 index 0000000000..481e97f8cc --- /dev/null +++ b/build/modules/aks/aks.tf @@ -0,0 +1,115 @@ +# Copyright 2019 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +provider "azuread" { + version = "=0.1.0" +} + +variable "machine_type" { + default = "Standard_D2_v2" +} + +# Create Service Principal password +resource "azuread_service_principal_password" "aks" { + end_date = "2299-12-30T23:00:00Z" # Forever + service_principal_id = "${azuread_service_principal.aks.id}" + value = "${random_string.password.result}" +} + +# Create Azure AD Application for Service Principal +resource "azuread_application" "aks" { + name = "agones-sp" +} + +# Create Service Principal +resource "azuread_service_principal" "aks" { + application_id = "${azuread_application.aks.application_id}" +} + +# Generate random string to be used for Service Principal Password +resource "random_string" "password" { + length = 32 + special = true +} + +resource "azurerm_resource_group" "test" { + name = "agonesRG" + location = "East US" +} + +resource "azurerm_kubernetes_cluster" "test" { + name = "agones" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + dns_prefix = "agones" + + agent_pool_profile { + name = "default" + count = 2 + vm_size = "${var.machine_type}" + os_type = "Linux" + os_disk_size_gb = 30 + } + + service_principal { + client_id = "${azuread_application.aks.application_id}" + client_secret = "${azuread_service_principal_password.aks.value}" + } + tags = { + Environment = "Production" + } +} + +output "client_certificate" { + value = "${azurerm_kubernetes_cluster.test.kube_config.0.client_certificate}" +} + +output "kube_config" { + value = "${azurerm_kubernetes_cluster.test.kube_config_raw}" +} + +resource "azurerm_network_security_group" "test" { + name = "agonesSecurityGroup" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_network_security_rule" "gameserver" { + name = "gameserver" + priority = 100 + direction = "Inbound" + access = "Allow" + protocol = "UDP" + source_port_range = "*" + destination_port_range = "7000-8000" + source_address_prefix = "*" + destination_address_prefix = "*" + resource_group_name = "${azurerm_resource_group.test.name}" + network_security_group_name = "${azurerm_network_security_group.test.name}" +} + + +resource "azurerm_network_security_rule" "traffic" { + name = "traffic" + priority = 100 + direction = "Outbound" + access = "Allow" + protocol = "Tcp" + source_port_range = "*" + destination_port_range = "*" + source_address_prefix = "*" + destination_address_prefix = "*" + resource_group_name = "${azurerm_resource_group.test.name}" + network_security_group_name = "${azurerm_network_security_group.test.name}" +} \ No newline at end of file diff --git a/build/modules/aks/helm.tf b/build/modules/aks/helm.tf new file mode 100644 index 0000000000..df99a73c2f --- /dev/null +++ b/build/modules/aks/helm.tf @@ -0,0 +1,193 @@ +# Copyright 2019 Google LLC All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +resource "kubernetes_service_account" "tiller" { + metadata { + name = "tiller" + namespace = "kube-system" + } + depends_on = ["azurerm_kubernetes_cluster.test"] + + automount_service_account_token = true +} + +resource "kubernetes_cluster_role_binding" "tiller" { + depends_on = ["kubernetes_service_account.tiller"] + metadata { + name = "tiller" + } + + role_ref { + kind = "ClusterRole" + name = "cluster-admin" + api_group = "rbac.authorization.k8s.io" + } + + subject { + kind = "ServiceAccount" + name = "tiller" + + api_group = "" + namespace = "kube-system" + } +} +variable "chart" { + default = "../../../install/helm/agones/" +} + +variable "agones_version" { + default = "" +} + +variable "crd_cleanup" { + default = "true" +} +variable "image_registry" { + default = "gcr.io/agones-images" +} +variable "pull_policy" { + default = "Always" +} +variable "always_pull_sidecar" { + default = "true" +} +variable "image_pull_secret" { + default = "" +} +variable "ping_service_type" { + default = "LoadBalancer" +} + +variable "values_file" { + default = "../../../install/helm/agones/values.yaml" +} +provider "kubernetes" { + version = "~> 1.5" + load_config_file = false + host = "${azurerm_kubernetes_cluster.test.kube_config.0.host}" + token = "${azurerm_kubernetes_cluster.test.kube_config.0.password}" + cluster_ca_certificate = "${base64decode(azurerm_kubernetes_cluster.test.kube_config.0.cluster_ca_certificate)}" +} + +provider "helm" { + version = "~> 0.7" + + debug = true + install_tiller = true + service_account = "${kubernetes_service_account.tiller.metadata.0.name}" + tiller_image = "gcr.io/kubernetes-helm/tiller:v2.12.3" + + kubernetes { + load_config_file = false + token = "${azurerm_kubernetes_cluster.test.kube_config.0.password}" + host = "${azurerm_kubernetes_cluster.test.kube_config.0.host}" + cluster_ca_certificate = "${base64decode(azurerm_kubernetes_cluster.test.kube_config.0.cluster_ca_certificate)}" + } +} + +# In Terraform version 0.12 Interpolation would only evaluate one branch of a condition +# https://github.com/hashicorp/terraform/issues/15605 +# so we can remove this and change values in helm_release to: +# +# values = [ +# "${length(var.values_file) == 0 ? "" : file("${var.values_file}"))}" +# ] +data "null_data_source" "values_file" { + count = "${length(var.values_file) == 0 ? 0 : 1}" + inputs = { + "values" = "${file("${var.values_file}")}" + } +} + + +data "helm_repository" "agones" { + depends_on = ["kubernetes_cluster_role_binding.tiller"] + name = "agones" + url = "https://agones.dev/chart/stable" +} + + +# TODO: remove - not needed in Terraform 0.12 +locals { + values = { + params = "${join("", data.null_data_source.values_file.*.outputs.values)}" + } + # Skip image tag if it is not needed + # for installing latest image it would use chart value + tag_name = "${var.agones_version != "" ? "agones.image.tag" : "skip"}" +} + +resource "helm_release" "agones" { + depends_on = ["null_resource.helm_init", "kubernetes_cluster_role_binding.tiller"] + name = "agones" + force_update = "true" + repository = "${data.helm_repository.agones.metadata.0.name}" + chart = "${var.chart}" + timeout = 420 + + values = [ + # Switch in terraform 0.12 to: + # "${length(var.values_file) == 0 ? "" : file("${var.values_file}"))}" + "${length(var.values_file) == 0 ? "" : local.values["params"]}" + ] + + set { + name = "crds.CleanupOnDelete" + value = "${var.crd_cleanup}" + } + set { + name = "${local.tag_name}" + value = "${var.agones_version}" + } + set { + name = "agones.image.registry" + value = "${var.image_registry}" + } + set { + name = "agones.image.controller.pullPolicy" + value = "${var.pull_policy}" + } + set { + name = "agones.image.sdk.alwaysPull" + value = "${var.always_pull_sidecar}" + } + set { + name = "agones.image.controller.pullSecret" + value = "${var.image_pull_secret}" + } + set { + name = " agones.ping.http.serviceType" + value = "${var.ping_service_type}" + } + set { + name = "agones.ping.udp.serviceType" + value = "${var.ping_service_type}" + } + version = "${var.agones_version}" + namespace = "agones-system" +} + +provider "null" { + version = "~> 2.1" +} + +# Creates folder with repositories so that helm provider would not fail +resource "null_resource" "helm_init" { + triggers = { + always_run = "${timestamp()}" + } + provisioner "local-exec" { + command = "helm init --client-only" + } +} diff --git a/examples/terraform-submodules/aks/module.tf b/examples/terraform-submodules/aks/module.tf new file mode 100644 index 0000000000..631f466bba --- /dev/null +++ b/examples/terraform-submodules/aks/module.tf @@ -0,0 +1,33 @@ +// Copyright 2019 Google LLC All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +// Run: +// terraform apply [-var agones_version="0.9.0"] + +// Install latest version of agones +variable "agones_version" { + default="" +} + +variable "machine_type" {default = "Standard_D2_v2"} + +module "agones" { + source = "git::https://github.com/GoogleCloudPlatform/agones.git//build/modules/aks/?ref=master" + + agones_version = "${var.agones_version}" + machine_type = "${var.machine_type}" + values_file="" + chart="agones" +} diff --git a/examples/terraform-submodule/module.tf b/examples/terraform-submodules/gke/module.tf similarity index 100% rename from examples/terraform-submodule/module.tf rename to examples/terraform-submodules/gke/module.tf diff --git a/site/content/en/docs/Installation/terraform.md b/site/content/en/docs/Installation/terraform.md index 3cec872316..68beb32885 100644 --- a/site/content/en/docs/Installation/terraform.md +++ b/site/content/en/docs/Installation/terraform.md @@ -1,5 +1,5 @@ --- -title: "Deploy GKE cluster and install Agones using Terraform" +title: "Deploy GKE/AKS cluster and install Agones using Terraform" linkTitle: "Install with Terraform" weight: 4 description: > @@ -12,10 +12,10 @@ description: > - Terraform v0.11.13 - [Helm](https://docs.helm.sh/helm/) package manager 2.10.0+ - Access to Google Cloud Kubernetes Engine -- `gcloud` utility installed +- `gcloud` or `az` utility installed - Git -## Installing the Agones as Terraform submodule +# Installing the Agones as Terraform submodule on Google Kubernetes Engine You can use Terraform to provision your GKE cluster and install agones on it using Helm Terraform provider. @@ -31,7 +31,7 @@ By default you will receive the latest version from [Helm repository](https://ag ## Example and parameters which is configurable The example of submodule configuration could be found here: - {{< ghlink href="examples/terraform-submodule/module.tf" >}}Terraform configuration with Agones submodule{{< /ghlink >}} + {{< ghlink href="examples/terraform-submodules/gke/module.tf" >}}Terraform configuration with Agones submodule{{< /ghlink >}} Configurable parameters and their meaning: - password - if not specified basic Auth would be disabled in GKE cluster @@ -70,7 +70,7 @@ Fetching cluster endpoint and auth data. kubeconfig entry generated for test-cluster. ``` -Check that your has access to kubernetes cluster: +Check that you have access to kubernetes cluster: ``` kubectl get nodes ``` @@ -83,3 +83,47 @@ Run next command to delete all Terraform provisioned resources: ``` terraform destroy ``` + +# Installing the Agones as Terraform submodule on Azure Kubernetes Service + +You can deploy cluster on Azure Kubernetes Service. + +The example of AKS submodule configuration could be found here: + {{< ghlink href="examples/terraform-submodules/aks/module.tf" >}}Terraform configuration with Agones submodule{{< /ghlink >}} + +Copy `module.tf` file into a separate folder. + +Login to Azure CLI: +``` +az login +``` + +Configure your terraform: +``` +terraform init +``` + +Now you can deploy your cluster (use variables from the above `az ad sp create-for-rbac` command output): +``` +terraform apply -var client_id="" -var client_secret="" +``` + +Once you created all resources on AKS you can get the credentials so that you can use `kubectl` to configure your cluster: +``` +az aks get-credentials --resource-group agonesRG --name agones +``` + +Check that you have access to kubernetes cluster: +``` +kubectl get nodes +``` + +## Uninstall the Agones and delete AKS cluster + +Run next command to delete all Terraform provisioned resources: +``` +terraform destroy +``` + +## Reference +Details on how you can authenticate your AKS terraform provider using official [instructions](https://www.terraform.io/docs/providers/azurerm/auth/service_principal_client_secret.html) \ No newline at end of file