반응형
 
 
1. MacDocker로 MariaDB 준비
 
MariaDB Docker 이미지 다운로드 
 
docker pull mariadb:10.1
 
MariaDB용 Docker 시작 스크립트 생성
참고로 Docker/Home/mysql 디렉토리가 로컬 컴퓨터에 존재해야 한다. 그러면 MariaDB 데이터베이스 파일이 거기에 만들어 진다.
 
MacBook-Pro-2:Docker jerryj$ cat start-mariadb
docker run -d --name mymaria -p 3306:3306 -v /Users/jerryj/Docker/Home/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root mariadb:10.1
 
echo View Log
sleep 1
docker logs -f mymaria
 
 
MacBook-Pro-2:Docker jerryj$ cat mysql
docker exec -it mymaria sh -c 'exec mysql -uroot -p'
 
MariaDB Docker 종료 스크립트
 
MacBook-Pro-2:Docker jerryj$ cat stop-mariadb
docker stop mymaria
docker rm mymaria
 
그러면 다음과 같이 쉽게 MariaDB를 시작하고 종료할 수 있다.
 
MacBook-Pro-2:Docker jerryj$ ./start-mariadb
e0a7793e0b01eb124a506b065b4bba4224b79bccb97d5f2dedca721795e8d07e
View Log
2017-03-26 15:07:39 139941082712000 [Note] mysqld (mysqld 10.1.21-MariaDB-1~jessie) starting as process 1 ...
2017-03-26 15:07:40 139941082712000 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
...
 
MacBook-Pro-2:Docker jerryj$ ./mysql
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 2
Server version: 10.1.21-MariaDB-1~jessie mariadb.org binary distribution
 
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.01 sec)
...
 
MacBook-Pro-2:Docker jerryj$ ./stop-mariadb
mymaria
mymaria
 
자 그러면 테스트할 MariaDB Docker 이미지는 준비되었다.
 
 

2. Replication 구성을 위한 두 개의 MariaDB 컨테이너 준비
 
mariadb:10.1 이미지를 이용하여 두 개의 별도 컨테이너를 생성한다.
동일한 이미지를 사용하지만 이름(mysql-a vs mysql-b), 포트(43306 vs 53306), 데이터베이스 디렉토리, 구성파일 디렉토리 등을 다르게 설정하여 서로 다른 데이터베이스가 되도록 하였다.
참고로 두 개의 컨테이너는 하나의 Docker 네트워크(jerry-network)를 통해 서로 연결되도록 되어 있다.
 
MacBook-Pro-2:Docker jerryj$ cat ./start-db-cluster
docker run -d --name mysql-a -p 43306:3306 -v /Users/jerryj/Docker/Home/mysql-a/mysql:/var/lib/mysql -v /Users/jerryj/Docker/Home/mysql-a/etc:/etc/mysql -e MYSQL_ROOT_PASSWORD=root --network jerry-network mariadb:10.1
 
echo ---------------------------------------------------------------
echo View Log
sleep 1
docker logs mysql-a
 
docker run -d --name mysql-b -p 53306:3306 -v /Users/jerryj/Docker/Home/mysql-b/mysql:/var/lib/mysql -v /Users/jerryj/Docker/Home/mysql-b/etc:/etc/mysql -e MYSQL_ROOT_PASSWORD=root --network jerry-network mariadb:10.1
 
echo ---------------------------------------------------------------
echo View Log
sleep 1
docker logs mysql-b
 
두 개의 MariaDB 인스턴스를 다음과 같이 실행하고 docker ps로 확인한다.
 
MacBook-Pro-2:Docker jerryj$ ./start-db-cluster
56ebb4e06899094276b62474fd384114f2f95aef360239797003b002add7475a
---------------------------------------------------------------
View Log
2017-03-26 15:12:47 140196917458880 [Note] mysqld (mysqld 10.1.21-MariaDB-1~jessie) starting as process 1 ...
2017-03-26 15:12:47 140196917458880 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
520b1848cea06c5189947b229b69646ef33b534b1e24f420d3a8fdcef78a1652
---------------------------------------------------------------
View Log
2017-03-26 15:12:49 140465053243328 [Note] mysqld (mysqld 10.1.21-MariaDB-1~jessie) starting as process 1 ...
2017-03-26 15:12:49 140465053243328 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
MacBook-Pro-2:Docker jerryj$
MacBook-Pro-2:Docker jerryj$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                     NAMES
520b1848cea0        mariadb:10.1        "docker-entrypoint..."   6 seconds ago       Up 5 seconds        0.0.0.0:53306->3306/tcp   mysql-b
56ebb4e06899        mariadb:10.1        "docker-entrypoint..."   8 seconds ago       Up 7 seconds        0.0.0.0:43306->3306/tcp   mysql-a
 
 
각각의 MariaDB 인스턴스는 다음 스크립트를 통해 접속한다.
 
MacBook-Pro-2:Docker jerryj$ cat mysql-a
docker exec -it mysql-a sh -c 'exec mysql -uroot -p'
MacBook-Pro-2:Docker jerryj$ cat mysql-b
docker exec -it mysql-b sh -c 'exec mysql -uroot -p'
 
자 그러면 Replication 테스트를 할 두 개의 MariaDB 컨테이너 준비는 끝났다. 그러면 본격적으로 MySQL(MariaDB) Replication 구성을 진행해 보자.
 

3. Binary Log 복제 설정
 
mysql-a와 mysql-b의 /etc/my.cnf에 각각 다음을 추가
 
MacBook-Pro-2:etc jerryj$ pwd
/Users/jerryj/Docker/Home/mysql-a/etc
MacBook-Pro-2:conf.d jerryj$ vi my.cnf
...
[mysqld]
 
log-bin=binlog
relay-log=relaylog
log-slave_updates=1
server-id=1
 
MacBook-Pro-2:etc jerryj$ pwd
/Users/jerryj/Docker/Home/mysql-b/etc
MacBook-Pro-2:conf.d jerryj$ vi my.cnf
...
[mysqld]
 
log-bin=binlog
relay-log=relaylog
log-slave_updates=1
server-id=2
 
Binary Log 옵션을 적용하기 위해 DB 서버 재시작
 
MacBook-Pro-2:Docker jerryj$ ./stop-db-cluster
mysql-a
mysql-b
mysql-a
mysql-b
MacBook-Pro-2:Docker jerryj$ ./start-db-cluster
16f93e1c4b60fa49383c75d448ac3c54e04abd32d8de045449569e918deee40b
---------------------------------------------------------------
View Log
2017-03-26 15:32:09 140363386005440 [Note] mysqld (mysqld 10.1.21-MariaDB-1~jessie) starting as process 1 ...
2017-03-26 15:32:09 140363386005440 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
120ea03ae6a4db30c1a7ec2683b17b68f6051047015f4d2d5cb5e8ec2bfb3072
---------------------------------------------------------------
View Log
2017-03-26 15:32:11 140592083466176 [Note] mysqld (mysqld 10.1.21-MariaDB-1~jessie) starting as process 1 ...
2017-03-26 15:32:11 140592083466176 [Warning] Setting lower_case_table_names=2 because file system for /var/lib/mysql/ is case insensitive
 
다음과 같이 mysql-a 에서 mysqldump를 실행하여 DB 복사 (암호 root를 입력해야 함)
혹시 fulldump.log 첫 줄에 Enter Password: 문구가 저장되었으면 vi 에디터로 제거한다.
 
acBook-Pro-2:Docker jerryj$ docker exec -it mysql-a sh -c 'mysqldump -u root -p -A --single-transaction --master-data=2' > fulldump.log
 
생성된 덤프 파일을 mysql-b의 디렉토리로 복사한 후 mysql-b로 접속하여 덤프 파일을 실행 
 
MacBook-Pro-2:Docker jerryj$ mv fulldump.log Home/mysql-b/etc/
MacBook-Pro-2:Docker jerryj$ docker exec -it mysql-b bash
root@c20e562c067a:/# mysql -u root -p < /etc/mysql/fulldump.log 
 
mysql-a(Master)에서 binlog 위치를 파악한다.
 
MariaDB [(none)]> show master status;
+---------------+----------+--------------+------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------+----------+--------------+------------------+
| binlog.000001 |      310 |              |                  |
+---------------+----------+--------------+------------------+
1 row in set (0.00 sec)
 
다음 명령을 mysql-b(Salve)의 mysql 쉘에서 실행한다. 노란색 부분은 상대편 DB의 로그/위치를 사용한다.
 
CHANGE MASTER TO
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=310,
MASTER_HOST='mysql-a',
MASTER_USER='root',
MASTER_PASSWORD='root';
START SLAVE;
SHOW SLAVE STATUS\G
RESET MASTER;
SHOW MASTER STATUS;
 
역시 같은 방법으로 mysql-a(Master)의 mysql 쉘에서 실행한다. 노란색 부분은 상대편 DB의 로그/위치를 사용한다.
 
CHANGE MASTER TO
MASTER_LOG_FILE='binlog.000001',
MASTER_LOG_POS=310,
MASTER_HOST='mysql-b',
MASTER_USER='root',
MASTER_PASSWORD='root';
START SLAVE;
SHOW SLAVE STATUS\G
 
 

4. 복제 확인
 
다음과 같이 mysql-a(Master)에서 DB와 계정을 생성한다.
 
MariaDB [(none)]> create database mattermost character set utf8 COLLATE utf8_bin;
Query OK, 1 row affected (0.00 sec)
 
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mattermost         |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.02 sec)
 
MariaDB [(none)]> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
 
Database changed
MariaDB [mysql]> INSERT INTO user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject) VALUES ('localhost', 'mmuser', password('mmuser'), '', '', '');
Query OK, 1 row affected, 1 warning (0.01 sec)
 
MariaDB [mysql]> INSERT INTO user (Host, User, Password, ssl_cipher, x509_issuer, x509_subject ) VALUES ('%', 'mmuser ', password('mmuser'), '', '', '');
Query OK, 1 row affected, 1 warning (0.01 sec)
 
MariaDB [mysql]> flush privileges;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [mysql]> grant all privileges on mattermost.* to mmuser@localhost with grant option;
Query OK, 0 rows affected (0.00 sec)
 
MariaDB [mysql]>
MariaDB [mysql]> flush privileges;
Query OK, 0 rows affected (0.00 sec)
 
그리고 나서 양쪽 데이터베이스에서 로그인을 시도한다.
 
MacBook-Pro-2:Docker jerryj$ docker exec -it mysql-a bash
root@c14263392084:/# mysql -ummuser -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 19
Server version: 10.1.21-MariaDB-1~jessie mariadb.org binary distribution
 
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [(none)]>
 
mysql-b(Slave)에서도 로그인이 된다.
 
MacBook-Pro-2:Docker jerryj$ docker exec -it mysql-b bash
root@c20e562c067a:/# mysql -ummuser -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 33
Server version: 10.1.21-MariaDB-1~jessie mariadb.org binary distribution
 
Copyright (c) 2000, 2016, Oracle, MariaDB Corporation Ab and others.
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
 
MariaDB [(none)]>
 
 
Posted by Hey Jerry
,
반응형
 
 
Google Cloud는 하이브리드 환경을 지원하기 위해 Cloud와 On-Premise 간 VPN 접속을 통한 연결을 제공한다.
 
 
물론 아래와 같이 두 지점(Google Cloud가 제공하는 POP와 On-Premise 데이터 센터) 사이에 직접 전용선을 통해서 연결하는 Interconnect 기능도 제공한다.
 
 
 
Cloud VPN
 
여기서는 Cloud VPN을 사용하는 방법과 실제 구성 테스트를 해 보려고 한다. 실제 구성 테스트는 직접 On-Premise 환경에 테스트 가능한 VPN 장비가 있으면 문제가 없지만 그렇지 못한 경우가 많으므로 여기서는 Cloud의 두 VPC 간을 연결(하나는 Cloud, 다른 하나는 On-Premise를 가정)하는 테스트를 해볼 예정이다. 실제로 이 방법을 이용하면 Google Cloud VPC와 다른 클라우드(예: Amazon AWS)의 VPC를 연결하는 Multi Cloud 환경을 구축하는데도 도움이 될 것이다.
 
먼저 Google Cloud VPN은 IPSec 방식의 VPN을 지원하며 IKE(Internet Key Exchange) 1 및 2 키 교환 방식을 지원한다.
IPSec 방식이 아닌 VPN은 지원하지 않는다.
 
다음은 GCP 내의 두 VPC(실제로 여기서는 서로 다른 GCP 프로젝트) 간에 VPN을 연결하는 모습을 표현한 다이어그램이다.
(Draw.io 다이어그램: 
GCP-VPN.xml
다운로드
)
 
다음은 연결하고자 하는 두 개의 VPC와 각 서브넷이다.
첫 번째 VPC의 서브넷은 asia-northeast1 지역에 위치하는 default이다.
 
상대방에 해당하는 두 번째 VPC 및 서브넷은 myownsubnet이다.
 
자 그러면 VPN을 생성해 본다.
 
(1) 첫 번쨰 프로젝트의 GCP 콘솔에 로그인해서 Interconnect ==> VPN으로 이동
 
 
(2) VPN 생성
 
(3) 두 번째 프로젝트의 GCP 콘솔에서 VPN 생성
 
(4) 첫 번째 프로젝트에서 VPN 터널 구성 (터널은 복수로 구성 가능)
 
Cloud Router를 설정하여 BGP를 이용한 자동 라우팅 구성을 할 수도 있지만, 여기서는 정적인 라우팅만을 테스트한다.
특히 shared secret(공유된 비밀번호)은 양쪽 VPN이 동일하게 지정해야 한다.
 
이렇게 하고 생성하면 아래와 같이 vpn-1은 상대편 vpn-2와 접속을 하기 위해 시도한다.
 
