Monday, January 20, 2025

[Ansible] Lesson 7 – Build Your Inventory

-

Để chạy một playbook trong Ansible, bạn cần có một danh sách các nút được quản lý được lưu trữ trong file “inventory”. Tệp “inventory” này giúp bạn tổ chức các nút của mình thành các nhóm và cung cấp thông tin như ansible_network_os và SSH user để Ansible có thể sử dụng để kết nối và quản lý các thiết bị mạng.

Khi sử dụng file inventory, một playbook có thể quản lý hàng trăm thiết bị mạng chỉ với một lệnh duy nhất. Điều này giúp tiết kiệm thời gian và nỗ lực của bạn khi quản lý nhiều thiết bị mạng.

Trang web của Ansible cung cấp hướng dẫn chi tiết về cách tạo file inventory bước một cách dễ dàng và hiệu quả.

Basic inventory

Trước tiên, bạn cần phân nhóm các thiết bị trong inventory một cách hợp lý. Thực hành tốt nhất là phân nhóm các máy chủ và thiết bị mạng theo What (ứng dụng, stack hoặc microservice), Where (trung tâm dữ liệu hoặc vùng), và When (giai đoạn phát triển):

  • What: db, web, leaf, spine
  • Where: east, west, floor_19, building_A
  • When: dev, test, staging, prod

Tránh sử dụng khoảng trắng, dấu gạch ngang và số đứng đầu (sử dụng floor_19, không phải 19th_floor) trong tên các nhóm. Tên các nhóm phân biệt chữ hoa và chữ thường.

Dưới đây là ví dụ về cấu trúc nhóm cơ bản của một trung tâm dữ liệu nhỏ. Bạn có thể nhóm các nhóm bằng cú pháp [tên nhóm cha: children] và liệt kê các nhóm là thành viên của nhóm cha. Ở đây, nhóm mạng bao gồm tất cả các leaf và tất cả các spine; nhóm datacenter bao gồm tất cả các thiết bị mạng cùng với tất cả các máy chủ web.

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
    leaf02:
      ansible_host: 10.16.10.12

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
    spine02:
      ansible_host: 10.16.10.14

network:
  children:
    leafs:
    spines:

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
    webserver02:
      ansible_host: 10.16.10.16

datacenter:
  children:
    network:
    webservers:

Inventory file cũng có thể được tạo dưới định dạng INI. Định dạng INI cũng là một cách phổ biến để tổ chức các thông tin về các nút được quản lý. Các nút có thể được phân loại thành các nhóm và các thông tin như địa chỉ IP, cổng SSH và hệ điều hành có thể được xác định cho từng nút.

Dưới đây là một ví dụ về một file INI đơn giản cho các nút mạng:

[leafs]
leaf01
leaf02

[spines]
spine01
spine02

[network:children]
leafs
spines

[webservers]
webserver01
webserver02

[datacenter:children]
network
webservers

Add variables to the inventory

Tiếp theo, bạn có thể thiết lập các giá trị cho nhiều biến mà bạn cần thiết trong lệnh Ansible đầu tiên của bạn trong inventory, để bạn có thể bỏ qua chúng trong lệnh ansible-playbook. Trong ví dụ này, inventory bao gồm địa chỉ IP, hệ điều hành và người dùng SSH của mỗi thiết bị mạng. Nếu các thiết bị mạng của bạn chỉ có thể truy cập qua địa chỉ IP, bạn phải thêm IP vào file inventory. Nếu bạn truy cập các thiết bị mạng của mình bằng tên máy chủ, thì địa chỉ IP không cần thiết.

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user
    leaf02:
      ansible_host: 10.16.10.12
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user
    spine02:
      ansible_host: 10.16.10.14
      ansible_network_os: vyos.vyos.vyos
      ansible_user: my_vyos_user

network:
  children:
    leafs:
    spines:

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
      ansible_user: my_server_user
    webserver02:
      ansible_host: 10.16.10.16
      ansible_user: my_server_user

datacenter:
  children:
    network:
    webservers:

Hoặc mình có 1 ví dụ khác.

[leafs]
leaf1 ansible_host=10.0.0.2 ansible_network_os=ios ansible_user=cisco

[spines]
spine1 ansible_host=10.0.0.1 ansible_network_os=ios ansible_user=cisco

[network:children]
leafs
spines

[datacenter:children]
network
webservers

Trong ví dụ này, các nhóm leaf và spine được tạo với các thông tin về địa chỉ IP, hệ điều hành và tên người dùng SSH được chỉ định cho mỗi nút. Nhóm network được tạo bằng cách sử dụng cú pháp [network:children] và liệt kê các nhóm thành viên của nó. Tương tự, nhóm datacenter được tạo bằng cách sử dụng [datacenter:children] và liệt kê network và nhóm webservers.

