[GCC/Terraform] 서브넷에 VM 인스턴스를 만들고Firewall 라이센스 IP에서만 SSH 연결

TL;DR

  • 여기 창고 참고하세요.
    -> https://github.com/nekoshita/gcp-vm-instance-in-subnet-example
  • 이런 사람을 향해

  • GCP의 VPC,subnet,Firewall
  • 을 잘 몰라요.
  • GCP로 벤치 서버 구축
  • AWS와 완전히 다르기 때문에 잘 모르겠다
  • terraform으로 GCP를 터치하고자 합니다
  • 해설


    네트워크 및 서브넷


    먼저 새 VPC 네트워크를 정의합니다.
    (VPC 네트워크 정보: https://cloud.google.com/vpc/docs/vpc?hl=ja
    GCP 프로젝트를 만들면 기본 VPC 네트워크가 만들어지지만 공개 설정이기 때문에 사용하지 않습니다.
    VPC 네트워크는 전 세계 자원이기 때문에 구역과 구역을 지정하지 않습니다.
    resource "google_compute_network" "my_network" {
      name                    = "my-network"
      # リージョンごとにサブネットを自動で作成してくれます。今回は使わないのでfalseにします。
      auto_create_subnetworks = false
    }
    
    그런 다음 VPC 네트워크에서 서브넷을 정의합니다.
    서브넷은 영역 리소스이며 각 서브넷은 IP 주소의 범위를 지정합니다.
    GCP에서 서브넷을 생성하면 기본 게이트웨이 및 경로가 자동으로 설정됩니다.
    기본 게이트웨이 정보 -> https://cloud.google.com/vpc/docs/vpc?hl=ja#affiliated_resources
    노선 정보 ->https://cloud.google.com/vpc/docs/routes?hl=ja#types_of_routes
    resource "google_compute_subnetwork" "my_subnetwork" {
      name   = "my-subnetwork"
      region = "asia-northeast1"
    
      # サブネットで使用したい内部IPアドレスの範囲を指定する
      ip_cidr_range = "10.0.0.0/16"
      network       = google_compute_network.my_network.self_link
    
      # CloudLoggingにFlowLogログを出力したい場合は設定する
      log_config {
        metadata = "INCLUDE_ALL_METADATA"
      }
    }
    

    서브넷에서 VM 인스턴스 만들기


    Google은 VM에 인스턴스를 부여하는 서비스 account을 만드는 것을 권장하기 때문에 서비스 account도 정의합니다.
    resource "google_service_account" "my_service_account_for_bastion" {
      account_id   = "my-service-account-for-bastion"
      display_name = "My Service Account For Bastion"
    }
    
    resource "google_compute_instance" "bastion" {
      # 好きな名前、マシンタイプ、ゾーンに作成してください
      name         = "bastion"
      machine_type = "f1-micro"
      zone         = "asia-northeast1-a"
    
      # Firewallでタグごとにルールを設定したいので、VMインスタンスにタグを設定しておく
      tags = ["bastion-tag"]
    
      # すきなディスクを選んでください
      boot_disk {
        initialize_params {
          image = "debian-cloud/debian-10"
        }
      }
    
      network_interface {
        # 自分で定義したsubnetwork内にインスタンスを起動する
        network    = google_compute_network.my_network.name
        subnetwork = google_compute_subnetwork.my_subnetwork.name
        # 外部IPアドレスを割り振る方法は次の2種類ある。静的外部IPアドレス、エフェメラル外部IPアドレス
        # 今回はエフェメラル外部IPアドレスを使うので、access_configの中は何も指定しない
        access_config {}
      }
    
      service_account {
        email  = google_service_account.my_service_account_for_bastion.email
        scopes = ["cloud-platform"]
      }
    
      scheduling {
        # 料金を抑えるためにプリエンプティブルにしておく
        preemptible = true
        # プリエンプティブルの場合は下のオプションが必須
        automatic_restart = false
      }
    }
    

    기본 Firewall 규칙


    GCP의 모든 VPC 네트워크에는 두 개의 Firewall 규칙이 있습니다.
  • 대부분의 다운타임 허용
  • 모든 상행 업무 거부
  • (세부내용->https://cloud.google.com/vpc/docs/vpc?hl=ja#affiliated_resources
    이 기본 규칙은 콘솔에 표시되지 않습니다.따라서 편집할 수도 없습니다.
    GCP에서는 서브넷을 만들면 기본 게이트웨이와 라우팅이 자동으로 설정되며, 방금 만든 VM 인스턴스에 외부 IP 주소가 할당되어 있어 SSH 연결은 가능하지만 아직 할 수 없습니다.
    위에서 설명한 대로 기본 Firewall 규칙은 VM 인스턴스에 대한 상위 비즈니스를 거부합니다.
    따라서 VM 인스턴스에 SSH 연결을 할 수 있도록 Firewall 규칙을 재설정합니다.

    Firewall 접속 네트워크 구성


    GCP는 VPC 네트워크 단위로 Firewall을 설정합니다.
    resource "google_compute_firewall" "my_network" {
      name    = "my-network-firewall"
      network = google_compute_network.my_network.name
    
      # 今回は内向きを選択する
      direction = "INGRESS"
    
      # 通信を許可するprotocolとportを指定する
      allow {
        protocol = "tcp"
        ports    = ["22"]
      }
    
      # 対象のVMインスタンスのタグを指定する
      target_tags = ["bastion-tag"]
      
      # VMインスタンスへのSSH接続元IPアドレス範囲を指定する
      # 今使ってるグローバルIPアドレスだけを許可したい場合は
      # $ curl httpbin.org/ip
      # で取得したIPアドレスを指定する
      # (例: 123.123.123.123/32)
      source_ranges = ["0.0.0.0/0"]
    
      # CloudLoggingにFlowLogログを出力したい場合は設定する
      log_config {
        metadata = "INCLUDE_ALL_METADATA"
      }
    }
    

    SSH 연결 사용자에게 Role 부여


    SSH 연결에 필요한 Role은 다음과 같습니다.
    resource "google_project_iam_binding" "access_user" {
      role = google_project_iam_custom_role.my_custom_role.id
    
      members = [
        "user:許可したいGoogleユーザーのメールアドレス",
      ]
    }
    
    resource "google_project_iam_custom_role" "my_custom_role" {
      role_id = "MyCustomRole"
      title   = "My Custom Role"
    
      permissions = [
        "compute.projects.get",
        "compute.instances.get",
        "compute.instances.setMetadata",
        "iam.serviceAccounts.actAs",
      ]
    }
    
    따라서 이번에 제작된 VPC 네트워크 내 외부 IP 주소가 있는 VM의 실례와 SSH를 연결하려면 다음과 같은 두 가지 방법이 필요하다.
  • SSH 연결을 위한 Role을 보유한 Google 사용자
  • Firewall 규칙에서 허가된 IP 주소 범위에서 접근
  • 실제 제작 리소스


    차리다


  • 설치Terraform v0.14.5
  • https://releases.hashicorp.com/terraform/
  • Google Cloud Plaatform 만들기 프로젝트
  • https://cloud.google.com/resource-manager/docs/creating-managing-projects
  • GCP Storage Bucket 생성
  • https://cloud.google.com/storage/docs/creating-buckets

  • 설치gcloud CLI
  • https://cloud.google.com/sdk/gcloud
  • 만들어서 SSH에 연결해보도록 하겠습니다.


    #-------------------
    # リポジトリをクローンする
    #-------------------
    $ git clone https://github.com/nekoshita/gcp-vm-instance-in-subnet-example
    $ cd gcp-vm-instance-in-subnet-example
    
    #-------------------
    # グローバルIPアドレスの取得
    #-------------------
    $ curl httpbin.org/ip
    # でグローバルIPアドレスを取得し(たとえば、123.123.123.123)、環境変数にセットする
    $ export GLOBAL_IP_ADDRESS="123.123.123.123"
    
    #-------------------
    # terraform applyしてリソースを作成する
    #-------------------
    $ export GCP_PROJECT_ID="your-gcp-project-id"
    $ export GCS_BUCKET_NAME="your-gcs-bucket-name"
    $ export USER_MAIL="[email protected]"
    $ bin/apply $GCP_PROJECT_ID $GCS_BUCKET_NAME $USER_MAIL $GLOBAL_IP_ADDRESS
    
    #-------------------
    # SSH接続する
    #-------------------
    $ export ZONE="asia-northeast1-a"
    $ export VM_INSTANCE_NAME="bastion"
    # GCPのprojectを作成したgoogleアカウントでログインする(すでにログインしてる場合は不要)
    $ gcloud auth login
    $ gcloud beta compute ssh --zone $ZONE $VM_INSTANCE_NAME --project $GCP_PROJECT_ID
    # パスフレーズの入力を求められるので、適当なパスフレーズを入力してあげてください
    
    #-------------------
    # 最後にリソースの削除をお忘れなく!
    #-------------------
    $ export GCP_PROJECT_ID="your-gcp-project-id"
    $ export GCS_BUCKET_NAME="your-gcs-bucket-name"
    $ export USER_MAIL="[email protected]"
    $ bin/destroy $GCP_PROJECT_ID $GCS_BUCKET_NAME $USER_MAIL $GLOBAL_IP_ADDRESS
    

    로그 보기


    서브넷 로그 보기


    GCP 콘솔VPC Network을 열고 만든 서브넷을 선택합니다.
    "View flow logs"라는 링크가 있는데, 이 링크를 클릭하면 Cloud Logging 페이지가 열립니다.
    VM Instan에 연결된 후 CloudLogging의 검색 필터에 "자신의 글로벌 IP 주소"를 추가하면 직접 액세스한 로그가 표시됩니다.

    Firewall 규칙 로그 보기


    GCP 콘솔Firewall을 열고 작성된 Firewall 규칙을 선택합니다.
    "view in Logs Explorer"라는 링크가 있는데, 클릭하면 Cloud Logging 페이지가 열립니다.

    최후


    공식 문서를 바탕으로 이해한 줄 알았는데 제 인식이 틀리면 제 잘못을 지적해 주시면 기쁩니다!

    좋은 웹페이지 즐겨찾기