이 게시물은 2014년 10월 nginx.conf에서 Belly Card의 Kevin Reedy가 발표한 프레젠테이션 내용을 수정한 것입니다. 몇 년 전 일이지만, 그 내용은 오늘날에도 여전히 매우 관련성이 높습니다. 프레젠테이션 녹화본은 YouTube 에서 볼 수 있습니다.
목차
0:00 | 소개 |
개요 | |
부인 성명 | |
1:16 | 벨리(Belly)란 무엇인가? |
벨리스 스택 | |
1:44 | 버전 0: 암흑의 시대 |
2:04 | 버전 1: 새로운 희망 |
2:35 | 버전 2: 홈페이지와 API 분리 |
오늘의 유행어: 서비스 지향적 아키텍처! | |
SOA 활성화 | |
NGINX가 ELB를 대체합니다 | |
업스트림 및 가상 서버 구성 | |
결과 | |
4:43 | Chef를 사용한 구성 |
레시피 | |
파일 | |
템플릿 | |
요리책 | |
6:49 | 예: NGINX의 셰프 |
설치, 구성 및 튜닝 | |
라우팅 API 트래픽 | |
9:46 | 실제 세계의 셰프 사례 |
10:08 | 버전 2: 앱 배포 |
10시 40분 | 버전 3: SOA 모든 것 |
그리고 Heartbleed가 일어났습니다. | |
SSL 모든 것 | |
12시 25분 | 버전 4: 도커 |
이익 | |
컨테이너 배포 | |
15:45 | 배포 전략 |
17:43 | 서비스 검색 옵션 |
18:33 | 영사 건축 |
19시 30분 | 영사 기능 |
22:07 | 영사 템플릿 |
Consul 템플릿을 시작하기 위한 명령 | |
Consul 템플릿을 사용한 NGINX 구성 | |
Consul 템플릿을 사용한 구성 관리 | |
24:35 | Chef를 사용하여 Consul 배포 |
25:44 | 프로 팁 |
셰프 부분 검색 | |
DNS | |
오래된 구성 방지 | |
30:35 | 질문 |
36:31 | 연락처 정보 |
안녕하세요 여러분. 저는 케빈 리디입니다. 저는 시카고에 있는 Belly Card라는 회사에서 일하고 있습니다. 우리 회사에는 직원이 100명 정도이고 엔지니어는 20명 정도입니다. 오늘은 우리가 부하 분산을 수행하는 방법, 특히 항상 변화하는 동적 인프라에서의 부하 분산에 대해 이야기해 보겠습니다.
그럼 먼저, 저는 암흑기라고 부르는 버전 0부터 시작하여 시간에 따른 인프라 스택에 대해 말씀드리겠습니다. 그런 다음 Chef를 사용하여 NGINX를 구성하는 방법을 살펴보겠습니다. 그 후 Consul 서비스 검색 플랫폼이라는 것에서 데이터를 사용하여 NGINX를 구성하는 방식으로 어떻게 변경했는지에 대해 이야기하겠습니다. 시간이 허락한다면 NGINX 구성에 대한 몇 가지 전문가 팁이 있습니다. 특히 구성 관리와 관련하여요.
그래서 제가 여러분에게 Chef와 Consul에 관해 이야기하려고 하지만, 이 이야기의 어떤 부분도 그 둘에만 국한되지 않는다는 점을 밝혀두고 싶습니다. Chef, Puppet, Ansible, Salt, CFEngine 등은 모두 훌륭한 제품들이고, 그중 하나를 꼭 사용해보세요. 저희는 셰프를 좋아하고, 다른 많은 사람들도 좋아할 거라고 확신합니다.
서비스 발견에도 마찬가지입니다. Consul, etcd, ZooKeeper는 모두 훌륭하므로 자신에게 맞는 것을 사용하면 됩니다.
벨리(Belly)란 무엇인가? 기본적으로 이것은 커피숍에서 음료 10잔을 사면 1잔을 무료로 받는 펀치 카드를 디지털로 대체한 것입니다. 우리는 매장에 아이패드를 놓고, 고객은 휴대폰이나 QR 코드가 있는 실제 카드를 사용하여 스캔하고, 우리는 고객의 포인트를 추적하고, 보상을 제공하고, 이를 기반으로 마케팅 도구를 구축합니다.
하지만 저는 여기서 여러분에게 회사의 배에 대해 이야기하려는 것이 아닙니다. 관심이 있으시다면 저희 웹사이트 로 가시면 됩니다. 저는 우리의 인프라 스택에 대해 말씀드리겠습니다.
그래서 버전 0이에요. 개발자가 3명이고 제가 그곳에서 일하기 전에 Belly는 모놀리식 Ruby on Rails 애플리케이션이었는데, 이는 모든 API 호출과 웹사이트의 일부가 단일 Rails 앱으로 이동했음을 의미합니다. MySQL, MongoDB, Memcached로 지원되었고, Heroku에 배포했는데, 시작하기에 좋은 곳입니다.
그래서 버전 1은 새로운 희망이에요. 우리는 Heroku가 더 이상 우리의 요구를 충족시킬 수 없다고 결정하고, 본질적으로 Ruby로 작성된 "셸 스크립트보다 더 나은" Capistrano라는 것을 배포하기 시작했습니다. 이는 물건을 배치하는 데 도움이 됩니다.
Amazon Web Services EC2에는 약 6개의 서버가 있었습니다. 그건 고정된 숫자였지만, 뭔가 큰 일이 일어난다고 생각되면 숫자를 늘렸고, 필요하다면 숫자를 줄였습니다. 그 앞에는 AWS Elastic Load Balancer가 있었습니다.
그래서 우리는 홈페이지를 나머지 API에서 분리하고 싶은 프로젝트가 생겼습니다. 우리는 홈페이지를 더 빨리 진행하고 다른 개발자들이 작업할 수 있도록 이렇게 하기를 원했습니다.
당시와 오늘날에도 여전히 가장 큰 유행어는 서비스 지향 아키텍처입니다.
따라서 스택의 버전 2는 서비스 지향 아키텍처를 활성화하는 것이었습니다. 우리의 첫 번째 계획은 홈페이지를 API에서 분리하는 것이었습니다. 정말 간단해 보입니다. www.bellycard.com 과 api.bellycard.com 만 있으면 됩니다.
하지만 일부 모바일 애플리케이션은 www.bellycard.com/api 와 /api‑assets를 사용하도록 정적으로 작성되었기 때문에 실제로는 정말 복잡하고 간단하지 않았습니다. 당사의 이메일 제공자와 이미 사람들에게 이메일로 발송된 모든 클릭 링크에는 "이메일 열기"를 나타내는 /eo 와 "이메일 클릭"을 나타내는 /ec가 있습니다. 우리의 페이스북 앱은 /facebook/callback 으로 구성되었습니다.
즉, AWS Elastic Load Balancer는 더 이상 이 트래픽을 다른 애플리케이션으로 라우팅하는 데 필요한 유연성을 제공하지 못했습니다. 그래서 NGINX가 등장해 문제를 해결했습니다. 구체적으로, 여러 개의 업스트림을 두고 규칙을 다시 작성해 트래픽을 서로 다른 애플리케이션으로 라우팅할 수 있습니다.
이 매우 기본적인 예에서 우리는 API를 위한 6개 서버로 구성된 업스트림
블록과 홈페이지를 위한 2개 서버로 구성된 블록을 정의합니다.
또한 두 개의 서버
블록(가상 서버 정의)이 있습니다. 첫 번째에서는 api.bellycard.com을 수신하고 해당 트래픽을 모두 API 서버로 라우팅합니다. 반면에 저희는 www.bellycard.com 의 의견을 듣고 그에 따라 계획을 세웁니다.
이것은 매우 효과적이었습니다. 이를 통해 개발자들이 빠르게 움직일 수 있었습니다. 우리 프런트엔드 사람들은 한 프로젝트를 진행 중이었고 API에 의해 차단되지 않았습니다. 그래서 우리는 세 번째 서비스를 배포했습니다. Apple의 Passbook과 통합하기 위한 것 같습니다. 네 번째는 Facebook 기능을 모두 이전한 것입니다. 다섯 번째는 웹사이트에서 사용자 이벤트를 처리하는 것이었습니다.
그러다가 누군가가 Node.js로 작성하는 게 좋은 생각이라고 생각해서, 이제 우리는 두 가지 언어로 다섯 가지 서비스를 제공하게 됐습니다. 그들은 모두 많은 구성 관리 없이 독립적으로 배포되었으며, 많은 사람들이 처음 시작할 때 사용할 NGINX를 수동으로 편집했습니다.
우리는 이 과정을 확장할 더 나은 방법이 필요했고, 그래서 Chef를 통해 그 방법을 찾았습니다.
Chef는 구성 관리 제품군입니다. 이 플랫폼은 Ruby로 작성되었으며 실제 구성 관리도 Ruby로 작성할 수 있으므로 개발자에게는 매우 유용합니다. learnchef.com은 Chef에 대해 배우기에 좋은 사이트입니다. 제가 45분만에 설명하는 것보다 훨씬 더 많은 내용을 이 플랫폼에서 배울 수 있습니다.
하지만 모두가 같은 생각을 하도록 몇 가지 기본적인 사항만 살펴보겠습니다.
Chef의 첫 번째 구성 요소는 레시피 입니다. 셰프는 칼을 도구로, 요리법을 모두 요리책 에 적는 등 똑똑한 이름을 많이 사용합니다. 그렇게 하면 재미있고 이해하기 쉬우며 훌륭한 은유를 제공하지만, 동시에 구글에서 무엇이든 검색하기 어렵게 만듭니다.
제가 생각할 수 있는 가장 기본적인 요리법은 다음과 같습니다. 패키지 nginx를
설치하고 nginx
서비스를 시작하고 활성화합니다.
파일 리소스를 가질 수도 있습니다. 예를 들어, /usr/share/NGINX/html/index.html 파일에 Hello
World!
라는 내용을 쓰고 싶습니다.
이를 템플릿 시스템으로 구축할 수도 있습니다. 여기에는 Hello
와 Kevin
에 대한 몇 개의 변수 g
와 w가
있고, 이 변수를 ERB 형식(Ruby 템플릿 스크립트)의 템플릿 파일에 전달할 수 있습니다.
그래서 단순히 내용을 직접 쓰는 대신, 읽을 내용과 인사할 사람을 위한 템플릿을 쓸 수 있습니다.
마지막 주요 구성 요소는 요리법, 파일, 템플릿을 모아 놓은 요리책입니다. 또한, 더 복잡한 리소스인 리소스, 공급자, 라이브러리도 있습니다. https://supermarket.getchef.com 에는 NGINX, MySQL, Java, apt
및 yum
에 대한 요리책을 비롯해 ssh_known_hosts 파일을 관리하는 방법 등 다양한 오픈 소스 및 기타 요리책이 많이 있습니다. 구성 관리에서 하려는 일의 주요 구성 요소는 이미 요리책에서 찾을 수 있습니다.
Chef를 사용하여 매우 빠른 NGINX 예제를 살펴보겠습니다. 여기서 NGINX를 설치하고 몇 가지 변수를 변경하여 구성해 보겠습니다. Chef를 사용하여 애플리케이션이 실행되는 위치를 파악한 다음 NGINX를 구성하여 트래픽을 애플리케이션으로 라우팅합니다.
따라서 이 예제에서 우리가 가장 먼저 하는 일은 노드 속성을 설정하는 것입니다. 각 노드에 대해 JSON 문서를 추가하여 속성 값을 설정할 수 있습니다. 이러한 속성의 설정을 찾는 타사 NGINX 요리책을 사용하려고 합니다. 우리는 worker_connections를
특정 값으로 설정하고, worker_rlimit_nofile
지시어, NGINX에서 사용할 이벤트
유형, 심지어 client_max_body_size까지
설정합니다.
그런 다음 NGINX 요리책에서 두 가지 요리법을 소개하겠습니다. 첫 번째는 nginx::repo 로 , 운영 체제에 따라 apt
또는 yum
저장소를 설정합니다. 그런 다음 [ nginx 레시피]는 NGINX를 설치합니다. 소스에서 NGINX를 설치할 수도 있지만 패키지를 사용하는 것이 더 빠릅니다.
다음으로 Chef의 검색 기능을 활용해 보겠습니다. Chef를 실행할 때는 컴퓨터에서 에이전트로 실행할 수도 있고, 스크립트처럼 실행하는 솔로 모드로 실행할 수도 있습니다. 머신에 에이전트가 있으면 Chef 서버에 노드와 기타 속성을 쿼리할 수 있습니다.
여기서 우리는 Chef에게 recipe belly‑api가 첨부된 모든 노드 목록을 제공해 달라고 요청하고 있습니다. 그 후, /sites‑enabled/api 라는 사이트 파일의 템플릿을 만듭니다. 그 소스는 제가 다음에 보여드릴 템플릿[ api.erb 라는 파일]입니다. 우리가 전달한 변수는 바로 전에 검색했던 노드입니다.
여기서 마지막으로 새로운 것은 nginx 서비스를 다시 로드하라는 알림
명령문입니다. 이는 이 템플릿이 변경될 때마다 이 서비스를 다시 로드하라는 의미입니다.
그럼 여기 있는 템플릿 파일은 매우 간단하죠. api 라는 업스트림이 있고 ERB에서 변수로 전달되는 모든 서버를 반복하며, IP 주소와 포트 8080으로 서버를 지정합니다. 우리는 심지어 서버 이름을 주석으로 첨부했습니다. 서비스 운영자가 해당 서비스에서 무슨 일이 일어나고 있는지 궁금해할 때, 이는 좋은 댓글이 될 것입니다.
또한 api.bellycard.com 을 수신하는 서버
블록을 정의합니다. 저는 모든 트래픽을 API 업스트림으로 전달합니다.
또한 실제 사례를 제공하고 싶습니다. 여러분이 읽기에는 너무 작을 수도 있지만, 셰프의 요리법이 얼마나 복잡해질 수 있는지 느낄 수는 있습니다. 이는 오늘날 우리의 일부 프로덕션 서버에서 사용된 실제 템플릿과 레시피입니다.
이제 스택으로 돌아가 보겠습니다. 이전에 말씀드렸듯이 저희는 약 5개의 애플리케이션을 배포했고, 그 작업이 매우 순조롭게 진행되고 있습니다. 이제 우리는 그들에게 트래픽을 라우팅할 방법을 갖게 되었고, 우리 개발자들은 그것을 바로 사용했고 오늘날 우리는 Chef를 사용하여 우리 서버에 배포된 약 40개의 Ruby 애플리케이션을 보유하고 있습니다. 트래픽은 NGINX를 사용하여 완전히 동적으로 라우팅됩니다.
저희 개발자들은 새로운 서비스 이름을 포함하기 위해 한 가지 레시피를 편집하는 것 외에는 실제로 아무것도 할 필요가 없습니다. 모든 트래픽은 NGINX를 통해 라우팅되며 Chef를 사용하여 동적으로 구성됩니다.
또한 우리는 S3에 배포하는 정적 파일인 프런트엔드 JavaScript 애플리케이션을 약 10개 정도 가지고 있었는데, 이 애플리케이션은 CDN인 [Amazon] CloudFront를 앞에 두고 있었습니다. 우리는 S3 버킷에서 index.html을 제공했고 나머지 자산은 CloudFront를 통해 제공되었습니다. 또한 개발자들이 Heroku에 푸시한 앱이 5개 정도 더 있었는데, 이는 단 한 번만 제공했지만 결국 프로덕션으로 전환되었고 아무도 이에 대해 알지 못했기 때문입니다.
[Heroku의 5개 앱]은 4월의 어느 아름다운 날 Heartbleed 버그가 발표되기 전까지는 완전히 별개였습니다. 즉, 당사 인프라 외부에 있었습니다. 많은 사람들이 허겁지겁 달려들었다. Heartbleed는 사람들이 잠재적으로 사용자의 개인 키를 추출할 수 있는 OpenSSL의 버그였습니다.
Chef를 사용하면서 패치가 제공되자마자 모든 상자에서 OpenSSL 인프라를 업그레이드할 수 있었습니다. 저는 그것이 우리 인프라 전반에 걸쳐 약 20분 만에 배포되었다고 믿습니다. 하지만 AWS(그리고 Heroku)는 Elastic Load Balancer에 패치를 적용하는 데 약 24시간이 걸렸습니다.
이로 인해 우리는 배포 위치(S3와 Heroku 모두)에 관계없이 모든 로드 밸런싱 및 SSL 종료를 NGINX로 실제로 옮기게 되었습니다. 그렇게 하면 약간의 페널티를 받지만, 적어도 4월의 그날만큼은 우리에게 가치 있는 일이었습니다.
그래서 우리 스택의 버전 3은 "모든 것을 갖춘 SOA"에서 "모든 것을 갖춘 SSL"로 바뀌었습니다. bellycard.com 과 하위 도메인으로 유입되는 모든 트래픽은 로드 밸런서를 통과합니다. 실제로 우리의 자산은 성능을 위해 다른 도메인의 CloudFront에서 제공됩니다. 우리는 SSL의 오버헤드를 원하지 않습니다. 게다가 우리는 동부 해안에 단 하나의 데이터 센터를 두고 있습니다.
버전 4 – 올해 모두가 이야기하는 유행어는 바로 Docker입니다. Docker가 0.5 버전이었던 것 같아서 저희 개발자들은 그것을 사용하게 되어 기뻤습니다.
[Docker를 사용하는] 이유는 간단합니다.
이를 통해 애플리케이션 배포가 크게 간소화됩니다. 쓸 수 있는 요리법이 없습니다. 자산 편찬을 어떻게 할 것인지 걱정할 필요가 없습니다. 다른 사람이 Python으로 앱을 작성하고 있을 때 당신이 Ruby로 앱을 작성한다고 해도 문제가 없습니다.
기본적으로 개발과 운영의 책임을 분리합니다. 개발자는 코드, 사용할 라이브러리, 어떤 Linux 패키지를 설치할지 등에 대해 걱정할 수 있습니다. 운영팀은 '어디에 배포할까?'와 같은 더 많은 사항에 대해 걱정할 수 있습니다. 어떻게 로깅을 캡처할 수 있나요? 어떻게 모니터링하나요? 이러한 문제와 작업을 해결하고 나면 어떤 언어로 작성되었든 모든 응용 프로그램이 작동하게 됩니다.
이것의 장점은 개발자들이 자신의 노트북에서 종속 서비스를 쉽게 시작할 수 있다는 것입니다. 제가 언급했듯이 우리는 약 55개의 다양한 애플리케이션을 개발했으며, 이 중 다수가 이제 Docker 컨테이너에 들어 있습니다.
이메일 캠페인을 발송하는 새로운 서비스를 개발 중이라고 가정해 보겠습니다. 이는 이메일 서비스에 의존합니다. 따라서 개발용 컴퓨터에서 일반적으로 코드를 다운로드하고 bundle
install을
실행한 다음 백그라운드에서 시작합니다. "아, 하지만 실제로는 다른 서비스인 사용자 서비스에 의존하는군요"라고 생각하게 됩니다.
그 서비스는 또 다른 것, 또 다른 것에 의존합니다. 사실 새로운 이메일 캠페인 서비스는 MySQL, Elasticsearch, Redis 등 약 5개의 다른 서비스에 의존하고 있으며 목록은 계속 늘어갑니다.
Docker를 사용하면 실제로 프로덕션에서 사용하는 것과 동일한 Chef 레시피로 컨테이너를 빌드하고 개발자에게 매우 빠르게 다운로드할 수 있는 컨테이너를 제공할 수 있습니다.
이렇게 하면 배포 및 개발 속도가 빨라집니다.
그래서 버전 4에서는 Chef를 사용하여 애플리케이션을 배포하는 방식에서 컨테이너에 배포하는 방식으로 전환했습니다. 이를 위한 해결책은 수없이 많고 앞으로도 더 많이 나올 거라고 확신합니다.
첫 번째는 CoreOS와 Fleet입니다. CoreOS는 etcd 라고 불리는 서비스 검색 엔진을 실행하는 단순화된 Linux 운영 체제입니다. Fleet은 "컨테이너를 5번 실행하고 싶지만 다른 서비스와 동일한 머신에서 실행하고 싶지 않음"과 같은 사항을 정의하는 방법입니다.
Heroku와 비슷한 Deis라는 Git Push 인터페이스가 있는 또 다른 서비스가 있습니다. Apache의 Mesos와 Google의 Kubernetes가 있고 Flynn도 최근에 나온 것입니다. 사실 우리는 우리만의 도구를 썼습니다. 왜냐하면 우리가 이 항해를 시작했을 때 이 도구들 중 대부분이 우리가 사용할 수 있는 곳에 없었기 때문입니다.
저희는 Jockey라고 불리는데, 저희의 배치 프로세스가 매우 의견이 많기 때문에 이 방법이 정말 잘 맞았습니다. Docker의 장점은 기본적으로 컨테이너화를 위한 공통 API 세트를 제공한다는 것입니다. Linux의 LXC 컨테이너만 사용한다면 우리가 걱정해야 할 많은 것들이 없습니다.
저희는 이것을 오픈 소스로 공개할 계획이지만, 앞서 언급했듯이 배포는 정말 의견이 반영되기 때문에 저희에게 효과가 있었던 것이 여러분에게는 효과가 없을 수도 있습니다.
Docker로 전환하면서 배포 전략도 다소 바뀌었습니다. 이전에는 새로운 버전의 애플리케이션을 기존에 배포하는 방식으로 다운타임 없이 배포를 진행했습니다. 즉, 4대의 기기에 사용자 팩스 서비스가 있는 경우 Chef를 사용하여 새 버전을 다운로드하고 [이전 버전] 위에 설치한 다음 웹 서버에 신호를 보내 다시 로드합니다. 유니콘은 그런 일을 하는 데에 매우 적합한 루비 엔진입니다.
하지만 컨테이너는 변경할 수 없습니다. 실행 중인 컨테이너가 있으면 새 빌드를 만들려면 새 컨테이너를 만들어야 합니다. Git에서 하는 것과 비슷하게, 여기에 첨부하고, 추가 명령을 실행한 다음 저장할 수 있습니다. 하지만 Docker를 최대한 활용하려면 컨테이너가 완전히 변경 불가능해야 합니다.
즉, 더 이상 현장에 배치할 수 없게 되었기 때문에 새로운 배치 전략을 알아내야 했습니다. 몇 가지가 있습니다. 청록색은 흥미로운 색상이에요. 여기서 4대의 컴퓨터에서 실행되는 애플리케이션이 있다면 이를 4대의 새 컴퓨터에서 실행하고 로드 밸런서가 새 컴퓨터를 가리키도록 합니다. 실제로 예상대로 작동하는지 확인한 후 파란색을 뜯어내면 녹색이 파란색이 됩니다. Amazon은 AWS를 사용하여 이를 수행하는 데 필요한 매우 훌륭한 도구를 갖추고 있습니다.
또한 새 머신의 한 버전을 배포하고 모니터링하며 메트릭 검사와 상태 검사를 통과하면 배포를 계속할 수 있는 "카나리아" 배포도 있습니다.
여기서 컨테이너와의 차이점은 컨테이너를 실제로 해체하고 새로운 컨테이너를 생성해야 하므로 인프라에서 실행되는 각 애플리케이션의 위치를 추적할 수 있는 어떤 종류의 시스템이 필요하다는 것입니다.
셰프는 실제로 이런 일을 하는 아주 좋은 방법이 되기 시작했습니다. Chef Metal이라는 이름의 쿡북이 병합되었는데, 이를 사용하면 Chef 인프라에서 컨테이너를 다른 리소스와 마찬가지로 실제로 처리할 수 있습니다.
서비스 발견도 있습니다. ZooKeeper는 Hadoop 전체에서 사용되는 매우 인기 있는 도구입니다. [Airbnb]는 SmartStack 이라는 훌륭한 제품을 가지고 있는데, 이를 통해 ZooKeeper에서 배포를 수행하고 추적할 수 있습니다.
저는 REST 인터페이스를 갖춘 분산 키-값 저장소인 etcd 에 대해 언급했습니다. ZooKeeper와 비교하면 훨씬 좋습니다. ZooKeeper는 Java 클라이언트 라이브러리에 가깝습니다. 이제 어떤 애플리케이션에서든 etcd와 통신할 수 있습니다. 제가 이전에 언급한 오픈소스 Platform‑as‑a‑Service 중 상당수(예: Deis, Flynn, Google의 Kubernetes)는 etcd를 사용합니다. CoreOS를 사용하고 있다면 etcd가 이미 기본으로 제공됩니다.
REST 기반의 Consul 이라는 또 다른 제품이 출시되었습니다. Vagrant와 Packer를 만들고 다른 수많은 멋진 도구를 만드는 HashiCorp의 사람들이 출시했습니다. 실제로 우리는 Consul을 사용하기로 결정했습니다.
다음은 Consul의 기본을 보여주는 다이어그램입니다. 여러 개의 데이터 센터가 있고, 각각 3개의 서버가 있는 것을 볼 수 있습니다. 데이터 센터 1에는 클라이언트도 있습니다. 흥미로운 점은 서버 에이전트 중에서 기본 에이전트를 선출하면 모든 클라이언트가 모든 서버뿐만 아니라 다른 모든 클라이언트도 실제로 인식하게 된다는 것입니다. 그런 다음 그들은 가십 프로토콜을 사용하여 다른 모든 에이전트와 소통합니다.
이것은 두 친구에게 말하고, 그 친구가 두 친구에게 말하고, 그 친구가 두 친구에게 말하고, 그 메시지가 노드 네트워크 전체로 퍼지는 오래된 AT&T 광고를 떠올리게 합니다. [ 편집자 - 글쎄요, 끝입니다. Faberge Organics 샴푸 광고였습니다. ] 이것은 기본적으로 서버 에이전트만 있고 클라이언트가 이에 연결하는 etcd나 ZooKeeper와 비교됩니다.
Consul 방식으로 작업을 수행하면 Docker를 배포하는 모든 곳, 로드 밸런서를 실행하는 모든 곳에서 사실상 모든 서버에서 Consul 클라이언트를 실행하게 됩니다. 따라서 항상 로컬호스트 포트 8500에서 해당 API와 통신할 수 있습니다.
etcd와 마찬가지로 [Consul]은 분산 키‑값 저장소입니다. 키를 설정하고 가져올 수 있으며 선형성을 유지하므로 항상 일관성을 유지할 수 있습니다. 몇 가지 문제점이 있지만, 그러한 문제가 어디에 있는지에 대한 설명이 놀라울 정도로 자세합니다. 그러나 etcd와 달리 서비스 검색을 일급 시민으로 취급합니다.
키-값 쌍 대신 API와 같은 서비스를 등록할 수도 있습니다. 서비스를 등록할 때 Consul에 실행 중인 노드를 알려줍니다. 즉, 컨테이너를 배포할 때 Consul에게 해당 호스트에도 이 서비스 API를 등록하라고 알려줘야 합니다.
그에 더해 Consul은 분산된 상태 검사를 제공하므로 이제 서비스 검색 플랫폼 내에서 바로 Nagios 스타일의 상태 검사를 정의할 수 있습니다. Consul에 쿼리를 보내면 API 서비스가 실행 중인 모든 위치 목록을 요청할 수 있습니다. "모두" 또는 "통과만" 또는 "건강에 해로움"에 대한 플래그를 보낼 수 있습니다.
또한 여러 데이터 센터를 지원합니다. 어디에서나 Consul 클라이언트를 실행해야 한다고 말씀드렸죠. 시작할 때 데이터 센터를 지정하는 매개변수를 전달합니다. 동부 데이터 센터와 서부 데이터 센터가 있는 경우 데이터 센터를 알고 있거나 주소를 묻거나 할 필요 없이 로컬 Consul 클라이언트에게 쿼리를 보낼 수 있습니다.
실제로 우리는 데이터 센터를 스테이징 및 프로덕션 환경의 경계로 사용합니다. 스테이징 중인 애플리케이션에 대한 구성은 " MySQL.services.consul 이 어디에 있는지 물어보세요"라고 말할 수 있습니다. 실제로 스테이징 노드에서 실행하든 프로덕션 노드에서 실행하든, 데이터 센터를 인식하거나 다중 환경을 인식하지 않고도 올바른 값을 얻을 수 있습니다.
이것(그리고 etcd)의 또 다른 장점은 HTTP 인터페이스에 롱 폴링 기능이 있다는 것입니다. 즉, 이 서비스를 실행 중인 모든 서버 목록을 쿼리하여 요청할 수 있고, 60초 동안 연결을 열어두고 무엇이든 변경되면 즉시 알림을 받을 수 있습니다. 투표시간은 실제로 최대 10분까지 걸릴 수 있습니다. 즉, 인프라의 모든 변경 사항에 대해 즉시 알림을 받을 수 있습니다.
제가 이미 언급한 또 다른 점은 모든 곳에 클라이언트를 배치함으로써 에이전트를 확장할 수 있는 능력을 구축할 수 있다는 것입니다. 이 기능은 항상 로컬호스트와 통신할 수 있어서 좋습니다.
하지만 가장 큰 의문은 이렇습니다. 이제 분산 서비스 검색 플랫폼에 데이터가 저장되었는데, 이 데이터에서 NGINX를 어떻게 구성해야 할까요?
다행히 Consul Template 이라는 도구가 있습니다. 어제 공개된 것이라서 오늘부터 슬라이드를 바꾸게 됐어요. 이전에는 "Consul HAProxy"라고 불렸는데, 실제로 HAProxy에만 국한되지 않았기 때문에 끔찍한 이름이었습니다.
Consul Template은 서비스 변경 사항, 해당 서비스의 상태 점검, 심지어 키-값 저장소를 구독하기 위한 템플릿을 구축할 수 있는 매우 간단한 인터페이스를 제공합니다. 이렇게 하면 키-값 저장소 내부의 NGINX 작업자 수와 같은 설정을 저장하고 해당 설정이 변경될 때 구성을 다시 생성할 수 있습니다.
여기서 가장 큰 기능은 템플릿에서 파일을 생성하는 것입니다. 이는 이전에 Chef에서 하던 일과 매우 비슷하게 들립니다. 더 큰 차이점은 ERB인 Ruby와 달리 Golang 템플릿 언어를 사용한다는 것입니다. 파일을 변경한 후에는 선택적으로 변경 사항에 대한 명령을 호출할 수 있습니다(예: service
nginx
reload
) .
다음은 명령줄에서 Consul Template을 실행하는 예입니다. 실제 Consul 호스트, 즉 이 경우에는 consul‑prod.example.com 을 가리키도록 합니다. 실제 운영 환경에서는 Consul을 어디서나 실행하고 로컬호스트에 연결하는 것이 좋습니다.
그런 다음 Golang 템플릿인 템플릿 파일을 전달합니다. 우리의 경우에는 /etc/consul‑templates/api 를 전달합니다. 그런 다음 실제로 쓸 파일을 전달합니다. 우리의 경우 /etc/NGINX/sites‑enabled/api 입니다 . 그런 다음 호출할 명령: service
nginx
reload
.
Consul 템플릿은 이전에 사용하던 슬라이드와 매우 유사합니다. 다만 ERB 대신 Golang으로 작성되었습니다. 그러므로 여기서 우리는 두 개의 상류를 정의합니다. 하나는 api 라고 하고, 다른 하나는 홈페이지 라고 합니다. 서비스 API에 대한 범위
문이 있으며, 해당 서비스가 실제로 실행되는 IP 및 포트를 가져오기 위한 내장 변수가 있습니다.
Consul Template의 장점과 이런 방식으로 사용하는 장점은 서비스 변경에 대한 융합이 빠르다는 것입니다. Docker로 배포하기 전에는 머신에 따라 약 5~10분 간격으로 Chef를 실행했습니다. 우리는 현장에 배치된 상태였기 때문에 그 정도는 충분히 빨랐습니다.
이제 우리는 보다 진보된 배포 시스템을 구축하고 있으므로 몇 분이 아닌 몇 초 안에 변경 사항에 대한 알림을 받아야 합니다. 실제로 우리는 밀리초 단위로, 평균적으로 약 200밀리초 정도로 얻습니다.
그러나 템플릿을 생성하려면 여전히 구성 관리가 필요합니다. Chef를 Consul로 바꿀 수는 없습니다. 우리는 아직 Consul과 Consul Template 등을 어떻게 배포할 것인지 알아내야 합니다.
사실 우리는 Chef 템플릿을 사용하여 Consul 템플릿을 배포하고 있는데, 약간 복잡해 보입니다. Chef 레시피에서 가장 먼저 하는 일은 Consul 호스트에게 모든 서비스 목록을 요청하는 것입니다. 그런 다음 Consul 템플릿을 생성합니다. 주형
그리고 원천
[문장]을 입력하고 SSL 인증서와 키 위치를 전달하고 다시 로드합니다. 영사 템플릿
. [편집자– Reedy 씨는 처음에 다음과 같이 언급했습니다. 영사 대리인
, 첫 번째에 나타납니다 통지하다
슬라이드에 대한 설명입니다. 그런 다음 그는 자신의 말을 바로잡고 해당 슬라이드가 Consul Template이 출시되기 이전에 나온 것이라고 명확히 밝혔습니다. ]
또한 Consul 템플릿에 대한 구성 파일을 작성하고 Consul 호스트, 소스, 대상 및 다시 로드 명령을 지정하는 [변수]를 전달합니다. 이는 Chef와 Consul을 함께 사용하여 NGINX 구성에 대한 즉각적인 업데이트를 얻는 방법의 핵심입니다.
다음으로 Chef, Consul, NGINX 구성에 대한 일반적인 전문가 팁을 알려드리겠습니다.
첫 번째 팁은 Chef 검색을 사용하여 서비스가 실행되는 위치를 찾는 경우 Chef 부분 검색을 살펴봐야 한다는 것입니다. Chef 검색의 문제점은 모든 속성을 포함하여 전체 노드의 복사본을 만든다는 것입니다. 노드의 속성에 많은 것을 저장하면 Chef 서버와 통신하는 동안 와이어를 통해 해당 항목을 가져와야 하며 메모리에도 저장해야 합니다.
Chef 검색에서 수백 또는 수천 개의 서버가 반환되면 실제 레시피에 대한 메모리가 어떻게 부족해질 수 있는지 쉽게 알 수 있습니다. 부분 검색을 사용하면 관심 있는 키만 반환됩니다.
예를 들어, 우리는 처음에
노드 = 검색(:노드, '레시피:벨리-api')
해당 검색은 모든 객체에 대한 모든 정보를 반환합니다. 여기에는 디스크 공간, RAM, CPU 및 자체 노드 속성을 작성한 모든 애플리케이션에 대한 정보가 포함됩니다.
대신, 우리는 search_keys
라는 새로운 해시를 만들고 우리가 관심 있는 키 목록(이 경우에는 이름과 IP 주소만)을 제공하는 부분 검색을 사용할 수 있습니다. 그런 다음 partial_search
라는 매우 유사한 API를 사용하고 추가 [ keys
] 매개변수를 전달합니다.
S3와 Heroku 앞에서 로드 밸런싱을 시작했을 때 우리를 괴롭힌 두 번째 문제는 NGINX가 구성을 다시 로드할 때만 업스트림
블록의 호스트 이름을 확인하기 위해 DNS를 사용한다는 것입니다. 즉, 업스트림 서버를 s3.amazonaws.com 또는 anything.herokuapp.com 으로 설정하고 이를 변경하면 로드 밸런서는 다음에 다시 로드할 때까지 새 IP 주소를 알 수 없습니다.
우리가 이 문제를 해결한 방법은 Chef에서 실제로 DNS 확인을 수행한 다음 해당 변경 사항이 발생하면 NGINX를 다시 로드하는 것입니다. 이로 인해 두 번째 문제가 발생했습니다. [DNS 응답의 주소 순서]는 항상 동일하지 않으므로 템플릿에 작성하기 전에 응답을 정렬해야 합니다.
수많은 서비스를 배포하기 시작할 때 발생하는 또 다른 문제는 오래된 구성을 피하고 싶다는 것입니다. [ 편집자 - Reedy 씨가 청중의 질문에 답하기 위해 프레젠테이션을 잠시 멈춥니다. ] Apache, NGINX 및 기타 UNIX에서 일반적인 구성 패턴은 conf.d 폴더를 만들고 거기에서 모든 것을 로드하는 것입니다. 따라서 서비스 A, B, C를 배포하는 경우 service-a.conf , service-b.conf , service-c.conf를 만듭니다.
그런 다음 서비스 B를 D로 바꾸기로 결정했고 이제 NGINX 구성 폴더에 4개의 구성이 있지만 서비스 B는 더 이상 존재하지 않습니다. B와 D는 비슷한 호스트 이름을 가지고 있기 때문에 충돌이 발생할 수 있습니다.
과거에 우리는 [오래된 구성을 제거하는] 두 가지 방법을 목표로 삼았습니다. 템플릿을 사용하면 :delete
함수를 추가할 수 있지만, 이렇게 하면 금세 다루기 힘들어집니다. 우리는 기본적으로 오래된 서비스 목록을 갖고 있었고, 그런 서비스가 존재한다면 항상 삭제하려고 노력했습니다. 실제로 확장성은 없었습니다.
또 다른 방법은 모든 사이트 구성을 하나의 파일로 렌더링하는 것입니다. 많은 사람들이 이것을 "멱등성을 위로 옮기자"라고 말했습니다. 기본적으로 여러 소스에서 로드하는 NGINX 구성을 갖는 대신, 모든 것을 nginx.conf 에 넣습니다.
실제로 상자에 로그인할 때는 약간 다루기 힘들지만, 운영 환경에서 설정 파일의 문제를 실시간으로 해결하지 않아도 되는 수준까지는 왔으면 좋겠습니다. Chef 레시피에서 여전히 다루기 어려운 경우, 여러 사이트를 로드하는 하나의 nginx.conf를 사용합니다. 예를 들어, 우리 사이트 구성 파일 중 하나에는 약 30개의 서비스가 나열되어 있고, 그 다음에는 Heroku 서비스 하나, S3 서비스 하나 등이 나열되어 있습니다.
따라서 모든 사이트 구성을 하나 또는 적은 양의 파일로 렌더링하는 경우 나중에 정리하는 데 대해 걱정할 필요가 없습니다. Chef의 관점에서 서비스가 사라지면 Chef는 실제 파일에 대한 렌더링을 중단합니다.
큐: 지금까지 Consul을 어떻게 사용하셨나요?
에이: 저희는 Consul을 정말 좋아했습니다. 제가 etcd와 같은 것에 비해 Consul에 대해 정말 좋아하는 점은 Consul을 기반으로 계속해서 구축되는 서비스가 있다는 것입니다. 서비스 발견에 대해 걱정할 필요가 없습니다. 사실, 레거시 애플리케이션이 있고 Consul을 사용하여 MySQL 서버를 배포하는 경우(예를 들어) Consul은 DNS 인터페이스도 제공합니다.
귀하의 애플리케이션은 Consul을 인식할 필요가 없습니다. 단지 " mysqldb.services.consul 에서 어떤 주소를 얻을 수 있습니까?"라는 질문만 쿼리하면 됩니다. 이 경우 Consul은 DNS 서버입니다. TLD[최상위 도메인]가 .consul
로 끝나는 경우 쿼리가 Consul로 라우팅되도록 DNS 인프라를 설정합니다.
우리에게는 확장성이 매우 좋았습니다. 우리는 서버 에이전트를 위한 프로덕션 노드 3개와 클라이언트 60개 정도를 부족하게 사용하고 있습니다. 우리는 아무런 문제에 부딪히지 않았습니다. 그들은 기능을 계속 추가하고 이전 버전과의 호환성을 손상시키지 않으므로 업그레이드는 항상 좋았습니다.
큐: NGINX Plus를 사용하시나요?
에이: 우리는 그렇지 않습니다. 우리는 Consul과 협력을 시작했을 때, 바로 이 문제에 대해 조사했습니다. 템플릿 시스템이 필요하지 않다면 좋을 텐데요. HTTP 롱 폴링을 수신하고 사용자를 대신해 NGINX API와 통신하는 스크립트만 있으면 되니까요. 여기서 유일한 문제는 NGINX가 다시 시작되는 경우를 대비해 템플릿 시스템도 필요하다는 것입니다. 그러면 업스트림 구성이 바로 다시 로드됩니다.
NGINX Lua에서 Consul에 직접 쿼리를 보내기 위해 다른 사람들이 수행한 작업도 있습니다. 아직 좋은 구현을 보지 못했는데, 두 가지 유형 중 하나에 속하는 경향이 있거든요. 첫 번째는 모든 HTTP 요청에 대해 Consul에 쿼리를 보내므로 속도가 느리다는 것입니다. 두 번째는 구성 런타임에 이를 로드하기 때문에 DNS에서 발생한 것과 동일한 문제가 발생한다는 것입니다. 그래서 지금은 템플릿을 사용하는 것이 가장 좋지만 앞으로 NGINX Lua로 이를 구현할 수 있는 방법이 나오더라도 놀랍지 않을 것 같습니다.
큐: 당신은 셰프에게서 멀어지고 싶은가요?
에이: Consul에는 해당 템플릿을 유지 관리할 수 있는 좋은 방법이 내장되어 있지 않으며, 우리는 이미 Chef와 함께 NGINX를 배포하고 있습니다. NGINX에서 로깅, 추적, 일부 OAuth를 포함하여 수행하는 다른 모든 작업에 대한 레시피는 현재 수백 줄, 아니 수천 줄에 달합니다. 저는 우리 인프라에서 Chef를 없애고 대체할 것이라고 생각하지 않지만, 그것은 훌륭한 증강이며 신속한 알림을 받는 좋은 방법입니다.
큐: Chef는 얼마나 많은 운영비를 제공합니까?
에이: 대부분의 기계가 단일 작업만 처리하기 때문에 실제로 셰프의 운영비는 매우 낮습니다. 유휴 상태일 때는 RAM 사용량이 낮습니다. 실제로 타이머에 앉아서 분기할 수 있습니다. 다른 사람들은 수렴 속도가 중요하지 않다면 cron
에서 실행합니다. 일부 무거운 레시피에서 CPU에 약간의 충돌이 발생했지만, 다른 서버를 배치해서 수정할 수 없는 문제는 아닙니다.
큐: CloudFormation을 얼마나 활용하셨나요?
에이: 아직 CloudFormation을 사용하고 있지 않습니다. 이는 우리의 관심사이지만, 우리가 변경한 사항 중 하나는 자동 크기 조정 그룹을 훨씬 더 많이 활용하는 것입니다. 이 작업의 작동 방식은 인스턴스가 시작될 때 Chef 실행 목록이 포함된 사용자 데이터가 있다는 것입니다.
새로운 머신은 이미 이미지에 기반한 키를 가진 클러스터에 포함되어 Chef 서버와 통신하고, 자체 등록을 하고, 필요한 요리책을 가져올 수 있습니다. 그렇게 하면 CloudFormation 관련 문제 대부분을 해결할 수 있습니다. 다른 AWS 도구를 많이 사용하지 않기 때문입니다.
큐: 서버가 파괴되면 어떻게 처리하나요?
에이: Auto Scaling 그룹에서 서버가 사라지면 Amazon SNS[Simple Notification Service]를 사용하여 해당 알림을 받을 수 있습니다. 우리는 이런 알림을 수신하고 Chef 서버를 정리하는 매우 간단한 서비스를 가지고 있습니다.
큐: AWS의 OpsWorks를 사용해 보셨나요?
에이: 우리는 그렇지 않았어요. 저희는 처음부터 호스팅 셰프를 사용해 왔고 정말 효과적이었습니다. 저는 이것에 대해 확신할 수 없지만 OpsWorks는 Chef Solo와 더 비슷하다고 생각합니다. 즉, 프로비저닝에만 사용된다는 뜻입니다. 우리는 여전히 거의 모든 머신에서 Chef Agent를 실행하고 있으며, 동일한 Chef 레시피를 사용하여 개발용 Docker 컨테이너를 생성합니다.
"이 블로그 게시물에는 더 이상 사용할 수 없거나 더 이상 지원되지 않는 제품이 참조될 수 있습니다. 사용 가능한 F5 NGINX 제품과 솔루션에 대한 최신 정보를 보려면 NGINX 제품군을 살펴보세요. NGINX는 이제 F5의 일부가 되었습니다. 이전의 모든 NGINX.com 링크는 F5.com의 유사한 NGINX 콘텐츠로 리디렉션됩니다."