Archive for June, 2013

auth.log가 quantum agent가 수행하는 sudo 로그로 꽉 찼어요..

어제 시스템 팀에서 연락이 왔습니다. /var/log/auth.log에 아래처럼 지속적으로 quantum-agent가 남기는 로그가 남는다구요.

Jun 23 06:33:26 network sudo: pam_unix(sudo:session): session opened for user root by (uid=106)
Jun 23 06:33:26 network sudo: pam_unix(sudo:session): session closed for user root
Jun 23 06:33:26 network sudo: pam_unix(sudo:session): session closed for user root
Jun 23 06:33:26 network sudo: quantum : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf ovs-vsctl --timeout=2 get Interface tapae222d3c-61 external_ids
Jun 23 06:33:26 network sudo: pam_unix(sudo:session): session opened for user root by (uid=106)
Jun 23 06:33:26 network sudo: quantum : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/usr/bin/quantum-rootwrap /etc/quantum/rootwrap.conf ovs-vsctl --timeout=2 get Interface tapae222d3c-61 external_ids

음.. 그렇군 하면서 보니까 /var/log/auth.log에는 로그가 정신없이 쌓이고 있군요. 한 호스트에 일주일에 쌓인 로그가 약 500M 정도입니다. 한 호스트에 이정도이니 다른 quantum-agent가 동작중인 network, compute 노드를 합치면.. 헐... 이 녀석을 처리하기로 했습니다. 당연히 모든 sudo의 로그를 날릴 수 없고, quantum agent가 날리는 sudo 명령만 없에기로 했습니다.

/var/log/auth.log는 어디서 생기느냐.. 당연히 아시겠지만 syslog가가 auth,authpriv.*인 내용만 골라서 분리한 내용입니다. Ubuntu의 경우는 rsyslog를 사용하기 때문에 /etc/rsyslog.d/50-default.conf에 정의되어 있지요.

auth,authpriv.*                 /var/log/auth.log

즉... 어디선가 syslog로 날리는 저 내용을 없애면 되는 것이죠.

로그 내용을 보면

  1. sudo에서 이용하는 pam의 세션이 열리고 닫혔다.
  2. sudo로 수행하는 명령은 어떤 것이다.

입니다. 첫번째 로그와 두번째 로그를 날리는 주체는 다릅니다. 첫번째는 pam.d, 두번째는 sudo...

두번째는 간단합니다. /etc/sudoers.d/quantum_sudoers에서 아래 라인을 추가하면 됩니다.

Defaults        logfile=/var/log/sudo.log
Defaults        !syslog

내용 보면 간단하죠? syslog로 로그를 남기지 않고 /var/log/sudo.log로 남깁니다. 그래서 /var/log/authl.log에 로그가 가지 않습니다.

여기까지 하고 /var/log/auth.log를 보면 여전히 세션이 열리고 닫힌 기록이 계속 남습니다. 이는 pam.d에서 해 줘야하는 것이죠. 그래서 /etc/pam.d/sudo를 보면

@include common-auth
@include common-account
@include common-session-noninteractive

이렇게 나와있습니다. 세션에 관련딘 내용은 세번째 줄 같죠? 맞습니다. 조금 긴 내용이 나옵니다. 여기서 잠깐 위의 로그 파일을 자세히 보면 ...

Jun 23 06:33:26 lion034 sudo: pam_unix(sudo:session): session closed for user root

뭔가 보이나요? 그렇죠.. pam_unix라는 곳에서 로그를 남기고 있다고 친절하게 알려주고 있습니다. 다시 pam_unix 관련된 라인이 있는지 찾아보면

session required        pam_unix.so

라고 친절히 있습니다. 그렇습니다.. 여기서 뭔가 해줘야 하겠는데.. 어떤게 있을까 하고 뒤져보니깐... 방법이 아주 간단히  있더군요.

session [success=1 default=ignore] pam_succeed_if.so service in sudo quiet use_uid
session required        pam_unix.so

자세한 내용은 모르겠고, sudo service에서 성공한 인증은 로그를 무시하라는 이야기 이군요.

자... 여기까지 하면... 그렇게 많이 쌓이던 로그가 갑자기 없어지는 신기한 경험을 합니다~~ ㅎ~

그리고 마지막으로 quantum sudo log를 /var/log/sudo.log로 보낸 것 기억하시죠? 이것까지 마무리 하면 되겠습니다.

/etc/logrotate.d/sudo:

/var/log/sudo.log {
    daily
    missingok                                                                           
    compress
    delaycompress
    notifempty
}

추가) 이런 방법 말고 rsyslog에서 필터링 하는 방법도 있군요. /etc/rsyslog.d/50-default.conf의 시작 부분에 다음을 추가합니다.

:msg, contains, "uid=106"
& ~

:msg, contains, "ovs-vsctl"
& ~

참고:


OpenStack: block migration

잘 알고 있다시피.. live migration을 하려면 shared storage(NFS, DFS...)가 필요합니다. 근데 share storage는 필연적으로 local storage에 비해서 느릴 수 밖에 없습니다. 그렇지요.

그리고 live migration은 OpenStack 시스템 유지/ 보수를 위해서도 필요합니다. 호스트 머신의 업그레이드가 필요할 때, 호스트 머신에 뭔가 작업을 할 때, 해당 호스트에서 서비스되는 인스턴스를 다른 곳으로 옮기고 작업해야하니깐요...

위에 언급했다시피, live migration은 shared storage가 필요하고, 이를 위해서는 IO를 일정부분 포기해야하는 경우가 생겨서, 이를 어떻게 만회할까하고 여기저기 뒤져보다가... block migration 기능이 있다는 것을 알았습니다.

live migration은 다른 호스트로 메모리만 복사하는 반면에 block migration은 메모리와 블럭 디바이스(인스턴스 스토리지, 볼륨 스토리지)도 같이 대상 호스트로 복사합니다. 결국 live migration이 조금 느린 반면에 shared storage가 필요 없어서, 유지보수를 위한 migration에는 사용할 수 있을 것 같습니다. 물론 갑작스런 호스트 머신의 오류일 경우에는 해당 사항이 없겠습니다.

사용방법은 간단합니다. 기존의 live migration 명령에 --block_migration 옵션만 붙이면 됩니다. 즉, 아래와 같죠.

$ nova live-migration --block_migrate

이를 위한 OpenStack 설정은 live migration 문서처럼 설정하고, 추가로 /etc/nova/nova.conf에 아래처럼 block_migration_flag를 설정합니다.

block_migration_flag= \
        VIR_MIGRATE_UNDEFINE_SOURCE, \
        VIR_MIGRATE_PEER2PEER, \
        VIR_MIGRATE_NON_SHARED_INC, \
        VIR_MIGRATE_LIVE

별 문제 없으면 잘 될겁니다. live migration이 필요했지만, shared storage가 준비되지 않으신 분들.. 한번 써 보세요~

그리고 추가로 OpenStack에서 migration에 대해서 간단히 정리합니다.

(True) live migration

shared storage를 사용하는 경우, instance의 memory만 대상 호스트로 복사하여 live migration을 수행합니다. 당연히 shared storage(NFS, GlusterFS, CephFS...)가 필요합니다.

메모리만 복사하므로 수초내에 migration이 완료됩니다.

$ nova live-migration <instance> <dest host>

참고) shared storage를 사용할 경우, live migration을 사용하기 위해서 disk cache를 disable 해야합니다. file 또는 ceph를 사용할 경우는 이 설정이 자동으로 들어가지만,  GlusterFS를 instance directory에 mount해서 사용할 경우 disk cache를 disable하는 것이 동작하지 않습니다. 따라서 glusterfs를 사용할 경우는 live_migration_flag를 아래처럼 VIR_MIGRATE_UNSAFE를 추가합니다.

live_migration_flag = \
        VIR_MIGRATE_UNDEFINE_SOURCE, \
        VIR_MIGRATE_PEER2PEER, \
        VIR_MIGRATE_LIVE, \
        VIR_MIGRATE_UNSAFE

block migration

live migration에 추가로 스토리지도 복사합니다. 약간 느리지만 live migration의 장점과 local storage의 IO의 장점을 동시에 취할 수 있습니다. 그리고 qemu에서 제공되는 기능을 사용하기 때문에 별도의 설정은 필요 없습니다.

$ nova live-migration --block_migrate <instance> <dest host>

migration

이건 live migration이 아니고, instance shutdown --> disk image copy --> instance boot 과정을 거침니다. 당연히 해당 호스트는 리부팅 됩니다. 그리고 migration이 되는 호스트는 scheduler에 의해서 자동으로 선택됩니다

$ nova migrate <instance>

block migration은 다른 호스트로 복사하는 기능을 qemu의 기능을 사용하므로 별도의 설정이 필요없었지만, migrate는 qemu나 libvirt의 기능을 사용하지 않고 수동(^^)으로 ssh를 이용하여 복사하기 때문에, 이동하려는 nova compute 노드에 nova 유저로 ssh login이 아무런 장애없이 되야됩니다. 또한 ubuntu로 설치했다면 nova 계정의 login shell이 /bin/false로 되어있는데 /bin/bash로 수정합니다. 결과적으로 compute에서 다른 compute로 아래 명령을 수행했을 때 오류가 없어야 합니다(아직까지 문서에 없음^^).

root@compute01:~# sudo -u nova ssh compute02 hostname
compute02
  • ssh public key authentication
  • ssh host key 등록

ps. 예상대로라면 volume을 붙인 인스턴스에서는 볼륨은 굳이 복사할 필요가 없으므로 volume이 없는 인스턴스와 block migration 성능 차이가 없어야 하는데도, 이상하게 volume이 붙어있는 인스턴스는 느리군요.. 이거 왜 이럴까요?

ps. 약간 알콜이 들어간 상태에서 쓴 글이라... 오타 작렬.. 논지도 왔다갔다... ㅎㅎ


chef: definition과 notifies

Chef Definition은 아주 간단하게 Resource를 만들 수 있습니다. 아래 코드를 보면 간단하게 ~/.ssh/authorized_keys를 설정하는 Resource를 만들 수 있지요

