Ansible 入門指南 - 安裝及 Ad-Hoc 命令使用

安裝及配置 ansible

Ansilbe 管理員節點和遠程主機節點經過 SSH 協議進行通訊。因此 Ansible 配置的時候只須要保證從 Ansible 管理節點經過 SSH 可以鏈接到被管理的遠程的遠程節點。html

每一臺被 ansible 遠程管理的主機,都須要配置基於 key 的 ssh 鏈接python

安裝 ansible

# Readhat/CentOS Linux, Ansible 目前放在 epel 源中
yum install -y epel-release
yum install -y ansible
# Mac
brew install ansible

安裝 ansible 在管理節點,那麼,須要配置管理節點->遠程主機之間基於 key 的免密訪問:nginx

# 生成 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 免密登陸git

ssh remote_user@remote_server

Host Inventory 主機清單

Host Inventory 是配置文件,用來告訴Ansible須要管理哪些主機。而且把這些主機根據按需分類。github

能夠根據用途分類:數據庫節點,服務節點,nginx 節點、構建機器節點shell

默認的配置文件在:/etc/ansible/hosts,能夠經過 -i 參數指定配置文件的,參考問題:數據庫

ansible 配置文件

ansible 的配置文件有多個位置,查找順序以下:macos

  1. 環境變量 ANSIBLE_CONFIG 所指向的位置
  2. 當前目錄下的 ansible.cfg
  3. HOME 目錄下的配置文件 ~/.ansible.cfg
  4. /etc/ansible/ansible.cfg

本文 ansible.cfg:ubuntu

[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 以外,還能夠:centos

  • inventory 文件中指定 ansible_useransible_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 的主要使用形式分爲兩種:

  1. 使用Ansilbe命令行管理主機(Ad-hoc command)
  2. 使用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 的方式執行了,下一篇文章中學習它。

參考

service 模塊的 restarted reload 區別?

相關文章
相關標籤/搜索