Tomcat 8 로 넘어오면서 manager 페이지 접근을 위한 패스워드 암호화 방법에 조금 변화가 있었다. 이에 대해서 기술한다.
Manager 페이지 접근 권한 – context.xml
기본값으로 /manager 페이지에 대한 접근은 localhost 로 제한이 걸려 있다. 이것은 manager 앱에 대한 context.xml 파일에 설정되어 있는 내용인데, 파일 경로는 $CATALINA_HOME/webpps/manager/META-INF/context.xml 이다. 다음과 같이 접근 제한된 부분에서 외부접속을 위한 설정을 해준다.
XHTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0"encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
stack 이 생성 정상적으로 생성되면 3개의 Service가 생성된다. 각각 Traefik, Portainer, Registry 이며 Portainer 는 Traefik 에 URI Reverse 로 연결된다. Portainer 의 URL 은 http://<IP>/portainer 이다.
Docker 를 단순한 빠르고 가볍게 애플리케이션을 구성하게 해주는 컨테이너(Container) 로만 이해하는 건 좁은 시각이다. Docker 는 이러한 컨테이너들을 위한 네트워크 환경도 제공하고 있다. 이것은 Docker 가 종합적인 IT 인프라를 제공할 수 있다는 것을 의미한다.
Docker 네크워크 상태
Docker 를 호스트에 설치하면 우선적으로 다음과 같은 네트워크 장치가 하나 보인다.
ZSH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
~$ifconfig
docker0 Link encap:Ethernet HWaddr02:42:33:37:4b:7f
컨테이너를 하나도 실행하지 않은 상태에서 단지 Docker 데몬이 실행만 되어도 이렇게 docker0 라는 네트워크 장치가 나타난다. 아이피는 172.17.0.1 이며 브로드캐스트(Broadcast) 가 172.17.255.255 인 것으로 봐서 docker0 장치가 속하는 네트워크 대역은 172.17.0.0/16 임을 알 수 있다.
docker0 는 Docker 가 실행되면서 자동으로 생성되는 가상의 네트워크 장치다. 네트워크 장치에도 여러가지 역할 혹은 모드를 부여할 수 있는데, docker0 가상네트워크는 브릿지모드로 동작하도록되어 있다.
ZSH
1
2
3
~$brctl show
bridge name bridge id STP enabled interfaces
docker08000.024233374b7fno
docker0 가상네트워크가 브릿지 모드로 동작한다는 것은 이 브릿지에 연결한 네트워크 장비들을 외부와 통신하도록 해준다. 말 그대로 다리 역할을 하는 것이 docker0 이다.
우분투 컨테이너의 Default Gateway 는 컨테이너를 실행한 호스트의 Docker 가상네트워크인 docker0 를 가르키고 있다. 결국 Docker 컨테이너의 모든 네트워크는 호스트의 docker0 를 가르키고 이는 모든 외부와의 트래픽은 docker0 을 통해서만 가능하다.
이를 도식으로 나타내면 다음과 같다.
Docker0 브릿지 네트워크
이 docker0 브릿지 네트워크는 Docker 네트워크중에 하나다.
ZSH
1
2
3
4
5
~$docker network ls
NETWORK ID NAME DRIVER SCOPE
13ed3c333711bridge bridge local
84d5591305cahost host local
352cc4d7e9bfnone nulllocal
Docker 가 기본으로 제공하는 네트워크 기능들이 나온다. 여기서 bridge 에 대한 내용을 자세하 살펴보면 다음과 같다.
위 내용을 보면 IPAM 에 Config 를보면 네트워크 설정 내용이 보인다. 그리고 Options 에 “com.docker.network.bridge.name”: “docker0” 라는게 보인다. 이렇게 docker0 가상네트워크가 Docker 에서 생성한 Bridge 라는 것을 알 수 있다.
또, 현재 Bridge 에 연결되 실행되는 컨테이너 네트워크 정보도 함께 알 수 있다.
Docker 네트워크 특징
도커 호스트에 있는 컨테이너를 위한 가상네트워크 장비는 컨테이너와 peer 된 상태가 된다. 컨테이너를 하나씩 실행할때마다 하나씩 늘어난다. 컨테이너 갯수에 맞춰서 존재한다는 것이다.
도커 호스트에 컨테이너를 위한 가상네트워크 장비인 veth4327b92 는 컨테이너가 재시작될때마다 veth 를 제외한 숫자가 매번 바뀐다. 우분투 컨테이너를 재시작하고 난후 vethffc000e 로 변경됐다.
또, 위 도식에 보면 컨테이너 네트워크에 12라는 숫자가 보인다. 그리고 도커 호스트에 컨테이너를 위한 가상네트워크 번호가 13으로 나온다. 이를 보면 도커 컨테이너 네트크워크 숫자는 veth 가상호스트의 숫자보다 하나 작은 값을 가진다는 것을 알 수 있다. 이 숫자도 도커 컨테이너가 재시작될때마다 바뀌지만 1 작은 상태는 그대로 유지 된다. 이로써 도커 컨테이너 네트워크가 외부에 어느 veth 네트워크와 연결되는지를 알수 있게 된다.
또, 컨테이너에서 외부의 veth 가상네트워크를 볼 수가 없다. 이는 커널의 Network Namespace 로 격리를 하기 때문이다.
Docker Network Namespace
docker 의 Network Namespace 는 Docker 컨테이너가 실행될때마다 /var/run/docker/netns 디렉토리에 생성된다. 이에 대한 정보는 컨테이너 상세정보를 보면 알 수 있다.
Network Namespace 를 통해서 컨테이너에 네트워크 관련 명령어를 내릴 수 있다.
docker0 와 eth0 의 연결: iptables -t nat
docker0 에서 외부 네트워크 연결을 위해서 특별한 프로그램을 별도 운영하진 않는다. 단지, NAT 를 위한 Iptables 를 세팅한다. 이것은 오래전에 리눅스 박스를 라우터 장비로 이용하기 위한 방법인(지금에 비교를 하자면 리눅스 박스를 공유기로 이용하는 방법이다.) 마스커레이드(MASQUERADE) 과 완전 동일하다.
docker0 가상네트워크를 공유기로서 동작하도록 설정하는 것이다. iptables 를 한번 봐보자.
데이베이스 이전은 매우 중요한 작업이다. 다른 IT 인프라와는 다른 속성을 가진 데이터베이스를 물리적 공간도 다른 곳에 옮기기는 쉬운 일이 아니다. 더군다나 데이터베이스는 모든 IT 비지니스에 핵심으로 사업 성공에 성패를 가르기도 한다.
AWS 를 사용하다보면 데이터베이스 이전 작업을 종종 겪게 된다. 처음부터 AWS 에서 제공하는 DaaS 인 RDS, Aurora 를 사용한다면 별 걱정이 없겠지만 AWS도 아닌 일반 IDC 의 데이터베이스를 AWS RDS, Aurora 로 옯기기는 매우 힘든 작업이다.
한마디로 말하면 답이 없는 작업이다. AWS 의 모범사례를 보면 이렇게 외부에MySQL 데이터베이스가 존재할 경우에 mysqldump 명령어를 이용해서 데이터를 Export 한 다음에 AWS RDS, Aurora 에 데이터를 Import 하고 외부MySQL(Master) – AWS RDS,Aurora(Slave) 로 묶어 둔 후에 Application 에서의 작업을 통해서 최종적으로 AWS RDS Aurora 만 사용하도록 하고 있다.
문제는 용량이다. 만일 외부MySQL 데이터베이스의 용량이 10TB, 아니 4TB 라고 해보자. 그러면 4TB 를 덤프 뜨는 시간이 얼마나 걸릴지 예상하기도 쉽지 않다. MySQL 은 데이터를 덤프 뜨는 동안 테이블을 잠그기 때문에 그동안 서비스를 중단해야 한다.
서비스 중단없이 어떻게 데이터 이전을 할것인하는 건 모든 사업자라면 하는 고민일 것이다.
Netflix 도 이에 대한 고민을 했던 것으로 보인다. 더군다나 외부데이터베이스 시스템이 Oracle 이고 이전하고자하는 데이터베이스가 MySQL 이라면 데이터 변환작업도 함께 진행되어야 한다. 거기다 무중단 서비스…
Netflix 의 이러한 고민은 다음의 기사로 나왔는데, 결론은 Oracle 의 Golden Gate 를 이용했다는 것이다. OGG 라고 불리우기도하는데, 개인적인 경험으로 매우 훌륭한 툴이다. OGG 와 같은 동일한 역할을 하는 소프트웨어가 여럿 존재할 것이다.
핵심은 외부 데이터베이스를 AWS 로 이전하려고 할 경우에 서비스 무중단을 원한다면 OGG 와 같은 프로그램을 이용하는게 답이라는 거다.
만일 무중단 데이터 이전을 자체적으로 하기 힘들다면 국내에 데이터베이스 기술지원을 하는 업체를 돈을 들여서라도 이용하는 편이 낫다. 괜히 능력도 안되는데 의지만 앞선 나머지 일을 진행하다가 데이터 손실이라도 발생하면 사업에 아주 심각한 영향을 줄것이기에 데이터베이스 만큼은 확실한 방법이 요구된다.
AWS Aurora 는 DB Cluster 로 구현된다. DB Cluster 는 Aurora 인스턴스와 Endpoint 를 포함한 일종의 그룹 개념이다. 이 DB Cluster 에는 1개의 Primary 인스턴스와 15개의 Replica 를 가질 수 있다.
각각의 구성에서 접속이 가능한 지점은 다음과 같이 3가지가 있다.
Cluster Endpoint
Read Replica Endpoint
Instance Endpoint
이러한 Endpoint 와 Aurora 인스턴스 그리고 Primary, Replica 를 조합한 아키텍쳐는 다음과 같다.
Cluster Endpoint
Cluster Endpoint 는 Aurora Cluster 에서 현재 Primary 인스턴스에 접속하기 위한 Endpoint 이다. 모든 Aurora Cluster 는 반드시 하나의 Primary 인스턴스와 이를 연결하는 Cluster Endpoint 를 가진다.
Primary 인스턴스는 Insert, Update, Delete 그리고 DDL(Data Definition Language) 에 관한 모든 쓰기 연산을(write operation) 지원하며 데이터 읽기 연산인 Select 도 지원한다. Cluster Endpoint 는 read/write 를 연산을 제공하는 Primary 인스턴스 접속을 제공한다.
Cluster Endpoint 는 read/write 접속에 대한 자동 FailOver 를 제공한다. Primary 인스턴스에 문제가 발생하면 Replica 인스턴스 중 하나를 Primary 인스턴스로 선택한다. Cluster Endpoint 는 DNS 를 이용해 기존의 Primary 인스턴스의 도메인을 버리고 Replica 인스턴스로 변경한다. 이렇게 함으로써 Cluster Endpoint 도메인 주소는 변경없이 계속 유지 된다. Cluster Endpoint 에서 새로운 Primary 인스턴스로 지정된 Replica 인스턴스는 read/write 역할을 위해서 Primary 인스턴스로 승격된다.
Reader Endpoint
Reader Endpoint 는 Aurora Replica 중에 하나와 연결된다. Aurora Replica 는 읽기 연산(read operation) 만 지원하기 때문에 Reader Endpoint 는 읽기 전용 연결지점이 된다.
만일 Aurora Replica 가 한개 이상이라면 Reader Endpoint 는 Load Balancing 을 지원한다. 각각의 연결은 Round robin 방법으로 Replica 인스턴스 하나와 연결이 되어 연결에 따른 부하가 분산된다.
Instance Endpoint
Aurora DB 를 생성은 결국 Instance 를 생성하게 된다. 모든 Aurora 에 인스턴스는 Endpoint 를 가지는데 이게 Instance Endpoint 이다. 모든 Instance 는 타입과 관련없이 유일한 Instance Endpoint 를 가진다.
이 Instance Endpoint 는 도메인 이름으로 불변이며 Cluster Endpoint, Reader Endpoint 에 CNAME 으로 등록되어 이들의 연결지점으로 사용되어 진다.
WAS Connection Pool
이제 WAS 에서 AWS Aurora 접속을 위한 설정에 대해서 이야기 해보자. WAS 서버가 무엇이든 AWS Aurora 접속을 위해서는 MySQL, MariaDB Connector/j 드라이버를 사용해야 한다.
그런데, Aurora Cluster 를 구성할 경우에 Primary 인스턴스와 Replica 인스턴스로 구성하고 Endpoint 를 각각 Cluster, Reader 로 구성하게 될 것이다. 이렇게되면 WAS 에서는 이를 분산해서 접속해야 할 필요가 생긴다.
MySQL, MariaDB 는 이렇게 read/write 접속과 read only 접속을 분리해서 연결하도록 하는 기능을 제공하는데 이를 Smart Driver 라고 부른다.
한가지 먼저 짚고 넘어가자면, AWS Aurora 를 사용할 경우에는 MariaDB Connector/j 드라이버를 사용할 것을 권장하고 있는데, MariaDB Connector/j 드라이버는 Aurora 를 공식적으로 지원한다.
MariaDB Connector/j 드라이버를 이용해 Cluster Endpoint, Reader Endpoint 를 설정하는 방법은 다음과 같다. (Tomcat 기준 JNDI 설정이다)
이렇게 Cluster Endpoint, Reader Endpoint 주소를 연속해서 주면 된다. 이렇게하면 서버단에서 접속 설정은 끝이난다.
하지만, 이렇게 서버단에서의 설정만으로 접속이 분리되는 것은 아니다. Spring MVC 기준으로 말을 하자면 Transactional 의 ReadOnly 프로퍼티를 준 경우에만 Reader Endpoint 로 접속이 이루어지고 이외에는 전부 Cluster Endpoint 로 접속이 이루어진다.
Spring MVC 에서 이것을 각각 지정하기보다는 TX, AOP 설정을 통해서 한꺼번에 설정이 가능하다.
XHTML
1
2
3
4
5
6
7
8
9
10
11
12
<!-- required to connect Slave Server only for get* method on Aurora Replication -->
위와같이 했을 경우에 get* 으로 시작하는 메소드 이름을 가진 Service 빈에서 Read-Only 속성을 부여해 Reader Endpoint 로만 접속하도록 하게 할 수 있다.
마지막으로 고려해야할 것이 한가지 더 있는데, Connection Pool 의 경우에는 접속/해제에 대한 오버헤드를 줄이기 위해서 미리 연결을 해놓는 경우인데, 만일 Aurora FailOver 기능을 사용할 경우에 기존의 Fail된 인스턴스와 연결을 계속 유지하는 경우가 생긴다.
Replica Role 이 승격되서 새로운 Primary Role 이 되면서 Read/Write 역할을 수행하게 되는데, 이때 Cluster Endpoint 의 DNS 의 CNAME 이 변경된다. 하지만 WAS 서버의 Connection Pool 은 장애가 발생한 기존 Primary Role 인스턴스를 가지고 있게 된다.
MariaDB Connector/J 드라이버에는 이를 위해서 SOCKET_TIMEOUT 값을 두고 있다. Aurora 의 경우에는 10000ms 로 10초 동안 접속이 이루어지지 않을 경우에 Socket Timetout 으로 간주해 FailOver 로직을 수행한다.
Socket Timeout 은 JDBC 드라이버 측에서 설정을 해줘야 한다. 이는 대부분 URL 에 파라메터로 지정하는데, 다음과 같이 할 수 있다.
MariaDB connector/J 에서 connectTimeout 기본값은 0이며 socketTimeout 의 경우 Aurora 일 경우 10000ms 로 되어 있다. 이정도면 MariaDB Connector/J 를 사용하는데 있어서 별도의 설정을 해주지 않아도 될 정도다.
AWS Aurora(오로라) 는 AWS RDS 서비스 중에 하나 이다. 다른 RDS 서비스들은 기존 오픈소스, 상용 데이터베이스를 이용해 만든 반면에 Aurora 는 AWS가 자체 개발한 데이터베이스이다.
AWS RDS 는 Database-as-a-service (DBaaS) 인데, 이는 데이터베이스 관리에 많은 부분을 AWS가 알아서 해준다. 예를들면 데이터베이스 서버운영, 버그 패치, 이중화, 자동 FailOver등이며 웹 콘솔을 이용해 사용자의 각종 설정들을 처리해는 서비스다.
이 글은 AWS Aurora, 그중에서 MySQL Engine 에 대해서만 간단히 정리한 것이다. 이 글은 AWS Aurora 전부를 담고 있지 않음을 주의해야 한다.
Aurora MySQL Engine
Aurora 는 2가지 엔진(PostgreSQL, MySQL) 을 호환 엔진을 가진다. MySQL 호환 엔진의 경우에 MySQL 메이저 버전별로(MySQL 5.6, 5.7) 또 나뉜다.
Aurora MySQL 엔진을 이해하기 위해서 먼저 MySQL 를 간단히 살펴보자.
MySQL Architecture
기존의 MySQL 이중화 아키텍쳐는 다음과 같다.
AWS RDS MySQL 인데, 일반적인 MySQL 의 Replication 도 위와 동일 하다. 이 그림이 설명하는 특징은 다음과 같다.
MySQL 서버들은(Primary, Replica) 자신만의 Storage 를 가진다.
Storage 는 EBS Storage 이다.
Replica Instance 는 Primary Instance 로부터 Binary log 를 전송받아 이것을 Relay 해 데이터를 복제한다.
AWS RDS MySQL 서비스조차도 MySQL이 제공하는 복제방식을 그대로 사용했기 때문에 On-Demand 의 MySQL Replication 아키텍쳐와 동일하다.
이런 아키텍쳐 운영에서 문제는 추가적인 Replica 구성에 있다. 추가적인 Replica 를 더했을 경우에 기존 데이터를 전부 덤프를 뜨고 Restore 해준다음에 Position 값을 맞춰줘야 한다.
거기다 Replica가 바쁜 상태일때에 Binlog Relay가 느려지는 Replication Lag 현상도 문제다. Primary 에 추가된 레코드가 한참이 지나도록 Replica 에서 조회가 안될 수도 있다.
Aurora Architecture
AWS Aurora 아키텍쳐로 특징은 다음과 같다.
Storage 는 모든 인스턴스에 공유 된다. .
Storage 는 EBS 가 아닌 Distributed Virtual Volume Storage 다.
Redo Log 만 전송된다.
Pallarel Query 를 지원한다.
Aurora MySQL 특징
가장 큰 차이점을 살펴봤는데, 이외에도 몇가지 차이가 존재한다.
Multi-AZ 를 지원하지 않는다. – 오해의 소지가 있는데, 기존의 Multi-AZ 는 내부 StandBy 서버를 말했었다. 하지만 Aurora 는 Muti-AZ Deployment 를 할 경우에 내부 StandBy 서버 없이 Read Replica 가 AZ 로 생성되면서 이 역할을 대신한다. 용어의 혼돈이 존재하는 부분이다.
MySQL 의 Single thread connection 방식인데, Aurora MySQL 은 Dynamic 방식이다. 내부적으로 Epoll Multiplex 를 사용한다.
사용할 Storage 용량을 정하지 않아도 된다. 10GB 씩 최대 64TB 까지 자동으로 늘어난다. (AWS RDS MySQL 의 경우 EBS 한계치인 16TB 까지다.)
Replica 에 대한 LoadBalancer 를 지원해 이중화를 지원한다. 이를 위해서는 읽기전용 Cluster Endpoint를 사용해야 한다.
FailOver 시에 Read Replica 중에 하나를 Primary Role 로 승격 시킨다. Primary Cluster Endpoint 를 사용하면 접속지점 변경이 없다.
중요한 특징들도 존재한다.
Aurora DB Cluster 역추적(Backtrack, 되감기)
보통의 DB 에서 특정 시점으로 되돌리기 위해서는 백업본을 이용해 Point-In-Time 복원을 수행해야 한다. AWS RDS 의 경우 특정 시점의 백업을 이용해 복원해 새로운 DB 클러스터를 만들어 내는데 이것이 Aurora DB 클러스터 백업 및 복원에 대한 개요 다.
Aurora DB Cluster 역추적은 백업/복원 과정이 아닌 데이터베이스를 특정시점으로 되감는 것이다. 새로운 DB 클러스터는 생성되지 않는다.
역추적 기능이 활성화된 상태에서 생성한 DB 클러스터에서만 역추적이 가능하다. (새 DB 클러스터를 만들 때, DB 클러스터의 스냅샷을 복원할 때, DB 클러스터를 복제할 때) 역추적 기능이 비활성화된 상태에서 생성한 DB 클러스터에서 역추적이 불가능 하다.
역추적이 활성화된 Aurora DB 클러스터를 업데이트하면 변경 레코드가 생성된다. Aurora은 대상 기간에 대한 변경 레코드를 보존하며 이 레코드를 저장하기 위해 시간당 요금을 지불한다.
Aurora Storage IOPs 는 오직 Aurora 의 인스턴스 타입에 따른다.
AWS RDS MySQL 의 경우에 EBS Storage 를 사용하기 때문에 IOPs 를 따로 결정할 수 있다. 하지만 AWS Aurora 의 경우에는 Storage 타입이 존재하지 않음으로 인해서 IOPs 는 인스턴스 타입에 따른다.
결과적으로 빠른 IOPs 가 필요하다면 Aurora 인스턴스 타입을 업그레이드 해줘야 한다.
Global Database 지원 – Region Replica 를 지원 한다.
Region 간 복제를 지원하는것인데, 현재 3개 지역만 지원한다.
Multi Master Replica
현재 Preview 단계에 있다. 언제 정식 서비스 될지는 모르지만 Preview로 맛을 볼수는 있다.
Free Tier 를 제공하지 않는다.
AWS Aurora 는 Free Tier 를 제공하지 않는다. 공자 사용 안된다는 이야기.
T2 타입에서 Performance Schema 활성화 안됨
적용 Capacity 를 가진 타입의 경우에 Performance Schema 활성화가 안된다.
AWS Aurora 비용
선택한 옵션에 따라서 추가 비용 부담이 있지만 기본적으로 가장 많은 비용이 들어가는 것으로는 다음과 같다.
Storage I/O 요금 – 1백만 건당 0.22 USD
스토리지 요금 – 월별 GB 0.11 USD
Global Database – 복제된 쓰기 I/O 백만 건당 0.22 USD
Storage I/O 요금을 주의해야 하는 것은 데이터 이관시다. AWS Aurora 로 데이터베이스를 바꿀려고 할 경우에 데이터를 부어야 하는데, 이때 대량의 Storage I/O 가 발생하게 되며 고 비용을 물어야 한다. – 처음부터 AWS Aurora 를 선택하는게 좋을 수 밖에..