Group variables within inventory

Khi các thiết bị trong một nhóm chia sẻ các giá trị biến giống nhau, chẳng hạn như hệ điều hành hoặc SSH user, bạn có thể giảm thiểu sự trùng lặp và đơn giản hóa việc bảo trì bằng cách tập trung chúng vào các biến nhóm:

Ví dụ, trong file inventory, bạn có thể định nghĩa một biến nhóm là ansible_network_os để chỉ định hệ điều hành của các thiết bị trong nhóm đó:

[network_devices]
switch1 ansible_host=192.168.1.10 ansible_network_os=ios ansible_user=admin
switch2 ansible_host=192.168.1.11 ansible_network_os=junos ansible_user=admin

[network_devices:vars]
ansible_ssh_pass=my_password

Ở đây, biến ansible_network_os được đặt trong nhóm network_devices để chỉ định hệ điều hành của các thiết bị trong nhóm này. Bạn cũng có thể sử dụng biến ansible_user để chỉ định tên người dùng SSH sử dụng để kết nối với các thiết bị. Cuối cùng, biến ansible_ssh_pass được đặt trong một phần tử vars trong nhóm để chỉ định mật khẩu SSH. Với cấu hình này, bạn có thể sử dụng Ansible để thực thi các tác vụ trên các thiết bị trong nhóm network_devices mà không cần phải cung cấp các biến này trong lệnh ansible-playbook.

Hoặc mình có 1 ví dụ khác.

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
    leaf02:
      ansible_host: 10.16.10.12
  vars:
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
    spine02:
      ansible_host: 10.16.10.14
  vars:
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user

network:
  children:
    leafs:
    spines:

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
    webserver02:
      ansible_host: 10.16.10.16
  vars:
    ansible_user: my_server_user

datacenter:
  children:
    network:
    webservers:

Variable syntax

Cú pháp để khai báo giá trị biến khác nhau trong Ansible Inventory, playbook và các file group_vars khác nhau.

  • Trong file inventory theo kiểu ini, bạn phải sử dụng cú pháp key=value để khai báo giá trị biến: ansible_network_os=vyos.vyos.vyos.
  • Trong bất kỳ file nào có phần mở rộng .yml hoặc .yaml, bao gồm playbook và file group_vars, bạn phải sử dụng cú pháp YAML: key: value.
  • Trong file group_vars, sử dụng tên đầy đủ của khóa: ansible_network_os: vyos.vyos.vyos.
  • Trong playbook, sử dụng tên viết tắt của khóa, loại bỏ tiền tố ansible: network_os: vyos.vyos.vyos.
---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
    leaf02:
      ansible_host: 10.16.10.12

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
    spine02:
      ansible_host: 10.16.10.14

network:
  children:
    leafs:
    spines:
  vars:
    ansible_connection: ansible.netcommon.network_cli
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
    webserver02:
      ansible_host: 10.16.10.16
  vars:
    ansible_user: my_server_user

datacenter:
  children:
    network:
    webservers:

Group inventory by platform

Khi danh sách inventory của bạn lớn lên, bạn có thể muốn nhóm các thiết bị theo nền tảng để dễ dàng chỉ định các biến đối với tất cả các thiết bị trên nền tảng đó. Ví dụ dưới đây minh họa cách sử dụng group_vars để định nghĩa biến ansible_network_os cho các thiết bị Cisco IOS, Junos, và VyOS:

# inventory
[cisco_ios]
router1
router2

[junos]
switch1
switch2

[vyos]
firewall1
firewall2

[ios:children]
cisco_ios

[network:children]
ios
junos
vyos

# group_vars/network.yml
---
ansible_network_os: junos.junos.junos
---
ansible_network_os: ios.ios.ios
---
ansible_network_os: vyos.vyos.vyos

Như vậy, trong file inventory của bạn, các thiết bị Cisco IOS được nhóm lại trong group cisco_ios, các thiết bị Junos được nhóm lại trong group junos, và các thiết bị VyOS được nhóm lại trong group vyos. Các group này được sử dụng trong các metagroup iosnetwork.

Bạn cũng có thể định nghĩa các biến cho tất cả các thiết bị trên cùng một nền tảng bằng cách sử dụng file group_vars. Ví dụ trên định nghĩa biến ansible_network_os cho các thiết bị trên ba nền tảng IOS, Junos, và VyOS. Trong đó, biến ansible_network_os cho các thiết bị Cisco IOS được định nghĩa trong file group_vars/ios.yml, biến cho các thiết bị Junos được định nghĩa trong file group_vars/junos.yml, và biến cho các thiết bị VyOS được định nghĩa trong file group_vars/vyos.yml.

