【ChatGPT 4oと一緒にAnsible化 Part2】Ciscoルータ(C890)にAnsibleを適用した話
Contents
はじめに
わたしは「2台のCisco設定をansible playbookを作成してください」とルータ2台分のコンフィグを貼って依頼し、ChatGPTに作成してもらいました。
私はCiscoでAnsibleを使ったことがなく、完全な素人です。
でもChatGPTにお願いすれば、どこまで簡単にできるだろう?と期待してやってみました。
前回は、ChatGPTにAnsibleのPlaybookを作ってもらったものの、DockerやRocky Linuxの環境構築で大苦戦。なんとか準備が整ったので、今回は実際にCiscoルータ(C890)にAnsibleを適用してみました。
👉 前回の記事はこちら:
【ChatGPTと一緒にAnsible化 Part1】Ciscoルータ(C890)にAnsibleを作成しようと思ったけど、Docker Rockyコンテナで格闘した話
構成
実行環境のバージョン
$ ansible --version
ansible [core 2.16.2]
config file = /etc/ansible/ansible.cfg
python version = 3.12.0
jinja version = 3.1.3
yaml version = 6.0.1
- ルータ:Cisco C890シリーズ 2台(rt01, rt02)
- IPアドレス:
- rt01: 10.1.100.40
- rt02: 10.1.100.46
- OS:IOS 15.4(3)M6a
- 接続方法:SSH
- 制御端末:Docker上のRocky LinuxからAnsible実行
- RT01とRT02にVlan10のネットワークにいるDocker (Rocky8)からansibleを適用します。

Ansible Playbook(最終版)
ディレクトリ構成(プロジェクトルート)
project_root/
├── inventory/
│ └── hosts
├── playbooks/
│ └── cisco_config.yml
インベントリファイル inventory/hosts
[cisco_routers]
rt01 ansible_host=10.1.100.40
rt02 ansible_host=10.1.100.46
[cisco_routers:vars]
ansible_connection=network_cli ansible_network_os=cisco.ios.ios ansible_user=runsuru ansible_password=cisco123 ansible_become=yes ansible_become_method=enable ansible_become_password=cisco123
ディレクトリ構成(プロジェクトルート)
project_root/
├── inventory/
│ └── hosts
├── playbooks/
│ └── cisco_config.yml
以下がChatGPTと対話しながら作成したPlaybookの最終形です。playbooks/cisco_config.yml
よくみると、変数vars:
として bgp_as_map:
など定義しているものの、BGPセクションを見るとベタ打ちでした。今回は敢えて訂正せず、このまま実施をします。
- name: Configure Cisco routers (rt01 / rt02)
hosts: cisco_routers
gather_facts: no
vars:
loopback_ip_map:
rt01: "1.1.1.1"
rt02: "2.2.2.2"
gig0_ip_map:
rt01: "192.168.12.1"
rt02: "192.168.12.2"
bgp_as_map:
rt01: "65001"
rt02: "65002"
bgp_neighbor_as_map:
rt01: "65002"
rt02: "65001"
bgp_description_map:
rt01: "BGP peer group to downstream routers"
rt02: "BGP peer group to upstream routers"
bgp_password_map:
rt01: "045802150C2E1D1C5A"
rt02: "060506324F41584B56"
bgp_neighbor_ip_map:
rt01: "192.168.12.2"
rt02: "192.168.12.1"
tasks:
- name: Configure VTY lines 0 to 4
cisco.ios.ios_config:
lines:
- login local
- rotary 1
- transport input ssh
parents: line vty 0 4
save_when: modified
- name: Configure VTY lines 5 to 15
cisco.ios.ios_config:
lines:
- login local
- rotary 1
- transport input ssh
parents: line vty 5 15
save_when: modified
- name: Set hostname
cisco.ios.ios_config:
lines:
- hostname {{ inventory_hostname }}
save_when: modified
- name: Configure loopback interface
cisco.ios.ios_config:
lines:
- interface Loopback0
- ip address {{ loopback_ip_map[inventory_hostname] }} 255.255.255.255
parents: interface Loopback0
match: exact
replace: line
save_when: modified
- name: Configure GigabitEthernet0 interface
cisco.ios.ios_config:
lines:
- interface GigabitEthernet0
- ip address {{ gig0_ip_map[inventory_hostname] }} 255.255.255.252
- duplex auto
- speed auto
- no shutdown
parents: interface GigabitEthernet0
match: exact
replace: line
save_when: modified
- name: Create VLAN10
cisco.ios.ios_config:
lines:
- vlan 10
save_when: modified
- name: Configure VLAN10 interface for SSH
cisco.ios.ios_config:
lines:
- description "### for ssh ###"
- ip address dhcp
parents: interface Vlan10
match: exact
replace: line
save_when: modified
- name: Configure BGP settings on rt01 and rt02
hosts: rt01:rt02
gather_facts: no
connection: network_cli
vars:
ansible_network_os: cisco.ios.ios
tasks:
- name: Configure BGP settings on rt01
when: inventory_hostname == 'rt01'
cisco.ios.ios_config:
lines:
- neighbor PEERS peer-group
- neighbor PEERS remote-as 65002
- neighbor PEERS description to-rt02
- neighbor PEERS password 7 045802150C2E1D1C5A
- neighbor PEERS timers 5 15
- neighbor 192.168.12.2 peer-group PEERS
- network 1.1.1.1 mask 255.255.255.255
- bgp log-neighbor-changes
parents: router bgp 65001
save_when: modified
- name: Configure BGP settings on rt02
when: inventory_hostname == 'rt02'
cisco.ios.ios_config:
lines:
- neighbor PEERS peer-group
- neighbor PEERS remote-as 65001
- neighbor PEERS description to-rt01
- neighbor PEERS password 7 045802150C2E1D1C5A
- neighbor PEERS timers 5 15
- neighbor 192.168.12.1 peer-group PEERS
- network 2.2.2.2 mask 255.255.255.255
- bgp log-neighbor-changes
parents: router bgp 65002
save_when: modified
rt02を初期化してから設定投入
シリアルコンソール接続して初期化:
rt02#write erase
*Feb 6 18:27:26.827: %SYS-7-NV_BLOCK_INIT: Initialized the geometry of nvram
rt02#reload
System configuration has been modified. Save? [yes/no]: no
Proceed with reload? [confirm]
----
Would you like to enter the initial configuration dialog? [yes/no]: no
—- 初期コンフィグ例:
! ホスト名(任意)
hostname rt02
! IPアドレス(SSH接続用)
interface Vlan10
description for ssh
ip address dhcp
no shutdown
! スイッチポート側を VLAN10 に接続
interface FastEthernet0
switchport access vlan 10
no shutdown
! SSH接続のためのユーザー パスワードはCisco123
username runsuru privilege 15 secret 5 $1$fwYo$rLJGF5x1KnAYVwcfgAArc0
! SSH有効化
ip domain-name example.local
crypto key generate rsa modulus 1024
ip ssh version 2
! VTYラインでSSHログインを許可
line vty 0 4
login local
transport input ssh
---
コンフィグを入れたら、sshできるように修正します。
# 初期化(既存のSSHキー情報を削除)
ssh-keygen -R 10.1.100.46
```bash
# SSHでログインして接続確認
ssh runsuru@10.1.100.46
この状態にしておけば、Ansibleでの投入準備が整います。
Playbookの実行ログ
以下は、rt02
に対して実際にPlaybookを実行した結果です。
[runsuru@6a9ba1ecee63 ansible]$ ansible-playbook -i inventory/hosts playbooks/cisco_config.yml -l rt02
PLAY [Configure Cisco routers (rt01 / rt02)] ********************************************************************************************
TASK [Configure VTY lines 0 to 4] *******************************************************************************************************
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the
running configuration on device
changed: [rt02]
TASK [Configure VTY lines 5 to 15] ******************************************************************************************************
changed: [rt02]
TASK [Set hostname] *********************************************************************************************************************
ok: [rt02]
TASK [Configure loopback interface] *****************************************************************************************************
changed: [rt02]
TASK [Configure GigabitEthernet0 interface] *********************************************************************************************
changed: [rt02]
TASK [Create VLAN10] ********************************************************************************************************************
changed: [rt02]
TASK [Configure VLAN10 interface for SSH] ***********************************************************************************************
changed: [rt02]
PLAY [Configure BGP settings on rt01 and rt02] ******************************************************************************************
TASK [Configure BGP settings on rt01] ***************************************************************************************************
skipping: [rt02]
TASK [Configure BGP settings on rt02] ***************************************************************************************************
changed: [rt02]
PLAY RECAP ******************************************************************************************************************************
rt02 : ok=8 changed=7 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
設定が正常に投入され、changed=7
として7つの項目が変更されたことが確認できます。
また、BGPピアも無事に確立されており、経路の広報・受信にも問題はありませんでした。
rt01#show ip bgp summary
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
192.168.12.2 4 65002 67 67 3 0 0 00:05:20 1
rt01#show ip bgp neighbors 192.168.12.2 advertised-routes
BGP table version is 3, local router ID is 1.1.1.1
Network Next Hop Metric LocPrf Weight Path
*> 1.1.1.1/32 0.0.0.0 0 32768 i
Total number of prefixes 1
rt01#show ip bgp neighbors 192.168.12.2 routes
BGP table version is 3, local router ID is 1.1.1.1
Network Next Hop Metric LocPrf Weight Path
*> 2.2.2.2/32 192.168.12.2 0 0 65002 i
Total number of prefixes 1
rt01#
ChatGPTとのやりとり(一部抜粋)
最初に提示されたPlaybookは一見正しく見えたものの、いざ実行するといくつかの箇所でエラーが発生しました。
その都度、エラー内容をChatGPTに貼り付けると、すぐに原因と修正案を提示してくれました。
エラー → 修正 → 再実行 を繰り返すことで、最終的に安定したPlaybookが完成しました。
実際のエラーとやりとり例:
TASK [Configure GigabitEthernet0 interface] *********************************************************************************************
fatal: [rt02]: FAILED! => {"changed": false, "module_stderr": "ip address 192.168.12.2 255.255.255.252
ip address 192.168.12.2 255.255.255.252
^
% Invalid input detected at '^' marker.
rt02(config)#", "module_stdout": "", "msg": "MODULE FAILURE
See stdout/stderr for the exact error"}
💻 ChatGPT:interface定義とIPアドレス設定が二重になっているか、parents
指定が足りない可能性あり。
TASK [Configure loopback interface] *****************************************************************************************************
fatal: [rt02]: FAILED! => {"changed": false, "module_stderr": "ip address 2.2.2.2 255.255.255.255
ip address 2.2.2.2 255.255.255.255
^
% Invalid input detected at '^' marker.
rt02(config)#", "module_stdout": "", "msg": "MODULE FAILURE
See stdout/stderr for the exact error"}
💻 ChatGPT:この場合も parents: interface Loopback0
が不足していた。正しく書く必要あり。
TASK [Configure VLAN10 for SSH] *********************************************************************************************************
fatal: [rt02]: FAILED! => {"changed": false, "module_stderr": "description \"### for ssh
description \"### for ssh
^
% Invalid input detected at '^' marker.
rt02(config-vlan)#", "module_stdout": "", "msg": "MODULE FAILURE
See stdout/stderr for the exact error"}
💻 ChatGPT:VLAN設定において description
を入れる場所が不適切だったため、該当セクションの構成を見直すよう提案。
感想
最初からパーフェクトなPlaybookは作れなかったけど、エラーが出てもその出力を貼ってChatGPTに相談すれば、即座に修正案がもらえる。
昔はGoogleでそれっぽいページを開いて、何度も試行錯誤していたけど、今は「会話しながら解決できる」。
これ、ほんとうに作業効率が段違いに違う。
今回は、1つのPlaybookにすべての設定をまとめて適用しましたが、実際の本番環境ではこのままでは利用が難しいと感じました。
なぜならば、拡張性がなく、現実のネットワークにはさまざまな機種や構成が存在し、必要なパラメータも多数あるためです。
Ansibleは、チームで管理することが多く、その場合はGitHubなどのバージョン管理システムを使うのが一般的です。
そうなると、Playbookに平文でパスワードが書かれていると、セキュリティ上の問題になります。
その点を踏まえ、次回はより実践的で再利用性の高いロール分け構成を、ChatGPTと一緒に構築していきたいと思います。
“【ChatGPT 4oと一緒にAnsible化 Part2】Ciscoルータ(C890)にAnsibleを適用した話” に対して1件のコメントがあります。