NGINX Unit : 100% Uptime으로 애플리케이션 업데이트
이 포스트는 서비스 중단이나 Downtime 없이 NGINX Unit 환경에서 애플리케이션을 업데이트할 때 각 단계에서 발생하는 상황을 이해하는 데 필요한 모든 배경과 세부 정보를 제공합니다.
목차
1. NGINX Unit 리뷰
2. 다중언어 애플리케이션 구성
3. NGINX Unit 애플리케이션 업데이트
3-1. 1단계: 새 애플리케이션 및 임시 Listener 만들기
3-2. 2단계: Production Listener 객체를 새 애플리케이션에 재할당
3-3. 3단계: 사용하지 않는 구성 객체 삭제
4. NGINX Unit 결론
1. NGINX Unit 리뷰
NGINX Unit은 애플리케이션 Downtime이나 인프라 중단 없이 애플리케이션의 구성 요소를 동적으로 업그레이드할 수 있는 API를 통해 여러 언어와 애플리케이션을 한 번에 처리하는 애플리케이션 서버입니다.
NGINX Unit API는 여러 객체로 구성됩니다. 여기에서는 다음 세 가지 작업을 수행합니다.
- 구성 객체는 현재 구성을 저장합니다.
- 애플리케이션 객체는 애플리케이션을 모든 애플리케이션 언어에 적용되는 일부 일반 매개 변수와 특정 언어 매개 변수의 모음으로 설명합니다.
- Listener 객체는 NGINX Unit이 지정된 애플리케이션에 대한 클라이언트 요청을 수신하는 IP 주소와 포트를 정의합니다.
NGINX Unit API에서 GET, PUT 및 DELETE 메서드를 사용하여 객체를 구성합니다. API는 HTTP 기반이고 JSON 형식의 객체를 나타내므로 원하는 RESTful 도구를 사용하여 제어할 수 있습니다. 동영상과 이 포스트에서는 curl 명령을 사용하고 –unix-socket 옵션으로 지정된 Unix 도메인 소켓에서 일반적인 방식으로 API에 액세스합니다.
Request Routing, Authentication, Rate Limiting 및 Static File Delivery과 같은 기능을 위해 NGINX Unit 앞에 NGINX를 사용하는 것이 좋습니다.
2. 다중언어 애플리케이션 구성
비디오에서는 Ruby, PHP, Perl, Go 및 Python2의 각 언어로 작성된 애플리케이션으로 시작합니다. 두 개 이상의 언어를 갖는 것은 현대 애플리케이션의 전형적인 예입니다.
우리는 해당 언어로 작성된 애플리케이션 객체에 필요한 매개변수를 지정하기 위해 각 애플리케이션에 대해 하나씩 다음 .json 파일을 생성하여 NGINX Unit에서 애플리케이션을 이미 구성했습니다.
- go-app.json
- perl-app.json
- php-app.json
- python2-app.json
- ruby-app.json
파일 생성은 선택 사항으로, JSON 페이로드를 동적으로 생성하거나 curl 명령에 JSON 형식 구성을 입력할 수 있지만 대량의 사전 설정된 데이터를 쉽게 시작할 수도 있으며, 마찬가지로 모든 애플리케이션에 대한 구성을 단일 파일에 저장할 수 있지만, 각 애플리케이션에 대해 별도의 파일을 사용하면 각 DevOps팀이 자체 구성을 쉽게 관리할 수 있으며, 한 번으로 단일 애플리케이션을 쉽게 변경할 수 있습니다.
각 애플리케이션에 대해 다음 형식의 API 호출을 사용하여 파일 내용을 NGINX Unit 구성 객체에 추가합니다. 이 예제는 ruby-app.json에 대한 것입니다. 각 애플리케이션에 대해 명령을 반복할 때 해당 구성 파일의 경로를 바꿉니다.
$ curl -X PUT --data-binary @/var/www/unit-ruby/ruby-app/ruby-app.json --unix-socket /run/control.unit.sock http://localhost/config/applications/ruby-app
또한 각 애플리케이션에 대한 Listener를 추가합니다.
$ curl -X PUT --data-binary '{"application":"ruby-app"}' --unix-socket /run/control.unit.sock 'http://localhost/config/listeners/*:8100'
선택 사항인 access log를 설정합니다.
$ curl -X PUT --data-binary '"/var/log/access.log"' --unix-socket /run/control.unit.sock http://localhost/config/access_log
언제든지 http://nginx-unit-host/config/로 시작하는 URL 경로에서 GET 메서드를 호출하여 NGINX Unit의 현재 구성 객체의 전체 또는 일부를 표시할 수 있습니다. 특히 활성 수정 및 업데이트 중에 구성을 자주 확인하는 것이 좋습니다. 다음은 각 애플리케이션에 대한 구성 파일을 로드하고 Listener를 정의하고 로그 파일을 초기화하기 위해 이전 명령을 실행한 후의 출력을 보여주는 예입니다.
$ curl --unix-socket /run/control.unit.sock http://localhost/config/
{
"listeners": {
"*:8100": {
"application": "ruby-app"
},
"*:8200": {
"application": "php-app"
},
"*:8300": {
"application": "perl-app"
},
"*:8400": {
"application": "go-app"
},
"*:8500": {
"application": "python2-app"
}
},
"applications": {
"ruby-app": {
"type": "ruby",
"user": "nobody",
"processes": 2,
"script": "/var/www/unit-ruby/ruby-app.ru"
},
"php-app": {
"type": "php",
"user": "nobody",
"processes": 2,
"root": "/var/www/unit-php/phpinfo-app",
"index": "index.php"
},
"perl-app": {
"type": "perl",
"user": "nobody",
"processes": 1,
"working_directory": "/var/www/unit-perl/perl-app",
"script": "/var/www/unit-perl/index.pl"
}
"go-app": {
"type": "go",
"user": "nobody",
"executable": "/var/www/go-app"
},
"python2-app": {
"type": "python 2.7",
"user": "nobody",
"processes": 2,
"path": "/var/www/unit-python2.7/python-app",
"module": "wsgi"
},
},
"access_log": "/var/log/access.log"
}
3. NGINX Unit 애플리케이션 업데이트
Python2에서 Python3으로 업그레이드된 Python 애플리케이션의 새 버전을 개발자로부터 받으려면 어떻게 해야 합니까? Production 환경을 중단하지 않고 스택에 추가해야 합니다.
100% Uptime 필요한 운영 환경에서 애플리케이션 업데이트는 다음과 같은 세 단계 프로세스로 이루어집니다.
- 새 애플리케이션 및 임시 Listener 만들기
- Production Listener 객체를 새 애플리케이션에 재할당
- 사용하지 않는 구성 객체 삭제
3-1. 1단계: 새 애플리케이션 및 임시 Listener 만들기
python3-app.json이라는 Python3 애플리케이션에 대한 구성의 .json 파일을 생성하여 이전과 같이 시작합니다.
파일의 데이터를 NGINX Unit 구성으로 업로드합니다.
$ curl -X PUT --data-binary @/var/www/unit-python3/python3-app/python3-app.json --unix-socket /run/control.unit.sock http://localhost/config/applications/python3-app
임시 Listener를 추가하여 액세스합니다.
$ curl -X PUT --data-binary '{"application":"python3-app"}' --unix-socket /run/control.unit.sock 'http://localhost/config/listeners/*:8800'
이제 python3-app이 활성화되어 테스트를 위해 임시 포트 8800에서 수신 대기합니다.
3-2. 2단계 Listener 재할당
새 애플리케이션이 제대로 실행되고 있는지 확인하기 위해 약간의 트래픽을 새 애플리케이션에 전송한 후 Production Listener 포트 8500을 여기에 재할당합니다.
$ curl -X PUT --data-binary '"python3-app"' --unix-socket /run/control.unit.sock 'http://localhost/config/listeners/*:8500/application'
3-3. 3단계: 사용하지 않는 객체 삭제
이제 포트 8800에서 실행 중인 것이 없으므로 임시 Listener를 삭제할 수 있습니다.
$ curl -X DELETE --unix-socket /run/control.unit.sock 'http://localhost/config/listeners/*:8800'
새 python3-app 애플리케이션 버전으로 시스템이 올바르게 실행되고 있음을 확인한 후 이전 python2-app를 제거합니다.
$ curl -X DELETE --unix-socket /run/control.unit.sock http://localhost/config/applications/python2-app
다음 명령을 실행하여 NGINX Unit의 구성을 보여줍니다. 출력은 python3-app이 python2-app를 대체했음을 보여줍니다.
$ curl --unix-socket /run/control.unit.sock http://localhost/config/
{
"listeners": {
"*:8100": {
"application": "ruby-app"
},
"*:8200": {
"application": "php-app"
},
"*:8300": {
"application": "perl-app"
},
"*:8400": {
"application": "go-app"
},
"*:8500": {
"application": "python3-app"
}
},
"applications": {
"ruby-app": {
"type": "ruby",
"user": "nobody",
"processes": 2,
"script": "/var/www/unit-ruby/ruby-app.ru"
},
"php-app": {
"type": "php",
"user": "nobody",
"processes": 2,
"root": "/var/www/unit-php/phpinfo-app",
"index": "index.php"
},
"perl-app": {
"type": "perl",
"user": "nobody",
"processes": 1,
"working_directory": "/var/www/unit-perl/perl-app",
"script": "/var/www/unit-perl/index.pl"
}
"go-app": {
"type": "go",
"user": "nobody",
"executable": "/var/www/go-app"
},
"python3-app": {
"type": "python 3.5",
"user": "nobody",
"processes": 2,
"path": "/var/www/unit-python3.5/python3-app",
"module": "wsgi"
},
"access_log": "/var/log/access.log"
}
4. NGINX Unit 결론
NGINX Unit 을 사용하면 추가 인프라 오버헤드 없이 애플리케이션에 Downtime 없이 무중단 롤링(Rolling) 업데이트를 달성할 수 있습니다.
NGINX Unit의 최신 소식을 빠르게 전달 받고 싶으시면 아래 뉴스레터를 구독하세요.