define :authorized_keys_for, :keys => nil, :group => nil, :home => nil do

  user  = params[:name]
  group = params[:group] || user
  home  = params[:home]  || "/home/#{user}"
  keys  = params[:keys].kind_of?(String) ? [params[:keys]] : params[:keys]

  if not keys.nil? and not keys.empty?
    directory "#{home}/.ssh" do
      owner user
      group group
      mode 0700
      action :create
      only_if "test -d #{home}"
    end

    file "#{home}/.ssh/authorized_keys" doㅁㄴ
      owner user
      group group
      content keys.map{ |x| x.strip }.join("\n")
    end
  end
end

뭐.. 간단한 일이면 이런 거 사용하면 됩니다. 저도 별 무리 없이 사용하고 있다가.. 여기서 notifies를 걸여줘야할 것이 생겼습니다. authorized_keys를 설정한 이후에 뭔가를 하려는 것이지요. 그래서 뭐 그냥 단순하게.. 아래처럼 했습니다...

authorized_keys_for charlie do
  keys ''
  notifies :create "ruby_bloc[foo]"
end

ruby_block "foo" do
  block do
    # do something with ruby
  end
  action :nothing
end

예.. 예상하시는데로.. 아무런 문제 없이 잘 될거라고 생각했지만, 역시나 안되었습니다(그러니까 이 글을 적고 있겠지요). 뭘까 뭘까? 하면서 다시 위 링크에 있는 문서를 다시 봤습니다.

A definition is not a resource or a lightweight resource

녜.. definition은 resource가 아닙니다. notifies나 subscribes는 resource에만 동작합니다. 그러니 아무리해도 안되지요... definition은 진짜로 C언어의 #define 처럼 동작하는 녀석인가 봅니다. ㅎㅎ


keystone token이 너무 많아요..

지난 일주일간 회사 워크삽으로 자리를 비웠다. 그 동안 단 한번도 노트북을 켜지 않았으니, 이거 참 대대한 일인 듯 하다. 작년 휴가에도 중간에 콜 받아서 노트북 켠 경험이 있는데 말이다...

각설하고.. 어쨌든 오늘 출근해서, 그래 내가 뭘 하고 있었던 거지? 하면서 설치된 오픈스택 구성을 둘러보려고, 딸랑 nova list 명령을 치는데, 이녀석이 먹통이다... 아무런 에러로 안뱉어내고 그냥 조용이 가만히 있는다.

이전에도 비슷하나 경험이 있었지만, 그때는 대충 넘어갔었지만, 들은 것도 있어서 뒤져봤는데 역시나... keystone의 token table에 데이터가 많이 쌓었나 보다.

mysql> select count(*) from token;
+----------+
| count(*) |
+----------+
|    20916 |
+----------+
1 row in set (25.17 sec)

뭐.. 개인 테스트 환경이고 해서, 무식하게 다 지우고 하니 nova list 명령이 잘 된다. 대략  들은 적이 있다. 각 호스트들의 agent들이 api를 수행할 때, 모두 keystone 인증 토큰을 발급 받는데, 이 토큰들이 계속 누적되어서 문제를 발생하는 것이다. 우선 간단하게 expire된 token을 날려버리는 것도 좋겠다.

mysql> delete from token where expires < current_timestamp 

근데 저 정도의 숫자로  MySQL의 성능 이슈에  걸리는 것도 이상한 것이다. MySQL 튜닝 문제인 것 같다. token을 보면 primary key를 지외하고는 인덱스를 잡지 않았으며, 쿼리에 맞게 인덱스를 추가하면 되겠다.

 # Query_time: 77.709733  Lock_time: 0.000087 Rows_sent: 0  Rows_examined: 20919 use keystone; SET timestamp=1371436405; SELECT token.id AS token_id, token.expires AS token_expires, token.extra AS token_extra, token.valid AS token_valid, token.user_id AS token_user_id, token.trust_id AS token_trust_id FROM token WHERE token.expires > '2013-06-17 02:32:08' AND token.valid = 0;

그냥 무식하게 DELETE 하기 전의 token 테이블에 걸린 slow query를 보면 위와 같은데... expires, valid에 index를 걸어주면 좀 더 빠른 실행이 가능하지 않을까?

mysql> explain select id from token where expires > '2013-06-17 02:32:08' AND token.valid = 0;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | token | ALL  | NULL          | NULL | NULL    | NULL |  492 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> create index idx_token_expires_valid on token(expires, valid);
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select id from token where expires > '2013-06-17 02:32:08' AND token.valid = 0;
+----+-------------+-------+-------+-------------------------+-------------------------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys           | key                     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+-------------------------+-------------------------+---------+------+------+--------------------------+
|  1 | SIMPLE      | token | index | idx_token_expires_valid | idx_token_expires_valid | 10      | NULL |  492 | Using where; Using index |
+----+-------------+-------+-------+-------------------------+-------------------------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

explain에 보듯이, 해당 slow query는 index를 타고 있다. 이제 일주일 후에도 같은 증상이 발생하는지 확인해보자..

추가) 그리고 어떤 녀석이 이런 token을 무지막지하게 만들어 내는지 확인해볼 필요가 있다.

