Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
스타트업에 traefik + docker-swarm을 추천하는 이유

스타트업에 traefik + docker-swarm을 추천하는 이유

  • Traefik: Reverse-proxy router
  • Docker-swarm: Docker-supported orchestrator

왜 Docker-Swarm인가?

  • kubernetes(이하 k8) 는 무겁고 느리다. docker-swarm(이하 DS)docker 최신버전에 기본으로 탑재되어 나온다. 또한 helm이나 별도의 관리 cli(kubeadm, kubectl)를 설치할 필요가 없다.

  • k8 은 세팅도 어렵다: 세팅하기가 워낙 까다로워 실제로 운영하기 적절한 경우는 devops 팀을 가진 최소 20명 이상의 대규모 사이즈 팀이다. 한 명이 작업하는 것이 아주 불가능한 것은 아니지만, 긴급수정시에는 많이 위험해질 수 있다. 총원이 10명이 되지 않는 우리팀 같은 경우는 한 사람이 급하게 기능수정을 해야될 일이 많다.

  • k8docker-swarm(이하 DS) 의 편리성을 따라잡고자 편리한 기능을 마구잡이로 수입해오고 있는 중. 예) Persistent Volume, kubectl run 명령어

  • 우리 프론트/백엔드에 가장 적절: 여러 클러스터/노드에 작업하는 경우와 달리 현재는 한 서버에 nginx + node 형식으로 싱글 클러스터/노드를 elastic beanstalk 로 묶은 형태로 운영중이다.(적어도 얼마 전 까지는) 적은 수의 클러스터 혹은 싱글 클러스터에서는 설정할 것이 비교적 적은 항상 DS 가 유리하다. 물론 DS 도 외부 클러스터/노드 연결, 로드밸런싱, 라운드로빈을 모두 지원한다.

  • DS 역시 k8 모드를 지원한다: DS 인터페이스 통하여 실제 작업은 k8으로 하는 모드. 혹은 커뮤니티 주도로 DS 설정 파일을 k8 설정 파일로 변경해주는 kompose 같은 툴도 있다. 즉 업계의 전반적인 분위기가 복잡한 k8보다 docker-swarm에 훨씬 호의적이다.

  • 물론 거대한 스케일의 개발은 k8이 항상 유리하다. 큰 용량만큼 각종 커스터마이징을 지원하기 때문. 그러나 스케일업을 노리는 작은 스타트업에는 대부분 무의미한 기능들이다. DS는 설치가 간단하고, 세팅파일의 크기도 작으므로 스케일업 할 때에는 그냥 DS를 과감하게 버리면 된다! 아니면 적절하게 k8으로 다시 써서 스케일업해도 된다. 도커로 작성한 이미지는 어차피 그대로 유지되고 변경되는 것은 오로지 라우터와 로드밸런서 정도 뿐이므로 쓸데없는 노동력 낭비가 아니다.

  • k8을 돌리기 위한 최소사양이 높고, 설치 과정이 까다롭거나 아예 막혀있기 때문에 k8의 경우 클라우드사 자체에서 서비스로 제공하는 k8을 사용하도록 권장되고 있다. 그러나 여기에 함정이 있다.

  • 구글 클라우드(GCP)를 제외하고 나머지 클라우드 k8은 다소 버전업이 늦고 포킹 때문에 저마다 다른 구현을 보여주고 있어서 추천되지 않는다. 예를 들면 Amazon EKS라던지...

  • 반대로 GCP의 k8(GKE)은 가격이 어마무시하게 비싸다. 현재 ec2 프론트가 한달 만원이 안되는 가격(9달러)에 서버 세개를 돌리는데, GKE는 서비스별로 컴퓨트 엔진이라는 명목하에 만원 넘는 가격이 되기 때문에 사실상 3~4배 이상의 가격이다:

    • ec2 한달 가격: 약 9달러(약 만원)
    • GKE: nginx+웹서비스(단일 노드)24.27달러 + 로드밸런서18.26달러 + 볼륨(디스크)0.05$ = 42.58(약 5만원) - 최대한 적게 잡은 금액이고, k8을 돌리기 위한 최소사양에 맞추면(너무 사양을 낮게 잡으면 k8이 이상작동하는 경우도 있다고 함) 더 비싸질 수 있음. 게다가 도커 레지스터 가격은 별도!
    • ec2 + 도커 레지스터: 2만원정도면 프론트 구현은 충분! 용량도 훨씬 크다.
  • 또한 2019 DEVIEW에서 알게된 바로는 bare-metal이 오케스트레이터를 통한 가용자원 분배에도 효율적이다. 서버에 남는 공간이 있으면 다른 컨테이너에 넘겨주는 방식으로…

  • 네이버도 Docker-swarm을 약 2년간 사용: DEVIEW참석했다 알게 됨. 아마도 규모에 따라 HA 이슈가 중요해지면서 당시 버전이 낮은 docker-swarm에 있던 문제들을 해결하기 위해 k8으로 옮겨탄 것으로 추정.

왜 Traefik인가?

  • nginx 의 경우 퍼포먼스로는 최강이지만, orchestrator 에는 적합하지 않다: 컨테이너를 인식하는 기능 자체가 없다. 이를 극복하기 위해서는 각종 헬퍼 툴 (DS: nginx-proxy, nginx-proxy-companion/k8: ingress-nginx) 을 이용해야되는데 오케스트레이터 툴과 달리 대부분 커뮤니티 주도로 운영되고 있어서 늦은 업데이트나 부실한 문서 등 문제가 있다. 반대로 기업용은 헬퍼 툴도 있으나 필요 이상의 비용 지불이 있다. Traefik 은 헬퍼 툴로 구현되는 기능 대부분을 직접 구현하고 있다. 즉 reverse-proxy router + container helper(companion) 의 결합체인 셈.

  • 각종 https 용 인증 작업도 내장되어 있어서 별도의 인증작업을 수동으로 하거나 적합한 인증툴을 찾아 돌아다닐 필요가 없다. 인증작업시의 오류 로그도 관찰하기 쉬운 편.

  • Containous 라는 컨테이너 전문 클라우드 기업에 의하여 오픈소스로 개발중이며 사실상 nginx를 대신할 차기 reverse-proxy router로 각광받고 있다. nginx가 초반에 개인 주도로 개발되어 이에 따른 각종 legacy를 갖고 있는 것에 비해 훨씬 합리적으로 개발되고 있다. 예를 들자면 문서에 버전이 달려있어 다른 버전간의 오류가 없고, 인터넷에서 설정을 인용할 때에도 내가 무슨 버전을 인용하고 있는지 알 수 있다. 또한 .toml과 .yaml 혹은 직접 CLI를 통한 imperative한 설정 어느 것도 다 가능하다.

  • 충실한 기술문서 제공: nginx는 무료버전(Community Edition:CE)/기업용 유료버전(Enterprise Edition:EE)간의 매뉴얼 차이가 큰데, Traefik은 어느 버전에서나 문서가 비교적 잘 제공되고 있다

  • nginx는 별도의 기능을 이용하기 위해 서드파티 module(플러그인)을 사용해야하고, 이를 위해서 직접 코드 리빌드를 해야된다. Traefik은 최신 툴답게 왠만한 기능은 이미 자체적으로 다 있다.

  • 이미 네이버NCC 에서도 nginx의존을 없애고 Traefik사용중

