Search

'CoreOS'에 해당되는 글 3건

  1. 2016.10.05 Consul & Registrator
  2. 2016.08.12 CoreOS fleet unit 작성 및 실행
  3. 2016.08.10 CoreOS etcd cluster 사이즈 변경하기

Consul & Registrator

MicroService 2016.10.05 20:13 Posted by 김한별 behonestar


consul cluster 구성하기

1. consul 설치

$ wget https://releases.hashicorp.com/consul/0.7.0/consul_0.7.0_linux_amd64.zip

$ unzip consul_0.7.0_linux_amd64.zip

$ sudo cp consul /usr/local/bin


2. consul server 실행 (@instance1)
* -bind에는 실행 중인 인스턴스의 IP를 적는다.

$ consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=agent1 -bind=172.31.4.225


3. consul client 실행 (@instance2)
* -bind에는 실행 중인 인스턴스의 IP를 적는다.

$ consul agent -data-dir /tmp/consul -node=agent2 -bind=172.31.0.27 -config-dir /etc/consul.d


4. joining 클러스터 (@instance1)
* 방화벽 8300, 8301, 8500 포트가 열려있어야 한다.

$ consul join 172.31.0.27



registrator를 사용하여 consul에 service 등록

1. registrator 컨테이너 실행 (@instance2)

$ docker run -d \

    --name=registrator \

    --net=host \

    --volume=/var/run/docker.sock:/tmp/docker.sock \

    gliderlabs/registrator:latest \

      consul://localhost:8500


2. redis 컨테이너 실행

* -P 옵션만 주면 호스트의 랜덤 포트가 컨테이너의 exposed 포트(6379)에 할당된다.

$ docker run -d -P --name=redis redis


3. consul 등록된 서비스 확인

$ curl localhost:8500/v1/catalog/services
{"consul":[],"redis":[]}


4. redis 정보 확인

$ curl localhost:8500/v1/catalog/service/redis

[{"Node":"agent2","Address":"172.31.0.27","TaggedAddresses":{"lan":"172.31.0.27","wan":"172.31.0.27"},"ServiceID":"ip-172-31-0-27:redis:6379","ServiceName":"redis","ServiceTags":[],"ServiceAddress":"","ServicePort":32769,"ServiceEnableTagOverride":false,"CreateIndex":126,"ModifyIndex":183}]


5. redis 정지하면 서비스에서 제거된 것 확인

$ docker stop redis

$ curl localhost:8500/v1/catalog/services
{"consul":[]}



'MicroService' 카테고리의 다른 글

Consul & Registrator  (0) 2016.10.05
CoreOS fleet unit 작성 및 실행  (0) 2016.08.12
CoreOS etcd 클러스터 구축하기  (0) 2016.08.11
CoreOS etcd cluster 사이즈 변경하기  (0) 2016.08.10

CoreOS fleet unit 작성 및 실행

MicroService 2016.08.12 13:28 Posted by 김한별 behonestar

fleet은 systemd를 클러스터 레벨에서 제어하는 클러스터 매니저입니다. 클러스터 내에서 서비스를 실행하기 위해서는 먼저 systemd unit을 submit 해야합니다.

Unit file 작성

Redis 컨테이너를 실행하는 Unit file을 작성합니다. 이 때 docker 명령문에서 -d 옵션을 사용하지 않도록 주의해야 합니다. -d 옵션으로 인해 컨테이너가 detached 되면 unit이 종료되기 때문입니다.


/etc/systemd/system/redis@.service

[Unit]

Description=Redis

After=docker.service

Requires=docker.service


[Service]

TimeoutStartSec=0

ExecStartPre=-/usr/bin/docker kill redis%i

ExecStartPre=-/usr/bin/docker rm redis%i

ExecStart=/usr/bin/docker run --name redis%i -p 6379:6379 redis

ExecStop=/usr/bin/docker stop redis%i


[X-Fleet]

MachineMetadata=role=worker


Redis 컨테이너가 실행된 머신에서 Redis 컨테이너를 대신해서 IP, Port를 리포트해줄 Discovery Unit을 작성합니다. 이와 같이 메인 컨테이너의 보조 역할을 하는 유닛을 Sidekick 컨테이너라고 부릅니다.


/etc/systemd/system/redis-discovery@.service

[Unit]

Description=Announce redis

BindsTo=redis@%i.service

After=redis@%i.service


[Service]

ExecStart=/bin/sh -c "while true; do etcdctl set /services/redis/redis@%i '{ \"host\": \"%H\", \"port\": 6379 }' --ttl 60;sleep 45;done"

ExecStop=/usr/bin/etcdctl rm /services/redis@%i


[X-Fleet]

MachineOf=redis@%i.service


Unit 실행

먼저 현재 클러스터를 구성하고 있는 머신들을 확인해봅니다. 저는 다섯개의 머신이 등록되어 있습니다. 메타데이터에 role=service로 표시된 3개의 머신이 etcd 클러스터를 구성하고 있습니다. role=worker로 표시된 머신은 etcd proxy를 통해 etcd를 사용합니다.


fleetctl list-machines

MACHINE         IP              METADATA

23d8bb5c...     172.31.24.253   role=worker

5a06ff68...     172.31.24.254   role=worker

69bf522c...     172.31.17.24    role=services

a5ba2fc0...     172.31.17.23    role=services

bd460f19...     172.31.17.22    role=services


redis@1 unit을 실행합니다. MachineMetadata=role=worker 옵션에 따라 role=worker 메타데이터를 갖는 두개의 머신 중 하나에서 unit이 실행됩니다.


$ fleetctl start redis@1

Unit redis@1.service inactive

Unit redis@1.service launched on 5a06ff68.../172.31.24.254


redis-discovery@1 unit을 실행합니다. MachineOf=redis@%i.service 옵션에 따라 redis-discovery@1 unit은 redis@1 unit이 실행된 머신에서 실행됩니다. 실제 etcd에 기록된 값도 직접 읽어봅니다.


fleetctl start redis-discovery@1

Unit redis-discovery@1.service inactive

Unit redis-discovery@1.service launched on 5a06ff68.../172.31.24.254


$ etcdctl ls /services --recursive

/services/redis/redis@1


etcdctl get /services/redis/redis@1

{ "host": "ip-172-31-24-253.ap-northeast-2.compute.internal", "port": 6379 }


아래 명령을 통해 unit file 목록을 확인할 수 있습니다. fleetctl destroy 명령을 사용하면 unit file을 목록에서 제거할 수 있습니다. 단, 현재 실행 중인 unit도 정지되니 주의해야 합니다.


$ fleetctl list-unit-files

UNIT                            HASH    DSTATE          STATE           TARGET

redis-discovery@1.service    2fe5611 launched        launched        5a06ff68.../172.31.24.254

redis@1.service                 dc3f4f7  launched        launched        5a06ff68.../172.31.24.254


현재 실행 중인 unit은 아래 명령으로 확인할 수 있습니다. fleetctl stop 명령을 사용하면 unit을 정지시킬 수 있습니다. 


fleetctl list-units

UNIT                            MACHINE                         ACTIVE  SUB

redis-discovery@1.service    5a06ff68.../172.31.24.254       active  running

redis@1.service                 5a06ff68.../172.31.24.254       active  running



머신 장애에 따른 리커버리

클러스터 내의 머신들은 스케쥴링(유닛을 머신에 할당하는 작업)을 수행할 리더를 선출하고 모든 멤버들끼리 지속적으로 통신을 유지합니다. 만약 하나의 머신에 장애가 생겨서 리더에게 heartbeat 패킷을 보내지 못하게 되면, 해당 머신에서 실행중이던 모든 유닛은 리스케쥴링 됩니다. 리더는 각 유닛을 실행하기에 적합한 머신을 찾아내고, 해당 머신이 유닛을 실행하도록 명령합니다. 리스케쥴링이 불가능한 유닛은 적합한 머신을 찾을 때까지 stop 상태로  남게됩니다.


만약 장애가 발생했던 머신이 다시 복구되면, 리더는 해당 머신에게 오래된 유닛들을 정지시키도록 명령합니다. 이로인해 머신은 새로운 작업을 수행할 수 있는 상태가 됩니다. sudo systemctl stop fleet 명령어를 사용하여 머신 하나를 정지시키면 sudo journalctl -u fleet 로그를 통해 무슨 일이 발생하는지 확인할 수 있습니다.



HAProxy를 활용한 서비스 디스커버리 구현


etcd에 기록된 정보를 바탕으로 다른 머신의 어플리캐이션에서 Redis로 연결을 해보려고 합니다. etcd로부터 host, port를 얻어오는 과정을 어플리캐이션에서 직접 구현해도 되지만 저는 별도의 Discovery Agent를 통해 구현하려고 합니다. 


어플리캐이션과 Agent를 분리하면 어플리캐이션 개발자는 플랫폼에 의존적이지 않아도 되기 때문에 규모가 큰 프로젝트에서 유리합니다. 또한 etcd를 consul과 같은 다른 서비스로 변경할 일이 생기더라도 소스코드를 수정하지 않아도 되니 플랫폼이 보다 유연해집니다.





Discovery Agent 컨테이너 실행

Discovery Agent는 etcd에 저장된 Redis Unit의 Host, Port 정보를 바탕으로 HAProxy 설정을 업데이트합니다. HAProxy는 80 포트에 바인딩되어 실행되므로 80 포트를 열어줍니다. 컨테이너의 이름은 'discovery-agent'로 지정합니다. 


git clone https://github.com/behonestar/service-discovery

cd discovery-agent

docker build -t discovery-agent .

docker run -it -p 80:80 --name discovery-agent discovery-agent

/services/redis/redis@1

config changed. reload haproxy

/services/redis/redis@1

/services/redis/redis@1

...



Worker 컨테이너 실행

Worker는 'haproxy'라는 host로 연결을 요청합니다. 따라서 'discovery-agent' 컨테이너를 'haproxy'라는 별칭으로 link합니다. 만약 연결에 실패한다면 Security Group의 6379 포트가 Inbound 설정이 되어 있는지 확인합니다.


git clone https://github.com/behonestar/service-discovery

cd worker

docker build -t worker .

docker run -it --link discovery-agent:haproxy worker

bar

bar

bar

bar

...



참고


'MicroService' 카테고리의 다른 글

Consul & Registrator  (0) 2016.10.05
CoreOS fleet unit 작성 및 실행  (0) 2016.08.12
CoreOS etcd 클러스터 구축하기  (0) 2016.08.11
CoreOS etcd cluster 사이즈 변경하기  (0) 2016.08.10
TAG CoreOS, Fleet

CoreOS etcd cluster 사이즈 변경하기

MicroService 2016.08.10 09:25 Posted by 김한별 behonestar

CoreOS 설치


Document를 보고 AWS EC2 환경에 CoreOS 클러스터를 구축하였습니다. CloudFormation으로 구축하니 클릭 몇번으로 환경이 구성되어 굉장히 편리하네요.



각 인스턴스의 UserData는 아래와 같이 구성되었습니다. 만약 UserData를 변경하고 싶다면 인스턴스를 Stop한 경우에만 가능하다고 하네요.




Cluster 사이즈 변경


etcd의 discovery값은 etcd 클러스터 개수에 기반하여 생성된 값입니다. 그렇다면 etcd 클러스터 사이즈를 늘리기 위해서는 인스턴스들을 정지시키고 User Data를 모두 변경해줘야 할까요?


Document를 조금 더 읽어보니 etcdctl 명령어를 사용하면 downtime없이 클러스터를 추가하거나 삭제하는 것이 가능하다고 하네요. 직접 확인해보기로 하였습니다.


Changing Cluster Size

After your cluster is up and running, adding or removing members is done via runtime reconfiguration, which allows the cluster to be modified without downtime. The etcdctl tool has member list, member add and member remove commands to complete this process.


현재 클러스터 상태를 확인해봅니다.


$ etcdctl cluster-health

member 713c502a7e25bd01 is healthy: got healthy result from http://172.31.29.103:2379

member 7cc9bfe3dc785752 is healthy: got healthy result from http://172.31.6.44:2379

member ef90985d6207ea94 is healthy: got healthy result from http://172.31.6.43:2379

cluster is healthy


현재 클러스터 멤버를 확인해봅니다.


$ etcdctl member list

713c502a7e25bd01: name=de53964f7e9b427aa198c613e1d59d0a peerURLs=http://172.31.29.103:2380 clientURLs=http://172.31.29.103:2379 isLeader=false

7cc9bfe3dc785752: name=8b32e59fd309452bb8e9caa1bec7b66f peerURLs=http://172.31.6.44:2380 clientURLs=http://172.31.6.44:2379 isLeader=false

ef90985d6207ea94: name=9c1cba3901a8487e821539c8ef2a1ce8 peerURLs=http://172.31.6.43:2380 clientURLs=http://172.31.6.43:2379 isLeader=true


멤버를 추가하기 위해서 CoreOS 인스턴스를 하나 더 생성합니다. 이미 생성된 CoreOS 인스턴스를 선택하고 마우스 오른쪽 버튼을 누른 후 'Launch More Like This'를 눌러줍니다.



인스턴스 생성이 완료되면 클러스터 멤버로 추가합니다. 명령을 실행하면 출력되는 문자열은 나중에 환경변수로 등록해야하니 기억해두도록 합니다.


$ etcdctl member add instance4 http://172.31.22.9:2380

Added member named instance4 with ID c815853c77ea5901 to cluster


ETCD_NAME="instance4"

ETCD_INITIAL_CLUSTER="de53964f7e9b427aa198c613e1d59d0a=http://172.31.29.103:2380,..."

ETCD_INITIAL_CLUSTER_STATE="existing"


현재 클러스터 멤버를 다시 확인해봅니다. 멤버로 등록은 되었지만 "unstarted"로 표시됩니다. etcd가 실행될 때 기존 클러스터에 추가되는 설정으로 실행되지 않았기 때문입니다. etcd 설정을 변경하고 재시작해야 합니다.


$ etcdctl member list

713c502a7e25bd01: name=de53964f7e9b427aa198c613e1d59d0a peerURLs=http://172.31.29.103:2380 clientURLs=http://172.31.29.103:2379 isLeader=false

7cc9bfe3dc785752: name=8b32e59fd309452bb8e9caa1bec7b66f peerURLs=http://172.31.6.44:2380 clientURLs=http://172.31.6.44:2379 isLeader=false

c815853c77ea5901[unstarted]: peerURLs=http://172.31.22.9:2380

ef90985d6207ea94: name=9c1cba3901a8487e821539c8ef2a1ce8 peerURLs=http://172.31.6.43:2380 clientURLs=http://172.31.6.43:2379 isLeader=true


새로 생성된 인스턴스의 User Data는 아래와 같이 설정되어있으며 이로부터 생성된 파일이 20-cloudinit.conf 입니다. 현재 etcd는 20-cloudinit.conf에 정의된 환경변수를 설정값으로 사용하여 데몬 형태로 실행되고 있습니다.


User Data

#cloud-config


coreos:

  etcd2:

    discovery: https://discovery.etcd.io/fe86a59a6724e67fc59047d4daf583b7

    advertise-client-urls: http://$private_ipv4:2379

    initial-advertise-peer-urls: http://$private_ipv4:2380

    listen-client-urls: http://0.0.0.0:2379,http://0.0.0.0:4001

    listen-peer-urls: http://$private_ipv4:2380

  units:

    - name: etcd2.service

      command: start

    - name: fleet.service

      command: start


20-cloudinit.conf (/run/systemd/system/etcd2.service.d/)

[Service]

Environment="ETCD_ADVERTISE_CLIENT_URLS=http://172.31.22.9:2379"

Environment="ETCD_DISCOVERY=https://discovery.etcd.io/fe86a59a6724e67fc59047d4daf583b7"

