https://blog.csdn.net/O4dC8OjO7ZL6/article/details/79765539 css
點擊上方「中興開發人員社區」,關注咱們html
天天讀一篇一線開發人員原創好文node
前言python
近期在重構一款命令行工具。使用 golang 又一次開發。但需要繼續維持原有的命令,同一時候添加新命令。golang
在重構的過程當中,需要對現命令行工具和原命令行工具的命令輸出結果進行比對,確保全然一致(項目要求)。命令行工具需要在部署完畢系統以後進行使用,每個系統完畢時的部署組件又略微有點差別。web
因此事實上需要在多套服務主機上進行測試。shell
需要作這些動做:編程
拷貝一些配置文件到主機上:用戶配置、IP和port文件api
安裝命令行工具,確保使其在服務主機上可以使用數組
運行一堆測試命令
按理說,我不斷把需要的配置和二進制文件複製到主機上進行測試也能完畢。
但在使用的過程當中存在如下幾個問題:
測試發現,結果不正確時需要及時改動代碼。再次拷貝二進制文件到主機上
主機環境需要屢次推倒,又一次部署,驗證版本號更新問題
需要手動一個一個命令的運行
測試有幾套主機
看上去手動的方法。有點費勁。
眼下我從事的工做就是 PaaS
部署相關的,部署層面的腳本的運行、組件的安裝、服務的啓動等都是使用 Ansible 來操做。詳細的腳本編寫由其它同事,我僅僅知道這個東西是幹嗎的。沒實質性的學習。因而想借這個機會主動學習下 Ansible.
學習之處,差點犯了老問題,即:從頭開始看官方文檔,而不注重當前需要解決的問題。
因爲事實上整個 Ansible 的內容體系很是多。
不注重當前需要解決的問題,會致使你抓不住重點。
意識到後專一在當前需要解決的問題上:
拷貝配置文件和安裝腳本到多個主機上
在多個主機上測試命令行工具
看了上面的事件背景。你大概知道這個 Ansible 到底是個什麼東西。
Ansible 是一個配置管理和應用部署工具。即在管理主機上操做一些命令就能在節點主機上進行對應的動做。由 Python 編寫。由模塊化組成,即運行動做的實體。在 ansible 上都是靠着對應的模塊運行動做,比方拷貝 copy 模塊、運行 command 模塊、shell 模塊、文件 file 模塊等。
Ansible 的目標有例如如下:
本身主動化部署應用
本身主動化管理配置
本身主動化的持續交付
本身主動化的(AWS)雲服務管理。
管理主機從 hosts 裏讀取主機清單,經過 playbook 按順序同一時候對管理的主機進行對應的操做。
如圖:
管理主機主要是對主機的定義和配置、編寫 playbook(即節點主機的運行動做)。
運行:
1. 命令行
ansible all -m ping
2. playbook
ansible-playbook example.yml
編輯文件:/etc/ansible/hosts
即:定義主機名稱,變量等
主機的變量包括什麼: 主機的運行用戶、鏈接port、password等
類似於 ini 格式的文件
[test-new-cli] 10.62.60.72 [test-old-cli] 10.62.62.88
上面的樣例:將兩個主機的分爲兩組:test-new-cli
和 test-old-cli
主機的變量有這麼些:
ansible_ssh_host
將要鏈接的遠程主機名.與你想要設定的主機的別名不一樣的話,可經過此變量設置.
ansible_ssh_port
sshport號.假設不是默認的port號,經過此變量設置.
ansible_ssh_user
默認的 ssh username
ansible_ssh_pass
ssh password(這樣的方式並不安全,咱們強烈建議使用 —ask-pass 或 SSH 密鑰)
ansible_sudo_pass
sudo password(這樣的方式並不安全,咱們強烈建議使用 —ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)
sudo 命令路徑(適用於1.8及以上版本號)
ansible_connection
與主機的鏈接類型.比方:local, ssh 或者 paramiko.
ansible_ssh_private_key_file
ssh 使用的私鑰文件.適用於有多個密鑰,而你不想使用 SSH 代理的狀況.
ansible_shell_type
目標系統的shell類型.默認狀況下,命令的運行使用 ‘sh’ 語法,可設置爲 ‘csh’ 或 ‘fish’.
ansible_python_interpreter
目標主機的 python 路徑.
看不懂怎麼用:
舉個樣例,你想鏈接主機 192.168.100.100
, 切換到 root 用戶下運行對應的操做。
假設你直接ssh username@192.168.100.100
會要求你輸入username和password。
假如我編輯主機清單使得本身不需要輸入usernamepassword,怎麼操做?
[test-new-cli] example ansible_ssh_host=192.168.100.100 ansible_ssh_user=username ansible_ssh_pass=root
即配置好192.168.100.100
的主機別名爲example
, 主機的username和password爲:username/root
包括三種類型:
鍵值對:key: value
數組
純量:整型、字符串、布爾型
這個很是好理解:假設你熟悉Python, 這三種類型就至關於:map, list, 變量
假設你熟悉golang, 這三種類型就至關於: map, 數組。 變量
演示樣例:
--- - name: "execute command nodepool node list by { {item.name} }" shell: "{ {item.cli} } nodepool node list { {item.id} }" register: result - name: show result debug: msg: "{ {result.stdout_lines} }" with_items: - { name: "new-cli", cli: "new-cli", id: "1" } - { name: "old-cli", cli: "old-cli", id: "1" }
ansible 命令行式,適合運行單條命令。
# 操做 192.168.100.100 主機。看管理主機是否和192.168.100.100的主機連通 ansible example -m ping # 操做 192.168.100.100 主機,拷貝管理主機下的/root/opcli/conf 文件至節點主機/etc/opcli/conf 下 ansible test-new-cli -m copy -a="src=/root/opcli/conf dest=/etc/opcli/conf"
m: 模塊
a: 接參數
可以看出適合運行單條命令
假如你的節點主機分組很是多了。Ad-hoc 怎樣選擇特定特徵的節點主機分組呢?
使用類正則表達式。
比方觸發所有節點主機進行動做:
ansible all -m ping ansible * -m ping 二者等價,都是選擇所有的節點主機
演示樣例:
one.example.com one.example.com:two.example.com 192.168.1.50 192.168.1.*
webservers webservers:dbservers
webservers:!phoenix # 隸屬 webservers 組但同一時候不在 phoenix組
webservers:&staging # 同一時候隸屬於 webservers 和 staging 組
webservers[0] webservers[0-25]
有什麼需求,看官方文檔吧。
編寫 yaml 文件。適合運行多步操做的複雜操做。可以當作是Ad-doc 命令的集合。甚至可以當作是一門編程語言。
運行:ansible-playbook example.yml
依照 example.yml 文件中的任務集合按步運行任務。
命令演示樣例,僅舉幾例。有帶參數、有沒帶參數的。
咱們終於的目標是:在節點主機上運行這些命令進行比對二者結果。
新版本號:
命令 | 說明 |
---|---|
command-cli nodepool list | 查詢資源池 |
command-cli nodepool node list | 查詢資源池節點 |
command-cli node list | 查詢節點 |
command-cli node show | 查詢某個節點 |
command-cli task list | 查詢部署任務 |
…
舊版本號:
命令 | 說明 |
---|---|
old-cli nodepool list | 查詢資源池 |
old-cli nodepool node list | 查詢資源池節點 |
old-cli node list | 查詢節點 |
old-cli node show | 查詢某個節點 |
old-cli task list | 查詢部署任務 |
…
文件夾結構:
demo-for-ansible: ---nodepool/nodepool-list.yml ---nodepool/nodepool-node-list.yml ---node/node-list.yml ---node/node-show.yml ---task/task-list.yml ---main.yml
/etc/ansible/hosts
[test_client] 192.168.100.100 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh 192.168.100.101 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh 192.168.100.102 ansible_ssh_user=xiewei ansible_ssh_pass=root ansible_connection=ssh
定義主機鏈接類型、username、password
主要動做:
在節點主機上建立兩個文件夾: /etc/client/conf
和 /et/client/commands
拷貝管理主機文件夾:/etc/client/conf
文件至節點主機: /etc/client/conf
拷貝管理主機二進制文件:/root/gosrc/src/client/command-cli
至節點主機 /etc/client/commands
軟鏈接節點主機二進制文件:/etc/client/commands/command-cli
至節點主機 /usr/bin/command-cli
運行上表中查詢命令:nodepool, node, task
main.yml
--- - hosts: test_client remote_user: root become: yes become_user: root become_method: sudo tasks: # 在節點主機上建立文件夾:/etc/client/conf - name: create /etc/client/conf /etc/client/commands file: path: "/etc/client/{ {item} }" owner: root group: root mode: 0755 state: directory with_items: - "conf" - "commands" # 拷貝管理主機配置文件/etc/client/conf和二進制文件至 /etc/client/conf, /etc/client/commands - name: copy /etc/client/conf copy: src="{ { item.src } }" dest="{ { item.dest } }" owner=root group=root mode=0644 with_items: - { src: "/etc/client/conf", dest: "/etc/client/conf" } - { src: "/root/gosrc/src/client/command-cli", dest: "/etc/client/commands"} # 軟鏈接到 /usr/bin/command-cli - name: link /etc/client/commands file: src="/etc/client/commands/command-cli" dest="/usr/bin/command-cli" state=link # nodePool list - include_tasks: "nodepool/nodepool-list.yml" with_items: - { client: "new client", name: "command-cli"} - { client: "old client", name: "old-cli"} # nodePool node list <id> - include_tasks: "nodepool/nodepool-node-list.yml" with_items: - { id: "1", client: "new client", name: "command-cli"} - { id: "1", client: "old client", name: "old-cli"} # node list - include_tasks: "node/node-list.yml" with_items: - { client: "new client", name: "command-cli"} - { client: "old client", name: "old-cli"} # node show <id> - include_tasks: "node/node-show.yml" with_items: - { client: "new client", name: "command-cli", id: 1} - { client: "old client", name: "old-cli", id: 1} # task list - include_tasks: "task/task-list.yml" with_items: - { client: "new client", name: "command-cli"} - { client: "old client", name: "old-cli"}
task-list.yml
--- - name: execute command task list shell: "{ {item.name} } task list" register: result - name: show result debug: msg: "{ {result.stdout_lines} }"
兩種方法
ansible-playbook main.yml --syntax-check
先安裝 pip install ansible-lint
ansible-lint main.yml
ansible-playbook main.yml
整個的編寫流程大概是這樣。核心是編寫 yml 文件,調用 ansible 支持的各類模塊完畢任務。
熟悉 playbook
熟悉 ansible 模塊
熟悉 ansible api
關注你當前需要解決的問題,切入學習,事半功倍。