docker-swarm을 사용하며 내가 배운 것들(대부분 구글에서 찾을 수 없는 것들)

  • nginx/proxy 사용시 특이사항:
    • internal network을 만들면 upstream error를 발생시킨다.(traefik과 반대)
    • gzip 설정은 vhost.d/${URL} 디렉토리를 통하여 제공해야한다.
  • 여러 강좌 및 용례를 통하여 봤을 때, 극단적인 사례를 제외하고 항상 traefik을 사용하는 쪽이 오케스트레이션에 용이하다. 퍼포먼스로는 조금 뒤쳐질지 모르나, 설정이 매우 편리하고 오케스트레이션만을 위한 최적화와 추가기능이 구비되어 있다. 최소 수십 명 이상의 대규모 개발진이 아닌 이상은 고려할만 하다.
  • dockerize구현이나 healthcheck는 생각보다 설정이 어렵다. 그리고 꼭 필요하다고 보기도 어렵다. 만약 에러가 없다면 당장은 필요하지 않을지도 모른다.
  • 앱은 직접 healthcheck 기능을 구현하고 있어야 한다. 그렇지 않으면 curl을 직접 설치해야되고 이는 이미지 용량에도 부담이 되며, 단순 url 핑 체크 이외의 기능을 구현하기가 까다로워진다.
  • 모든 설정은 파일이 아니라 환경변수를 통하여 제공되어야 한다. 그래야 오케스트레이션에서 한눈에 보고 설정하기 편하다.
  • traefik 버전 2.0 문서가 1.0보다 훨씬 낫다. LTS버전도 10월부터 2.0으로 올라갔다.
  • ACME let's encrypt는 인증 횟수 제한이 있으므로 stage url에서 개발하고 로그에 문제가 없으면 버전을 올리자. 오케스트레이션을 통하여 자동인증을 받게 될 경우 기본세팅에 따라 대부분 인증이 성공할때까지 연속시도를 하게 되기 때문에, 금방 횟수 제한에 걸려 블락을 먹게 되기 때문이다. 블락을 먹게 될 경우 blacklist되었다는 내용이 메시지로 전달되므로 로그를 유심히 보자.
  • 개인적인 의견이지만, 개발 단계에서부터 docker-swarm/docker-stack 형식으로 개발하는 편이 docker-compose로 작성하고 나중에 양식을 변경하는 것보다 쉽다. 그리고 traefik 에서 두 가지를 다루는 방식이 꽤 다르기 때문에 나중에 골치가 아프다.
  • traefik 사용시 특이사항:
    • traefik.yaml이 없을 경우 로그가 아예 남지 않는다. 아무도 언급하지 않지만 제일 중요한 사항.
    • httphttpsdeploy.labels 세팅은 각각 별도로 제공되어야 한다.
    • docker-swarm에서는 별도로 포트를 열지 않아도 모든 컨테이너의 포트가 서로 통신할 수 있다. docker-compose 파일에서 포트를 여는 것은 내부로 포트를 여는 것이 아니라 외부로 포트를 연다는 뜻이다. 포트는 디버그를 위해서 여는 것이고 불필요하게 포트를 열면 보안 취약점이 된다.
    • docker container logs ${container name}으로 컨테이너 로그를 확인하고, docker stack ps ${APP_NAME} --no-trunc로 서비스 로그를 확인한다. 각기 다른 로그를 제공하므로 둘다 놓치지 않고 확인해야한다.
    • GoLang이 작은따옴표를 제대로 파싱하지 못하기 때문에 작은따옴표(') 대신 백틱(`)을 사용해야 한다.
    • traefik용 서비스는 manager node로 지정해야 한다.
    • driver:overlay는 다른 네트워크에 있는 별도 노드에 접속하기 위해서 사용한다. 단일 노드일때에는 별로 중요하지 않은데, 후일 스케일업을 위해서 넣는 편이 좋다.
  • 암호는 항상 파일로 전달하는 편이 환경 변수로 전달하는 것보다 안전하다. 왜냐하면 파일과 달리 environment variable은 다른 컨테이너로 노출될 수 있기 때문이다. 따라서 여러 이미지를 굴리다보면 의도하지 않게 보안 취약점을 만들게 될 수 있다.
  • db 인증이 되지 않는다면 볼륨을 확인하여 삭제하자. 첫 실행에서 아이디와 비밀번호가 생성되는 것이 보통 관례이다. 휘발성 있는 k8의 볼륨과 달리 docker-swarm의 볼륨은 항상 유지되므로 주의하자.
  • db 로그인시 인코딩에 주의하자! 또는 stdout과 파일, 환경변수가 각각 모두 다른 인코딩을 가지고 있을 수 있음에 주의하자!
  • node.js 주의점:
    • 도커 시크릿은 입력값이 파일로 변환되면서 줄바꿈이 임의로 삽입된다. 줄바꿈을 항상 제거하고 시크릿 값을 사용하자
  • HTTPS 보안 구현:
    • HTTPS challenge 종류 설명
    • HTTPS challenge 종류 설명 2
      • TLS-SNI-01: 2019년 3월에 종료(deprecated). 사용하지 말 것.
      • DNS-01: DNS API 암호키를 제공하여야 한다. 하지만 서버가 공격받을 경우 DNS에 등록된 개인정보까지 털릴 수 있어서 극도로 위험하다. 가능하면 이용하지 말 것.
      • TLS-ALPN-01 : traefik이 443포트로 접근이 가능해야 한다. 임시 인증서를 발급하여 이를 DNS로 확인하는 challenge 방식. official docs on TLS-ALPN challenge
      • HTTP-01: traefik이 80포트로 접근이 가능해야 한다. 와일드카드 서브도메인(*.xxxx.xxx)을 사용할 수 없다. 일부 프로바이더들은 80포트를 안전상의 이유로 막아놓기도 한다. 임시 파일을 호스팅하여 이를 DNS로 확인하는 방식. official docs on HTTPS challenge
  • 템플릿을 서빙하는 임시 이미지를 실제 웹 도메인에 먼저 올려서 나중의 인증작업에서 시간을 더 낭비하지 않도록 하자.
  • letsencrypt json file 을 확인하여 HTTPS 성공 여부를 확인 가능하다.
  • :443포트와 :433 포트를 헷갈리는 경우가 간혹 있다. 주의하자.
  • redirect middleware를 사용하지 말고 HTTPS redirection header 를 사용하자. 특정 경우에서 redirect middleware가 이상하게도 동작하지 않는 경우가 있었다.
  • middleware에 대한 traefik 공식 문서에 따르면 xxx@file 이 외부 설정파일에 사용된다고만 하지 정확히 어디까지가 외부파일인지 명확하게 밝혀놓지 않았다. 기본 .yaml 이나 .toml@docker 도 아니고 @file 도 아니다. 설정을 좀더 간단하게 하고 싶다면 .deploy.labels + xxxx@docker 를 결합하여 사용하는 쪽이 낫다.

기타 참조 링크

@dailyworker

This comment has been minimized.

Copy link

@dailyworker dailyworker commented Feb 22, 2021

매우 좋은 아티클이네요 잘 보고 갑니다!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment