๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ๊ตฌ์„ฑ


๊ฐ€์ƒ ๋จธ์‹ (VM) ๋ฐ ๋ฒ ์–ด ๋ฉ”ํƒˆ ์ธ์Šคํ„ด์Šค์— ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค์˜ ๊ณ ์ • IP ์ฃผ์†Œ๋ฅผ ๋ณ€๊ฒฝ, ๋‚˜์—ด, ํ•ด์ œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝํ•˜๋ ค๋ฉด ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ์˜ˆ์•ฝ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

์™ธ๋ถ€ IP ์ฃผ์†Œ๋Š” ๊ณ ์ • ๋˜๋Š” ์ž„์‹œ ์ฃผ์†Œ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค์— ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋‹ค์Œ ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

  1. ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ƒˆ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ์ž„์‹œ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์Šน๊ฒฉํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  2. ์˜ˆ์•ฝ๋œ IP ์ฃผ์†Œ๋ฅผ ๊ธฐ์กด ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•˜๊ฑฐ๋‚˜ ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๋ถ€ Compute Engine ๋„คํŠธ์›Œํฌ์— ๊ณ ์ • IP ์ฃผ์†Œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ๋Œ€์‹  ๊ณ ์ • ๋‚ด๋ถ€ IP ์ฃผ์†Œ ์˜ˆ์•ฝ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ์˜ˆ์•ฝ ๋˜๋Š” ์ „์—ญ ์™ธ๋ถ€ IP ์ฃผ์†Œ ์ƒ์„ฑ์— ๊ด€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ์˜ˆ์•ฝ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

  • IP ์ฃผ์†Œ์— ๋Œ€ํ•ด ์•Œ์•„๋ด…๋‹ˆ๋‹ค.
  • ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ์˜ ํ• ๋‹น๋Ÿ‰ ๋ฐ ํ•œ๋„์— ๋Œ€ํ•ด ์ฝ์–ด๋ด…๋‹ˆ๋‹ค.
  • ์™ธ๋ถ€ IP ์ฃผ์†Œ ๊ฐ€๊ฒฉ ์ฑ…์ •์— ๋Œ€ํ•ด ์ฝ์–ด๋ด…๋‹ˆ๋‹ค.
  • ์•„์ง ์ธ์ฆ์„ ์„ค์ •ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ์€ Google Cloud ์„œ๋น„์Šค ๋ฐ API์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•ด ID๋ฅผ ํ™•์ธํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์ฝ”๋“œ ๋˜๋Š” ์ƒ˜ํ”Œ์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋‹ค์Œ ์˜ต์…˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜์—ฌ Compute Engine์— ์ธ์ฆํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

    Select the tab for how you plan to use the samples on this page:

    Console

    When you use the Google Cloud console to access Google Cloud services and APIs, you don't need to set up authentication.

    gcloud

    1. After installing the Google Cloud CLI, initialize it by running the following command:

      gcloud init

      If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

    2. Set a default region and zone.
    3. Terraform

      ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์ด ํŽ˜์ด์ง€์˜ Terraform ์ƒ˜ํ”Œ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด gcloud CLI๋ฅผ ์„ค์น˜ ๋ฐ ์ดˆ๊ธฐํ™”ํ•œ ๋‹ค์Œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์„ค์ •ํ•˜์„ธ์š”.

      1. Install the Google Cloud CLI.

      2. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

      3. To initialize the gcloud CLI, run the following command:

        gcloud init
      4. If you're using a local shell, then create local authentication credentials for your user account:

        gcloud auth application-default login

        You don't need to do this if you're using Cloud Shell.

        If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

      5. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋‹ค์Œ์„ ์ฐธ์กฐํ•˜์„ธ์š”: Set up authentication for a local development environment.

      REST

      ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์ด ํŽ˜์ด์ง€์˜ REST API ์ƒ˜ํ”Œ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด gcloud CLI์— ์ œ๊ณตํ•œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

        After installing the Google Cloud CLI, initialize it by running the following command:

        gcloud init

        If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

      ์ž์„ธํ•œ ๋‚ด์šฉ์€ Google Cloud ์ธ์ฆ ๋ฌธ์„œ์˜ REST ์‚ฌ์šฉ์„ ์œ„ํ•œ ์ธ์ฆ์„ ์ฐธ์กฐํ•˜์„ธ์š”.

ํ•„์š”ํ•œ ์—ญํ• 

๊ณ ์ • IP ์ฃผ์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ถŒํ•œ์„ ์–ป์œผ๋ ค๋ฉด ๊ด€๋ฆฌ์ž์—๊ฒŒ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ๋‹ค์Œ IAM ์—ญํ• ์„ ๋ถ€์—ฌํ•ด ๋‹ฌ๋ผ๊ณ  ์š”์ฒญํ•˜์„ธ์š”.

์—ญํ•  ๋ถ€์—ฌ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ํ”„๋กœ์ ํŠธ, ํด๋”, ์กฐ์ง์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ด€๋ฆฌ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

์ด๋Ÿฌํ•œ ์‚ฌ์ „ ์ •์˜๋œ ์—ญํ• ์—๋Š” ๊ณ ์ • IP ์ฃผ์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ถŒํ•œ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ์ •ํ™•ํ•œ ๊ถŒํ•œ์„ ๋ณด๋ ค๋ฉด ํ•„์ˆ˜ ๊ถŒํ•œ ์„น์…˜์„ ํŽผ์น˜์„ธ์š”.

ํ•„์ˆ˜ ๊ถŒํ•œ

๊ณ ์ • IP ์ฃผ์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋ ค๋ฉด ๋‹ค์Œ ๊ถŒํ•œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ compute.instances.update ๊ถŒํ•œ
  • ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ compute.instances.updateNetworkInterface ๊ถŒํ•œ
  • ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ compute.instances.addAccessConfig ๊ถŒํ•œ
  • ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ compute.instances.deleteAccessConfig ๊ถŒํ•œ
  • ๋„คํŠธ์›Œํฌ์— ๋Œ€ํ•œ compute.networks.list
  • ์„œ๋ธŒ๋„ท์— ๋Œ€ํ•œ compute.subnetworks.use ๊ถŒํ•œ
  • ์„œ๋ธŒ๋„ท์— ๋Œ€ํ•œ compute.subnetworks.list ๊ถŒํ•œ
  • ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ:
    • ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ compute.instances.create ๊ถŒํ•œ
    • ์ปค์Šคํ…€ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ VM ๋งŒ๋“ค๊ธฐ: ์ด๋ฏธ์ง€์— ๋Œ€ํ•œ compute.images.useReadOnly ๊ถŒํ•œ
    • ์Šค๋ƒ…์ƒท์„ ์‚ฌ์šฉํ•˜์—ฌ VM ๋งŒ๋“ค๊ธฐ: ์Šค๋ƒ…์ƒท์— ๋Œ€ํ•œ compute.snapshots.useReadOnly ๊ถŒํ•œ
    • ์ธ์Šคํ„ด์Šค ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜์—ฌ VM ๋งŒ๋“ค๊ธฐ: ์ธ์Šคํ„ด์Šค ํ…œํ”Œ๋ฆฟ์— ๋Œ€ํ•œ compute.instanceTemplates.useReadOnly ๊ถŒํ•œ
    • VM์— ๊ธฐ์กด ๋„คํŠธ์›Œํฌ ํ• ๋‹น: ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ compute.networks.use ๊ถŒํ•œ
    • VM์˜ ๊ณ ์ • IP ์ฃผ์†Œ ์ง€์ •: ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ compute.addresses.use ๊ถŒํ•œ
    • ๊ธฐ์กด ๋„คํŠธ์›Œํฌ ์‚ฌ์šฉ ์‹œ VM์— ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ• ๋‹น: ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ compute.networks.useExternalIp ๊ถŒํ•œ
    • VM์˜ ์„œ๋ธŒ๋„ท ์ง€์ •: ํ”„๋กœ์ ํŠธ ๋˜๋Š” ์„ ํƒํ•œ ์„œ๋ธŒ๋„ท์— ๋Œ€ํ•œ compute.subnetworks.use ๊ถŒํ•œ
    • VPC ๋„คํŠธ์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ VM์— ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ• ๋‹น: ํ”„๋กœ์ ํŠธ ๋˜๋Š” ์„ ํƒํ•œ ์„œ๋ธŒ๋„ท์— ๋Œ€ํ•œ compute.subnetworks.useExternalIp ๊ถŒํ•œ
    • VM์— VM ์ธ์Šคํ„ด์Šค ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์„ค์ •: ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ compute.instances.setMetadata ๊ถŒํ•œ
    • VM์— ํƒœ๊ทธ ์„ค์ •: VM์— ๋Œ€ํ•œ compute.instances.setTags ๊ถŒํ•œ
    • VM์— ๋ผ๋ฒจ ์„ค์ •: VM์— ๋Œ€ํ•œ compute.instances.setLabels ๊ถŒํ•œ
    • VM์— ์‚ฌ์šฉํ•  ์„œ๋น„์Šค ๊ณ„์ • ์„ค์ •: VM์— ๋Œ€ํ•œ compute.instances.setServiceAccount ๊ถŒํ•œ
    • VM์˜ ์ƒˆ ๋””์Šคํฌ ๋งŒ๋“ค๊ธฐ: ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ compute.disks.create ๊ถŒํ•œ
    • ๊ธฐ์กด ๋””์Šคํฌ๋ฅผ ์ฝ๊ธฐ ์ „์šฉ ๋˜๋Š” ์ฝ๊ธฐ-์“ฐ๊ธฐ ๋ชจ๋“œ๋กœ ์—ฐ๊ฒฐ: ๋””์Šคํฌ์— ๋Œ€ํ•œ compute.disks.use ๊ถŒํ•œ
    • ๊ธฐ์กด ๋””์Šคํฌ๋ฅผ ์ฝ๊ธฐ ์ „์šฉ ๋ชจ๋“œ๋กœ ์—ฐ๊ฒฐ: ๋””์Šคํฌ์— ๋Œ€ํ•œ compute.disks.useReadOnly ๊ถŒํ•œ

์ปค์Šคํ…€ ์—ญํ• ์ด๋‚˜ ๋‹ค๋ฅธ ์‚ฌ์ „ ์ •์˜๋œ ์—ญํ• ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๊ถŒํ•œ์„ ๋ถ€์—ฌ๋ฐ›์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ œํ•œ์‚ฌํ•ญ

  • ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ๋ฆฌ์†Œ์Šค๋งŒ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • IP ์ฃผ์†Œ๊ฐ€ ๋ฆฌ์†Œ์Šค์— ํ• ๋‹น๋˜๋ฉด ํ•ด๋‹น ์ฃผ์†Œ๊ฐ€ ๊ณ ์ • ์ฃผ์†Œ์ธ์ง€ ์ž„์‹œ ์ฃผ์†Œ์ธ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. IP ์ฃผ์†Œ๋ฅผ ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์— ์˜ˆ์•ฝ๋œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ๋ชฉ๋ก๊ณผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ์˜ ๋ชฉ๋ก์„ ํ™•์ธํ•˜๋ ค๋ฉด gcloud compute addresses list ํ•˜์œ„ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ VM์—๋Š” ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐ ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” ์Šคํƒ ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ค์Œ IP ์ฃผ์†Œ๊ฐ€ ํ• ๋‹น๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • IPv4 ์ „์šฉ ์ธํ„ฐํŽ˜์ด์Šค:
      • ๋‚ด๋ถ€ IPv4 ์ฃผ์†Œ(ํ•„์ˆ˜)
      • ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ(์„ ํƒ์‚ฌํ•ญ)
    • ์ด์ค‘ ์Šคํƒ(IPv4 ๋ฐ IPv6) ์ธํ„ฐํŽ˜์ด์Šค:
      • ๋‚ด๋ถ€ IPv4 ์ฃผ์†Œ(ํ•„์ˆ˜)
      • ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ(์„ ํƒ์‚ฌํ•ญ)
      • /96 IPv6 ์ฃผ์†Œ ๋ฒ”์œ„(๋‚ด๋ถ€ ๋˜๋Š” ์™ธ๋ถ€ ์ค‘ ํ•˜๋‚˜)(ํ•„์ˆ˜)
    • IPv6 ์ „์šฉ ์ธํ„ฐํŽ˜์ด์Šค(ํ”„๋ฆฌ๋ทฐ):
      • /96 IPv6 ์ฃผ์†Œ ๋ฒ”์œ„(๋‚ด๋ถ€ ๋˜๋Š” ์™ธ๋ถ€ ์ค‘ ํ•˜๋‚˜)(ํ•„์ˆ˜)
  • IPv6 ์ „์šฉ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ๋Š” VM์˜ ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋Š” ํ• ๋‹น ํ•ด์ œํ•˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•ด๋„ ์ฃผ์†Œ๊ฐ€ ๊ณ„์† ์˜ˆ์•ฝ๋˜๋„๋ก ๋ฆฌ์†Œ์Šค์˜ ์ž„์‹œ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋กœ ์Šน๊ฒฉํ•  ์ˆ˜๋Š” ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ณ ์ • IP ์ฃผ์†Œ ์ด๋ฆ„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ : ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์—ฌ๋Ÿฌ ์ „๋‹ฌ ๊ทœ์น™์œผ๋กœ๋ถ€ํ„ฐ ํŠธ๋ž˜ํ”ฝ์„ ์ˆ˜์‹ ํ•˜๋ฉฐ ์ด ์ „๋‹ฌ ๊ทœ์น™์€ ๋‹ค๋ฅธ ์™ธ๋ถ€ IP ์ฃผ์†Œ์—๋„ ์ ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์™ธ๋ถ€ IP ์ฃผ์†Œ์—์„œ ์ด๋Ÿฌํ•œ ์ „๋‹ฌ ๊ทœ์น™์„ ํ†ตํ•ด ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ ํ•˜๋‚˜์™€ ์™ธ๋ถ€ /96 IPv6 ์ฃผ์†Œ ๋ฒ”์œ„ ํ•˜๋‚˜๋งŒ ํ• ๋‹น๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถ€ํ•˜ ๋ถ„์‚ฐ ๋ฐ ์ „๋‹ฌ ๊ทœ์น™์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ถ€ํ•˜ ๋ถ„์‚ฐ ๋ฌธ์„œ๋ฅผ ์ฝ์–ด๋ณด์„ธ์š”.

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ๋ณด๊ธฐ

ํ”„๋กœ์ ํŠธ์— ์˜ˆ์•ฝํ•œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ฝ˜์†”

  1. Google Cloud ์ฝ˜์†”์—์„œ IP ์ฃผ์†Œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    IP ์ฃผ์†Œ๋กœ ์ด๋™

  2. ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

gcloud

gcloud compute addresses list ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๋ชจ๋“  IP ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute addresses list
  • ๋ชจ๋“  ์ „์—ญ IP ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute addresses list --global
  • ํŠน์ • ๋ฆฌ์ „์˜ ๋ชจ๋“  ๋ฆฌ์ „ IP ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute addresses list \
        --regions=REGION
    

    REGION์„ ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•  ๋ฆฌ์ „์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค. ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•œ ๋ฆฌ์ „ ์ด๋ฆ„์„ ์ง€์ •ํ•˜์—ฌ ์—ฌ๋Ÿฌ ๋ฆฌ์ „์˜ ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    gcloud compute addresses list \
        --regions=REGION1,REGION2,..REGION_n_
    

API

  • ๋ฆฌ์ „ IPv4 ๋˜๋Š” IPv6 ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•˜๋ ค๋ฉด addresses.list ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/regions/REGION/addresses
    

    ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • PROJECT_ID: ์ด ์š”์ฒญ์˜ ํ”„๋กœ์ ํŠธ ID
    • REGION: ์š”์ฒญ์˜ ๋ฆฌ์ „ ์ด๋ฆ„
  • ๋ชจ๋“  ๋ฆฌ์ „์˜ ๋ชจ๋“  ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•˜๋ ค๋ฉด addresses.aggregatedList ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/aggregated/addresses
    
  • ์ „์—ญ IPv4 ๋˜๋Š” IPv6 ์ฃผ์†Œ๋ฅผ ๋‚˜์—ดํ•˜๋ ค๋ฉด globalAddresses.list ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

    GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/global/addresses
    

    ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    PROJECT_ID: ์ด ์š”์ฒญ์˜ ํ”„๋กœ์ ํŠธ ID

Go

import (
	"context"
	"fmt"
	"io"

	compute "cloud.google.com/go/compute/apiv1"
	"google.golang.org/api/iterator"

	"cloud.google.com/go/compute/apiv1/computepb"
)

// listRegionalExternal retrieves list external IP addresses in Google Cloud Platform region.
func listRegionalExternal(w io.Writer, projectID, region string) ([]*computepb.Address, error) {
	// projectID := "your_project_id"
	// region := "europe-west3"

	ctx := context.Background()
	// Create the service client.
	addressesClient, err := compute.NewAddressesRESTClient(ctx)
	if err != nil {
		return nil, err
	}
	defer addressesClient.Close()

	// Build the request.
	req := &computepb.ListAddressesRequest{
		Project: projectID,
		Region:  region,
	}

	// List the addresses.
	it := addressesClient.List(ctx, req)

	// Iterate over the results.
	var addresses []*computepb.Address
	for {
		address, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}
		addresses = append(addresses, address)
	}

	// Print the addresses.
	fmt.Fprint(w, "Fetched addresses: \n")
	for _, address := range addresses {
		fmt.Fprintf(w, "%s\n", *address.Name)
	}

	return addresses, nil
}

// listGlobalExternal retrieves list external global IP addresses in Google Cloud Platform.
func listGlobalExternal(w io.Writer, projectID string) ([]*computepb.Address, error) {
	// projectID := "your_project_id"

	ctx := context.Background()
	// Create the service client.
	addressesClient, err := compute.NewGlobalAddressesRESTClient(ctx)
	if err != nil {
		return nil, err
	}
	defer addressesClient.Close()

	// Build the request.
	req := &computepb.ListGlobalAddressesRequest{
		Project: projectID,
	}

	// List the addresses.
	it := addressesClient.List(ctx, req)

	// Iterate over the results.
	var addresses []*computepb.Address
	for {
		address, err := it.Next()
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, err
		}
		addresses = append(addresses, address)
	}

	// Print the addresses.
	fmt.Fprint(w, "Fetched addresses: \n")
	for _, address := range addresses {
		fmt.Fprintf(w, "%s\n", *address.Name)
	}

	return addresses, nil
}

์ž๋ฐ”


import com.google.cloud.compute.v1.Address;
import com.google.cloud.compute.v1.AddressesClient;
import com.google.cloud.compute.v1.GlobalAddressesClient;
import com.google.cloud.compute.v1.ListAddressesRequest;
import com.google.cloud.compute.v1.ListGlobalAddressesRequest;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;

public class ListStaticExternalIp {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Region where the VM and IP is located.
    String region = "your-region-id";

    listStaticExternalIp(projectId, region);
  }

  // Lists all static external IP addresses, either regional or global.
  public static List<Address> listStaticExternalIp(String projectId, String region)
          throws IOException {
    // Use regional client if a region is specified
    if (region != null) {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      try (AddressesClient client = AddressesClient.create()) {
        ListAddressesRequest request = ListAddressesRequest.newBuilder()
                .setProject(projectId)
                .setRegion(region)
                .build();

        return Lists.newArrayList(client.list(request).iterateAll());
      }
    } else {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      try (GlobalAddressesClient client = GlobalAddressesClient.create()) {
        ListGlobalAddressesRequest request = ListGlobalAddressesRequest.newBuilder()
                .setProject(projectId)
                .build();

        return Lists.newArrayList(client.list(request).iterateAll());
      }
    }
  }
}

Python

from typing import List, Optional

from google.cloud.compute_v1.services.addresses.client import AddressesClient
from google.cloud.compute_v1.services.global_addresses import GlobalAddressesClient
from google.cloud.compute_v1.types import Address


def list_static_ip_addresses(
    project_id: str, region: Optional[str] = None
) -> List[Address]:
    """
    Lists all static external IP addresses, either regional or global.

    Args:
    project_id (str): project ID.
    region (Optional[str]): The region of the IP addresses if regional. None if global.

    Returns:
    List[Address]: A list of Address objects containing details about the requested IPs.
    """
    if region:
        # Use regional client if a region is specified
        client = AddressesClient()
        addresses_iterator = client.list(project=project_id, region=region)
    else:
        # Use global client if no region is specified
        client = GlobalAddressesClient()
        addresses_iterator = client.list(project=project_id)

    return list(addresses_iterator)  # Convert the iterator to a list to return

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ๊ตฌ์„ฑ

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ธ์Šคํ„ด์Šค์˜ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธ์Šคํ„ด์Šค ๋งŒ๋“ค๊ธฐ

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝํ•œ ํ›„ ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ˜์†”

  1. Google Cloud ์ฝ˜์†”์—์„œ ์ธ์Šคํ„ด์Šค ๋งŒ๋“ค๊ธฐ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    ์ธ์Šคํ„ด์Šค ๋งŒ๋“ค๊ธฐ๋กœ ์ด๋™

  2. ์ธ์Šคํ„ด์Šค์— ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋‹ค์Œ ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

    1. ํƒ์ƒ‰ ๋ฉ”๋‰ด์—์„œ ๋„คํŠธ์›Œํ‚น์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    2. ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค ์„น์…˜์—์„œ ๋‹ค์Œ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ ์ธ์Šคํ„ด์Šค์— ์›ํ•˜๋Š” ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

      • ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค ์ถ”๊ฐ€๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋„คํŠธ์›Œํฌ ๋ชฉ๋ก์—์„œ ๋„คํŠธ์›Œํฌ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

      • ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ญ์ œํ•˜๋ ค๋ฉด ์‚ญ์ œ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    3. ๋‹ค์Œ ์˜ต์…˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

      • ๊ณ ์ • ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

        1. ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํŽผ์นฉ๋‹ˆ๋‹ค.
        2. ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ ๋ชฉ๋ก์—์„œ IP ์ฃผ์†Œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
      • ๊ณ ์ • ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

        1. ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ ๋ฒ”์œ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์„œ๋ธŒ๋„ท์ด ํฌํ•จ๋œ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํŽผ์นฉ๋‹ˆ๋‹ค.
        2. ์„œ๋ธŒ๋„คํŠธ์›Œํฌ ๋ชฉ๋ก์—์„œ ํ•ด๋‹น ์„œ๋ธŒ๋„ท์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
        3. IP ์Šคํƒ ์œ ํ˜•์—์„œ IPv4 ๋ฐ IPv6(์ด์ค‘ ์Šคํƒ) ๋˜๋Š” IPv6(๋‹จ์ผ ์Šคํƒ)์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
        4. ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ ๋ชฉ๋ก์—์„œ ์ƒˆ๋กœ ์˜ˆ์•ฝ๋œ ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ๊ณ ์ • ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ ์˜ˆ์•ฝ์„ ์„ ํƒํ•˜๊ณ  ์ƒˆ ๊ณ ์ • ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค.
        5. ๋„คํŠธ์›Œํฌ ์„œ๋น„์Šค ๋“ฑ๊ธ‰์—์„œ ํ”„๋ฆฌ๋ฏธ์—„์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    4. ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค ์ˆ˜์ •์„ ์™„๋ฃŒํ•˜๋ ค๋ฉด ์™„๋ฃŒ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ณ„์† ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

gcloud

์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฏธ ์˜ˆ์•ฝํ•œ ๊ณ ์ • ๋ฆฌ์ „ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ณ ์ • ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute instances create INSTANCE_NAME \
        --zone=ZONE \
        --address=IPV4_ADDRESS
    
  • ๊ณ ์ • ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute instances create INSTANCE_NAME \
        --zone=ZONE \
        --subnet=SUBNET \
        --stack-type=STACK_TYPE \
        --external-ipv6-address=IPV6_ADDRESS \
        --external-ipv6-prefix-length=96 \
        --ipv6-network-tier=PREMIUM
    

    ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • INSTANCE_NAME: ์ปดํ“จํŒ… ์ธ์Šคํ„ด์Šค์˜ ์ด๋ฆ„
    • ZONE: ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์˜์—ญ
    • IPV4_ADDRESS: ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  IPv4 ์ฃผ์†Œ. ์ฃผ์†Œ ์ด๋ฆ„์ด ์•„๋‹Œ ์˜ˆ์•ฝ๋œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • SUBNET: ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๊ฐ€ ํฌํ•จ๋œ ์„œ๋ธŒ๋„ท
    • STACK_TYPE: ์ธ์Šคํ„ด์Šค์˜ ์Šคํƒ ์œ ํ˜•, IPV4_IPV6(์ด์ค‘ ์Šคํƒ) ๋˜๋Š” IPV6_ONLY
    • IPV6_ADDRESS: ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  IPv6 ์ฃผ์†Œ. ์ฃผ์†Œ ์ด๋ฆ„์ด ์•„๋‹Œ ์˜ˆ์•ฝ๋œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Terraform

google_compute_instance ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

resource "google_compute_instance" "default" {
  name         = "dns-proxy-nfs"
  machine_type = "n1-standard-1"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "ubuntu-1404-trusty-v20160627"
    }
  }

  network_interface {
    network = "default"
    access_config {
      nat_ip = google_compute_address.default.address
    }
  }
}

REST

  • ์ƒˆ ์ปดํ“จํŒ… ์ธ์Šคํ„ด์Šค์— ๊ณ ์ • ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋‹ค์Œ ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

    ์ƒˆ ์ธ์Šคํ„ด์Šค ๋งŒ๋“ค๊ธฐ ์š”์ฒญ์—์„œ networkInterfaces[].accessConfigs[].natIP ์†์„ฑ๊ณผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    {
      "name": "INSTANCE_NAME",
      "machineType": "zones/ZONE/machineTypes/MACHINE_TYPE",
      "networkInterfaces": [{
          "accessConfigs": [{
            "type": "ONE_TO_ONE_NAT",
            "name": "External NAT",
            "natIP": "IPV4_ADDRESS"
          }],
          "network": "global/networks/default"
      }],
      "disks": [{
          "autoDelete": "true",
            "boot": "true",
            "type": "PERSISTENT",
            "initializeParams": {
                "sourceImage": "SOURCE_IMAGE"
             }
      }]
    }
    

    ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • INSTANCE_NAME: ์ปดํ“จํŒ… ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.
    • ZONE: ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์˜์—ญ
    • MACHINE_TYPE: ์„ ํƒ์‚ฌํ•ญ: ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•  ๋จธ์‹  ์œ ํ˜• ๋ฆฌ์†Œ์Šค์˜ ์ „์ฒด ๋˜๋Š” ๋ถ€๋ถ„ URL(zones/ZONE/machineTypes/MACHINE_TYPE ํ˜•์‹)
    • IPV4_ADDRESS: ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  IPv4 ์ฃผ์†Œ. ์ฃผ์†Œ ์ด๋ฆ„์ด ์•„๋‹Œ ์˜ˆ์•ฝ๋œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • SOURCE_IMAGE: ๊ณต๊ฐœ ์ด๋ฏธ์ง€์˜ ํŠน์ • ๋ฒ„์ „(์˜ˆ: projects/debian-cloud/global/images/debian-10-buster-v20200309) ๋˜๋Š” ์ด๋ฏธ์ง€ ๊ณ„์—ด(์˜ˆ: projects/debian-cloud/global/images/family/debian-10)
  • ์ƒˆ ์ธ์Šคํ„ด์Šค์— ๊ณ ์ • ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋‹ค์Œ ์•ˆ๋‚ด๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

    ์ƒˆ ์ธ์Šคํ„ด์Šค ๋งŒ๋“ค๊ธฐ ์š”์ฒญ์—์„œ networkInterfaces[].ipv6AccessConfigs[].externalIpv6 ์†์„ฑ๊ณผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    {
      "name": "INSTANCE_NAME",
      "machineType": "zones/ZONE/machineTypes/MACHINE_TYPE",
      "networkInterfaces": [{
              "ipv6AccessConfigs": [{
             "externalIpv6": "IPV6_ADDRESS",
             "externalIpv6PrefixLength": 96,
             "name": "external-ipv6-access-config",
             "networkTier": "PREMIUM",
             "type": "DIRECT_IPV6"
              }],
          "stackType": "STACK_TYPE",
          "subnetwork":"SUBNETWORK"
      }],
      "disks": [{
          "autoDelete": "true",
          "boot": "true",
          "mode": "READ_WRITE",
          "type": "PERSISTENT",
          "initializeParams": {
              "sourceImage": "SOURCE_IMAGE"
          },
      }],
    }
    

    ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • INSTANCE_NAME: ์ปดํ“จํŒ… ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.
    • ZONE: ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ์˜์—ญ
    • MACHINE_TYPE: ์„ ํƒ์‚ฌํ•ญ: ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•  ๋จธ์‹  ์œ ํ˜• ๋ฆฌ์†Œ์Šค์˜ ์ „์ฒด ๋˜๋Š” ๋ถ€๋ถ„ URL(zones/ZONE/machineTypes/MACHINE_TYPE ํ˜•์‹)
    • IPV6_ADDRESS: ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  IPv6 ์ฃผ์†Œ. ์ฃผ์†Œ ์ด๋ฆ„์ด ์•„๋‹Œ ์˜ˆ์•ฝ๋œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    • STACK_TYPE: ์ธ์Šคํ„ด์Šค์˜ ์Šคํƒ ์œ ํ˜•, IPV4_IPV6(์ด์ค‘ ์Šคํƒ) ๋˜๋Š” IPV6_ONLY
    • SUBNET: ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๊ฐ€ ํฌํ•จ๋œ ์„œ๋ธŒ๋„ท
    • SOURCE_IMAGE: ๊ณต๊ฐœ ์ด๋ฏธ์ง€์˜ ํŠน์ • ๋ฒ„์ „(์˜ˆ: "projects/debian-cloud/global/images/debian-10-buster-v20200309") ๋˜๋Š” ์ด๋ฏธ์ง€ ๊ณ„์—ด(์˜ˆ: "projects/debian-cloud/global/images/family/debian-10")

Go


// assignStaticExternalToNewVM creates a new VM instance and assigns a static external IP address to it.
// NOTE: ip address is expected to exist and be located in the same region as new VM
func assignStaticExternalToNewVM(w io.Writer, projectID, zone, instanceName, ipAddress string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// ipAddress := 301.222.11.123

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	imagesClient, err := compute.NewImagesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewImagesRESTClient: %w", err)
	}
	defer imagesClient.Close()

	// List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details.
	newestDebianReq := &computepb.GetFromFamilyImageRequest{
		Project: "debian-cloud",
		Family:  "debian-12",
	}
	newestDebian, err := imagesClient.GetFromFamily(ctx, newestDebianReq)
	if err != nil {
		return fmt.Errorf("unable to get image from family: %w", err)
	}

	req := &computepb.InsertInstanceRequest{
		Project: projectID,
		Zone:    zone,
		InstanceResource: &computepb.Instance{
			Name: proto.String(instanceName),
			Disks: []*computepb.AttachedDisk{
				{
					InitializeParams: &computepb.AttachedDiskInitializeParams{
						DiskSizeGb:  proto.Int64(10),
						SourceImage: newestDebian.SelfLink,
						DiskType:    proto.String(fmt.Sprintf("zones/%s/diskTypes/pd-standard", zone)),
					},
					AutoDelete: proto.Bool(true),
					Boot:       proto.Bool(true),
					Type:       proto.String(computepb.AttachedDisk_PERSISTENT.String()),
				},
			},
			MachineType: proto.String(fmt.Sprintf("zones/%s/machineTypes/n1-standard-1", zone)),
			NetworkInterfaces: []*computepb.NetworkInterface{
				{
					AccessConfigs: []*computepb.AccessConfig{
						{
							Type:        proto.String(computepb.AccessConfig_ONE_TO_ONE_NAT.String()),
							Name:        proto.String("External NAT"),
							NetworkTier: proto.String(computepb.AccessConfig_PREMIUM.String()),
							NatIP:       proto.String(ipAddress),
						},
					},
				},
			},
		},
	}

	op, err := instancesClient.Insert(ctx, req)
	if err != nil {
		return fmt.Errorf("unable to create instance: %w", err)
	}

	if err = op.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}

	fmt.Fprintf(w, "Static address %s assigned to new VM", ipAddress)

	return nil
}

์ž๋ฐ”


import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.Type;
import com.google.cloud.compute.v1.Address.NetworkTier;
import com.google.cloud.compute.v1.AttachedDisk;
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
import com.google.cloud.compute.v1.GetInstanceRequest;
import com.google.cloud.compute.v1.ImagesClient;
import com.google.cloud.compute.v1.InsertInstanceRequest;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AssignStaticExternalNewVmAddress {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Instance ID of the Google Cloud project you want to use.
    String instanceId = "your-instance-id";
    // Name of the zone to create the instance in. For example: "us-west3-b"
    String zone = "your-zone-id";
    // machine type of the VM being created. This value uses the
    // following format: "zones/{zone}/machineTypes/{type_name}".
    // For example: "zones/europe-west3-c/machineTypes/f1-micro"
    String machineType = String.format("zones/%s/machineTypes/{your-machineType-id}", zone);
    // boolean flag indicating if the instance should have an external IPv4 address assigned.
    boolean externalAccess = true;
    // external IPv4 address to be assigned to this instance. If you specify
    // an external IP address, it must live in the same region as the zone of the instance.
    // This setting requires `external_access` to be set to True to work.
    String externalIpv4 = "your-externalIpv4-id";

    assignStaticExternalNewVmAddress(projectId, instanceId, zone,
            externalAccess, machineType, externalIpv4);
  }

  // Create a new VM instance with assigned static external IP address.
  public static Instance assignStaticExternalNewVmAddress(String projectId, String instanceName,
                                                          String zone, boolean externalAccess,
                                                          String machineType, String externalIpv4)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    String sourceImage;
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (ImagesClient imagesClient = ImagesClient.create()) {
      sourceImage = imagesClient.getFromFamily("debian-cloud", "debian-11").getSelfLink();
    }
    AttachedDisk attachedDisk = buildAttachedDisk(sourceImage, zone);

    return createInstance(projectId, instanceName, zone,
            attachedDisk, machineType, externalAccess, externalIpv4);
  }

  private static AttachedDisk buildAttachedDisk(String sourceImage, String zone) {
    AttachedDiskInitializeParams initializeParams = AttachedDiskInitializeParams.newBuilder()
            .setSourceImage(sourceImage)
            .setDiskSizeGb(10)
            .setDiskType(String.format("zones/%s/diskTypes/pd-standard", zone))
            .build();

    return AttachedDisk.newBuilder()
            .setInitializeParams(initializeParams)
            // Remember to set auto_delete to True if you want the disk to be deleted
            // when you delete your VM instance.
            .setAutoDelete(true)
            .setBoot(true)
            .build();
  }

  // Send an instance creation request to the Compute Engine API and wait for it to complete.
  private static Instance createInstance(String projectId, String instanceName,
                                         String zone, AttachedDisk disks,
                                         String machineType, boolean externalAccess,
                                         String externalIpv4)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient client = InstancesClient.create()) {
      Instance instanceResource =
              buildInstanceResource(instanceName, disks, machineType, externalAccess, externalIpv4);

      InsertInstanceRequest build = InsertInstanceRequest.newBuilder()
              .setProject(projectId)
              .setRequestId(UUID.randomUUID().toString())
              .setZone(zone)
              .setInstanceResource(instanceResource)
              .build();
      client.insertCallable().futureCall(build).get(60, TimeUnit.SECONDS);

      GetInstanceRequest getInstanceRequest = GetInstanceRequest.newBuilder()
              .setInstance(instanceName)
              .setProject(projectId)
              .setZone(zone)
              .build();

      return client.get(getInstanceRequest);
    }
  }

  private static Instance buildInstanceResource(String instanceName, AttachedDisk disk,
                                                String machineType, boolean externalAccess,
                                                String externalIpv4) {
    NetworkInterface networkInterface =
            networkInterface(externalAccess, externalIpv4);

    return Instance.newBuilder()
            .setName(instanceName)
            .addDisks(disk)
            .setMachineType(machineType)
            .addNetworkInterfaces(networkInterface)
            .build();
  }

  private static NetworkInterface networkInterface(boolean externalAccess, String externalIpv4) {
    NetworkInterface.Builder build = NetworkInterface.newBuilder()
            .setNetwork("global/networks/default");
    if (externalAccess) {
      AccessConfig.Builder accessConfig = AccessConfig.newBuilder()
              .setType(Type.ONE_TO_ONE_NAT.name())
              .setName("External NAT")
              .setNetworkTier(NetworkTier.PREMIUM.name());
      if (externalIpv4 != null) {
        accessConfig.setNatIP(externalIpv4);
      }
      build.addAccessConfigs(accessConfig.build());
    }

    return build.build();
  }
}

Python

from __future__ import annotations

import re
import sys
from typing import Any
import warnings

from google.api_core.extended_operation import ExtendedOperation
from google.cloud import compute_v1


def get_image_from_family(project: str, family: str) -> compute_v1.Image:
    """
    Retrieve the newest image that is part of a given family in a project.

    Args:
        project: project ID or project number of the Cloud project you want to get image from.
        family: name of the image family you want to get image from.

    Returns:
        An Image object.
    """
    image_client = compute_v1.ImagesClient()
    # List of public operating system (OS) images: https://cloud.google.com/compute/docs/images/os-details
    newest_image = image_client.get_from_family(project=project, family=family)
    return newest_image


def disk_from_image(
    disk_type: str,
    disk_size_gb: int,
    boot: bool,
    source_image: str,
    auto_delete: bool = True,
) -> compute_v1.AttachedDisk:
    """
    Create an AttachedDisk object to be used in VM instance creation. Uses an image as the
    source for the new disk.

    Args:
         disk_type: the type of disk you want to create. This value uses the following format:
            "zones/{zone}/diskTypes/(pd-standard|pd-ssd|pd-balanced|pd-extreme)".
            For example: "zones/us-west3-b/diskTypes/pd-ssd"
        disk_size_gb: size of the new disk in gigabytes
        boot: boolean flag indicating whether this disk should be used as a boot disk of an instance
        source_image: source image to use when creating this disk. You must have read access to this disk. This can be one
            of the publicly available images or an image from one of your projects.
            This value uses the following format: "projects/{project_name}/global/images/{image_name}"
        auto_delete: boolean flag indicating whether this disk should be deleted with the VM that uses it

    Returns:
        AttachedDisk object configured to be created using the specified image.
    """
    boot_disk = compute_v1.AttachedDisk()
    initialize_params = compute_v1.AttachedDiskInitializeParams()
    initialize_params.source_image = source_image
    initialize_params.disk_size_gb = disk_size_gb
    initialize_params.disk_type = disk_type
    boot_disk.initialize_params = initialize_params
    # Remember to set auto_delete to True if you want the disk to be deleted when you delete
    # your VM instance.
    boot_disk.auto_delete = auto_delete
    boot_disk.boot = boot
    return boot_disk


def wait_for_extended_operation(
    operation: ExtendedOperation, verbose_name: str = "operation", timeout: int = 300
) -> Any:
    """
    Waits for the extended (long-running) operation to complete.

    If the operation is successful, it will return its result.
    If the operation ends with an error, an exception will be raised.
    If there were any warnings during the execution of the operation
    they will be printed to sys.stderr.

    Args:
        operation: a long-running operation you want to wait on.
        verbose_name: (optional) a more verbose name of the operation,
            used only during error and warning reporting.
        timeout: how long (in seconds) to wait for operation to finish.
            If None, wait indefinitely.

    Returns:
        Whatever the operation.result() returns.

    Raises:
        This method will raise the exception received from `operation.exception()`
        or RuntimeError if there is no exception set, but there is an `error_code`
        set for the `operation`.

        In case of an operation taking longer than `timeout` seconds to complete,
        a `concurrent.futures.TimeoutError` will be raised.
    """
    result = operation.result(timeout=timeout)

    if operation.error_code:
        print(
            f"Error during {verbose_name}: [Code: {operation.error_code}]: {operation.error_message}",
            file=sys.stderr,
            flush=True,
        )
        print(f"Operation ID: {operation.name}", file=sys.stderr, flush=True)
        raise operation.exception() or RuntimeError(operation.error_message)

    if operation.warnings:
        print(f"Warnings during {verbose_name}:\n", file=sys.stderr, flush=True)
        for warning in operation.warnings:
            print(f" - {warning.code}: {warning.message}", file=sys.stderr, flush=True)

    return result


def create_instance(
    project_id: str,
    zone: str,
    instance_name: str,
    disks: list[compute_v1.AttachedDisk],
    machine_type: str = "n1-standard-1",
    network_link: str = "global/networks/default",
    subnetwork_link: str = None,
    internal_ip: str = None,
    external_access: bool = False,
    external_ipv4: str = None,
    accelerators: list[compute_v1.AcceleratorConfig] = None,
    preemptible: bool = False,
    spot: bool = False,
    instance_termination_action: str = "STOP",
    custom_hostname: str = None,
    delete_protection: bool = False,
) -> compute_v1.Instance:
    """
    Send an instance creation request to the Compute Engine API and wait for it to complete.

    Args:
        project_id: project ID or project number of the Cloud project you want to use.
        zone: name of the zone to create the instance in. For example: "us-west3-b"
        instance_name: name of the new virtual machine (VM) instance.
        disks: a list of compute_v1.AttachedDisk objects describing the disks
            you want to attach to your new instance.
        machine_type: machine type of the VM being created. This value uses the
            following format: "zones/{zone}/machineTypes/{type_name}".
            For example: "zones/europe-west3-c/machineTypes/f1-micro"
        network_link: name of the network you want the new instance to use.
            For example: "global/networks/default" represents the network
            named "default", which is created automatically for each project.
        subnetwork_link: name of the subnetwork you want the new instance to use.
            This value uses the following format:
            "regions/{region}/subnetworks/{subnetwork_name}"
        internal_ip: internal IP address you want to assign to the new instance.
            By default, a free address from the pool of available internal IP addresses of
            used subnet will be used.
        external_access: boolean flag indicating if the instance should have an external IPv4
            address assigned.
        external_ipv4: external IPv4 address to be assigned to this instance. If you specify
            an external IP address, it must live in the same region as the zone of the instance.
            This setting requires `external_access` to be set to True to work.
        accelerators: a list of AcceleratorConfig objects describing the accelerators that will
            be attached to the new instance.
        preemptible: boolean value indicating if the new instance should be preemptible
            or not. Preemptible VMs have been deprecated and you should now use Spot VMs.
        spot: boolean value indicating if the new instance should be a Spot VM or not.
        instance_termination_action: What action should be taken once a Spot VM is terminated.
            Possible values: "STOP", "DELETE"
        custom_hostname: Custom hostname of the new VM instance.
            Custom hostnames must conform to RFC 1035 requirements for valid hostnames.
        delete_protection: boolean value indicating if the new virtual machine should be
            protected against deletion or not.
    Returns:
        Instance object.
    """
    instance_client = compute_v1.InstancesClient()

    # Use the network interface provided in the network_link argument.
    network_interface = compute_v1.NetworkInterface()
    network_interface.network = network_link
    if subnetwork_link:
        network_interface.subnetwork = subnetwork_link

    if internal_ip:
        network_interface.network_i_p = internal_ip

    if external_access:
        access = compute_v1.AccessConfig()
        access.type_ = compute_v1.AccessConfig.Type.ONE_TO_ONE_NAT.name
        access.name = "External NAT"
        access.network_tier = access.NetworkTier.PREMIUM.name
        if external_ipv4:
            access.nat_i_p = external_ipv4
        network_interface.access_configs = [access]

    # Collect information into the Instance object.
    instance = compute_v1.Instance()
    instance.network_interfaces = [network_interface]
    instance.name = instance_name
    instance.disks = disks
    if re.match(r"^zones/[a-z\d\-]+/machineTypes/[a-z\d\-]+$", machine_type):
        instance.machine_type = machine_type
    else:
        instance.machine_type = f"zones/{zone}/machineTypes/{machine_type}"

    instance.scheduling = compute_v1.Scheduling()
    if accelerators:
        instance.guest_accelerators = accelerators
        instance.scheduling.on_host_maintenance = (
            compute_v1.Scheduling.OnHostMaintenance.TERMINATE.name
        )

    if preemptible:
        # Set the preemptible setting
        warnings.warn(
            "Preemptible VMs are being replaced by Spot VMs.", DeprecationWarning
        )
        instance.scheduling = compute_v1.Scheduling()
        instance.scheduling.preemptible = True

    if spot:
        # Set the Spot VM setting
        instance.scheduling.provisioning_model = (
            compute_v1.Scheduling.ProvisioningModel.SPOT.name
        )
        instance.scheduling.instance_termination_action = instance_termination_action

    if custom_hostname is not None:
        # Set the custom hostname for the instance
        instance.hostname = custom_hostname

    if delete_protection:
        # Set the delete protection bit
        instance.deletion_protection = True

    # Prepare the request to insert an instance.
    request = compute_v1.InsertInstanceRequest()
    request.zone = zone
    request.project = project_id
    request.instance_resource = instance

    # Wait for the create operation to complete.
    print(f"Creating the {instance_name} instance in {zone}...")

    operation = instance_client.insert(request=request)

    wait_for_extended_operation(operation, "instance creation")

    print(f"Instance {instance_name} created.")
    return instance_client.get(project=project_id, zone=zone, instance=instance_name)


def assign_static_external_ip_to_new_vm(
    project_id: str, zone: str, instance_name: str, ip_address: str
) -> compute_v1.Instance:
    """
    Create a new VM instance with assigned static external IP address.

    Args:
        project_id (str): project ID or project number of the Cloud project you want to use.
        zone (str): name of the zone to create the instance in. For example: "us-west3-b"
        instance_name (str): name of the new virtual machine (VM) instance.
        ip_address(str): external address to be assigned to this instance. It must live in the same
        region as the zone of the instance and be precreated before function called.

    Returns:
        Instance object.
    """
    newest_debian = get_image_from_family(project="debian-cloud", family="debian-12")
    disk_type = f"zones/{zone}/diskTypes/pd-standard"
    disks = [disk_from_image(disk_type, 10, True, newest_debian.self_link, True)]
    instance = create_instance(
        project_id,
        zone,
        instance_name,
        disks,
        external_ipv4=ip_address,
        external_access=True,
    )
    return instance

์™ธ๋ถ€ IP ์ฃผ์†Œ ๋ณ€๊ฒฝ ๋˜๋Š” ๊ธฐ์กด ์ธ์Šคํ„ด์Šค์— ํ• ๋‹น

์ž„์‹œ ๋˜๋Š” ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด IPv4 ์ „์šฉ ๋˜๋Š” ์ด์ค‘ ์Šคํƒ ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ˆ์ฐจ๋Š” IPv6 ์ „์šฉ ์ธ์Šคํ„ด์Šค์—๋Š” ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ปดํ“จํŒ… ์ธ์Šคํ„ด์Šค์—๋Š” ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹จ์ผ ์Šคํƒ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ•˜๋‚˜ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ค‘ ์Šคํƒ ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ 1๊ฐœ์™€ ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ 1๊ฐœ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค์— ์ด๋ฏธ ์™ธ๋ถ€ IP ์ฃผ์†Œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋จผ์ € ํ•ด๋‹น ์ฃผ์†Œ๋ฅผ ์‚ญ์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ƒˆ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ธฐ์กด ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ˜์†”

  1. Google Cloud ์ฝ˜์†”์—์„œ VM ์ธ์Šคํ„ด์Šค ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    VM ์ธ์Šคํ„ด์Šค๋กœ ์ด๋™

  2. ์™ธ๋ถ€ IP๋ฅผ ํ• ๋‹นํ•˜๋ ค๋Š” ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค ์„ธ๋ถ€์ •๋ณด ํŽ˜์ด์ง€๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

  3. ์ธ์Šคํ„ด์Šค ์„ธ๋ถ€์ •๋ณด ํŽ˜์ด์ง€์—์„œ ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

    1. ์ˆ˜์ •์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
    2. ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํŽผ์นฉ๋‹ˆ๋‹ค.
    3. ํ•„์š”ํ•œ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์„ ํƒํ•˜์—ฌ ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค๊ฐ€ IPv4 ์ „์šฉ์ธ๋ฐ IPv6 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด ๋จผ์ € ์Šคํƒ ์œ ํ˜•์„ ์ด์ค‘ ์Šคํƒ์œผ๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      1. ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ์˜ ๊ฒฝ์šฐ ์ž„์‹œ ๋˜๋Š” ๊ณ ์ • ์™ธ๋ถ€ IPv4 ์ฃผ์†Œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
      2. ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ์˜ ๊ฒฝ์šฐ ์ž„์‹œ ๋˜๋Š” ๊ณ ์ • ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    4. ์™„๋ฃŒ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
  4. ์ €์žฅ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

gcloud

  1. ์„ ํƒ์‚ฌํ•ญ: ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝํ•ฉ๋‹ˆ๋‹ค.

    ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์—๋Š” ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝํ•˜๊ณ  ํ•ด๋‹น ์ฃผ์†Œ๊ฐ€ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค์—์„œ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ์•ˆ๋‚ด์— ๋”ฐ๋ผ ์ƒˆ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝํ•˜๊ฑฐ๋‚˜ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹น ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

    ์ž„์‹œ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ์—๋Š” ์ด ๋‹จ๊ณ„๋ฅผ ๊ฑด๋„ˆ ๋›ฐ๊ณ , Compute Engine์ด ์ž„์‹œ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๋ฌด์ž‘์œ„๋กœ ํ• ๋‹นํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  2. ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ• ๋‹น ํ•ด์ œ์˜ ์„ค๋ช…๋Œ€๋กœ ๊ธฐ์กด IP ์ฃผ์†Œ ํ• ๋‹น์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

  3. ์ƒˆ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

    • IPv4 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด instances add-access-config ํ•˜์œ„ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

      ์ฐธ๊ณ : IP_ADDRESS๋ฅผ ๊ณ ์ • IP ์ฃผ์†Œ์˜ ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊พธ์ง€ ๋งˆ์„ธ์š”. ์‹ค์ œ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      gcloud compute instances add-access-config INSTANCE_NAME \
        --access-config-name="ACCESS_CONFIG_NAME" --address=IP_ADDRESS
      

      ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

      • INSTANCE_NAME: ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
      • ACCESS_CONFIG_NAME: ์•ก์„ธ์Šค ๊ตฌ์„ฑ์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. ๋”ฐ์˜ดํ‘œ ์‚ฌ์ด์— ์ „์ฒด ์ด๋ฆ„์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
      • IP_ADDRESS: ์ถ”๊ฐ€ํ•  IP ์ฃผ์†Œ์ž…๋‹ˆ๋‹ค.

      ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  Compute Engine์ด ์ž„์‹œ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋„๋ก ํ•˜๋ ค๋ฉด --address IP_ADDRESS ์†์„ฑ์„ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.

      gcloud compute instances add-access-config INSTANCE_NAME \
        --access-config-name="ACCESS_CONFIG_NAME"
      
    • ์ธ์Šคํ„ด์Šค๋ฅผ ์ด์ค‘ ์Šคํƒ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  IPv6 ์ฃผ์†Œ๋ฅผ ํ• ๋‹นํ•˜๋ ค๋ฉด instance network-interfaces update ํ•˜์œ„ ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

      gcloud compute instances network-interfaces update INSTANCE_NAME \
        --network-interface=NIC \
        --ipv6-network-tier=PREMIUM \
        --stack-type=STACK_TYPE \
        --external-ipv6-address=IPV6_ADDRESS \
        --external-ipv6-prefix-length=96 \
        --zone=ZONE
      

      ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

      • INSTANCE_NAME: ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
      • NIC: ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
      • STACK_TYPE: ์ธ์Šคํ„ด์Šค์˜ ์Šคํƒ ์œ ํ˜•์œผ๋กœ IPV4_IPV6์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์Šคํƒ ์œ ํ˜•์„ IPV6_ONLY๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
      • IPV6_ADDRESS: ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•  IPv6 ์ฃผ์†Œ์ž…๋‹ˆ๋‹ค. /96 ๋ฒ”์œ„์—์„œ ์ฒซ ๋ฒˆ์งธ IPv6 ์ฃผ์†Œ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
      • ZONE: ์ธ์Šคํ„ด์Šค์˜ ์˜์—ญ์ž…๋‹ˆ๋‹ค.

REST

์ธ์Šคํ„ด์Šค์˜ ์ƒˆ ์•ก์„ธ์Šค ๊ตฌ์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ธ์Šคํ„ด์Šค์˜ ์™ธ๋ถ€ IPv4 ๋˜๋Š” IPv6 ์ฃผ์†Œ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ• ๋‹น ํ•ด์ œ์˜ ์„ค๋ช…๋Œ€๋กœ ๊ธฐ์กด IP ์ฃผ์†Œ ํ• ๋‹น์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

  2. instances.deleteAccessConfig ๋ฉ”์„œ๋“œ์— POST ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ธฐ์กด ์•ก์„ธ์Šค ๊ตฌ์„ฑ์„ ์‚ญ์ œํ•˜์„ธ์š”.

    POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/deleteAccessConfig
    
  3. instances.addAccessConfig ๋ฉ”์„œ๋“œ์— POST ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์ธ์Šคํ„ด์Šค์˜ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์— ์ƒˆ ์•ก์„ธ์Šค ๊ตฌ์„ฑ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    • IPv4 ์ฃผ์†Œ์˜ ๊ฒฝ์šฐ ๋‹ค์Œ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

      POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/addAccessConfig
      {
      "natIP": "IPV4_ADDRESS",
      "name": "ACCESS_CONFIG_NAME"
      }
      
    • IPv6 ์ฃผ์†Œ์˜ ๊ฒฝ์šฐ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์˜ stackType์„ IPV4_IPV6๋กœ ์—…๋ฐ์ดํŠธํ•˜๊ณ  networkInterfaces[].ipv6AccessConfigs[].externalIpv6 ์†์„ฑ๊ณผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์™ธ๋ถ€ IPv6 ์ฃผ์†Œ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

      ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ƒˆ ์ธ์Šคํ„ด์Šค์— ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ• ๋‹น์„ ์ฐธ์กฐํ•˜์„ธ์š”.

Go

import (
	"context"
	"fmt"
	"io"

	"google.golang.org/protobuf/proto"

	compute "cloud.google.com/go/compute/apiv1"
	"cloud.google.com/go/compute/apiv1/computepb"
)

// assignStaticAddressToExistingVM assigns a static external IP address to an existing VM instance.
// Note: VM and assigned IP must be in the same region.
func assignStaticAddressToExistingVM(w io.Writer, projectID, zone, instanceName, IPAddress, networkInterfaceName string) error {
	// projectID := "your_project_id"
	// zone := "europe-central2-b"
	// instanceName := "your_instance_name"
	// IPAddress := "34.111.222.333"
	// networkInterfaceName := "nic0"

	ctx := context.Background()
	instancesClient, err := compute.NewInstancesRESTClient(ctx)
	if err != nil {
		return fmt.Errorf("NewInstancesRESTClient: %w", err)
	}
	defer instancesClient.Close()

	reqGet := &computepb.GetInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
	}

	instance, err := instancesClient.Get(ctx, reqGet)
	if err != nil {
		return fmt.Errorf("could not get instance: %w", err)
	}

	var networkInterface *computepb.NetworkInterface
	for _, ni := range instance.NetworkInterfaces {
		if *ni.Name == networkInterfaceName {
			networkInterface = ni
			break
		}
	}

	if networkInterface == nil {
		return fmt.Errorf("No network interface named '%s' found on instance %s", networkInterfaceName, instanceName)
	}

	var accessConfig *computepb.AccessConfig
	for _, ac := range networkInterface.AccessConfigs {
		if *ac.Type == computepb.AccessConfig_ONE_TO_ONE_NAT.String() {
			accessConfig = ac
			break
		}
	}

	if accessConfig != nil {
		// network interface is immutable - deletion stage is required in case of any assigned ip (static or ephemeral).
		reqDelete := &computepb.DeleteAccessConfigInstanceRequest{
			Project:          projectID,
			Zone:             zone,
			Instance:         instanceName,
			AccessConfig:     *accessConfig.Name,
			NetworkInterface: networkInterfaceName,
		}

		opDelete, err := instancesClient.DeleteAccessConfig(ctx, reqDelete)
		if err != nil {
			return fmt.Errorf("unable to delete access config: %w", err)
		}

		if err = opDelete.Wait(ctx); err != nil {
			return fmt.Errorf("unable to wait for the operation: %w", err)
		}
	}

	reqAdd := &computepb.AddAccessConfigInstanceRequest{
		Project:  projectID,
		Zone:     zone,
		Instance: instanceName,
		AccessConfigResource: &computepb.AccessConfig{
			NatIP: &IPAddress,
			Type:  proto.String(computepb.AccessConfig_ONE_TO_ONE_NAT.String()),
		},
		NetworkInterface: networkInterfaceName,
	}

	opAdd, err := instancesClient.AddAccessConfig(ctx, reqAdd)
	if err != nil {
		return fmt.Errorf("unable to add access config: %w", err)
	}

	if err = opAdd.Wait(ctx); err != nil {
		return fmt.Errorf("unable to wait for the operation: %w", err)
	}

	fmt.Fprintf(w, "Static address %s assigned to the instance %s\n", IPAddress, instanceName)

	return nil
}

์ž๋ฐ”


import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.Type;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class AssignStaticExistingVm {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Instance ID of the Google Cloud project you want to use.
    String instanceId = "your-instance-id";
    // Name of the zone to create the instance in. For example: "us-west3-b"
    String zone = "your-zone-id";
    // Name of the network interface to assign.
    String netInterfaceName = "your-netInterfaceName-id";

    assignStaticExistingVmAddress(projectId, instanceId, zone, netInterfaceName);
  }

  // Updates or creates an access configuration for a VM instance to assign a static external IP.
  // As network interface is immutable - deletion stage is required
  // in case of any assigned ip (static or ephemeral).
  // VM and ip address must be created before calling this function.
  // IMPORTANT: VM and assigned IP must be in the same region.
  public static Instance assignStaticExistingVmAddress(String projectId, String instanceId,
                                                       String zone, String netInterfaceName)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient client = InstancesClient.create()) {
      Instance instance = client.get(projectId, zone, instanceId);

      NetworkInterface networkInterface = null;
      for (NetworkInterface netInterface : instance.getNetworkInterfacesList()) {
        if (netInterface.getName().equals(netInterfaceName)) {
          networkInterface = netInterface;
          break;
        }
      }

      if (networkInterface == null) {
        throw new IllegalArgumentException(
                String.format(
                        "No '{network_interface_name}' variable found on instance %s.",
                        instanceId)
        );
      }
      AccessConfig accessConfig = null;
      for (AccessConfig config : networkInterface.getAccessConfigsList()) {
        if (config.getType().equals(Type.ONE_TO_ONE_NAT.name())) {
          accessConfig = config;
          break;
        }
      }

      if (accessConfig != null) {
        // Delete the existing access configuration first
        client.deleteAccessConfigAsync(projectId, zone, instanceId,
                        accessConfig.getName(), netInterfaceName)
                .get(30, TimeUnit.SECONDS);
      }

      // Add a new access configuration with the new IP
      AccessConfig newAccessConfig = AccessConfig.newBuilder()
              // Leave this field undefined to use an IP from a shared ephemeral IP address pool
              // .setNatIP(ipAddress)
              .setType(Type.ONE_TO_ONE_NAT.name())
              .setName("external-nat")
              .build();

      client.addAccessConfigAsync(projectId, zone, instanceId, netInterfaceName, newAccessConfig)
              .get(30, TimeUnit.SECONDS);

      // return updated instance
      return client.get(projectId, zone, instanceId);
    }
  }
}

Python

import uuid

from google.cloud.compute_v1 import InstancesClient
from google.cloud.compute_v1.types import AccessConfig
from google.cloud.compute_v1.types import AddAccessConfigInstanceRequest
from google.cloud.compute_v1.types import DeleteAccessConfigInstanceRequest


def assign_static_ip_to_existing_vm(
    project_id: str,
    zone: str,
    instance_name: str,
    ip_address: str,
    network_interface_name: str = "nic0",
):
    """
    Updates or creates an access configuration for a VM instance to assign a static external IP.
    As network interface is immutable - deletion stage is required in case of any assigned ip (static or ephemeral).
    VM and ip address must be created before calling this function.
    IMPORTANT: VM and assigned IP must be in the same region.

    Args:
        project_id (str): Project ID.
        zone (str): Zone where the VM is located.
        instance_name (str): Name of the VM instance.
        ip_address (str): New static external IP address to assign to the VM.
        network_interface_name (str): Name of the network interface to assign.

    Returns:
        google.cloud.compute_v1.types.Instance: Updated instance object.
    """
    client = InstancesClient()
    instance = client.get(project=project_id, zone=zone, instance=instance_name)
    network_interface = next(
        (ni for ni in instance.network_interfaces if ni.name == network_interface_name),
        None,
    )

    if network_interface is None:
        raise ValueError(
            f"No network interface named '{network_interface_name}' found on instance {instance_name}."
        )

    access_config = next(
        (ac for ac in network_interface.access_configs if ac.type_ == "ONE_TO_ONE_NAT"),
        None,
    )

    if access_config:
        # Delete the existing access configuration first
        delete_request = DeleteAccessConfigInstanceRequest(
            project=project_id,
            zone=zone,
            instance=instance_name,
            access_config=access_config.name,
            network_interface=network_interface_name,
            request_id=str(uuid.uuid4()),
        )
        delete_operation = client.delete_access_config(delete_request)
        delete_operation.result()

    # Add a new access configuration with the new IP
    add_request = AddAccessConfigInstanceRequest(
        project=project_id,
        zone=zone,
        instance=instance_name,
        network_interface="nic0",
        access_config_resource=AccessConfig(
            nat_i_p=ip_address, type_="ONE_TO_ONE_NAT", name="external-nat"
        ),
        request_id=str(uuid.uuid4()),
    )
    add_operation = client.add_access_config(add_request)
    add_operation.result()

    updated_instance = client.get(project=project_id, zone=zone, instance=instance_name)
    return updated_instance

์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํŠน์ • ์ธ์Šคํ„ด์Šค๋กœ ์ œํ•œ

ํŠน์ • ์›Œํฌ๋กœ๋“œ์—์„œ๋Š” ๊ธฐ๋ณธ์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋ณด์•ˆ ๋ฐ ๋„คํŠธ์›Œํฌ ์ œํ•œ์‚ฌํ•ญ์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํŠน์ • ์ปดํ“จํŒ… ์ธ์Šคํ„ด์Šค๋งŒ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ œํ•œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๋ฌด๋‹จ ๋ฐ˜์ถœ์„ ๋ฐฉ์ง€ํ•˜๊ฑฐ๋‚˜ ๋„คํŠธ์›Œํฌ ๊ฒฉ๋ฆฌ๋ฅผ ์œ ์ง€ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์กฐ์ง ์ •์ฑ…์„ ์‚ฌ์šฉํ•˜๋ฉด ์กฐ์ง ๋˜๋Š” ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ์ธ์Šคํ„ด์Šค์˜ ์™ธ๋ถ€ IP ์ฃผ์†Œ ์‚ฌ์šฉ์„ ์ œ์–ดํ•˜๋Š” ์ œ์•ฝ ์กฐ๊ฑด์ด ํฌํ•จ๋œ ํŠน์ • ์ธ์Šคํ„ด์Šค์—์„œ๋งŒ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ธ์Šคํ„ด์Šค์—์„œ ์™ธ๋ถ€ IP ์ฃผ์†Œ ์ œ์–ด๋ฅผ ์œ„ํ•œ ์ œ์•ฝ ์กฐ๊ฑด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

constraints/compute.vmExternalIpAccess

์ œ์•ฝ ์กฐ๊ฑด์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์Šคํ„ด์Šค์˜ allowedList๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์ฑ…์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ •์ฑ…์„ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์ธ์Šคํ„ด์Šค์— ๋ชจ๋“  ์™ธ๋ถ€ IP ์ฃผ์†Œ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ •์ฑ…์ด ์ ์šฉ๋˜๋ฉด allowedValues ๋ชฉ๋ก์— ๋‚˜์—ด๋œ ์ธ์Šคํ„ด์Šค์—๋งŒ ์™ธ๋ถ€ IP ์ฃผ์†Œ(์ž„์‹œ ๋˜๋Š” ๊ณ ์ •)๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๊ณ , ์กฐ์ง ๋˜๋Š” ํ”„๋กœ์ ํŠธ์—์„œ ์ •์ฑ…์— ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜๋˜์ง€ ์•Š์€ ๋‹ค๋ฅธ Compute Engine ์ธ์Šคํ„ด์Šค๋Š” ์™ธ๋ถ€ IP ์ฃผ์†Œ ์‚ฌ์šฉ์ด ๊ธˆ์ง€๋ฉ๋‹ˆ๋‹ค.

์ธ์Šคํ„ด์Šค๋Š” ํ—ˆ์šฉ ๋ฐ ๊ฑฐ๋ถ€ ๋ชฉ๋ก์—์„œ ์ธ์Šคํ„ด์Šค์˜ URI๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹๋ณ„๋ฉ๋‹ˆ๋‹ค.

projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME

์™ธ๋ถ€ IP ์ฃผ์†Œ ์ œํ•œ ์‚ฌ์–‘

  • ์ด ๋ชฉ๋ก ์ œ์•ฝ ์กฐ๊ฑด์€ ์ธ์Šคํ„ด์Šค์—๋งŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด ์ œ์•ฝ์กฐ๊ฑด์€ ์†Œ๊ธ‰ํ•ด์„œ ์ ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ •์ฑ…์„ ์‚ฌ์šฉ ์„ค์ •ํ•˜๊ธฐ ์ „์— ์™ธ๋ถ€ IP ์ฃผ์†Œ๊ฐ€ ์žˆ๋Š” ๋ชจ๋“  ์ธ์Šคํ„ด์Šค๊ฐ€ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ์ด ์ œ์•ฝ์กฐ๊ฑด์€ allowedList ๋˜๋Š” deniedList๋ฅผ ํ—ˆ์šฉํ•˜์ง€๋งŒ ๋™์ผ ์ •์ฑ…์—์„œ ๋‘˜ ๋‹ค ํ—ˆ์šฉํ•˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
  • ํ•„์š”ํ•œ ๊ถŒํ•œ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ๋˜๋Š” ๊ด€๋ฆฌ์ž๊ฐ€ ์ธ์Šคํ„ด์Šค ์ˆ˜๋ช… ์ฃผ๊ธฐ ๋ฐ ๋ฌด๊ฒฐ์„ฑ์„ ๊ด€๋ฆฌ ๋ฐ ์œ ์ง€๋ณด์ˆ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ œ์•ฝ ์กฐ๊ฑด์€ ์ธ์Šคํ„ด์Šค์˜ URI๋งŒ ํ™•์ธํ•˜๋ฉฐ, ํ—ˆ์šฉ ๋ชฉ๋ก์— ์žˆ๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ณ€๊ฒฝ, ์‚ญ์ œ ๋˜๋Š” ์žฌ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์ œํ•œํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ถŒํ•œ

ํ”„๋กœ์ ํŠธ ๋˜๋Š” ์กฐ์ง ์ˆ˜์ค€์—์„œ ์ œ์•ฝ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๋ ค๋ฉด ํ•ด๋‹น ์กฐ์ง์—์„œ orgpolicy.policyAdmin ์—ญํ• ์„ ๋ถ€์—ฌ ๋ฐ›์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์กฐ์ง ์ˆ˜์ค€์—์„œ ์ •์ฑ… ์ œ์•ฝ์กฐ๊ฑด ์„ค์ •

์ฝ˜์†”

  1. ์กฐ์ง ์ •์ฑ… ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    ์กฐ์ง ์ •์ฑ…์œผ๋กœ ์ด๋™

  2. ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํ”„๋กœ์ ํŠธ ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด์—์„œ ํ•„์š”ํ•œ ์กฐ์ง์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
  3. VM ์ธ์Šคํ„ด์Šค์— ํ—ˆ์šฉ๋˜๋Š” ์™ธ๋ถ€ IP ์ •์˜๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
  4. ์ˆ˜์ •์„ ํด๋ฆญํ•˜์—ฌ ์™ธ๋ถ€ IP ์ •์ฑ…์„ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜์ • ๋„๊ตฌ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์œผ๋ฉด ์ ์ ˆํ•œ ๊ถŒํ•œ์ด ์—†๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  5. ๋งž์ถค์„ค์ •์„ ์„ ํƒํ•˜์—ฌ ํŠน์ • ์ธ์Šคํ„ด์Šค์˜ ์กฐ์ง ์ •์ฑ…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    ์กฐ์ง ์ •์ฑ… ์ˆ˜์ • ํŽ˜์ด์ง€์˜ ๋งž์ถค์„ค์ • ์˜ต์…˜

  6. ํ•„์š”ํ•œ ์ •์ฑ… ์‹œํ–‰ ๋ฐ ์ •์ฑ… ์œ ํ˜•์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  7. ์ •์ฑ… ๊ฐ’์—์„œ ์ปค์Šคํ…€์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  8. ์ธ์Šคํ„ด์Šค์˜ URI๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. URI๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜•์‹์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
    
  9. ์ƒˆ ์ •์ฑ… ๊ฐ’์„ ํด๋ฆญํ•˜๊ณ  ํ•„์š”์— ๋”ฐ๋ผ ์ธ์Šคํ„ด์Šค์˜ URI๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

  10. ์ €์žฅ์„ ํด๋ฆญํ•˜์—ฌ ์ œ์•ฝ์กฐ๊ฑด์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.

gcloud

์™ธ๋ถ€ IP ์ฃผ์†Œ์— ๋Œ€ํ•ด ์ œ์•ฝ์กฐ๊ฑด์„ ์„ค์ •ํ•˜๋ ค๋ฉด ๋จผ์ € ์กฐ์ง ID๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. organizations list ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ์‘๋‹ต์—์„œ ์ˆซ์ž ID๋ฅผ ์ฐพ์•„ ์กฐ์ง ID๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

gcloud organizations list

gcloud CLI๋Š” ์กฐ์ง ๋ชฉ๋ก์„ ๋‹ค์Œ ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

DISPLAY_NAME               ID
example-organization1      29252605212
example-organization2      1234567890

gcloud resource-manager org-policies set-policy ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์ฑ…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ •์ฑ…์„ JSON ํŒŒ์ผ๋กœ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ํ˜•์‹์œผ๋กœ JSON ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

{
"constraint": "constraints/compute.vmExternalIpAccess",
"listPolicy": {
  "allowedValues": [
     "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
     "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
     "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
  ]
 }
}

๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

  • PROJECT_ID: ์š”์ฒญ์˜ ํ”„๋กœ์ ํŠธ ID(์˜ˆ: example-project). ์ด๋Š” ์กฐ์ง ์ˆซ์ž ID๊ฐ€ ํ•„์š”ํ•œ ์กฐ์ง ์ •์ฑ… ์„ค์ •๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
  • ZONE: ์ธ์Šคํ„ด์Šค์˜ ์˜์—ญ
  • INSTANCE_NAME: ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.

๋˜๋Š” deniedValues ๋ชฉ๋ก์„ ์ง€์ •ํ•˜์—ฌ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–์ง€ ๋ชปํ•˜๋„๋ก ๋ช…์‹œ์ ์œผ๋กœ ๊ธˆ์ง€ํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชฉ๋ก์— ์—†๋Š” ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋‘ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–๋„๋ก ์•”์‹œ์ ์œผ๋กœ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. allowedValues ๋˜๋Š” deniedValues ์ค‘ ํ•˜๋‚˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‘˜ ๋‹ค ์ง€์ •ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์š”์ฒญ์„ ์‚ฌ์šฉํ•ด์„œ ํŒŒ์ผ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

gcloud resource-manager org-policies set-policy MY_POLICY.JSON --organization=ORGANIZATION_ID

ORGANIZATION_ID๋ฅผ ์กฐ์ง์˜ ์ˆซ์ž ID๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

์ธ์Šคํ„ด์Šค๊ฐ€ ์™ธ๋ถ€ IP ์ฃผ์†Œ์— ์•ก์„ธ์Šคํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด allValues๊ฐ€ DENY๋กœ ์„ค์ •๋œ ์ •์ฑ…์„ ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

{
  "constraint": "constraints/compute.vmExternalIpAccess",
  "listPolicy": {
    "allValues": "DENY"
  }
}

REST

setOrgPolicy() API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ œ์•ฝ์กฐ๊ฑด์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•˜๋Š” allowedValue ๋ชฉ๋ก์˜ ์ธ์Šคํ„ด์Šค๋Š” ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” deniedValues ๋ชฉ๋ก์„ ์ง€์ •ํ•˜์—ฌ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–์ง€ ๋ชปํ•˜๋„๋ก ๋ช…์‹œ์ ์œผ๋กœ ๊ธˆ์ง€ํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชฉ๋ก์— ์—†๋Š” ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋‘ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–๋„๋ก ์•”์‹œ์ ์œผ๋กœ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. allowedValues ๋˜๋Š” deniedValues ์ค‘ ํ•˜๋‚˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‘˜ ๋‹ค ์ง€์ •ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์€ ์กฐ์ง ๋‚ด ํŠน์ • ํ”„๋กœ์ ํŠธ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ํ—ˆ์šฉ๋˜๋Š” compute.vmExternalIpAccess ์ œ์•ฝ ์กฐ๊ฑด์„ ์กฐ์ง์— ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.

POST https://cloudresourcemanager.googleapis.com/v1/organizations/ORGANIZATION_ID:setOrgPolicy

์—ฌ๊ธฐ์„œ ORGANIZATION_ID๋Š” ์กฐ์ง์˜ ์ˆซ์ž ID์ž…๋‹ˆ๋‹ค.

์ด์ œ ์š”์ฒญ ๋ณธ๋ฌธ์—์„œ ์ด ์ œ์•ฝ์กฐ๊ฑด์˜ ์ •์ฑ…์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

{
  "policy": {
    "constraint": "constraints/compute.vmExternalIpAccess",
    "listPolicy": {
      "allowedValues": [
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME",
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
        ]
      }
    }
 }

์ธ์Šคํ„ด์Šค๊ฐ€ ์™ธ๋ถ€ IP ์ฃผ์†Œ์— ์•ก์„ธ์Šคํ•˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด allValues๊ฐ€ DENY๋กœ ์„ค์ •๋œ ์ •์ฑ…์„ ์„ค์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

{
  "policy": {
    "constraint": "constraints/compute.vmExternalIpAccess",
    "listPolicy": {
      "allValues": "DENY"
      }
    }
 }

ํ”„๋กœ์ ํŠธ ์ˆ˜์ค€์—์„œ ์ •์ฑ… ์„ค์ •

ํ”„๋กœ์ ํŠธ ์ˆ˜์ค€์—์„œ ์ •์ฑ…์„ ์„ค์ •ํ•˜๋ฉด ์กฐ์ง ์ˆ˜์ค€์˜ ์ •์ฑ…์ด ์žฌ์ •์˜๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์กฐ์ง ์ˆ˜์ค€์—์„œ allowedValues ๋ชฉ๋ก์— example-vm-1์ด ์žˆ์ง€๋งŒ, ํ”„๋กœ์ ํŠธ ์ˆ˜์ค€์˜ ์ •์ฑ…์—์„œ deniedValues ๋ชฉ๋ก์— ๋™์ผํ•œ ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์ธ์Šคํ„ด์Šค๊ฐ€ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ํ—ˆ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฝ˜์†”

์กฐ์ง ์ˆ˜์ค€์—์„œ ์ •์ฑ… ์ œ์•ฝ์กฐ๊ฑด ์„ค์ •์— ์„ค๋ช…๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ ˆ์ฐจ๋ฅผ ๋”ฐ๋ฅด์ง€๋งŒ, ์กฐ์ง ๋Œ€์‹  ํ”„๋กœ์ ํŠธ ์„ ํƒ๊ธฐ์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ์„ ํƒ๊ธฐ

gcloud

gcloud resource-manager org-policies set-policy ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์ฑ…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ •์ฑ…์„ JSON ํŒŒ์ผ๋กœ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ํ˜•์‹์œผ๋กœ JSON ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

{
 "constraint": "constraints/compute.vmExternalIpAccess",
 "listPolicy": {
  "allowedValues": [
   "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
  ]
 }
}

๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

  • PROJECT_ID: ์š”์ฒญ์˜ ํ”„๋กœ์ ํŠธ ID(์˜ˆ: example-project). ์ด๋Š” ์กฐ์ง ์ˆซ์ž ID๊ฐ€ ํ•„์š”ํ•œ ์กฐ์ง ์ •์ฑ… ์„ค์ •๊ณผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.
  • ZONE: ์ธ์Šคํ„ด์Šค์˜ ์˜์—ญ์ž…๋‹ˆ๋‹ค.
  • INSTANCE_NAME: ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.

๋˜๋Š” ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–์ง€ ๋ชปํ•˜๋„๋ก ๋ช…์‹œ์ ์œผ๋กœ ๊ธˆ์ง€ํ•  ์ธ์Šคํ„ด์Šค์˜ deniedValues ๋ชฉ๋ก์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชฉ๋ก์— ์—†๋Š” ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋‘ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–๋„๋ก ์•”์‹œ์ ์œผ๋กœ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. allowedValues ๋˜๋Š” deniedValues ์ค‘ ํ•˜๋‚˜๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‘˜ ๋‹ค ์ง€์ •ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์š”์ฒญ์„ ์‚ฌ์šฉํ•ด์„œ ํŒŒ์ผ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

gcloud resource-manager org-policies set-policy MY_POLICY.JSON --project=example-project

REST

setOrgPolicy API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ œ์•ฝ์กฐ๊ฑด์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•˜๋Š” allowedValue ๋ชฉ๋ก์˜ ์ธ์Šคํ„ด์Šค๋Š” ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜๋Š” deniedValues ๋ชฉ๋ก์„ ์ง€์ •ํ•˜์—ฌ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–์ง€ ๋ชปํ•˜๋„๋ก ๋ช…์‹œ์ ์œผ๋กœ ๊ธˆ์ง€ํ•  ์ธ์Šคํ„ด์Šค๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชฉ๋ก์— ์—†๋Š” ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋‘ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–๋„๋ก ์•”์‹œ์ ์œผ๋กœ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. allowedValues ๋˜๋Š” deniedValues ์ค‘ ํ•˜๋‚˜๋งŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‘˜ ๋‹ค ์ง€์ •ํ•  ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ์€ ํŠน์ • ์ธ์Šคํ„ด์Šค๊ฐ€ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋Š” compute.vmExternalIpAccess ์ œ์•ฝ ์กฐ๊ฑด์„ ํ”„๋กœ์ ํŠธ์— ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.

POST https://cloudresourcemanager.googleapis.com/v1/projects/PROJECT_ID:setOrgPolicy

PROJECT_ID๋ฅผ ์ด ์š”์ฒญ์˜ ํ”„๋กœ์ ํŠธ ID๋กœ ๋ฐ”๊พธ์„ธ์š”.

์š”์ฒญ ๋ณธ๋ฌธ์—๋Š” ์ด ์ œ์•ฝ์กฐ๊ฑด์˜ ์ •์ฑ…์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

{
  "policy": {
    "constraint": "constraints/compute.vmExternalIpAccess",
    "listPolicy": {
      "allowedValues": [
        "projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME"
      ]
    }
  }
}

์™ธ๋ถ€ IP ์ฃผ์†Œ ์ œํ•œ ๊ด€๋ จ ๊ถŒ์žฅ์‚ฌํ•ญ

  • ์ด ์ œ์•ฝ ์กฐ๊ฑด๊ณผ ํ•จ๊ป˜ deniedValues ๋ชฉ๋ก์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. deniedValues ๋ชฉ๋ก์— ๊ฐ’์„ ์ •์˜ํ•˜๋ฉด deniedValues ๋ชฉ๋ก์— ์žˆ๋Š” ์ธ์Šคํ„ด์Šค๋งŒ ์™ธ๋ถ€ IP ์ฃผ์†Œ ์‚ฌ์šฉ์ด ์ œํ•œ๋ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์ œ์–ดํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, ์ด ๋ฐฉ์‹์€ ๋ณด์•ˆ์ƒ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. allowedValues ๋ชฉ๋ก์—์„œ ํŠน์ • ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ญ์ œํ•˜๋ ค๋ฉด, ์ธ์Šคํ„ด์Šค๋ฅผ ํ•˜์œ„ ๊ณ„์ธต์˜ deniedValues ๋ชฉ๋ก์— ๋„ฃ๋Š” ๋Œ€์‹  allowedList์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ญ์ œํ•˜๋„๋ก ๊ธฐ์กด ์ •์ฑ…์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฆฌ์†Œ์Šค ๊ณ„์ธต์˜ ๋Œ€๋ถ€๋ถ„์— ์ ์šฉํ•  ์ •์ฑ…์„ ์„ค์ •ํ•˜๋˜ ํŠน์ • ํ”„๋กœ์ ํŠธ๋ฅผ ์ œ์™ธ์‹œํ‚ค๋ ค๋Š” ๊ฒฝ์šฐ ๊ธฐ๋ณธ ์ •์ฑ…์„ ๋ณต์›ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ ํ”„๋กœ์ ํŠธ์˜ ๋ชจ๋“  ์ธ์Šคํ„ด์Šค๊ฐ€ ์™ธ๋ถ€ IP ์ฃผ์†Œ์™€ ์—ฐ๊ฒฐ๋  ์ˆ˜ ์žˆ๋„๋ก restoreDefault ๊ฐ์ฒด๋ฅผ ์ง€์ •ํ•˜์—ฌ setOrgPolicy ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ํ˜„์žฌ ์ •์ฑ…์€ ๊ธฐ๋ณธ ์„ค์ •์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ํ™˜๊ฒฝ์„ ๋ณด๋‹ค ํšจ๊ณผ์ ์œผ๋กœ ์ œ์–ดํ•˜๋ ค๋ฉด ์กฐ์ง ์ •์ฑ…์„ IAM ์—ญํ• ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด ์ •์ฑ…์€ ์ธ์Šคํ„ด์Šค์—๋งŒ ์ ์šฉ๋˜์ง€๋งŒ, ๋„คํŠธ์›Œํฌ ๊ธฐ๊ธฐ์—์„œ ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์ œ์–ดํ•˜๊ณ  ์ œํ•œํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์ ์ ˆํ•œ ๋‹น์‚ฌ์ž์—๊ฒŒ compute.networkAdmin ์—ญํ• ์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ •์ฑ…์ด ์‚ฌ์šฉ ์„ค์ •๋œ ์ƒํƒœ๋กœ Compute Engine์—์„œ ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์กฐ์ง ๋˜๋Š” ํ”„๋กœ์ ํŠธ ๋‚ด์˜ ๋ชจ๋“  ์„œ๋น„์Šค ๋ฐ ์ œํ’ˆ์€ ์ด ์กฐ์ง ์ •์ฑ…์˜ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํŠนํžˆ Google Kubernetes Engine, Dataflow, Dataproc, Cloud SQL ๊ฐ™์€ ์„œ๋น„์Šค๊ฐ€ ์ด ์ •์ฑ…์˜ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฌธ์ œ๊ฐ€ ๋  ๊ฒฝ์šฐ์—๋Š” ์กฐ์ง ์ •์ฑ…์ด ์ ์šฉ๋˜์ง€ ์•Š๋Š” ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ ๋‹ค๋ฅธ ์„œ๋น„์Šค ๋ฐ ์ œํ’ˆ์„ ์„ค์ •ํ•˜๊ณ  ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๊ณต์œ  VPC๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ๊ด€๋ฆฌ

๋‹ค์Œ ์„น์…˜์—์„œ๋Š” ์ธ์Šคํ„ด์Šค์˜ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด๋ถ€ IP ์ฃผ์†Œ๊ฐ€ ์ž„์‹œ ์ฃผ์†Œ ๋˜๋Š” ๊ณ ์ • ์ฃผ์†Œ์ธ์ง€ ํ™•์ธ

๊ณ ์ • ๋ฐ ์ž„์‹œ ๋‚ด๋ถ€ IP ์ฃผ์†Œ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ๋ชจ์–‘๊ณผ ๋™์ž‘์ด ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ณ ์ • ๋‚ด๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๋‹ค์‹œ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ์—๋„ ๋™์ผํ•œ ๋ฆฌ์†Œ์Šค์— ๊ฐ™์€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ž„์‹œ IP ์ฃผ์†Œ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์ค‘์ง€ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•  ๋•Œ ํ•ด์ œ๋ฉ๋‹ˆ๋‹ค.

์ฃผ์†Œ๊ฐ€ ๊ณ ์ • ์ฃผ์†Œ ๋˜๋Š” ์ž„์‹œ ์ฃผ์†Œ์ธ์ง€ ํ™•์ธํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  1. Google Cloud ์ฝ˜์†”์—์„œ IP ์ฃผ์†Œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    IP ์ฃผ์†Œ๋กœ ์ด๋™

  2. ๋ชฉ๋ก์—์„œ ์ฃผ์†Œ๋ฅผ ์ฐพ๊ณ  ์œ ํ˜• ์—ด์—์„œ IP ์ฃผ์†Œ ์œ ํ˜•์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ• ๋‹น ํ•ด์ œ

IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹น ํ•ด์ œํ•˜๋ฉด ๋ฆฌ์†Œ์Šค์—์„œ ์‚ญ์ œ๋˜์ง€๋งŒ, IP ์ฃผ์†Œ๋ฅผ ์˜ˆ์•ฝ๋œ ์ƒํƒœ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹น ํ•ด์ œํ•˜๋ฉด IP ์ฃผ์†Œ๋ฅผ ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค์— ๋‹ค์‹œ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ ˆ์ฐจ๋Š” ์ด์ค‘ ์Šคํƒ ์ธ์Šคํ„ด์Šค์—๋Š” ์ง€์›๋˜์ง€๋งŒ IPv6 ์ „์šฉ ์ธ์Šคํ„ด์Šค์—๋Š” ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ธ์Šคํ„ด์Šค๋ฅผ ์‚ญ์ œํ•˜์—ฌ IPv4 ๋˜๋Š” IPv6 ์ฃผ์†Œ๋ฅผ ํ• ๋‹น ํ•ด์ œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ˜์†”

  1. Google Cloud ์ฝ˜์†”์—์„œ IP ์ฃผ์†Œ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

    IP ์ฃผ์†Œ๋กœ ์ด๋™

  2. ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

  3. ํ• ๋‹น ํ•ด์ œํ•˜๋ ค๋Š” ๊ณ ์ • IP ์ฃผ์†Œ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  4. ์ž‘์—… ๋ณด๊ธฐ๋ฅผ ํด๋ฆญํ•˜๊ณ  ๋‹ค๋ฅธ ๋ฆฌ์†Œ์Šค์— ์žฌํ• ๋‹น ์˜ต์…˜์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  5. ์—ฐ๊ฒฐ ๋Œ€์ƒ ๋“œ๋กญ๋‹ค์šด ๋ชฉ๋ก์—์„œ ์—†์Œ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

  6. ํ™•์ธ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

gcloud

  1. gcloud compute addresses list ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ ์ • IP ์ฃผ์†Œ๊ฐ€ ์‚ฌ์šฉ ์ค‘์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute addresses list
    

    ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.

    NAME                      REGION    ADDRESS                  STATUS
    example-address-ipv4      REGION    198.51.100.1             RESERVED
    example-address-new-ipv4  REGION    203.0.113.1              IN_USE
    example-address-ipv6      REGION    2001:db8:1:1:1:1:1:1     RESERVED
    example-address-new-ipv6  REGION    2001:db8:4:4:4:4:4:4     IN_USE
    
    • IP ์ฃผ์†Œ๊ฐ€ ์‚ฌ์šฉ ์ค‘์ด ์•„๋‹ˆ๋ฉด ์ƒํƒœ๋Š” RESERVED์ž…๋‹ˆ๋‹ค.
    • IP ์ฃผ์†Œ๊ฐ€ ์‚ฌ์šฉ ์ค‘์ด๋ฉด ์ƒํƒœ๋Š” IN_USE์ž…๋‹ˆ๋‹ค.
  2. IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธ์Šคํ„ด์Šค์˜ ์ด๋ฆ„์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute addresses describe ADDRESS_NAME \
      --region=REGION
    

    ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • ADDRESS_NAME: IPv6 ์ฃผ์†Œ ๋ฆฌ์†Œ์Šค์˜ ์ด๋ฆ„
    • REGION: IPv6 ์ฃผ์†Œ ๋ฆฌ์†Œ์Šค์˜ ๋ฆฌ์ „

    ์ถœ๋ ฅ์€ ๋‹ค์Œ๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.

    address: IP_ADDRESS
    addressType: EXTERNAL
    ...
    region: https://www.googleapis.com/compute/v1/projects/PROJECT/regions/REGION
    selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT/regions/REGION/addresses/ADDRESS_NAME
    status: IN_USE
    subnetwork: https://www.googleapis.com/compute/v1/projects/PROJECT/regions/REGION/subnetworks/SUBNET
    users:
    - https://www.googleapis.com/compute/v1/projects/PROJECT/zones/ZONE/instances/INSTANCE_NAME
    

    users ํ•„๋“œ์— IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธ์Šคํ„ด์Šค์˜ ์ด๋ฆ„์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

  3. ์ธ์Šคํ„ด์Šค์—์„œ IP ์ฃผ์†Œ๋ฅผ ํ• ๋‹น ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

    • IPv4 ์ฃผ์†Œ๋ฅผ ํ• ๋‹น ํ•ด์ œํ•˜๋ ค๋ฉด ์ธ์Šคํ„ด์Šค ์•ก์„ธ์Šค ๊ตฌ์„ฑ ํŒŒ์ผ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

      1. ์‚ญ์ œํ•˜๋ ค๋Š” ์•ก์„ธ์Šค ๊ตฌ์„ฑ์˜ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ค๋ ค๋ฉด gcloud compute instances describe ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. INSTANCE_NAME์„ ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

        gcloud compute instances describe INSTANCE_NAME
        

        ์•ก์„ธ์Šค ๊ตฌ์„ฑ์€ ๋‹ค์Œ ํ˜•์‹์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

        networkInterfaces:
          - accessConfigs:
            - kind: compute#accessConfig
              name: external-nat
              natIP: 203.0.113.1
              type: ONE_TO_ONE_NAT
        
      2. gcloud compute instances delete-access-config ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ก์„ธ์Šค ๊ตฌ์„ฑ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

        gcloud compute instances delete-access-config INSTANCE_NAME \
          --access-config-name="ACCESS_CONFIG_NAME"
        

        ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

        • INSTANCE_NAME: ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
        • ACCESS_CONFIG_NAME: ์‚ญ์ œํ•  ์•ก์„ธ์Šค ๊ตฌ์„ฑ์˜ ์ด๋ฆ„. ๋”ฐ์˜ดํ‘œ ์‚ฌ์ด์— ์ „์ฒด ์ด๋ฆ„์„ ํฌํ•จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • IPv6 ์ฃผ์†Œ ๋ฒ”์œ„๋ฅผ ํ• ๋‹น ํ•ด์ œํ•˜๋ ค๋ฉด instance network-interfaces update ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

      gcloud compute instances network-interfaces update INSTANCE_NAME \
        --network-interface=nic0 \
        --stack-type=IPV4_ONLY \
        --zone=ZONE
      

      ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

      • INSTANCE_NAME: IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์ธ์Šคํ„ด์Šค์˜ ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.
      • ZONE: ์ธ์Šคํ„ด์Šค์˜ ์˜์—ญ์ž…๋‹ˆ๋‹ค.
  4. ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  IN_USE ๋Œ€์‹  RESERVED๋กœ ํ‘œ์‹œ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    gcloud compute addresses list \
      --filter="ADDRESS_NAME AND region=REGION"
    

    ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

    • ADDRESS_NAME: IP ์ฃผ์†Œ ๋ฆฌ์†Œ์Šค์˜ ์ด๋ฆ„
    • REGION: IP ์ฃผ์†Œ ๋ฆฌ์†Œ์Šค์˜ ๋ฆฌ์ „

์ด์ œ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ด๋ฅผ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค์— ํ• ๋‹นํ•˜๋„๋ก ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

REST

๊ณ ์ • ์™ธ๋ถ€ IPv4 ๋˜๋Š” IPv6 ์ฃผ์†Œ๋ฅผ ํ• ๋‹น ํ•ด์ œํ•˜๋ ค๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • IPv4 ์ฃผ์†Œ์˜ ๊ฒฝ์šฐ ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ธ์Šคํ„ด์Šค์— ์—ฐ๊ฒฐ๋œ ์•ก์„ธ์Šค ๊ตฌ์„ฑ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

    1. ์ธ์Šคํ„ด์Šค์˜ ์•ก์„ธ์Šค ๊ตฌ์„ฑ ์„ธ๋ถ€์ •๋ณด๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด instances.get ๋ฉ”์„œ๋“œ์— GET ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”.

      GET https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME
      
    2. instances.deleteAccessConfig ๋ฉ”์„œ๋“œ์— POST ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ธฐ์กด ์•ก์„ธ์Šค ๊ตฌ์„ฑ์„ ์‚ญ์ œํ•˜์„ธ์š”.

      POST https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/deleteAccessConfig
      

      ๋‹ค์Œ์„ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

      • PROJECT_ID: ์ด ์š”์ฒญ์˜ ํ”„๋กœ์ ํŠธ ID์ž…๋‹ˆ๋‹ค.
      • ZONE: ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ๋Š” ์˜์—ญ
      • INSTANCE_NAME: ์ธ์Šคํ„ด์Šค ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.
  • IPv6 ์ฃผ์†Œ์˜ ๊ฒฝ์šฐ IPv6 ์ฃผ์†Œ๊ฐ€ ์—ฐ๊ฒฐ๋œ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ๋„คํŠธ์›Œํฌ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์Šคํƒ ์œ ํ˜•์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

    1. instances.updateNetworkInterface ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด PATCH ์š”์ฒญ์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    2. ์š”์ฒญ ๋ณธ๋ฌธ์—์„œ stackType ํ•„๋“œ ๊ฐ’์„ IPV4_ONLY๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

      ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

      PATCH https://compute.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/INSTANCE_NAME/updateNetworkInterface
      
      {
        "networkInterfaces": [{
          ...
          "stackType" : "IPV4_ONLY"
          ...
          }]
      }
      

์ž๋ฐ”


import com.google.cloud.compute.v1.AccessConfig;
import com.google.cloud.compute.v1.AccessConfig.Type;
import com.google.cloud.compute.v1.Instance;
import com.google.cloud.compute.v1.InstancesClient;
import com.google.cloud.compute.v1.NetworkInterface;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class UnassignStaticIpAddress {

  public static void main(String[] args)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // TODO(developer): Replace these variables before running the sample.
    // Project ID or project number of the Google Cloud project you want to use.
    String projectId = "your-project-id";
    // Instance ID of the Google Cloud project you want to use.
    String instanceId = "your-instance-id";
    // Name of the zone to create the instance in. For example: "us-west3-b"
    String zone = "your-zone";
    // Name of the network interface to assign.
    String netInterfaceName = "your-netInterfaceName";

    unassignStaticIpAddress(projectId, instanceId, zone, netInterfaceName);
  }

  public static Instance unassignStaticIpAddress(String projectId, String instanceId,
                                                 String zone, String netInterfaceName)
          throws IOException, ExecutionException, InterruptedException, TimeoutException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests.
    try (InstancesClient client = InstancesClient.create()) {
      Instance instance = client.get(projectId, zone, instanceId);
      NetworkInterface networkInterface = null;
      for (NetworkInterface netIterface : instance.getNetworkInterfacesList()) {
        if (netIterface.getName().equals(netInterfaceName)) {
          networkInterface = netIterface;
          break;
        }
      }

      if (networkInterface == null) {
        throw new IllegalArgumentException(
                String.format(
                        "No '{network_interface_name}' variable found on instance %s.",
                        instanceId)
        );
      }

      AccessConfig accessConfig = null;
      for (AccessConfig config : networkInterface.getAccessConfigsList()) {
        if (config.getType().equals(Type.ONE_TO_ONE_NAT.name())) {
          accessConfig = config;
          break;
        }
      }

      if (accessConfig != null) {
        // Delete the existing access configuration first
        client.deleteAccessConfigAsync(projectId, zone, instanceId,
                        accessConfig.getName(), netInterfaceName).get(30, TimeUnit.SECONDS);
      }

      // return updated instance
      return client.get(projectId, zone, instanceId);
    }
  }
}

Python

import uuid

from google.cloud.compute_v1 import InstancesClient
from google.cloud.compute_v1.types import DeleteAccessConfigInstanceRequest


def unassign_static_ip_from_existing_vm(
    project_id: str,
    zone: str,
    instance_name: str,
    network_interface_name: str = "nic0",
):
    """
    Updates access configuration for a VM instance to unassign a static external IP.
    VM (and IP address in case of static IP assigned) must be created before calling this function.

    Args:
        project_id (str): Project ID.
        zone (str): Zone where the VM is located.
        instance_name (str): Name of the VM instance.
        network_interface_name (str): Name of the network interface to unassign.
    """
    client = InstancesClient()
    instance = client.get(project=project_id, zone=zone, instance=instance_name)
    network_interface = next(
        (ni for ni in instance.network_interfaces if ni.name == network_interface_name),
        None,
    )

    if network_interface is None:
        raise ValueError(
            f"No network interface named '{network_interface_name}' found on instance {instance_name}."
        )

    access_config = next(
        (ac for ac in network_interface.access_configs if ac.type_ == "ONE_TO_ONE_NAT"),
        None,
    )

    if access_config:
        # Delete the existing access configuration
        delete_request = DeleteAccessConfigInstanceRequest(
            project=project_id,
            zone=zone,
            instance=instance_name,
            access_config=access_config.name,
            network_interface=network_interface_name,
            request_id=str(uuid.uuid4()),
        )
        delete_operation = client.delete_access_config(delete_request)
        delete_operation.result()

    updated_instance = client.get(project=project_id, zone=zone, instance=instance_name)
    return updated_instance

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ•ด์ œ

๊ณ ์ • ์™ธ๋ถ€ IPv4 ๋˜๋Š” IPv6 ์ฃผ์†Œ๊ฐ€ ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉด IP ์ฃผ์†Œ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•˜์—ฌ IP ์ฃผ์†Œ๋ฅผ ํ•ด์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ญ์ œํ•ด๋„ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๊ฐ€ ์ž๋™์œผ๋กœ ํ•ด์ œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์€ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋Š” ์ˆ˜๋™์œผ๋กœ ํ•ด์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ๋ฅผ ํ•ด์ œํ•˜๋ ค๋ฉด VPC ๋ฌธ์„œ์˜ ๊ณ ์ • ์™ธ๋ถ€ IP ์ฃผ์†Œ ํ•ด์ œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๋‹ค์Œ ๋‹จ๊ณ„