• yundream
  • 2016-04-17 16:43:25
  • 2016-02-01 07:13:17
  • 108150

Contents

Dnsmasq

Dnsmasq는 작은 규모의 네트워크에서 DNS, DHCP, 네트워크 부트 등을 서비스하기 위해서 사용하는 소프트웨어다. 가볍고 설정이 간단하기 때문에 데스크탑 가상화 소프트웨어, 핫스팟(hotspots), 스마트폰 등에 널리 사용하고 있다. 또한 가볍고 분산하기가 쉬워서 네트워크 가상화나 같은 산업 영역에서도 사용하고 있다. DHCP의 서브시스템인 DHCPv4, DHCPv6, BOOTP, PXE도 지원한다. 이들 기능은 클라우드 인프라의 자동 프로비저닝등에 활용 할 수 있다.

dnsmaq로 아래의 주제들을 고민해 보려 한다.
  1. 간단한 사용 방법
  2. 컨테이너 기반 가상화 환경에서의 네트워크 구성
  3. 다이나믹 DNS 설정
  4. 데이터 센터를 위한 DNS 서비스 시스템. AWS의 Route53과 같은 유연하고 확장성있는 route53 서비스를 만들려면 어떻게 해야 할지 고민한다.

설치 및 간단 사용

환경

모든 테스트는 우분투 리눅스 14.04를 기준으로 한다. 가상화 환경은 docker1.9.1, 우분투 리눅스 14.04 이미지로 구성한다. 가상화 네트워크는 flat network와 Overlay network 에서 테스트 한다.

설치 및 테스트

# apt-get install dnsmasq

Dynamic DNS 구성

AWS의 Route53의 경우 아스테릭(*) 도메인의 처리를 지원한다. 예를 들어 *.joinc.co.kr를 A 레코드로 설정하면, joinc.co.kr에 대한 모든 서브도메인을 A레코드 주소로 보낸다. 이 기능을 이용하면 유저가 서브도메인을 잘못 입력하더라도, 원하는 도메인으로 보낼 수 있다.

더 중요한 활용용도는 소규모 네트워크에서의 다이나믹 DNS 구성이다. joinc.co.kr로 다양한 서비스를 기획한다고 가정해 보자. 새로운 서비스가 만들어질 때마다 서브 도메인을 할당해야 한다고 가정해 보자. DNS서버(우분투 리눅스의 경우 bind9을 주로 사용한다.)의 경우 아스테릭을 지원하지 않기 때문에 DNS 서버를 일일이 설정하고 새로 리스타트 해야 한다. Dnsmasq는 아스테릭을 지원하는데, 아래와 같이 간단하게 구성할 수 있다.

 Dnsmasq를 이용한 다이나믹 DNS 환경 구성

  1. joinc.co.kr 도메인을 관리하는 DNS 호스팅 업체에 joinc.co.kr 서브 도메인의 관리를 Dnsmasq DNS Server에 위임한다.
  2. Dnsmasq에는 *.joinc.co.kr룰과 내부에서 관리하는 서브도메인 설정을 가지고 있다. 유저가 a.joinc.co.kr 도메인에 대한 룩업을 요청하면, Dnsmasq 서버로 요청이 전달된다. Dnsmasq는 *.joinc.co.kr에 의해서 Nginx 서버의 주소인 11.12.33.44를 전달한다.
  3. 유저는 11.12.33.44에 접속한다.
  4. Nginx server는 각 서브도메인을 처리할 서버의 IP 정보들을 가지고 있다. Nginx server는 a.joinc.co.kr(11.1.1.2)로 reverse proxy 한다.
이 방식은 도메인 관리가 전혀 필요없다는 장점을 가진다. 새로운 서비스가 추가 되면, Nginx의 /etc/hosts 설정에 호스트이름만 설정해 주는 것으로 즉시 서비스를 할 수 있다.

Dnsmasq로 Service discovery system 만들기

SaaS나 PaaS를 구축하려면 Service discovery system이 필요하다. SaaS와 PaaS에서 유저 애플리케이션은 인스턴스와 네트워크에 상관없이 자유롭게 떠다닌다. IP가 계속 변하기 때문에 IP로는 애플리케이션을 찾을 수 없다. 결국 도메인 이름을 이용 해서 애플리케이션을 찾아야 한다. Service discovery system의 구조는 아래와 같을 것이다.

 service discovery system 구조

