confd, systemd, fleet을 이용한 
어플리케이션 배포 in CoreOS 
Docker Seoul Meetup #2 / Sep 26, 2014 
! 
by @subicura (김충섭)
service discovery 
haproxy 
load-balancer 
web1 
web application 
web2 
web application
Docker 구동에 최적화된 
가볍고 최소화된 모던 OS 
no package manager (apt/yum)
CoreOS 특징 
A Minimal Operating System Painless Updating 
Docker Containers Clustered By Default
CoreOS 구성 
etcd 
systemd 
fleet
etcd 
A highly-available key value store 
directory 
/services/web/web_1 172.17.8.101:49155 
key value
etcd 
A highly-available key value store 
cluster
Sidekick for service discovery 
APP ! haproxy 
APP ip/port 
set command etcdctl set key value 
etcdctl set /services/web/web_1  
172.17.8.101:49155 
etcdctl set /services/web/web_1  
172.17.8.101:49155  
--ttl 60 
*ttl : Time to live
service discovery 
APP ! haproxy 
APP ip/port 
get command etcdctl get key 
etcdctl get /services/web/web_1 
*recursive : 하위 디렉토리 포함 
watch command etcdctl watch key 
etcdctl watch /services/web  
--recursive
service discovery 
haproxy 
172.17.8.101:49155 
APP1 
APP2 
172.17.8.102:49155 
䡬 변화감지 
䡬 설정파일 수정 
䡬 프로그램 재시작 
= confd 
䡬 설정저장
confd 
lightweight configuration management tool 
䡬 written in Go 
䡬 etcd / Consul support 
䡬 template resource config (TOML) 
䡬 source template 
䡬 not stable (template syntax change) 
䡬 only support polling (not yet)
template resource config 
[template] 
src = "haproxy.conf.tmpl" 
dest = "/etc/haproxy/haproxy.conf" 
owner = "root" 
group = "root" 
mode = "0644" 
keys = [ 
“/services/web", 
] 
reload_cmd = "/usr/sbin/service haproxy restart" 
haproxy.toml
source template 
… 
! 
backend default 
balance {{ getv “/haproxy/balance" }} 
option httpclose 
option forwardfor 
{{ if ls "/services/web" }} 
{{ range gets "/services/web/*" }} 
server {{base .Key}} {{.Value}} check 
{{ end }} 
{{ end }} 
haproxy.cfg.tmpl 
https://github.com/kelseyhightower/confd/blob/0.6.x/docs/templates.md
DEMO
systemd 
System and Service Manager 
CoreOS default init system
sample.service 
[Unit] 
Description=My Service 1 
Requires=docker.service 
After=docker.service 
! 
[Service] 
ExecStart=/usr/bin/docker run --rm --name app1 busybox  
/bin/sh -c "while true; do echo Hello World; sleep 1; done" 
ExecStop=/usr/bin/docker kill app1
fleet 
distributed init system (systemd + etcd)
fleet 
[X-Fleet] fleet-specific Options 
䡬 MachineID - 해당하는 machine에서 실행 
䡬 MachineOf - 특정 서비스가 수행중인 machine에서 실행 
䡬 MachineMetadata - metadata를 가진 machine에서 실행 
䡬 Conflicts - 해당 서비스가 수행중인 machine을 피해서 실행 
*<= 0.8.0 : X-Condition prefix
sidekick pattern 
container를 실행하거나 
container를 중지할때 
container의 정보를 etcd에 저장하는 
sidekick용 service를 활용
sidekick pattern 
web 
application 
container 
web 
application 
sidekick 
service 
기존 컨테이너 수정없이 추가하여 사용가능 
(socket 통신시) 
etcd
/etc/environment 
COREOS_PUBLIC_IPV4=172.17.8.102 
COREOS_PRIVATE_IPV4=172.17.8.102
docker inspect 
"NetworkSettings": { 
"Bridge": "docker0", 
"Gateway": "10.1.42.1", 
"IPAddress": "10.1.0.16", 
"IPPrefixLen": 16, 
"PortMapping": null, 
"Ports": { 
"80/tcp": [ 
{ 
"HostIp": "0.0.0.0", 
"HostPort": "49167" 
} 
] 
} 
} 
docker inspect --format='{{(index (index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' web1
web.service의 sidekick service 
[Unit] 
Description=Web1 Sidekick Container 
! 
After=web.1.service 
BindsTo=web.1.service 
! 
[Service] 
EnvironmentFile=/etc/environment 
! 
… 
! 
[X-Fleet] 
MachineOf=web.1.service 
! 
! 
! 
# 특정 서비스 실행 후 실행 
# 특정 서비스 종료 시 종료 
! 
! 
# CoreOS cloud 설정파일 
! 
! 
! 
! 
# 특정 서비스가 실행중인 
서버에서 실행
web.service의 sidekick service 
ExecStart=/bin/sh -c  
"SERVICE_PORT=$(docker inspect --format='{{(index 
(index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' web1) &&  
while true; do  
etcdctl set /services/web/web1  
”$COREOS_PRIVATE_IPV4:$SERVICE_PORT" --ttl 60;  
sleep 45;  
done" 
ExecStop=/usr/bin/etcdctl rm /services/web/web1 
ttl을 활용하자
DEMO - ver.1
더 나은 systemd service 파일 
1. %p %i 변수를 사용하자 
web@1.service 
%p %i
더 나은 systemd service 파일 
1. %p %i 변수를 사용하자 
[Unit] 
Description=My Service %i 
Requires=docker.service 
After=docker.service 
! 
[Service] 
ExecStart=/usr/bin/docker run --rm --name %p-%i busybox  
/bin/sh -c "while true; do echo Hello World; sleep 1; done" 
ExecStop=/usr/bin/docker kill %p-%i
더 나은 systemd service 파일 
2. TimeoutStartSec=0 옵션을 추가하자. 
[Service] 
TimeoutStartSec=0 
docker pull이 오래걸릴 경우 
timeout으로 실패하는 걸 방지
더 나은 systemd service 파일 
3. Restart=always 옵션을 추가하자. 
[Service] 
Restart=always 
RestartSec=10s 
실행이 종료될 경우 자동으로 재시작함
더 나은 systemd service 파일 
4. Environment 옵션을 활용하자. 
[Service] 
Environment="SERVICE_NAME=%p_run-%i" 
Environment=“SERVICE_ETCD_KEY=/services/web/%p-%i" 
Environment="SERVICE_IMAGE_URL=subicura/whoami" 
범용적으로 활용가능
더 나은 systemd service 파일 
5. ExecStartPre 옵션을 활용하자. 
[Service] 
ExecStartPre=-/usr/bin/docker kill $SERVICE_NAME 
ExecStartPre=-/usr/bin/docker rm $SERVICE_NAME 
ExecStartPre=/usr/bin/docker pull $SERVICE_IMAGE_URL 
ExecStart=/usr/bin/docker run --rm  
--name $SERVICE_NAME -P $SERVICE_IMAGE_URL 
ExecStop=/usr/bin/docker stop $SERVICE_NAME 
“-“ 옵션은 프로세스가 실패해도 다음을 진행함
DEMO - final
conclusion 
easy & flexible configuration 
type default docker etcd+confd 
방식 설정파일 환경변수 etcd 
특징 
위치를 찾기 어려움 
너무 많은 옵션 
문서화가 필수 
관리 어려움 
중요한 옵션 찾기 쉬움 
파일로 관리 
관리 쉬움 
모든 설정파일을 한곳 
에서 관리함 
동적 설정이 쉬움
conclusion 
service manage 
type default docker fleet 
방식 source repository container service file 
특징 
소스 컴파일 또는 소스 
저장소를 이용함 
관리 어려움 
Dockerfile을 이용함 
관리 쉬움 
중앙에서 관리 가능
THANK YOU 
! 
QUESTION?
code 
䡬 discovery sample - https://github.com/subicura/ 
discovery-fleetd-sample 
䡬 haproxy-confd - https://github.com/subicura/ 
haproxy-confd 
䡬 whoami - https://github.com/subicura/whoami

Confd, systemd, fleet을 이용한 어플리케이션 배포 in CoreOS

  • 1.
    confd, systemd, fleet을이용한 어플리케이션 배포 in CoreOS Docker Seoul Meetup #2 / Sep 26, 2014 ! by @subicura (김충섭)
  • 2.
    service discovery haproxy load-balancer web1 web application web2 web application
  • 3.
    Docker 구동에 최적화된 가볍고 최소화된 모던 OS no package manager (apt/yum)
  • 4.
    CoreOS 특징 AMinimal Operating System Painless Updating Docker Containers Clustered By Default
  • 5.
    CoreOS 구성 etcd systemd fleet
  • 6.
    etcd A highly-availablekey value store directory /services/web/web_1 172.17.8.101:49155 key value
  • 7.
    etcd A highly-availablekey value store cluster
  • 8.
    Sidekick for servicediscovery APP ! haproxy APP ip/port set command etcdctl set key value etcdctl set /services/web/web_1 172.17.8.101:49155 etcdctl set /services/web/web_1 172.17.8.101:49155 --ttl 60 *ttl : Time to live
  • 9.
    service discovery APP! haproxy APP ip/port get command etcdctl get key etcdctl get /services/web/web_1 *recursive : 하위 디렉토리 포함 watch command etcdctl watch key etcdctl watch /services/web --recursive
  • 10.
    service discovery haproxy 172.17.8.101:49155 APP1 APP2 172.17.8.102:49155 䡬 변화감지 䡬 설정파일 수정 䡬 프로그램 재시작 = confd 䡬 설정저장
  • 11.
    confd lightweight configurationmanagement tool 䡬 written in Go 䡬 etcd / Consul support 䡬 template resource config (TOML) 䡬 source template 䡬 not stable (template syntax change) 䡬 only support polling (not yet)
  • 12.
    template resource config [template] src = "haproxy.conf.tmpl" dest = "/etc/haproxy/haproxy.conf" owner = "root" group = "root" mode = "0644" keys = [ “/services/web", ] reload_cmd = "/usr/sbin/service haproxy restart" haproxy.toml
  • 13.
    source template … ! backend default balance {{ getv “/haproxy/balance" }} option httpclose option forwardfor {{ if ls "/services/web" }} {{ range gets "/services/web/*" }} server {{base .Key}} {{.Value}} check {{ end }} {{ end }} haproxy.cfg.tmpl https://github.com/kelseyhightower/confd/blob/0.6.x/docs/templates.md
  • 14.
  • 15.
    systemd System andService Manager CoreOS default init system
  • 16.
    sample.service [Unit] Description=MyService 1 Requires=docker.service After=docker.service ! [Service] ExecStart=/usr/bin/docker run --rm --name app1 busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done" ExecStop=/usr/bin/docker kill app1
  • 17.
    fleet distributed initsystem (systemd + etcd)
  • 18.
    fleet [X-Fleet] fleet-specificOptions 䡬 MachineID - 해당하는 machine에서 실행 䡬 MachineOf - 특정 서비스가 수행중인 machine에서 실행 䡬 MachineMetadata - metadata를 가진 machine에서 실행 䡬 Conflicts - 해당 서비스가 수행중인 machine을 피해서 실행 *<= 0.8.0 : X-Condition prefix
  • 19.
    sidekick pattern container를실행하거나 container를 중지할때 container의 정보를 etcd에 저장하는 sidekick용 service를 활용
  • 20.
    sidekick pattern web application container web application sidekick service 기존 컨테이너 수정없이 추가하여 사용가능 (socket 통신시) etcd
  • 21.
  • 22.
    docker inspect "NetworkSettings":{ "Bridge": "docker0", "Gateway": "10.1.42.1", "IPAddress": "10.1.0.16", "IPPrefixLen": 16, "PortMapping": null, "Ports": { "80/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "49167" } ] } } docker inspect --format='{{(index (index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' web1
  • 23.
    web.service의 sidekick service [Unit] Description=Web1 Sidekick Container ! After=web.1.service BindsTo=web.1.service ! [Service] EnvironmentFile=/etc/environment ! … ! [X-Fleet] MachineOf=web.1.service ! ! ! # 특정 서비스 실행 후 실행 # 특정 서비스 종료 시 종료 ! ! # CoreOS cloud 설정파일 ! ! ! ! # 특정 서비스가 실행중인 서버에서 실행
  • 24.
    web.service의 sidekick service ExecStart=/bin/sh -c "SERVICE_PORT=$(docker inspect --format='{{(index (index .NetworkSettings.Ports "80/tcp") 0).HostPort}}' web1) && while true; do etcdctl set /services/web/web1 ”$COREOS_PRIVATE_IPV4:$SERVICE_PORT" --ttl 60; sleep 45; done" ExecStop=/usr/bin/etcdctl rm /services/web/web1 ttl을 활용하자
  • 25.
  • 26.
    더 나은 systemdservice 파일 1. %p %i 변수를 사용하자 web@1.service %p %i
  • 27.
    더 나은 systemdservice 파일 1. %p %i 변수를 사용하자 [Unit] Description=My Service %i Requires=docker.service After=docker.service ! [Service] ExecStart=/usr/bin/docker run --rm --name %p-%i busybox /bin/sh -c "while true; do echo Hello World; sleep 1; done" ExecStop=/usr/bin/docker kill %p-%i
  • 28.
    더 나은 systemdservice 파일 2. TimeoutStartSec=0 옵션을 추가하자. [Service] TimeoutStartSec=0 docker pull이 오래걸릴 경우 timeout으로 실패하는 걸 방지
  • 29.
    더 나은 systemdservice 파일 3. Restart=always 옵션을 추가하자. [Service] Restart=always RestartSec=10s 실행이 종료될 경우 자동으로 재시작함
  • 30.
    더 나은 systemdservice 파일 4. Environment 옵션을 활용하자. [Service] Environment="SERVICE_NAME=%p_run-%i" Environment=“SERVICE_ETCD_KEY=/services/web/%p-%i" Environment="SERVICE_IMAGE_URL=subicura/whoami" 범용적으로 활용가능
  • 31.
    더 나은 systemdservice 파일 5. ExecStartPre 옵션을 활용하자. [Service] ExecStartPre=-/usr/bin/docker kill $SERVICE_NAME ExecStartPre=-/usr/bin/docker rm $SERVICE_NAME ExecStartPre=/usr/bin/docker pull $SERVICE_IMAGE_URL ExecStart=/usr/bin/docker run --rm --name $SERVICE_NAME -P $SERVICE_IMAGE_URL ExecStop=/usr/bin/docker stop $SERVICE_NAME “-“ 옵션은 프로세스가 실패해도 다음을 진행함
  • 32.
  • 33.
    conclusion easy &flexible configuration type default docker etcd+confd 방식 설정파일 환경변수 etcd 특징 위치를 찾기 어려움 너무 많은 옵션 문서화가 필수 관리 어려움 중요한 옵션 찾기 쉬움 파일로 관리 관리 쉬움 모든 설정파일을 한곳 에서 관리함 동적 설정이 쉬움
  • 34.
    conclusion service manage type default docker fleet 방식 source repository container service file 특징 소스 컴파일 또는 소스 저장소를 이용함 관리 어려움 Dockerfile을 이용함 관리 쉬움 중앙에서 관리 가능
  • 35.
    THANK YOU ! QUESTION?
  • 36.
    code 䡬 discoverysample - https://github.com/subicura/ discovery-fleetd-sample 䡬 haproxy-confd - https://github.com/subicura/ haproxy-confd 䡬 whoami - https://github.com/subicura/whoami