Cisco AutoInstall

はじめに - AutoInstallとは?

AutoInstall とは、Cisco機器がデフォルトのコンフィグで起動する際、ネットワーク経由で外部からコンフィグファイルをロードし、自動的にコンフィグを行うという機能である。まあ PXE ブートみたいなモノだな。おおざっぱに仕組みを書くと、ネットワーク機器の起動時にDHCPでIP設定 + コンフィグファイル等のオプションを渡す、ネットワーク機器は渡された情報に基づいて TFTP をつかって設定ファイル読み込み・自動設定という流れになる。

なぜ AutoInstall なのか?

今回は検証環境セットアップの省力化のために試してみた。なぜ? たとえば下の図のように検証環境にルータが4台ほどあるとしよう。検証環境を作るときは、どうしても最初のIP設定してリモートアクセスできるところまで持って行くのにシリアルコンソールから設定を投入しなければいけない。シリアルサーバとかあればまだリモートでやれるのだけど、そういう機材がない場合いちいちシリアルつなぎ替えながら設定しなければいけないわけで、これが非常に不便だ。面倒くさすぎる。

検証環境なのである程度やりたいことが終わったら全部クリアするわけだ。で、また次のことやろうと思うとまたシリアルつなぎ替えてセットアップ始めなければいけない。こんな面倒なことやってられないよね…。設定クリアしたら自動的に初期コンフィグ(リモートアクセスができるレベルのコンフィグ)になってくれたらいいじゃないかと。

別に、ルータの中(flash:/)に初期コンフィグ名前を使って保存しておいて、検証が終わったら copy flash:/init-confg startup-confg して reload でいいじゃん、という話もある。でも俺はそれを忘れるんだ。write erase + reload!! だーん、あっ、みたいなのをやってしまう。それとね、その初期コンフィグを作ってローカルに保存するという作業も、結局はどこかで個別にシリアルつなぎ替えながらやらないといけないんだよね。AutoInstall なら必要最小限の情報 (各機器の MAC アドレス) がわかっていれば、数が増えても個別のロード用コンフィグ書き換えたモノだけ用意しておいて、一気にデプロイする、というのができるんだ。数台ならまあよいかもしれないけど、たとえばこれが仕事で10台、あるいは100台の初期コンフィグ投入しなければいけないとしたら? 手間はちょっとでも少ない方がいい。


準備

構成は上の図のように、ひとつの管理用セグメント(VL901)に設定したい機材とサーバがぶら下がっているだけ、というシンプルな構成で考える。

いるもの

  • DHCPサーバ
    • IOS でもできる。が、今回は構成上の理由により Ubuntu 上の isc-dhcpd を使う。
    • 必ずしも機器とサーバがセグメントが同一である必要はない。別に ip helper 使って飛ばせば良いだけなので。
  • DNSサーバ
    • 必須ではない。今回は使わない。
  • TFTPサーバ
    • コンフィグ転送用サーバとして使う。今回は DHCP サーバと同居。

Ciscoのサイト見ると書いてあるのだけど、ネットワーク機器が起動 → DHCPIPアドレス設定 + ロードするファイル情報の取得 → ファイルを tftp で取得、という流れになる。このファイルを取得する際、何という名前のファイルをとってくるかというので、

  • ホスト名ベースでファイル名を探す (-confg, .cfg, これは設定されたIPで名前を引くので、このときDNSサーバが必要)
  • デフォルトのファイル名で探す(network-confg, router-confg, cisconet.cfg とか)
  • dhcp option で指定されたファイル名で探す

という感じ。今回はオプションでファイル名を指定してしまうので DNS は用意しない。

サーバ設定

Ciscoでやってみる?

service dhcp してあれば IOS でもできる。

ip dhcp pool exprtr1
   host 172.16.1.91 255.255.255.0
   hardware-address 0027.0daf.89ba
   next-server 172.16.1.16
!

こんな感じ。ただ、今回これは使えなかった。というのは、図にある core/exp1 というのは VRF なのだけど、'host' pool は vrf 指定できないというのがあったから。('network' pool であれば vrf オプションがある。) なんで VRF なのかとかその辺の話はまた別途書こうかと思うのでいまは省略。

Restrictions
Currently, the ip dhcp excluded-address global configuration command cannot be used to exclude addresses from VRF associated pools.

The vrf DHCP pool configuration command is currently not supported for host pools.

Attribute inheritance is not supported on VRF pools.

ちなみに VRF で 'network' pool を設定するとこういう書き方になる。

ip dhcp excluded-address vrf exp1 172.16.1.1 172.16.1.89
!
ip dhcp pool exprtr1
   vrf exp1
   network 172.16.1.0 255.255.255.0
!

ついでに。この状態で debug ip dhcp server event して、ルータに DHCP で IP を振ってみる。

Feb  1 00:13:23.439 JST: DHCPD: Sending notification of DISCOVER:
Feb  1 00:13:23.439 JST:   DHCPD: htype 1 chaddr 0027.0daf.89ba
Feb  1 00:13:23.439 JST:   DHCPD: table id 1 = vrf exp1
Feb  1 00:13:23.439 JST:   DHCPD: interface = Vlan901
Feb  1 00:13:23.439 JST:   DHCPD: out_vlan_id 0
Feb  1 00:13:23.439 JST: DHCPD: Sending notification of DISCOVER:
Feb  1 00:13:23.439 JST:   DHCPD: htype 1 chaddr 0027.0daf.89ba
Feb  1 00:13:23.439 JST:   DHCPD: table id 1 = vrf exp1
Feb  1 00:13:23.439 JST:   DHCPD: interface = Vlan901
Feb  1 00:13:23.439 JST:   DHCPD: out_vlan_id 0
Feb  1 00:13:25.452 JST: DHCPD: Adding binding to radix tree (172.16.1.128)
Feb  1 00:13:25.452 JST: DHCPD: VPN 'exp1'
Feb  1 00:13:25.452 JST: DHCPD: Adding binding to hash tree
Feb  1 00:13:25.452 JST: DHCPD: assigned IP address 172.16.1.128 to client 0063.6973.636f.2d30.3032.372e.3064.6166.2e38.3962.612d.4661.30. (2969 0)
Feb  1 00:13:25.452 JST: DHCPD: DHCPOFFER notify setup address 172.16.1.128 mask 255.255.255.0
Feb  1 00:13:25.452 JST: DHCPD: Sending notification of ASSIGNMENT:
Feb  1 00:13:25.452 JST:  DHCPD: address 172.16.1.128 mask 255.255.255.0
Feb  1 00:13:25.452 JST:   DHCPD: htype 1 chaddr 0027.0daf.89ba
Feb  1 00:13:25.452 JST:   DHCPD: table id 1 = vrf exp1
Feb  1 00:13:25.452 JST:   DHCPD: lease time remaining (secs) = 86400
Feb  1 00:13:25.452 JST:   DHCPD: interface = Vlan901
Feb  1 00:13:25.452 JST:   DHCPD: out_vlan_id 0
core#
core#sh ip dhcp vrf exp1 binding *
Load for five secs: 6%/0%; one minute: 6%; five minutes: 8%
Time source is NTP, 00:14:05.214 JST Wed Feb 1 2012


Bindings from VRF pool exp1:
IP address          Client-ID/              Lease expiration        Type
                    Hardware address/
                    User name
172.16.1.128        0063.6973.636f.2d30.    Feb 02 2012 12:13 AM    Automatic
                    3032.372e.3064.6166.
                    2e38.3962.612d.4661.
                    30
core#

ここで着目したいのが、client identifier として振られている "0063.6973.636f.2d30.3032.372e.3064.6166.2e38.3962.612d.4661.30" という謎の数字。これ、説明によると "nullcisco-0027.0daf.89ba-Fa0" を ASCII Code で表した物とのこと。

NUL c  i  s  c  o  -  0  0  2  7  .  0  d  a  f  .  8  9  b  a  -  F  a  0
00  63 69 73 63 6f 2d 30 30 32 37 2e 30 64 61 66 2e 38 39 62 61 2d 46 61 30

で、これをキーにして機器に振るIPアドレスとオプション設定してもよいみたいなんだけど、さすがにこのキーをとってきたり生成したりするのは面倒。で、実は普通に MAC アドレスだけ指定しておけばいけました、という話になるんだけど。

DHCPd (isc-dhcpd)

さくっとこんな感じで。

  • dhcpd.conf
ddns-update-style none;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;

subnet 172.16.1.0 netmask 255.255.255.0 {
}

host exprtr1 {
  fixed-address 172.16.1.91;
  option subnet-mask 255.255.255.0;
  option tftp-server-name "172.16.1.16";
  hardware ethernet 00:27:0d:af:89:ba;
  filename "exprtr1-confg";
}

見ての通り、MAC/IP/コンフィグファイル名を個別に指定していくだけ。

TFTPd

Ubuntu では今回 atftpd を standalone で使った(デフォルトだと xinetd 経由とかだったはず)

  • /tftpboot にネットワーク機器に読ませたい初期コンフィグファイルを置く。
    • exprtr1-confg
service nagle
no service pad
service tcp-keepalives-in
service tcp-keepalives-out
service timestamps debug datetime msec localtime show-timezone
service timestamps log datetime msec localtime show-timezone
service password-encryption
!
hostname exprtr1
!
boot-start-marker
boot-end-marker
!
logging message-counter syslog
logging buffered 16384
logging console informational
logging monitor informational
enable secret 5 ******************************
!
no aaa new-model
clock timezone JST 9
!
!
ip cef
ip vrf mgmt
 rd 65535:1
 route-target export 65535:1
 route-target import 65535:1
!
no ipv6 cef
ntp server vrf mgmt 172.16.1.16
!
multilink bundle-name authenticated
!
ip tftp source-interface FastEthernet0
!
interface FastEthernet0
 ip vrf forwarding mgmt
 ip address 172.16.1.101 255.255.255.0
 no ip proxy-arp
 ip virtual-reassembly
 duplex auto
 speed auto
!
interface FastEthernet2
 switchport mode trunk
!
interface Vlan1
 no ip address
!
ip forward-protocol nd
ip route vrf mgmt 0.0.0.0 0.0.0.0 172.16.1.1
no ip http server
no ip http secure-server
!
line con 0
 logging synchronous
 exec prompt timestamp
line aux 0
line vty 0 4
 exec-timeout 0 0
 password 7 ****************
 logging synchronous
 login
 exec prompt timestamp
line vty 5 15
 exec-timeout 15 0
 login
 transport input none
 transport output none
!

と、まあ実機で一度コンフィグ作ってそれを必要な物だけに削ったのでそれなりにごちゃごちゃ書いてあるけど、ここで用意する初期コンフィグで絶対に必要なのは以下の設定

  • enable password
  • remote access
    • vty の login password
    • ssh だと key generate を伴うので AutoInstall で設定したときにすぐリモートアクセス可能になるように telnet にしてある。

注意が必要なのは tftp による接続性だろうか。

  • 1812J の場合、スイッチポート(Fa2-9)とL3ポート(Fa0-1)があるけど、初期状態で dhcp でIP設定できるのは普通に考えて Fa0-1 or Vlan1 しかないだろう。(VLAN Interface は vlan database で vlan 作ってやらないといけないので。) ということで確実な Fa0 を管理アクセス用のポートとして選択してみた。
  • 検証用のルータなので、ルータで設定する環境と管理アクセス用のパスを VRF で完全に分離すべく vrf "mgmt" を作っている。tftp でのコンフィグのやりとり (copy run tftp とか)では vrf option がないみたいなので、ip tftp source-interface を指定してある。
ネットワーク機器識別子の情報取得

要は各機器の MAC アドレス(DHCPしゃべってIPを設定するインタフェースのMACアドレス)が必要になる。機器ごと個別にコンフィグファイルを配布したい場合は、作業としてこれだけはどうしても必要だ。でも、各機器ごとシリアルつなぎ替えて情報とらなければいけないのはこれだけ。

やってみる

ということで設定できたら write erase でコンフィグ全部消して reload する。

(略)
If you require further assistance please contact us by sending email to
export@cisco.com.

Installed image archive
Cisco 1812-J (MPC8500) processor (revision 0x300) with 354304K/38912K bytes of memory.
Processor board ID FHK0*******, with hardware revision 0000

10 FastEthernet interfaces
1 ISDN Basic Rate interface
62720K bytes of ATA CompactFlash (Read/Write)

Loading exprtr1-confg from 172.16.1.16 (via FastEthernet0): !
[OK - 1325 bytes]

% Interface FastEthernet0 IP address 172.16.1.91 removed due to enabling VRF mgmt


Press RETURN to get started!

"Loading exprtr1-confg" ってなってるよね。これで起動するとちゃんと初期コンフィグが読み込まれた状態になっている。初期化して再起動した後でいきなり telnet でリモートアクセス可能な状態に!

DHCPサーバ側でもこんな感じででる。

Feb  2 01:20:13 expsvr1 dhcpd: DHCPDISCOVER from 00:27:0d:af:89:ba via eth1
Feb  2 01:20:13 expsvr1 dhcpd: DHCPOFFER on 172.16.1.91 to 00:27:0d:af:89:ba via eth1
Feb  2 01:20:14 expsvr1 dhcpd: DHCPREQUEST for 172.16.1.91 (172.16.1.16) from 00:27:0d:af:89:ba via eth1
Feb  2 01:20:14 expsvr1 dhcpd: DHCPACK on 172.16.1.91 to 00:27:0d:af:89:ba via eth1
Feb  2 01:20:25 expsvr1 atftpd[7008]: Serving exprtr1-confg to 172.16.1.91:56065
Feb  2 01:20:25 expsvr1 atftpd[7008]: Serving exprtr1-confg to 172.16.1.91:65033
Feb  2 01:20:34 expsvr1 dhcpd: DHCPRELEASE of 172.16.1.91 from 00:27:0d:af:89:ba via eth1 (not found)

起動 → DHCP → TFTP という流れ。あとは所定の IP で telnet して設定書き換えて保存。一通り検証が終わって環境初期化したくなったら write erase + reload で一発で初期化ができる。これで最初の MAC アドレスを調べて回るとき以外は基本的にシリアルのつなぎ替えとかしないでもいつでもリモートアクセスできる状態になったはず。(リモートアクセスの設定とかACLの設定とか間違えなければだけど。)
あとは必要に応じて台数分初期コンフィグ用意 (どうせ hostname と ip address しか変えない) して、dhcpd に各機器の MAC 指定したコンフィグ水増しするだけでいい。つないで電源投入で一発で初期コンフィグのデプロイができる。

もう一工夫するとして

  • 最初の MAC アドレス調べるのだけがちょっと面倒だけど。でも仕事で使う場合とかであれば最初に検品するはずで、そのときに一緒に show int の情報全部とっちゃえば良いわけですよ。各インタフェースの MAC アドレス一覧があれば良いのだから。機器自体のシリアル番号 (show version)と MAC アドレス一覧 (show interface) のデータだけとっておけばあとは準備が進められる。
  • それなりの台数になるのであれば、必然的に、ルータ用コンフィグを自動生成する、dhcpd.conf を自動生成するという方向になるだろう。実際今回も自分の環境用には書いたし。パラメータ書き換えるだけだものね。mod_ruby とかと併用するといろいろやりやすいんじゃないかな。