2012年06月06日

iPXE を導入した記念に blog を書いてみたけど、タイトルが悩ましいので、この記事のタイトル募集中!

はてなブックマークに登録

PXEと同じネットワークブートファームウェアの一つであるiPXE(gPXE)を実運用に取り入れてみたので、今回はiPXE(gPXE)を紹介していきたいと思います。

(自分の書いたタイトルはダメ出しされたので、募集することにしてみました(^^;;記事を読んでいただいて、もし、よいタイトルを思いついたら、ぜひ、コメントにでもお願いしますm(_ _)m。次回のタイトルに使わせていただくかも(^^)

  • PXEとは、ネットワークブートのための仕組みの1つ。NIC上のフラッシュROM に書き込まれている。ネットワークブートに必要なファイルの取得には、DHCPとTFTP を用いる
  • iPXE(gPXE)とは、PXEを拡張したオープンソースなネットワークブートファームウェア/ローダ

iPXE(gPXE)には、下記のような特徴があります。

  • MACアドレスの他にもサーバのDMI情報を取得できる
  • コマンドが用意されていてそのコマンドで組んだスクリプトを利用可能
  • httpでのリクエストをサポートしている

つまり・・・

  • DMI情報を取得できるということは、そのサーバがどんな機種なのか分かる
  • スクリプトから取得した機種情報を使ったリクエストをすることができそう
  • http+cgiで、リクエストに応じて動的にレスポンスを返すことができそう

どうでしょう。試してみたくなりませんか?
ではでは、これから、実際にiPXEを触っていくとしましょう。

iPXE(gPXE)の紹介

gPXEのほうがよく知られているかもしれませんが、gPXEの開発が止まり、その後釜として始まったプロジェクトがiPXEとなります。

本来は、PXEと同じくNICのROMに焼いて使用するようですが、そうすると、元からあるPXEは当然消えてしまいますし、数十台、数百台のサーバを運用している場合に、すべてのNICに適用するとしたら、気が遠くなりそうです。しかしながら、よくみてみると、PXEからiPXEをチェインロードできるとあります。この方法を使えば、NICのROMに手を加えることなく、iPXEを利用することができそうです。

iPXEを実際に起動してみて、触ってみよう

PXEからチェインロードする方法でiPXEを試しに起動させてみます。
ここでは、isc-dhcpd,tftpd,thttpd(cgiは、bashスクリプト)を使用し、設定は、以下のようになっているとします。
(ここでは、iPXE以外の細かい設定に関しては、割愛します)

・tftpd,thttpdサーバのIPアドレス
192.168.0.1

・tftpd,thttpdルートディレクトリ
/tftp/

・thttpdのcgiディレクトリ
/tftp/cgi-bin/

・iPXE関連ファイルの格納ディレクトリ
/tftp/iPXE/

まずは、PXEチェインロード用のバイナリであるundionly.kpxeを以下のページ内のリンクからDLし、/tftp/iPXE/undionly.kpxeに保存します。

http://ipxe.org/howto/chainloading

上記ページのリンク先に紹介されているように、DHCPの設定ファイルに以下のように記述を追加します。

  if exists user-class and option user-class = "iPXE" {
    filename "http://192.168.0.1/iPXE/boot.ipxe";
  } else {
    filename "iPXE/undionly.kpxe";
  }
  next-server 192.168.0.1;

filenameの値を、iPXEからのリクエストにはiPXEの起動用スクリプト(boot.ipxe)を返し、iPXE以外のリクエストにはiPXEをロードするためのundionly.kpxeを返すようにしています。
これにより、以下のような流れとなります。
PXE起動

iPXE(undionly.kpxe)を取得してロード

iPXE起動

起動用スクリプト(boot.ipxe)を取得してロード

boot.ipxeの内容を実行

/tftp/iPXE/boot.ipxeは、以下のように記述しておきます。

#!ipxe
imgfree
chain http://${next-server}/cgi-bin/boot_ipxe.cgi?type=${product:uristring}&mac=${mac}

boot.ipxeの中身の説明はとりあえず一旦おいといて、実際にマシンをPXEブートしてみると、以下のようになります。

Intel(R) Boot Agent GE v1.2.40                                                  
Copyright (C) 1997-2006, Intel Corporation                                      
                                                                                
CLIENT MAC ADDR: XX XX XX XX XX XX  GUID: xxxxxxxxxxxxxxxxxxxxxxxxxxx  
CLIENT IP: 192.168.0.xx  MASK: 255.255.255.0  DHCP IP: 192.168.0.1             
GATEWAY IP: 192.168.0.xx                                                       
PXE->EB: !PXE at 97CA:0070, entry point at 97CA:0106                            
         UNDI code segment 97CA:3F20, data segment 919C:62E0 (582-623kB)        
         UNDI device is PCI 07:00.0, type DIX+802.3                             
         582kB free base memory after PXE unload                                
iPXE initialising devices...ok                                                  

                                                                                
iPXE 1.0.0+ -- Open Source Network Boot Firmware -- http://ipxe.org             
Features: HTTP iSCSI DNS TFTP AoE bzImage ELF MBOOT PXE PXEXT Menu      
                                                                                
Press Ctrl-B for the iPXE command line...

iPXEがチェインロード起動されると、自動的にboot.ipxeを取得して実行となるのですが、インタラクティブモードに入ると、自動実行は行わず、手動でコマンド入力をすることが出きるようになります。"Press Ctrl-B for the iPXE command line..."の表示がされたら、すかさず、Ctrl+Bを入力してみましょう。すると、下記のプロンプトが表示され、コマンドの入力ができるようになります。では、試しに、いくつかコマンドを入力してみましょう。

iPXE> 
# マックアドレスを表示
iPXE> show mac
net0/mac:hex = xx:xx:xx:xx:xx:xx
# DHCPにてIPアドレスを取得
iPXE> dhcp
DHCP (net0 xx:xx:xx:xx:xx:xx)... ok
# IPアドレスを表示
iPXE> show ip
net0.dhcp/ip:ipv4 = 192.168.0.xx
# DHCPで設定されたfilenameを表示
iPXE> show filename
net0.dhcp/filename:string = http://192.168.0.1/iPXE/boot.ipxe
# DHCPで設定されたnext-serverを表示
iPXE> show next-server                                                          
net0.dhcp/next-server:ipv4 = 192.168.0.1
# サーバの機種情報を表示
iPXE> show product
smbios/product:string = Express5800/i120Ra-e1 [N8100-1482Y]
# urlエンコードして表示
iPXE> show product:uristring
smbios/product:uristring = Express5800%2Fi120Ra-e1%20%5BN8100-1482Y%5D

サーバの機種情報も無事取得できているようです。次は、boot.ipxeをhttp経由で取得できるかどうか試してみます。

iPXE> imgfetch ${filename}
http://192.168.0.1/iPXE/boot.ipxe.... ok
iPXE> imgstat
boot.ipxe : 102 bytes

無事、取得できているようですので、boot.ipxeの内容を手動で試してみましょう。ここでは、まだ、cgiを準備していないので、エラーとなりますが、どのようにアクセスされるかの確認ができます。

iPXE> imgfetch http://${next-server}/cgi-bin/boot_ipxe.cgi?type=${product:uristring}&mac=${mac}
http://192.168.0.1/cgi-bin/boo_ipxe.cgi?type=Express5800%2Fi120Ra-e1%20%5BN8100-1482Y%5D&mac=xx%3Axx%3Axx%3Axx%3Axx%3Axx... No such file or directory (http://ipxe.org/2d0c613b)

機種情報とMACアドレスが代入されてhttpリクエストをしていることが確認できました。
もうお分かりのようにboot.ipxeは、機種情報とMACアドレスを取得し、それをboot_ipxe.cgiにクエリ文字列として付与して叩き、そのレスポンスの内容を実行するスクリプトということになります。(${product}でも、自動的にurlエンコードされるようですが、念のため、uristringでの出力指定をしています。)
では、サーバ起動用の簡単なiPXEスクリプトを、機種情報やMACアドレスを元にboot_ipxe.cgiで動的に生成して、実際にサーバを起動させてみましょう。

Linuxを起動してみる

MACアドレスと機種情報にしたがって、initrdとkernelを決定して起動するだけの簡単なboot_ipxe.cgiを用意してみます。
ちなみに、iPXEでは確認していませんが、gPXEでは、Content-Lengthを指定しないとうまく動作しなかったため、指定するようにしています。

#!/bin/bash

# クエリ文字列は、$QUERY_STRINGに格納されている
# 変数type,macをクエリ文字列から生成する
for q in $(echo ${QUERY_STRING} | tr "&" " "); do
  eval $q
done

case $type in
  *Express*)
    initrd_file=initrd.gz
    ;;
esac

case $mac in
  *xx%3Axx%3Axx%3Axx%3Axx%3Axx*)
    kernel_file=vmlinuz
    ;;
