筆記 ansible 操作方法
ansible 目錄結構 ansible.cfg # 參數 hosts # 要被執行的主機
ansible.cfg [defaults] inventory = hosts private_key_file=/path/to/file.pem hosts # yml 也可以 [webservers] 192.168.5.141 192.168.5.142 192.168.5.143
LAB 環境建立
開始前先建立 LAB 環境 使用 vagrant 建立 1 台 mgmt 及 3 台 node 由 mgmt 執行 ansible 控制 3 台 node
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
# box 來源
config.vm.box = "rockylinux.box"
# box 驗證方式
config.ssh.username = "root"
config.ssh.password = "P@ssw0rd"
# 設定 VM 資源及使用 link clone 節省 host 空間
config.vm.provider "virtualbox" do |v|
v.linked_clone = true
v.memory = 2048
v.cpus = 2
end
# 使用迴圈建立大量 VM
(1..3).each do |i|
# Defining VM properties
config.vm.define "rockylinux_vm#{i}" do |node|
node.vm.hostname = "node#{i}.local"
node.vm.network "public_network", ip: "192.168.15.#{140+machine_id}"
end
end
# 建立單一VM
config.vm.define "rockylinux_mgmt" do |mgmt|
mgmt.vm.hostname = "mgmt.local"
# 設定 public 網卡,讓 host 能夠連線
mgmt.vm.network "public_network", ip: "192.168.15.100"
end
end
安裝
ansible 需使用 python3 (目前 ansible 需 python 3.8 以上) 連線至 mgmt 安裝套件
dnf install -y git wget vim bash-completion curl jq tar iproute-tc python39 sshpass
wget https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py
# check version is python3.9
python3 -V
pip3 -V
pip3 install ansible
ansible --version
[root@mgmt ~]# ansible --version
ansible [core 2.12.2]
config file = None
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.9.6 (default, Nov 9 2021, 13:31:27) [GCC 8.5.0 20210514 (Red Hat 8.5.0-3)]
jinja version = 3.0.3
libyaml = True
測試執行
控制本機執行 ping
[root@mgmt ~]# ansible localhost -m "ping"
[WARNING]: No inventory was parsed, only implicit localhost is available
localhost | SUCCESS => {
"changed": false,
"ping": "pong"
}
控制遠端執行 ping
mkdir ansible-lab
cd ansible-lab
cat <<EOF>> inventory
all:
hosts:
192.168.15.141:
192.168.15.142:
192.168.15.143:
vars:
ansible_connection: ssh
ansible_user: root
ansible_ssh_pass: P@ssw0rd
EOF
[root@mgmt ansible-lab]# ansible -i inventory all --list-hosts
hosts (3):
192.168.15.141
192.168.15.142
192.168.15.143
# 關閉 ssh fingerprint 是否接受
cat <<EOF>> /etc/ssh/ssh_config
StrictHostKeyChecking no
EOF
# 建立 inventory file 給 ansible 連線用
==========================
# 執行指令
[root@mgmt ansible-lab]# ansible -i inventory all -m ping
192.168.15.143 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.15.141 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.15.142 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
# 或是不在 inventory 設定帳密
ansible all -i host.yaml -m "ping" --extra-vars "ansible_user=root
使用 ansible-vault
前面的設定檔我們將帳密寫在 inventory 中,在資安中會是不小的風險
ansible-vault
提供將我們的設定檔或是字串做加密保護的動作
參考文章 https://www.digitalocean.com/community/tutorials/how-to-use-vault-to-protect-sensitive-ansible-data
ansible 分為加密變數及加密整個檔案
加密整個 yaml 檔案
優點: 安全性提升,可以使用 rekey 重新加密 缺點: 不易閱讀內容
# 加密
ansible-vault encrypt <filename.yaml>
# 查看
ansible-vault view <filename.yaml>
# 編輯
ansible-vault edit <filename.yaml>
# 解密
ansible-vault decrypt <filename.yaml>
# 執行
ansible -i inventory-var-encrypte all -m ping --ask-vault-pass
# rekey 重新加密
ansible-vault rekey <filename.yaml>
Vault password:
New Vault password:
Confirm New Vault password:
加密後的檔案
[root@mgmt ansible-lab]# cat inventory-var-encrypte
$ANSIBLE_VAULT;1.1;AES256
39666135363865333833353138333630376465356563313435376135396231653435316536653739
3831623130366136323663383862333730616538366234610a363764616437316630656632643134
64626164356532373134636534633336383130633063326331623936626266386137306330616164
3938366563346530300a313233373866626565653234396538363663363335636366326664373430
37383361396439353236363132633963356464663236396666636331386434383631663533653431
33313235306464633931653538613862343535323264653932376463333032636431373935623462
35393531663364393365633834636463616231623438613938326239626234303366363637303861
62616665386138383862303935393937663832373738613963626262663033643839373432613331
61663666643065623161353162306338633439643262616631383035393732313134666637353231
31646434623766346465646435376639306666396565633562666464383362343065343433383662
62333966323034633936396230666664343166636262333538663462373061303837356433613030
33383936313263313263393765376533653766356662623365376265333435656536333735626431
加密變數
優點: 只加密變數,使檔案維持易讀性 缺點: 無法直接更新加密過的變數
加密變數稍微不同的點在於 加密的執行跟輸出是採用 stdin 、 stdout
舉例 原本 var-crypt.yaml 檔如此
--- #定義該檔為 yaml format
all:
hosts:
192.168.15.141:
192.168.15.142:
192.168.15.143:
vars:
ansible_connection: ssh
ansible_user: root
ansible_ssh_pass: P@ssw0rd
將 ansible_ssh_pass 進行加密
[root@mgmt ansible-lab]# ansible-vault encrypt_string -n 'ansible_ssh_pass' 'P@ssw0rd'
New Vault password:
Confirm New Vault password:
ansible_ssh_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
35643435323937363061666532643633653839643739623562396438306637633939336137363130
6330393833313533633765343537306438663835326333610a646466303963643935393135636439
63303036303135633732343966653639636464393264646664656665623839633038393364396439
3566323366353361300a353139306230666664303038303966393732336465666136623265383561
3937
Encryption successful
跟前面 file encrypt 比較 加密的開頭從 $ANSIBLE_VAULT 變成 ansible_ssh_pass: !vault 在把這串加密過後的輸出存至 var-crypt.yaml 內
--- #定義該檔為 yaml format
all:
hosts:
192.168.15.141:
192.168.15.142:
192.168.15.143:
vars:
ansible_connection: ssh
ansible_user: root
ansible_ssh_pass: !vault |
$ANSIBLE_VAULT;1.1;AES256
35643435323937363061666532643633653839643739623562396438306637633939336137363130
6330393833313533633765343537306438663835326333610a646466303963643935393135636439
63303036303135633732343966653639636464393264646664656665623839633038393364396439
3566323366353361300a353139306230666664303038303966393732336465666136623265383561
3937
如此即完成變數加密 測試執行
[root@mgmt ansible-lab]# ansible -i var-crypt.yaml all -m ping --ask-vault-pass
Vault password:
192.168.15.143 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.15.141 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.15.142 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
更多人的作法是將跟機密有關係的內容另存一個 yaml 檔 再加密此 yaml
使用密碼檔進行加密
前面的範例皆為使用輸入密碼的方式進行加解密 可以使用密碼檔的方式進行加解密動作
# 建立密碼檔
echo 'my_vault_password' > .vault_pass
# git 排除密碼檔
echo '.vault_pass' >> .gitignore
# 使用時,加上 --vault-password-file=.vault_pass 即可
ansible-vault encrypt --vault-password-file=.vault_pass vault-pass.yaml
ansible-vault view --vault-password-file=.vault_pass vault-pass.yaml
# Reading the Password File Automatically
export ANSIBLE_VAULT_PASSWORD_FILE=./.vault_pass
ansible-playbook
再前面的範例中
用的 ansible
指令、都只執行單行命令(ad-hoc commands)
要能夠執行多個指令
要使用 ansible-playbook
playbook 就是將執行的指令寫成多個檔案,像讀一本 book 一般進行執行
關於 yaml 的格式 可以看 https://github.com/ansible/ansible/tree/devel/examples 做參考
以 ansible-playbook 執行 多個指令
在前面的目標,將目標行寫成多個檔案 ansible.cfg hosts.yaml main.yaml
ansible.cfg ansible 在執行時會找目前目錄下的 ansible.cfg 作為每次要帶入的參數
[defaults]
# 主機清單
inventory = hosts.yaml
# 同步執行數量
forks = 5
# 不跳出 SSL 警告避免中斷
host_key_checking = False
這裡將主機分成兩個 group (webservers,testing) hosts.yaml
--- #定義該檔為 yaml format
webservers:
hosts:
192.168.15.141:
192.168.15.142:
testing:
hosts:
192.168.15.143:
接著寫一個 main.yaml 來作為所有執行階段的起點 main.yaml
---
- hosts: webservers
tasks:
- name: running ping
ping:
- hosts: testing
tasks:
- name: running setup
setup:
執行語法檢查
ansible-playbook --syntax-check main.yaml
執行 play book
[root@mgmt ansible-lab]# ansible-playbook main.yaml
PLAY [webservers] *******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************************************************************
ok: [192.168.15.142]
ok: [192.168.15.141]
TASK [running ping] *****************************************************************************************************************************************************************************************************
ok: [192.168.15.142]
ok: [192.168.15.141]
PLAY [testing] **********************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************************************************************
ok: [192.168.15.143]
TASK [running setup] ****************************************************************************************************************************************************************************************************
ok: [192.168.15.143]
PLAY RECAP **************************************************************************************************************************************************************************************************************
192.168.15.141 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.15.142 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
192.168.15.143 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
其他
Setting the Ansible Vault Editor
nano ~/.bashrc
export EDITOR=nano
# or one time config
EDITOR=nano ansible-vault . . .
extra-vars
使用帳密登入
ansible all -i host.yaml -m "ping" --extra-vars "ansible_user=root ansible_password=P@ssw0rd"
plugin-index https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html#plugin-index
absent | present
present = install absent = uninstall