준비하기
1. API 활성화하기
GKE를 생성하기 위해 아래 API를 활성화합니다.
- Compute Engine API
- Kubernetes Engine API
$ gcloud services enable compute.googleapis.com container.googleapis.com
2. Service account 생성하기
아래 역할(Role)을 가지고 있는 Service account를 생성합니다.
- Kubernetes Engine Admin
- Compute Network Admin
- Service Account User
3. Install
- terraform
- gcloud cli ( make sure to gcloud login )
- kubectl
Terraform 파일 작성하기
GKE를 생성하기 위한 Terraform 파일을 작성
1. 자원 정의
terraform-gke 디렉토리를 생성
main.tf 파일을 생성합니다.
$ mkdir terraform-gke
$ cd terraform-gke
$ vi main.tf
1.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 network
resource 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 network
ip_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 cluster
1) GKE cluster
min_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 Pool
node_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
default
workspace를 초기화하면 기본값으로 “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_x5
GKE 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.900
3개의 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.