Thêm 1 ví dụ khác.

---

leafs:
  hosts:
    leaf01:
      ansible_host: 10.16.10.11
    leaf02:
      ansible_host: 10.16.10.12

spines:
  hosts:
    spine01:
      ansible_host: 10.16.10.13
    spine02:
      ansible_host: 10.16.10.14

network:
  children:
    leafs:
    spines:
  vars:
    ansible_connection: ansible.netcommon.network_cli
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user

webservers:
  hosts:
    webserver01:
      ansible_host: 10.16.10.15
    webserver02:
      ansible_host: 10.16.10.16
  vars:
    ansible_user: my_server_user

datacenter:
  children:
    network:
    webservers:

Với cấu hình này, bạn có thể chạy playbook first_playbook.yml chỉ với hai cờ:

ansible-playbook -i inventory.yml -k first_playbook.yml 

Với cờ -k, bạn cung cấp mật khẩu SSH tại nhắc lệnh. Ngoài ra, bạn có thể lưu trữ các bí mật SSH và mật khẩu khác một cách an toàn trong các file group_vars của mình với ansible-vault. Xem Chi tiết bảo vệ các biến nhạy cảm với ansible-vault để biết thêm thông tin.

Verifying the inventory

Lệnh ansible-inventory CLI cho phép hiển thị inventory file dưới dạng Ansible. Khi sử dụng lệnh này, bạn có thể kiểm tra inventory đã được tạo chính xác chưa. Các tùy chọn trong lệnh này cho phép bạn xem inventory dưới nhiều dạng khác nhau, bao gồm JSON, YAML hoặc một số định dạng khác. Bạn cũng có thể sử dụng lệnh này để hiển thị thông tin về các biến được cấu hình trong inventory. Việc kiểm tra inventory thường được thực hiện để đảm bảo rằng mọi thiết bị đã được đăng ký đầy đủ và chính xác trong inventory và các biến cũng đã được đặt đúng giá trị.

ansible-inventory -i test.yml --list
  {
    "_meta": {
        "hostvars": {
            "leaf01": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.11",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "leaf02": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.12",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "spine01": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.13",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "spine02": {
                "ansible_connection": "ansible.netcommon.network_cli",
                "ansible_host": "10.16.10.14",
                "ansible_network_os": "vyos.vyos.vyos",
                "ansible_user": "my_vyos_user"
            },
            "webserver01": {
                "ansible_host": "10.16.10.15",
                "ansible_user": "my_server_user"
            },
            "webserver02": {
                "ansible_host": "10.16.10.16",
                "ansible_user": "my_server_user"
            }
        }
    },
    "all": {
        "children": [
            "datacenter",
            "ungrouped"
        ]
    },
    "datacenter": {
        "children": [
            "network",
            "webservers"
        ]
    },
    "leafs": {
        "hosts": [
            "leaf01",
            "leaf02"
        ]
    },
    "network": {
        "children": [
            "leafs",
            "spines"
        ]
    },
    "spines": {
        "hosts": [
            "spine01",
            "spine02"
        ]
    },
    "webservers": {
        "hosts": [
            "webserver01",
            "webserver02"
        ]
    }
  }

Protecting sensitive variables with ansible-vault

Trong Ansible, lệnh ansible-vault cung cấp tính năng mã hóa cho các tập tin và/hoặc biến như mật khẩu. Bạn có thể sử dụng lệnh này để mã hóa nhiều thông tin nhạy cảm khác, chẳng hạn như mật khẩu cơ sở dữ liệu, mật khẩu nâng cao quyền và nhiều hơn nữa.

Đầu tiên, bạn cần tạo mật khẩu cho ansible-vault. Nó được sử dụng như khóa mã hóa, và với nó, bạn có thể mã hóa hàng chục mật khẩu khác nhau trong dự án Ansible của mình. Bạn có thể truy cập tất cả những bí mật đó (giá trị đã mã hóa) bằng một mật khẩu duy nhất (mật khẩu ansible-vault) khi chạy các playbook của mình. Dưới đây là một ví dụ đơn giản.

Tạo một file và viết mật khẩu cho ansible-vault vào đó:

echo “my-ansible-vault-pw” > ~/my-ansible-vault-pw-file Tạo mật khẩu SSH đã mã hóa cho các thiết bị mạng VyOS của bạn, lấy mật khẩu ansible-vault của bạn từ file bạn vừa tạo:

ansible-vault encrypt_string –vault-id my_user@~/my-ansible-vault-pw-file ‘VyOS_SSH_password’ –name ‘ansible_password’ Nếu bạn muốn gõ mật khẩu ansible-vault thay vì lưu trữ nó trong một file, bạn có thể yêu cầu nhập:

ansible-vault encrypt_string –vault-id my_user@prompt ‘VyOS_SSH_password’ –name ‘ansible_password’ và nhập mật khẩu vault cho my_user.

Cờ –vault-id cho phép các mật khẩu vault khác nhau cho các người dùng hoặc các cấp độ truy cập khác nhau. Kết quả bao gồm tên người dùng my_user từ lệnh ansible-vault của bạn và sử dụng cú pháp YAML key: value:

ansible_password: !vault |
       $ANSIBLE_VAULT;1.2;AES256;my_user
       66386134653765386232383236303063623663343437643766386435663632343266393064373933
       3661666132363339303639353538316662616638356631650a316338316663666439383138353032
       63393934343937373637306162366265383461316334383132626462656463363630613832313562
       3837646266663835640a313164343535316666653031353763613037656362613535633538386539
       65656439626166666363323435613131643066353762333232326232323565376635
Encryption successful

Đây là một ví dụ sử dụng trích dẫn từ một inventory YAML, vì định dạng INI không hỗ trợ inline vaults:

...

vyos: # this is a group in yaml inventory, but you can also do under a host
  vars:
    ansible_connection: ansible.netcommon.network_cli
    ansible_network_os: vyos.vyos.vyos
    ansible_user: my_vyos_user
    ansible_password:  !vault |
         $ANSIBLE_VAULT;1.2;AES256;my_user
         66386134653765386232383236303063623663343437643766386435663632343266393064373933
         3661666132363339303639353538316662616638356631650a316338316663666439383138353032
         63393934343937373637306162366265383461316334383132626462656463363630613832313562
         3837646266663835640a313164343535316666653031353763613037656362613535633538386539
         65656439626166666363323435613131643066353762333232326232323565376635

 ...

Để sử dụng biến inline được mã hóa bằng ansible-vault với inventory ở định dạng INI, bạn cần lưu nó vào một file ‘vars’ ở định dạng YAML. File này có thể nằm trong thư mục host_vars/ hoặc group_vars/ để tự động được chọn hoặc được tham chiếu từ một play thông qua vars_files hoặc include_vars.

Để chạy một playbook với cấu hình này, hãy loại bỏ cờ -k và thêm một cờ cho vault-id của bạn.

ansible-playbook -i inventory --vault-id my_user@~/my-ansible-vault-pw-file first_playbook.yml

Nếu bạn không muốn lưu mật khẩu Ansible Vault vào một tập tin, bạn có thể yêu cầu Ansible yêu cầu mật khẩu trực tiếp từ người dùng bằng cờ --vault-id prompt. Khi chạy lệnh này, Ansible sẽ yêu cầu bạn nhập mật khẩu Vault để tiếp tục thực hiện. Ví dụ:

ansible-playbook -i inventory --vault-id my_user@prompt first_playbook.yml

Khi chạy lệnh này, Ansible sẽ hỏi bạn nhập mật khẩu Vault trước khi thực hiện playbook. Bạn chỉ cần nhập mật khẩu và chờ Ansible tiếp tục thực hiện các task của playbook.

Module debug trong Ansible dùng để hiển thị thông tin debugging, giúp cho việc tìm lỗi và kiểm tra các giá trị của các biến trong playbook dễ dàng hơn.

Để hiển thị giá trị ban đầu của một biến sau khi nó đã được mã hóa bằng ansible-vault, ta có thể sử dụng module debug. Lưu ý nếu file YAML của bạn xác định biến ansible_connection (như chúng ta đã sử dụng trong ví dụ của chúng ta), nó sẽ có hiệu lực khi bạn thực thi lệnh debug. Để tránh điều này, hãy sao chép file mà không có biến ansible_connection.

cat vyos.yml | grep -v ansible_connection >> vyos_no_connection.yml

ansible localhost -m debug -a var="ansible_password" -e "@vyos_no_connection.yml" --ask-vault-pass
Vault password:

localhost | SUCCESS => {
    "ansible_password": "VyOS_SSH_password"
}

Cảnh báo:

Trong Ansible, nội dung của vault chỉ có thể được giải mã bằng mật khẩu đã được sử dụng để mã hóa nó. Nếu bạn muốn dừng sử dụng mật khẩu cũ và chuyển sang mật khẩu mới, bạn có thể cập nhật và mã hóa lại nội dung vault hiện có bằng lệnh ansible-vault rekey myfile, sau đó cung cấp mật khẩu cũ và mật khẩu mới. Các bản sao của nội dung vault vẫn được mã hóa với mật khẩu cũ và có thể được giải mã với mật khẩu cũ.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories