GW LABS

Google Cloud StudyJam (4) - Deployment Manager 본문

Infrastructure/Cloud Computing

Google Cloud StudyJam (4) - Deployment Manager

GeonWoo Kim 2020. 12. 9. 12:55

Google Cloud StudyJam

이번 포스팅에서는 GCP Deployment Manager에 대해 알아본다. GCP를 사용하면서 Cloud Console 화면만을 이용해서 개발을 진행한다고 가정해보자. 매번 VM 인스턴스를 생성할 때마다 네비게이션 메뉴에서 Compute Engine을 찾고, 거기에서 VM instances란을 클릭한다. 그리고 create 버튼을 클릭에서 정보를 입력하고 생성한다. 클라우드에 대한 지식이 없는 상태에서는 이렇게 접근하는 것이 안전해보일 수 있지만, 익숙해진 상태에서는 너무 지루하고 비효율적이다.

 

Cloud Shell을 사용한다면 조금은 편해진다. 인스턴스 생성명령어를 미리 메모장에 작성해두고 설정을 바꿔야한다면 명령어를 수정해서 다시 실행하면 된다. 그러나 매번 변경이 일어날때마다 이런 작업을 해야한다면 명령어들을 모두 기억해야하고, 실수의 가능성도 있다. 해결방법이 없을까?


Deployment Manager

Google Cloud Deployment Manager는 이런 문제를 해결해주는 서비스이다. 미리 구성 파일에 생성해야하거나 수정해야하는 리소스들을 작성해두고 이 구성 파일에 따라 리소스를 배포하는 것이다. 이렇게 관리한다면 클라우드 리소스에 대한 수정이 훨씬 편해지고 구성 파일의 수정에 대해 버전관리도 할 수 있기 때문에 이슈가 발생했을 때 훨씬 유연하게 대응할 수 있다. 즉 "Infrastructure as Code(IaC)"가 가능해진다. 파이썬 파일을 통해서 동적으로 구성을 변경해주는 방법도 가능하다. 큰 규모의 클라우드 프로젝트를 다뤄야할 때에는 꼭 필요한 기능이다.

 

구성 파일의 구조

resources:
- name: example
  type: compute.v1.instance
  properties:
    zone: us-central1-a
    machineType: zones/us-central1-a/machineTypes/n1-standard-1
    disks:
    - deviceName: boot
      type: PERSISTENT
      boot: true
      autoDelete: true
      initializeParams:
        sourceImage: projects/debian-cloud/global/images/family/debian-9
    networkInterfaces:
    - network: global/networks/default

Deployment Manager의 기본 구성파일은 .yaml 파일로 위와 같은 구조를 갖고 있다. 구성 파일은 반드시 resources 항목을 갖고 있어야하며, 각각의 resources들은 name, type, properties가 포함되어 있어야한다. 잘 살펴보면 GCP에서 인스턴스를 생성할 때 설정해야하는 속성들을 파일로 작성했다는 것을 알 수 있다. 

관리하려고 하는 자원이 여러 개이고 설정해야줘야 하는 속성들이 너무 많아 한 파일에 관리할 수 없을 때에는 여러 개의 파일로 나누어서 관리도 가능하다. 구성파일 .yaml 파일에 파이썬 파일 템플릿이나 .jinja 파일 템플릿을 포함하여 관리가 가능하다. 어떤식으로 Deployment Manager를 활용할 수 있을지 예제를 통해서 알아보자.

 

Deployment Manager 예제

Deployment Manager를 통해서 구현할 아키텍처

GCP 둘러보기 포스팅에서 위와 같은 아키텍처를 직접 만들었었다. 이번에는 Deployment Manager를 통해서 위와 같은 아키텍처를 생성하려고 한다. Deployment Manager 파일들은 Github 링크를 통해서 볼 수 있다. 달라지는 점이 있다면 VM 인스턴스 그룹을 생성해서 로드밸런서에 붙인다는 점과 로드밸런서를 L7 타입으로 사용한다는 점이다. 또한 인스턴스 그룹으로 인스턴스들을 관리하면 오토스케일링 기능을 사용할 수 있는데 오토스케일링 기능도 인스턴스 그룹에 붙여줬다.

https://github.com/youlive789/gcp-deployment-manager-example

 

youlive789/gcp-deployment-manager-example

sample projects for practice gcp deployment manager - youlive789/gcp-deployment-manager-example

github.com

 

 

1. 네트워크 생성 템플릿

resources:
- name: {{env["name"]}}
  type: compute.v1.network
  properties:
    autoCreateSubnetworks: true

default 네트워크를 생성해서 사용해도 되지만, 구성 파일간의 의존성을 쉽게 다루기 위해서는 템플릿을 통해 생성하고 참조하는 방식으로 구성하는게 좋다. github 저장소의 autonetwork-template.jinja 파일은 default 네트워크와 동일한 자동으로 서브넷을 생성하는 VPC 네트워크를 생성해준다. "{{}}"안에는 리소스를 생성할 때 main.yaml 파일에서 정의한 속성들을 가져와서 사용하는 일종의 참조 문법이다.

 

2. 인스턴스 방화벽 규칙 생성 템플릿

resources:
- name: {{ env["name"] }}
  type: compute.v1.firewall
  properties:
    network: {{ properties["network"] }}
    sourceRanges: ["0.0.0.0/0"]
    targetTags: {{ properties["targetTags"] }}
    allowed:
    - IPProtocol: {{ properties["IPProtocol"] }}
      ports: {{ properties["Port"] }}

인스턴스에 적용할 방화벽 규칙을 생성하기 위한 템플릿이다. github 저장소의 firewall-template.jinja이며, 후에 main.yaml에서 정의한 network, tag 등을 받아 방화벽 규칙을 생성한다. 또한 인스턴스 템플릿에서 이 방화벽 규칙을 참조해야한다.

 

3. 인스턴스 템플릿 생성 템플릿

resources:
- name: {{ env["name"] }}
  type: compute.v1.instanceTemplate
  properties:
    properties:
      description: apache
      tags:
        items:
          - {{ properties["tags"] }}
      machineType: f1-micro
      canIpForward: false
      disks:
      - deviceName: boot
        type: PERSISTENT
        boot: true
        autoDelete: true
        initializeParams:
          sourceImage: projects/debian-cloud/global/images/family/debian-9
      networkInterfaces:
      - network: {{ properties["network"] }}
        accessConfigs:
        - name: External NAT
          type: ONE_TO_ONE_NAT
      scheduling:
        onHostMaintenance: MIGRATE
        automaticRestart: true
      serviceAccounts:
        - email: default
          scopes:
          - https://www.googleapis.com/auth/compute.readonly
          - https://www.googleapis.com/auth/devstorage.read_only
          - https://www.googleapis.com/auth/service.management.readonly
      metadata:
        items:
        - key: startup-script
          value: |
            #! /bin/bash
            sudo apt-get update
            sudo apt-get install apache2 -y
            sudo service apache2 restart
            echo '<!doctype html><html><body><h1>'$(hostname)'</h1></body></html>' | tee /var/www/html/index.html

VM 인스턴스 템플릿을 생성해주는 구성파일 템플릿이다. github 저장소의 webserver-template.jinja 파일이며 생성할 인스턴스들의 기본적인 설정들을 템플릿에 구성한다. 이 인스턴스 템플릿을 인스턴스 그룹을 생성하는 템플릿이 참조하게 된다. 또 startup-script로 아파치를 설치하고 해당 머신의 인스턴스 이름을 출력하도록 구성했다. 이후에 로드밸런서로 접근하게되면 어떤 인스턴스에 접근했는지 알 수 있다.

 

4. 인스턴스 그룹 생성 템플릿

resources:
- name: {{ env["name"] }}
  type: compute.v1.instanceGroupManagers
  properties:
    baseInstanceName: {{ properties["baseInstanceName"] }}
    instanceTemplate: {{ properties["instanceTemplate"] }}
    targetSize: {{ properties["targetSize"] }}
    zone: us-central1-a

github 저장소의 webserver-ig-template.jinja 파일은 이전에 정의한 인스턴스 템플릿을 참조하여 생성한다. 존은 기본 구성으로 us-central1-a에 생성하도록 구성했다. 

 

5. 인스턴스 오토스케일러 생성 템플릿

resources:
- name: {{ env["name"] }}
  type: compute.v1.autoscaler
  properties:
    zone: us-central1-a
    target: {{ properties["target"] }}
    autoscalingPolicy:
      maxNumReplicas: 5

github 저장소의 webserver-as-template.jinja 파일은 인스턴스 그룹에 참조되면서 오토스케일링 기능을 추가해준다. 네트워크 타겟을 지정해줘야하며 얼마나 많은 인스턴스를 생성해줄 것인지, 최소 인스턴스는 얼마나 될 지 지정해 줄 수 있다. 

 

6. 로드밸런서 생성 템플릿

resources:
- name: health-check-{{ env["name"] }}
  type: gcp-types/compute-v1:httpHealthChecks
  properties:
    port: 80
    requestPath: /

- name: lb-{{ env["name"] }}
  type: gcp-types/compute-v1:backendServices
  properties:
    healthChecks:
      - $(ref.health-check-{{ env["name"] }}.selfLink)
    port: 80
    portName: http
    protocol: HTTP
    backends:
    - name: lb-backend-{{ env["name"] }}
      balancingMode: UTILIZATION
      group: {{ properties["instanceGroups"] }}

- name: apache-url-map    
  type: compute.v1.urlMap
  properties:
    defaultService: $(ref.lb-{{ env["name"] }}.selfLink)

- name: apache-http-proxy
  type: compute.v1.targetHttpProxy
  properties:
    urlMap: $(ref.apache-url-map.selfLink)

- name: apache-ipaddress
  type: compute.v1.globalAddress

- name: apache-http-forwardingrule
  type: compute.v1.globalForwardingRule
  properties:
    target: $(ref.apache-http-proxy.selfLink)
    IPAddress: $(ref.apache-ipaddress.address)
    IPProtocol: TCP
    portRange: 80-80

로드 밸런서를 생성할 때에는 health-check, backedService, urlMap, proxy, 고정 IP, forwardingrule을 생성해줘야 한다. 이 모든 리소스들이 로드 밸런서를 생성하기 위한 것들이므로 파일을 분리시키지 않고 loadbalancer-template.jinja 파일에 정의했다. 어려워보이지만 클라우드 콘솔화면에서 로드밸런서를 생성하기 위한 입력값들을 생각해보면 쉽게 이해할 수 있을 것이다.

 

7. 구성 파일

imports:
- path: autonetwork-template.jinja
- path: firewall-template.jinja
- path: webserver-template.jinja
- path: webserver-ig-template.jinja
- path: webserver-as-template.jinja
- path: loadbalancer-template.jinja

resources:
- name: webserver-network
  type: autonetwork-template.jinja

- name: webserver-firewall
  type: firewall-template.jinja
  properties:
    network: $(ref.webserver-network.selfLink)
    IPProtocol: TCP
    Port: [22, 80]
    targetTags: ["webserver"]

- name: webserver-template
  type: webserver-template.jinja
  properties:
      tags: webserver
      network: $(ref.webserver-network.selfLink)

- name: webserver-ig
  type: webserver-ig-template.jinja
  properties:
    baseInstanceName: webserver
    instanceTemplate: $(ref.webserver-template.selfLink)
    targetSize: 2

- name: webserver-as
  type: webserver-as-template.jinja
  properties:
    target: $(ref.webserver-ig.selfLink)

- name: webserver-lb
  type: loadbalancer-template.jinja
  properties:
    instanceGroups: $(ref.webserver-ig.instanceGroup)

마지막으로 구성파일을 위와 같이 정의한다. $(ref.[자원이름].[내부속성]) 식으로 자원들을 참조할 수 있다. 위와 같이 템플릿 파일과 구성파일인 .yaml 파일을 준비하면 deployment manager를 사용할 수 있다.

 

 

Deployment manager로 배포하기

우선 github에서 위의 저장소 파일들을 GCP shell에서 clone 받아야 한다. 이후 아래와 같은 명령어를 통해 정의한 리소스들을 배포시킬 수 있다.

 

gcloud deployment-manager deployments create sample-project --config main.yaml

 

배포가 잘못되어 삭제해야한다면 delete 명령어를 실행시키면 된다.

 

gcloud deployment-manager deployments delete sample-project

 

create 명령으로 배포가 완료되면 네비게이션 메뉴 Tools에 있는 Depolyment Manager 대시보드에 우리가 생성한 deploy를 확인할 수 있다.

 

Deploy가 생성된 모습

 

Deployment에 사용된 파일들

 

로드 밸런서가 고정 IP를 할당받고 생성되더라고 작동하기까지 시간이 걸릴 수 있다. 이 문제 때문에 계속 배포가 잘못된지 알고 디버깅을 했었는데 5분정도 기다리면 로드 밸런서와 인스턴스들이 정상작동하는 모습을 볼 수 있다.

 

로드밸런서의 고정아이피는 Frontends 란에서 확인할 수 있다.

 

로드밸런서의 고정아피를 통해 인스턴스에 접근하는 모습. 번갈아가며 인스턴스에 접근한다.

 

 

위와 같이 Deployment Manager를 통해 클라우드 리소스들을 정의하고 배포하는 과정까지 알아봤다. GCP에서 IaC는 Deployment Manager로 가능하며, 규모가 큰 시스템일수록 코드를 통해 시스템을 정의하는 것이 관리/운영 측면에서 더 효율적일 것이다.

 

 

 

Reference

 - https://github.com/sveronneau/gcp-dm/blob/master/instance-template-mig.yaml

 - https://github.com/krishan03/gcp-deployment-manager-networks-firewalls-vms/blob/master/config.yaml

Comments