vagrant의 sandbox 플러그인

너무 글을 안써서 글을 좀 써야겠다는 마음으로 짧지만 삶에 도움되는
vagrant sandbox 명령어를 사용할 수 있게 해주는
sahara라는 플러그인을 소개하려고 한다.

해당 플러그인의 소스 저장소는 다음의 링크를 참고하시라.

sahara

sahara가 뭐하는 녀석인가?

사하라 하면 사막!
사막하면 모래!
모래 하면 sandbox 이다! (말도안되지만..그냥 넘어가자..ㅎ)
vagrant에서 사용하는 virtualbox를 sandbox 처럼 사용할 수 있게 해주는 플러그인이다.

주의

  • sahara는 Vagrant 1.0 이하에서는 제대로 동작하지 않는다.

설치

리눅스 계열은 요렇게 하면된다. (윈도우즈는….ㅠㅠ)

[code lang=text]
$ git clone https://github.com/ryuzee/sahara.git
$ cd sahara
$ bundle install
$ vagrant plugin install sahara
[/code]

설치 잘됐는지 확인

아래와 같이 나오면 잘되는 것이다.

[code lang=text]
$vagrant plugin list
sahara (0.0.17)
[/code]

사용법

이름은 sahara 인데 설치하면 사용할 수 있는 명령어는 sandbox 이다. 그냥 이름이 sandbox 였으면 안헷갈렸을것 같다.
명령어는 달랑 5개 밖에 없긴 한데, 그걸로도 충분하다.

[code lang=text]
### 샌드박스 모드 활성화
$ vagrant sandbox on

### 스냅샷 저장하기
$ vagrant sandbox commit

### 롤백하기
$ vagrant sandbox rollback

### 샌드박스 모드 끄기
$ vagrant sandbox off

### 샌드박스 상태 확인
$ vagrant sandbox status
[/code]

sandbox commit은 겁나 느리다

이걸 빠르게 하려면 가상머신을 끄고 하면 빠르다
~~근데 다시 켜는 시간은..읍읍..~~

[code lang=text]
$ vagrant halt
$ vagrant sandbox commit
[/code]

이제 이걸로 좀 더 편하게 chef질을 할 수 있게 됐다~! 예이!

참고로 virtualbox 뿐 아니라 VMware fusion, libvirt, parallels 도 지원한다~!

Chef Server 12으로 인프라 자동화하기

Chef Server 12를 사용해보기

 

2년전에 chef-server로 게임서버들을 잘 구성해서 사용했었다.
knife-solo로 하면 10대 정도까지는 그냥 관리가 가능하긴 한데,
role이나 databag같은 메타데이터를 다루게 되면,
그때부터는 chef-server를 사용하는 것도 좋은 것 같다.

2년 전에도 쉐프 서버 구축할 때 이리저리 고생을 했던 기억이 나는데,
정리를 제대로 안해놨더니, 했던 삽질을 다시하면서 나의 멍청함을 뇌로 되새기고 있다.

아무튼 다시는 그런일이 벌어지지 않게 하기 위해서,
좀 정성들여서 정리를 하는중이고, 특히 에러가 나는 포인트를 계속해서 정리중이다.

chef서버와 client는 virtual box를 사용해서 2대를 실행했고,
workstation은 mac에 chefdk를 설치해서 돌리고 있다.

사실 chef server 이외에는 chef client & knife가 깔리면 되는거라서, 뭘 어떻게 하든 크게 관계는 없을 것 같다.

기본지식

  • chef-server-core만 인스톨한 후에는 chef-server-ctl커맨드로 reconfigure을 실행해주어야한다. 설정파일이 변경되면 reconfigure를 실행해야한다.
  • chef-server-core관련 파일은 /etc/opscode에 있다.
  • 로그는 /var/log/opscode에 있다
  • chef서버의 로그를 실시간으로 보려면 chef-server-ctl tail 명령어를 사용하면 된다.

chef server 12에서는 여러가지 기능이 추가된 것 같긴한데, 기본만 설치하자.
– chef-server-core
– manage ui

chef-server-core 설치

아래 링크에서 chef-server-core_12.x.x-x_amd64.deb를 받는다. (버전은 그때 그때 다르다. RHEL은 패스)
2016년 10월의 최신버전은 12.9.1이다.

우분투 16.04
https://packages.chef.io/stable/ubuntu/16.04/chef-server-core_12.9.1-1_amd64.deb

우분투 14.04
https://packages.chef.io/stable/ubuntu/14.04/chef-server-core_12.9.1-1_amd64.deb

우분투 12.04
https://packages.chef.io/stable/ubuntu/12.04/chef-server-core_12.9.1-1_amd64.deb

아래 명령어를 실행

[code lang=text]
$ sudo dpkg -i chef-server-core_12.x.x-x_amd64.deb
$ sudo chef-server-ctl reconfigure
[/code]

reconfigure 실행시의 에러 처리

reconfigure를 실행시에 아래와 같은 에러가 날 수 있는데, 이는 nginx cookbook의 이슈이다.

[code lang=text]
Chef::Exceptions::ValidationFailed
———————————-
common_name is required
[/code]

이를 해결하려면 /etc/hosts에 유효한 호스트명을 뭐라도 넣어줘야된다.
에는 hostname 이라는 명령어를 치면 나오는 녀석으로 변경해야한다.

sudo echo "127.0.0.1 localhost localhost.localdomain <hostname>" | sudo tee -a /etc/hosts

이게 오픈소스가 되서그런지 버그가 은근 있는데, reconfigure 시에 아래와 같은 에러가 나올 수도 있다.

[code lang=text]
ubuntu@chef-server:~$ sudo chef-server-ctl reconfigure
Starting Chef Client, version 12.14.98
resolving cookbooks for run list: [“private-chef::default”]
Synchronizing Cookbooks:
– enterprise (0.10.1)
– yum (3.13.0)
– runit (1.6.0)
– packagecloud (0.2.5)
– apt (2.9.2)
– openssl (6.0.0)
– private-chef (0.1.0)
Installing Cookbook Gems:
Compiling Cookbooks…
[2016-10-21T03:00:43+00:00] WARN: Chef::Provider::AptRepository already exists! Cannot create deprecation class for LWRP provider apt_repository from cookbook apt
[2016-10-21T03:00:43+00:00] WARN: AptRepository already exists! Deprecation class overwrites Custom resource apt_repository from cookbook apt
[2016-10-21T03:00:43+00:00] WARN: Chef::Provider::YumRepository already exists! Cannot create deprecation class for LWRP provider yum_repository from cookbook yum
[2016-10-21T03:00:43+00:00] WARN: YumRepository already exists! Deprecation class overwrites Custom resource yum_repository from cookbook yum
Recipe: private-chef::default
* directory[/etc/opscode] action create (up to date)
* directory[/etc/opscode/logrotate.d] action create (up to date)
[2016-10-21T03:00:43+00:00] FATAL:

———————————————————————–
BOOT007: The secrets file (/etc/opscode/private-chef-secrets.json) is present
but the file /etc/opscode/pivotal.pem is missing.

Ensure that private-chef-secrets.json is copied into /etc/opscode from the
first Chef Server node that you brought online, then run
‘chef-server-ctl reconfigure’ again.
———————————————————————–
[/code]

이 경우에는 /etc/opscode/private-chef-secrets.json 파일을 삭제하고
다시 sudo chef-server-ctl reconfigure를 해주면 된다.

user/org를 생성

[code lang=text]
### user생성
chef-server-ctl user-create user_name first_name last_name email password –filename ADMIN_PEM_FILE_NAME

### org생성
chef-server-ctl org-create short_name full_organization_name –association_user user_name –filename ORG_VALIDATION_KEY_FILE_NAME
[/code]

/etc/opscode/admin.pem
/etc/opscode/orgname-validator.pem
등의 이름이 뭘하는 파일인지 알아보기 쉽다.

chef manage ui 설치

이번 버전부터 ui가 엄청 이뿌게 변했다.
소스를 대충 보니 bootstrap을 사용한것 같은데, 개발자스럽긴하지만, 이쁜 UI이다.

[code lang=text]
$ sudo chef-server-ctl install opscode-manage
$ sudo opscode-manage-ctl reconfigure
[/code]

12.9 버전에서 opscode-manage가 chef-manage로 변경되었다. 최신버전을 쓰는 사람은 chef-manage로 설치하자

[code lang=text]
$ sudo chef-server-ctl install chef-manage
$ sudo chef-server-ctl reconfigure
$ sudo chef-manage-ctl reconfigure
[/code]

workstation 구축

chef를 설치

[code lang=text]
$ sudo curl -L https://www.opscode.com/chef/install.sh | sudo bash
[/code]

chefdk(chef development kit) 라는 녀석을 설치해도 된다.

chefdk에는 chef, Test Kitchen, ChefSpec, Foodcritic, Chef Client, Knife, Ohai, Chef Zero 등이 함께 들어 있어서 쉐프 레시피개발 및 테스트에 좋다.

knife 설정

[code lang=text]
$ knife configure
Where should I put the config file? [/home/USER/.chef/knife.rb]
Please enter the chef server URL: [https://xxx:443] https://chef-server/organizations/org
Please enter an existing username or clientname for the API: [user] <USER>
Please enter the validation clientname: [chef-validator] <ORG>-validator
Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem] /Users/wapj/chef/.chef/<ORG>-validator.pem
Please enter the path to a chef repository (or leave blank): <CHEF-REPO-PATH>
[/code]

위와 같이 하면 .chef 디렉토리 아래에 knife.rb 파일이 생긴다.
해당 파일은 아래와 같이 생겼다.

[code lang=text]
### knife.rb
log_level :info
log_location STDOUT
node_name ‘wapj’
client_key ‘/Users/wapj/chef/.chef/admin.pem’
validation_client_name ‘company-validator’
validation_key ‘/Users/wapj/chef/.chef/org-validator.pem’
chef_server_url ‘https://wapj-VirtualBox/organizations/wapj’
syntax_check_cache_path ‘/Users/wapj/chef/.chef/syntax_check_cache’
cookbook_path [“/Users/wapj/chef/site-cookbooks”]
[/code]

admin.pem파일과 org-validator.pem 파일은 쉐프 서버에서 scp 명령어 등으로 잘 가져와서 해당디렉토리에 복사하자.

chef서버와 잘 통신되는지 확인

아래와 같은 명령어로 확인이 가능하다.

[code lang=text]
$ knife ssl check
[/code]

trouble shooting

knife.rb의 chef_server_url설정에 아이피를 넣은 경우

아래와 같은 에러가 난다.

[code lang=text]
Connecting to host 192.168.10.111:443
ERROR: The SSL cert is signed by a trusted authority but is not valid for the given hostname
ERROR: You are attempting to connect to: ‘192.168.10.111’
ERROR: The server’s certificate belongs to ‘wapj-VirtualBox’

TO FIX THIS ERROR:

The solution for this issue depends on your networking configuration. If you
are able to connect to this server using the hostname wapj-VirtualBox
instead of 192.168.10.111, then you can resolve this issue by updating chef_server_url
in your configuration file.

If you are not able to connect to the server using the hostname wapj-VirtualBox
you will have to update the certificate on the server to use the correct hostname.
[/code]

이 경우 /etc/hosts에 server의 domain혹은 QFDN을 아래와 같은 식으로 넣어주어야 한다.

[code lang=text]
# hosts
192.168.10.111 wapj-VirtualBox
[/code]

chef server에서 받은 인증서가 localhost로 되어 있을 때

로컬에서만 테스트하다가 실제로 서버를 올리면 이런 일이 생기곤 한다.
workstation 에서 아래의 명령어를 실행했는데

[code lang=text]
$ knife ssl check
[/code]

아래와 같은 에러가 나는경우

[code lang=text]
Connecting to host chef.gyus.me:443
ERROR: The SSL cert is signed by a trusted authority but is not valid for the given hostname
ERROR: You are attempting to connect to: ‘chef.gyus.me’
ERROR: The server’s certificate belongs to ‘localhost’

TO FIX THIS ERROR:

The solution for this issue depends on your networking configuration. If you
are able to connect to this server using the hostname localhost
instead of chef.gyus.me, then you can resolve this issue by updating chef_server_url
in your configuration file.

If you are not able to connect to the server using the hostname localhost
you will have to update the certificate on the server to use the correct hostname.
[/code]

이 경우는 chef server의 /etc/opscode/chef-server.rb 파일에 설정을 추가해주어야한다.
chef server의 도메인이 chef.gyus.me라고 한다면, 아래와 같이 수정해 주면 된다.

[code lang=text]
### /etc/opscode/chef-server.rb
api_fqdn “chef.gyus.me”
[/code]

설정 파일이 수정되었으므로 서버에서 chef-server-ctl reconfigure를 한번더 실행해준다.

그리고 workstation으로 돌아와서 인증서를 받아오는 작업을 다시 해주자.

[code lang=text]
$ knife ssl fetch
$ knife ssl check
[/code]

아래와 같이 나오면 성공이다.

[code lang=text]
Connecting to host chef.gyus.me:443
Successfully verified certificates from `chef.gyus.me’
[/code]

아래와 같은 에러가 날 때

[code lang=text]
$knife status
ERROR: The object you are looking for could not be found
Response: <!DOCTYPE html>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7″ />
<title>Chef – 404 Not Found</title>
<link media=”all” rel=”stylesheet” type=”text/css” href=”/css/all.css” />
<!–[if lt IE 7]><link rel=”stylesheet” type=”text/css” href=”/css/lt7.css” /><![endif]–>
</head>
<body>
<div class=”header-block”>
<div id=”header”>
<strong class=”logo”><a href=”http://www.getchef.com”>Chef</a></strong>
</div>
</div>
<div id=”wrapper”>
<div id=”main”>
<div class=”mybox”>
<div id=”content”>
<h1>404 – Not Found</h1>
<p>Sorry, I can’t find what you are looking for.</p>
</div>
</div>
</div>
</div>
<div class=”footer-block”>
<div id=”footer”>
<div class=”mybox”>
</div>
<div class=”footer-bottom”>
<span>© 2010 – 2014 Chef Software, Inc. All Rights Reserved</span>
</div>
</div>
</div>
</body>
</html>
[/code]

knife.rb 설정의 chef_server_url에 정말로 serverURL만 넣은 경우에 나는 에러이다.

아래와 같은 식으로 되어있다면,

[code lang=text]
chef_server_url https://wapj-VirtualBox/
[/code]

뒤에 organizations/<ORGANIGATION>을 붙여주자.

[code lang=text]
chef_server_url https://wapj-VirtualBox/organizations/wapj
[/code]

쿡북 만들기

아래 명령어로 hello라는 쿡북을 site-cookbooks에 만들었다.
레시피

[code lang=text]
$ knife cookbook create hello -o site-cookbooks
[/code]

간단히 아래 파일을 변경하자.

[code lang=text]
site-cookbooks/hello/recipes/defau1t.rb
[/code]

[code lang=text]
### default.rb
log “Hello , Chef!”
[/code]

쿡북을 서버로 업로드하기

아래의 커맨드를 사용하면 모든 쿡북이 서버로 업로드 된다.

[code lang=text]
$ knife cookbook upload -a
[/code]

하나의 쿡북만 업로드 하고 싶은 경우는 아래의 커맨드를 사용하자.

[code lang=text]
$ knife cookbook upload <쿡북이름> -o <해당쿡북의 폴더가 있는 경로>
$ knife cookbook upload hello -o ./site-cookbooks/
[/code]

쿡북 업로드시에 SSL 에러가 나는 경우

[code lang=text]
WARN: Found a directory hello in the cookbook path, but it contains no cookbook files. skipping.
ERROR: SSL Validation failure connecting to host: 192.168.10.111 – hostname “192.168.10.111” does not match the server certificate
[/code]

자가 인증서로 검증하기 때문에 나는 당연한 에러(?!) 라서, 검증하지 말라고 하면 된다..;;

아래 한줄을 knife.rb에 추가해주자

[code lang=text]
ssl_verify_mode :verify_none
[/code]

chef-client

chef 설치

  • 서버와의 인증에는 비밀키를 사용한다.
  • chef server는 client별로 비밀키를 발행하고, 공개키를 chef-server에 등록한다.
  • client별로 비밀키를 발행해야 하기 때문에, 미리 준비된 validator-key를 사용한다.
  • client는 처음에는 validator-key로 통신해서 chef server에 client로 등록한후 이후의 통신에 필요한 비밀키가 발행된다.
  • workstation에서 삽질했던것 처럼 hosts에 chef server의 ip를 등록해야한다.

knife bootstrap으로 client 등록하기

전제 조건
1. chef server에서 client서버로 비밀번호 없이 root계정으로 로그인을 할 수 있어야한다.
2. bootstrap 을 실행할 서버의 /etc/hosts에 chef server의 ip를 등록한다.

1번 조건은 root의 홈디렉토리에 chef server의 퍼블릭키를 authorized_keys파일에 등록하면 된다.
2번은 위의 workstation 설정시에 보았던, /etc/hostschef server의 ip를 등록하면 된다.

chef server가 만약에 해킹당하게 되면, 모든 서버에 접속 할 수 있으므로 이 방법을 사용할 때에는,
chef server의 보안에 특히 주의 해야한다.
나 같은 경우는 chef server를 사용할 때만 켰다가 끄는 방식으로 사용했다.

위의 조건이 만족되면, 아래의 커맨드로 바로 노드를 등록할 수 있다.

[code lang=text]
$ knife bootstrap <client server ip> -x <user> -N <node name>
[/code]

성공하게 되면 아래와 같은 메세지가 나오게 된다.

[code lang=text]
### workstation의 chef repo 디렉토리에서 실행하면 된다.

$knife bootstrap 192.168.10.101 -x root -N node1
Doing old-style registration with the validation key at /Users/wapj/chef/my-chef/.chef/company-validator.pem…
Delete your validation key in order to use your user credentials instead

Connecting to 192.168.10.101
192.168.10.101 —–> Existing Chef installation detected
192.168.10.101 Starting the first Chef Client run…
192.168.10.101 Starting Chef Client, version 12.7.2
192.168.10.101 Creating a new client identity for node1 using the validator key.
192.168.10.101 resolving cookbooks for run list: []
192.168.10.101 Synchronizing Cookbooks:
192.168.10.101 Compiling Cookbooks…
192.168.10.101 [2016-02-16T21:02:32+09:00] WARN: Node node1 has an empty run list.
192.168.10.101 Converging 0 resources
192.168.10.101
192.168.10.101 Running handlers:
192.168.10.101 Running handlers complete
192.168.10.101 Chef Client finished, 0/0 resources updated in 02 seconds
[/code]

node가 등록되었는지 확인

[code lang=text]
### workstation의 chef repo에서 실행
$ knife node list
[/code]

잘 등록되었다면 아래와 같이 나올 것이다.

[code lang=text]
node1
[/code]

node에 레시피 등록 하기

노드는 등록되었지만, 레시피가 아무것도 없으므로 실행해봐야 아무것도 안나온다.
레시피를 등록해보자.

해당 작업은 chef server의 WEB UI에서도 가능하므로, 웹사이트에 들어가서 해도 된다.

[code lang=text]
### workstation의 chef repo에서 실행
$ knife node run_list add <노드명> ‘recipe[레시피명]’
$ knife node run_list add node1 ‘recipe[hello]’
[/code]

node에서 레시피 실행하기

레시피의 실행은 각 노드 서버에 들어가서 $ sudo chef-client 를 실행해주면 되지만,
귀찮게 일일이 들어가면 굳이 서버를 설치한 이유가 없으니 서버에서 실행할 수 있는 방법을 찾아보자.

바로 knife search node를 이용하는 방법인데,

아래의 명령어를 실행하면, 조건을 줘서 chef client를 찾을 수 있다.

[code lang=text]
$ knife search node “fqdn:*”
[/code]

그리고 조건은 knife ssh에도 동일하게 사용가능 한데, 조건과 조합하여 여러서버에 커맨드를 날릴수있다.
예를 들어 아래와 같이 실행하게 되면, 모든 서버에 echo "hello" 명령을 날리게 된다.

[code lang=text]
$ knife ssh “fqdn:*” ‘echo “hello”‘
[/code]

이를 응용하여 아래와 같이 실행하게 되면, 모든 클라이언트에 sudo chef-client를 실행 할 수 있게 된다.

[code lang=text]
$ knife ssh “fqdn:*” “sudo chef-client”
[/code]

hosts에 정보가 없는 경우

아래와 같은 에러가 난다.

[code lang=text]
WARNING: Failed to connect to node1 — SocketError: getaddrinfo: nodename nor servname provided, or not known
[/code]

이 경우는 workstation의 /etc/hosts에 node1의 ip를 등록해야한다.

[code lang=text]
### workstaions의 /etc/hosts
192.168.10.101 node1
[/code]

다시 실행해보면~

[code lang=text]
$ knife ssh “fqdn:*” “sudo chef-client”
[/code]

아직도 에러가 난다;;;

[code lang=text]
node1
node1 Starting Chef Client, version 12.7.2
node1 resolving cookbooks for run list: [“hello”]
node1 Synchronizing Cookbooks:
node1 [2016-02-16T21:45:15+09:00] ERROR: SSL Validation failure connecting to host: wapj-virtualbox – hostname “wapj-virtualbox” does not match the server certificate
node1 [2016-02-16T21:45:15+09:00] ERROR: SSL Validation failure connecting to host: wapj-virtualbox – hostname “wapj-virtualbox” does not match the server certificate
node1 [2016-02-16T21:45:15+09:00] ERROR: SSL Validation failure connecting to host: wapj-virtualbox – hostname “wapj-virtualbox” does not match the server certificate
node1 ================================================================================
node1 Error Syncing Cookbooks:
node1 ================================================================================
node1
node1 Unexpected Error:
node1 —————–
node1 OpenSSL::SSL::SSLError: SSL Error connecting to https://wapj-virtualbox/bookshelf/organization-7479a4a25da1226f99983095c54052ba/checksum-40dcaffc3a2cdc8968a18f61672dab63?AWSAccessKeyId=49472f43a12b78c05ea083a9e82ac20de4ca4463&Expires=1455655515&Signature=ftp5IYQKkyvjyXYPG%2BlPltfh/18%3D – hostname “wapj-virtualbox” does not match the server certificate
node1 Running handlers complete
node1 [2016-02-16T21:45:40+09:00] ERROR: Exception handlers complete
node1 Chef Client failed. 0 resources updated in 27 seconds
node1 [2016-02-16T21:45:40+09:00] FATAL: Stacktrace dumped to /var/chef/cache/chef-stacktrace.out
node1 [2016-02-16T21:45:40+09:00] ERROR: SSL Validation failure connecting to host: wapj-virtualbox – hostname “wapj-virtualbox” does not match the server certificate
node1 [2016-02-16T21:45:40+09:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
node1 [2016-02-16T21:45:40+09:00] ERROR: SSL Error connecting to https://wapj-virtualbox/bookshelf/organization-7479a4a25da1226f99983095c54052ba/checksum-40dcaffc3a2cdc8968a18f61672dab63?AWSAccessKeyId=49472f43a12b78c05ea083a9e82ac20de4ca4463&Expires=1455655515&Signature=ftp5IYQKkyvjyXYPG%2BlPltfh/18%3D – hostname “wapj-virtualbox” does not match the server certificate
node1 [2016-02-16T21:45:40+09:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
[/code]

에러는 인증서가 매치가 안된다는 말인데, 자가 인증서이기 때문에 안되는 문제이다.

/etc/chef/client.rbssl_verify_mode :verify_none을 또 추가해주자.

아래와 같은 형태로 client.rb가 되어 있으면 된다.

[code lang=text]
### node1 서버 client.rb
log_location STDOUT
chef_server_url “https://chef-server/organizations/company”
validation_client_name “company-validator”
node_name “node1”
trusted_certs_dir “/etc/chef/trusted_certs”
ssl_verify_mode :verify_none
[/code]

다시 실행해보자

[code lang=text]
$ knife ssh “fqdn:*” “sudo chef-client”
[/code]

아래와 같이 실행된다.

[code lang=text]
node1
node1 Starting Chef Client, version 12.7.2
node1 resolving cookbooks for run list: [“hello”]
node1 Synchronizing Cookbooks:
node1 – hello (0.1.0)
node1 Compiling Cookbooks…
node1 Converging 1 resources
node1 Recipe: hello::default
node1 * log[Hello Chef!] action write
node1
node1
node1 Running handlers:
node1 Running handlers complete
node1 Chef Client finished, 1/1 resources updated in 01 seconds
[/code]

개발PC에서 cookbook을 만들어서 올리고, chef의 API를 사용해서 실행하는 것을 보여주기위해
workstation이라는 것을 예로 들었지만, workstation을 굳이 만들지 않아도 되고, chef serverchef를 설치해서 하는 것이 더 간단한 방법일 수도 있다.
개념을 파악하고 구조를 파악해서, 각자의 환경에 맞게 잘 사용하면 될 것 같다.

좀 길었지만, chef server 설치중에 내가 만난 문제들은 다 정리가 된것 같다.
몇가지 수동으로 했던 부분들을 자동화하게 되면, 훌륭한 인프라 툴이 될 것이다.

TIPS

여기서 부터는 꼭 안봐도 되고, 약간씩 도움이 되는 팁을 정리하려고 한다.
알면 좋고 모르면, 그냥 손이 수고하면 되는(?) 그런 부분이다. 귀찮으면 과감히 패스~

knife.rb 설정에 변수 사용하기

팁이라고 하기도 뭐한 팁인데,
쉐프의 소스가 git 같은 소스 관리 프로그램으로 관리되는 경우,
키의 경로를 절대 경로로 잡아주게 되면,
다른 pc나 인스턴스에서 쉐프 소스를 받게 되면, 매번 수정해야 하는 번거로움이 생긴다.
이 때에 각 키의 경로를 그냥 knife.rb와 같은 경로로 변수를 사용하는 팁이 되시겠다.

knife.rb 파일은 말 그대로 루비 스크립트 이므로 루비의 문법을 사용하면 되는데,
File.dirname(__FILE__) 이라는 녀석이랑 erb의 문법을 사용할 것이다.

[code lang=text]
### knife.rb
urrent_dir = File.dirname(__FILE__)
log_level :info
log_location STDOUT
node_name “company”
client_key “#{current_dir}/admin.pem”
validation_client_name “company-validator”
validation_key “#{current_dir}/gyus-validator.pem”
chef_server_url “https://deploy.gyus.me/organizations/gyus”
syntax_check_cache_path “#{current_dir}/syntax_check_cache”
ssl_verify_mode :verify_mode
[/code]

위의 파일에서 중요한 것은 홑따옴표 ' 가 아니라 쌍따옴표 "를 써야 변수를 루비가 인식하고 변환해준다는 점이다.

업데이트 (2016.10.21)

자가 인증서가 아닌 comodo등의 기관에서 발급받은 인증서를 적용하고 싶은경우.

/var/opt/opscode/nginx/ca 아래에 있는 chef-server.crt, chef-server.key 를 자신이 가지고 있는 인증서로 바꿔치기 하면된다.

파일명을 같게한다음(확장자는 맞춰줘야함) 덮어쓰자.

그 후 설정을 변경하기위해 sudo chef-server-ctl reconfigure 를 실행하고 sudo chef-server-ctl restart를 실행해주자.

이렇게 하면 끝난다. 파일명을 다르게 적용하고 싶다면, /var/opt/opscode/nginx/etc/chef_https_lb.conf 안에 있는 설정을 변경해야한다.

아래와 같은 설정이 있는데, 파일명도 바꿔주면 된다.

[code lang=text]
ssl_certificate /var/opt/opscode/nginx/ca/chef-server.crt;
ssl_certificate_key /var/opt/opscode/nginx/ca/chef-server.key;
[/code]

어려울 줄 알았는데, 생각보다 너무 쉬웠음.

Chef 서버 설치하고 테스트해보기

Chef 서버 설치하고 테스트해보기

vagrant + virtualbox로 5대의 멀티 인스턴스 올리기

Chef 서버의 환경을 이해해 보려면 3개이상 가상머신을 설치해서 해보는게 좋다.
Vagrant로 5대의 가상머신을 올려보자.
Vagrant를 설치하고 VagrantFile에 아래와 같이 설정한 후

vagrant up을 실행하면 된다.

vagrant 사용법은 아래의 링크를 참고 하자.

Chef의 테스트 환경을 만드는데 매우 적합한 툴 – Vagrant (http://gyus.me/?p=326)

 

VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.define :chef_server do |cfg|
cfg.vm.box = "base"
cfg.vm.network :private_network, ip: "192.168.30.10"
cfg.vm.host_name = "chef-server"
end
config.vm.define :workstation do |cfg|
cfg.vm.box = "base"
cfg.vm.network :private_network, ip: "192.168.30.20"
cfg.vm.host_name = "workstation"
end
config.vm.define :node01 do |cfg|
cfg.vm.box = "base"
cfg.vm.network :private_network, ip: "192.168.30.21"
cfg.vm.host_name = "node01"
end
config.vm.define :node02 do |cfg|
cfg.vm.box = "base"
cfg.vm.network :private_network, ip: "192.168.30.22"
cfg.vm.host_name = "node02"
end
config.vm.define :node03 do |cfg|
cfg.vm.box = "base"
cfg.vm.network :private_network, ip: "192.168.30.23"
cfg.vm.host_name = "node03"
end
end

 

chef server 설치

아래 사이트에서 패키지를 다운 받아서 설치

http://www.getchef.com/chef/install/

[code lang=text]
wget https://opscode-omnitruck-release.s3.amazonaws.com/ubuntu/12.04/x86_64/chef-server_11.0.6-1.ubuntu.12.04_amd64.deb
[/code]

[code lang=text]
sudo dpkg -i chef-server.deb
[/code]

설치 완료후 chef-server-ctl로 Chef Server를 설정함

[code lang=text]
sudo chef-server-ctl reconfigure
[/code]

위 커맨드를 실행하면 서버를 기동시키고, nginx가 HTTPS 443포트를 바인드한다.

Chef의 각종 파일은 /opt 디렉토리에 인스톨된다.

knife 설정

[code lang=text]
knife configure
[/code]

실행하면 아래와 같은 설정 항목들이 나옴 걍 엔터.

[code lang=text]
Where should I put the config file? [/home/vagrant/.chef/knife.rb]
Please enter the chef server URL: [https://chef-server:443]
Please enter an existing username or clientname for the API: [vagrant]
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem]
Please enter the path to a chef repository (or leave blank):
[/code]

임의의 클라이언트가 처음 Chef Server와 통신을 할경우, 디지털서명이 없기 때문에,
최초 한번, chef-validator라는 Client등록작업만을 전문으로 하는 클라이언트 에서 인증서를 빌려서 Chef Client의 등록작업을 하게됨. 이 작업이 완료되면 이후는 클라이언트 쪽에서 작성한 디지털서명에 의해 통신이 이루어지도록 된다.

dep패키지로 Chef Server를 설치하면 /etc/chef-server 디렉토리에 아래와 같은 파일이 있음. knife configure로 knife에게 이러한 인증서의 패스를 정확히 설정할 필요가 있다.
우선은 서버와 같은 호스트의 knife가 잘동작하도록 하고, 후에 workstation에 인증서를 전송하는 순서로 설치를 하겠음.
일단은 /etc/chef-server이하의 pem파일을 홈디렉토리로 카피함.

  • chef-validator.pem : chef-validator용의 디지털 인증서 파일
  • admin.pem : 관리자용의 클라이언트 인증서 파일(이 것을 사용하는 클라이언트 만 chef-validator를 통하지 않고 미리 작성되어 있음)

[code lang=text]
vagrant@chef-server:/$ sudo knife configure
Please enter the chef server URL: [https://chef-server:443] https://192.168.30.10
Please enter an existing username or clientname for the API: [vagrant] admin
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem] ~/.chef/validation.pem
Please enter the path to a chef repository (or leave blank):
[/code]

위의 설정에서
* server URL : https://192.168.30.10
* clientname : admin
* validation key : /etc/chef-server/chef-validation.pem
을 설정함. 이것으로 해당 서버의 knife는 클라이언트의 인증서가 있는 ~/.chef/admin.pem을 이용해서 통신을 하게끔 된다. 한번 시험해봅시다.

[code lang=text]
$ knife client list
[/code]

Work Station의 셋업

새로운 Chef Client를 셋업 할 경우, 인증서의 생성과 클라이언트를 서버에 등록하는 것이 필요하다. 이것도 knife로 하게됨. 서버에 설치한 knfie를 사용해 보도록 하자.

knife client create를 실행하면 에디터에서 메타데이터의 편집을 요구하기때문에, EDITOR의 환경변수를 미리 설정해둠. knife client create 옵션의 -a 는 관리권한을 가진 클라이언트의 작성, -f는 인증파일의 저장소 지정. Vagrant를 사용하는 경우는 가상머신의 /vagrant는 공유 디렉토리로 마운트되어 있어서 다른 가상서버로의 파일전송이 편리하다. 거기에 저장을 하도록 해보자.

[code lang=text]
$ export EDITOR=vi
$ knife client create workstation -a -f /vagrant/workstation.pem
[/code]

Work Station의 knife에도 validation.pem을 저장해두면 나중에 편하니 거기에도 카피해두자.

그리고 여기서 부터는 Work Station에서 작업해야한다. 우선은 Work Station에 Chef Solo를 설치할때 사용한 Opscode Omnibug Packaging의 인스톨스크립트를 실행해서 Chef를 설치한다.

[code lang=text]
$ vagrant ssh workstation
$ curl -L https://www.opscode.com/chef/install.sh | sudo bash
$ chef-client -v
Chef: 11.8.2
[/code]

이 다음으로는 서버에서 한것과 동일하게 knife를 설정해야한다.

[code lang=text]
$ cp /vagrant/workstation.pem ~/.chef/
$ cp /vagrant/validation.pem ~/.chef/
$ knife configure
WARNING: No knife configuration file found
Where should I put the config file? [/home/vagrant/.chef/knife.rb]
Please enter the chef server URL: [https://workstation:443] https://192.168.30.10
Please enter an existing username or clientname for the API: [vagrant] workstation
Please enter the validation clientname: [chef-validator]
Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem] ~/.chef/validation.pem
Please enter the path to a chef repository (or leave blank):
[/code]

서버의 URL과 방금 설정한 인승키의 패스를 설정.
제대로 설정을 했다면 knife client list로 출력이 되고 새로운 Client로 workstation이 등록된다.

[code lang=text]
### Chef Server에서 작업
$ knife client list
chef-validator
chef-webui
workstation
[/code]

<h3>Chef Client의 설치</h3>
Chef Server와 Work Station이 완료된 후에는 Client를 작업하자.
관리 대상이 되는 노드를 Chef Client로 셋업하자.

클라이언트측의 Chef인스톨도 Opscode Omnibus Packaging의 인스톨 스크립트를 실행하면 된다.

우분투를 클린상태로 설치했다면, 몇가지 패키지를 설치해야하니 다음 순서로 설치해보자.

[code lang=text]
### Chef Client에서 실행함.
$ sudo apt-get update
$ sudo apt-get install curl vim -y
$ curl -L https://www.opscode.com/chef/install.sh | sudo bash
$ chef-client -v
$ sudo mkdir -p /etc/chef
$ sudo cp /vagrant/validation.pem /etc/chef/validation.pem
[/code]

위의 스크립트를 한줄 한줄 실행해도 되고 귀찮은 사람은 파일로 만들어서 한방에 실행해도 된다.

노드에서 chef-client를 실행해서 해당 노드를 서버에 등록하자. –server로 서버의 URL을 지정하고, -N으로 노드명을 지정할 수 있다.(생략하려면 /etc/chef/client.rb를 설정하면 된다. 자세히 알고 싶으면 매뉴얼을 보도록 하자.)

[code lang=text]
$ sudo chef-client –server https://192.168.30.10 -N node01
[/code]

최초의 Client실행 때에 /etc/chef/client.pem에 클라이언트용 인증서가 생성되고, 이후의 통신은 validation.pem이 아닌 클라이언트용 인증서를 사용하게 된다.

Chef Server에 노드가 등록되었는지 Work Station의 knife에서 확인가능하다.

[code lang=text]
### Work Station에서 실행
$ knife client list
chef-validator
chef-webui
node01
workstation
[/code]

node02, node03에는 추후에 따로 세팅을 할테니 우선 두자.

헉헉헉…길다…
<h3>레시피 실행하기</h3>
잘동작하는지 테스트용 레시피를 작성후 실행해보자.
테스트로는 해당노드에 대한 각종 정보를 가지고 있는 ohai를 확인해 보는 레시피를 작성하도록 하자.
Work Station에서 쿡북을 작성하고 Server에 업로드 한 뒤 클라이언트에 적용해보자.
<h4>쿡북의 작성</h4>

[code lang=text]
$ knife cookbook create sample -o ~/chef-repo/cookbooks
[/code]

<h4>
레시피의 작성</h4>

[code lang=text]
$ vi ~/chef-repo/cookbooks/recipes/default.rb

bash "print ohai info" do
user 'vagrant'
group 'vagrant'
cwd '/home/vagrant'
environment "HOME" => '/home/vagrant'
code < /tmp/ohai.txt
EOC
creates "/tmp/ohai.txt"
end
[/code]

<h4>쿡북의 업로드</h4>

[code lang=text]
$ knife cookbook upload -a -o ~/chef-repo/cookbooks
[/code]

<h4>Node Object의 run_list 레시피 추가</h4>

[code lang=text]
$ knife node run_list add node01 'recipe[sample]'
[/code]

<h4>Node Object를 에디터에서 편집하고 싶은 경우</h4>

[code lang=text]
$ knife node edit node01
[/code]

이제 서버에 필요한 정보의 등록은 완료됐다.
노드 쪽에서 chef-client를 실행하고 생성된 파일을 확인해 보자.

[code lang=text]
$ sudo chef-client –server https://192.168.30.10 -N node01
$ cat /tmp/ohai.txt | head
{
"languages": {
"ruby": {
"platform": "x86_64-linux",
"version": "1.8.7",
"release_date": "2012-02-08",
"target": "x86_64-unknown-linux-gnu",
"target_cpu": "x86_64",
"target_vendor": "unknown",
"target_os": "linux",

[/code]

knife bootstrap 으로 노드 설정하기

가상머신으로 실행중인 경우 Work Station에서 knife bootstrap 명령을 원격으로 실행 가능하도록, 몇가지 선행되어야하는 작업이 있는데 다음과 같다.

  • 가상서버에 ssh로그인 가능하도록 호스트 OS의 ~/.vagrant.d/insecure_private_key를 Work Station의 ~/.ssh/id_rsa에 카피

[code lang=text]
### 호스트 OS에서 작업
$ scp ~/.vagrant.d/insecure_private_key worksstation:~/.ssh/id_rsa
[/code]

  • 가상서버에 설치되어 있는 옛날 버젼의 Chef가 설치시 에러를 일으킬 수 있으므로 제거. /usr/bin 디렉토리의 chef-* 파일을 어딘가로 이동해두면 된다.

[code lang=text]
### Work Station에서 작업
$ mv /usr/bin/chef-* /tmp/
[/code]

  • Work Station의 /etc/hosts에 각 노드의 IP주소를 등록해둔다.

[code lang=text]
# /etc/hosts

192.168.30.21 node01
192.168.30.22 node02
192.168.30.23 node03
[/code]

위의 설정은 knife ssh가 호스트로의 통신을 FQDN(Fully Qualified Domain Name)으로 실행하기 위한 것이다.

정리

설치와 실행이 매우 길고 좀 복잡해 보이는데, 차근차근 따라해보면 그렇지도 않다. 관리하는 서버가 10대를 넘어가면 Chef Server를 고려해 보는 것이 좋은 것 같다.

Role – 노드를 역활별로 그루핑 해서 관리하고 싶을 때

Node Object

chef solo로 관리하는 서버가 늘면, Node Object를 정의하는 JSON파일 수가 서버수만큼 늘게 되는데, Node Object에 정의한 run_list에 실행할 레시피를 일일이 JSON파일에 적어주는게 귀찮아진다.

예를 들어 같은 레시피를 적용할 5개의 노드가 있는 경우 새로운 레시피를 추가하고 싶은경우 5번을 복사 붙이기를 하는건 DRY법칙에 어긋나고 귀찮기도 하다. 그래서 run_list와 Attribute를 노드의 역활별로 그루핑 할 수 있는 Role을 사용하면 된다.

Chef solo의 경우 Role은 roles디렉토리의 아래에 Role별로 파일을 만들고, 그안에 Rolo에 필요한 내용을 JSON으로 적는다.

웹서버용 노드의 Role을 rolos/webserver.json으로 작성해보자.

json
{
"name":"webserver",
"default_attributes": {},
"override_attributes": {},
"json_class":"Chef::Role",
"description":"",
"chef_type":"role",
"run_list":[
"recipe[yum::epel]",
"recipe[nginx]",
"recipe[sysstat]"
]
}

배포하려는 서버의 Node Object에는 아래와 같이 적으면 됨

json
{
"run_list":[
"role[webserver]"
]
}

여러개 섞어서 적는것도 가능

“`json
{
“run_list”:[
“recipe[nginx]”,
“role[webserver]”,
“role[db]”
]

}
“`

Role에 어트리뷰트를 정의하는 것도 가능

json
default_attributes "apache2" => {
"listen_ports" => ["80", "443"]
}

chef정리

chef 정리

knife가지고 놀기

cookbook 만들기

shell
$ knife cookbook craete [쿡북이름] -o [디렉토리명]
$ knife cookbook craete hello -o site-cookbooks

knife solo

knife-solo의 설치

knife-solo는 rubygem이므로 아래의 커맨드로 설치가능
shell
$ gem install knife-solo

설치하는 것 만으로도 knife커맨드에 chef-solo를 위한 커맨드가 추가 됨.

knife solo를 파라메터 없이 실행해 보면 사용가능한 커맨드의 리스트가 출력 됨.

knife-solo의 문서

https://github.com/matschaffer/knife-solo/blob/master/README.rdoc

레시피 전송 & 실행 knife solo cook

shell
$ knife solo cook 유저@호스트명

cook 커맨드는 키친(리포지토리)를 대상 서버에 업로드하고, chef-solo를 실행시킨다.

knife-solo를 이용한 chef-solo 실행환경 준비

shell
$ knife solo prepare 유저@호스트
$ knife solo prepare -p 포트 유저@호스트

리포지토리 작성

shell
$ knife solo init 리포지토리 명

디렉토리 구성은 아래와 같다.

├── .chef
│ └── knife.rb
├── cookbooks #다운로드한 쿡북을 저장
├── data_bags #노드간에 공유할 수 있는 변수 저장
├── nodes #노드별로 JSON파일을 저장
├── roles
└── site-cookbooks #자신이 만든 쿡북을 저장

prepare + cook = bootstrap

shell
knife solo bootstrap 유저@호스트

knife solo prepare 를 호출하고 나서 knife solo cook을 호출.

clean

shell
$ knife solo clean 유저@호스트

대상 호스트에 있는 키친(레포지토리)을 완전히 삭제

Chef의 테스트 환경을 만드는데 매우 적합한 툴 – Vagrant

Vagrant : 가상머신을 간단히 만들고, 부수고 할 수 있는 VirtualBox의 프론트 엔드툴.

Chef Solo로 만든 레시피를 실험해보기엔 최적이다.

공식 사이트

http://www.vagrantup.com/

문서

  • 당연한 말이지만, 문서에 읽어볼 만한게 많다. 기본적인건 아래의 글을 참고하고, 좀 더 추가적인 기능들은 문서를 참고하길!

http://docs.vagrantup.com/v2/

Vagrant 도입하기

http://downloads.vagrantup.com/ 에서 다운 받을 수 있는데, 나는
http://downloads.vagrantup.com/tags/v1.2.7 에서 Mac용 dmg파일을 받아서 설치했다. 설치는 매우 쉬우니 생략.

가상서버 올리기

서버 올리는거는 커맨드라인에서 vagrant명령어를 실행하는 걸로 됨. 처음에는 Vagrant Box라는 OS 이미지를 다운로드 해야함.

http://www.vagrantbox.es 에 Vagrant용 OS이미지가 종류별로 공개되어 있음.

vagrant box add {title} {url}

요거 실행하면, ~/.vagrant.d/boxes라는 디렉토리아래에 {title}이라는 디렉토리가 생기고,
그 아래에 virtualbox라는 폴더 아래에 버추얼 머신 관련 파일이 다 들어 있음.

을 실행하는 것으로 가능.

적당한 디렉토리를 만들고 거기에 들어간다음

$ vagrant init {title}

을 실행하면 해당 디렉토리 내에 Vagrantfile이라는 ruby로 된 설정파일이 만들어진다.

그리고 나서 기동

$ vagrant up

실제로 내가 테스트해본 커맨드는 아래와 같다.

$ vagrant box add ubuntu http://dl.dropbox.com/u/1537815/precise64.box
(실행후 이미지 다운받느라 시간 좀 걸림)
$ mkdir virtualEnv
$ cd virtualEnv
$ vagrant init ubuntu
$ vagrant up

ssh로 로그인 하려면(1)

$ vagrant ssh

와 같은 명령어를 실행해 주면 된다.

vagrant ssh말고 ssh 커맨드로 가상머신에 들어가고 싶을 때에는 Vagrantfile의 네트워크 설정을 조금 수정해야한다.

아래와 같은 코드가 주석 처리 되어 있는데, 주석을 풀어주면 된다.
config.vm.network :private_network, ip: "192.168.33.10"

그러면 ssh로도 들어갈 수는 있지만, 암호를 물어보는데, 이렇게 말고 Vagrant의 비밀키를 디폴트로 사용하게끔 설정 가능하다.

ssh로 로그인 하려면(2)

$ vagrant ssh-config --host [호스트 명]
이렇게 하면, 가상머신 서버에 관한 ssh설정이 나오는데,

$ vagrant ssh-config --host [호스트 명] >> ~/.ssh/config
이렇게 해두면

$ ssh [호스트 명]
으로 접속 가능하다.

※ ssh 커맨드는 knife-solo같은 툴에서 기본적으로 사용하니 ssh로 로그인 할 수 있게 해두는게 좋다.

정지 / 부수기

$ vagrant halt #정지
$ vagrant destory #부수기

일단 이렇게 해서 한번 설정을 해두면, 2번째 부터는 VagrantFile이 있는 디렉토리에 들어가서 vagrant up만 해주면 된다.

다른 가상 머신을 만들어 보려면

  1. 임의로 폴더를 만들고
  2. vagrant init를 실행하고
  3. Vagrantfile의 네트워크 설정을 변경해주고
  4. vagrant up
  5. vagrant ssh-config --host [별칭] >> ~/.ssh/config 로 ssh설정해주기
  6. vagrant sshssh [별칭]으로 게스트OS에 접속 가능.

$ mkdir sandbox
$ cd sandbox
$ vagrant init
$ vi Vagrantfile #네트워크 쪽 설정 수정하기.
$ vagrant up
$ vagrant ssh-config --host box >> ~/.ssh/config