CephのOSD毎のPlacement Groupの数を確認する


Cephのテスト環境を構築してみた。

シナリオ通りに構築を進めていき、とりあえずは問題なくは終わった。
終わったんだけど、最後にステータスでも確認してみるかとceph healthを実行してみたところHEALTH_WARNが・・・

[root@ceph01 ~]# ceph health
HEALTH_WARN too many PGs per OSD (480 > max 300)
[root@ceph01 ~]#

OSDにたくさんのPGが割り当てられてる、といってるけど、具体的にはどれくらいあるんだろう?

と調べていくと、stackoverflowにある、下記のPGとOSDの関係性に関する質問を発見
Ceph too many pgs per osd: all you need to know

そこで紹介されている「Get the Number of Placement Groups Per Osd」に、OSD毎のPG数をコマンドで確認する手法が掲載されていた。

「ceph pg dump」の出力結果を整形して見やすいようにしている、というものだった。

ceph pg dump | awk '
BEGIN { IGNORECASE = 1 }
 /^PG_STAT/ { col=1; while($col!="UP") {col++}; col++ }
 /^[0-9a-f]+\.[0-9a-f]+/ { match($0,/^[0-9a-f]+/); pool=substr($0, RSTART, RLENGTH); poollist[pool]=0;
 up=$col; i=0; RSTART=0; RLENGTH=0; delete osds; while(match(up,/[0-9]+/)>0) { osds[++i]=substr(up,RSTART,RLENGTH); up = substr(up, RSTART+RLENGTH) }
 for(i in osds) {array[osds[i],pool]++; osdlist[osds[i]];}
}
END {
 printf("\n");
 printf("pool :\t"); for (i in poollist) printf("%s\t",i); printf("| SUM \n");
 for (i in poollist) printf("--------"); printf("----------------\n");
 for (i in osdlist) { printf("osd.%i\t", i); sum=0;
   for (j in poollist) { printf("%i\t", array[i,j]); sum+=array[i,j]; sumpool[j]+=array[i,j] }; printf("| %i\n",sum) }
 for (i in poollist) printf("--------"); printf("----------------\n");
 printf("SUM :\t"); for (i in poollist) printf("%s\t",sumpool[i]); printf("|\n");
}'

これをテスト環境で実行してみると下記の様な出力を得られた

[root@ceph01 ~]# ceph pg dump | awk '
BEGIN { IGNORECASE = 1 }
 /^PG_STAT/ { col=1; while($col!="UP") {col++}; col++ }
 /^[0-9a-f]+\.[0-9a-f]+/ { match($0,/^[0-9a-f]+/); pool=substr($0, RSTART, RLENGTH); poollist[pool]=0;
 up=$col; i=0; RSTART=0; RLENGTH=0; delete osds; while(match(up,/[0-9]+/)>0) { osds[++i]=substr(up,RSTART,RLENGTH); up = substr(up, RSTART+RLENGTH) }
 for(i in osds) {array[osds[i],pool]++; osdlist[osds[i]];}
}
END {
 printf("\n");
 printf("pool :\t"); for (i in poollist) printf("%s\t",i); printf("| SUM \n");
 for (i in poollist) printf("--------"); printf("----------------\n");
 for (i in osdlist) { printf("osd.%i\t", i); sum=0;
   for (j in poollist) { printf("%i\t", array[i,j]); sum+=array[i,j]; sumpool[j]+=array[i,j] }; printf("| %i\n",sum) }
 for (i in poollist) printf("--------"); printf("----------------\n");
 printf("SUM :\t"); for (i in poollist) printf("%s\t",sumpool[i]); printf("|\n");
}'
dumped all in format plain

pool :  4       5       6       7       8       9       10      11      12      13      14      1       2       15      3       | SUM
----------------------------------------------------------------------------------------------------------------------------------------
osd.4   39      29      25      36      27      24      35      34      30      28      34      33      35      29      32      | 470
osd.5   36      35      28      31      21      29      27      37      37      30      32      36      37      27      37      | 480
osd.6   38      37      30      35      30      24      37      33      32      31      27      32      33      31      27      | 477
osd.7   33      34      30      31      25      34      35      42      32      33      21      30      31      28      33      | 472
osd.8   29      32      39      35      28      39      31      34      36      35      38      34      35      24      21      | 490
osd.9   32      34      33      33      37      38      39      27      30      31      28      29      27      26      26      | 470
osd.10  39      31      34      24      35      36      35      40      34      37      37      45      32      31      37      | 527
osd.11  25      26      30      33      36      42      27      30      42      31      28      32      28      35      31      | 476
osd.0   27      39      38      29      35      24      34      26      28      31      38      23      33      31      32      | 468
osd.1   29      30      29      28      43      24      34      30      22      34      30      37      34      44      29      | 477
osd.2   27      32      35      33      31      38      21      24      30      26      37      26      26      36      33      | 455
osd.3   30      25      33      36      36      32      29      27      31      37      34      27      33      42      46      | 498
----------------------------------------------------------------------------------------------------------------------------------------
SUM :   384     384     384     384     384     384     384     384     384     384     384     384     384     384     384     |
[root@ceph01 ~]#

また、NAKAMURA Minoru’s Home Pageにある「RADOS の概略 (RADOS と CRUSH と Placement Group の関係)」は、Cephの理解に役に立った

OpenStack上の仮想インスタンスを物理サーバ間移動(マイグレーション)させる手法について


OpenStackで仮想インスタンスを動かしている場合に、物理サーバ間を移動させる手法について、いまいちまとまっているものがなかったので、メモ。

・物理サーバを指定して仮想インスタンスを起動
 → 不可能
  アベイラビリティーゾーン(availability-zone)というサーバをまとめたグループ(雑な表現)を指定して
  起動することまでしかできない

・仮想インスタンスを稼働中に物理サーバを移動させる
 → 可能
 例えば起動ディスクを含めcinderボリュームを使っている場合、下記コマンドで実施できる

# openstack server migrate --live 移動先ComputeNote --block-migration 仮想インスタンスUUID --wait

「migrate」と「migration」の2つの単語が混じっているので、惑わされないこと。

 上記だと、移動が終わるまでコマンドが終了しない。「–wait」を抜いた場合、下記の様な形でマイグレーションの進捗状況を確認することが出来る

# openstack server migrate --live 移動先ComputeNote --block-migration 仮想インスタンスUUID
# nova server-migration-list
# nova server-mgirationshow 仮想インスタンスUUID マイグレーション番号

「openstack sevrer show 仮想インスタンスUUID」では進捗のパーセンテージのみ確認可能。
それに対して、「nova server-mgirationshow 仮想インスタンスUUID マイグレーション番号」では、全体で何バイト転送する必要があり、現在何バイト転送が終了しているか、といった詳細を確認することができる。

参考資料
 nova Migrate instances
 nova Live-migrate instances

・止まってる物理サーバ上にあった仮想インスタンスを他の物理サーバで起動させる
 → nova evacuateコマンドで可能

# nova evacuate 仮想インスタンスUUID 移動先ComputeNode

nova evacuateは、元々起動していた物理サーバ上の「nova-compute」と通信が取れない場合に実行できる。
nova-computeと通信が取れる状態だとエラーになる・・・無理矢理実行したいのであれば、該当サーバ上のnova-computeを落とせばできなくもない。

参考資料
 nova Evacuate instances
 nova Recover from a failed compute node

・ERRORステータスになっててmigrateが出来ない
「nova reset-state 仮想インスタンスUUID」を実行することで、ステータスがリセットできる。

参考資料
 nova Troubleshoot Compute