diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl new file mode 100644 index 0000000..4353010 --- /dev/null +++ b/.terraform.lock.hcl @@ -0,0 +1,46 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/digitalocean/digitalocean" { + version = "2.34.1" + constraints = "~> 2.0" + hashes = [ + "h1:QfEfcgrNurRsMvaqWRnUtaH7BrLolVcIJEB3gQ8Tmwo=", + "zh:022d4c97af3d022d4e3735a81c6a7297aa43c3b28a8cecaa0ff58273a5677e2e", + "zh:1922f86d5710707eb497fbebcb1a1c5584c843a7e95c3900d750d81bd2785204", + "zh:1b7ab7c67a26c399eb5aa8a7a695cb59279c6a1a562ead3064e4a6b17cdacabe", + "zh:1dc666faa2ec0efc32329b4c8ff79813b54741ef1741bc42d90513e5ba904048", + "zh:220dec61ffd9448a91cca92f2bc6642df10db57b25d3d27036c3a370e9870cb7", + "zh:262301545057e654bd6193dc04b01666531fccfcf722f730827695098d93afa7", + "zh:63677684a14e6b7790833982d203fb2f84b105ad6b9b490b3a4ecc7043cdba81", + "zh:67a2932227623073aa9431a12916b52ce1ccddb96f9a2d6cdae2aaf7558ccbf8", + "zh:70dfc6ac33ee140dcb29a971df7eeb15117741b5a75b9f8486c5468c9dd28f24", + "zh:7e3b3b62754e86442048b4b1284e10807e3e58f417e1d59a4575dd29ac6ba518", + "zh:7e6fe662b1e283ad498eb2549d0c2260b908ab5b848e05f84fa4acdca5b4d5ca", + "zh:9c554170f20e659222896533a3a91954fb1d210eea60de05aea803b36d5ccd5d", + "zh:ad2f64d758bd718eb39171f1c31219900fd2bfb552a14f6a90b18cfd178a74b4", + "zh:cfce070000e95dfe56a901340ac256f9d2f84a73bf62391cba8a8e9bf1f857e0", + "zh:d5ae30eccd53ca7314157e62d8ec53151697ed124e43b24b2d16c565054730c6", + "zh:fbe5edf5337adb7360f9ffef57d02b397555b6a89bba68d1b60edfec6e23f02c", + ] +} + +provider "registry.terraform.io/hashicorp/kubernetes" { + version = "2.25.1" + constraints = "~> 2.0" + hashes = [ + "h1:cnoVmYWWaQ7RDvSkriqGMOqaq9f+4siSzacYqbUA390=", + "zh:019dcbdd0f6b79bc6331de0f985974585ebdae135924a47991448552f6e7b614", + "zh:10e8e1d4952d1a8d964cf9d9ef980d769ac2b94f56be6cd093b65c700a5023a6", + "zh:11315addb658a91d38f6d1db3358f72de4f3b9bae0934f2f8b0bdff93088711b", + "zh:480db7342b6763dabdaf248782de5a145f7c3b38f88e15e935fd890ad3947d7c", + "zh:4e6d361b3515d1f0255f04ae8b3952cc7ee0133e98142b2fa4b09e83b5c92721", + "zh:5571cf6f7a674c98a9dad4558c1aa65f5883e643e958fcf43c2f7bb474f39fae", + "zh:aec2fe1cafdb413b28e2e74f7f307929497146b99feaaf120a50e4b35e3a892d", + "zh:b6fef36d86b06aec67ffd08280e467b6a268228a4e30202e1981854de8ce7b24", + "zh:ba5eb0e7764df926eb46424bf567ff6226deb00fca389792aa960470345d86cd", + "zh:c79e260c98decd69e956a5a55347127a5a8b3ec5a08c57a0eb127b2cd4bb9292", + "zh:e80a1ee38c21a85607da635c9c18b847d7c2e72a9b1b43e37f05490754d35213", + "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + ] +} diff --git a/README.md b/README.md index 38d5441..8595b48 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ # Terraform Kubernetes Digital Ocean Deploy + Source repository for Digital Ocean deploy conference. This repository contains an example showing how to create a Kubernetes cluster in Digital Ocean, and how to deploy applications to it using Terraform. ## Resources Created -* 1x DOKS cluster, single node `s-2vcpu-2gb` -* Minecraft running as a pod on the clsuter -* 1x External load balancer pointed at the Minecraft instance -* 1x 10GB volume attached to the Minecraft pod used for storing config + +- 1x DOKS cluster, single node `s-2vcpu-2gb` +- Minecraft running as a pod on the clsuter +- 1x External load balancer pointed at the Minecraft instance +- 1x 10GB volume attached to the Minecraft pod used for storing config and data. ## Setup @@ -17,19 +19,19 @@ Terraform can be installed from the following link: [https://www.terraform.io/do ### Obtain your Digital Ocean API Key and set it as an environment variable -* Visit the page: -[https://cloud.digitalocean.com/account/api/tokens](https://cloud.digitalocean.com/account/api/tokens) +- Visit the page: + [https://cloud.digitalocean.com/account/api/tokens](https://cloud.digitalocean.com/account/api/tokens) -* Click Generate New Token: -![](images/generate.png) +- Click Generate New Token: + ![](images/generate.png) -* Give the token a name, ensure Read and Write is set and click generate -![](images/dialog.png) +- Give the token a name, ensure Read and Write is set and click generate + ![](images/dialog.png) -* Copy the the token (long string beneath the name) to your clip board -![](images/token.png) +- Copy the the token (long string beneath the name) to your clip board + ![](images/token.png) -* Create an environment variable using the token +- Create an environment variable using the token ```shell export DIGITALOCEAN_TOKEN=c789eb2af98226de4f31582016b3eb83298a7a3baeb608310880936899a4a4d9 @@ -39,8 +41,8 @@ Terraform will automaticaly read the environment variable `DIGITALOCEAN_TOKEN` a to communicate with the Digital Ocean API. NOTE: Ensure to keep this token private do not add it to any files which may be uploaded to public souce code repositories like GitHub. - ## Initialize Terraform + Before creating resources with Terraform you need to initialize the configuration, this downloads any necessary dependencies and should only need to be done once. To do this run `terraform init` in the current folder. @@ -72,7 +74,7 @@ commands will detect it and remind you to do so if necessary. ## Terraform apply -To create resources you can run a `terraform apply`, this will create the cluster and +To create resources you can run a `terraform apply`, this will create the cluster and the application. Before Terraform creates the cluster it will inform you of the changes it is about to make. This is known as the Terraform plan. Before Terraform will actually create the resources you need to answer `yes` that you approve the plan. @@ -164,15 +166,16 @@ lb_address = 188.166.134.43 ``` ## Connecting to the cluster + To connect to the cluster you need to fetch a Kubernetes config file, Terraform allows the definition of output variables which contain data from the created resources. The `k8s_config` variable contains the config needed to connect to the cluster. You can output this to a file using the following command: ``` -terraform output k8s_config > kubeconfig.yaml +terraform output -raw k8s_config > kubeconfig.yaml ``` -Then you can use `kubectl` as normal to connect to the cluster, running get pods will show you a single pod +Then you can use `kubectl` as normal to connect to the cluster, running get pods will show you a single pod running. ``` @@ -182,7 +185,8 @@ minecraft-66988b7999-wgm5k 1/1 Running 0 7m39s ``` ## Connecting to the Minecraft server -As an example application a Minecraft server has been deployed as a pod to your Kuberenetes cluster. To + +As an example application a Minecraft server has been deployed as a pod to your Kuberenetes cluster. To access the server an external loadbalancer has been created. The address for this load balancer can be retrieved by again querying Terraform output variables. @@ -202,7 +206,7 @@ can add authorization to access the server. ![](images/minecraft_2.png) -You can add access by using the `rcon-cli` inside the Minecraft container, use the following command +You can add access by using the `rcon-cli` inside the Minecraft container, use the following command to get shell access to the container. ``` @@ -229,8 +233,8 @@ Once you have whitelisted your user you can now log into the server. ![](images/minecraft_3.png) - ## Cleaning up and Destroying resources + To clean up all resource created you can use the `teraform destroy` command. ``` diff --git a/k8s.tf b/k8s.tf index 48f0aee..af86d62 100644 --- a/k8s.tf +++ b/k8s.tf @@ -1,12 +1,22 @@ -provider "digitalocean" { - version = "1.22.2" +terraform { + required_providers { + digitalocean = { + source = "digitalocean/digitalocean" + version = "~> 2.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0" + } + } } +provider "digitalocean" {} + resource "digitalocean_kubernetes_cluster" "minecraft" { name = var.name region = var.region - # Grab the latest version slug from `doctl kubernetes options versions` - version = "1.19.3-do.2" + version = "1.28.2-do.0" node_pool { name = "worker-pool" @@ -16,19 +26,14 @@ resource "digitalocean_kubernetes_cluster" "minecraft" { } provider "kubernetes" { - version = "1.13.2" - - load_config_file = false - host = digitalocean_kubernetes_cluster.minecraft.endpoint - token = digitalocean_kubernetes_cluster.minecraft.kube_config[0].token - cluster_ca_certificate = base64decode( - digitalocean_kubernetes_cluster.minecraft.kube_config[0].cluster_ca_certificate - ) + host = digitalocean_kubernetes_cluster.minecraft.endpoint + token = digitalocean_kubernetes_cluster.minecraft.kube_config[0].token + cluster_ca_certificate = base64decode(digitalocean_kubernetes_cluster.minecraft.kube_config[0].cluster_ca_certificate) } resource "kubernetes_deployment" "minecraft" { metadata { - name = "minecraft" + name = "minecraft" labels = { app = "minecraft" } @@ -52,20 +57,20 @@ resource "kubernetes_deployment" "minecraft" { spec { container { - image = var.image - name = "minecraft" + image = var.image + name = "minecraft" image_pull_policy = "Always" port { container_port = var.port - name = "minecraft" + name = "minecraft" } - + dynamic "env" { for_each = var.envs content { - name = env.key + name = env.key value = env.value } } @@ -74,36 +79,35 @@ resource "kubernetes_deployment" "minecraft" { for_each = var.mounts content { - name = kubernetes_persistent_volume_claim.minecraftdata.metadata.0.name - sub_path = volume_mount.value.source + name = kubernetes_persistent_volume_claim.minecraftdata.metadata[0].name + sub_path = volume_mount.value.source mount_path = volume_mount.value.destination } } - } volume { - name = kubernetes_persistent_volume_claim.minecraftdata.metadata.0.name + name = kubernetes_persistent_volume_claim.minecraftdata.metadata[0].name + persistent_volume_claim { - claim_name = kubernetes_persistent_volume_claim.minecraftdata.metadata.0.name - } + claim_name = kubernetes_persistent_volume_claim.minecraftdata.metadata[0].name + } } - } } } } - resource "kubernetes_service" "minecraft" { metadata { name = "minecraft" } + spec { selector = { - app = kubernetes_deployment.minecraft.metadata.0.labels.app + app = "minecraft" } - + port { port = var.port target_port = var.port @@ -117,6 +121,7 @@ resource "kubernetes_persistent_volume_claim" "minecraftdata" { metadata { name = var.volume } + spec { access_modes = ["ReadWriteOnce"] resources { @@ -128,9 +133,10 @@ resource "kubernetes_persistent_volume_claim" "minecraftdata" { } output "k8s_config" { - value = digitalocean_kubernetes_cluster.minecraft.kube_config.0.raw_config + value = digitalocean_kubernetes_cluster.minecraft.kube_config[0].raw_config + sensitive = true } output "lb_address" { - value = kubernetes_service.minecraft.load_balancer_ingress.0.ip + value = kubernetes_service.minecraft.status[0].load_balancer[0].ingress[0].ip } \ No newline at end of file