Terraform을 사용하여 GKE 클러스터 만들기 및 워크로드 배포


이 빠른 시작에서는 Google Kubernetes Engine(GKE) Autopilot 클러스터를 만들고 Terraform을 사용하여 워크로드를 배포하는 방법을 알아봅니다.

코드형 인프라(IaC)는 코드를 사용하여 소프트웨어 인프라 리소스를 관리하고 프로비저닝하는 방식입니다. Terraform은 GKE를 포함한 다양한 Cloud 서비스를 지원하는 널리 사용되는 오픈소스 IaC 도구입니다. GKE 플랫폼 관리자는 Terraform을 사용하여 Kubernetes 클러스터 구성을 표준화하고 DevOps 워크플로를 간소화할 수 있습니다. 자세한 내용은 GKE에 대한 Terraform 지원을 참조하세요.

목표

  • IPv6 Virtual Private Cloud(VPC) 네트워크 만들기
  • GKE Autopilot 클러스터 만들기
  • 클러스터에 워크로드 배포
  • 서비스를 사용하여 워크로드 노출

시작하기 전에

다음 단계에 따라 Kubernetes Engine API를 사용 설정합니다.

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the GKE API.

    Enable the API

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE API.

    Enable the API

  8. Make sure that you have the following role or roles on the project: roles/container.admin, roles/compute.networkAdmin, roles/iam.serviceAccountUser

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role colunn to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      IAM으로 이동
    2. 프로젝트를 선택합니다.
    3. 액세스 권한 부여를 클릭합니다.
    4. 새 주 구성원 필드에 사용자 식별자를 입력합니다. 일반적으로 Google 계정의 이메일 주소입니다.

    5. 역할 선택 목록에서 역할을 선택합니다.
    6. 역할을 추가로 부여하려면 다른 역할 추가를 클릭하고 각 역할을 추가합니다.
    7. 저장을 클릭합니다.

    Terraform 기본사항을 잘 알고 있어야 합니다. 다음 리소스를 사용할 수 있습니다.

환경 준비

이 튜토리얼에서는 Cloud Shell을 사용하여 Google Cloud에서 호스팅되는 리소스를 관리합니다. Cloud Shell에는 Terraform, kubectl, Google Cloud CLI를 포함하여 이 튜토리얼에 필요한 소프트웨어가 사전에 설치되어 있습니다.

  1. Cloud Shell 활성화 아이콘 Cloud Shell 활성화 셸 활성화 버튼를 클릭하여 Google Cloud 콘솔에서 Cloud Shell 세션을 시작합니다. 그러면 Google Cloud 콘솔 하단 창에서 세션이 시작됩니다.

    이 가상 머신과 연결된 서비스 사용자 인증 정보가 자동으로 생성되므로 서비스 계정 키를 설정하거나 다운로드할 필요가 없습니다.

  2. 명령어를 실행하기 전에 다음 명령어를 사용하여 gcloud CLI에서 기본 프로젝트를 설정합니다.

    gcloud config set project PROJECT_ID
    

    여기서 PROJECT_ID프로젝트 ID로 바꿉니다.

  3. GitHub 저장소를 클론합니다.

    git clone https://github.com/terraform-google-modules/terraform-docs-samples.git --single-branch
    
  4. 작업 디렉터리로 변경합니다.

    cd terraform-docs-samples/gke/quickstart/autopilot
    

Terraform 파일 검토

