Ba năm trước, một kỹ sư mới trong nhóm của tôi vô tình đẩy sai cấu hình VLAN lên một switch lõi trong giờ làm việc. Chỉ trong vài phút, nửa văn phòng mất kết nối. Việc khắc phục mất hai tiếng đồng hồ — không phải vì vấn đề phức tạp, mà vì chúng tôi không biết cấu hình switch trông như thế nào trước khi thay đổi. Tất cả đều phải làm việc bằng trí nhớ.
Sự cố đó dạy tôi một điều mà tôi luôn nói với mọi kỹ sư mới: sao lưu cấu hình không phải tùy chọn. Dựa vào export thủ công cũng chẳng khác gì không có backup.
Vấn Đề Mất Cấu Hình Mà Ít Ai Nói Đến
Hầu hết các nhóm network đều có phiên bản câu chuyện tương tự. Ai đó thực hiện thay đổi, có sự cố xảy ra, và mọi người cuống cuồng cố nhớ lại cài đặt ban đầu là gì. Hóa ra “bản backup” là file config được export từ sáu tháng trước mà không ai đụng vào sau lần bảo trì cuối.
Các tình huống gây ra sự cố còn đa dạng hơn nhiều người nghĩ:
- Phần cứng hỏng, thiết bị thay thế cần cấu hình lại từ đầu
- Cấu hình sai vô tình mà không có điểm tham chiếu để rollback
- Kiểm toán tuân thủ yêu cầu bằng chứng về lịch sử thay đổi cấu hình
- Nhân sự nghỉ việc mang theo toàn bộ kiến thức nội bộ
Tại Sao Script Backup Thủ Công Luôn Hỏng
Giải pháp đầu tiên thường nghĩ đến là một cron job SSH vào từng thiết bị và lưu running config ra file. Cách này hoạt động được trong tuần đầu. Rồi ai đó thêm một switch mới và quên cập nhật script. Một mật khẩu được đổi. Một SSH key hết hạn. Script âm thầm thất bại suốt ba tháng trong khi mọi người vẫn nghĩ backup đang chạy tốt.
Nguyên nhân gốc rễ không phải do lười biếng. Script không có khả năng nhận biết danh sách thiết bị của bạn. Chúng không xử lý được sự khác biệt về cú pháp lệnh giữa các nhà sản xuất. Không có cơ chế phát hiện điều gì thực sự thay đổi giữa các lần chạy. Kết quả là một đống file text có timestamp mà không có cách nào dễ để trả lời câu hỏi “router này thay đổi gì giữa thứ Hai và thứ Ba?”
Năm switch? Còn quản lý được. Năm mươi thiết bị gồm Cisco IOS, Juniper JunOS, MikroTik RouterOS và HP ProCurve? Lúc đó bạn đang bảo trì một công cụ bảo trì thay vì một hệ thống backup.
So Sánh Các Lựa Chọn: RANCID vs Script vs Oxidized
RANCID (Really Awesome New Cisco confIg Differ) là giải pháp truyền thống. Có mặt từ đầu những năm 2000, hỗ trợ thiết bị đa nhà sản xuất với CVS hoặc Subversion để kiểm soát phiên bản. Điểm khó chính là cài đặt — yêu cầu cấu hình Perl phức tạp, cấu trúc thư mục đặc thù, và quy trình làm việc cảm giác lỗi thời so với Git hiện đại.
Ansible playbook có thể lấy cấu hình thiết bị, nhưng được thiết kế để đẩy thay đổi chứ không phải thu thập cấu hình liên tục. Chạy playbook mỗi giờ để lấy config thì về mặt kỹ thuật là được nhưng lãng phí và vận hành rất bất tiện.
Oxidized được xây dựng chuyên biệt cho vấn đề này. Viết bằng Ruby, hỗ trợ hơn 100 loại thiết bị — Cisco, Juniper, MikroTik, Arista, HP ProCurve và nhiều hơn nữa — kết nối qua SSH hoặc Telnet với tích hợp Git sẵn có. Nó chạy như một daemon, polling thiết bị theo lịch và commit mọi thay đổi phát hiện được trực tiếp vào một Git repository. Repo đó trở thành lịch sử đầy đủ, có thể tìm kiếm, của mọi thay đổi cấu hình trên toàn bộ hạ tầng mạng của bạn.
Cài Đặt Oxidized với Git Backend
Cài đặt
Oxidized yêu cầu Ruby 2.5+. Trên Debian/Ubuntu:
sudo apt update
sudo apt install -y ruby ruby-dev libsqlite3-dev libssl-dev pkg-config cmake libgit2-dev
sudo gem install oxidized oxidized-script oxidized-web
Trên RHEL/Rocky Linux:
sudo dnf install -y ruby ruby-devel sqlite-devel openssl-devel cmake libgit2-devel
sudo gem install oxidized oxidized-script oxidized-web
Cấu Hình Cơ Bản
Oxidized lưu cấu hình tại ~/.config/oxidized/config. Tạo config tối thiểu để bắt đầu:
---
username: netbackup
password: yourpassword
model: ios
resolve_dns: true
interval: 3600
use_syslog: false
debug: false
pid: "/var/run/oxidized/oxidized.pid"
output:
default: git
git:
single_repo: true
path: /opt/oxidized/configs
source:
default: csv
csv:
file: /etc/oxidized/router.db
delimiter: !ruby/regexp /:/
map:
name: 0
ip: 1
model: 2
username: 3
password: 4
model_map:
cisco: ios
juniper: junos
mikrotik: routeros
Các thông số quan trọng cần hiểu:
interval: 3600— poll mỗi thiết bị mỗi 3600 giây (1 tiếng)output.git.single_repo: true— tất cả cấu hình thiết bị lưu trong một Git repositorysource.csv— danh sách thiết bị đọc từ file CSV thuần túy
File Danh Sách Thiết Bị
Tạo /etc/oxidized/router.db với danh sách thiết bị của bạn. Mỗi dòng theo định dạng hostname:ip:model:username:password:
core-sw-01:192.168.1.1:ios:admin:secretpass
core-sw-02:192.168.1.2:ios:admin:secretpass
edge-router:192.168.1.254:junos:netbackup:junpass
mikrotik-ap:192.168.2.1:routeros:admin:mtpass
Khởi Tạo Git Repository
Oxidized không tự tạo Git repo — bạn cần khởi tạo trước:
mkdir -p /opt/oxidized/configs
cd /opt/oxidized/configs
git init
git config user.email "[email protected]"
git config user.name "Oxidized Backup"
Nếu muốn đẩy lên remote (GitHub, GitLab hoặc Gitea tự host), thêm ngay bây giờ:
git remote add origin [email protected]:yourorg/network-configs.git
Oxidized xử lý commit cục bộ. Thiết lập post-commit hook hoặc một cron job riêng để đẩy lên remote sau mỗi commit.
Chạy Oxidized như một Service
Chạy Oxidized thủ công trước để bắt lỗi kết nối trước khi chuyển sang chạy nền:
oxidized
Hai vấn đề thường gặp nhất ở lần chạy đầu. Thứ nhất là lỗi xác nhận SSH host key — thêm đoạn này vào /etc/ssh/ssh_config cho dải mạng quản lý của bạn:
Host 192.168.1.*
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Thứ hai là lỗi nhận dạng model, khi prompt của thiết bị không khớp với pattern mà Oxidized mong đợi. Nếu một thiết bị hiển thị là không kết nối được nhưng SSH thủ công vẫn hoạt động bình thường, chạy oxidized -d để xem output phiên thô và xác định chỗ không khớp.
Sau khi lần poll đầu tiên thành công, chuyển Oxidized thành systemd service:
sudo useradd -r -s /bin/false oxidized
sudo chown -R oxidized:oxidized /opt/oxidized /etc/oxidized
sudo tee /etc/systemd/system/oxidized.service <<EOF
[Unit]
Description=Sao Lưu Cấu Hình Mạng Oxidized
After=network.target
[Service]
User=oxidized
ExecStart=/usr/local/bin/oxidized
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable --now oxidized
sudo systemctl status oxidized
Xem Lịch Sử Cấu Hình trong Git
Sau lần poll thành công đầu tiên, Git repo có một commit cho mỗi thiết bị kết nối được. Mỗi lần poll tiếp theo phát hiện thay đổi sẽ tạo một commit mới, xây dựng lịch sử kiểm toán đầy đủ:
cd /opt/oxidized/configs
# Toàn bộ thay đổi của một thiết bị cụ thể
git log --oneline -- core-sw-01
# So sánh cấu hình hôm nay với tuần trước
git diff HEAD~7 HEAD -- core-sw-01
# Lịch sử thay đổi đầy đủ với diff từng dòng
git log --follow -p -- edge-router
Output của diff cho thấy chính xác những dòng nào thay đổi giữa các commit:
-interface GigabitEthernet0/1
- description Old_Uplink
- switchport mode trunk
+interface GigabitEthernet0/1
+ description Uplink_to_Core
+ switchport mode trunk
+ switchport trunk allowed vlan 10,20,30
Cái diff đó đã có thể tiết kiệm cho chúng tôi hai tiếng trong sự cố tôi kể ở đầu bài.
Bảo Mật Thông Tin Xác Thực trên Môi Trường Production
Mật khẩu plaintext trong router.db là điểm yếu rõ ràng nhất trong một thiết lập Oxidized cơ bản. Với môi trường production:
- Tạo tài khoản backup chuyên dụng chỉ đọc trên từng thiết bị với quyền chỉ đọc cấu hình
- Dùng biến môi trường cho thông tin xác thực dùng chung qua cú pháp
!ruby/object:Oxidized::Envcủa Oxidized - Giữ Git repository riêng tư nếu cấu hình chứa địa chỉ IP nhạy cảm hoặc SNMP community string
- Giới hạn truy cập SSH vào IP của server Oxidized bằng ACL trên từng thiết bị được quản lý
Tạo tài khoản chỉ đọc tối thiểu trên Cisco IOS:
username netbackup privilege 1 secret StrongBackupPass!
ip access-list standard MGMT-ACL
permit 192.168.100.10
line vty 0 4
login local
access-class MGMT-ACL in
Sau Một Tuần Chạy Oxidized
Chạy git log sau một tuần vận hành. Bạn gần như chắc chắn sẽ tìm thấy những thay đổi mà bạn không biết — phần mềm NMS tự đẩy cập nhật, các kỹ sư khác âm thầm chỉnh sửa, cấu hình dần dần trôi dạt mà không ai để ý. Chỉ riêng khả năng hiển thị đó đã đủ biện minh cho thời gian cài đặt.
Repo còn kiêm luôn vai trò audit trail, bằng chứng tuân thủ và điểm khởi đầu phục hồi thảm họa. Thay vì hỏi “switch đó trước khi hỏng có gì?”, chạy git show HEAD:core-sw-01. Câu trả lời đầy đủ, trong chưa đầy một giây.