유저가 SaaS 서비스를 만든다고 가정해보자. 이 SaaS 애플리케이션은 10.1.1.2 Instance에 컨테이너 형태로 만들어졌다. 대략 아래와 같은 시나리오로 서비스를 찾을 수 있다.
  1. 유저가 SaaS 서비스를 요청한다.
  2. Service Admin은 자원이 남는 인스턴스 (여기에서는 10.1.1.2)에 service01 컨테이너를 만들어서 애플리케이션을 전개한다.
  3. 이 애플리케이션을 찾기 위해서는 두 개의 정보가 필요하다. 우선 인스턴스를 찾기 위한 도메인 이름이 필요하다.. 인스턴스를 찾았다면, 인스턴스 안에 있는 애플리케이션(컨테이너)를 찾아야 하는데, 역시 도메인 이름으로 찾을 수 있다. 첫번째 도메인 이름은 인스턴스의 IP, 두번째 도메인 이름은 컨테이너의 id를 가리킨다.
  4. 유저가 service01.joinc.priv를 요청한다. 요청을 받은 Public Dns Server는 Proxy Server의 IP를 반환한다.
  5. 유저는 Proxy Server로 접근한다. 요청을 받은 Proxy Server는 Private DNS Server에 DNS 질의를 한다.
  6. Private DNS Server는 Instance의 IP를 반환한다.
  7. Proxy Server는 유저의 요청을 해당 Instance로 보낸다.
  8. 이 요청은 Instance 내부에 있는 Proxy로 전송된다. Proxy는 Private DNS Server에 요청해서 containerid를 가져온다.
  9. Contaierid로 service01 컨테이너의 네트워크 정보를 알아낸 후 접근한다.

테스트 환경 구축

VirtualBox를 이용해서 테스트 환경을 구축했다.

 Dnsmasq를 이용한 Service discovery 테스트 호나경 구축
  1. Public Dns Server : 인터넷 상에서 서비스의 위치를 찾을 수 있도록 네임서비스를 한다.
  2. Private Dns Server : 로컬네트워크로 SaaS 인프라 내부의 인스턴스를 찾을 수 있도록 네임서비스를 한다.
  3. ProxyServer : *.joinc.priv는 192.168.56.155로 접근한다. 여기에는 NginX가 설치돼 있다. NginX는 Private Dns Server를 resolver로 도메인에 대한 인스턴스를 찾을 수 있다.
  4. Container Instance : SaaS 애플리케이션이 설치되는 컨테이너 인스턴스들이다. 도커가 설치돼 있다.

Public DNS Server 구성

dnsmasq를 설치하고 아래와 같이 설정을 변경했다.
# cat /etc/dnsmasq.conf
.....
address=/.joinc.priv/192.168.56.155
# service dnsmasq restart
이제 *.joinc.priv로 dns 질의를 하면 192.168.56.155를 반환한다. 테스트해보자. 먼저 /etc/resolv.conf를 변경했다.
# cat /etc/resolv.conf
nameserver 192.168.56.200
dig로 테스트했다.
# dig yundream.joinc.priv

; <<>> DiG 9.9.5-3ubuntu0.7-Ubuntu <<>> yundream.joinc.priv
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37739
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;yundream.joinc.priv.		IN	A

;; ANSWER SECTION:
yundream.joinc.priv.	0	IN	A	192.168.56.155

;; Query time: 2 msec
;; SERVER: 192.168.56.200#53(192.168.56.200)
;; WHEN: Sun Apr 17 02:06:20 KST 2016
;; MSG SIZE  rcvd: 53
192.168.56.155를 반환하는 걸 확인 할 수 있다. 이 것으로 설정 끝.

Private DNS Server 구성

Private DNS Server를 구성하자. *.joinc.priv를 요청한 유저는 ProxyServer의 NginX 서버로 접근한다. NginX 서버는 유저의 요청을 192.168.56.100과 192.168.56.101중 하나로 프락시해야 한다. 프락시는 Host 이름을 기반으로 하는데, 이를 위해서 Private DNS Server를 구성해야 한다. 테스트를 위해서 아래와 같은 DNS 테이블을 구성하기로 했다.
Host Container instance IP
myapp.joinc.priv 192.168.56.100
yundream.joinc.priv 192.168.56.101
foo.joinc.priv 192.168.56.101
dnsmasq 패키지를 설치하고, 위 DNS 테이블의 내용을 담은 hosts 파일을 만들었다. /etc/hosts 파일은 운영체제에서 사용하는 것이므로, /etc/private.hosts 라는 별도의 파일을 만들기로 했다.
# cat /etc/private.hosts
192.168.56.100   myapp.joinc.priv
192.168.56.101   yundream.joinc.priv
192.168.56.101   foo.joinc.priv

ProxyServer 구성

NginX로 리버스 프락시 서버를 만든다.
# apt-get install nginx

NginX 리버스 프락스를 설정한다.
server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.html index.htm;

    server_name localhost;
    resolver 192.168.56.201;

    location / { 
        proxy_pass http://$request_uri;
    }
}
resolver로 Private Dns Server를 설정했다. 이제 유저요청이 들어오면 HOST정보를 읽어서 도메인이름을 룩업한 IP로 프락시한다. 192.168.56.201이 제대로 작동하는지 테스트해보자.
# nslookup 
> server 192.168.56.201
Default server: 192.168.56.201
Address: 192.168.56.201#53

> foo.joinc.priv
Server:		192.168.56.201
Address:	192.168.56.201#53

Name:	foo.joinc.priv
Address: 192.168.56.101
> yundream.joinc.priv
Server:		192.168.56.201
Address:	192.168.56.201#53

Name:	yundream.joinc.priv
Address: 192.168.56.101
> myapp.joinc.priv
Server:		192.168.56.201
Address:	192.168.56.201#53

Name:	myapp.joinc.priv
Address: 192.168.56.100

Container Instance 구성

SaaS 애플리케이션을 올리기 위해서 2개의 컨테이너 인스턴스(192.168.56.100, 192.168.56.101)을 만들었다. 일단 여기까지 연결이 잘 되는지 확인 하기 위해서 nginx 서버를 설치했다. 유저가 curl로 myapp.joinc.priv를 요청하면, 192.168.56.100 웹 서버에 접근을 할 것이다. 흐름은 다음과 같다.
  1. 유저가 curl로 myapp.joinc.priv를 요청한다.
  2. Prublic DNS Server는 *.joinc.priv에 등록된 IP인 192.168.56.155를 반환한다.
  3. curl은 192.168.56.155에 접속한다.
  4. Nginx는 등록된 resolver로 myapp.joinc.priv의 IP 주소를 가져오고, 192.168.56.100 으로 프락시 한다.
이제 도커 컨테이너로 웹 서비스를 올려서 테스트를 하면 된다. 이를 위해서는 인스턴스에도 프락시 서버가 필요하다. 아래 그림을 보자.

 Local Proxy Server

Public DNS Server와 Private DNS Sever를 이용해서 인스턴스까지 찾았다. 하지만 서비스를 위해서는 컨테이너까지 연결이 필요하다. DNS Server는 인터넷에 연결된 NIC을 찾는 것 까지가 역할이다. 애플리케이션을 찾기 위해서는 포트(Port)를 이용해야 한다. 여기에서는 80번 하나의 포트만을 이용해야 하므로, 결국 인스턴스에도 프락시 서버가 필요하게 된다. 이 프락시 서버는 도메인에 대한 컨테이너 ID 정보를 가지고 있다. 요청이 들어오면 HOST 이름을 읽어서 컨테이너로 프락시 한다.

범용 Service Discovery System 구성

SaaS 서비스의 핵심 기술은 DNS와 프락시다. 범용으로 사용할 수 있는 SaaS 서비스를 만들기 위해서는 애플리케이션 별로 프락시 서버를 만들어야 한다. 주요 애플리케이션들은 프락시 서버 혹은 프락시 서버를 개발 할 수 있는 라이브러리등을 제공하므로 어렵지 않게 개발 할 수 있을 것이다.

분산 시스템의 구성

프락시 서버와 DNS 서버들의 확장성과 가용성, 성능을 위해서 분산 시스템의 구성이 필요하다.