Google Cloud Provider는 HashiCorp의 코드형 인프라(IaC) 도구인 Terraform을 사용하여 Google Cloud 리소스를 관리하고 프로비저닝할 수 있게 해주는 플러그인입니다. Terraform 구성과 Google Cloud API 사이의 브리지 역할을 하므로 선언적 방식으로 가상 머신 및 네트워크와 같은 인프라 리소스를 정의할 수 있습니다.

  1. cluster.tf 파일을 검토합니다.

    cat cluster.tf
    

    출력은 다음과 비슷합니다.

    resource "google_compute_network" "default" {
      name = "example-network"
    
      auto_create_subnetworks  = false
      enable_ula_internal_ipv6 = true
    }
    
    resource "google_compute_subnetwork" "default" {
      name = "example-subnetwork"
    
      ip_cidr_range = "10.0.0.0/16"
      region        = "us-central1"
    
      stack_type       = "IPV4_IPV6"
      ipv6_access_type = "INTERNAL" # Change to "EXTERNAL" if creating an external loadbalancer
    
      network = google_compute_network.default.id
      secondary_ip_range {
        range_name    = "services-range"
        ip_cidr_range = "192.168.0.0/24"
      }
    
      secondary_ip_range {
        range_name    = "pod-ranges"
        ip_cidr_range = "192.168.1.0/24"
      }
    }
    
    resource "google_container_cluster" "default" {
      name = "example-autopilot-cluster"
    
      location                 = "us-central1"
      enable_autopilot         = true
      enable_l4_ilb_subsetting = true
    
      network    = google_compute_network.default.id
      subnetwork = google_compute_subnetwork.default.id
    
      ip_allocation_policy {
        stack_type                    = "IPV4_IPV6"
        services_secondary_range_name = google_compute_subnetwork.default.secondary_ip_range[0].range_name
        cluster_secondary_range_name  = google_compute_subnetwork.default.secondary_ip_range[1].range_name
      }
    
      # Set `deletion_protection` to `true` will ensure that one cannot
      # accidentally delete this instance by use of Terraform.
      deletion_protection = false
    }

    이 파일은 다음 리소스를 설명합니다.

    • 내부 IPv6가 사용 설정된 VPC 네트워크 애플리케이션을 인터넷에 노출하려면 ipv6_access_typeEXTERNAL로 변경합니다. 이렇게 변경하면 다음 단계의 app.tf 파일에서 networking.gke.io/load-balancer-type 주석도 삭제해야 합니다.
    • 이중 스택 서브네트워크
    • us-central1에 있는 이중 스택 Autopilot 클러스터
  2. app.tf 파일을 검토합니다.

    cat app.tf
    

    출력은 다음과 비슷합니다.

    data "google_client_config" "default" {}
    
    provider "kubernetes" {
      host                   = "https://${google_container_cluster.default.endpoint}"
      token                  = data.google_client_config.default.access_token
      cluster_ca_certificate = base64decode(google_container_cluster.default.master_auth[0].cluster_ca_certificate)
    
      ignore_annotations = [
        "^autopilot\\.gke\\.io\\/.*",
        "^cloud\\.google\\.com\\/.*"
      ]
    }
    
    resource "kubernetes_deployment_v1" "default" {
      metadata {
        name = "example-hello-app-deployment"
      }
    
      spec {
        selector {
          match_labels = {
            app = "hello-app"
          }
        }
    
        template {
          metadata {
            labels = {
              app = "hello-app"
            }
          }
    
          spec {
            container {
              image = "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
              name  = "hello-app-container"
    
              port {
                container_port = 8080
                name           = "hello-app-svc"
              }
    
              security_context {
                allow_privilege_escalation = false
                privileged                 = false
                read_only_root_filesystem  = false
    
                capabilities {
                  add  = []
                  drop = ["NET_RAW"]
                }
              }
    
              liveness_probe {
                http_get {
                  path = "/"
                  port = "hello-app-svc"
    
                  http_header {
                    name  = "X-Custom-Header"
                    value = "Awesome"
                  }
                }
    
                initial_delay_seconds = 3
                period_seconds        = 3
              }
            }
    
            security_context {
              run_as_non_root = true
    
              seccomp_profile {
                type = "RuntimeDefault"
              }
            }
    
            # Toleration is currently required to prevent perpetual diff:
            # https://github.com/hashicorp/terraform-provider-kubernetes/pull/2380
            toleration {
              effect   = "NoSchedule"
              key      = "kubernetes.io/arch"
              operator = "Equal"
              value    = "amd64"
            }
          }
        }
      }
    }
    
    resource "kubernetes_service_v1" "default" {
      metadata {
        name = "example-hello-app-loadbalancer"
        annotations = {
          "networking.gke.io/load-balancer-type" = "Internal" # Remove to create an external loadbalancer
        }
      }
    
      spec {
        selector = {
          app = kubernetes_deployment_v1.default.spec[0].selector[0].match_labels.app
        }
    
        ip_family_policy = "RequireDualStack"
    
        port {
          port        = 80
          target_port = kubernetes_deployment_v1.default.spec[0].template[0].spec[0].container[0].port[0].name
        }
    
        type = "LoadBalancer"
      }
    
      depends_on = [time_sleep.wait_service_cleanup]
    }
    
    # Provide time for Service cleanup
    resource "time_sleep" "wait_service_cleanup" {
      depends_on = [google_container_cluster.default]
    
      destroy_duration = "180s"
    }

    이 파일은 다음 리소스를 설명합니다.

    • 샘플 컨테이너 이미지가 포함된 배포
    • LoadBalancer 유형의 서비스. 이 서비스는 포트 80에서 배포를 노출합니다. 애플리케이션을 인터넷에 노출하려면 networking.gke.io/load-balancer-type 주석을 삭제하여 외부 부하 분산기를 구성합니다.

클러스터 만들기 및 애플리케이션 배포

  1. Cloud Shell에서 다음 명령어를 실행하여 Terraform을 사용할 수 있는지 확인합니다.

    terraform
    

    출력은 다음과 비슷하게 표시됩니다.

    Usage: terraform [global options] <subcommand> [args]
    
    The available commands for execution are listed below.
    The primary workflow commands are given first, followed by
    less common or more advanced commands.
    
    Main commands:
      init          Prepare your working directory for other commands
      validate      Check whether the configuration is valid
      plan          Show changes required by the current configuration
      apply         Create or update infrastructure
      destroy       Destroy previously-created infrastructure
    
  2. Terraform을 초기화합니다.

    terraform init
    
  3. Terraform 구성을 계획합니다.

    terraform plan
    
  4. Terraform 구성 적용

    terraform apply
    

    메시지가 표시되면 yes를 입력하여 작업을 확인합니다. 이 명령어가 완료되는 데 몇 분이 소요될 수 있습니다. 출력은 다음과 비슷합니다.

    Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
    

클러스터가 작동하는지 확인

클러스터가 올바르게 실행 중인지 확인하려면 다음을 수행합니다.

  1. Google Cloud 콘솔에서 워크로드 페이지로 이동합니다.

    워크로드로 이동

  2. example-hello-app-deployment 워크로드를 클릭합니다. 포드 세부정보 페이지가 표시됩니다. 이 페이지에는 주석, 포드에서 실행되는 컨테이너, 포드를 노출하는 서비스, 측정항목(예: CPU, 메모리, 디스크 사용량)과 같은 포드에 대한 정보가 표시됩니다.

  3. Google Cloud 콘솔에서 서비스 및 인그레스 페이지로 이동합니다.

    서비스 및 인그레스로 이동

  4. example-hello-app-loadbalancer LoadBalancer 서비스를 클릭합니다. 서비스 세부정보 페이지가 표시됩니다. 이 페이지에는 서비스와 연결된 포드 및 서비스에서 사용하는 포트와 같은 서비스에 대한 정보가 표시됩니다.

  5. 외부 엔드포인트 섹션에서 IPv4 링크 또는 IPv6 링크를 클릭하여 브라우저에서 서비스를 봅니다. 출력은 다음과 비슷합니다.

    Hello, world!
    Version: 2.0.0
    Hostname: example-hello-app-deployment-5df979c4fb-kdwgr
    

삭제

이 페이지에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 다음 단계를 수행합니다.

이 페이지에서 사용한 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 다음 단계를 수행합니다.

Cloud Shell에서 다음 명령어를 실행하여 Terraform 리소스를 삭제합니다.

terraform destroy --auto-approve

The network resource 'projects/PROJECT_ID/global/networks/example-network' is already being used by 'projects/PROJECT_ID/global/firewalls/example-network-yqjlfql57iydmsuzd4ot6n5v'와 유사한 오류 메시지가 표시되면 다음을 수행합니다.

  1. 방화벽 규칙을 삭제합니다.

    gcloud compute firewall-rules list --filter="NETWORK:example-network" --format="table[no-heading](name)" | xargs gcloud --quiet compute firewall-rules delete
    
  2. Terraform 명령어를 다시 실행합니다.

    terraform destroy --auto-approve
    

다음 단계

  • Google Cloud Provider 문서에서 google_container_clustergoogle_container_node_pool 리소스를 살펴봅니다. 이 페이지에서는 Google이 Terraform에서 지원하는 GKE 클러스터 및 노드 풀 구성의 인수와 속성을 설명합니다.
  • Terraform GKE 모듈 GitHub 저장소의 독자적인 구성 샘플을 참조하세요.