mysql> select user_id, count(*) from token group by user_id;
+----------------------------------+----------+
| user_id                          | count(*) |
+----------------------------------+----------+
| 36068019a00e427c8c8e97e8a3cee8a2 |        1 |
| 5700bfc6b03b476f97021e5eede7989e |        4 |
| 8232fea985ff44c0be44b0473cac5fac |      557 |
+----------------------------------+----------+
3 rows in set (0.02 sec)

위 처럼 특정 user_id에 의해서 집주적으로 토큰이 발생하는 것을 확인할 수 있으며

mysql> select id, name from user;
+----------------------------------+---------+
| id                               | name    |
+----------------------------------+---------+
| 5700bfc6b03b476f97021e5eede7989e | admin   |
| f09f583150f24c72a3a3ef1e1b12ae7d | cinder  |
| 8152fd3ea78a477eb096e829aa2e0bce | demo    |
| dcabff792209441794a4256f6611f43e | glance  |
| 36068019a00e427c8c8e97e8a3cee8a2 | nova    |
| 8232fea985ff44c0be44b0473cac5fac | quantum |
+----------------------------------+---------+
6 rows in set (0.00 sec)

처럼 quantum 서비스에 의해서 발생됩니다. quantum의 plugin 들이지요.

update 1) 저 무지막지한 토큰은 quantum에 의해 발생하는 것이 아니라, nova 서비스에서 quantum을 사용하면서 keystone token을 재사용하지 않아서 발생하는 문제입니다. 소스는 잊어버렸...

update 2) Launchpad에 버그가 등록되어 있습니다.

update 3) 이 문제를 해결하는 가장 간단한 방법은 token driver를 memcache로 변경하는 것이다.

[token]
driver = keystone.token.backends.memcache.Token

ceph as OpenStack instance storage backend

이 전 포스트에서 GlusterFS를 instance storage backend로 사용했었습니다. Ceph는 GlusterFS에 비해서 콤포넌트도 많고, 설치 과정도  복잡해서 "보여서" 우선 GlusterFS로 했었지요. 이번에는 Ceph로 live migration을 할 수 있게 instance storage backend로 설정해 봤습니다.

GlusterFS와 다르게 Ceph는 swift, {nova,cinder}-volume과 통합도 준비되어 있지만, 현재 목적에 맞지 않기에 여기서는 다루지 않습니다.

Overview

설치 전에 우선 Ceph의 구성을 알아보면, mon, mds, osd 세가지 프로세스로 구성되어 있으며, 각각의 기능은 대략 아래와 같습니다.

  • mon: cluster의 상태등의 데이터를 관리
  • mds: CephFS에 제공하는 메타정보 데이터 관리
  • osd: 데이터 저장, replication, recovery 등을 제공하고, mon 프로세스에 모니터링 정보를 제공

Ceph를 instance storage backend로 사용하기 위해서는 glusterfs와 마찬가지로 /var/lib/nova/instance 디렉토리를 cephfs로 마운트하여 사용합니다. qemu에서 librbd를 이용하여 직접 Ceph를 접근할 것으로 예상했지만 {nova,cinder}-volume은 문서상에 librbd를 이용하도록 나와있는 반면에, instance storage의 경우는 별도의 안내가 없습니다(제가 못찾은건지 모르겠지만....).

또한 ceph cluster를 별도로 구성하는 것을 권장하지만, 실험 환경이기 때문에 compute 노드에 osd를 glance 노드에 mon, msd를 구성하기로 합니다.

참고로 권장하는 최소 구성은 아래와 같습니다.

  • (mon + mds) x 3
  • osd x 3

권장은 저렇고, 제 테스트 환경에서는 충분한 노드가 없기 때문에 glusterfs 경우처럼 compute node에 osd를 glance 노드에 mon + mds, 그리고  control 노드에 ceph-deploy를 준비합니다.

설치 준비

Ceph의 설치는 ceph-deploy를 이용합니다. 이전 버전에서는 mkcephfs 등의 툴을 이용했었지만, 이제는 ceph-deploy를 이용해서 셋업합니다. ceph-deploy는 ssh로 설치하려는 노드에 접속하여 sudo를 통해 패키지 설치, 설정 등을 자동으로 진행합니다. chef, puppet, juju등 자동화 툴로 설치할 필요가 없다고 설명하고 있습니다.

ceph-deploy를 실행할 노드를 ceph admin 노드라고하고, 여기에서는 아래 준비가 필요합니다.

  • ceph 계정 만들기
  • ceph 계정의 private / public key 만들기
  • ceph 패키지 설치

ceph가 설치될 mon, mds, osd 가 실행될 노드에는 아래의 준비가 필요합니다.

  • ceph 계정 만들기
  • ceph 계정의 sudo 허용
  • admin 노드에서 생성된 public key로 접속 허용
  • ceph 패키지 설치: ceph-deploy가 패키지 설치를 하지만, 미러를 사용한다면 직접 설치를..

ceph 패키지 설치: 모든 노드

$ wget -q -O- 'https://ceph.com/git/?p=ceph.git;a=blob_plain;f=keys/release.asc' | sudo apt-key add - 
$ echo deb http://ceph.com/debian-cuttlefish/ $(lsb_release -sc) main | sudo tee /etc/apt/sources.list.d/ceph.list
$ apt-get install ceph

ceph 유저 생성: 모든 노드

$ useradd -m ceph

sudoer에 등록: 모든 노드

ceph-deploy는 ssh로 ceph@node로 들어가서 sudo를 이용하여 설정을 하기 때문에 sudoer에 등록한다.

$echo "ceph ALL = (root) NOPASSWD:ALL" | sudo tee /etc/sudoers.d/ceph

ceph keypair 생성: admin 노드

$ su - ceph
$ ssh-keygen -t rsa -q -f /home/ceph/.ssh/id_rsa -P ""

ceph-deploy가 실행할 환경 설정

여기서 생성된 /home/ceph/.ssh/id_rsa.pub 파일을 모든 노드에 /home/ceph/.ssh/authorized_keys로 복사한다. 그리고 admin 노드의 ssh 설정을 아래처럼 하여 ssh hostname으로 ceph 유저로 로그인할 수 있도록 한다. 몰론 ceph-deploy가 접속한 모든 노드 (mon, mds, osd)를 모두 등록한다.

$ more ~/.ssh/config
Host compute01
Hostname compute01.stack
User ceph

....

그리고 처음으로 ssh로 연결하면 ssh key 확인 메시지가 뜨는데, 이를 없애기 위해서 미리 아래처럼 ssh server public key를 등록한다.

$ ssh-keyscan compute01.stack >> .ssh/known_hosts

모든게 정상적으로 설정 되었다면 아래 명령을 내렸을 때 아무런 입력 없이 바로 실행이 되어야 한다.

$ ssh compute01 sudo ls /

cluster 생성

클러스터 생성은 monitor 노드의 호스트를 지정하여 시작합니다. 여기서는 glance 노드를 monitor, mds로 사용하기로 했으므로 아래처럼 합니다.

$ ceph-deploy -v new glance
$ ls
ceph.conf ceph.log ceph.mon.keyring

실행하면 지정한 모니터로 ceph.conf 파일과 ceph.mon.keyring 파일을 생성합니다. 아직까지는 설정 파일만 만든 상태입니다.

만든 설정 파일을 monitor 호스트로 복사하고, 서비스를 시작하는 명령은 아래와 같습니다.

$ ceph-deploy -v mon create glance
Deploying mon, cluster ceph hosts glance
Deploying mon to glance
Distro Ubuntu codename precise, will use upstart

monitor 호스트인 glance에서 프로세스를 보면 ceph-mon 프로세스가 돌아가는 것을 확인할 수 있다. 그리고 glance 호스트에 보면 설정파일이 /etc/ceph/ceph.conf로 복사된 것을 확인할 수 있으며 /etc/ceph/ceph.client.admin.keyring 으로 어드민 키링이 생성된 것을 확인할 수 있다.

gatherkey 명령으로 monitor에 생성된 키를 가져온다.

$ ceph-deploy -v gatherkeys glance
Checking glance for /etc/ceph/ceph.client.admin.keyring
Got ceph.client.admin.keyring key from glance.
Have ceph.mon.keyring
Checking glance for /var/lib/ceph/bootstrap-osd/ceph.keyring
Got ceph.bootstrap-osd.keyring key from glance.
Checking glance for /var/lib/ceph/bootstrap-mds/ceph.keyring
Got ceph.bootstrap-mds.keyring key from glance.

ceph.client.admin.keyring, ceph.bootstrap-osd.keyring, ceph.bootstrap-mds.kerying 파일을 가져왔다. 이 키들은 osd, mds에서 사용된다. 여기서 가저온 ceph.client.admin.keyring은 아래처럼 사용할 수 있다.

$ ceph -c ceph.conf -k ceph.client.admin.keyring mon stat
e1: 1 mons at {glance=10.100.0.8:6789/0}, election epoch 2, quorum 0 glance

mds 설치: admin 노드

mds는 cephfs를 사용(cephfs로 마운트)한다면 필요한 것으로, rbd를 사용한다면 설치할 필요는 없다. 우리는 /var/lib/nova/instance를 cephfs로 마운트해서 사용할 것이므로 mds를 설치한다.

마찬가지로 glance host에 설치한다.

$ ceph-deploy -v mds create glance
Deploying mds, cluster ceph hosts glance:glance
Distro Ubuntu codename precise, will use upstart
Deploying mds bootstrap to glance
Host glance is now ready for MDS use.
Deploying mds.glance to glance

역시 glance 호스트에 보면 ceph-mds 프로세스가 떠있는 것을 확인할 수 있다.

osd 설치

osd는 ceph에 저장되는 데이터가 실제로 저장되는 곳입니다. disk와 journal로 구성이 됩니다.

Disk는 block device 또는 directory이고, 별도의 디스크를 권장하지만, 여기서는 /ceph/disk 디렉토리를 사용하겠습니다. 그리고 디렉토리를 사용할 경우 btrfs 또는 xfs를 권장하고 있지만, 여기서는 그냥 기존 파일 시스템에 쓰겠습니다.

Journal은 SSD를 권장하지만, 그냥 파일로 /ceph/journal 을 사용하겠습니다.

따라서 osd 노드에서는 아래처럼 미리 디렉토리를 생성합니다.

$ mkdir -p /ceph/disk

이제 osd를 설치합니다.

$ ceph-deploy -v osd create compute01:/ceph/disk:/ceph/journal
Preparing cluster ceph disks compute01:/ceph/disk:/ceph/journal
Deploying osd to compute01
Host compute01 is now ready for osd use.
Preparing host compute01 disk /ceph/disk journal /ceph/journal activate True

패키지가 설정되고, /etc/ceph/ceph.conf 파일이 복사됩니다. 하지만 아직은 osd가 활성화되지는 않았고, 아래처럼 활성화합니다.

$ ceph-deploy -v osd activate compute01:/ceph/disk:/ceph/journal
Activating cluster ceph disks compute01:/ceph/disk:/ceph/journal
Activating host compute01 disk /ceph/disk
Distro Ubuntu codename precise, will use upstart

이제 ceph-osd 프로세스가 시작되었으며, 아래처럼 osd가 하나 등록된 것을 확인할 수 있습니다.

$ ceph -c ceph.conf -k ceph.client.admin.keyring osd stat
e5: 1 osds: 1 up, 1 in

그리고 osd 노드에서도 ceph 관련 명령을 수행할 수 있게 admin 키를 보냅니다.

$ ceph-deploy -v admin compute01
Pushing admin keys and conf to compute01

이 키가 있어야 아래처럼 osd 노드에서도 ceph 명령을 수행할 수 있습니다.

ceph@compute01:~$ ceph osd stat
e5: 1 osds: 1 up, 1 in

마찬가지로 compute02, compute03도 설치합니다.

instance 디렉토리 마운트

아래처럼 인스턴스 디렉토리를 마운트 합니다.

$ mount -t ceph 10.100.0.8:6789:/ /var/lib/nova/instances -o name=admin,secretkey=AQA+QrVRYNAnFhAAcN68f1a7xFqBzsSEqXQHmg==

10.100.0.8은 monitor 노드이고 secretkey는 /etc/ceph/ceph.admin.client.keyring에 있는 키를 사용합니다.

live migration

live migration 설정 및 방법은 glusterfs의 경우와 같습니다. 단 glustefs의 경우에는 VIR_MIGRATE_UNSAFE 옵션이 있어야 했지만, ceph의 경우는 해당 옵션이 없이 기본 값으로도 live migration이 됩니다.

$ nova show cirros1
+-------------------------------------+------------------------------------------------------------+
| Property                            | Value                                                      |
+-------------------------------------+------------------------------------------------------------+
| status                              | ACTIVE                                                     |
| updated                             | 2013-06-10T03:59:04Z                                       |
| OS-EXT-STS:task_state               | None                                                       |
| OS-EXT-SRV-ATTR:host                | compute02                                                  |
| key_name                            | admin                                                      |
| image                               | cirros-0.3.1-x86_64 (4f494d0b-ebdc-4ebd-8afc-8df804eaaf4e) |
| hostId                              | 4cf03b72c10726d78424eb6b1a62ddc4762cbbd1b148b8d684020c5b   |
| OS-EXT-STS:vm_state                 | active                                                     |
| OS-EXT-SRV-ATTR:instance_name       | instance-00000003                                          |
| OS-EXT-SRV-ATTR:hypervisor_hostname | compute01.stack                                            |
| flavor                              | m1.tiny (1)                                                |
| id                                  | a01a3bd7-6e49-485a-afc3-88c5b7c401d5                       |
| security_groups                     | [{u'name': u'default'}]                                    |
| user_id                             | 5700bfc6b03b476f97021e5eede7989e                           |
| name                                | cirros1                                                    |
| created                             | 2013-06-10T03:57:17Z                                       |
| tenant_id                           | 6f524cc90eb54f4b99ac70f3a3c070a7                           |
| OS-DCF:diskConfig                   | MANUAL                                                     |
| metadata                            | {}                                                         |
| admin network                       | 10.250.0.4                                                 |
| accessIPv4                          |                                                            |
| accessIPv6                          |                                                            |
| progress                            | 0                                                          |
| OS-EXT-STS:power_state              | 1                                                          |
| OS-EXT-AZ:availability_zone         | nova                                                       |
| config_drive                        |                                                            |
+-------------------------------------+------------------------------------------------------------+
$ nova live-migration cirros1 compute01
$ nova show cirros1
+-------------------------------------+------------------------------------------------------------+
| Property                            | Value                                                      |
+-------------------------------------+------------------------------------------------------------+
| status                              | ACTIVE                                                     |
| updated                             | 2013-06-10T04:03:03Z                                       |
| OS-EXT-STS:task_state               | None                                                       |
| OS-EXT-SRV-ATTR:host                | compute01                                                  |
| key_name                            | admin                                                      |
| image                               | cirros-0.3.1-x86_64 (4f494d0b-ebdc-4ebd-8afc-8df804eaaf4e) |
| hostId                              | beeddd176ef0ed6fdd0c7a04b376ee05dcda276e0596760ea021d649   |
| OS-EXT-STS:vm_state                 | active                                                     |
| OS-EXT-SRV-ATTR:instance_name       | instance-00000003                                          |
| OS-EXT-SRV-ATTR:hypervisor_hostname | compute01.stack                                            |
| flavor                              | m1.tiny (1)                                                |
| id                                  | a01a3bd7-6e49-485a-afc3-88c5b7c401d5                       |
| security_groups                     | [{u'name': u'default'}]                                    |
| user_id                             | 5700bfc6b03b476f97021e5eede7989e                           |
| name                                | cirros1                                                    |
| created                             | 2013-06-10T03:57:17Z                                       |
| tenant_id                           | 6f524cc90eb54f4b99ac70f3a3c070a7                           |
| OS-DCF:diskConfig                   | MANUAL                                                     |
| metadata                            | {}                                                         |
| admin network                       | 10.250.0.4                                                 |
| accessIPv4                          |                                                            |
| accessIPv6                          |                                                            |
| progress                            | 0                                                          |
| OS-EXT-STS:power_state              | 1                                                          |
| OS-EXT-AZ:availability_zone         | nova                                                       |
| config_drive                        |                                                            |
+-------------------------------------+------------------------------------------------------------+

아마도 이 영향인 것인지 live migration이 glusterfs에 비해서 약간 느리다는 인상을 받았습니다.

update) OpenStack 관련 문서에는 없지만, libvirtd 항목에 보면 rbd를 사용할 수 있습니다. 이건 나중에... ^^;


glusterfs as OpenStack instance storage backend

OpenStack에서 Live migration을 지원하려면 기본적으로 shared storage가 있어야 한다. 지금 요구사항 중의 하나가 장애에 대비한 live migration이라 shared storage를 설정해야했다.

요즘 대세는 Ceph이라고, 저번 오픈스택 모임에서 그랬는데, 잠깐 Ceph를 시도해본 결과, 설치과정이 그리 맘에 들지 않습니다. 그래요 완전히 개인적인 생각입니다.

그래서 상대적으로 쉬운 GlusterFS를 먼저 해보고려 합니다.

GlusterFS를 한다면 GlusterFS is Ready for OpenStack이라고 발표를 했는데, 문제는 아직 Beta 단계인 3.4 이야기이고, 자신들의 OpenStack Distribution인 RDO에 테스트 해 봤다는 이야기입니다.

내용을 보면 Instance Storage도 libgfapi를 이용해서 glusterfs에 직접 IO를 통해서 합니다. 그래서 중간의 파일 시스템에서 생기는 성능/ 캐쉬 등등의 문제를  없앴죠. Ceph도 그렇구요. 이거 제대로 된다면 바로 적용해 보려고 했지만... Ubuntu Package가 아직 없어요.. 그래서 정식 버전이 나오기 전에는 3.2에서 테스트 하기로 했습니다. 아고 서론이 길었어요.

Overview

테스트 환경에서는 별도의 glusterfs cluster를 구성하지 않고 glusterfs server는 compute node에 설치하기로 했습니다(아마도 별 문제 없으면 실제로도 그렇게 갈 생각이구요). 그리고 각 compute node는 /var/lib/nova/instance를 glusterfs localhost로 마운트 합니다.

Gluster FS 설치

간단히 각 compute node에서 설치합니다.

$ apt-get install glusterfs-server

Peer probe

$ gluster peer probe compute02.stack
$ gluster peer probe compute03.stack

Volume create

$ gluster volume create vm-instances replica 3 \
      compute01.stack:/gluster/instances \
      compute02.stack:/gluster/instances \
      compute03.stack:/gluster/instances

물론 각 compute node에는 만드려는 brick의 디렉토리인 /gluster/instance를 미리 만들어야합니다.

Volume start

$ gluster volume start vm-instances

마운트

마운트 하기 전에 아무런 인스턴스들이 생성되지 않은 상태로 합니다.

$ mount -t glusterfs localhost:vm-instances /var/lib/nova/instances

마운트하면 인스턴스 디렉토리의 소유권이 root.root가 되는데, nova.nova로 수정합니다. 신기하게도 이거 바꾸면 다른 노드도 같이 수정이 되는군요.

$ chown nova.nova /var/lib/nova/instances

한쪽 compute 노드에서 파일을 생성하면, 다른 컴퓨터 노드에도 같이 보이는 것을 확인할 수 있습니다.

nova.conf 설정

live migration을 하지 않는다면, 별도로 수정할 내용은 없습니다. 파일 권한이 제대로 되어있다면 바로 인스턴스를 생성 가능하고, 생셩된 인스턴스 파일은 다른 컴퓨트 노드에서 잘 보입니다.

live migration

Live Migration을 하려면 우선 OpenStack에 있는데로 설정합니다. 그런데 이 상태로 live migration을 하면 바로 아래처럼 오류가 발생합니다.

2013-06-03 11:52:20.743 11492 ERROR nova.virt.libvirt.driver [-] [instance: 4717b4d4-61a7-4f4d-b5fc-5ff526822e89] Live Migration failure: Unsafe migration: Migration may lead to data corruption if disks use cache != none

이것은 libvirt가 live migration을 할 때 안정성을 이유로 디스크 캐쉬가 된 상태에서는 live migration을 수행하지 않습니다. nova.conf에서 disk_modes=file=none,block=none 형태로 캐쉬를 안해주면 되겠지만, 이렇게 하고 하면 인스턴스를 생성할 때 부터 문제가 생깁니다. ㅎㅎ

그래서 불안정하게라도 live migration 하겠다고 하면 디스크가 캐쉬가 된 상태도 라이브 마이그레이션을 지원합니다. 이를 설정하면 nova.conf에 아래처럼 설정합니다.

live_migration_flag=VIR_MIGRATE_UNDEFINE_SOURCE, \
        VIR_MIGRATE_PEER2PEER, \
        VIR_MIGRATE_LIVE, \
        VIR_MIGRATE_UNSAFE

마지막의 VIR_MIGRATE_UNSAFE가 그것이죠.

어렇게 하고 live migration을 하면 잘 되는 것이죠.

root@control:~# nova show cirros1
+-------------------------------------+------------------------------------------------------------+
| Property                            | Value                                                      |
+-------------------------------------+------------------------------------------------------------+
| status                              | ACTIVE                                                     |
| updated                             | 2013-06-03T07:17:53Z                                       |
| OS-EXT-STS:task_state               | None                                                       |
| OS-EXT-SRV-ATTR:host                | compute01                                                  |
| key_name                            | admin_key                                                  |
| image                               | cirros-0.3.1-x86_64 (f81518a9-9dc2-4a2a-aeaf-331cc074d063) |
| hostId                              | a2b92d1a2237ab4772f395b2fde3e462bfad9420e0ffc33ad3d1a19d   |
| OS-EXT-STS:vm_state                 | active                                                     |
| OS-EXT-SRV-ATTR:instance_name       | instance-00000011                                          |
| OS-EXT-SRV-ATTR:hypervisor_hostname | compute01.stack                                            |
| flavor                              | m1.tiny (1)                                                |
| id                                  | 2991ad7d-b33e-4d3c-828b-da07338119f1                       |
| security_groups                     | [{u'name': u'default'}]                                    |
| user_id                             | 8f5b56a6a51c45338b0c1ba7cd7d9ebb                           |
| name                                | cirros1                                                    |
| created                             | 2013-06-03T06:21:27Z                                       |
| tenant_id                           | b5db61c3fa3845848b0f15c010dd500c                           |
| OS-DCF:diskConfig                   | MANUAL                                                     |
| metadata                            | {}                                                         |
| admin network                       | 10.250.0.2                                                 |
| accessIPv4                          |                                                            |
| accessIPv6                          |                                                            |
| progress                            | 0                                                          |
| OS-EXT-STS:power_state              | 1                                                          |
| OS-EXT-AZ:availability_zone         | nova                                                       |
| config_drive                        |                                                            |
+-------------------------------------+------------------------------------------------------------+

cirros1은 compute01에 있습니다. 이를 compute02로 옮긴다면..

root@control:~# nova live-migration cirros1 compute02

이제 compute02로 이사갔어요...

root@control:~# nova show cirros1
+-------------------------------------+------------------------------------------------------------+
| Property                            | Value                                                      |
+-------------------------------------+------------------------------------------------------------+
| status                              | MIGRATING                                                  |
| updated                             | 2013-06-03T07:18:59Z                                       |
| OS-EXT-STS:task_state               | migrating                                                  |
| OS-EXT-SRV-ATTR:host                | compute01                                                  |
| key_name                            | admin_key                                                  |
| image                               | cirros-0.3.1-x86_64 (f81518a9-9dc2-4a2a-aeaf-331cc074d063) |
| hostId                              | a2b92d1a2237ab4772f395b2fde3e462bfad9420e0ffc33ad3d1a19d   |
| OS-EXT-STS:vm_state                 | active                                                     |
| OS-EXT-SRV-ATTR:instance_name       | instance-00000011                                          |
| OS-EXT-SRV-ATTR:hypervisor_hostname | compute01.stack                                            |
| flavor                              | m1.tiny (1)                                                |
| id                                  | 2991ad7d-b33e-4d3c-828b-da07338119f1                       |
| security_groups                     | [{u'name': u'default'}]                                    |
| user_id                             | 8f5b56a6a51c45338b0c1ba7cd7d9ebb                           |
| name                                | cirros1                                                    |
| created                             | 2013-06-03T06:21:27Z                                       |
| tenant_id                           | b5db61c3fa3845848b0f15c010dd500c                           |
| OS-DCF:diskConfig                   | MANUAL                                                     |
| metadata                            | {}                                                         |
| accessIPv4                          |                                                            |
| accessIPv6                          |                                                            |
| admin network                       | 10.250.0.2                                                 |
| OS-EXT-STS:power_state              | 1                                                          |
| OS-EXT-AZ:availability_zone         | nova                                                       |
| config_drive                        |                                                            |
+-------------------------------------+------------------------------------------------------------+

Update: Andrew님의 제보에 의하면 3.2 버전에서는 파일 싱크할 때 파일이 read only로 걸려서 instance도 read lock이 걸리는 현상이 있다는군요. 3.3 부터는 OK


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