Environment="ETCD_INITIAL_ADVERTISE_PEER_URLS=http://172.31.22.9:2380"

Environment="ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379,http://0.0.0.0:4001"

Environment="ETCD_LISTEN_PEER_URLS=http://172.31.22.9:2380"


새로운 etcd 노드가 기존 클러스터에 추가되어야하는 경우에는 ETCD_NAME, ETCD_INITIAL_CLUSTER, ETCD_INITIAL_CLUSTER_STATE 환경변수를 설정해줘야 합니다. 이 변수들은 etcdctl member add 명령을 실행했을 때 결과로 출력되었습니다. 


또한 20-cloudinit.conf가 정의한 ETCD_DISCOVERY를 제거해줘야 ETCD_INITIAL_CLUSTER 값이 적용됩니다. ETCD_DISCOVERY는 ETCD_INITIAL_CLUSTER보다 우선순위가 높기 때문입니다.


저는 임시로 데몬을 생성하여 위와 같은 작업을 수행하도록 하였습니다. 아래의 내용대로 99-restore.conf 파일을 작성합니다. 그리고 데몬을 갱신하고 필요한 작업을 수행하고 etcd를 재시작합니다.


99-restore.conf (/run/systemd/system/etcd2.service.d/)

[Service]

ExecStartPre=/usr/bin/rm -rf /var/lib/etcd2/proxy

Environment="ETCD_NAME=instance4"

Environment="ETCD_DISCOVERY="

Environment="ETCD_INITIAL_CLUSTER=de53964f7e9b427aa198c613e1d59d0a=http://172.31.29.103:2380,..."

# If this option is set to existing, etcd will attempt to join the existing cluster.

Environment="ETCD_INITIAL_CLUSTER_STATE=existing"


$ sudo systemctl daemon-reload

$ sudo journalctl _PID=1 -e -u etcd2

$ sudo systemctl restart etcd2


참고로 EC2 인스턴스의 User Data를 수정해서 20-cloudinit.conf의 환경변수 자체를 변경하는 방법도 있습니다.


#cloud-config


hostname: etcd-node

coreos:

  etcd2:

    name: instance4

    advertise-client-urls: http://$private_ipv4:2379

    initial-advertise-peer-urls: http://$private_ipv4:2380

    listen-client-urls: http://0.0.0.0:2379

    listen-peer-urls: http://$private_ipv4:2380

    initial-cluster: de53964f7e9b427aa198c613e1d59d0a=http://172.31.29.103:2380,...

    initial-cluster-state: "existing"

  units:

    - name: etcd2.service

      command: start


등록된 멤버를 다시 확인합니다. 정상적으로 표시되는 것을 볼 수 있습니다.


$ etcdctl member list

713c502a7e25bd01: name=de53964f7e9b427aa198c613e1d59d0a peerURLs=http://172.31.29.103:2380 clientURLs=http://172.31.29.103:2379 isLeader=false

7cc9bfe3dc785752: name=8b32e59fd309452bb8e9caa1bec7b66f peerURLs=http://172.31.6.44:2380 clientURLs=http://172.31.6.44:2379 isLeader=false

c815853c77ea5901: name=instance4 peerURLs=http://172.31.22.9:2380 clientURLs=http://172.31.22.9:2379 isLeader=false

ef90985d6207ea94: name=9c1cba3901a8487e821539c8ef2a1ce8 peerURLs=http://172.31.6.43:2380 clientURLs=http://172.31.6.43:2379 isLeader=true


이제 restore 데몬은 필요없으므로 제거합니다.


$ sudo rm /run/systemd/system/etcd2.service.d/99-restore.conf

$ sudo systemctl daemon-reload





참고


'MicroService' 카테고리의 다른 글

Consul & Registrator  (0) 2016.10.05
CoreOS fleet unit 작성 및 실행  (0) 2016.08.12
CoreOS etcd 클러스터 구축하기  (0) 2016.08.11
CoreOS etcd cluster 사이즈 변경하기  (0) 2016.08.10