Archive for July, 2012

귀찮다. ssh 접속 키 확인 무시하자구!

테스트용으로 가상 머신을 많이 사용하다 보면... 가상 머신 안에서 IP가 중복됩니다.  지금 이 순간에도 제 VMWare에는 약 20개 정도가 생성되어있고, 8개가 running 중입니다.

이런 상황에서 귀찮은 것은 ssh로 접속할 때 ssh key fingerprint가 변경되었다느니... 서버의 핑커프린트를 저장할 것이라는둥 귀찮은 질문을 막 합니다. 귀찮아서 찾아봤더니 StrictHostsKeyChecking 옵션이 있군요. 이렇게 하면 간단하게 경고 메시지를 보이면서 서버 키를 무조건 저장합니다. 귀찮게 물어보는 것이 없어졌네요

$ ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null 10.200.1.10
Warning: Permanently added '10.200.1.10' (ECDSA) to the list of known hosts.

그리고 물론 .ssh/config 파일에 넣을 수 있습니다.

Host 10.200.*
        StrictHostKeyChecking no
        UserKnownHostsFile /dev/null

물론 실제 환경에서는 핑커 프린트가 변경된 경우는 뭔가 이상이 있는 거니 이런거 쓰지 말기 바랍니다.


gluster with chef #1

공부삼아서 Chef로 Gluster를 셋업하는 것(https://github.com/whitekid/chef-glusterfs) 해 봤는데, 역시나 공부삼아 코멘트 적어봅니다.

물론 당연히도 저는 Chef와 Ruby를 처음 다르기에 정석과는 많이 다를 수 있고, 여기에서 이야기하는 것들이 틀릴 수 도 있습니다. ㅎㅎ..

https://github.com/whitekid/chef-glusterfs는 chef에서 사용하는 cookbook입니다. cookbook 즉 요리책은 형상관리할 대상을 어떻게 요리할 지 적어 놓은 것이죠. 이 cookbook안에 recipe가 있으며, 이 recipe를 작성하여 하나의 인프라를 관리합니다.

recipes 디렉토리를 보시면 client.rb, server.rb, default.rb 라는 파일이 있습니다. 이게 recipe이며, 이것들이 여러개 모여서 glusterfs 클라이언트와 서버를 관리하는 cookbook이 되는 것이죠. 이름에서 보이다시피 client.rb는 glusterfs 클라이언트를 설치하고 서버와 연결하여 마운트하는 recipe이고, server.rb는 glusterfs 클러스터를 구성하고 volume을 생성하는 recipe입니다.

우선 간단한 recipes/client.rb부터 봅니다.

package "glusterfs-fuse" do
  action :install
end

여기서 ":install" 이 뭘까요?

저는 한참 고민했습니다. 엇듯 봐서는 method 같기도 하고, action이 method이면 :install은 parameter인 것 같기도 하고.. 처음에는 우선 그려러니 하고 넘어갔었는데, 찾아보니 :install은 문자열 "install"의 symbol이라고 합니다. 문자열 reference죠.

irb> :install.equal? :install
=> true

로 나옵니다. 여기서 equals?는 값 비교가 아닌 object 비교, 즉 같은 메모리를 점유하고 있는 오브젝트인가를 검사하는 것인데 같이 나오는 것으로 보면 같은 object이죠.

python의 immutable과 비슷하다고 봐야합니다. ruby symbol도 immutable입니다.

"Symbols are a way to represent strings and names in ruby."라 설명하고 있네요.

근데 그럼 action은 뭘까요? 이건.. attribute입니다. 즉 package 리소스의 action attribute를 "install"로 설정하는 것입니다.

package라는 리소스를 이용해서 gluster-fuse 패키지를 설치합니다. package는 각 chef node의 OS에 맞게 패키지를 설치합니다. 따라서 CentOS는 yum을 Ubuntu는 apt-get을 FreeBSD는 ports를 이용하여 설치를 합니다.

chef에서 사용되는 리소스는 opscode의 리소스 패이지(http://wiki.opscode.com/display/chef/Resources)를 보시기 바랍니다. 아주 자세히 설명되어 있습니다.

당연히 gluster-fuse는 CentOS에서 있는 패키지 이름입니다. 만일 Ubuntu를 사용한다면 다른 이름을 넣어주겠죠.

이렇게 각 노드의 특성에 따라서 달라지는 것들은 attribute에 설정합니다. 아마 attrbiute/default.rb 파일은 다음처럼 될 겁니다.

case platform do
  when "ubutu", "debian"
    default[:node][:gluster_client_package] = "gluster-client"
  when "centos", "redhat"
    default[:node][:gluster_client_package] = "gluster-fuse"
end

recipes는 아래처럼 사용합니다.

package node[:ntp][:gluster_client_package] do
  action :install
end

근데 이런 node 특성에 따른 설정을 attribute에서만 꼭 둬야하냐? 라고 말하면 recipe에 둬도 됩니다. 편하실대로 하는는 것이 좋겠습니다. 예전에 잠깐 듣기론 recipe에 넣는 것이 더 편하는 이야기를 들은 것 같아요.

클라이언트 패키지를 설치했으므로 glusterfs 클러스터에 마운트합니다. glusterfs 클러스터는 server recipe에서 셋업을 진행했고 attributes/server.rb에서 설정한 peer의 첫번째로 마운트 하도록 하겠습니다.

node[:glusterfs][:client][:mount].each do |volume, mount_to|  # ---- [1]
  if not File.directory?(mount_to)                      # ---- [2]
    directory mount_to do
      action :create
      recursive true
    end
  end

  # mount -t glusterfs -o log-level=WARNING,log-file=/var/log/gluster.log \
  #       10.200.1.11:/test /mnt
  server = node[:glusterfs][:server][:peers][0]
  mount mount_to do                                    # ---- [3]
    device "#{server}:/#{volume}"
    options "log-level=WARNING,log-file=/var/log/gluster.log"
  end
end

----[1] glusterfs의 볼륨은 여러개 있을 수 있습니다. 따라서 각각의 볼륨에 대해서 glusterfs 마운트를 진행합니다. recipes/server.rb에 아래처럼 array로 정의되어 있습니다.

default[:glusterfs][:server][:volumes] = ["test"]

array의 each를 이용하여 모든 element를 돌면서 주어진 코드 블럭을 수행합니다. ruby 스타일의 언어를 처음 접하면 어색하겠지만, for문과 같다고 보시면 됩니다.

for volume, mount in node['glusterfs']['client']['mount']:
    bla bla

python 스타일로 하면 위와 같은데.. python은 for 안의 실행하는 문장이 같은 for 문에 속하는 scope에 속하는 반면에, ruby에서는 do ~ end 가 코드 블럭이 되어서 each 함수의 파라미터로 전달이 되고 each 안에서 다시 호출되는 방식입니다. 아마도 javascript의 이벤트 핸들러를 작성해 봤다면 그것과 비슷하도고 보시면 됩니다.

----[2] 마운트 포인트 디렉토리가 없는 경우는 새로 만들어 줍니다. 디렉토리 생성은 directory라는 리소스를 통해서 생성하며 :create action으로 수행됩니다.

---- [3] mount 리소스를 이용해서 gluster 서버로 마운트 합니다. 위의 주석으로 달린 명령과 동일한 과정을 수행합니다.

그리고 어찌보면 요상한 "#{server}:/#{volume}" 문자열이 나오는데, sh로 치면 "${server}:/${volume}"과 동일하며 python으로 치면 "%s:/%s" % (server, volume)와 동일한 문자열 치환 입니다. python 스타일보다 훨씬 직관적으로 보기 좋습니다. 그렇다고 python "%{server}s:/%{volume}s" % locals() 가 있나고 하신다면.. 그래도 ruby style이 더 좋습니다..

음.. 대충 적으려고 계획했는데.. 글 재주도 없고 모르는 것 적으려니 이것저것 찾아보면서 해서 오래걸리네요.. 오늘은 이만하고 다음에 나머지 진행하겠습니다... 이거 참 하루 저녁 작업하고 설명하는데 몇일 걸리겠네요.. ㅡㅡ; 게다가 서버쪽은 더 복잡해 큰일군요.


초간단 Chef 설치하기

[toc]Ubuntu에서 Chef  초간단 설치하기 입니다.

About Chef

Chef는 1. 서버 형상 관리 툴 2. 서버 관리 자동화 툴 3. 요세는 클라우드 자동화 툴이라고도 합니다. puppet도 같은 비슷하죠.

Chef는 ruby로 작성되어 있으며, 작업하다보면 rails와 비슷하단 느낌을 많이 받습니다. 근데 저도 아직 잘 chef에 관해서 모릅니다. 공부하고 있는 단계죠. 어쨌든!

chef-server

레포지트리 설정

Ubuntu나 CentOS로 공식적으로 들어간 chef 패키지는 없고, 개발사인 opscode에서 관리하는 레포지트리를 사용합니다.

$ echo "deb http://apt.opscode.com/ `lsb_release -cs`-0.10 main" | sudo tee /etc/apt/sources.list.d/opscode.list

Repository PGP 키 추가

$ sudo mkdir -p /etc/apt/trusted.gpg.d
$ gpg --keyserver keys.gnupg.net --recv-keys 83EF826A
$ gpg --export packages@opscode.com | sudo tee /etc/apt/trusted.gpg.d/opscode-keyring.gpg > /dev/null

레포지트리 업데이트

$ sudo apt-get update

Chef 설치

$ sudo apt-get install chef-server
  • 설치하면서 URL을 물어보는데 http://<ip-address>:4040 으로 설정합니다. localhost로 설정하면 나중에 bootstrap으로 클라이언트 설치하는데 오류가 발생합니다.

knife 설정

knife는 chef를 움직이는 cli 툴입니다. 현재 계정(root가 아닌)에서 knife를 사용하여 명령을 내릴 수 있도록 설정합니다.

$ mkdir -p ~/.chef
$ sudo cp /etc/chef/validation.pem /etc/chef/webui.pem ~/.chef
$ sudo chown -R `whoami` ~/.chef
$ knife configuration -i
  • 인증서의 위치는 위에서 복사한 ~/.chef의 경로로 입력

knife 설치 확인

$ knife client list
$ knife cookbook list

클라이언트 설치(precise)

chef bootstrap은 Ubuntu 10.04를 지원하지만, 12.04(precise)를 지원하지 않습니다. 하지만 간단히 그냥 lucid를 precise로 바꾸기만 하면 됩니다. 물론 lucid를 이용하는 경우는 기존 것 그대로 이용하면 됩니다.

$ cd /usr/lib/ruby/vendor_ruby/chef/knife/bootstrap
$ cp ubuntu10.04-apt.erb ubuntu12.04-apt.erb
$ sed  -i 's/lucid/precise/g' ubuntu12.04-apt.erb
$ knife bootstrap 10.200.1.5 -d ubuntu12.04-apt --sudo -x <user_id> -P <password> --bootstrap-version 0.10
  • 10.200.1.5: chef-client를 설치할 호스트 아이피
  • -d: 배포판을 지정한다. lucid인 경우는 ubuntu10.04
  • --sudo: sudo를 이용해서 명령을 실행한다.
  • -x: ssh로 접속할 사용자를 지정한다. root 계정으로 직접 접근하지 못하는 서버들에 설정한다.
  • -P: ssh password
  • --bootstrap-version 0.10: bootstrap 설치할 버전

에러없이 잘 실행된다면

$ knife node list

로 해당 호스트가 등록된 것을 확인할 수 있습니다.

정상적으로 설치가 완료되었는데, 노드가 등록이 안되는 경우는 거의 대부분 시간이 안맞아서 그렇습니다. chef는 ampq를 사용하는데, 여기선 시간이 아주 중요하기 때문이지요. 시간이 안맞다면 ntpdate -u kr.pool.ntp.org 이렇게 시간이 중요하기 때문에 서버를 포함한 모든 노드는 ntpd를 설치하여 시간을 동기화하시기 바랍니다.

Cookbook 시작하기...

이제 Chef 설치는 잘 되었을 것이고, cookbook, knife등을 익힐 차례입니다. Cookbook Fast Start Guide에서 시작하기 바랍니다.

http://wiki.woosum.net/Chef


ubuntu: eth1에 기본 gateway 두기..

eth0, eth1이렇게 2개 NIC가 있는 상황에서 거의 기본으로는 eth0에서 public internet이 나가도록 설정이 될 겁니다. 대부분 그렇지요. 그런데 필요에 따라서는 eth1가 public internet인 경우가 있습니다. 그리고 eth0는 다른 목적으로 사용되는 경우로 말입니다.

이 경우 CentOS의 경우는 그냥 아무 생각없이 /etc/sysconfig/network-script/ifcfg-eth1에 설정하면 eth0 설정한거 무시되면서 eth1의 설정이 먹히는 데 Ubuntu의 경우는 안그럽니다.

auto eth2
iface eth2 inet static
    address 10.100.0.11
    netmask 255.255.255.0
    gateway 10.100.0.1

이렇게 두면 이녀석이 eth2의 gateway 설정을 알어먹지 못합니다. 그래서 수동으로 해 줘아합니다. 근데 수동으로하면 골치아프죠. 그럴땐 post-up, pre-down으로..

auto eth0
iface eth0 inet static
   address 10.200.1.11
   netmask 255.255.255.0
   dns-nameservers 168.126.63.1

auto eth1
    iface eth1 inet static
    address 10.100.0.11
    netmask 255.255.255.0
    post-up route add default gw 10.100.0.1
    pre-down route del default gw 10.100.0.1

이렇게 하면 되지요.



Screen session 저장?

제목이 영 이상하긴 한데요.. screen으로 작업하다보면 가끔 난감한 경우가 있습니다.

screen의 세션이 저 멀리 서버에 있어서 이 세션이 영원이 닫히지 않는다고 생각하면 별 문제 없을텐데, 이게 가끔 리부팅한다던가, 아니면 로컬에 있어서 리부팅하면 날라가는 경우.. .근데 이 세션들이 아주아주 자주 사용하는 경우 계속 세로운 세션 만드는 것 영 귀찮습니다.

저같은 경우는 개발, 테스트하면서 여러 서버들을 동시에 봐야해서, screen으로 여러개 움직이면서 작업하는데, 이거 참 날아가니깐.. 귀찮습니다.

뒤져보니 세션을 완전히 저장하고, 다시 살리는 방법은 없습니다. 하지만 가능한 방법은 screen.rc를 이용하여 그 서버에 연결되는 윈도우만 열어도 상당히 편리합니다.

screen.rc 파일을 적당히 만들고 screen -c screen.rc 로 그 세션을 시작하면 되죠..

screen.rc:

sessionname my-persistent-session

screen -t 'server01' sshpass -p <pass> ssh <server>
screen -t 'server01' sshpass -p <pass> ssh <server>

여기까지 하면 괜찮습니다. 그런데 사람의 욕심이라는게 말이죠. 위처럼하면 문제는 sshpass 명령이 종료되거나 ssh 연결이 안되면 해당 윈도우는 닫힌다는 것입니다. 이거 참 난감하죠.. 궁리해봤는데, screen 의 명령으로는 해결할 수 없고 아래처럼 ssh를 실행하는 스크립트를 만들어서 그걸로 연결하고, 해당 스크립트에서는 ssh 연결후 bash를 실행하면 됩니다.

bin/sshpass.sh:

#!/bin/sh
sshpass $1 $2 $3 $4
$SHELL

그러면, screen.rc의 내용도 바뀌겠죠?

screen.rc:

sessionname my-persistent-session

screen -t 'server01' sshpass.sh -p <pass&gt; ssh <server>
screen -t 'server01' sshpass.sh -p <pass&gt; ssh <server>

이제 screen -s screen.rc 하면 언제나 원하는 윈도우를 연 스크린으로... ㅎㅎ

물론 더 좋은 방법 있으면 알려주삼~~


  • Copyright © 1996-2010 Your wish is my command. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress