安裝及配置 ansible
Ansilbe 管理員節點和遠程主機節點通過 SSH 協議進行通信。所以 Ansible 配置的時候只需要保證從 Ansible 管理節點通過 SSH 能夠連接到被管理的遠程的遠程節點。
每一台被 ansible 遠程管理的主機,都需要配置基於 key 的 ssh 連接
安裝 ansible
# Readhat/CentOS Linux, Ansible 目前放在 epel 源中
yum install -y epel-release
yum install -y ansible
# Mac
brew install ansible
安裝 ansible 在管理節點,那么,需要配置管理節點->遠程主機之間基於 key 的免密訪問:
# 生成 ssh key,如果你之前配置過 Git,那么已經生成過一個了
ssh-keygen -t rsa -C "649168982@qq.com"
# 拷貝 ssh key 至遠程主機,下次管理節點就可以免密訪問遠程主機了
ssh-copy-id remote_user@remote_server
# ssh 的時候不會提示是否保存 key
ssh-keyscan remote_servers >> ~/.ssh/known_hosts
這時候在管理節點登錄遠程節點時,就不會輸入密碼也不會提醒你存儲key,之前寫過一篇文章,記錄設置免密登錄的文章Linux 雙向 SSH 免密登錄:
ssh remote_user@remote_server
Host Inventory 主機清單
Host Inventory 是配置文件,用來告訴Ansible需要管理哪些主機。並且把這些主機根據按需分類。
可以根據用途分類:數據庫節點,服務節點,nginx 節點、構建機器節點
默認的配置文件在:/etc/ansible/hosts
,可以通過 -i
參數指定配置文件的,參考問題:
ansible 配置文件
ansible 的配置文件有多個位置,查找順序如下:
- 環境變量
ANSIBLE_CONFIG
所指向的位置 - 當前目錄下的
ansible.cfg
- HOME 目錄下的配置文件
~/.ansible.cfg
/etc/ansible/ansible.cfg
本文 ansible.cfg:
[defaults]
# 這個參數表示主機清單 inventory 文件的位置
inventory = ./inventory
# 並發連接數,默認為5
forks = 5
remote_user = root
# 設置默認執行命令的用戶,~~sudo_user~~ 參數在 ansbile 2.8 版本將會作廢的
become_user = root
#指定一個存儲ansible日志的文件(默認不記錄日志)
log_path = ./ansible.log
指定用戶名除了在 ansible.cfg
中指定 remote_user
之外,還可以:
- inventory 文件中指定
ansible_user
或ansible_ssh_user
- 使用
-u
參數指定用戶名
更多 ansbile.cfg
的配置參考鏈接
inventory 文件
inventory: 英 ['ɪnv(ə)nt(ə)rɪ] 美 ['ɪnvəntɔri]
n. 存貨,存貨清單;詳細目錄
Ansible 可同時操作屬於一個組的多台主機,組和主機之間的關系通過 inventory 文件配置。
inventory:
[centos]
192.168.3.43
[centos:vars]
ansible_ssh_user=root
- 方括號
[]
中是組名,用於對主機進行分類,便於對不同主機進行個別的管理 - 一個主機可以屬於不同的組
[組名:vars]
定義了「組的變量」
拓展: 可以把一個組作為另一個組的子成員,以及分配變量給整個組使用. 這些變量可以給 /usr/bin/ansible-playbook
使用,但不能給 /usr/bin/ansible
使用
[atlanta]
host1
host2
[raleigh]
host2
host3
[southeast:children]
atlanta
raleigh
Inventory 參數可以控制 ansible 與遠程主機的交互方式:
ansible_ssh_host
將要連接的遠程主機名.與你想要設定的主機的別名不同的話,可通過此變量設置.
ansible_ssh_port
ssh端口號.如果不是默認的端口號,通過此變量設置.
ansible_ssh_user
默認的 ssh 用戶名
ansible_ssh_pass
ssh 密碼(這種方式並不安全,我們強烈建議使用 --ask-pass 或 SSH 密鑰)
ansible_sudo_pass
sudo 密碼(這種方式並不安全,我們強烈建議使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)
sudo 命令路徑(適用於1.8及以上版本)
ansible_connection
與主機的連接類型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默認使用 paramiko.1.2 以后默認使用 'smart','smart' 方式會根據是否支持 ControlPersist, 來判斷'ssh' 方式是否可行.
ansible_ssh_private_key_file
ssh 使用的私鑰文件.適用於有多個密鑰,而你不想使用 SSH 代理的情況.
ansible_shell_type
目標系統的shell類型.默認情況下,命令的執行使用 'sh' 語法,可設置為 'csh' 或 'fish'.
ansible_python_interpreter
目標主機的 python 路徑.適用於的情況: 系統中有多個 Python, 或者命令路徑不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.我們不使用 "/usr/bin/env" 機制,因為這要求遠程用戶的路徑設置正確,且要求 "python" 可執行程序名不可為 python以外的名字(實際有可能名為python26).
與 ansible_python_interpreter 的工作方式相同,可設定如 ruby 或 perl 的路徑....
參考
用命令管理主機
ansible 的主要使用形式分為兩種:
- 使用Ansilbe命令行管理主機(Ad-hoc command)
- 使用Ansilbe腳本語言管理主機(腳本語言Playbook)
本文就先從 ad-hoc 方式開始學習。
ansible -h
中將命令行工具叫做 Ad-Hoc Commands
,格式是:
Usage: ansible <host-pattern> [options]
ad hoc——臨時的,在ansible中是指需要快速執行,並且不需要保存的命令。說白了就是執行簡單的命令——一條命令。對於復雜的命令后面會說playbook。關於命令中使用的模塊,之后專門詳細再做功課,這里先簡單意會入門吧。
我的目錄初始化時的組成:
.
├── ansible.cfg
└── inventory
這里的 host-pattern
既可以是一個具體的主機 IP,也可以是 inventory 中的組名。
常用的命令選項示例:
ansible all --list-hosts
列出所有主機的 IP,這里的all
不是組名,而是只 inventory 中所有的主機
在進入下面的小節學習相關模塊簡單用法之前,咱們先學習一個命令,這對於今后的使用很有幫助:
$ansible-doc <module_name>
批量執行 ssh 授信 - authorized——key 模塊
在未進行批量授信之前,可以使用 --ask-pass
參數來進行認證,例如:ansible all -m ping --ask-pass
。但是這樣並不方便,可以通過將 ansible server 機器上的公鑰復制到遠程主機 ~/.ssh/authorized_keys
文件中,實現免密登錄。機器很多時,這樣做就比較麻煩了,可以用如下模塊實現:
ansible centos -m authorized_key -a "user=root key='{{ lookup('file', '/Users/michael/.ssh/id_rsa.pub') }}' path=/root/.ssh/authorized_keys manage_dir=yes" --ask-pass
檢查 ansbile 安裝環境 - ping 模塊
ping 模塊用於測試 ansible server 到 inventory 主機的連通性,這是官網的介紹ping – Try to connect to host, verify a usable python and return pong on success
$ ansible -i inventory centos -m ping -u root
192.168.3.43 | SUCCESS => {
"changed": false,
"ping": "pong"
}
-i
指定了inventory
文件,后面要接着目標主機名,不然會報錯-m
后面接使用的module
-u
只以什么用戶登錄到目標主機
下面實例中,沒有加目標主機名,就報錯了:
ansible -i inventory centos -m ping -u root
ERROR! Missing target hosts
下面錯誤示例,指定的用戶名 hh
無法免密登錄到目標主機:
$ ansible -i inventory centos -m ping -u hh
192.168.3.43 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: hh@192.168.3.43: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\r\n",
"unreachable": true
}
此時,我在這篇文章中看到了這樣的用法也可以指定登錄遠程主機的用戶名,並且,優先級比 -u
或者在 ansible.cfg
中指定都高:
[centos]
192.168.3.43
[centos:vars]
ansible_ssh_user=michael
在遠程主機執行命令
command 模塊
command模塊為ansible默認模塊,不指定-m參數時,使用的就是command模塊;comand模塊比較簡單,常見的命令都可以使用,但其命令的執行不是通過shell執行的,所以,像這些 "<", ">", "|", and "&"操作都不可以,當然,也就不支持管道;
在遠程主機上執行命令 pwd
:
$ ansible centos -a 'pwd'
192.168.3.43 | CHANGED | rc=0 >>
/home/michael
缺點:不支持管道,就沒法批量執行命令
- 這里沒有再用
-i
參數指定 inventory 文件,因為我運行ansible --version
時,看到了它識別到了我當前目錄下的ansible.cfg
文件 centos
就是必不可少的參數host-pattern
,讓我們復習一下用法ansible <host-pattern> [options]
-a
/--args
模塊參數
shell模塊
使用shell模塊,在遠程命令通過/bin/sh
來執行;所以,我們在終端輸入的各種命令方式,都可以使用; 但是我們自己定義在.bashrc/.bash_profile
中的環境變量shell模塊由於沒有加載,所以無法識別;
如果需要使用自定義的環境變量,就需要在最開始,執行加載自定義腳本的語句;
對shell模塊的使用可以分成兩塊: 1.如果待執行的語句少,可以直接寫在一句話中:
$ ansible all -m shell -a ". ~/.bashrc;ps -fe |grep sa_q"
192.168.3.43 | CHANGED | rc=0 >>
root 2849 2844 2 14:58 pts/0 00:00:00 /bin/sh -c . ~/.bashrc;ps -fe |grep sa_q
root 2866 2849 0 14:58 pts/0 00:00:00 grep sa_q
2.如果在遠程待執行的語句比較多,可寫成一個腳本,通過 copy
模塊傳到遠端,然后再執行;但這樣就又涉及到兩次ansible調用;對於這種需求,ansible已經為我們考慮到了,script模塊就是干這事的。
script模塊
使用 scripts
模塊可以在本地寫一個腳本,在遠程服務器上執行(遠程服務器不需要python環境):
ansible all -m script -a "./test-20190224.sh"
test-20190224.sh
位於當前目錄下,表示在所有的遠程主機上執行test.sh
腳本,省略了先把文件復制過去的步驟
參考
文件傳輸 - copy 模塊
拷貝本地文件 /Users/michael/Code/05-Github-Own/ansible-learn/file_mbp.txt
至遠程主機的 /tmp
目錄下:
ansible centos -m copy -a "src=//Users/michael/Code/05-Github-Own/ansible-learn/file_mbp.txt dest=/tmp/ [owner=root group=root mode=0755]"`
ansible centos -m copy -a "src=//Users/michael/Code/05-Github-Own/ansible-learn/file_mbp.txt dest=/tmp/centos.txt [owner=root group=root mode=0755]"
上面 []
中的內容表示非必須。這個 copy
模塊挺智能,如果目標沒有寫文件名,那么傳過去的文件就同名,如果自定義了文件名,就進行了重命名:
安裝包 - yum 模塊
$ ansible centos -m yum -a "name=lrzsz state=latest"
192.168.3.43 | SUCCESS => {
"ansible_facts": {
"pkg_mgr": "yum"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"All packages providing lrzsz are up to date",
""
]
}
yum
模塊來安裝軟件包name
指定安裝的軟件包的名字state
指定安裝軟件包時的行為,它有幾個選項值,installed
/present
它倆是等價的,表示如果遠程主機上有這個包了,則不重新安裝了;latest
顧名思義,會去安裝最新版的,這個對於生產是比較危險的,有可能因此破壞了生產的環境
Yum 模塊
state
值得具體區別,參考了這個問題:
添加用戶 - user 模塊
ansible centos -m user -a "name=foo password=<crypted password here>"
//移除用戶
ansible all -m user -a 'name=foo state=absent'
下載 Git 倉庫 - git 模塊
$ ansible centos -m git -a "repo=https://github.com/Michael728/my-config-files.git dest=/tmp/my-config-files version=HEAD"
192.168.3.43 | CHANGED => {
"after": "6faf55b17a1d7c25dfda6f6197839deaa2aa2bd5",
"before": null,
"changed": true
}
- 使用 git 模塊下載了代碼庫默認分支的最新版本
repo
是必選參數dest
也是必選參數,指定代碼庫的下載路徑
代碼庫地址除了選擇用 https
鏈接之外,還可以用 ssh
地址,事實上,公司中大多使用 ssh
地址會更方便:
ansible centos -m git -a "repo=git@github.com:Michael728/my-config-files.git dest=/tmp/my-config-files version=HEAD accept_hostkey=yes"
遠程主機首次使用 git clone
命令時,是需要手動接受 knows_hosts 的,這時候加上 accept_hostkey=yes
可以避免出錯
參考:
啟動服務 - service 模塊
# 啟動服務
ansible centos -m service -a "name=httpd state=started"
# 重啟服務,效果類似 stopped+started,如果服務已經停止的,執行完,會重啟
ansible centos -m service -a "name=httpd state=restarted"
# 重載服務,不會中斷服務,如果服務之前未啟動,那么會啟動服務,如果啟動了不一定會使用新的配置文件,還是推薦重啟
ansible centos -m service -a "name=httpd state=reloaded"
# 停止服務
ansible centos -m service -a "name=httpd state=stopped"
state 有幾個可選值(Choices: reloaded, restarted, started, stopped)[Default: (null)]
:
started'/
stopped` are idempotent[冪等] actions that will not run commands unless necessary.restarted
will always bounce the service.reloaded
will always reload. At least one of state and enabled are required. Note that reloaded will start the service if it is not already started, even if your chosen init system wouldn't normally.
參考
並行執行重啟
$ansible centos -a "/sbin/reboot" -f 10
-f
參數會 fork 出 10 個子進程,以並行的方式
這個命令雖然顯示是出現問題了,但是我發現虛擬機確實重啟了:
$ ansible all -a "reboot" -f 6
192.168.3.43 | UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Shared connection to 192.168.3.43 closed.\r\n",
"unreachable": true
}
查看遠程主機的全部系統信息 - setup 模塊
ansible all -m setup
# 通過 filter 獲取某一個 fact 變量
ansible all -m setup -a 'filter=ansible_*mb'
總結
可以發現,ansible Ad-Hoc 的命令使用比較簡單,適用於不復雜的場景,如果需要實現復雜的任務,那么就需要通過 ansible-playbook 的方式執行了,下一篇文章中學習它。
參考
- 官宣-All modules
- shijinjin-Ansible 入門-Ansible用命令管理主機 本系列學習的主要參考
- 【mac】ansible安裝及基礎使用
- the5fire-自動化工具——ansible中文指南
- Ansible-入門
- Ansible簡明教程 介紹 ansible-playbook 命令較多
service 模塊的 restarted reload 區別?