예제 4: 레시피에 흐름 제어 추가 - AWS OpsWorks

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

예제 4: 레시피에 흐름 제어 추가

중요

이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두 사용할 수 없게 되었습니다. 고객은 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션할 것을 강력히 권장합니다. 마이그레이션에 대해 궁금한 점이 있으면 AWS re:Post 또는 Premium AWS Support를 통해 AWS Support 팀에 문의하세요.

일부 레시피는 일련의 Chef 리소스에 불과합니다. 이 경우, 레시피를 실행하면 레시피는 단순히 각각의 리소스 공급자를 순차적으로 실행합니다. 하지만 보다 복잡한 실행 경로가 있으면 유용한 경우가 많습니다. 다음은 두 가지 일반적인 시나리오입니다.

  • 레시피가 같은 리소스를 서로 다른 속성 설정으로 여러 번 실행하도록 하려는 경우.

  • 운영 체제에 따라 서로 다른 속성 설정을 사용하려는 경우.

이러한 시나리오는 Ruby 제어 구조를 레시피에 통합하여 해결할 수 있습니다. 이 섹션에서는 예제 3: 디렉터리 생성의 레시피를 수정하여 두 가지 시나리오를 모두 해결하는 방법을 살펴봅니다.

반복

예제 3: 디렉터리 생성에서는 directory 리소스를 사용하여 디렉터리 또는 디렉터리 체인을 생성하는 방법을 살펴봤습니다. 하지만 /srv/www/config/srv/www/shared라는 2개의 별도의 디렉터리를 생성하려 한다고 가정해 봅시다. 각 디렉터리마다 별도의 디렉터리 리소스를 구성할 수도 있지만 아주 많은 디렉터리를 생성하려는 경우, 이 방법은 번거로울 수 있습니다. 다음 레시피는 이 작업을 처리하는 보다 간단한 방법을 보여 줍니다.

[ "/srv/www/config", "/srv/www/shared" ].each do |path| directory path do mode 0755 owner 'root' group 'root' recursive true action :create end end

이 레시피는 각 하위 디렉터리에 별도의 디렉터리 리소스를 사용하는 대신 하위 디렉터리 경로가 포함된 문자열 모음을 사용합니다. Ruby each 메서드는 첫 번째 모음 요소부터 시작하여 각 모음 요소에 한 번씩 리소스를 실행합니다. 요소의 값은 리소스에서 path 변수에 의해 표시되며, 이 경우에는 디렉터리 경로를 나타냅니다. 이 예제를 쉽게 조정하여 얼마든지 많은 하위 디렉터리를 생성할 수 있습니다.

레시피를 실행하려면
  1. createdir 디렉터리를 그대로 열어 두고, 다음 여러 예제에 이 쿡북을 사용합니다.

  2. 아직 실행하지 않은 경우 kitchen destroy를 실행합니다. 그러면 깨끗한 인스턴스로 시작할 수 있습니다.

  3. default.rb의 코드를 이 예제로 바꾸고 kitchen converge를 실행합니다.

  4. 인스턴스에 로그인합니다. 그러면 /srv에 새로 생성된 디렉터리가 있습니다.

해시 테이블을 사용하여 각 반복에 2개의 값을 지정할 수 있습니다. 다음 레시피는 각각 다른 모드로 /srv/www/config/srv/www/shared를 생성합니다.

{ "/srv/www/config" => 0644, "/srv/www/shared" => 0755 }.each do |path, mode_value| directory path do mode mode_value owner 'root' group 'root' recursive true action :create end end
레시피를 실행하려면
  1. 아직 실행하지 않은 경우 kitchen destroy를 실행합니다. 그러면 깨끗한 인스턴스로 시작할 수 있습니다.

  2. default.rb의 코드를 이 예제로 바꾸고 kitchen converge를 실행합니다.

  3. 인스턴스에 로그인합니다. 그러면 /srv에 지정된 모드로 새로 생성된 디렉터리가 있습니다.

참고

AWS OpsWorks 스택 레시피는 일반적으로 이 접근 방식을 사용하여 스택 구성 및 배포 JSON (기본적으로 큰 해시 테이블) 에서 값을 추출하여 리소스에 삽입합니다. 예시는 Deploy 레시피단원을 참조하세요.

조건부 논리

Ruby 조건부 논리를 사용하여 여러 실행 분기를 생성할 수도 있습니다. 다음 레시피는 if-elsif-else 로직을 사용하여 이전 예제를 확장하므로 /srv/www/shared라는 이름의 하위 디렉터리를 생성하지만 Debian 및 Ubuntu 시스템에서만 가능합니다. 다른 모든 시스템의 경우, Test Kitchen 출력에 표시되는 오류 메시지를 로깅합니다.

if platform?("debian", "ubuntu") directory "/srv/www/shared" do mode 0755 owner 'root' group 'root' recursive true action :create end else log "Unsupported system" end
예제 레시피를 실행하려면
  1. 인스턴스가 여전히 실행 중인 경우 kitchen destroy를 실행하여 종료합니다.

  2. default.rb의 코드를 이 예제 코드로 바꿉니다.

  3. .kitchen.yml을 편집하여 CentOS 6.4 시스템을 플랫폼 목록에 추가합니다. 파일의 platforms 섹션은 다음과 같아야 합니다.

    ... platforms: - name: ubuntu-12.04 - name: centos-6.4 ...
  4. kitchen converge를 실행합니다. 이 코드는 인스턴스를 생성하고 각 플랫폼에 대해 .kitchen.yml의 레시피를 순서대로 실행합니다.

    참고

    인스턴스를 하나만 수렴하려는 경우 인스턴스 이름을 파라미터로 추가합니다. 예를 들어, Ubuntu 플랫폼에서만 레시피를 수렴하려면 kitchen converge default-ubuntu-1204를 실행합니다. 플랫폼 이름을 모르는 경우에는 kitchen list를 실행하면 됩니다.

Test Kitchen 출력의 CentOS 부분에 다음과 같은 로그 메시지가 표시되어야 합니다.

... Converging 1 resources Recipe: createdir::default * log[Unsupported system] action write[2014-06-23T19:10:30+00:00] INFO: Processing log[Unsupported system] action write (createdir::default line 12) [2014-06-23T19:10:30+00:00] INFO: Unsupported system [2014-06-23T19:10:30+00:00] INFO: Chef Run complete in 0.004972162 seconds

이제 인스턴스에 로그인하여 디렉터리가 생성되었는지 여부를 확인할 수 있습니다. 다만 지금은 kitchen login을 실행할 수 없습니다. 플랫폼 이름(예: kitchen login default-ubuntu-1204)을 추가하여 어떤 인스턴스인지 지정해야 합니다.

참고

Test Kitchen 명령이 인스턴스 이름을 받는 경우, 완전한 이름을 입력할 필요가 없습니다. Test Kitchen은 인스턴스 이름을 Ruby 정규식으로 취급하므로 고유한 일치를 제공하기에 충분한 문자만 있으면 됩니다. 예를 들어 kitchen converge ub를 실행하여 Ubuntu 인스턴스만 수렴하거나 kitchen login 64를 실행하여 CentOS 인스턴스에 로그인할 수 있습니다.

아마도 지금 시점에서 의문은 어떻게 레시피가 어느 플랫폼에서 실행 중인지 아느냐일 것입니다. Chef는 플랫폼을 포함한 시스템 데이터를 수집하는 모든 실행에 대해 Ohai라는 도구를 실행하며, 이를 노드 객체라고 하는 구조에서 속성 집합으로 나타냅니다. Chef platform? 메서드는 괄호로 묶인 시스템들을 Ohai 플랫폼 값과 비교하고 그중 하나가 일치하면 true를 반환합니다.

node['attribute_name']을 사용하면 코드에서 직접 노드 속성의 값 단원을 참조할 수 있습니다. 예를 들어 플랫폼 값은 node['platform']으로 나타냅니다. 가령 이전 예제를 다음과 같이 작성했을 수 있습니다.

if node[:platform] == 'debian' or node[:platform] == 'ubuntu' directory "/srv/www/shared" do mode 0755 owner 'root' group 'root' recursive true action :create end else log "Unsupported system" end

레시피에 조건부 논리를 포함시키는 일반적 이유는 Linux 제품군마다 가끔 패키지, 디렉터리 등에 사용되는 이름이 다르다는 점을 감안하기 위해서입니다. 예를 들어 Apache 패키지 이름은 CentOS 시스템에서는 httpd이고 Ubuntu 시스템에서는 apache2입니다.

시스템에 따라 다른 문자열만이 필요한 경우, Chef value_for_platform 메서드가 if-elsif-else보다 간단한 해법입니다. 다음 레시피는 CentOS 시스템에 /srv/www/shared 디렉터리, Ubuntu 시스템에 /srv/www/data 디렉터리, 그 밖의 모든 시스템에 /srv/www/config 디렉터리를 생성합니다.

data_dir = value_for_platform( "centos" => { "default" => "/srv/www/shared" }, "ubuntu" => { "default" => "/srv/www/data" }, "default" => "/srv/www/config" ) directory data_dir do mode 0755 owner 'root' group 'root' recursive true action :create end

value_for_platformdata_dir에 적절한 경로를 할당하며, directory 리소스는 이 값을 사용하여 디렉터리를 생성합니다.

예제 레시피를 실행하려면
  1. 인스턴스가 여전히 실행 중인 경우 kitchen destroy를 실행하여 종료합니다.

  2. default.rb의 코드를 이 예제 코드로 바꿉니다.

  3. kitchen converge를 실행한 다음 각 인스턴스에 로그인하여 해당 디렉터리가 있는지 확인합니다.