빠르게 훑어보는 구글 클라우드 플랫폼

나온지는 조금 되었지만, 방금 받아본 책

일부지만 열심히 작성했던 구글 클라우드 플랫폼 가이드가 E-Book으로 나오고 종이책(주문형)으로도 나왔습니다.

간단하게 Google Cloud Platform 입문 또는 사용하시는 분들에게 도움이 되시길.

E북은 무료고 종이책은 유료(인세를 포함한 관련 수익금은 전액 사회 기부)입니다. 

2권도 조만간 만들어질 거 같네요.


빠르게 훑어보는 구글 클라우드 플랫폼 - 무료 E-Book 링크

http://www.hanbit.co.kr/realtime/books/book_view.html?p_code=E5359426070#hanbit_network




'일상' 카테고리의 다른 글

생각의 전환  (0) 2017.03.08

In-memory query execution in Google BigQuery

 

빅쿼리의 In-memory query 실행

 

최유석

원글 주소 : https://cloud.google.com/blog/big-data/2016/08/in-memory-query-execution-in-google-bigquery

원글 작성자 : Hossein Ahmadi, BigQuery Technical Lead

 

개요

빅쿼리는 대규모의 데이터에 대해서 실시간에 가까운 쿼리실행 속도를 제공한다. 빅쿼리는 높은 성능을 제공하기 위해서 모든 연산이 메모리에서 이루어진다. 이러한 쿼리 실행 속도의 배경에는 빅쿼리의 심플한 아키텍쳐 구조와, 빠른 쿼리 실행이 가능하게 하는 메모리 기반의 연산, 그리고 페타바이트 급의 분석이 가능하게 하는 확장성 있는 데이터의 재분할(repartitioning), 셔플(shuffle) 기능이 있다. 이 글에서는 빅쿼리의 셔플(shuffle)에 대해서 자세히 알아보고, 구글의 페타비트급(petabit-scale) 네트워킹 기술(Jupiter)을 활용해 어떻게 높은 성능으로 메모리상에서 쿼리 실행을 가능하게 하는지 알아보고자 한다.

 

구글의 빅데이터 분석

시작하기에 앞서 구글의 경우, 구글의 수많은 서비스들(YouTube, Gmail. Search,등) 각각의 이용자들만 해도 수억 명에 이른다. 따라서 자연스럽게 구글 내부적으로 빅데이터를 분석하기 위한 기술들이 개발되고 사용되어 왔다. 구글은 오픈소스 플랫폼을 지향하는 모습으로 빅데이터를 포함한 여러 기술들의 논문을 공개해왔다. 몇가지 사례를 보면, Apache Hadoop의 근간이 되는 GFS와 MapReduce, Apache HBase의 근간이 되는 Big Table등이 있으며, BigQuery는 2010년 문서로 공개된 Dremel이라는 기술을 근간으로 한다.

빅쿼리의 성능과 인프라

빅쿼리의 쿼리 실행의 대한 내용을 알아보기에 앞서, 먼저 예제를 통해 빅쿼리의 성능과 인프라에 관련한 부분을 알아보도록 하자.

예제로 보는 빅쿼리의 성능

빅쿼리의 쿼리 실행속도, 즉 성능을 보기 위한 사례로 다음의 예제가 많이 사용된다.

(출처: https://cloud.google.com/blog/big-data/2016/01/anatomy-of-a-bigquery-query )

 

빅쿼리에서 제공하는 공개 데이터 셋에 저장 되어있는 위키피디아 페이지의 제목, 뷰수, 등의 정보가 저장된 테이블에서 1000억(100 billion record)개의 레코드를 스캔하고 제목(title)컬럼에서 정규표현식(regular expression)과 3개의 wildcard를 사용해서 해당하는 문자열("G.*o.*o.*g")을 검색한 결과를 가지고 해당 제목(title)을 가진 페이지의 뷰(views) 수를 카운트하고 각각의 언어별로 그룹으로 묶고 내림차순으로 정렬해서 결과를 보여주는 예제이다.

 

위의 예제에서 쿼리가 실행된 시간은 24.7초가 소요되었으나, 항상 동일한 속도로 실행되지는 않는다. 하지만 직접 실행해서 확인하더라도 동일한 쿼리에 대해서 약 30초 이내에 실행이 되는 것을 확인 할 수 있다.

 

예제로 보는 빅쿼리의 인프라

이제 앞의 예제가 실행되는 동안, 빅쿼리 내부적으로는 사용된 인프라에 대해서 알아보도록 하자. 먼저 위의 쿼리가 실행되는 약 30초 동안 약 4TB의 데이터를 처리하게 된다. 이때 사용되는 빅쿼리 인프라에 대한 대략적인 수치는

이 사용되고 위의 예제의 쿼리를 실행하는데 약 $20 정도의 비용이 발생한다. 위와 같은 쿼리실행 및 인프라 사용을 가능하게 하는 것은 빅쿼리가 방대한 규모의 인프라를 공유하는 멀티 테넌트(multitenancy)서비스이기 때문이다.

빅쿼리의 심플한 사용

일반적인 관계형 데이터베이스(RDBMS) 또는 여러 빅데이터 솔루션을 사용하더라도 위의 예제 분량의 쿼리실행을 하기 위해서는 해당 솔루션에 대한 이해와 설치, 분석에 필요한 코드실행이 필요하고, 또한 제대로 실행하기 위해서 끊임없는 튜닝과 모니터링을 포함한 유지보수가 필요하다. 하지만 빅쿼리의 경우 표준 ANSI SQL과 유사한 SQL(표준 ANSI SQL은 현재 베타로 지원)을 사용하여 쿼리를 입력하고 쿼리 실행버튼인 RUN QUERY만 클릭하면 자동적으로 빅쿼리 내부적으로 위와 비슷하거나, 더 많은 규모의 인프라를 사용하여 실행된 쿼리의 결과를 볼 수 있다.

 

빅쿼리 실행엔진(기본 아키텍쳐)

구글 클라우드 플랫폼(Google Cloud Platform)에서 서비스되고 있는 빅쿼리는 앞서 언급한 Dramel뿐만아니라 구글의 자체적인 기술들인 Borg, Colossus, Jupiter가 융합되어 놀라운 성능을 만들어낸다. 그렇다면 이와 같은 기술들이 어떤 구조로 동작하는지 알아보도록 하자.

 

빅쿼리의 기본 구조

(출처 : https://cloud.google.com/blog/big-data/2016/01/bigquery-under-the-hood )

Dremel

빅쿼리에서 요청이 들어오면 분산 스토리지인 Colossus에서 데이터를 읽고

그 해당 데이터를 페타비트(Petabit)급 네트워크인 Jupiter를 통해 컴퓨팅 처리 계층인 Dremel로 전달한다. 이 때, 데이터를 전달 받은 Dremel에서는 디스크 없이 컴퓨팅 처리가 이루어 진다. Dremel에서는 Leaf Nodes(slots), Mixers, Root server계층으로 나눠지고, Leaf Nodes (slots)에서 필요한 모든 계산을 수행하고, 앞의 예제 기준으로는 Colossus에서 읽은 1000억개의 각각의 레코드에 대한 정규표현식 체크를 하는 것이 이 계층(slots)이다. 그 다음 Leaf Nodes (slots)에서 처리된 데이터에 대해서 Mixer에서 aggregation(집계) 작업을 수행한다. 마지막으로 Mixer에서 집계된 데이터에 대한 정렬 등의 작업을 처리 하고 결과를 리턴 한다.

이렇게 데이터를 처리하는 단계에서 셔플(shuffle)작업이 이루어지며, Jupiter를 통해 빠른 속도로 데이터의 이동이 가능하게 한다. 또한 Dremel, Colossus, Jupiter의 리소스는 Borg를 통해 클러스터로 관리되고 동작한다.

 

 

Colossus

GFS(Google File System)의 후속 버전인 분산 파일 시스템으로 구글 데이터 센터에서 Colossus 클러스터를 가지고 있으며, 한번에 모든 빅쿼리 사용자의 요청에 대해 쿼리 실행 시 수천개의 디스크를 제공할 수 있도록 되어있다. 또한 콜로서스에 저장되는 모든 빅쿼리의 데이터는 자동으로 여러 데이터 센터에 분산 및 복제(replication)되어 저장되기 때문에 높은 안정성을 제공한다. Colossus를 통해 빅쿼리는 In-memory 데이터베이스와 유사한 성능을 보이지만, 저렴한 가격, 높은 병렬성, 확장성, 내구성을 가진 인프라이기 때문에 활용가치가 높다.

빅쿼리는 콜로서스에 구조화된 데이터에 대한 컬럼(Column) 기반 저장형식과 압축 알고리즘을 활용해서 데이터를 저장한다. 이를 통해 빠른 쿼리 실행을 가능하게 하며, 높은 비용을 들이지 않고도 데이터에 대한 저장을 할 수 있다.

Borg

구글의 대규모의 클러스터 관리시스템으로 구글의 서비스들에 사용되는 자원(CPU, RAM, disk, network)을 관리하고 할당하는 역할을 하며, 빅쿼리에서도 쿼리실행,등의 작업요청이 들어오면 미리 예약한 자원을 기반으로 필요한 자원을 할당해서 해당 작업의 실행을 가능하게 한다. 위의 예제처럼 쿼리가 실행 될 때, Dremel클러스터에 수천개의 CPU를 제공하는 것도 Borg의 역할이다. 또한 서버를 포함해서 전원, 네트워크에 이르기까지 수많은 오류에 대한 보호를 하고 관리를 하기 때문에 사용자 입장에서는 발생하는 문제를 개의치 않고 이용 할 수 있다.

 

Jupiter

대규모의 데이터를 원활하게 처리하려면 그에 걸맞는 네트워크도 필수로 필요하다. 구글이 클라우드 플랫폼을 통해 구축하여 제공하는 네트워크(Jupiter)는 양방향 1 Petabit/sec의 대역폭을 제공한다. 10만VM이 각각 10Gb로 통신할 수 있는 속도이다. 이렇듯 상상이상의 대역폭을 자랑하는 Jupiter를 통해 모든 쿼리에 대해서 데이터가 저장된 스토리지(Colossus)에 직접 접근해서 수초만에 테라바이트(terabytes)의 데이터를 읽을 수 있다.

빅쿼리 셔플(Shuffle)의 변화

하둡(Hadoop), 스파크(Spark), 구글 데이터 플로우(Google Cloud Dataflow)에 이르기까지 모든 분산 데이터 처리 시스템에서 셔플은 핵심요소로 작용한다. 데이터 처리 중간의 셔플단계는 크고 복잡한 조인, 집계 및 분석 작업의 실행을 위해 필요하다. 빅쿼리의 셔플은 쿼리 특성과 요구사항의 증가로 인한 셔플 처리 단계의 개선 요구로 인해, 2014년 메모리 기반(디스크 스풀링 지원) 및 구글의 데이터 센터에서 네트워크 기술(Jupiter)로 특별하게 설계되었고 새롭게 개발된 인프라로 이전되었다. 게다가, 특정한 분산 작업을 넘어선 활용사례(예를 들면, 해시조인)와 유연한 데이터 전송 시스템으로 설계되었다. 이 프로젝트는 데이터 전송 기술에 다년간의 연구 및 개발 노력의 산물이다.

빅쿼리 셔플의 차이점

빅쿼리의 셔플은 전용된 호스팅 원격 메모리의 노드 집합에 쿼리 처리의 다양한 단계에서 생산되는 중간 데이터를 셔플링해서 저장한다. 스파크(Spark), 피콜로(Piccolo) 등의 많은 시스템에서 일반적으로 데이터를 처리 할 때 중간 데이터 결과를 지속하여 저장한다. 그러나 빅쿼리는 셔플 작업에서 긴밀한 통합으로 메모리에서 처리된 중간 결과에 대해 다른 방향을 보인다.

 

빅쿼리 셔플의 구성요소

빅쿼리의 셔플 구성은 3가지의 컴포넌트로 구성된다.

빅쿼리 셔플의 구성요소

 

셔플에서 Producer, Consumer, Controller는 다음과 같이 구현되어 있다.

Producer (producer_id) {
void SendRow(row, consumer_id) : Called to send a row to a given consumer
on behalf of this producer.
}
Consumer (consumer_id) {
string ReceiveRow() : Called to receive one row for this consumer.
}
Controller {
StartShuffle() : Called before any producers or consumers start sending or
receiving rows.
EndShuffle() : Called after all producers and consumers have successfully
sent and received all rows.
}

위의 API들은 공유 메모리의 개념을 제공하도록 설계되었기 때문에, 데이타 프로세싱 파이프라인상에서, 데이타를 파티셔닝하는데 범용적으로 사용될 수 있다.

 

빅쿼리 셔플(shuffle)의 개념

빅쿼리 셔플의 기본 동작은 다음의 그림과 같이 설명될 수 있다.

(출처 : https://cloud.google.com/blog/big-data/2016/08/in-memory-query-execution-in-google-bigquery )

 

빅쿼리의 셔플은 많은 Producer들이 효율적으로 원격지의 머신의 메모리에 데이타를 저장할 수 있도록 하며, Consumer역시 높은 처리량으로 동시 읽기가 가능하다. 특히 Producer는 인접한 메모리 블록에 생성된 행(rows)에 로그(Log)하고 색인(index)을 남긴다.

이 색인(index)은 Consumer가 해당 행을 효율적으로 검색하고 읽을 수 있도록 해준다

빅쿼리 셔플의 복합적인 동작

(출처 : https://cloud.google.com/blog/big-data/2016/08/in-memory-query-execution-in-google-bigquery )

 

재분할한 데이타를 메모리에 저장하는 특징이외에도, 빅쿼리 셔플은 또 다른 측면에서 MapReduce스타일의 셔플과 다르다. MapReduce 스타일의 셔플은 모든 행이 재정렬 된 다음에 데이타를 접근할 수 있는데 반하여 빅쿼리에서는 producers에 의해 셔플된 각각 행(rows)은 바로 workers에 의해 접근이 가능하다. 그래서 파이프 라인에서 분산된 작업을 수행 하게 할 수 있게 한다.

빅쿼리의 데이터 분할(partitioning)

데이터의 파티셔닝(partitioning)은 BigQuery의 쿼리의 성능에 상당한 영향을 미친다.

제대로 된 결과를 얻기 위해서는 Consumer와, Provider를 적절한 숫자로 맞추는 것이 중요하다. (빅쿼리가 자동으로 수행)

최적화 되지 않은 데이터의 분할로 쿼리가 매우 느리게 실행되거나, 심지어는 자원의 제약으로 실패할 수 도 있다.

빅쿼리의 파티셔닝은 데이터 크기, 백그라운드의 부하, 기타 요인에 기초하여 쿼리에 사용 된 연산자의 종류에 따라 파티셔닝(분할)을 지능적으로 선택하는 동적 분할 메카니즘을 사용한다. 이로인하여 빅쿼리는 데이타의 특정 분포나, 키에 따른 정렬에 따른 오버헤드 없이 임의의 데이터 셋에 대한 효율적인 쿼리 실행을 할 수 있게 한다.

 

빅쿼리에서 콜로서스를 활용한 이점

빅쿼리는 페타바이트의 데이터에 쿼리를 사용할 수 있다. 대부분의 케이스에서 빅쿼리는 인메모리 셔플링을 통하여 데이타를 재분할 하는데, 메모리만 사용할 경우, 연산 비용이 매우 크기 때문에, 이를 해결하기 위해서 콜로서스 파일 시스템에 경우에 따라 데이타를 메모리에서 부터 이동하여 저장한다.

디스크의 경우 메모리에 비해서 많이 느리기 때문에, 빅쿼리에서는 디스크 억세스를 최소화하는 방법으로 성능 문제를 최소화한다.

 

빅쿼리는 multi-tenant service 이다.

빅쿼리는 사용자가 인프라를 공유해서 사용하는 멀티 테넌트 (multi-tenant) 서비스로 모든 고객이 쿼리를 실행하기 위해 VM의 클러스터의 크기를 조정하고 배포하거나, 리소스(자원)에 대한 프로비저닝이 필요 없다. 그렇게 하기 위해 빅쿼리의 셔플은 메모리에서 대부분의 쿼리를 실행 할 수 있는 지능적인 메모리 자원 관리 시스템을 사용한다. 빅쿼리는 고객으로부터 발생하는 부하의 변동에 따라 즉각적으로 적응한다.

 

결론

모든 빅쿼리의 쿼리는 하나 또는 다수의 셔플 동작을 포함하고, 단일 행 데이터 또는 페타바이트의 쿼리 데이터를 전송하는데 동일한 인프라를 사용한다. 구글 네트워크 기술과 함께 긴밀한 통합(tight intergration)으로 만들어내는 빅쿼리 셔플의 극한의 유연성은 빅쿼리의 사용자가 모든 규모에서 빠른 데이터 분석을 할 수 있게 한다.

 

 

참고자료

https://cloud.google.com/blog/big-data/2016/08/in-memory-query-execution-in-google-bigquery

 

https://cloud.google.com/blog/big-data/2016/01/anatomy-of-a-bigquery-query

 

https://cloud.google.com/blog/big-data/2016/01/bigquery-under-the-hood

 

 

빅쿼리 스트리밍 데이터 로딩하기

 

최유석

 

개요

구글 빅쿼리에서는 비동기 처리방식인 Job을 통해서 데이터를 로딩하는 방법 외에도 실시간으로 데이터를 로딩 할 수 있는 방법으로 스트리밍(Streaming) API를 제공한다. 이 글에서는 구글 빅쿼리에서 제공하는 스트리밍 API를 이용해서 실시간으로 데이터를 로딩하는 방법을 알아보도록 하자.

 

스트리밍(Streaming) API

비동기 연산인 Job을 통한 데이터 로딩방식이 아닌 API형태로 tabledata().insertAll() 메소드를 제공하여 한번에 하나씩 레코드를 삽입하는 방법을 제공한다. 하나의 레코드에는 하나 또는 다수의 행을 포함할 수 있다. 

*레코드는 빅쿼리가 지원하는 데이터 타입으로 하나 이상, 다수의 데이터 필드에 대한 일종의 집합이다.

*스트리밍 API를 이용한 데이터 로딩은 partition table에 적용되지 않는다.

 

스트리밍 로딩의 할당량 정책(quota policy)

스트리밍 API를 사용한 데이터로딩은 실시간으로 처리되는 부분으로 Job의 데이터로딩(batch) 방법에 비해서 처리 가능한 데이터의 크기와 행의 수가 제한적이다.

  • 최대 행 사이즈 : 1MB
  • HTTP 요청 사이즈 제한 : 10MB
  • 초당 최대 입력 가능 행 수 : 테이블 당 100,000 행, 프로젝트 당 1,000,000 행
  • 요청당 최대 입력 가능 행 수 : 제한은 없으나, 최대 500 행을 권장
  • 초당 최대 바이트 크기 : 100MB

 

*스트리밍 데이터 로딩 시에 위의 정책을 초과하는 경우에 에러가 발생한다. 따라서 그러한 경우는 Job을 통한 데이터 로딩을 권장한다.


데이터 일관성 보장

데이터에 대한 일관성을 보장할 수 있는 옵션으로 각각의 입력 행에 대해서 insertId를 적용할 수 있다. insertId는 행 입력 시 최소1분 정도 빅쿼리가 기억하고 있게 된다.

*이미 입력된 행에 대해서 insertId를 통해 중복된 데이터는 추가로 입력되지 않으며, 만약 변경된 데이터(행)를 입력하면 해당 insertId를 가진 데이터(행)는 변경된 데이터(행)로 입력된다.

 

템플릿 테이블

templateSuffix 속성을 통해서 지정한 대상 테이블을 기본 템플릿으로 하여 같은 스키마를 가진 새로운 테이블을 자동으로 생성할 수 있다. 

templateSuffix의 값은 사용자가 임의로 설정할 수 있다.

<대상 테이블> + <templateSuffix> 형태로 새로운 테이블이 생성된다.

 

Tabledata: insertAll정의

Tabledata는 API형태로 제공되는 Resource type으로 스트리밍 데이터 로딩을 지원하는 insertAll 메소드를 포함하고 있다.

 

HTTP 요청(request) 기본형식

POST https://www.googleapis.com/bigquery/v2/projects/projectId/datasets/datasetId/tables/tableId/insertAll

POST요청으로 각각 해당되는 project, dataset, table ID를 설정하면 된다.

 

insertAll 권한 범위

스트리밍 요청을 할 때 VM인스턴스가 위의 각각의 권한 범위를 나타내는 URI중에서 

적어도 하나의 범위의 권한을 가지고 있어야 한다.

Google API 접근 범위에 대한 참고 https://developers.google.com/identity/protocols/googlescopes

 


Request body 구조

{
  "kind": "bigquery#tableDataInsertAllRequest",
  "skipInvalidRows": boolean,
  "ignoreUnknownValues": boolean,
  "templateSuffix": string,
  "rows": [
    {
      "insertId": string,
      "json": {
        (key): (value)
      }
    }
  ]
}

필수(Required) 속성

  • kind : 응답의 자원 유형 - 사용하는 프로그래밍 언어에 따라서 직접적으로 사용이 필요한 경우가 있다.
  • rows[] : 삽입할 데이터(행)들을 포함한다.
  • rows[].json :
  • json형태로 데이터를 입력 가능하다. key(스키마): value(입력 값)의 구조를 가지며, 대상 테이블의 스키마 구조에 대응되는 형태로 스키마와 값을 입력하여야 한다. 하나이상의 행에 대한 입력이 가능하다.

 

선택적(Optional) 속성
  • rows[].insertId : 앞서 설명한 데이터의 일관성을 보장하기 위한 옵션이다.
  • templateSuffix : 앞서 설명한 것처럼, String 타입의 값으로 사용자가 임의의 값을 설정하여 데이터 로딩을 실행하면 <대상 테이블> + <templateSuffix>형태로 새로운 테이블이 자동생성되고 해당 요청에 대한 데이터가 로딩된다.
  • skipInvalidRows : 적합하지 않은 행이 존재하더라도 모든 유효한 행의 데이터를 삽입한다. boolean형으로 기본값은 false이다.
  • ignoreUnknownValues: 테이블의 스키마와 일치하지 않는 유형의 값은 무시된다. boolean형으로 기본값은 false이다.

 

Response body구조

  • kind : 응답 자원 유형을 나타낸다. - 사용하는 프로그래밍 언어에 따라서 직접적으로 사용이 필요한 경우가 있다.
  • insertErrors[] : 실패한 요청의 경우 해당 오류에 대한 내용을 json배열형태로 반환한다.


※앞서 스트리밍 데이터 로딩을 위한 기초적인 내용을 설명하였으며, Node.js를 활용하여 실제로 스트리밍으로 데이터를 로딩하여 보도록 하자.


VM환경 준비하기

프로젝트 선택

기존의 프로젝트를 선택하거나,

 

또는 새로 생성하고 진행한다.

  

VM준비(VM 생성 or 기존의 VM사용)

스트리밍 API를 사용해서 데이터로딩을 하기위해서 리눅스 기반의 VM인스턴스를 준비한다. 

주의할 점으로 해당 VM은 앞서 설명한, tabledata().insertAll() 메소드를 접근해서 사용 할 수 있는 범위의 권한을 가지고 있어야 한다.

 

이글에서는 기존의 VM을 사용했으며, 테스트에 사용한 VM의 정보는 다음과 같다. 

  • Name : test
  • Boot disk : Ubuntu 14.04 LTS / SSD 10GB

*리눅스 기반의 각자가 사용하기 편리한 다른 OS이미지를 포함하여, disk의 용량이나 타입도 각자의 환경에 맞춰서 적용해도 상관없다.

  • Access scopes : Allow full access to all Cloud APIs

편의를 위해 구글 클라우드의 모든 서비스에 Access 가능한 범위를 지정하였다.

*앞서 언급한 tabledata().insertAll() 메소드를 사용할 수 있는 권한 범위를 적용하여야 한다.

  • 나머지는 기본값으로 설정


선택사항

  • Firewalls : Allow HTTP traffic, Allow HTTPS traffic 체크

이 글에서는 HTTP, HTTP(S)의 방화벽 규칙을 설정하고 진행한다.


*단순 스트리밍 로딩을 위해서는 따로 HTTP(S)트래픽을 허용하지 않아도 위의 다른 GCP서비스에 대한 접근 범위 설정을 통해 Streaming API에 사용에 대한 권한을 가지게 된다. 때문에 무리없이 실행은 가능하다. 하지만 실제 어플리케이션 구성에서는 구성환경에 맞춰서 HTTP, HTTP(S)에 대한 트래픽을 허용해기 위해 방화벽 규칙을 설정해야 될 것이다.

   

VM인스턴스 접근 범위 확인하기

Access scopes에 대한 적합한 설정이 되어있어야 한다는 것만 명심하자.

또한 Access scopes는 VM을 생성 할 때만 적용 가능하다.

  

VM 신규 생성 시 주의사항

Identity and API access에서 적합한 Access scopes를 설정하고 생성해야 한다.


BigQuery API 활성화

스트리밍 데이터 로딩을 실행하기 위해서는 BigQuery API를 활성화 해야 한다. 다음의 BigQuery API페이지로 이동한다.

https://console.developers.google.com/apis/api/bigquery

 

상단의 ENABLE를 클릭하여 BigQuery API를 활성화 한다.

만약, 이미 BigQuery API가 활성화 되어 있다면 다음 단계로 바로 이동한다.

 

Google Cloud SDK설치

기본적으로 구글 클라우드 SDK(command line interface) 가 설치되어 있다는 가정하에 진행한다. 

만약 설치가 안되어 있다면 다음의 주소를 참고하여 설치하도록 한다.

https://cloud.google.com/sdk

 

Auth 인증

다음으로 Default Credentials정보를 인증하기 위해 SSH터미널에 접속한다.

auth인증을 위해 다음 명령어를 실행한다.

%gcloud auth login

만약 위의 명령어로 진행이 되지 않는다면 아래 명령어를 입력하여 진행한다.

% gcloud auth application-default login 

위의 명령어를 입력하고 y를 입력하고 아래에 나타난 링크를 복사하여 브라우저에서 해당 링크로 접속한다.

해당 계정을 선택하면 다음과 같은 화면이 나타나고 허용을 클릭한다.

 

다음과 같이 인증코드가 생성된다.

 

 

인증코드를 복사하여 앞서 코드를 검증하는 부분에 붙여 넣고 엔터를 입력하면

Default Credentials 인증이 성공한 것을 확인할 수 있다.

 

Node.js 환경 준비하기

이번 예제에서는 기본적으로 node.js와 npm이 설치되어 있다고 가정하고 진행한다. 

이 글은 node.js 4.4.7버전과 npm 2.15.8버전을 기준으로 작성하였다.

또한 root계정으로 진행한다. 편의를 위해 express프로젝트로 진행한다.

 

Express generator 설치

Express generator설치를 통해서 기본적인 Express 프로젝트의 구조로 생성하기 위해 다음의 명령어를 실행한다.

% npm install express-generator -g

 

Express 프로젝트 생성

Express 프로젝트를 생성하기 위해 다음의 명령어를 실행한다.

% express --session --ejs --css stylus test

다음 명령어를 실행하여 프로젝트 생성을 마무리한다.

% cd test && npm install

 

Express 프로젝트 및 프레임워크에 대해서는 http://bcho.tistory.com/887

http://bcho.tistory.com/888 글을 참고하기 바란다.

 

Bigquery API Client Library 설치

구글 빅쿼리는 npm으로 node.js Library를 제공한다. 다음의 명령어를 실행해서 Bigquery API Client Library를 설치한다.

% npm install googleapis  --save

 

 

스트리밍 데이터 로딩하기

이제 스트리밍 데이터 로딩을 위한 준비는 완료되었다. Node.js와 스트리밍 API를 사용해서 데이터 로딩을 해보도록 한다.

 

Streaming API 기본 예제 - Node.js

vi등의 편집기를 이용해서 app.js파일을 열고 다음과 같은 내용을 추가한다.

var google = require('googleapis');
var bigquery = google.bigquery('v2');

google.auth.getApplicationDefault(function(err, authClient) {
  if (err) {
    console.log('Authentication failed because of ', err);
    return;
  }
  if (authClient.createScopedRequired && authClient.createScopedRequired()) {
    var scopes = ['https://www.googleapis.com/auth/cloud-platform'];
    authClient = authClient.createScoped(scopes);
  }

  var request = {
    // TODO: Change placeholders below to appropriate parameter values for

the 'insertAll' method:

    // Project ID of the destination table.
    projectId: "",
    // Dataset ID of the destination table.
    datasetId: "",
    // Table ID of the destination table.
    tableId: "",
    resource: {},
    // Auth client
    auth: authClient
  };

  bigquery.tabledata.insertAll(request, function(err, result) {
    if (err) {
      console.log(err);
    } else {
      console.log(result);
    }
  });
});


Node 예제 구성요소 안내

google.auth.getApplicationDefault() {}

앞서 Auth 인증한 Default Credentials 정보를 확인한다. 

var scopes = ['https://www.googleapis.com/auth/cloud-platform'];
위에
설명한 것처럼, 스트리밍 로딩을 위한 VM생성 시에 가지고 있는 접근 범위 에 따라서 적합한 범위의 URI가 입력되어야 한다.

https://www.googleapis.com/auth/cloud-platform 은 구글 클라우드 플랫폼의 모든 서비스에 대한 Full Access 범위를 나타난다.

var request 내부 내용을 살펴보면 기본적으로 확인 할 내용은 다음과 같다.

projectId: "",

""안에 해당하는 프로젝트 ID,

datasetId: "",

""안에 해당하는 데이터셋의 ID,

tableId: "",

""안에 해당하는 대상 테이블의 ID 

resource: {} 에서 중괄호 안에 위에서 설명한 기본 Request body의 형식에 맞게 실제 입력할 데이터의 내용을 입력한다.

bigquery.tabledata.insertAll() {}부분에서 데이터 로딩이 실행되는 부분으로, 만약 에러가 있다면 에러에 대한 내용을 반환한다.

 

스트리밍 로딩 테스트

이제 예제 코드에 대한 대략적인 구조를 파악하였다면 스트리밍 API를 사용해서 실제 테이블에 데이터를 입력해보자.

 

테이블 정보

테스트에 사용할 테이블은 앞서 구글 스토리지를 활용한 데이터 로딩에서 생성한 csv_test 테이블을 사용하도록 한다. 테이블 csv_test는 다음과 같은 스키마를 가지고 있다.

 

Node.js 코드 작성하기

  • projectId: “사용자의 프로젝트ID”
  • datastId: “데이터를 입력할 테이블을 가지고 있는 데이터셋ID”
  • tableId: “실제로 데이터를 로딩 할 테이블Id”
  • resource: { 입력 할 데이터 }

위에서 설명한 request body의 형식으로 대상 테이블의 스키마에 대응되는 적합한 값을 입력해야 한다. 입력을 완료하고 파일을 저장한다.

 

데이터 로딩 실행 

이제 앞서 작성한 내용의 데이터를 로딩하기 위해 다음 명령어를 실행해서 Node.js서버를 구동한다.

%npm start

해당 스트리밍 로딩 요청에 대한 tableDataInsertAllResponse로 응답이 완료됨을 확인할 수 있다. 응답이 완료된 것을 확인하고 ctrl+c를 입력하여 실행을 중지한다.

 

데이터 로딩 결과 확인하기

이제 빅쿼리 웹 콘솔(Web UI)로 이동해서 간단한 쿼리 실행을 통해 데이터가 정상적으로 입력되었는지 확인해보자.

  

쿼리 실행하기

좌측 상단의 COMPOSE QUERY 버튼을 클릭한다.

 

다음과 같이 쿼리를 입력하고 RUN QUERY 버튼을 클릭하여 쿼리를 실행한다.

SELECT word, word_count, corpus, corpus_date

FROM load_test.csv_test

WHERE word_count=1111

 

쿼리가 실행되었다. 앞서 입력한 데이터를 확인 할 수 있다.

 

템플릿 테이블을 이용한 테이블 자동생성

이제 앞서 설명한 templateSuffix속성을 활용해 csv_test 테이블을 템플릿으로 하여 같은 스키마를 가진 새로운 테이블을 생성해보자.

 

Node.js 코드 작성하기

vi편집기등으로 app.js파일을 열고 다음의 내용을 추가하고 파일을 저장한다.

  • templateSuffix: "String형의 임의의 값"

 

자동 테이블 생성 및 데이터 로딩 실행

템플릿 테이블을 활용해서 자동으로 새로운 테이블 생성 및 데이터로딩을 위해 node.js 서버를 실행한다.

%npm start

응답이 완료되었다. ctrl+c를 입력하여 실행을 중지한다.

 

자동 테이블 생성 및 데이터 로딩 결과 확인하기

이제 다시 빅쿼리 웹 콘솔로 이동해서 테이블이 자동으로 생성되고 입력한 데이터가 제대로 로딩되었는지 확인한다. (새로고침이 필요할 수 있다.)

 

먼저 자동 생성된 테이블 부터 확인한다. 앞서 설명한 것처럼 <대상 테이블> + <templateSuffix>의 형태로 csv_test1234라는 새로운 테이블이 생성되었다. 템플릿의 대상이 되는 테이블인 csv_test와 동일한 스키마를 가진다.

 

데이터 로딩 결과 확인하기 - 자동생성 테이블

이제 자동으로 생성된 테이블을 확인하였다면 해당 테이블에 스트리밍으로 입력한 데이터를 확인해보도록한다.

 

쿼리 실행하기

COMPOSE QURERY버튼을 클릭해서 다음과 같은 쿼리를 입력하고 RUN QUERY 버튼을 클릭하여 쿼리를 실행한다.

SELECT word, word_count, corpus, corpus_date

FROM load_test.csv_test1234

WHERE word_count=1111


쿼리가 실행되었다. 앞서 입력한 데이터를 확인 할 수 있다.

*날짜 단위 또는 각각의 사용자 단위 등으로 테이블을 분할하여 생성할 필요가 있을 때, 

templateSuffix의 값에 따라서 자동으로 테이블을 생성하여 데이터를 입력할 수 있기 때문에 매우 유용한 기능이다.

 

자동 테이블 생성 참고사항

templateSuffix속성을 활용해서 자동으로 테이블 생성하고 데이터를 입력한 경우에 빅쿼리 

웹콘솔에서 바로 Preview를 클릭하면 스트리밍 버퍼에서 데이터 로딩을 통해 입력한 데이터를 

가지고 있어서 입력한 값이 바로 나타나지 않을 수 있다.

*스트리밍 데이터 입력에 수초가 소요될 수 있으며, 입력된 데이터를 복사하고, 

내보내기에 사용 될 수 있기까지 90분까지 소요 될 수 있다

 

 

데이터 일관성 확인

앞서 insertId를 통해 데이터의 일관성을 보장해주는 부분에 설명하였다. 이제 실제로 insertId를 사용해 데이터가 어떻게 변화하는지 확인해본다.

 

Node.js 코드 작성하기

vi등의 편집기를 이용해서 app.js파일을 열고 다음의 내용을 추가하고, 입력할 데이터의 내용을 수정한다.

  • insertId: "String형의 임의의 값"

입력 데이터의 경우 앞서 테스트한 결과와 구분을 위해 다른 값으로 변경한다.

   

데이터 로딩 실행 - insertId

insertId가 적용된 데이터로딩을 하기 위해서 node.js서버를 실행한다.

%npm start

응답이 완료되었으면 빅쿼리 웹 콘솔로 이동해서 입력된 데이터를 확인한다.

 

데이터 로딩 결과 확인하기 - insertId

빅쿼리 웹 콘솔에서 COMPOSE QUERY를 클릭하고 다음의 쿼리를 입력한다.

SELECT word, word_count, corpus, corpus_date

FROM load_test.csv_test1234

WHERE word_count=2222

RUN QUERY를 클릭하여 쿼리를 실행하고 입력된 데이터를 확인한다.

쿼리 수행결과를 통해, 정상적으로 입력된 데이터를 확인 할 수 있다.

 

데이터 중복 입력 확인하기

다시 SSH터미널에서 ctrl+c를 입력하여 서버 실행을 중지하고 app.js의 내용을 변경하지 않고, 다시 한번 node.js서버를 실행한다.

 

데이터 중복 확인 - 쿼리 테스트

빅쿼리 웹 콘솔로 이동해서 위와 동일한 쿼리를 실행해서 결과를 확인한다.

 

쿼리를 실행하면 앞서 입력한 데이터(행)만 나타난다. 같은 insertId를 가지고 있기 때문에 중복된 데이터가 추가로 입력되지 않는다.

 

*insertId가 없는 경우, 스트리밍 로딩을 할 때 데이터의 중복에 관계없이 새로운 데이터(행)가 추가된다. 각각 테스트해보길 권장한다.

   

데이터 변경하기 - Node.js 코드 수정하기

SSH 터미널에서 node.js서버를 중지하고 vi등의 편집기로 app.js파일을 열고 데이터의 내용을 변경하고 저장한다.

 

데이터 변경 후 로딩 실행 - insertId

앞서 같은 insertId를 가진 상태에서 변경한 데이터를 로딩하기 위해 다음 명령어를 실행해서 node.js서버를 구동한다.

%npm start

응답을 확인하고 웹 콘솔로 이동해서 입력된 데이터를 확인해보자.

 

데이터 변경 입력 후, 로딩 결과 확인하기

기존에 데이터가 어떻게 변화하였는 지 확인하기 위해 빅쿼리 웹 콘솔에서 앞서 실행한 쿼리를 입력하고 결과를 확인한다.

SELECT word, word_count, corpus, corpus_date

FROM load_test.csv_test1234

WHERE word_count=2222 

앞서 위의 쿼리 실행을 통해 데이터가 로딩된 결과를 확인했었다. 하지만 해당 쿼리가 

실행되면 조회되는 데이터가 없음을 확인 할 수 있다

 

이번에는 변경한 데이터의 word_count값인 3333으로 WHERE 조건을 변경하고 쿼리를 실행해보자

SELECT word, word_count, corpus, corpus_date

FROM load_test.csv_test1234

WHERE word_count=3333

변경해서 입력한 데이터에 대한 조회결과가 나타난다. 이와 같이 같은 행에 대한 insertId가 적용된 상태에서 데이터가 변경되어 다시 입력되는 경우, 기존의 입력된 데이터는 변경된다.

 

*insertId의 경우 데이터의 일관성을 확인하고 보장하기 위해 좋은 수단이 될 수 있으나, 앞서 언급한 것처럼 1분정도만 보장되는 시간적인 제약이 있으니 참고하기 바란다.

 

결론

빅쿼리의 스트리밍 데이터 로딩의 경우, 몇가지 제약적인 부분은 있지만, 실시간으로 대량의 이벤트 로그 분석, 실시간으로 데이터와 연동하는 dashboard등에 활용하기 좋다. 또한 빅쿼리의 대용량의 데이터 분석 뿐만 아니라 실시간의 데이터 로딩, 분석을 융합적으로 활용하면, 급변하는 시장에서 빠르게 대응 할 수 있는 또 하나의 대안이나 수단으로 이용할 수 있을 것이다.

 

참고자료

https://cloud.google.com/bigquery/streaming-data-into-bigquery

https://cloud.google.com/bigquery/docs/reference/v2/tabledata/insertAll

https://cloud.google.com/bigquery/quota-policy#streaminginserts

구글 클라우드 사용팁

최유석

 

Compute Engine

여러 VM인스턴스에서 디스크 공유 하기

VM인스턴스들은 read-only(읽기전용) mode로 성능하락 없이 디스크를 공유할 수 있다.

read-write(읽기-쓰기) mode에서는 하나의 VM인스턴스에서만 해당 디스크를 사용할 수 있다.

 

디스크 공유하기

1.VM 상세 페이지에서 Edit를 클릭하고 Boot disk and local disk탭에서 Additional disks부분의

+Add item을 클릭한다.

 

2. Mode를  Read only로 변경하고 Name에서 Create disk를 클릭하여 디스크를 생성한다.

적당한 디스크 이름(test-disk)을 입력하고 Source type탭에서 None(blank disk)를 지정하고 

생성하기를 원하는 Size를 입력하고 Create버튼을 클릭하여 디스크를 생성한다.

 

 

*기존에 생성했던 디스크가 있다면 해당 디스크를 사용 할 수 있다. 

추가적인 disk가 없기에 새로 생성하는 방법으로 진행한다.

 

3. VM인스턴스 상세페이지에서 Save를 클릭하여 적용한다.

 

4. 읽기전용 disk를 공유하기 위해 다른 VM의 상세 페이지에서 Edit를 

클릭하고 디스크 탭으로 이동한다. 위와 마찬가지로 +Add item을 클릭한다.

5. 앞서 다른 VM에서 생성한 disk를 Name을 클릭하면 선택 할 수 있으며, 

해당 disk를 선택하고 Mode를 Read only로 지정한 후 페이지 하단의 Save를

 클릭하여 해당 내용을 저장한다.

6. 디스크 공유가 완료되었다. 디스크를 생성해서 연결한 VM과 뒤에 추가로 

같은 disk를 연결한 VM의 상세페이지에서 각각 읽기전용으로 디스크가 공유된 것을 확인 할 수 있다.

 

  • 디스크를 생성하고 연결한 VM

  • 추가적으로 디스크를 공유한 VM

같은 방법으로 다른 VM에도 추가적으로 디스크 연결이 가능하다.

 

* 주의할 점은 하나의 디스크로 각각 다른 VM에 읽기전용, 읽기/쓰기 동시 지원이 안되니 참고바란다. 

오직 디스크가 읽기전용에서만 여러 VM인스턴스에서 공유 가능하다.

* 하나의 VM에 연결 된 디스크는 읽기전용, 읽기/쓰기 모드의 상호변경이 가능하다.

 

디스크 공유하기 참고페이지

https://cloud.google.com/compute/docs/disks/add-persistent-disk

 

구글 클라우드 시작하기

구글 빅쿼리 데이터 로딩하기

 최유석

개요

구글의 대용량 데이터 분석 서비스인 빅쿼리에 구글 클라우드 스토리지를 활용하여 CSV, JSON형식의 데이터를 로드하고 테이블을 생성하는 방법에 대해서 알아보도록 한다.

 

또한,빅쿼리에서는 데이터 파일의 단일 업로드뿐만 아니라 병렬 업로드(다중파일 동시 업로드)도 제공한다.따라서, 이번 글의 뒤쪽에서는 단일CSV파일로 데이터로딩을 해보고, 그 CSV파일을 여러 개의 파일로 분할하여 병렬로 데이터를 로드해서 각각의 처리 속도를 확인해본다.

그리고 CSV 병렬 업로드를 위해 분할한 데이터를 이용하여 JSON, Avro포맷으로 변환하여 각각의 형식에 따라 동일데이터라도 데이터 로딩시간이 어떻게 달라지는지 확인해보도록 하자

 

구글 클라우드 스토리지(Google Cloud Storage : GCS)

구글 클라우드 스토리지는 구글 클라우드 플랫폼에서 지원하는 BLOB(Binary large object) Store로 구글 클라우드 플랫폼의 모든 서비스들과 연계하여 사용이 가능하다.구글 클라우드 플랫폼에서 제공하는 파일,미디어 등의 저장에 특화된 서비스이다.

 

GCS 스토리지 클래스

Standard:

높은 data availability(99.9%)와low latency을 가지고 있어서 데이터에 대한 빠른 응답속도(ms)를 보인다.따라서 데이터에 대한 빠른 접근,빈번한 접근이 필요한 경우에 사용하기 적합하다.활용하기 적합한 예로는 웹사이트 컨텐츠,모바일 또는 게임 어플리케이션, 등이 있다.

   

Durable Reduced Availability (DRA) :

Standard에 비해 약간 낮은 가격과 data availability(99%)를 가지고 있다.

데이터 백업,배치(batch) 작업에 사용하기 적합한 클래스이다.

 

Nearline : data archiving 이나 online backup, 재해복구(disaster recovery)용도로 사용하기 적합한 클래스로 가장 저렴한 비용으로 이용할 수 있다. 데이터 접근에 시간단위가 소요되는AWS의 glacier서비스등에 비해서 매우 빠른 속도로 초 단위(대략3초)로 다른 클라우드 업체들의 유사서비스들에 비해서 매우 높은 성능을 가진다.

 

*구글 클라우드 스토리지 클래스 모두 동일한 API를 사용하고 AWS의 S3와 API호환되서 API사용에 대한 부담이 적다.

 

GCS 기본 구성요소

프로젝트(Project) :

최상위 컨테이너로 구글 클라우드 스토리지의 모든 자원(resources)은 프로젝트 위에서 생성되고 관리된다. 또한 스토리지 자원들에 대하여 권한제어가 가능하다.

 

버켓(Bucket) :

데이터 또는 파일을 저장하고 관리하기 위한 컨테이너이다.구글 클라우드 스토리지에서의 최소단위인 Object(각각의 데이터 또는 파일단위)가 저장되는 공간이며, 버켓 생성 시에 앞서 설명한 클래스와 데이터가 저장될 위치를 지정하여야 하고 생성 후에는 변경이 불가능하다.새로 생성하거나 다른 버켓으로 이동시키는 등의 방법을 사용하여야 한다.

  

오브젝트(Object) :

실제로 구글 클라우드 스토리지에 저장되는 각각의 데이터 또는 파일을 의미한다. 하나의 오브젝트는 최대 5TB까지 저장할 수 있다.

 

빅쿼리 기본구조

*빅쿼리에 대한 개념, 아키텍쳐 등의 기본적인 이해가 필요하다면 아래 주소의 정보를 참고하기 바란다.

http://bcho.tistory.com/category/%EB%B9%85%EB%8D%B0%EC%9D%B4%ED%83%80/Google%20BigQuery

   

프로젝트(Project)

빅쿼리에서 프로젝트는 하위 구조인 데이터셋을 가질 수 있으며,하나의 프로젝트 안에는 다수의 데이터셋을 가질 수 있다. 또한 사용자와 데이터셋에 대한 권한 제어를 포함한 전반적인 리소스의 관리를 담당한다.

 

데이터셋(Dataset)

하나 이상의 테이블을 가질 수 있는 테이블에 대한 집합으로 테이블을 관리한다. 빅쿼리에서 권한제어를 할 수 있는 최소 단위로 데이터셋에 대한 권한부여를 통해 다른 사용자와 데이터를 공유 할 수 있다. (MySQL의 database와 비슷한 개념이다.)

 

테이블(Table)

실제 데이터가 저장되는 테이블이다. 스키마를 가지고 있으며 행(row)단위 업데이트는 지원되지 않는다.테이블에 대한 권한제어는 따로 적용되지 않으며 해당 테이블을 가지고 있는 부모 데이터 셋으로부터 상속받는다.

 

잡(Job)

잡은 쿼리, 데이터 로딩, 삭제, 복사, 내보내기 등의 명령을 수행하는 비동기식 연산으로 4가지 구성요소를 가지고 있다.

 

잡(Job)의 구성요소

○ Reference - job ID : 유니크 한 이름

○ Configuration - job task : 수행하는 작업의 종류

○ Status - job state : 오류와 경고를 포함한 상태

○ Statistics - job statistics : 수행내역을 제공하는 통계

 

잡의 구성요소들은 향후 감사(Audit)등의 목적을 위해서 로그를 남기게 된다. 또한 잡은 실행 도중 취소가 가능하다. 하지만 취소하였다 하더라도 해당 명령에 대한 프로세싱은 이루어지기 때문에 비용이 발생한다.

 

데이터 타입

  • STRING : UTF-8인코딩. 최대 2MB
  • BYTES : base64로 인코딩 된 이진 데이터
  • INTEGER : 64 bit signed integer
  • FLOAT : Double precision, floating-point format
  • BOOLEAN : CSV format: true or false (case insensitive), or 1 or 0

                                      JSON format: true or false (case insensitive)

  • RECORD : A Collection of one or more field
  • TIMESTAMP

 

*데이터 타입 중 RECORD의 경우 중첩 및 반복을 허용하고 JSON과 같이 여러 개의 데이터 값을 가질 수 있다. 불필요한 반복 및 중첩이 많아지면 쿼리를 포함한 여러 가지 작업들이 어려워지니 가급적 피하는 게 좋다.

 

데이터 필드의 모드

  • REQUIRED : NULL값을 허용하지 않음
  • NULLABLE : NULL값을 허용(기본값)
  • REPEATED : NULL값을 허용하고 1개 또는 배열 형태로 여러 개의 값을 가질 수 있으며 JSON, Avro포맷에서만 사용가능하다.

 

데이터 로딩 포맷

  • CSV
  • JSON(newline-delimited)
  • Avro
  • Cloud Datastore backups
  • Google sheets

*스키마에 따라서 CSV, JSON, Avro 모두 flat data를 지원하지만, 스키마에 중첩되거나 반복되는 필드를 가진 경우 JSON, Avro만 지원한다.

*기본적으로 데이터에 줄바꿈(개행문자)이 포함되어 있는 경우 JSON, Avro가 빠르다.

 

데이터 로딩 지원도구(Tools)

  • Web UI : 웹 브라우저 기반으로 제공하는 빅쿼리 전용 웹 콘솔로 비전문가도 사용하기 쉽다.
  • Command-line interface (CLI) : 파이썬 기반의 명령어 도구가 제공된다.
  • REST API (POST) : POST요청으로 데이터 로딩을 할 수 있는 REST형태의 API를 제공하며, 재개 가능(Resumable)업로드, 다중 부분(Multipart) 업로드의 두가지 옵션을 제공한다.
  • Streaming API : 잡을 사용해서 대규모의 데이터를 로드하는 대신 한번에 하나의 레코드를 삽입할 수 있는 API를 제공한다.
  • Third-party ETL tools and connectors : 각종 3party의 ETL(Extract, Transform, Load) 툴 및 시각화, 개발환경 등과의 연동할 수 있도록 커넥터를 제공한다.

 

데이터 로딩(Load job)제한

 

*하루 기준으로 실패를 포함하여 최대 테이블 당 1,000개, 프로젝트 당 10,000개의 잡을 처리할 수 있다.

 

최대 행(row) 또는 cell 크기(데이터 포맷에 따라 구분)

Data Format Max limit
CSV 2 MB (row and cell size)
JSON 2 MB (row size)
Avro 16 MB (block size)

 

*하나의 테이블 당 최대 10,000개의컬럼(columns)까지 생성 할 수 있다.

 

데이터 파일 최대크기 (데이터 포맷에 따라 구분)

File Type Compressed Uncompressed
CSV 4 GB • With quoted new-lines in values: 4 GB
• Without new-lines in values: 5 TB
JSON 4 GB 5 TB
Avro Compressed Avro files are not supported, but compressed data blocks are. BigQuery supports the DEFLATE codec. 5 TB (2 MB for the file header)

 * Avro포맷의 경우 파일에 대한 압축은 지원되지 않음

* 데이터 로딩동시 업로드 파일은 최대 10,000개까지 지원한다.

 

구글 클라우드 스토리지를 활용하여 CSV, JSON 형식의 데이터 로딩하기

 

프로젝트지정

기존의 프로젝트를 선택하여 진행하거나

 

새로 생성해서 진행한다.

 

 

 

구글 클라우드 스토리지에 데이터 업로드하기

구글 클라우드 스토리지에서 CSV, JSON파일을 업로드하여 사용하기 위해 좌측상단 탭의 스토리지 메뉴로 이동한다.

 

 

버켓(bucket)생성하기

 

  • Name : load-bigquery (임의의 값)
  • Storage class : Standard (각자의 프로젝트 환경에 적용할 클래스를 선택한다.)
  • Location : Asia (원하는 지역을 선택해도 무방하다.)

 

CSV, JSON파일 업로드

본 예제에서는 다음의 파일들을 이용한다. 서로 동일한 테이블 데이터를 가지고 있다.

  • CSV   : shakespeare.csv
  • JSON : shakespeare.json

상당의 UPLOAD FILES를 클릭 후 파일을 선택하고 업로드를 진행한다.

 

업로드가 완료되었다.

   

이제 빅쿼리로 이동해서 앞서 구글 클라우드 스토리지에 업로드한 CSV, JSON형식의 데이터를 사용해서 테이블을 생성하고 데이터를 로드해보자

 

데이터 로딩하기

구글 클라우드 콘솔의 좌측 상단 탭을 클릭하여 빅쿼리 웹 UI로 이동한다.

  

데이터셋(dataset)생성하기

프로젝트명 오른쪽에 있는 화살표 박스를 클릭하여 데이터셋을 생성한다

 

데이터셋에 생성 할 ID를 입력하고 나머지는 기본값으로 데이터셋을 생성한다

 

  • Dataset ID : load_test (임의의 값)
  • Data location : unspecified (unspecified, US, EU)
  • Data expiration : Never (영구히 저장하거나 또는 만료기간 지정가능 – 자동 삭제됨)

 

*Data location은 데이터셋이 가지고 있는 테이블을 포함하여 데이터가 실제로 위치할 위치를 지정할 수 있다. 제공되는 옵션으로는 지정하지않거나, 미국, 유럽을 선택할 수 있다.

 

Dataset이 생성되었다. 앞서 임의로 생성한 데이터셋 load_test 위에 테이블을 생성해보자.

   

테이블 생성하기 - CSV

구글 클라우드 스토리지에 저장한 CSV 파일을 이용해서 데이터를 로딩하여 테이블을 생성해보자

 

먼저 데이터셋 우측의 +모양의 버튼을 클릭하여 테이블 생성 메뉴를 불러온다

   

CSV포맷의 데이터를 로드하고 테이블을 생성하기 위해 내용을 입력하고 필요한 옵션을 설정하여 테이블을 생성한다..

 

Source Data

Location : Google Cloud Storage - gs://load-bigquery/shakespeare.csv

데이터를 가져올 위치로 앞서 구글 클라우드 스토리지에 저장한 CSV파일의 URI를 입력한다

 

*구글 클라우드 스토리지 URI 형식 : gs://<bucket>/<object>

* Location의 다른 옵션

  • File Upload : 로컬 파일을 업로드하여 사용할 수 있다.
  • Google Drive : 구글드라이브에 저장된 파일을 공유한 링크를 이용할 수 있다.
  • None(create empty table) : 스카마만 구성하여 빈 테이블을 생성할 수 있다.

 

File format : CSV

Location에서 none(빈테이블 생성)을 제외한 모든 옵션에서 CSV, JSON, Avro포맷을 사용 할 수 있다.

 

*특수한 경우로 각각의 위치에 따라서 추가적으로 지원되는 포맷이 다르다.

구글 클라우드 스토리지: Google Cloud Datastore backup files

구글 드라이브: Google Sheets

 

Destination Table

Table name : load_test . csv_test

Destination Table은 앞서 생성한 데이터셋인 load_test를 지정하고 뒤에 생성 할 테이블 이름을 입력한다.

*테이블의 경우 ( . ) 으로 구분하여 <project id>:<dataset id>.<table name> 형태로 쿼리에 사용할 수 있다. 프로젝트 ID의 경우 해당 프로젝트에서 작업하는 경우 생략 가능하다.

 

Table type : Native table

빅쿼리 내부 스토리지에 저장되는 테이블)

Table type 추가옵션 : External table

빅쿼리 내부 스토리지가 아닌 구글 클라우드 스토리지나 구글 드라이브에 저장되는 테이블로 빠른 생성 및 수정이 가능하지만, 빅쿼리의 쿼리성능을 높이는 컬럼 기반 구조를 사용할 수 없게 되어 성능저하가 발생한다.

 

Schema

Edit as Text를 클릭하고 다음과 같이 "name:type" 형태(CSV기준)로 입력하거나,

 

word:STRING, word_count:INTEGER, corpus:STRING, corpus_date:INTEGER 

 

또는 Add Field를 클릭하여 각각 필드를 추가하여 Name을 입력하고 Type을 지정한다.

 

Field delimiter:Comma ( 구분자로 사용할 요소를 선택 )

Header rows to skip : 1 (최상단의 행부터 행단위로 데이터를 스킵하고 해당 예제에서는 상단에 스키마 정보가 있는 상태라서 1행을 스킵하고 진행한다.)

*데이터만 입력하는 경우 기본값인 0으로 입력한다.

테이블을 생성 시에 기본적으로 고려해야할 사항들에 대해서 언급하였으며,나머지는 기본값으로 입력하고 Create Table을 클릭하여 생성한다.

 

테이블이 생성되었다.

 

테이블 테스트 - CSV

좌측상단의 COMPOSE QUERY를 클릭하여 테이블이 정상적으로 생성되었는지 간단한 쿼리를 실행해서 테스트해보자.

 

다음은 테이블의 모든 데이터를 읽어와10개값만 보여주는 SELECT쿼리이다.

 

SELECT word, word_count, corpus, corpus_date 

 

 

FROM load_test.csv_test 

 

 

ORDER BY word_count DESC LIMIT 10 

 

 

RUN QUERY버튼을 클릭하여 쿼리를 실행한다.

   

테스트로 입력한 쿼리가 정상적으로 실행되었다.

 

다음으로는 JSON형식의 데이터 파일을 로드 하여 테이블을 생성해보자.

 

데이터 로딩하기 - JSON

데이터셋(load_test)의 우측 + 버튼을 클릭하여 테이블을 생성한다.

 

JSON포맷의 데이터를 로드하고 테이블을 생성하기 위해 내용을 입력하고 필요한 옵션을 설정하여 테이블을 생성한다. .

 

Source Data

Location : gs://load-bigquery/shakespeare.json

JSON 파일도 마찬가지로 구글 클라우드 스토리지의 JSON파일 URI를 입력한다

File format : JSON(Newline Delimited)

 

Destination Table

Table name : json_test(임의의 값)

 

Schema

Edit as Text에 다음과 같이 텍스트로 JSON형태의 스키마를 입력한다.

 

[ 

 

 

    { 

 

 

        "name": "word", 

 

 

        "type": "STRING", 

 

 

        "mode": "REQUIRED" 

 

 

    }, 

 

 

    { 

 

 

        "name": "word_count", 

 

 

        "type": "INTEGER", 

 

 

        "mode": "REQUIRED" 

 

 

    }, 

 

 

    { 

 

 

        "name": "corpus", 

 

 

        "type": "STRING", 

 

 

        "mode": "REQUIRED" 

 

 

    }, 

 

 

    { 

 

 

        "name": "corpus_date", 

 

 

        "type": "INTEGER", 

 

 

        "mode": "REQUIRED" 

 

 

    } 

 

 

] 

 

*Add Field로 각각 생성해도 상관없다.각각의 환경에 따라서 사용하기 편한 방식으로 이용하도록 하자.

다음과 같이 스키마 정보가 정상적으로 입력된 것을 확인 할 수 있다.

 

이제 나머지 값은 기본값으로 하여 Create Table 버튼을 클릭하여 테이블을 생성해보자.

 

JSON포맷의 데이터로 생성한 테이블이 생성되었다.

 

테이블 테스트 – JSON

COMPOSE QUERY를 클릭하여 CSV로 입력한 데이터와 같은 데이터를 가지고 있기 때문에, 앞에서 CSV를 테스트한 쿼리를 이용하여 테스트해보자. 

 

SELECT word, word_count, corpus, corpus_date  

 

 

FROM load_test.json_test  

 

 

ORDER BY word_count DESC LIMIT 10 

 

 

RUN QUERY버튼을 클릭하여 쿼리를 실행해보자

 

테스트로 입력한 쿼리가 정상적으로 실행되었다.

 

*구글 클라우드 스토리지를 이용하여 데이터 교환의 표준 포맷이라고 할 수 있는 CSV, JSON형식의 데이터를 이용해 테이블을 생성하고 데이터를 로드하였다. 위의 예제에서는 데이터를 로딩하는 방법에 대한 설명하기 위해 작은 용량의 데이터를 가지고 진행하였다.하지만 빅쿼리는 기본적으로 대용량의 데이터를 실시간에 가까운 속도로 처리하고 분석하기 위해 설계되었고,GB,TB급의 데이터라도 매우 빠른 속도로 로딩이 가능하다. 따라서 위의 예제의 데이터보다는 비교적 큰 데이터를 이용해 앞서 언급한 단일, 병렬, 포맷에 따른 데이터 로딩시간을 확인해보도록 한다

 

업로드 속도 비교하기

시작하기전에 먼저 각각의 방식에서 속도(성능)를 확인하는 것이 주요 목적으로

각각의 업로드 방법에 대한상세한 설명은 생략한다.

 

기본 준비사항

원본 데이터

아래는 원본 테이블의 정보이다. 2014년의 항공편에 대한 데이터를 가지고 있으며 용량은 1GB가 약간 넘으며, 6,303,310개의 행(Rows)으로 이루어져 있다.

bq 명령어 도구

앞서 언급한 Command-line interface로 제공되는 도구이다. 파이썬 기반의 도구로 Google Cloud SDK에 포함되어 있으며, 기타 SSH를 사용하는 경우 따로 설치도 가능하다. 이후 진행 할 단일/병렬 업로드에 bq도구를 활용하도록 하겠다.

 

VM인스턴스 준비

테스트를 위해 Google Compute Engine의 VM인스턴스를 하나 생성하거나 기존의 VM인스턴스를 사용한다.

테스트에 사용한 VM은

  • machine type : n1-standard-1 (1 vCPU, 3.75 GB memory)
  • zone : asia-east1-b
  • disk : 10GB SSD
  • OS : ubuntu-1404-trusty-v20160627
  • 나머지는 기본값으로 설정

 

VM이 생성되면 이후 테스트를 진행하기 위해bq도구를 사용하기 위해 SSH에 접속한다.

 

CSV 단일 파일 업로드

데이터 준비

미리 구글 클라우드 스토리지에 데이터파일을 저장한다.

하나의 CSV 데이터파일과 해당파일을 6개의 파일로 분할한 파일들이다.

 

다음 명령어를 통해 CSV데이터의 업로드를 실행한다.

 

bq load --skip_leading_rows=1 \ 

 

 

--source_format=CSV bigquery-1369:load_test.flight_csv_single \ 

 

 

gs://load-bigquery/csv/flight.csv \ 

 

 

./schema_flight_performance.json 

 

  • bq : bq를 쓰기위한 명령어
  • load : 데이터 로딩을 위한 명령어
  • --skip_leading_rows=1 : 웹 UI의 Header rows to skip 옵션과 동일
  • --source_format=CSV : 포맷 지정
  • bigquery-1369:load_test.flight_csv_single :  

                생성 할 테이블 위치 <project id>:<dataset id>.<table name

               형태로 테이블을 지정한다.(웹 UI의 Table name과 동일)

  • gs://load-bigquery/csv/flight.csv :

                가져올 데이터 위치(웹 UI의 구글 클라우드 

                스토리지 URI와 동일)

  • ./schema_flight_performance.json : 사용할 스키마 내용 또는 파일

 

테이블이 생성 되었다.

 

웹 콘솔의 job History를 통해데이터 로딩에 소요된 시간을 확인해보자.

 

해당 잡의 시작시간과 종료시간을 보면CSV 단일 데이터 로딩에 46초가 소요된 걸 확인할 수 있다. (여러 번 테스트 해본 결과 테스트 결과 40초 ~ 60초 정도 소요됨)

 

다음 bq명령어로도 확인 가능하다

 

bq ls -j 

 

 

CSV 병렬 업로드

빅쿼리에서는 제공 하는 와일드카드 "*"로 동일 패턴의 String을 가진 여러 파일에 대한 동시 업로드를 사용할 수 있으며,

['gs://my-bucket/file-name-*.json']형태로 사용할 수 있다.

 

다음 명령어를 통해CSV데이터의 병렬 업로드를 실행한다.

 

bq load --skip_leading_rows=1 \ 

 

 

--source_format=CSV bigquery-1369:load_test.flight_csv_multi \ 

 

 

gs://load-bigquery/csv/flight0*.csv \ 

 

 

./schema_flight_performance.json 

 

생성한 테이블 명 : flight_csv_multi

가져올 데이터 위치(와일드카드 사용) : 

gs://load-bigquery/csv/flight0*.csv

 

테이블이 생성되었다.

 

웹 콘솔의 job History를 통해 데이터 로딩에 소요된 시간을 확인해보자.

해당 CSV 병렬데이터 로딩에 37초가 소요된 걸 확인할 수 있다.

(여러 번 테스트 해본 결과 테스트 결과 36초 ~ 50초 정도 소요됨)

 

*단일 업로드에 46초, 병렬 업로드에 37초가 소요되었다.9초의 차이가 발생한다. 당연한 결과지만 병렬 업로드가 더 빠르다.따라서 이 뒤의 JSON, Avro

포맷의 단일파일 업로드는 제외하고 진행한다.

 

JSON병렬 업로드

앞서 CSV병렬 업로드에 사용한 6개의 파일을 JSON으로 변환하고 변환된 파일들을 이용하여 병렬 업로드를 실행하고 속도를 확인해보자. 변환과정은 생략한다.

   

데이터 준비

CSV -> JSON으로 변환한 파일을 구글 클라우드 스토리지에 저장한다.

CSV와 비교했을 때 데이터 파일의 크기가 확연하게 커졌다. 차이가 발생하는 이유는 JSON의 경우 구조상 모든 데이터가 스키마를 포함하게 되어 데이터를 포함한 JSON파일의 크기가 커지게 된다.

 

 

다음 명령어를 통해 JSON포맷의 병렬 업로드를 실행한다.

 

bq load --source_format=NEWLINE_DELIMITED_JSON \ 

 

 

bigquery-1369:load_test.flight_json_Multi \ 

 

 

gs://load-bigquery/json/flight*.json \ 

 

 

./schema_flight_performance.json 

 

--source_format=NEWLINE_DELIMITED_JSON : JSON 포맷으로 지정한다.

 

테이블이 생성 되었다.

 

웹 콘솔의 job History를 통해 데이터 로딩에 소요된 시간을 확인해보자.

JSON포맷의병렬 데이터 로딩에 28초가 소요된 걸 확인할 수 있다.

(여러 번 테스트 해본 결과 20초 ~ 30초 정도 소요됨)

 

*CSV와 비교했을 때 JSON이 더 빠른 데이터로딩 속도를 보인다.

 

Avro 병렬 업로드

마지막으로 JSON과 동일한 방법으로 CSV병렬 업로드에 사용한 6개의 파일을 Avro포맷으로 변환하여 병렬 업로드를 하여 속도를 확인해보자. 변환과정은 생략한다.

 

데이터 준비

CSV -> Avro으로 변환한 파일을 구글 클라우드 스토리지에 저장한다.

같은 데이터를 가지고 있지만 CSV, JSON포맷과 비교했을 때데이터 파일의 크기가 작다.

 

다음 명령어를 통해 Avro포맷의 병렬 업로드를 실행한다.

 

bq load --source_format=AVRO \ 

 

 

bigquery-1369:load_test.flight_avro_Multi \  

 

 

gs://load-bigquery/avro/flight*.avro 

 

--source_format=AVRO : Avro포맷으로 지정한다

Avro의 경우 데이터파일에서 스키마의 정보를 포함하고 있기에 스키마를 따로 지정하지 않아도 된다.

 

테이블이 생성 되었다

 

웹 콘솔의 job History를 통해 데이터 로딩에 소요된 시간을 확인해보자.

Avro포맷의병렬 데이터 로딩에 40초가 소요된 걸 확인할 수 있다. 

(여러 번 테스트 해본 결과 35 ~ 45초 정도 소요됨)

 

*여러 번 테스트 한 결과 CSV 병렬 업로드 보다 빠르고 JSON보다는 느리다.

 

데이터 로딩 결과(시간)

  CSV(단일) CSV(다중) JSON(다중) Avro(다중)
업로드 시간 40초 ~ 60초 36초 ~ 50초 20초 ~ 30초 35 ~ 45초

 

결론

빅쿼리가 지원하는 데이터 포맷(CSV,JSON, Avro)을 이용해동일한 데이터에 대해서단일 파일 데이터 로딩을 포함하여, 단일 데이터파일을 분할하여 여러 개로 나눠서 병렬(다중파일 동시 업로드)데이터 로딩을 테스트하였다.다음과 같은 결과를 확인할 수 있었다.

  • 로딩 속도는 CSV > Avro > JSON

 

  • 데이터의 크기(비용적인 측면)는 Avro < CSV < JSON

 

물론 데이터의 크기가 더 커진다면 결과가 달라 질 수도 있겠지만, 위에서 테스트한 정보를 토대로 이야기하면 1GB의 용량에 6백만 행을 가진 데이터가 작지 않은 데이터라고 볼 수 있으나, 현재와 같이 빅데이터가 일반화 되어가는 시기에 수십,수백GB에서 TB까지(또는 그 이상)의데이터의 로딩의 여러가지 측면(비용,속도)을 생각하면, Avro포맷을 고려해 보는 것도 좋은 선택이 될 수 있을 것이다.

   

참고자료

https://cloud.google.com/bigquery/docs/

https://cloud.google.com/bigquery/loading-data

https://cloud.google.com/bigquery/docs/loading-data-cloud-storage

https://cloud.google.com/bigquery/data-types

https://cloud.google.com/bigquery/data-formats

https://cloud.google.com/bigquery/bq-command-line-tool

 

구글 클라우드 시작하기

구글 클라우드의 서브넷과 NAT 네트워크 구성하기

 최유석

구글 클라우드의 인스턴스(VM)과 네트워크를 활용하여 서브넷 구성으로 간단한 웹 어플리케이션을 구성해보고 그 웹 어플레케이션 서버에 NAT(Network Address Translation) Gateway를 추가하여 구성해 보도록 한다.

 

네트워크 구성요소 

 

서브넷 정의?

하나의 공공 네트워크(공인IP)를 논리적으로 분할하여 여러 개의 지역 네트워크(사설IP)로 사용할 수 있게 해주는 방법이다.

 

한정적인 네트워크 자원인 공인IP주소의 효율적인 관리 및 사용을 할 수 있게 해준다. 또한 트래픽을 분산하여 통신속도를 높이는 효과가 있으며, 네트워크를 분할 하여 독립적인 네트워크로 사용하여 보안상에서의 이점을 얻을 수 있다.

 

구글 클라우드에서 서브넷(사설IP : Internal IP)은 리전 범위에서 미리 지정된 범위에서 생성되는 자동(auto)모드와 사용자가 직접 IP범위를 지정하여 생성할 수 있는 맞춤설정(custom) 모드로 서브넷 생성이 가능하다.

 

네트워크 종류

자동(auto)모드

자동(auto)모드에서는 사전에 지정된 IP범위로 자동 생성되며 리전 당 각각 하나의 서브넷으로 구성 할 수 있다.

자동(AUTO)모드에서 사전에 지정된 범위

출처 : https://cloud.google.com/compute/docs/networking#subnet_network

 

맞춤설정(custom)모드

맞춤설정(custom)모드는 사용자가 직접 IP범위(10.0.0.0/8 또는 192.168.0.0/16이내)를 지정하여 서브넷을 구성할 수 있다.

 

레거시(Legacy) 모드 : non-subnetwork

구글 클라우드 안에서 서브넷없이 단일 IP범위로 단일 게이트웨이로 구성되는 네트워크로 모든 리전범위에 걸쳐서 사용 할 수 있다. IP주소는 전체범위로 생성되기 때문에 리전이나 존범위에서 연속적이지 않을 수 있다.

*레거시 모드의 경우 클라우드 콘솔(Web UI)로 생성 할 수 없으며, CLI 툴(Cloud SDK, SSH등)을 사용해서 gcloud명령어를 통해서 만 생성 가능하다.

 

네트워크 참고사항

Default네트워크는 자동(auto)모드로 생성되는 네트워크이다.

* 네트워크는 프로젝트당 5개까지 구성할 수 있다.

* 프로젝트당 최대 100개까지 서브넷 생성이 가능하다.

*각각의 네트워크들은 상호 변경이 불가능하며, VM인스턴스 또한 처음 생성할 때에 지정한 네트워크(Internal IP)의 경우 변경이 불가능하다.

 

NAT(Network Address Translation) Gateway

사설IP를 공인IP로 변환하여 주는 통신망의 통신 변환기이다. NAT을 사용하는 목적은 다수의 사설IP를 하나의 공인IP로 변환하여 다수의 사설IP가 하나의 공인IP를 사용할 수 있도록 함으로써 한정자원인 공인IP를 절약하는 효과가 있다. 또한 공개된 인터넷에 사설IP의 외부노출 및 직접연결을 차단하고 방화벽을 설치하여 외부공격으로부터 사용자의 통신망을 보호하는 기본적인 수단으로 활용 할 수 있다.

 

IP주소

Internal IP(내부/사설 IP) :

모든 VM은 생성 시 내부 IP를 가진다. 적용되는 IP는 위에서 설명한 서브넷(auto or custom)또는 레거시(legacy)로 지정한 IP범위를 가지게 되고 같은 네트워크 상에서는 VM인스턴스의 이름을 기반으로 내부 VM들과 통신을 한다. 외부 인터넷과의 통신이 제한된다.

 

External IP(외부/공인 IP) :

내/외부(인터넷) 통신이 가능하며, 임시(ephemeral), 고정(static), 없음(none)으로 생성 가능하다. 구글 클라우드에서 같은 네트워크가 아니더라도 VM인스턴스들은 외부IP를 통해 통신하게 되며 외부IP로 통신하더라도 구글 내부망을 이용하기 때문에 속도, 보안, 비용적인 측면에서 이점을 가진다.

 

Routes(경로)

네트워크에서 효율적인 통신을 위해서 수많은 네트워크들 중 최적의 경로를 결정하는 역할이 필요하다. 이때 필요한 것들 중의 하나가 Route이다. 이러한 Route들이 모여서 Routing Table(라우팅 테이블)이 된다.

구글 클라우드에서의 Routes란 일종의 라우팅 테이블이며 전체 글로벌 범위에서 사용 가능하다. 네트워크 생성 시 인터넷 게이트웨이와 내부 네트워크에 대한 경로는 기본적으로 생성되며, 추가적인 경로 설정을 통해 다대일(many-to-one) NAT(Network Address Translation) Gateway, VPN(Virtual Private network) Gateway 구성 등에 사용할 수 있다.

 

방화벽 규칙(Firewall-rules)

구글 클라우드 네트워크로 들어오는 모든 Inbound 트래픽에 대해서 막혀 있으며, 인바운드 허용(Inbound Allow)규칙만 생성 할 수 있다.

 

default네트워크에서 TCP 22번포트(SSH), 3389(RDP), icmp, Internal(VM간의 통신)을 제외하고 모두 막혀 있다(= 직접 서브넷이나 레거시로 구성하여 내트워크를 생성하는 경우에 방화벽 규칙이 없다.)

 

CIDR표기법과 VM인스턴스 태그를 사용한 범위로 트래픽을 제한 할 수 있다.

 

네트워크 로드밸런싱(TCP/UDP 기반)

TCP 로드밸런서는 HTTP 로드밸런서와는 다르게 리전 단위로만 사용이 가능하다. (리전간의 밸런싱은 HTTP 로드밸런서만 가능하다.) 리전 범위에서 서버의 부하를 분산하고 장애를 인지하여 밸런싱 하는L4스위치와 비슷한 기능을 가진다.

또한 pre-warming이 필요 없어서 구성 후 바로 사용 가능하다.(몇몇 클라우드 로드밸런서의 경우 갑자기 높은 부하를 주면 받아내지 못하는 경우가 있어서 미리 그만한 부하를 지속적으로 줘서 로드밸런서의 크기를 키워주는 pre-warming이 작업이 필요하다)

 

HTTP(S)로드 밸런싱도 가능하며 자세한 내용은 아래의 주소를 참고하기 바란다.

http://bcho.tistory.com/1111

http://bcho.tistory.com/1113

 

*기본적인 TCP/UDP 네트워크 로드밸런싱의 흐름

출처: https://cloud.google.com/compute/docs/load-balancing-and-autoscaling#network_load_balancing

 

프로토콜 전달(protocol forwarding)을 사용하기 위해서 전달규칙(Forwarding rule)에서 지정한 IP를 통해 요청이 들어오면 해당 요청에 대해서 처리할 수 있게 지정한 인스턴스 또는 인스턴스 풀에 전달하여 요청을 처리한다. 추가적인 옵션으로 Health check를 구성하여 주기적으로 인스턴스의 상태를 체크하고 상태가 안좋은 인스턴스의 경우 제외하는 기능을 한다.

 

리전과 존(Region / Zone)

리전은 지리적인 위치인 대륙 범위로 생각하면 될 것이다.

현재 미국 동부, 중앙과 유럽 서부와 아시아 동부 리전이 있다. 존은 각각의 리전(지역)에 실제로 위치한 데이터 센터이다.

 

 

기본적으로 구성될 구성요소들과 용어들에 대한 간단한 소개를 하였으며 이제 서브넷과 TCP로드 밸런싱을 이용해 간단한 웹 어플리케이션을 구성해보고, 추가적으로 NAT gateway구성을 해보도록 하자.

 

네트워크 및 서버 구성하기

 

구글 클라우드 가입하기

먼저 https://cloud.google.com/ 에 접속해서 Try It Free버튼을 클릭하여 로그인을 한 후, 해당되는 내용들을 입력하여 구글 클라우드 서비스에 가입을 한다.(신용카드 정보 입력 필요)

 

계정이 생성되면 자동으로 $300한도로 60일동안 사용할 수 있는 무료 평가판으로 이용 가능하다. ($300을 먼저 소모하거나 60일이 경과하면 소멸한다.)

신용 카드정보를 입력하지만 확인 용도이며, 사용자가 직접 업그레이드를 하지 않는 이상 비용이 결제 되지 않는다.

 

프로젝트 생성

구글 클라우드는 VM을 포함한 모든 서비스 자원들을 묶은 하나의 컨테이너 형태로 프로젝트라는 개념을 사용한다. 처음 무료 평가판을 등록하면 프로젝트가 없으니 새로 생성하여야 한다.

 

네트워크 생성하기

좌측 상단의 탭을 선택하고 COMPUTE부분에서 하단의 Networking을 선택하여 네트워크 메뉴로 이동한다.

 

 

 

상단의 CREATE NETWORK메뉴를 선택하고 네트워크를 생성한다.

  • Name : sub-nw
  • Subnetworks -> custom : Name : sub-asia

Region : asia-east1

IP address range : 192.168.10.0/24

 

이번 예제는 네트워크 이름 sub-nw(임의의 값)

Subnetworks에서 Custom을 선택하고 서브넷의 이름은 sub-asia(임의의 값)

Region(지역)은 asia-east1을 선택하고 범위는 192.168.10.0/24(지정가능한 범위<10.0.0.0/8 또는 192.168.0.0/16이내>에서 임의의 범위) 로 지정하였다.

 

아래와 같이 네트워크가 생성되었다.

 

간단하게 프로젝트내부의 네트워크 정보를 확인 할 수 있으며 해당 이름을 클릭하면 자세한 정보를 얻을 수 있다.

 

방화벽규칙(Firewall-rules) 생성

좌측메뉴에서 Firewall rules를 선택하면 방화벽 규칙들에 대한 정보를 얻을 수 있으며 관리를 할 수 있다. 위에 설명한대로 default네트워크를 제외하고는 내부통신을 위한 TCP, UDP, ICMP까지 모두 수동으로 생성해야 한다.

 

상단의 CREATE FIRLWALL RULE메뉴를 클릭하여 방화벽을 생성한다 

 

  • Name : asia-sub-internal
  • Network : sub-nw
  • Source filter : Subnetworks -> sub-aisa 192.168.10.0/24
  • Allowed protocols and ports : tcp;udp;icmp

 

방화벽 이름은 asia-sub-internal 으로 Network는 이전에 생성한 sub-nw 를 선택하고

Source filter는 Subnetworks를 지정해서 이전에 생성한 sub-asia를 선택한다.

Source filter의 경우 위에 설명한 CIDR범위나 인스턴스 태그를 지정하여 허용하게 할 수 있다. 또한 하단의 Target tags는 인스턴스 태그만 지정 가능하며, 지정하지 않을 경우 해당 네트워크의 모든 인스턴스에 적용된다.

Allowed protocols and ports같은 네트워크안에서 VM들의 통신을 위해 tcp;udp;icmp 를 입력하여 생성한다.

 

추가로 SSH접속을 위한 TCP 22번 포트 방화벽 생성

 

  • Name : asia-sub-ssh
  • Network : sub-nw
  • Source filter : Allow form any source (0.0.0.0/0)
  • Allowed protocols and ports : tcp:22

 

TCP 22번 포트의 경우 외부에서 SSH 접속을 위한 용도 때문에 0.0.0.0/0(모든 범위)로 생성한다.

프로젝트 환경에 맞게 지정하길 바라며 이 예제에서는 모든 범위로 지정한다.

 

VM 인스턴스 생성

좌측 상단 탭을 클릭하여 Compute Engine탭으로 이동한다.

 

상단의 CREATE INSTANCE를 클릭하여 VM을 생성한다.

 

이 예제에서는 다음과 같이 구성한다.(각자 원하는 환경으로 Machine type, Zone등은 편하게 구성해도 무방하며 리눅스 기반의 OS로 설명한다)

 

  • VM인스턴스 이름 : nat-node-as-1
  • Zone : asia-east1-a
  • Machine type: 1vCPU, 3.75 – n1-standard-1
  • Boot disk는 Change클릭하여 Ubuntu 14.04 LTS / SSD 10GB
  • Identity and API access는 default access로도 충분하지만 Full access선택
    (구글 클라우드 서비스들에 대한 VM의 액세스 범위를 지정하는 부분이다. 생성 후 에는 추후에 변경이 불가능하니 신중하게 선택해야 한다.)
  • 하단의 Management, disk, networking, SSH keys를 클릭하여 첫번째 Management탭에서 Tags를 nat-as 세번째 Networking탭에서 network는 위에서 생성한 sub-nw를 선택하고
  • Subnetwork는 역시 위에서 생성한 sub-asia 을 선택한다
  • Internal IP(내부IP)는 Automatic(자동)또는 Custom(맞춤설정)으로 직접 이전에 생성한 범위에 맞춰서 생성한 범위로 지정 가능하나, 이 예제에서는 자동으로 생성하겠다. (위에서 생성한 아시아 리전의 서브넷인 sub-asia범위로 지정한 192.168.10.0/24범위에서 자동 생성된다.)
  • External(외부IP)는 Ephemeral(임시)로 생성한다. 이후 NAT구성시 none(없음)으로 변경 예정이다.
  • 나머지 값은 기본값으로 적용하여 생성한다.

 

두번째 VM인스턴스 생성

위에서 생성한 인스턴스 nat-node-as-1이 생성되면 이름을 클릭하고 상세페이지로 들어가서 상단의 CLONE를 클릭한다.

 

 

모든 값이 동일한지 확인하고 만약 다르다면 위에서 설정한 값과 동일하게 설정하고 인스턴스 이름을

nat-node-as-2 , Zone을 asia-east1-b로 선택하여 추가로 인스턴스를 생성한다.

 

기존의 구성이 완료된 인스턴스를 복제하는 방법

먼저 복제할 인스턴스의 디스크를 이용해 Snapshots(복제본)을 만든다.

 

CREATE SNAPSHOT을 클릭하여 스냅샷을 생성한다.

 

  • Name : node-ex-my-disk
  • Source disk : nat-node-as-1
  • 나머지 : 기본값

스냅샷의 이름(임의의 값)을 입력하고 source disk를 선택(기본적으로 인스턴스 들의 이름과 동일하게 생성되어 있음)하여 생성한다.

 

그 다음 Disks 탭으로 이동하여


CREATE DISK를 클릭하여 DISK를 생성한다.

 

  • Name : node-ex-my-disk
  • Zone : asia-east1-a
  • Source type : Snapshot
  • Source snapshot : node-ex-my
  • Size : 10GB (스냅샷과 동일하게 또는 더 크게)
  • 나머지 : 기본값

디스크의 이름(임의의 값)을 입력하고 해당 DISK를 위치 시킬 Zone를 선택한다.

DISK의 경우 Zone범위의 리소스이다.

디스크 타입을 원하는 대로 선택하고 source type에서 중간의 Snapshot를 선택한다.

Source snapshot에서 앞서 생성한 스냅샷(모든 설치, 구성이 완료된 VM디스크의 스냅샷)을 선택하고 디스크 크기는 기존의 크기와 같게 또는 더 크게 생성한다.

 

스냅샷을 이용해서 디스크를 생성하고 Images탭으로 이동해서 해당 디스크에 대한 이미지를 생성한다. 이미지란 OS를 포함한 DISK를 말하며 해당 사이즈는 최소 크기이다.

 

상단의 CREATE IMAGE를 선택하여 이미지를 생성한다

 

  • Name : node-ex-my-ubunt
  • Source : Disk
  • Source disk : node-ex-my-disk (스냅샷을 통해 새로 생성한 디스크)

이미지의 이름(임의의 값)을 입력하고 소스를 DISK로 지정하고 Source disk는 앞서 스냅샷으로 생성한 디스크를 선택하여 생성을 완료한다

생성이 완료되면 VM인스턴스 생성 시 이미지(OS) 선택 부분에서 Your image탭에서 임의로 생성한 이미지를 통해 기존 VM인스턴스의 디스크를 복제한 이미지로 생성이 가능하다.

 

 

 

이 예제에서는 node.js와 MySQL을 이용해 간단한 웹 어플리케이션을 구성할 예정이다. node.js 및 MySQL설치 및 구성에 대한 자세한 설명은 생략한다.

프로그램의 기본적인 설치 후 npm express로 웹 프로젝트를 생성하고 MySQL에 입력한 값을 select query를 통해 읽어서 화면에 출력하는 웹 어플리케이션이다

 

VM인스턴스 페이지에서 해당 VM의 오른쪽에 있는 SSH 버튼을 클릭하여 터미널에 접속하여 프로그램들을 설치하고 구성한다.

 

웹 브라우저 접근을 위한 http(80포트) 방화벽 규칙을 추가한다.

  • Name : asia-sub-http
  • Network : sub-nw
  • Source filter : Allow form any source (0.0.0.0/0)
  • Allowed protocols and ports : tcp:80

 

먼저 앞서 생성한 VM의 내/외부 IP정보를 확인하자.

 

다음은 간단하게 node.js express 모듈로 웹 프로젝트를 만들고 MySQL서버에서 사전에 입력한 테이블 데이터를 가져오는 웹 어플리케이션이다.

어플리케이션이나 데이터 값이 적기 때문에 nat-node-as-1에 MySQL을 설치하고 테이블을 구성하고 값을 입력하였으며, nat-node-as-2에서는 nat-node-as-1의 MySQL DB정보를 참조하여 데이터를 읽는다.

MySQL 접속 정보이다. 인스턴스 nat-node-as-1은 자신의 DB를 사용하기 때문에 localhost로 접근하고

인스턴스 nat-node-as-2은 nat-node-as-1과 내부통신을 통해서 nat-node-as-1의 MySQL에 접근하기 위해 접속할 호스트를 nat-node-as-1의 내부IP정보(192.168.10.2)로 설정한다.


해당 웹 어플리케이션을 구동한 모습

이제 서로 다른 IP로 구성된 VM인스턴스들을 네트워크 로드밸런싱을 적용하여 하나의 IP를 사용하여 접근 할 수 있도록 하겠다.

 

네트워크 로드밸런싱 구성하기

좌측상단 탭을 이용해 네트워킹메뉴로 이동하여 좌측 중간의 로드 밸런싱 메뉴를 선택한다.

 

Create load balancer 버튼을 클릭하여 나온 3가지 메뉴 중 TCP Load Balancing에서 Start configuration을 클릭한다.

 

이름은 임의로 web-target을 입력하고

 

  • Name : web-target

 

Backend configuration

  • Region : asia-east-1
  • Backends : Select existing instances -> add an instance 

                                                                            : nat-node-as-1,nat-node-as-2

 

리전을 asia-east1을 선택하고Backends에서 기존 인스턴스를 클릭하고 Add an instance를 통해 앞서 생성한 nat-node-as-1, 2를 추가한다.

나머지 값은 기본값으로 하고 설정한다.

*Backup pool은 사전에 백업해서 구성 인스턴스 풀을 이용하여 헬스체크를 하여 장애조치를 하는 옵션이고,

Health check는 백엔드에 구성된 인스턴스의 상태를 체크하여 상태가 나쁜 인스턴스를 제외하는 기능이며,

Session affinity는 설정 옵션에 따라서 요청에 대한 처리를 지정해서 할 수 있게 하는 기능이다.

 

Frontend configuration으로 이동한다. IP의 경우 새로 고정IP를 생성하여 진행하며 포트는 80으로 설정한다.

 

 

임의로 IP 이름이 lb-ip인 고정 IP를 생성하고 선택한다.

 

  • IP : 104.155.228.179(lb-ip)
  • Port : 80

이제 기본적인 설정은 끝났으며 TCP로드밸런서를 생성한다.

Health check 생략하여 경고가 나온다. 해당 옵션은 추가가 가능하며 로드밸런서 설정이 이 가이드에서 설명하고자하는 주요내용이 아니기 때문에 이 예제에서는 생략하고 진행한다.

 

nat-node-as-1, 2 인스턴스에서 어플리케이션을 실행하고 로드밸런서의 동작을 테스트해보자. 프론트로 설정한 IP인 104.155.228.179로 접근 하면 다음과 같이 정상적으로 동작됨을 확인 할 수 있다.

 

VM인스턴스 페이지로 이동하면 앞서 생성한 VM들이 앞서 구성한TCP 로드밸런서인 web-target에 사용되고 있음을 확인할 수 있다.

 

기본적인 TCP네트워크 로드밸런싱을 적용하여 웹 어플리케이션 서버와 네트워크 구성을 완성하였다.

 

TCP네트워크 로드밸런싱을 적용한 네트워크 및 VM구성도

 

NAT를 이용하기

이제 로드밸런싱을 통해 고정IP로 접속이 가능하기 때문에 해당 VM들의 외부IP를

제거하여 외부인터넷과의 직접 연결을 차단하여 보안성을 향상 시킬 수 있다.   


앞서 설명한 것처럼 내부IP만으로는 인터넷에 접근이 안되기 때문에 이후 인터넷에

연결이 필요한 경우(추가적인 프로그램설치, 등) 에 제한이 생긴다. 따라서

현재의 보안성을 유지하고 외부 인터넷에 접근할 수 있게 하기 위해서 NAT gateway를 구성해보자.

 

외부(External IP제거)

이제 로드밸런싱을 통해 고정IP로 접속이 가능하기 때문에 해당 VM들의 외부IP를 없애고 인터넷과의 직접 연결을 차단하여 보안성을 높여보자

 

VM인스턴스의 이름을 클릭하여 상세페이지로 이동하여 상단의 EDIT를 클릭한다.

External IP부분이 선택할 수 있게 변경되며 None를 선택하고 저장한다..

nat-node-as-2도 같은 방식으로 외부IP를 제거한다.

 

아래 이미지는 외부 IP를 제거한 모습이다.

 

NAT Gateway 역할의 VM생성

VM 인스턴스 명은 nat-gw-as(임의의 값)으로 하고  나머지부분은 전체적으로  앞서  생성한 VM(어플리케이션 서버)들의 설정을 따라 구성한다.  

 

다르게 구성할 부분은 태그는 생략해도 되고,  하단의 추가 옵션부분에서 IP forwarding를 On으로 지정 하여야 한다. (해당부분을 제외하고 임의로 구성하여 생성할 수 있음)

 

*IP forwarding의 경우 최초 VM생성 시에만 적용 할 수 있다.

*일관된 기능을 위해 외부IP는 고정IP로 생성하는 게 권장되나 FREE TRIAL의 경우 리전 당 하나의 고정IP만 생성 가능하다.  

앞서 설정한 로드밸런서 생성 시에 해당 리전에서 고정 IP를 사용하였기에 임시IP로 생성한다.

 

Route 생성

앞서 설명한 것처럼, Route(경로)란 네트워크에서 통신을 위해서 필요한 경로이다. 이러한 경로에 여러가지 옵션을 적용하여 외부 인터넷과의 연결이 가능하게 할 수 있게 해주는 NAT gateway에 필요한 설정을 할 수 있다.

여기에서는 어플리케이션 역할을 하는 nat-node-as-1, 2에서 외부 인터넷으로 트래픽을 내부통신을 통해서 NAT gateway역할을 하는 nat-gw-as로 전달하고 전달받은 트래픽 요청을  nat-gw-as의 외부IP로 외부 인터넷에 접근하는 방식을 적용한다.

 

네트워크 메뉴로 이동해 Routes탭으로 이동한다.

 

CREATE ROUTE버튼을 클릭하여 route를 생성한다

  • Name : nat-route
  • Network : sub-nw
  • Destionation IP range : 0.0.0.0/0
  • Priority : 800
  • Instance tags : nat-as
  • Next hop : Specify an instance
  • Next hop instance : nat-gw-as

 

route 이름은 nat-route(임의의 값)으로 입력하고 Network는 해당 네트워크인 sub-nw를 선택한다.

Destination IP range는 0.0.0.0/0 (전체 인터넷에 접속하기 위해 제한을 두지 않음) 으로 지정하고  

Priority(우선순위) 는 800 (기본적으로 자동 생성된 route의 경우 1000)  

Instance tags(인스턴스 태그)는 앞서 nat-node-as-1, 2인스턴스 생성 시 입력한 태그인 nat-as를 입력하고  

Next hop은 Specify an instance로 변경하여 인스턴스를 NAT gateway역할을 할 VM인스턴스 인 nat-gw-as로 선택하고 생성한다.

 

iptables을 통한 NAT gateway 구성

iptables란?

리눅스에서 사용하는 방화벽을 구성하는 유틸리티이다.

 

VM인스턴스 SSH접속

VM인스턴스 페이지에서 nat-gw-as VM의 오른쪽에 있는 SSH버튼을 통해 SSH터미널에 접속한다.

 

접속 후 다음 명령어를 실행하여 IP전송을 활성화 한다

%echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

 

이후, 다음 명령어를 실행하여 마스커레이드(MASQUERADE)를 활성화하여 사설IP를 외부 인터넷과 연결 가능하게 한다. (따로 표시되는 내용 없음)

%sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

 

앞서 구성한 TCP로드밸런싱이 적용된 웹 어플리케이션 서버들에 추가적으로 구성한 NAT gateway에 대한 구성이 완료되었다.

 

NAT gateway 적용이 완료된 네트워크 및 VM 구성도

 

NAT gateway 테스트

SSH를 통해 nat-node-as-1, 2에 접속

%ssh nat-node-as-1

 

nat-node-as-2도 같은 방식으로 접속한다. 만약 권한이 부족하다고 나오면 다음 두단계의 명령어를 실행해서 접속을 시도해보고

% eval `ssh-agent`

% ssh-add ~/.ssh/google_compute_engine

만약 두번째 명령어 실행 시 해당 파일, 디렉토리를 찾지 못한다면

다음 명렁어를 실행하여 SSH 키를 생성하고 다시 시도한다

% gcloud compute ssh nat-gw-as --ssh-flag="-A" --zone asia-east1-a

 

리눅스의 router 경로추적 명령어인 traceroute를 입력하여 경로 확인하기

NAT gateway로 지정한 nat-gw-as의 내부IP인 192.168.10.4를 경유해서 www.google.com에 접속하는 것을 확인 할 수 있다.

VM인스턴스 : nat-node-as-1

VM인스턴스 : nat-node-as-2

 

기존에 외부IP를 제거하기 전 traceroute로 경로를 수집한 결과이다.

아파치 벤치마크를 이용해서 부하를 주고 테스트 해보자

100개의 클라이언트로 각각 3000개의 부하를 주었다

먼저 위에서 구성한 TCP 로드밸런싱으로 구성한 어플리케이션의 경우

% ab -n 3000 -c 100 http://104.155.228.179/

 

단일 노드(동일한 내부구성을 가진 단일 VM인스턴스를 신규 생성)

%b -n 3000 -c 100 http://104.199.169.70/

같은 zone에 생성하였기 때문에 접속시간은 거의 동일하며 서버에서 처리되는 시간과 대기시간에서 차이를 보인다. 앞서 설명한 것처럼 서브넷으로 웹 어플리케이션 서버를 구성하고, 또한  TCP네트워크 로드 밸런서를 이용하여 부하를 분산하기 때문에 나타난 결과이다.

 

서브넷을 통한 웹 어플리케이션 두대의 서버구성을 하였으며 또한 효율적인 트래픽 처리를 위해 부하를 분산하는 기능을 하는 네트워크 로드 밸런싱을 적용하였으며, 중간에 NAT gateway를 구성하여 외부 인터넷의 직접 연결을 차단하여, 보안성을 높인 구성을 하였다. 이러한 방법을 통해 웹 서버 구성을 조금 더 쉽게 할 수 있기를 바란다.

 

참고자료

https://cloud.google.com/compute/docs/networking

https://cloud.google.com/compute/docs/subnetworks

https://cloud.google.com/compute/docs/protocol-forwarding/

https://cloud.google.com/compute/docs/load-balancing/network/forwarding-rules

https://cloud.google.com/compute/docs/load-balancing/network/target-pools

https://cloud.google.com/compute/docs/load-balancing/network/

 

실습 참고 자료

https://cloud.google.com/compute/docs/load-balancing/network/example

https://codelabs.developers.google.com/codelabs/cloud-subnetworks/index.html?index=..%2F..%2Findex#0

https://codelabs.developers.google.com/codelabs/cloud-networking-101/index.html?index=..%2F..%2Findex

https://codelabs.developers.google.com/codelabs/cloud-networking-102/index.html?index=..%2F..%2Findex#0

 

 

 

구글 클라우드 시작하기

구글 클라우드 네트워크 이해하기

최유석

 

구글에 대해서 이야기를 할 때 수많은 서비스(검색, 지도, Apps, Gmail, YouTube, 등)뿐만 아니라 그러한 서비스들의 기반이 되는 수많은 데이터센터와 네트워크에 대해서 이견이 없는 한 그 어떤 기업도 따라오기 힘든 가장 강력한 인프라를 가진 회사라는 것에 대하여 인정 할 것이다. 앞서 언급한 구글의 내부 서비스뿐만 아니라 구글 클라우드에서 제공하는 네트워크 서비스에도 같은 인프라를 사용하고 있다. 이 글에서는 그러한 구글 클라우드에서 제공하는 기본적인 네트워크 서비스에 대해서 설명하고자 한다.

 

구글의 클라우드의 네트워크 인프라

구글 클라우드에 구축된 네트워크 기술인 주피터(Jupiter)는 초당 양방향 대역폭이 1페타비트 이상을 제공하며 최대 1.3Pbps을 지원한다. 메쉬구조인 클로스 토폴리지(Clos topology)를 적용하고 범용 스위치를 활용해 큰 규모의 스위치를 논리적으로 구현했다. 이를 효율적으로 제어하기 위해 중앙에서 제어하는 SDN(Software Defined Networking)을 구현했으며 오픈소스인 오픈 플로우(Open Flow)를 활용해 작동된다.

 

구글의 데이터센터들은 서로 광케이블 기반의 백본 네트워크로 묶여 있다. 또한 30개의 국가에 70개이상의 Points of presence(또는 Edge node)라고 해서 일종의 중계 서버를 배치하여 이 중계서버를 활용해 광케이블 네트워크를 사용할 수 있어서 글로벌 서비스 시에 거리에 따라 속도가 저하되는 일반 인터넷 망을 이용한 서비스에 비해 빠른 응답속도를 보장할 수 있다. (자세한 내용은 http://bcho.tistory.com/1109 참고)

 

리전과 존(Region / Zone)

리전은 지리적인 위치인 대륙 범위로 생각하면 될 것이다.

현재 미국 동부, 중앙과 유럽 서부와 아시아 동부 리전이 있다. 존은 각각의 리전(지역)에 실제로 위치한 데이터 센터이다.

네트워크의 구성요소 및 참고사항

구글 클라우드에서 내부 통신은 IPv4 유니캐스트(unicast)기반으로 통신하며, IPv6는 아직 지원되지 않는다.

 

네트워크와 프로젝트, 인스턴스의 관계

네트워크는 하나의 프로젝트안에 묶이고 하나의 프로젝트에 5개까지 생성 가능하다. 또한 VM인스턴스들은 하나의 네트워크안에 묶이고 하나의 네트워크에 다수의 VM을 연결할 수 있다.

 

VM인스턴스사이의 통신

각각의 VM들은 TCP, UDP, ICMP를 통해서만 통신한다.

 

네트워크 종류

네트워크 구성은 범위의 제약이 없는 하나의 글로벌 IP를 가지는 레거시 네트워크(legacy network) 또는 리전 범위의 서브넷(Subnet network)을 구성 할 수 있다.

 

레거시 네트워크의 경우 IP주소가 리전 또는 존 범위로 그룹화 되어있지 않다. (IP가 연속적이지 않다)

 

Legacy Networks (non-subnet) 예시

이미지 출처 : https://cloud.google.com/compute/docs/networking

 

서브넷의 경우 자동(auto)모드와 맞춤설정(custom)모드로 구성할 수 있으며 자동(auto)모드로 구성 시 미리 정의 된 IP범위(아래 이미지 참조)와 게이트웨이를 사용하여 서브넷이 구성된다.

리전 당 하나의 자동(auto)모드 서브넷 생성 가능

출처 : https://cloud.google.com/compute/docs/networking#subnet_network

맞춤설정(custom)모드로 서브넷을 구성 시에는 생성 시 리전범위에서 IP범위(10.0.0.0/8 또는 192.168.0.0/16이내)를 지정하여야 하며 0, 1또는 다수의 서브넷을 구성 할 수 있다. (프로제트 당 최대 100개)

 

Subnet network 예시

이미지 출처 : https://cloud.google.com/compute/docs/networking

 

레거시(legacy) 네트워크와 서브넷(subnet) 네트워크는 상호 변경이 불가능하다.

 

방화벽 규칙(Firewall-rules)

기본적으로 모든 Inbound(내부로 들어오는) 트래픽에 대해 막혀 있으며Allow 규칙만 생성 할 수 있다. (default네트워크의 경우 SSH연결을 위한 TCP 22번포트, RDP연결을 위한 TCP 3389포트 및 internal, icmp는 생성되어 있다)

 

IP Addresses

Internal IP : 모든 VM은 생성시 임시의 내부 IP를 가지고 있으며 이를 통해 같은 네트워크 상에서 포함된 VM인스턴스의 이름을 기반으로 내부VM들과 통신을 한다. subnet(auto/custom) 및 legacy 네트워크를 구성 시에 Internal IP에 적용된다.

아래 도식은 내부 및 외부와 통신하는 기본 구조를 나타낸 예이다.

External IP : 내부 및 외부(인터넷) 통신이 가능하며 VM생성 시에 임시(ephemeral)또는 고정(static)으로 생성하거나 없음(none)을 선택하여 외부IP(public IP) 없이 생성하고 앞서 설명한 내부IP(private IP)를 이용하여 로드밸런서를 통해 접근을 하게 하는 등의 방법을 이용하여 외부로의 접근을 차단하여 보안을 향상 시킬 수 있다. 또한 임시로 외부IP를 생성하고 고정IP로 변경도 가능하다.

 

아래 도식은 서로 다른 네트워크나 서로 다른 프로젝트에서의 VM간의 통신 예시이다.

**GCP내부에서의 서로 다른 프로젝트, 같은 프로젝트라도 서로 다른 네트워크에서 VM끼리 통신 시 External IP를 통해 통신을 하게 된다. 이 경우에도 외부 인터넷을 통하지 않고 구글 클라우드의 내부 광케이블 네트워크를 이용해서 통신하기 때문에 속도, 보안, 비용적인 부분에서의 이점을 얻을 수 있다.

 

Routes

네트워크에 연결된 글로벌 리소스이다. 각각의 VM인스턴스에 대해 읽기전용으로 생성된 라우팅 테이블이다.

VPN, many-to-one NAT, proxies구성 등에 사용된다.

 

네트워크 구성하기

가입하기

먼저 https://cloud.google.com/ 에 접속해서 Try It Free버튼을 클릭하여 로그인을 한 후, 해당되는 내용들을 입력하여 구글 클라우드 서비스에 가입을 한다.(신용카드 정보 입력 필요)

 

계정이 생성되면 자동으로 $300한도로 60일동안 사용할 수 있는 무료 평가판으로 이용 가능하다. ($300을 먼저 소모하거나 60일이 경과하면 소멸한다.)

신용 카드정보를 입력하지만 확인 용도이며, 사용자가 직접 업그레이드를 하지 않는 이상 비용이 결제 되지 않는다.

 

프로젝트 생성

구글 클라우드는 VM을 포함한 모든 서비스 자원들을 묶은 하나의 컨테이너 형태로 프로젝트라는 개념을 사용한다. 처음 무료 평가판을 등록하면 프로젝트가 없으니 새로 생성하여야 한다.

 

VM 인스턴스 생성하기 (자세한 정보는 http://bcho.tistory.com/1107를 참고)

좌측 상단의 탭을 클릭하여 Compute Engine을 선택하고 VM을 생성한다.

인스턴스이름은 net-test로 zone은 asia-east1-b로 생성하였으며, 나머지는 기본값으로 설정했다. 기본값으로 생성시 Internal IP의 경우 auto로 External IP의 경우 Ephemeral(임시)로 생성된다.

방화벽을 통해 HTTP트래픽 허용하는 부분은 인스턴스 생성 후 에도 변경가능하다.

액세스 범위(Access scopes)는 인스턴스 생성 시에만 지정할 수 있고 이후 변경이 불가능하다. 인스턴스를 사용 할 범위를 생각해서 신중하게 지정하여야 한다.

(기본적인 네트워크 구성 및 확인만 할 예정이다. 이름을 제외하고 기본값으로 선택해도 문제없다. 실제 서비스 구성을 위해 구성 시 에는 해당 서비스에 적합한 구성으로 생성하길 바란다. )

 

구글 클라우드 콘솔(Web UI)을 통해 SSH접속하기

VM생성 후 우측에 SSH버튼을 누르면 SSH에 접속된다.

 

자동(auto)모드로 서브넷 네트워크 생성하기

서브넷을 추가하기전에 다음 명령어를 통해 default로 구성된 서브넷을 확인해보면

%gcloud compute networks subnets list

리전 별로 IP범위가 지정되어 있음을 확인 할 수 있다. 또한 auto모드로 서브넷 생성 시 사전 정의된 IP범위에서 생성되며, 따로 리전과 범위를 지정할 필요 없다.

 

다음 명령어를 통해 자동(auto)모드로 서브넷을 생성한다. create 다음 auto-networks1은 서브넷 이름이니 임의로 생성해도 되며, --mode flag뒤에 auto를 지정하여야 한다.

%gcloud compute networks create auto-networks1 --mode auto

네트워크가 생성된 것을 확인 할 수 있으며, 방화벽 규칙을 생성해야 해당 네트워크를 통한 통신이 허용된다. 기본적으로 전부 막혀있다.

 

방화벽 규칙 생성 예시

%gcloud compute firewall-rules create autonet --network auto-networks1 --allow tcp:22,tcp:3389,udp,icmp --source-ranges 10.140.0.0/20

임의로 방화벽규칙명 : autonet으로 설정하였으며 프로토콜은 tcp22, 3389포트, udp, icmp를 지정하였고 IP범위를 아시아 리전의 사전 정의 범위인 10.140.0.0/20를 지정하였다. 단순 예시일 뿐이며 상황 및 조건에 따라 원하는 형태로 방화벽규칙을 생성 할 수 있다.

 

임의로 방화벽이름을 설정하고 –-network flag를 통해 네트워크를 지정하고 필요한 프로토콜 및 포트를 지정하여 방화벽규칙을 생성하면 된다. IP범위를 지정할 수 도 있다.

 

(참고 : gcloud 명령어 사용 시 다음 명령어가 기억이 안난다면 –-help를 입력하면 다음 명령어에 대한 정보를 얻을 수 있다.

예시

%gcloud –-help

%gcloud compute –-help

%gcloud compute networks –-help

경우에 따라서 –h로 입력해야 나올 수 있음)

다음 명령어를 통해 앞서 생성한 auto-networks를 확인 할 수 있다.

%gcloud compute networks subnets list –-sort-by NAME

 

맞춤설정(custom)모드로 서브넷 네트워크 생성하기

다음 명령어를 실행하여 custom네트워크를 생성한다. 앞서 생성할 때의

–-mode auto를 custom으로 변경해주고 임의의 네트워크 이름만 지정하면된다.

%gcloud compute networks create custom-network1 --mode custom

임의로 네트워크명을 custom-network1으로 지정했다.

네트워크가 생성된 것을 확인 할 수 있으며, 역시 마찬가지로 방화벽 규칙을 생성해야 통신이 가능하다.

 

사용자 정의 서브넷 구성하기 (네트워크와 헷갈릴 수 있으니 유의)

앞서 생성한 custom네트워크에 서브넷을 연결해 생성한다.

auto모드와 다르게 custom모드로 서브넷 구성 시 리전과 IP범위를 지정해야 한다.

 

%gcloud compute networks subnets create subnet-us-central-192 \

--network custom-network1 \

--region us-central1 \

--range 192.168.1.0/24

 

%gcloud compute networks subnets create subnet-asia-east-192 \

--network custom-network1 \

--region asia-east1 \

--range 192.168.7.0/24

%gcloud compute networks subnets create subnet-europe-west-192 \

--network custom-network1 \

--region europe-west1 \

--range 192.168.5.0/24

 

다음 명령어를 실행해 생성한 서브넷들을 확인 할 수 있다.

%gcloud compute networks subnets list --sort-by NAME

 

서브넷을 지정해서 인스턴스생성

%gcloud compute instances create instance1 \

--zone us-central1-a \

--subnet subnet-us-central-192

앞서 생성한 subnet-us-central-192의 IP범위 192.168.1.0/24로 Internal IP가 생성된 것을 확인 할 수 있다. (네트워크끼리 변경은 안되며, 인스턴스에 할당된 네트워크도 변경이 안됨. 신중하게 진행 해야함)

 

앞서 설명한 것처럼 레거시(Legacy) 네트워크로도 구성할 수 있으며, 각각의 환경에 따라서 필요한 네트워크를 구성해서 사용하길 바란다.

 

또한, 구글 클라우드 콘솔(브라우져)에서 좌측 상단 Networking탭으로 이동하면

네트워크와 관련한 정보들을 쉽게 확인 할 수 있다.

 

자세한 내용은 아래 페이지들 참고

https://cloud.google.com/compute/docs/networking

https://cloud.google.com/compute/docs/subnetworks

https://cloud.google.com/compute/docs/networks-and-firewalls

https://cloud.google.com/compute/docs/vm-ip-addresses

네트워크 실습 및 이해하기 좋은 페이지

https://codelabs.developers.google.com/codelabs/cloud-networking-101/index.html?index=..%2F..%2Findex#0

https://codelabs.developers.google.com/codelabs/cloud-networking-102/index.html?index=..%2F..%2Findex#0

구글 클라우드 시작하기

IAM으로 권한 설정하기

최유석 

여러 명의 사용자가 동시에 자원을 공유해서 사용해야 하는 기업 프로젝트 환경에서 리소스에 대한 접근 및 권한 관리는 선택이 아니라 필수이다. 구글의 클라우드에서 제공하는 IAM(Identity and Access Management)은 구글 클라우드 서비스들에 대한 편리하고 일관된 방식으로 통합적인 접근 제어를 제공한다.

 

IAM (Identity and Access Management) 이란?

 

구글 클라우드 서비스의 전체 리소스에 대해서 뿐만 아니라 통합적으로 사용자 또는 특정유형 별로 구글 클라우드 서비스 각각의 단위로 리소스의 접근 범위를 지정해서 해당 리소스에 대한 권한의 관리를 쉽게 할 수 있게 하는 서비스이다.

  

다른 예로, 리눅스의 Permissions은 파일, 디렉토리 단위로 적용한다면, IAM은 구글 클라우드의 서비스의 프로젝트 레벨에서의 전체 리소스 또는 세부적인 단위로 적용한다고 생각할 수 있다..

 

IAM의 필요성

예를들면, 만약에 어떤 기업에서 구글 클라우드 Compute Engine의 VM과 구글 클라우드 스토리지를 이용해서 미디어 서비스를 하고 있으며, 개발자 또는 엔지니어와 디자이너는 각각의 미디어파일과 소스코드의 정보는 공유가 필요하다면 디자이너에게 어플리케이션의 소스코드를 수정할 수 있는 권한을 줄 수도 없고 반대의 경우도 마찬가지 아닌가? 보안도 문제가 되고 안정적인 운영에도 문제가 될 수 있다. 이러한 문제들을 극복하기 위해 구글 클라우드에서 제공하는 권한 제어 서비스가 IAM이다.

 

먼저 구글 클라우드 IAM에서 권한을 부여할 수 있는 유형은 다음과 같다.

  • Google account
  • Service account
  • Google group
  • Google Apps domain
     

IAM 기본 유형 별 정의

 

먼저 구글 계정은 gmail계정이다. (예 : test@gmail.com)

 

다음으로 서비스 계정은 구글 클라우드 서비스에 대한 ID이며 하나의 ID로 다른 구글 클라우드 서비스에 접근할 수 있도록 해주는 이메일 형태의 계정이다. IAM관리 페이지에서 추가로 생성 가능하다. (기본 GCE, GAE 서비스 ID제공)

(예 : <project_id or project number>@developer.gserviceaccount.com 형식이며,

Test-1234@appspot.gserviceaccount.com – project_id 형식,

1234567891011-compute@developer.gserviceaccount.com – project-number 형식)

 

마지막 구글그룹과 구글앱스 도메인은 지정하게 될 경우 해당 모든 구성원에게 권한이 부여된다.

구글그룹 - (예 : test@googlegroups.com) / 구글앱스 도메인 – (예 : test-company.com)

 

* 프로젝트의 식별자로 Project Name, ID, Number 세가지 제공되며 Unique한 값으로 생성하여야 하며 Number는 자동으로 부여된다. Project ID의 경우 APP Engine의 어플리케이션 ID로도 사용되며 프로젝트 삭제 시 다시 같은 ID로 생성할 수 없다.

 

구글 클라우드 IAM은 단순하며 유연한 역할을 제공한다.

기본적인 역할 모델로 보면 다음과 같다.

  • Viewer
  • Editor
  • Owner

먼저 뷰어는 말그대로 구글 클라우드 리소스를 보는 권한만 부여된다.

 

편집자는 보기 권한 + 리소스의 생성/삭제/변경이 추가된다.

 

마지막으로 소유자는 앞의 모든 권한을 가지면서 프로젝트 멤버 및 프로젝트 자체를 관리(추가/삭제)할 수 있는 권한이 부여된다.

*프로젝트 최초 생성시에 소유자레벨의 권한이 부여되어 있다.

 

*기본적인 역할 외에 프로젝트 레벨에서Service Account Actor가 있는데

서비스 별 세분화 한 역할을 지정하여 사용시에 서비스계정의 정보를 획득하고

인증 시 사용하여 보안성을 높인다. (서비스 단위로 권한 적용시 동시 사용)

 

추가적으로 결제와 관련한 부분은 Billing administrator(결제 관리자)를 통해 관리된다. 처음 프로젝트 생성 시에 소유자로 지정되어 있으며 리소스에 대한 권한은 제한된다.

 

IAM설정 방법은 매우 단순하다.

설명을 위해 임의로 프로젝트를 생성하여 진행한다.

예시 프로젝트 명 : iamtest / 프로젝트ID : iamtest-1341

프로젝트 소유 계정 : namu.test1@gmail.com

추가권한 부여 계정 : namu.test2@gmail.com

(만약 기존 프로젝트가 없다면 새로 생성한다. 프로젝트 생성 방법의 자세한 내용은 http://bcho.tistory.com/1107 참고)

 

 

좌측 상단 탭을 이용해서 IAM페이지로 이동한다.

 

먼저 IAM페이지에서 멤버를 추가하려면 ADD MEMBER를 클릭 한다.

Name에 추가하려는 계정 명을 넣고

 

부여하려는 권한 레벨을 선택하고 ADD버튼을 누르면 추가가 완료된다. .

Viewer권한을 가진 멤버의 추가가 완료된 모습이다.

 

추가한 계정(namu.test2@gmail.com)에서 접속한 모습이다. 해당 계정은 이제 프로젝트 iamtest의 리소스를 확인 할 수 있다.

   

프로젝트 소유 계정으로 임의로 인스턴스 생성 후, VM인스턴스 페이지를 확인한 모습이다.

 

비교를 위해 뷰어 권한을 받은 계정으로 접속한 모습이다. 리소스를 변경할 수 있는 권한이 없어서 인스턴스 및 그룹 생성, SSH접속 등이 비활성화 되어있다.

 

임의로 생성한 VM의 상세페이지에서도 VM인스턴스에 대한 조작이 비활성화 되어있다. 이렇듯 리소스에 대한 정보 확인만 가능하다.

 

기본적인 역할 Owner, Editor, Viewer는 프로젝트 전체 리소스에 대해서 적용된다.

 

 

구글 클라우드에서는 앞서 설명한 것처럼 아래와 같이 서비스별로 세분화된 제어도 제공한다.

 

(이미지 출처: https://cloud.google.com/iam/docs/overview)

 

프로젝트 레벨에서의 권한제어를 각각의 서비스 모듈 별로 할 수 있게 확장된 것으로 볼 수 있으며, 이러한 서비스 모듈 별 세부적인 적용을 통해서

전체 프로젝트 리소스 관리의 부담을 줄일 수 있다.

 

자세한 내용은 https://cloud.google.com/iam/docs/를 참고

+ Recent posts