esac

body=$(#!ipxe
initrd http://\${next-server}/${initrd_file}
kernel http://\${next-server}/${kernel_file}
boot
)

echo "Content-type: text/plain"
echo "Connection: close"
echo "Content-Length: $(echo -e "${body}" | wc -c)"
echo ""
echo -e "${body}"

wgetなどで、先ほどのiPXEが出力したパスを叩いて確認してみると、以下のような出力となります。

$ wget -q -O - "http://192.168.0.1/cgi-bin/boo_ipxe.cgi?type=Express5800%2Fi120Ra-e1%20%5BN8100-1482Y%5D&mac=xx%3Axx%3Axx%3Axx%3Axx%3Axx"
#!ipxe
initrd http://${next-server}/initrd.gz
kernel http://${next-server}/vmlinuz
boot

では、/tftp/以下に適当なvmlinuzとinitrd.gzを準備して、マシンを再起動させてみます。

Intel(R) Boot Agent GE v1.2.40                                                  
Copyright (C) 1997-2006, Intel Corporation                                      
                                                                                
CLIENT MAC ADDR: XX XX XX XX XX XX  GUID: xxxxxxxxxxxxxxxxxxxxxxxxxxx  
CLIENT IP: 192.168.0.xx  MASK: 255.255.255.0  DHCP IP: 192.168.0.1             
GATEWAY IP: 192.168.0.xx                                                       
PXE->EB: !PXE at 97CA:0070, entry point at 97CA:0106                            
         UNDI code segment 97CA:3F20, data segment 919C:62E0 (582-623kB)        
         UNDI device is PCI 07:00.0, type DIX+802.3                             
         582kB free base memory after PXE unload                                