(5) 두 번째 프로젝트에서 VPN 터널 구성
 
두 번째 VPN도 구성이 완료되면 서로 통신을 해서 다음과 같이 연결이 완료된다.
 
(6) VM을 생성하여 상호 통신이 되는지 확인
 
단, 이때 양쪽 VPN을 연결한 서브넷이 존재하는 지역에 VM을 생성해야 한다.
 
다음은 각각 생성된 두 개의 VM이다. 두 개의 VM은 방화벽에서 통신이 가능한 상태이어야 한다.
 
 
(7) 상호 네트워크 연결 테스트
 
다음과 같이 두 번째 프로젝트의 VM(서브넷 10.192.0.0)에서 첫 번째 프로젝트의 VM(서브넷 10.146.0.0)으로 ping과 ssh가 접속된다.
 
 
당연한 얘기지만 여태까지 작성한 VPN 구성을 삭제하면 둘 사이의 네트워크는 다시 단절된다.
 
 
이와 같이 실제 물리적인 VPN 장비 없이 Google Cloud의 VPN 기능을 테스트하였다.
 
참고로 아래는 각종 벤더들의 VPN 장비와 Google Cloud VPN을 연결하기 위한 가이드들이다.
 
 
 
 
 
Posted by Hey Jerry
,
반응형
 
다음과 같이 CSV 파일을 BigQuery 로딩할 때
 
bq load -F " " \
jerryjg-kr-ce-api:test.page_access \
large_csv.txt \
log_dt:string,page_no:integer,page_value:string,psc_url:string,referer:string,user_agent:string,user_ip:string,gd_no:string,sid:integer,affiliate_contract_cd:string,reg_dt:string,tracking_session_id:string,svc_nation_cd:string,inflow_referer:string,gate_flag:string,ref_page_no:string,flowpath_no:string,flowpath_value:string,ref_page_value:string,landing_page_no:integer,landing_page_value:string,gdlc_cd:string,gdmc_cd:string,gdsc_cd:string,login_id:string,cust_age:integer,cust_gender:string,sell_cust_no:string,site_id:string,landing_flowpath_no:string,landing_flowpath_value:string,cust_no:integer,dev_cd:string,app_no:integer,pv_yn:string,add_info2:string,page_context_id:string,client_side_access_yn:string,lang_cd:string
 
 
다음과 같은 에러가 나면서 로딩에 실패하는 경우가 있다. 
 
Upload complete.
Waiting on bqjob_r4d5161fe7efea7dd_0000015ffc077c7b_1 ... (0s) Current status: DONE   
BigQuery error in load operation: Error processing job
'api-project-249965614499:bqjob_r4d5161fe7efea7dd_0000015ffc077c7b_1': CSV table encountered too many errors, giving up.
Rows: 1; errors: 1.
Failure details:
- file-00000000: CSV table references column position 14, but line
starting at position:0 contains only 14 columns.
 
 
에러 메시지의 내용은 15번째 컬럼(0부터 시작)이 정의되어 있지만, 실제로 CSV 파일에는 14개의 컬럼만 정의되어 있어 로딩에 실패했다는 의미이다.
이런 경우는 실제로 필드 수를 잘못 지정해서 발생하는 경우도 있지만 CSV 파일이 잘못 포맷팅(예: Quotation 없이 컴머가 포함)되어 발생하는 경우가 많다.
트러블 슈팅을 하려면 컬럼들을 하나씩 지워가면서 어떤 필드에 문제가 있는지 찾기가 쉽지 않은데,
다음과 같이 --autodetect 옵션을 사용해서 일부 데이터를 로딩하면 쉽게 문제를 찾아낼 가능성이 높다.
 
head -n 100 large_csv.txt > 100.txt
 
bq load -F "," --null_marker "\N" --autodetect \
jerryjg-kr-ce-api:test.page_access \
100.txt
 
 
위와 같이 하면 컴머가 잘못 들어가 있더라도 상관 없이 BigQuery가 자동으로 컬럼들을 추정하여 데이터를 로딩한다.
그러면 BigQuery Web UI에 들어가서 문제가 되는 데이터를 쉽게 찾아낼 수 있다.
이 문제의 경우 웹서버 로그에서 user_agent 부분의 데이터에 컴머가 포함되어 문제가 되었다는 것을 알 수 있다.
 
 
이런 경우에는 CSV를 생성할 때 Quotation(")으로 데이터를 둘러쌓게 하여 Export를 해서 로딩을 해야 한다.
 
 
 
Posted by Hey Jerry
,
반응형
 
Standard SQL의 UDF
 
기존 BigQuery에서 제공 가능한 SQL은 BigQuery 고유의 Legacy SQL뿐이었지만, 현재(2017년 10월)는 SQL 2011과 호환되는 형식의 Standard SQL도 제공하고 있다. Legacy SQL에서 제공하는 UDF는 Map 함수 기반의 방식이며, Standard SQL의 UDF에서 제공하는 것은 실제 SQL 함수와 유사한 방식이다.
Standard SQL이 제공하는 UDF가 기존 BigQuery Legacy SQL의 UDF와 가장 큰 차이는, SQL 문에서 실제로 데이터 연산에 필요한 함수를 제공한다는 점이다. 특히 일반 SQL의 sum, avg 등과 같은 aggregation 방식의 통계 함수도 작성할 수 있다.
 
함수 작성 방법
Standard SQL UDF를 작성하기 위해서는 당연히 BigQuery SQL을 Standard로 전환해야 한다. 다음과 같이 Web UI에서 Use Legacy SQL 옵션을 Uncheck 함으로써 가능하다.
 
그리고 나서 UDF 함수의 내용은 UDF Editor가 아닌 Query Editor에서 직접 입력한다. Query Editor에 입력할 수 있는 SQL 문은 원래 하나로 제한이 되지만, UDF를 작성하는 경우에는 예외적으로 추가로 SQL 문을 작성하여 세미콜론(;)으로 구분할 수 있다. 그리고 User Defined Function의 내용은 Java Script 언어로 작성한다. 다음은 작성한 UDF와 그것을 테스트하는 SQL 문의 예이다.
 
create temporary function udftest(a STRING, b STRING)
returns STRING
language js as '''
return a + ":" + b;
''';
 
SELECT udftest(tbl.by, tbl.author) FROM `jerryjg-kr-ce-api.workshop.comments_copy` tbl LIMIT 1000
 
 
여기서는 udftest라는 함수를 정의하고 입력은 문자열 두 개를 받아 결과로 문자열을 반환한다. 작성 언어 문법은 JavaScript(js)를 사용하고, 내용은 간단하게 두 문자열을 더해 반환하는 것 뿐이다. 실제 SQL 문에서는 udftest 함수에 쿼리 결과에서 나오는 필드 두개를 넣어 호출하였다.
 
Aggregation 함수 작성 방법
 
SQL 문에서 group by 등을 통해 레코드들을 그룹으로 묶으면 그것들의 sun, avg 등과 같은 통계값을 구하는 경우가 있다. Standard SQL UDF에서는 이러한 Aggregation 통계 함수도 작성할 수 있는데, 약간의 예외적인 방법이 필요하다. 일반적인 SQL의 통계 함수는 다음과 같이 group by 절과 함께 함수를 사용하면 자동으로 그것을 감지하여 동작한다.
 
Select sum(tbl.ranking), avg(tbl.ranking) from emp_list;
 
 
하지만 여기 UDF에서는 group by 결과로 만들어진 레코드나 그것의 필드들을 ARRAY_AGG라는 함수로 묶어 배열을 만들어 함수에 전달해야 한다. 다음은 UDF로 만들어진 Aggregation 함수의 예로서 주어진 필드의 max 값을 구하는 함수이다. 실제 SQL이 제공하는 max와 비교하도록 같이 사용하여 보았다.
 
create temporary function udfmax(a ARRAY<INT64>)
returns INT64
language js as '''
var max = 0;
a.forEach(function(i) {
   n = Number(i)
   if(n > max) {
     max = n;
   }
});
return max;
''';
 
SELECT udfmax(ARRAY_AGG(tbl.ranking)), max(tbl.ranking) FROM `jerryjg-kr-ce-api.workshop.comments_copy` tbl group by deleted
 
 
여기 UDF 함수에서는 입력 값이 단일 값이 아닌 ARRAY를 받도록 되어 있는 것을 알 수 있다. 그리고 그것을 사용하는 SQL 구문에서도 ARRAY_AGG() 함수를 이용하여 결과 필드값들을 묶어 배열로 만들어 전달하고 있다.
 
이렇게 만들어지는 UDF 함수는 Query Editor 내에서 작성되는 SQL 세션 내에서만 유효하며 다른 SQL 구문에서는 사용할 수 없다. 즉, 다른 SQL에서 동일한 함수를 사용하려면 같은 내용을 매번 넣어 줘야 한다는 의미이다.
 
 
Posted by Hey Jerry
,
반응형
 

Authorized View를 이용한 특정 데이터 공유

위에서 설명한 것처럼 BigQuery는 하나의 공간에 데이터를 모아 놓고 여러 부서나 사용자에게 필요한 Dataset을 공유해 줄 수 있다. 전통적인 DW에서 필요한 데이터를 ETL을 통해 옮겨 Mart를 구성해 주던 것과 유사하지만, 물리적으로 별도의 저장소(Mart를 위한)를 구성하거나 복제할 필요가 없기 때문에 훨씬 효율적이다. 여기에 더불어 BigQuery는 원하는 데이터만을 SQL 기반 View로 만들어 공유해 주는 기능이 있다.
그림으로 보면 다음과 같다. 원본 Dataset에 들어 있는 A, B, C 테이블의 내용을 join 해서 두 개의 View를 만들어 각각의 Dataset 1, 2에 저장했다. 특히 View를 생성하는 과정에 WHERE 문에서 특정 조건에 부합하는 레코드들만 조회되도록 하였다. 그리고 나서 두 개의 Dataset을 Marketing, Sales, Customer Support와 같은 각각의 부서에 조회 권한을 부여하였다. 그러면 각 부서에서는 조회된 권한이 부여된 데이터와 View에 대해서만 조회가 가능하다.
 
 
이러한 Authorized View를 세팅하는 과정은 다음과 같다. 먼저 다음과 같은 SQL 문을 통해 View를 만든다. 이 때, View를 만드는 SQL은 기존의 Legacy SQL이 아닌 Standard SQL을 사용해야 한다.
 
SELECT title, sum(num_characters) as size
FROM `bigquery-public-data.samples.wikipedia`
where title like '%seoul%' or title like '%Seoul%'
group by title
order by size desc
 
 
Standard SQL 옵션은 다음과 같이 지정한다.
 
RUN QUERY 버튼을 눌러 결과가 나오면 이제 Save Query 버튼을 눌러 View로 저장한다. 여기서 저장할 Dataset을 선택한다.
 
그러면 다음과 같이 View가 만들어진다.
 
해당 View에 대한 공유 설정은 다음과 같이 Share dataset에서 시작한다.
 
먼저 대상 그룹이나 사용자에 대해 Dataset에 대한 View 권한을 부여하고 나서, 다음과 같이 조회 가능한 Authorized View를 선택한다.
 
조회 가능한 View를 선택한다.
 
그리고 나서 Add 버튼을 눌러 추가하면 된다.
 
그러면 다른 사용자가 다음과 같은 쿼리를 통해 조회 가능하다.
 
SELECT * FROM `api-project-249965614499.workshop.testview_wikipedia_seoul` LIMIT 1000
 
 
 
Posted by Hey Jerry
,
반응형
 
 
기부하러 가기: http://www.tofighthiv.org/goto/Jerry 
다가오는 6월 제가 AIDS 환자 돕기 싸이클링 대회인 ALC(AIDS Life Cycle) 2018에 참가합니다. 개인적으로도 어려운 도전(7일간 900km)이고 참가비용(참가/숙박/항공)은 제가 부담을 하지만... 또 한 가지 어려운 점은 환자들을 위한 기부금 모집도 필요합니다. 최소 3000$ 기부가 목표라 이렇게 부탁을 드려봅니다.
 
기부 방법은 아래 링크로 들어가서 다음과 같이 진행하시면 됩니다.
1. "기부하러 가기" 링크
2. 주황색 "Donate Now" 버튼 클릭
3. Gift Information 페이지에서 액수 입력
4. "Next" 버튼 클릭 후 신용카드 결제 정보 입력
5. 다음 페이지에서 최종 확인
 
 
AIDS로 고통 받는 환자들을 위해서, 저 자신의 목표를 향해 달립니다!!!
세상의 인연은 기적입니다. 그 기적은 끝 없이 연결됩니다.
 
불과 6개월 전까지 전혀 알지도 못했던 ALC(AIDS Lifecycle) 2018에 참가합니다.
2015년 대만인으로는 세계 최초로 대회에 참가했던 Edward의 한 마디를 우연히 들었습니다.
그것은 제 가슴을 뛰게 했습니다. 물론 두려움도 있었습니다. 하지만 참가하고싶은 의욕이 더 강했습니다.
Edward가 없었다면 참가는 물론 아마 ALC 존재 자체를 모르고 살았을 것입니다.
 
이제 한국의 추운 겨울도 끝나고 봄이 왔습니다. 그저 묵묵히 준비 중입니다.
같이 최초가 될지는 모르겠지만 또 다른 한국인 참가자이자 저의 친동생 같은 영준도 같이 갑니다.
같이 대회에 참가하지 않으시더라도 둘의 트레이닝에 같이 참여해서 응원해 주시면 어떠실지요!!!
 
제게는 평생을 잊을 수 없는 친구가 있습니다. 짧은 만남이었지만 제 인생을 바꿔준 친구입니다.
40대가 넘은 나이에 만나서 절친이 되었습니다. 부드러움이 강하다는 걸 알게해 준 친구입니다.
마음 먹은 것은 해야 한다는 것을 알게해 준 친구입니다. 가족의 소중함을 알게해 준 친구입니다.
같이 자전거를 타며 시간을 보냈던 그 친구는 그 많은 것을 알게해 주고 하늘 나라에 갔습니다. 
남은 친구들과 같이 달렸던 자전거 길을 가다보면 저도 모르게 아직도 눈물이 납니다.
아마도 저는 그 친구 덕분에 인생의 의미를 깨우친 것 같습니다.
 
세상의 인연은 기적입니다.
 
 
Go Go !!
For patients suffering from AIDS. For my own goals !!!
It is a miracle that we're connected.
 
I will participate in the ALC (AIDS Lifecycle) 2018, which I had never heard until just six months ago.
It was Edward who participated as the first Taiwanese in 2015, told me about the event.
It made my heart beating. Of course there was fear also. But I was more motivated to participate.
Without Edward, I probably wouldn't be able to participate, and even wouldn't know existence of the event.
 
After the long cold winter of Korea, I'm just starting the training.
I do not know if it will be the first time, but another Korean participant and my close friend, Young-jun, goes with me.
https://goo.gl/VdFJA1 (Young-jun Jeong)
Even if you do not participate the event together, I would like you to join our training!!
 
I have a friend who can not forget throughout my whole life. 
It was a short time we met together, but he've changed my life completely.
We met in our 40s and became the best friend each other. 
He made me realize that softness is strong, because he was soft but strong.
He made me realize that I had to do what I thought, because he achieved what he thought.
He made me realize the importance of family, because he did the best for his family.
The friend I spent time cycling together went to heaven, let me know a lot of things.
https://goo.gl/hi3jGe (Bong-chun Lee)
Whenever I go to the bicycle road that I went with him, I still can't but cry.
Perhaps I learned the meaning of life from him.
 
We're connected. It's a miracle.
 
 
 
Posted by Hey Jerry
,
반응형
 
 
Google Cloud CDN 설정 방법
 
구글 클라우드 콘솔( http://console.cloud.google.com )에서
 
  • Network services ==> Cloud CDN 메뉴
  •  
  • Add Origin 클릭
  • Origin에 Create a loadbalancer 선택
  • Name: Loadbalancer(CDN) 이름 지정
  • Backend configuration: 불러올 컨텐츠를 선택. Backend buckets(GCS Bucket 지정) 선택
    • Dynamic Contents도 지정할 수 있지만 여기서는 Cloud Storage 사용
  •  
  • Host and path rules: Backend가 여러 개일 경우 URL 기반의 Matching을 통해 라우팅 규칙 생성
    • 디폴트로 두면 모든 요청은 하나의 백엔드로
    • 또는 다음과 같이 Host, Path에 다른 규칙을 부여할 수 있음
      • Path 규칙을 사용하려면 Bucket에도 동일한 서브 디렉토리가 존재해야 함 (예: /static 이면 bucket에도 /static/a.jpg 처럼)
      • 모든 Host를 허용하려면 * 로 지정
    • 적용이 잘 안되면 Caching 메뉴에서 Invalidation (예: jerrycdn.ddns.net/*)
  •  
  • Frontend configuration: 클라이언트 입력을 받아들일 Endpoint 지정
    • HTTP 또는 HTTPS(인증서 필요) 지정
    • Network Service Tier
      • Premium이 디폴트... Standard는 저렴하지만 Latency 보장 안됨
    • IP address
      • Ephemeral: 유동 IP 사용
      • Create IP address: 고정 IP 생성
    • Port: 서비스할 포트
  •  
  • 다음은 생성된 모습
  •  
  •  
  • 다음과 같이 테스트 
 
 
Posted by Hey Jerry
,
반응형
 
구글클라우드 Compute Engine(VM)을 워크로드에 맞추어 Autoscaling 하는 방법에 대한 가이드입니다.
 
 
Autoscaling 기능 자체의 개념은 간단하지만, 실제 운영 환경에서 원하는 Autoscaling이 장점을 얻기 위해서는 다음과 같은 과정을 잘 따라야 합니다.
특히 Autoscaling에 사용되는 정책은 최대한 보수적(가능하면 부하보다는 높은 용량 유지) 이해해야 실제 VM의 개수가 증가하고 감소하는 현상에 대한 납득이 가능하기도 합니다.
 
0.Autoscaling 환경 아키텍처
 
먼저 Autoscaling에 사용되는 주요 컴포넌트와 설정들을 도식화한 것입니다. 
Autoscaling 기능은 주로 Load Balancer와 같이 사용되지만, 반드시 그래야 하는 것은 아닙니다. Autoscaling 기능은 Instance Group에서 설정을 하도록 되어 있습니다.
  • Instance Group: 동일한 VM들의 집합으로서 Instance Template을 통해서 새로운 VM을 생성할 수 있음
  • Instance Template: VM을 만들기 위한 Template으로서 기본적으로 어떤 운영체제(VM) Image를 사용할지 지정하고, 그 외에도 리전/존, 머신 타입, 네트워크 구성 등을 미리 정함
  • Health Check: Instance Group 내에서 VM이 기동되면 해당 인스턴스가 정상적으로 업무 처리가 가능한지 검사하는 기능. TCP 포트만 체크할 수도 있고, HTTP 요청을 통해 실제 성공적인 응답이 오는지 체크할 수도 있음
  • Autoscaler: Instance Group 설정 내에 포함되어 그룹 내 VM 인스턴스의 개수를 자동으로 조절(scaling)하는데 사용되는 정책이자 조건. 기본적으로 CPU 점유율이나 요청의 개수(초당 또는 분당)를 기반으로 scaling 가능하며, Stackdriver의 모니터링 metric을 사용한 scaling도 가능 함. Stackdriver는 CPU 사용률은 물론 네트워크 트래픽, 디스크 사용량 등 다양한 metric을 수집할 수 있고, Custom metric을 만들어 애플리케이션 specific한 조건을 사용할 수도 있음 (예: 자체 큐에 쌓여 있는 메시지의 개수)
  • VM Image: Instance Template에 지정하며 생성될 VM의 Base Image를 지정. GCP에서 제공하는 기본적인 운영체제(예: CentOS, Window)를 사용할 수도 있지만 VM에 필요한 소프트웨어들을 설치하여 Custom Image를 만들어 사용할 수도 있음
 
 
Instance Group은 독립적으로도 동작이 가능하지만 실제로 많은 경우는 클라이언트의 요청을 배분하는 Load Balancer에 연결하여 사용하게 됩니다. Load Balancer는 클라이언트의 요청을 받아 Backend 설정을 통해 Instance Group으로 요청들을 분배 및 전달하게 됩니다
 
  • Cloud Load Balancer: 클라이언트의 요청을 받는 Frontend와 해당 요청을 처리할 Backend를 가지고 있으며, Backend에는 Static 컨텐츠를 처리하는 CDN과 Dynamic 컨텐츠를 처리하기 위한 VM들의 Instance Group이 올 수 있음
  • Frontend: 클라이언트의 요청을 받는 수신 프토로콜을 지정. TCP, HTTP, HTTPS, UDP 등이 가능
  • Backend: 실제로 요청을 처리할 CDN이나 Instance Group을 연결. 하나 이상의 Backend를 연결하여 여러 Region이나 여러 Zone에 있는 Instance Group을 통해 요청을 분산 처리하게 할 수 있음. Ausoscaler에서 Instance Group 안에 포함된 VM들의 scaling 조건에 부가적으로 Max CPU Utilization, Max RPS, Capacity 등의 조건을 지정할 수 있음 (적용 방법은 아래에서 설명)
 
아래에서는 실제 테스트 프로젝트를 통해 Autoscaling 기능과 Load Balancer를 설정하는 방법에 대해 알아봅니다.
 
1.인스턴스 Image 준비
 
먼저 Google Cloud Console(http://console.cloud.google.com)에서 서비스에 사용할 VM을 생성하고 필요한 소프트웨어를 설치합니다. Autoscaling을 사용하게 되면 VM이 자동으로 기동되어 관리자가 개입 없이도 서비스가 가능해야 하므로, 부팅 스크립트 등을 통해 요청 처리에 필요한 모든 과정이 이루어지도록 해야 합니다. 여기서는 CentOS 7 이미지에 Apache HTTPD를 설치해서 서비스 하도록 테스트합니다.
 
sudo yum install httpd
 
sudo vi /var/www/html/index.html
# 임의의 HTML 컨텐츠 추가
 
curl http://loalhost
# HTML 정상 서비스 여부 체크
 
sudo chkconfig httpd on
# HTTPD 부탕 시 자동 실행
 
 
그리고 VM에 대한 기본적인 모니터링은 물론, Stackdriver를 통한 Autoscaling 기능을 활용을 위해서는 Stackdriver Monitoring Agent가 미리 설치되어야 합니다. Stackdriver Monitoring Agent 설치는 다음 문서를 참고합니다.
 
 
VM이 정상적으로 요청을 처리할 수 있는지 확인이 되면 VM을 정상 종료하고 Image로 생성합니다.
 
 
 
2.VM 생성용 Instance Template
 
VM Image가 만들어졌으면, 해당 Image 기반으로 VM이 기동되었을 때 필요한 디스크, 네트워크, 보안 등에 대한 설정을 Instance Template으로 생성합니다. SSH 로그인이 필요하면 SSH Public Key도 등록합니다.
 
 
3.Instance Group 생성
 
앞에서 생성된 Instance Template을 기반으로 Instance Group을 생성합니다. 생성할 VM Instance의 리전(region), 존(zone)도 결정합니다. 그리고 Autoscaling 조건을 지정하는데, 이번 테스트에서는 CPU 사용률이 40% 이상(Instance Group 내 VM들의 CPU 사용률 총합을 VM 개수로 나눈 결과)이면, 최대 10대까지 증가하도록 합니다. Autoscaling 조건은 VM 기동 후 60초(Cool down period)가 지난 시점(VM 시작 직후에는 CPU 사용률이 높을 수 있으므로)부터 수집합니다.
 
 
Instance Group 생성 화면의 하단에서는 Health Check 조건을 생성 및 지정할 수 있는데, 앞에서 말한 것처럼 Health Check는 동작 중인 VM이 실제 업무 요청을 처리할 수 있는지(GCP uses the overall health state of each VM to determine its eligibility for receiving new requests) 조건을 지정하는 것입니다. Health Check는 VM 기동 후 30초(Initial delay)가 지난 시점부터 체크합니다.
 
여기서는 다음과 같은 조건의 Health Check를 생성합니다.
 
  • Protocol: HTTP
  • Port: 80
  • Port Specification: Fixed port
  • Request path: /
  • Healthcheck 옵션 가이드: Fixed port (옵션이 내용은 아래 참고. --port가 Fixed port에 해당)
  • 10초 마다 체크해서 5초 내로 응답이 2회 오면 정상으로 판정... 3회 이상 오지 않으면 실패로 판정
 
다음은 위의 조건을 기반으로 생성된 Health Check입니다.
 
 
Instance Group을 생성하면 다음과 같이 실제 런타임 상의 변화가 발생합니다. 먼저 Minimum number of instances가 1이므로 하나의 VM이 생성됩니다.
 
 
그리고 나서 Autoscaling 기능을 테스트 하기 위해 첫 번째 VM에 SSH로 접속해서 부하를 발생시킵니다.
 
stress --cpu 1
 
그러면 아래와 같이 추가로 VM들이 기동되는데 이유는 총 4개의 VM이 각각 40%의 용량(Target CPU usage)을 가지고 있으므로 40% * 4 = 160% 가 전체 Instance Group의 용량입니다. 그리고 현재 하나의 VM이 100% CPU 사용 중이므로 100% 이상의 용량을 가진 Instance Group을 만들기 위해 늘린 것입니다. 다만, 3개의 VM만 띄워도 120%이기 때문에 현재 사용량을 넘어서지만, Autoscaler는 VM 기동 시간 동안 처리가 안된다는 보수적으로 관점에서 필요한 용량보다 더 많은 VM을 띄우게 됩니다. 이렇게 넘치는 용량은 Cooling down 과정을 통해 다시 줄어들게 됩니다.
  • Gaps between target and actual utilization
    • scale up을 할 때 부족한 것을 방지하기 위해 aggressive 하게 진행 (통상 필요한 VM 보다 더 많이 생성)
 
 
위에서 설명한 Instance Group의 용량과 실제 부하는 GCP Console의 Instance Group 모니터링 탭에서 확인할 수 있습니다.
 
다시 한 번 테스트를 위해 4개의 VM 중 두 번째 VM에 접속해서 역시 부하를 주게 되면, 다음과 같이 9개의 VM이 생성되었다가 시간이 지나면 cooling down 과정을 통해 8개로 정리가 됩니다.
 
 
Cooling down 과정 즉, 부하가 줄어들어 VM Instance를 줄이는 과정을 테스트 하기 위해 2번 VM에서 부하를 중지합니다.
 
 
Cooling down 과정은 바로 발생하지 않고 최대한 보수적으로 10분을 기다렸다가 진행하며 위의 그래프를 보면 10분 후에 VM의 개수가 줄어드는 것을 확인할 수 있습니다. 이러한 Cooling down 과정에서 VM이 셧다운될 때 graceful한 종료를 위해 VM의 Shutdown 스크립트를 등록하여 진행 중인 트랜잭션을 정리하는 과정을 넣어주는 것이 좋습니다.
 
[참고] Instance Template을 중간에 변경
 
운영 중인 Instance Group의 Instance Template을 변경(즉, VM을 변경)하게 되면 새로 만들어지는 VM에 대해서만 적용이 되며, 현재 실행 중인 VM들은 영향을 받지 않습니다.
 
 
[참고] Rolling Update 기능
 
여러 개의 Instance Template을 지정하여 종류가 다른 VM 간의 A/B Test나 Canary Test 등을 진행할 수 있는 기능입니다.
 
 
[참고] Rolling Restart/Replace
 
현재 운영 중인 VM들을 재시작 하거나, 새로 지정된 Instance Template 기반의 VM으로 점진적으로 교체합니다.
 
 
4.Load Balancer 생성
 
Instance Group에 외부 클라이언트로부터의 요청을 전달하기 위해 Load Balancer를 생성합니다. 생성 가능한 종류는 다음과 같으며 각각의 기능은 다음 문서를 참고하시기 바랍니다. 여기서는 HTTP Load Balancer를 선택합니다.
 
 
Load Balancer는 크게 Frontend 구성과 Backend 구성으로 나뉘며 생성할 Backend의 내용은 다음과 같습니다.
  • Name: autoscale-vm-a2-be
  • Instance Group으로 위에서 만든 것을 지정
  • Maximum CPU utilization: 100% (Instance Group의 조건을 override 하지 않기 위해)
  • Maximum RPS(Request Per Seconds): N/A
  • Capacity: 100% (Instance Group의 조건을 override 하지 않기 위해)
  • Health Check: Instance Group의 것과 동일한 것 선택
  • Session Affinity: Generated Cookie, 쿠키를 생성해서 그것으로 추적
  • HTTP 서버를 운영 중이므로 80번 포트를 통해서 접속
 
다음은 Instance Group에 지정한 Autoscaling 기능과 유사한 역할을 하는 Backend 설정에 대한 설명입니다.
 
==> Balancing Mode: 어떤 부하를 기준으로 요청을 분배할지... 만약 Max CPU/RPS+Capacity에 지정된 모든 용량이 찼다면 지정된 정책에 따라 적은쪽으로 분배
 
==> Max CPU utilizationBackend Instance Group의 모든 VM들의 평균으로... 복수의 Backend를 둘 경우 허용 가능한 부하 
   Capacity에 차지 않았으면 Instance Group으로 하여금 VM을 증설하도록 하지만, 만약 Capacity에 찼다면 다른 Region이나 Instance Group으로 요청 포워딩
   Instance Group의 Auoscaler에 Target CPU Usage가 80%, LB의 Max CPU가 80%라면 Instance Group의 평균 CPU가 80% * 80% = 64% 일 때 새로운 VM 생성
   결국 Instance Group의 설정에 영향을 주고 싶지 않다면 Max CPU와 Capacity를 100%로 지정
   단, 모든 Backend가 100% 라면 Balancing Mode에 지정된 규칙대로 부하가 적은쪽으로 분배
 
==> Maximum RPS: backend의 instance group으로 갈 수 있는 최대 RPS(Request per second)
 
==> Capacity(CPU, RPS): Max CPU, Max RPS에 부가적인 용량 제어... Max CPU 80%임에도 절반의 CPU만 사용하고 싶다면 여기를 50%로 함. 설정을 override 하고싶지 않다면 100%를 지정
 
Frontend는 다음과 같은 내용으로 생성합니다. 일반적인 HTTP(80) 서비스입니다.
 
  • Frontend
  • Name: autoscale-vm-a2-fe
  • Protocol: HTTP
  • 두 개 이상의 Frontend 생성 가능
 
다음은 Load Balancer를 생성한 직후의 모습입니다.
 
 
Backend VM이 정상 준비(Health Check까지 완료)된 모습입니다.
 
 
 
[참고] 커맨드를 사용한 TCP Health Check 생성
 
TCP Health Check 생성
[jerryj@jerrydev load-balancing-scaling]$ cat create_tcp_healthcheck.sh
gcloud compute health-checks create tcp hc-tcp-80 \
    --project jerry-vpc-test \
    --description="Health check: TCP 80" \
    --check-interval=5s \
    --timeout=5s \
    --healthy-threshold=2 \
    --unhealthy-threshold=2 \
    --port=80
 
[참고] TCP Load Balancer 생성
 
Backend 구성 내용입니다. Health Check는 TCP 용으로 새로 만들었습니다.
 
 
Frontend 구성 내용입니다.
 
 
 
5.Stackdriver Metric으로 Scaling 하는 방법
 
다음은 Stackdriver의 metric 그 중에서도 특정 NIC 카드의 네트워크 트래픽을 기준으로 autoscaling을 하는 방법입니다.
 
먼저 VM에 Monitoring Agent를 설치하는 방법으로 이미 위에서 VM Image 생성 단계에서 완료한 내용입니다.
 
 
sudo chkconfig stackdriver-agent on
 
 
[jerryj@autoscale-vm-a2-1 ~]$ gcloud auth list
                  Credentialed Accounts
ACTIVE  ACCOUNT
 
다음은 VM의 Service Account가 Monitoring Metric Write 가능하도록 하는 것인데, IAM에서 확인한 아래의 예에서는 Project Editor 권한이 있어 가능합니다.
 
만약 안되면 다음과 같이 IAM에서 Service Account에 권한을 부여해야 합니다.
 
다음 두 개의 권한으로 Account 생성 후 Key 파일 다운로드
 
다음 경로로 Key 파일 복사
 
자 그러면 이번에는 Stackdriver 모니터링 기능을 통해 autoscaling에 사용할 metric을 찾습니다.
 
GCP. Console의 Stackdriver 모니터링 화면
  • Resources ==> Instances ==> VM ==> Network Traffic (또는 Metric Explorer에서 더 다양한 모니터링 항목 선택 가능)
  • 네트워크 부하를 주었을 때 아래 분홍색 그래프처럼 수치가 증가하는 것이 보임
 
Instance Group의 Autoscaling 부분에서 Stackdriver monitoring metric을 선택한 후 다음과 같이 설정합니다.
 
 
Metric identifier에서는 다음을 지정합니다. "traffic"이라고만 치면 조회가 됩니다.
  • agent.googleapis.com/inerface/traffic
 
Utilization target type에서는 Gauge를 선택합니다.
  • Gauge: 최근 몇 분간 수집된 데이터들의 평균 값
  • [참고] 아래와 같은 옵션들이 있습니다.
 
Additional filter expression for metric labels에는 다음을 입력하여 VM 내 여러 개의 NIC 중에서 eth0의 Outbound 트래픽만을 선택합니다.
  • metric.label.device=eth0 AND metric.label.direction=tx
 
다음은 입력한 결과입니다.
 
 
Instance Group의 모니터링 탭을 보면 아래와 같이 autoscaling이 동작할 네트워크 트래픽의 기준점이 1M(1,048,576)임이 보입니다.
 
 
다음과 같은 curl 명령과 쉘스크립트로 부하를 발생시켜 네트워크 트래픽 기반의 autoscaling 기능을 확인합니다.
 
부하 발생
  • GLB로 부하 발생
[jerryj@jerrydev load-balancing-scaling]$ cat load_generate.sh
while true
do
curl -s -o /dev/null 35.227.216.228
done
 
 
 
 
 
 
Posted by Hey Jerry
,
반응형
 
 
HTTP Proxy를 이용한 사내 방화벽/보안장비(Outbound 액세스 제한)로 인한 API 접속 문제를 해결하는 방법입니다.
 
1. Squid 서버 설치
 
GCP에 VM 작은 걸 하나 만드시고... (Static IP 부여)
CentOS 같은 경우는 그냥 다음과 같이 하면 됩니다. 
Ubuntu 계열도 어렵진 않을 듯 합니다.
 
yum install squid
 
2. Squid 서버 설정
 
vi /etc/squid/squid.conf
 
다음과 같이해서 모든 외부서버로 접속을 가능하게 합니다. (설정 파일을 완전히 교체)
(Google API IP가 계속 변경되므로 DNS를 이용한 Outbound 설정 필요)
설정에서 allowed_ip를 변경하여 허용되는 소스 IP를 추가할 수 있습니다.
SSL_ports에는 SSL로 사용할 포트, Safe_ports에는 일반 허용 가능한 포트를 지정합니다.
http_access allow CONNECT 에 SSL로 접근 가능한 조건을 선택합니다.
http_access allow 에 Non-SSL로 접근 가능한 조건을 선택합니다.
 
# For Google Cloud
acl allowed_ip src 10.146.0.2/32 1.240.103.160/32 104.198.121.215/32
acl CONNECT method CONNECT
acl google_apis dstdomain .googleapis.com .google.com
acl SSL_ports port 443
acl Safe_ports port 80
http_access allow CONNECT allowed_ip google_apis SSL_Ports
http_access allow allowed_ip google_apis Safe_Ports
http_access deny all
http_port 0.0.0.0:8080
 
# Uncomment and adjust the following to add a disk cache directory.
#cache_dir ufs /var/spool/squid 100 16 256
 
# Leave coredumps in the first cache dir
coredump_dir /var/spool/squid
 
#
# Add any of your own refresh_pattern entries above these.
#
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320
 
3. VM의 방화벽 설정
 
우선 VM 내부 파이어월을 열어 주고 (방화벽이 있다면)
 
sudo firewall-cmd --permanent --zone=public --add-port=8080/tcp; sudo firewall-cmd --reload
 
VPC 설정에서 8080 포트를 역시 열어 줍니다. 아래는 각각 VPC Firewall과 VM Network의 설정입니다.
단, 이 때 외부에서 접속 가능한 IP를 반드시 PC가 있는 사무실이나 서버가 있는 IDC로 제한을 하셔야 합니다.
 
 
4. API 호출 클라이언트에서 사용 방법
 
다음과 같이 Proxy 서버를 환경변수에 지정합니다. profile 스크립트에 넣어도 좋겠죠
export http_proxy=http://<squid vm ip>:8080
export https_proxy=http://<squid vm ip>:8080
 
==> 제외하고 싶은 주소가 있다면 다음과 같이 설정합니다.
export no_proxy="ecar-web01,ecar-iot01,172.20.90.60,172.20.90.62"
 
5. Java에서는
 
다음과 같이 옵션을 지정합니다.
java -Dhttps.proxyHost=35.187.200.95 -Dhttps.proxyPort=8080
 
 
그리고 나서 API 호출하시면 Squid HTTP Proxy를 통해서 실행이 됩니다.
내부 방화벽이나 보안장비에서 squid vm ip를 제외하시면 됩니다.
Posted by Hey Jerry
,
반응형
구글 검색엔진의 검색 결과를 프로그램에서 사용하고 싶으시다면, Google Custom Search API를 사용할 수 있습니다.
 
다음 문서를 참고합니다.
 
Custom Search API를 활성화 합니다.
 
그러면 API Key가 생성됩니다ㅏ.
 
Control Panel에 가서 검색 엔진을 설정합니다.
 
검색 엔진 생성
 
검색 엔진 ID를 구해서 API 호출에 사용합니다.
 
다음과 같이 하면 특정 도메인이 아닌 모든 싸이트 검색 결과를 받아올 수 있습니다.
 
검색 API 호출하는 예제입니다.
[jerryj@jerrydev search-api]$ cat query.sh
API_KEY=AIzaSyA6UWNS3FoWoomibgWvnTMICLJt65vb8Xc
ENGINE_ID=010328994824229770323:3v-oregc47y
curl "https://www.googleapis.com/customsearch/v1?key=${API_KEY}&cx=${ENGINE_ID}&q=javalove93"
 
검색 결과입니다.
...
"items": [
  {
   "kind": "customsearch#result",
   "title": "javalove93 (Jerry Jeong) · GitHub",
   "htmlTitle": "\u003cb\u003ejavalove93\u003c/b\u003e (Jerry Jeong) · GitHub",
   "link": "https://github.com/javalove93",
   "displayLink": "github.com",
   "snippet": "javalove93 has 21 repositories available. Follow their code on GitHub.",
   "htmlSnippet": "\u003cb\u003ejavalove93\u003c/b\u003e has 21 repositories available. Follow their code on GitHub.",
   "cacheId": "MuQL2KxJQmQJ",
   "formattedUrl": "https://github.com/javalove93",
   "htmlFormattedUrl": "https://github.com/\u003cb\u003ejavalove93\u003c/b\u003e",
 
 
실제 구글 싸이트 검색 결과와 비교해 봅니다.
 
 
RU5DMKCweyHDKrQJE9BIJoi+fzXxgWiAf3gmBZgU6tOfKOb/+74bBArivRogfdslL1hfk4fP1xNUKrguhHeV7KLw8Q2b63bmOwlchzJzcMoayDysBXmK26L4RBKPdNjNZfH0YLkgNw7BjWKqWyqGrUCFRvGGTNDm4Ji6F5YDrJA4Wj1M2wfNLV1hQ4+knogz/ueyf2EFx2+/+MwOxlufg3/OYr1T1WrA8cjahbIenRTUt6lBE4YGzIxVZ3zZSO1HIgeuqAD76d4aOzfws3uu51Qj19tptjWlBfkbf2lV2poc+RfopI3OGAiYPrKCYg8INSeW3N0NlyGJ4VsLw9v65eJpCKxRNIPbu/bH7CSYPWvo4EAB2PGuSz//oq22BvNIdInFjG8IIVDL09OFUXwyF2I1BSeyNQmrcLz0sucOvxHhd7P9mp0SgT14NVQhsqn1+YoRy4ZTe17hirjWdBLhUQ4UEp9QrCJp/vY0AKmPe8pRQeooYX6a9NdsuaoYY51MUu0jAZnrH4qlCnP8S+HNqs/UqNPeOcvffZUPVR6SmQ1mltZ+bSe+6j2My/iEqSiy/JOqTOaDZTCN0NjkB+hb3wBt4xW/wucygO8vInOKl3soNyII
 
Posted by Hey Jerry
,