此文件僅張聰明同學個人筆記;新負責KTH-RPL Cluster GPU的漫漫學習長路
English Docs:
中文相關文件:
- https://ansible.leops.cn/basic/Quickstart/
- https://blog.csdn.net/xinshuzhan/article/details/115915698 ← 這篇博文寫的更為仔細
請注意下面有引用框的 均為這些參考文件中的話語,相關圖片也由他們而來,不再在文中單獨說明
測試學習階段 請不要執行危險的指令,比如 rm -rf * 當然你沒有sudo的話 刪的只是自己使用者下的 問題不大,切記管理人員 不要執行 自己直接copy過來看都沒看的script 或者 指令! 建議以下學習時,就列印列印資訊
簡要介紹
Ansible是一款為類Unix系統開發的自由開源的配置和自動化工具。
它用Python寫成,類似於saltstack和Puppet,但是有一個不同和優點是我們不需要在節點中安裝任何客戶端。 它使用SSH來和節點進行通訊。
Ansible基於 Python paramiko 開發,分散式,無需客戶端,輕量級,配置語法使用 YMAL 及 Jinja2模板語言,更強的遠端命令執行操作。
主要呢 可以透過這幅圖看出來,也就是東西是裝在你自己的主機上的:
- 透過 主機清單 和playbooks進行配置 當然也可以單獨就執行一段指令 後續的實踐部分再介紹
- 主機【也就是自己的電腦】透過SSH 進行其他機器的連線
- 然後就可以 快樂一個ansible 所有ssh 機器都執行
所以ansible 是安裝在自己電腦上的 [沒錯 我一開始以為每個node server都得裝 hhhh 理解沒到位
安裝
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible
當然因為本身是Python 程式碼 可以透過pip install或者是conda install進行library的安裝,建議感興趣的可以看 官方文件的 這個部分
安裝完後 第一件事! 所有的工具類 安裝完後都可以試著執行 —help 去快速瞭解指令
ansible --help
常用指令開頭為 擷取至 官方文件 建議都再次 --help
:
ansible
ansible-inventory
ansible-playbook
ansible-config
ansible-console
ansible-doc
ansible-galaxy
ansible-pull
ansible-vault
初步嘗試
根據上面簡要介紹中內容,我們首先確定一下 ansible 知道的host 應該是什麼? 才能去連線到各個節點進行指令執行
設定 host
根據官方文件 我們得知 應該要寫一個 /etc/ansible/hosts
內容大概長這樣
mail.example.com
[webservers]
foo.example.com
bar.example.com
[dbservers]
one.example.com
two.example.com
three.example.com
-
然後我們回到自己電腦上可以看到 有一個這樣的檔案 開啟雖然都註釋掉了 但也能理解
# # - Comments begin with the '#' character # - Blank lines are ignored # - Groups of hosts are delimited by [header] elements # - You can enter hostnames or ip addresses # - A hostname/ip can be a member of multiple groups # Ex 1: Ungrouped hosts, specify before any group headers: ## green.example.com ## blue.example.com ## 192.168.100.1 ## 192.168.100.10 # Ex 2: A collection of hosts belonging to the 'webservers' group: ## [webservers] ## alpha.example.org ## beta.example.org ## 192.168.1.100 ## 192.168.1.110 # If you have multiple hosts following a pattern, you can specify # them like this: ## www[001:006].example.com # Ex 3: A collection of database servers in the 'dbservers' group: ## [dbservers] ## ## db01.intranet.mydomain.net ## db02.intranet.mydomain.net ## 10.25.1.56 ## 10.25.1.57 # Here's another example of host ranges, this time there are no # leading 0s: ## db-[99:101]-node.example.com
對於伺服器的話 因為之前我們有寫在 ~/.ssh/config
大概一個config長這樣:
Host Server3
HostName xxx # ip or hostnames
IdentityFile ~/.ssh/id_rsa
Port xxx # 可連通的Port節點
User xxx # node節點上登入的使用者名稱
Host Server10
HostName xxx # ip or hostnames
IdentityFile ~/.ssh/id_rsa
Port xxx # 可連通的Port節點
User xxx # node節點上登入的使用者名稱
-
如果是給是我之前那樣的設定的話 我會把 ``/etc/ansible/hosts` 寫成這樣:
[local] localhost ansible_connection=local ansible_python_interpreter=/usr/bin/python3 [compute] Server3 Server5 Server8 Server4 Server12 Server13 Server11 [cluster:children] compute [cluster:vars] ansible_python_interpreter=/usr/bin/python3
列印 graph
然後 設定完成後,儲存退出,在終端輸入:
ansible-inventory --graph --vars
比如我的設定完 伺服器的所有節點:
執行 command
首先我們測試幾個點,然後再仔細解釋一下 即更進階的版本
小試一下 連通這些節點 :
ansible cluster -m ping
可以看到 server3 不能被連通 其他的都可
那麼我們再試一下 讀取所有伺服器上的的gpu 狀態
ansible cluster -m command -a "nvidia-smi"
好了,是時候要解釋一下了 【再次提醒 --help
是個好東西】:
-
ansible
使用的工具名字 -
cluster
我對host裡面的命名,比如上面舉例ansible-inventory --graph --vars
這個執行完後 能看到 graph是從cluster 這個名字開啟的,所以 也就是在cluster組的所有節點上都執行 -
-m command
-m 是 ansible的引數,從第一次安裝完 我們列印了--help
裡面有提到這個- m MODULE_NAME, --module-name MODULE_NAME
Name of the action to execute (default=command)
command 的意思就是 我自己會給指令讓他執行
-m ping
因為ping是ansible裡面內建的module名字 所以 -m 帶上 ping就是測試這個組的所有節點是否連通 - m MODULE_NAME, --module-name MODULE_NAME
-
-a "nvidia-smi"
一般 -a 跟著的是 -m command 或者 是沒有(因為預設是command) 因為一般只有自己輸入特定指令需要給這個引數- a MODULE_ARGS, --args MODULE_ARGS
The action's options in space separated k=v format: -a 'opt1=val1 opt2=val2'
- a MODULE_ARGS, --args MODULE_ARGS
ok 隨堂測試 這條指令幹什麼 【可以自己試試】:
ansible cluster -m command -a "nvidia-smi --query-gpu=index,gpu_name,utilization.gpu,memory.total,memory.used,temperature.gpu --format=csv,noheader,nounits"
實際上到這裡 普通使用者用來 看看 server的狀態 就差不多了,進階呢 就是把command -a 後面的 搞成一個yaml檔案,這樣就不用輸入一系列長的指令了
進階嘗試
主要 適用人員 就是對node節點要幹些什麼,不是單純的列印資訊了;比如統一升級某個包、統一新增一個使用者、統一解除安裝什麼東西 等等等
首先介紹一下ansible 的模組
-
command
:也就是上面我們介紹過了的 常見命令都可以使用,但是執行不是透過shell的 所以 < > | and & 等操作 nopeansible cluster -m command -a "nvidia-smi"
-
shell
:預設/bin/sh執行,所以終端輸入的命令都可以使用可以看到 -m 後面跟的是shell! 然後我們還接了一個 &&
ansible cluster -m shell -a "nvidia-smi && ls | grep config"
當然看到這裡,確實shell 是可以把自己的scripts 先 cp 過去,然後再執行,但是呢 這樣需要呼叫兩次ansible 第一次 cp 第二次 run
# copy 過去 ansible cluster -m copy -a "src=/home/kin/echo_test.sh dest=/home/kin owner=kin group=kin mode=0777" # 然後執行 ansible cluster -m shell -a "./home/kin/echo_test.sh"
而下面介紹的scripts 和 playbook 就不需要了
-
scripts
:在本地寫一個指令碼,在遠端伺服器上執行
scripts執行
首先這個 我們需要寫好一個指令碼,舉個例子
寫個echo_test.sh
就列印一下顯示卡和 echo Hello
#!/bin/bash
#nvidia-smi
date
hostname
echo "Hello Test ansible Here!"
然後執行:
ansible cluster -m script -a "/home/kin/echo_test.sh"
playbook 介紹
終於到大頭了 看到這裡還記得第一幅圖的東西嗎?所有的部分基本快速過了一遍 還差一個playbook! 關於ansible自己文件的介紹 在這裡
- Playbooks are automation blueprints, in
YAML
format 並使用它進行部署和配置節點等
那麼為什麼上面的script不夠用呢? 可以停下想想
因為 在你執行上面scripts 的時候 沒法說 node B執行這段,node B執行第二段;或者是不同的使用者屬性不同操作等等 【官方的答案還有幾個點 感興趣可以點上面的link;這麼一看 playbook這個名字取得真不錯 按照劇本 演】
好 進入正題,先給一個參考部落格裡的 playbooks 樣子:
---
- name: Update web servers
hosts: webservers
remote_user: root
tasks:
- name: Ensure apache is at the latest version
ansible.builtin.yum:
name: httpd
state: latest
- name: Write the apache config file
ansible.builtin.template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
解釋一下:
name
task description 任務描述資訊hosts
要執行這個task的 節點組,比如我們之前一直的命名是cluster
ansible.builti
這裡都是使用了ansible 內建的模組功能module_name
module_args #需要使用的模組名字: 模組引數shell
使用shell模組
---
- hosts: mongo_servers
tasks:
- include: roles/mongod/tasks/shards.yml
其中include 的playbook 長這樣:
---
#This Playbooks adds shards to the mongos servers once everythig is added
- name: Create the file to initialize the mongod Shard
template: src=shard_init.j2 dest=/tmp/shard_init_{{ inventory_hostname }}.js
delegate_to: '{{ item }}'
with_items: groups.mongos_servers
- name: Add the shard to the mongos
shell: /usr/bin/mongo localhost:{{ mongos_port }}/admin -u admin -p {{ mongo_admin_pass }} /tmp/shard_init_{{ inventory_hostname }}.js
delegate_to: '{{ item }}'
with_items: groups.mongos_servers
這是官方的一個示例
是不是大概看懂了?【反正我第一次是沒看懂 一堆admin 也不敢執行 所以還是 祖傳!檢查disk space 是不是剩餘ok
- name: Disk space in local storage
hosts: cluster
tasks:
- set_fact:
mount: "{{ ansible_mounts | selectattr('mount', 'equalto', '/') | first }}"
- set_fact:
size_total_gb: "{{ (mount.size_total / (1024*1024*1024)) }}"
size_used_gb: "{{ ((mount.size_total - mount.size_available) / (1024*1024*1024)) }}"
size_used_percent: "{{ 100 * (mount.size_total - mount.size_available) / mount.size_total }}"
- set_fact:
size_ok: "{{ ( (mount.size_total - mount.size_available) / mount.size_total ) < 0.80 }}"
size_msg: "Local storage: {{ size_used_gb|float|round(1) }}/{{ size_total_gb|float|round(1) }}GB ({{ size_used_percent|float|round(1) }}%)"
- assert:
that: size_ok
quiet: true
fail_msg: "{{size_msg}}"
vim 完了 可以試一下check,這個check mode只是一個模擬 不會輸入任務的output,但是是一個非常適合驗證這個playbook在一個節點上 執行的一些配置管理操作【當然 我們上面只是判斷一下 硬碟還有儲存空間
ansible-playbook echo_local.yaml --check
如果只想在一個node上執行可以 加 --limit node_name
比如:
ansible-playbook echo_local.yaml --limit Server5
實際的執行指令很簡單,直接跟yaml即可:
總結
意猶未盡?ansible 自己官方給了很多很多 examples,歡迎去探索:https://github.com/ansible/ansible-examples
然後這個 文件 真的是一個特別特別特別簡單的入門 瞭解 嘗試,也是張聰明同學第一次學的時候 邊學邊寫的… 有錯誤很正常 或者是隨時間 萬一指令不對了 過時了 大家都看官方文件為主哈
贈人點贊 手有餘香 ?;正向回饋 才能更好開放記錄 hhh