iPXE initialising devices...ok                                                  

                                                                                
iPXE 1.0.0+ -- Open Source Network Boot Firmware -- http://ipxe.org             
Features: HTTP iSCSI DNS TFTP AoE bzImage ELF MBOOT PXE PXEXT Menu 

net0: xx:xx:xx:xx:xx:xx using undionly on UNDI-PCI07:00.0 (open)                
DHCP (net0 xx:xx:xx:xx:xx:xx)... ok                                             
net0: 192.168.0.xx/255.255.255.0 gw 192.168.0.xx                            
Next server: 192.168.0.1                                                     
Filename: http://192.168.0.1/iPXE/boot.ipxe                         
http://192.168.0.1/iPXE/boot.ipxe... ok                             
http://192.168.0.1/cgi-bin/boot_ipxe.cgi?type=type=Express5800%2Fi120Ra-e1%20%5BN8100-1482Y%5D&mac=xx%3Axx%3Axx%3Axx%3Axx%3Axx...ok
http://192.168.0.1/initrd.gz... ok
http://192.168.0.1/vmlinuz... ok
[    0.000000] Initializing cgroup subsys cpuset                                                    
[    0.000000] Initializing cgroup subsys cpu                                  
[    0.000000] Linux version 3.0.21 .....
....
....
....

カーネルがロードされ、無事起動できたようです。

実際の運用で使ってみるとすると・・・

DSASでは、ほとんどのサーバがPXEブート+PXELINUXを利用してディスクレスサーバとして起動されるようになっています。
また、リモートからのサーバ管理にIPMIを利用しており、SOL(Serial over Lan)対応シリアルポートを、PXELINUXの起動設定ファイルにて記述することにより、IPMIのSOL経由にてPXELINUXの起動メニューの表示/編集やLinuxの起動メッセージの表示ができるようにしています。

iPXEは、独自メニューを作成可能なのですが、残念ながら、PXELINUXやGRUBのように、起動時にインタラクティブに編集することは出来ないようです。
ですが、PXELINUXのpxelinux.0やSYSLINUXのcom32をロードして実行することができます(com32に関しては、SYSLINUXのver4.xxのcom32ファイルの直接実行はできず、ver3.86以下のものを使用する必要があります)。
そこで、pxelinux.0やmenu.c32(com32ファイルで用意されているメニュー用ファイル)を利用し、そのメニュー設定をiPXEで取得できる情報から動的に生成すれば、サーバ機種によって適切な起動カーネルパラメータを指定することができそうです。また、起動時にインタラクティブにパラメータを編集するといったこともいけそうです。

さて、今回は、ここまでとして、次回ではmenu.c32のメニュー機能をiPXEから利用したり、IPMI SOL経由で表示したりする例を紹介できたらと思っています。

klab_gijutsu2 at 17:45│Comments(0)TrackBack(0)運用 | tool

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント