구글 클라우드 인사이트 Terraform을 사용하여 GKE 생성하기 구글 인사이트 by Miyeon. Jo 2023년 02월 06일 2023년 02월 06일 462 목차준비하기Terraform 파일 작성하기Terraform workspace 초기화하기GKE Cluster 생성생성자원 확인변경하기삭제하기준비하기1. API 활성화하기GKE를 생성하기 위해 아래 API를 활성화합니다.Compute Engine API Kubernetes Engine API $ gcloud services enable compute.googleapis.com container.googleapis.com2. Service account 생성하기아래 역할(Role)을 가지고 있는 Service account를 생성합니다.Kubernetes Engine Admin Compute Network Admin Service Account User3. Installterraformgcloud cli ( make sure to gcloud login )kubectlTerraform 파일 작성하기GKE를 생성하기 위한 Terraform 파일을 작성1. 자원 정의terraform-gke 디렉토리를 생성 main.tf 파일을 생성합니다.$ mkdir terraform-gke $ cd terraform-gke $ vi main.tf1.1. Provider 선언provider name: google provider version: “~> 3.46” project: var.project_id (GCP의 project 이름, “variables.tf”에 정의) region: var.region (GCP의 region 이름, “variables.tf”에 정의) provider "google" { version = "~> 3.400" project = var.project_id region = var.region }1.2. Network : GKE를 생성할 network를 선언1) VPC networkresource type: google_compute_network (생성할 resource type) local name: vpc (local에서 참조할 이름) auto_create_subnetworks: false (subnet 자동 생성 옵션) resource "google_compute_network" "vpc" { name = "${var.project_id}-vpc" auto_create_subnetworks = "false" }2) Subnet networkip_cidr_range: “10.10.0.0/24” (CIRD 범위) resource "google_compute_subnetwork" "subnet" { name = "${var.project_id}-subnet" region = var.region network = google_compute_network.vpc.name ip_cidr_range = "10.10.0.0/24" }1.3. GKE cluster1) GKE clustermin_master_version: “1.23” (Master의 최소 버전) remove_default_node_pool: true (Default node pool 삭제 여부) initial_node_count: 1 (각 zone에 생성할 node 수) resource "google_container_cluster" "primary" { name = "${var.project_id}-gke" location = var.region min_master_version = "1.23" remove_default_node_pool = true initial_node_count = 1 network = google_compute_network.vpc.name subnetwork = google_compute_subnetwork.subnet.name }참고 “remove_default_node_pool” Cluster는 default node pool 없이 생성이 불가능합니다 (일종의 template). 그래서 remove_default_node_pool 값을 “true”로 설정하면 default node pool을 작게 생성한 뒤 바로 삭제합니다.2) Separately Managed Node Poolnode_count: var.gke_num_nodes (각 zone에 생성할 node 수, “variables.tf”에 정의) node_config.oauth_scopes: API 접근 권한 node_config.metadata.disable-legacy-endpoints: true (Legacy endpoint 비활성화 여부) resource "google_container_node_pool" "primary_nodes" { name = "${google_container_cluster.primary.name}-node-pool" location = var.region cluster = google_container_cluster.primary.name node_count = var.gke_num_nodes node_config { oauth_scopes = [ "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring", ] labels = { env = var.project_id } machine_type = var.gke_machine_type tags = ["gke-node", "${var.project_id}-gke"] metadata = { disable-legacy-endpoints = "true" } } }[참고] “node_count”는 각 zone에 생성할 node의 수입니다. 만약 이 값을 3으로 설정하고 region이 “asia-northeast3″라면 3개의 zone에 각각 3개의 node가 생성되어 총 9개의 node가 생성됩니다.[참고] GKE 1.12 버전 이상부터 “disable-legacy-endpoints” 값은 “true”가 기본으로 설정됩니다. 만약 metadata를 설정하고 “disable-legacy-endpoints”의 기본값을 선언하지 않으면, terraform은 이 값을 해제합니다. 이를 방지하기 위해서 “disable-legacy-endpoints” 값을 “true”로 설정해야합니다.2. 변수 정의하기variables.tf 파일을 생성 project_id, region, gke_num_nodes, gke_machine_type 변수를 선언default 값이 있는 경우 정의해주고, description 값에 변수에 대한 주석을 작성합니다. 이 변수는 terraform 명령 실행 시 다른 값으로 치환할 수 있습니다.$ vi variables.tf variable "project_id" { description = "project id" } variable "region" { description = "region" } variable "gke_num_nodes" { default = 3 description = "number of gke nodes" } variable "gke_machine_type" { default = "n1-standard-4" description = "machine type of gke nodes" }3. 결과 정의하기자원을 생성한 후 추출해야하는 값이 있는 경우 “output” block에 선언합니다. 이 값은 terraform apply 실행 시 사용자에게 보여집니다. “kubernetes_cluster_name”는 이 output의 식별자이고 value는 생성한 자원의 이름입니다.$ vi outputs.tf output "kubernetes_cluster_name" { value = google_container_cluster.primary.name description = "GKE Cluster Name" }4. 버전 정의하기필요한 버전을 선언합니다.$ vi version.tf terraform { required_version = ">= 0.12" }Terraform workspace 초기화하기$ terraform init ... Terraform has been successfully initialized! $ ls -al drwxr-xr-x 4 ... ... .terraform $ cat .terraform/environment defaultworkspace를 초기화하면 기본값으로 “default 값이 생성됩니다.workspace 목록을 조회$ terraform workspace list * default“*” 표시(활성화된 workspace)를 확인$ cat .terraform/plugins/selections.json { "registry.terraform.io/hashicorp/google": { "hash": "h1:UIugsEPd4efky7G86YVdjkW5wwMIIW/WWeFod7RsbbQ=", "version": "3.47.0" } }“main.tf”의 “provider.version”에 선언한 대로 plugin을 설치한 것을 확인할 수 있습니다.모듈을 불러오기 위한 설정$ ls -all .terraform/plugins/registry.terraform.io/hashicorp/google/3.47.0/darwin_amd64 ... -rwxr-xr-x 1 ... ... terraform-provider-google_v3.47.0_x5GKE cluster 생성하기1. 환경 변수 설정하기variabes.tf 파일을 작성 terraform.tf vars파일에 아래와 같이 선언project_id = "my-project-gke" region = "asia-northeast3"민감한 정보가 있는 경우 OS 환경변수에 정의 (git 에 업로드 하지 않는게 보안상 좋음)GOOGLE_APPLICATION_CREDENTIALS: 생성한 service account json file의 경로 입력## "GOOGLE_APPLICATION_CREDENTIALS" is a file's path exported from service account. export GOOGLE_APPLICATION_CREDENTIALS="REPLACE_ME" export PROJECT_ID="REPLACE_ME" export REGION="REPLACE_ME" ## e.g export GOOGLE_APPLICATION_CREDENTIALS="/home/user/.gcp/gke-service-account.json" export PROJECT_ID="my-project" export REGION="asia-northeast3"2. 검증하기자원을 생성하기전 먼저 검증을 할 수 있습니다. 인프라 자원을 변경하는 것은 매우 조심스러운 작업인데 실수로 지워버린다던가 하는 위험성을 줄여주는 좋은 기능입니다. main.tf에서 정의한대로 vpc network, subnet network, gke cluster, gke node pool이 어떤식으로 생성될지 미리 보여줍니다.$ terraform plan \ -var "project_id=$PROJECT_ID" \ -var "region=$REGION" \ -var "gke_num_nodes=1" ... Terraform will perform the following actions: ... # google_compute_network.vpc will be created + resource "google_compute_network" "vpc" { ... # google_container_cluster.primary will be created + resource "google_container_cluster" "primary" { ... # google_container_node_pool.primary_nodes will be created + resource "google_container_node_pool" "primary_nodes" { … Plan: 4 to add, 0 to change, 0 to destroy.3. 생성하기$ terraform apply \ -var "project_id=$PROJECT_ID" \ -var "region=$REGION" \ -var "gke_num_nodes=1" ... Plan: 4 to add, 0 to change, 0 to destroy. ##plan 명령과 다른 점은 실제로 이 명령을 수행할 것인지 한번 더 물어봅니다. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes ##인프라 자원 생성 시작 google_compute_network.vpc: Creating... google_compute_network.vpc: Still creating... [13s elapsed] google_compute_network.vpc: Creation complete after 22s ... google_compute_subnetwork.subnet: Creation complete after 15s ... ##전체 단계가 완료되면 outputs.tf 정의한 값이 출력됩니다. Outputs: + kubernetes_cluster_name = "my-project-gke" + region = "asia-northeast3" Apply complete! Resources: 4 added, 0 changed, 0 destroyed.생성한 자원 확인하기gcloud CLI를 통해 credential 정보를 저장합니다.$ gcloud container clusters get-credentials my-project-gke \ --region asia-northeast3 \ --project my-project Fetching cluster endpoint and auth data. kubeconfig entry generated for my-project-gke.node-pools의 정보 조회$ gcloud container node-pools list \ --cluster=$PROJECT_ID-gke \ --project=$PROJECT_ID \ --region=$REGION NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION my-project-gke-node-pool n1-standard-4 100 1.23.13-gke.9003개의 node 정보를 정상적으로 가져오는것을 확인할 수 있습니다.$ kubectl get nodes NAME STATUS ROLES AGE VERSION gke-asia--default-pool-23b72450-009z Ready <none> 10d v1.22.15-gke.2500 gke-asia--default-pool-23b72450-7f6p Ready <none> 10d v1.22.15-gke.2500 gke-asia--default-pool-23b72450-7xsi Ready <none> 10d v1.22.15-gke.2500변경하기이번에는 GKE cluster의 설정을 변경해보겠습니다. Machine type : n1-standard-4 -> n1-highmem-4적용전에 검증을 합니다. 기존 machine type의 node_pool을 삭제하고 새로운 node_pool이 추가되는 것을 확인.$ terraform plan \ -var "project_id=$PROJECT_ID" \ -var "region=$REGION" \ -var "gke_num_nodes=1" \ -var "gke_machine_type=n1-highmem-4" ... Terraform will perform the following actions: # google_container_node_pool.primary_nodes must be replaced ~ machine_type = "n1-standard-4" -> "n1-highmem-4" # forces replacement Plan: 1 to add, 0 to change, 1 to destroy.$ terraform apply \ -var "project_id=$PROJECT_ID" \ -var "region=$REGION" \ -var "gke_num_nodes=1" \ -var "gke_machine_type=n1-highmem-4" ... Plan: 1 to add, 0 to change, 1 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes google_container_node_pool.primary_nodes: Destroying... [id=projects/my-project/locations/asia-northeast3/clusters/my-project-gke/nodePools/my-project-gke-node-pool] ... google_container_node_pool.primary_nodes: Creation complete after 1m22s [id=projects/my-project/locations/asia-northeast3/clusters/my-project-gke/nodePools/my-project-gke-node-pool] ... Apply complete! Resources: 1 added, 0 changed, 1 destroyed. Outputs: kubernetes_cluster_name = my-project-gke기존 node pool을 삭제하고 새로운 node pool을 생성하는것이 확인됩니다.참고 node pool이 삭제되면서 실행중인 pod도 전부 삭제됩니다. 실제 개발/운영 환경이라면 node pool을 여러개 만들어 놓고 변경 작업이 일어나는 node의 pod를 모두 다른 node로 migration하는 작업이 선행되어야 합니다.변경 작업이 완료되면 node pool을 다시 조회해봅니다. Machine type이 n1-highmem-4로 변경되었습니다.$ gcloud container node-pools list \ --cluster=$PROJECT_ID-gke \ --project=$PROJECT_ID \ --region=$REGION NAME MACHINE_TYPE DISK_SIZE_GB NODE_VERSION my-project-gke-node-pool n1-highmem-4 100 1.23.13-gke.900삭제하기## cluster삭제$ terraform destroy \ -var "project_id=$PROJECT_ID" \ -var "region=$REGION" ... Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes ... Destroy complete! Resources: 4 destroyed. 출처https://cloud.google.com/docs/terraform/get-started-with-terraform?hl=kohttps://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/container_clusterhttps://yunsangjun.github.io/terraform/2020/11/09/getting-started-terraform.html