Ansible是一款IT自動化工具,可用於配置系統、部署軟件、安排更爲高級的IT任務,如連續部署或滾動更新。

Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates. — About Ansible

本文簡要介紹Ansible,並通過Shell腳本實現在GNU/Linux中的安裝。

Origins

Ansible的起源

Author

Michael DeHaanAnsible的作者,他先後在Red HatPuppet任職。

Cobbler是其在Red Hat時的項目。

離開Puppet後,他於February 23, 2012開始了Ansible項目。更多細節內容見:

Ansible

關於 Ansible 這個名字的由來,Learn Ansible - Russ McKendrickAnsible’s story章節有簡短的介紹。

Ansible這個詞最早出現在科幻小說作家Ursula K. Le Guin於1966年出版的小說Rocannon’s World中,Ansible是一種虛構的設備,可以比光更快地發送、接收信息。

1974年,Ursula K. Le Guin在其另一部小說The Dispossessed: An Ambiguous Utopia中通過探索數學理論使得Ansible這種技術成爲可能。

In 1974, Ursula K. Le Guin’s novel The Dispossessed: An Ambiguous Utopia, was published; this book features the development of the Ansible technology by exploring the (fictional) details of the mathematical theory that would make such a device possible.

Acquisition

Red Hat2015.10.16 宣佈收購Ansible,詳見 FAQ: Red Hat Acquires Ansible

Official Site

Site Link
Official Site https://www.ansible.com
GitHub https://github.com/ansible/ansible
Documentation https://docs.ansible.com/ansible/
Blog https://www.ansible.com/blog
Twitter https://twitter.com/ansible

可通過如下命令查看最新釋出版本

1
2
# wget -qO-
curl -fsL https://releases.ansible.com/ansible/ansible-latest.tar.gz.sha | sed -r -n '[email protected]*ansible-([[:digit:].]+)\..*[email protected]\[email protected];p'

Features

Ansible使用Python語言開發,控制臺(Control Machine)通過SSH管理遠程主機(Managed Node),可同時對多臺主機進行並行(parallel)操作。

Ansible的版本釋出週期爲4個月。

Ansible’s release cycles are usually about four months long. Due to this short release cycle, minor bugs will generally be fixed in the next release versus maintaining backports on the stable branch. Major bugs will still have maintenance releases when needed, though these are infrequent. – What Version To Pick?

Idempotence

Ansible具有 冪等性(idempotence),即相同命令運行多次,結果均相同。在配置工具(Configuration Tool)領域中有2種思想:

type explanation
idempotence 冪等,每一次的運行結果都相同
convergence 收斂、趨同,運行多次,逐步接近預期效果

關於Ansibleidempotence,其開發者Michael DeHaan寫過一篇 Idempotence, convergence, and other silly fancy words we use too often,有興趣者可自行查看。

Via SSH

Ansible無需安裝數據庫、守護進程(daemon),所有操作通過SSH進行。

Ansible by default manages machines over the SSH protocol. – Basics / What Will Be Installed

Push-based

Ansible將主機分爲2類:

Type Explanation
Control Machine 控制主機,用於管理 Managed Node
Managed Node 被管理的主機

Puppet等工具相比,Ansible更爲輕量。因爲Ansible無需在各node中添加數據庫、安裝agent或運行daemon(守護進程等)。

站在Managed Node的角度,二者的顯著差異是:

  • Ansible屬於 push-based
    • Control Machine推送
  • Puppet屬於 pull-based
    • Managed Node通過安裝的agent進行週期性檢查,從Control Machine拉取配置信息到本地

Requirements

Python版本要求

Host Type Python version
Control Machine Python 2 (2.6 or 2.7) or Python 3 ( >= 3.5)
Managed Node Python 2 (2.6 or 2.7) or Python 3 ( >= 3.5)

If you have SELinux enabled on remote nodes, you will also want to install libselinux-python on them before using any copy/file/template related functions in Ansible. – Managed Node Requirements

Control Machine

Please note that some modules and plugins have additional requirements. For modules these need to be satisfied on the ‘target’ machine and should be listed in the module specific docs.

Managed Node

  • 如果遠程主機中的SELinux已啓用,則須安裝libselinux-python以支持copy、file、template等功能;
  • Ansible默認使用的解釋器(interpreter)位於/usr/bin/python,但某些新的Linux發行版默認只有Python3 (/usr/bin/python3),可通過變量ansible_python_interpreter設置路徑或安裝Python2;

Installation

Ansible官方文檔 Installation,介紹了Ansible的安裝、配置方式。

Ansible的代碼公佈在GitHub上

Type Url
GitHub https://github.com/ansible/ansible
Tarball http://releases.ansible.com/ansible/

Ansible官方提供包管理器安裝、pip安裝、源碼編譯安裝、Tar包安裝等安裝方式。詳見 Installing the Control Machine

爲了安裝最新釋出的版本,此處選擇通過Tar包安裝,以下爲Shell腳本實現。

Shell Script

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
#!/usr/bin/env bash
set -u  #Detect undefined variable
set -o pipefail #Return return code in pipeline fails

# Write: MaxdSre
# Date: Sun 2018-08-05 09:22:32 +0800 CST
# Target: Installing Ansible On GNU/Linux Via Tarball Package.

[[ "$UID" -ne 0 ]] && echo 'this script requires superuser privileges (eg. root, su).' && exit

installation_dir=${installation_dir:-'/opt/Ansible'}
config_dir=${config_dir:-'/etc/ansible'}
readonly temp_save_dir='/tmp'
readonly bak_suffix='_bak'

python_interpreter=${python_interpreter:-'python'}
[[ -n $(which python3 2> /dev/null || command -v python3 2> /dev/null) ]] && python_interpreter='python3'

download_tool=${download_tool:-'wget -qO-'}
[[ -n $(which curl 2> /dev/null || command -v curl 2> /dev/null) ]] && download_tool='curl -fsL'

latest_release_pack_url='https://releases.ansible.com/ansible/ansible-latest.tar.gz'
# https://releases.ansible.com/ansible/ansible-latest.tar.gz
# https://releases.ansible.com/ansible/ansible-latest.tar.gz.sha
latest_sha256_info=$($download_tool "${latest_release_pack_url}.sha")
# 747e4cca09c10833ffe3a7c53af310d2d387bd4f499ec6e1bde60662606aaff8  ansible-2.6.2.tar.gz
sha256_dgst="${latest_sha256_info%% *}"
online_release_version=$(echo "${latest_sha256_info}" | sed -r -n '[email protected]*ansible-([[:digit:].]+)\..*[email protected]\[email protected];p')

is_need_download=${is_need_download:-0}
is_existed=${is_existed:-0}
setup_python_path=${setup_python_path:-"${installation_dir}/setup.py"}

if [[ -s "${setup_python_path}" ]]; then
    cd "${installation_dir}"
    [[ $($python_interpreter "${setup_python_path}" --version) != "${online_release_version}" ]] && is_need_download=1
    is_existed=1
else
    is_need_download=1
fi

echo -e "online release version is ${online_release_version}\nis existed ${is_existed}, is need download ${is_need_download}."

# remote existed files about ansible
# sudo rm -rf /etc/ansible/ /opt/Ansible /usr/local/lib/python*/dist-packages/ansible* /usr/local/bin/ansible*

if [[ "${is_need_download}" -eq 1 ]]; then
    temp_pack_save_path="${temp_save_dir}/${latest_release_pack_url##*/}"
    $download_tool "${latest_release_pack_url}" > "${temp_pack_save_path}"

    if [[ $(shasum -a 256 "${temp_pack_save_path}" 2>/dev/null | sed -r '[email protected]^[[:space:]]*([^[:space:]]+).*[email protected]\[email protected]') != "${sha256_dgst}" ]]; then
        echo 'fail to sha256 dgst verifin'
        exit
    fi

    if [[ "${is_existed}" -eq 1 && ! -d "${installation_dir}${bak_suffix}" ]]; then
        mv "${installation_dir}" "${installation_dir}${bak_suffix}"
    fi

    [[ -d "${installation_dir}" ]] || mkdir -p "${installation_dir}"

    # decompress
    tar xf "${temp_pack_save_path}" -C "${installation_dir}" --strip-components=1

    # cp config file to /etc
    if [[ "${is_existed}" -ne 1 && -d "${installation_dir}/examples/" ]]; then
        [[ -d "${config_dir}" ]] || mkdir -p "${config_dir}"
        cp -R "${installation_dir}"/examples/* "${config_dir}"
    fi

    # install
    if [[ -s "${setup_python_path}" ]]; then
        cd "${installation_dir}"
        ${python_interpreter} "${setup_python_path}" build &> /dev/null
        ${python_interpreter} "${setup_python_path}" install &> /dev/null
    fi

    # /usr/local/lib/python2.x/dist-packages/ansible
    # /usr/local/lib/python3.x/dist-packages/ansible*
    [[ -f "${temp_pack_save_path}" ]] && rm -f "${temp_pack_save_path}"

    if [[ -s '/usr/local/bin/ansible' ]]; then
        [[ -d "${installation_dir}${bak_suffix}" ]] && rm -rf "${installation_dir}${bak_suffix}"

        #$USER exist && $SUDO_USER not exist, then use $USER
        [[ -n "${USER:-}" && -z "${SUDO_USER:-}" ]] && login_user="$USER" || login_user="$SUDO_USER"

        echo -e 'version info\n'
        if [[ "${login_user}" == 'root' ]]; then
            ansible --version
        else
            sudo -u "${login_user}" ansible --version
        fi

    else
        [[ -d "${installation_dir}" ]] && rm -rf "${installation_dir}"
        [[ -d "${installation_dir}${bak_suffix}" ]] && mv "${installation_dir}${bak_suffix}" "${installation_dir}"
        echo 'fail to install/upgrade ansible'
    fi

fi

# Script End

Ansible的可執行程序默認安裝在目錄/usr/local/bin/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Debian GNU/Linux 9.5 (stretch)

# which ansible
/usr/local/bin/ansible

# ansible --version
ansible 2.6.2
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/maxdsre/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.5/dist-packages/ansible-2.6.2-py3.5.egg/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.5.3 (default, Jan 19 2017, 14:11:04) [GCC 6.3.0 20170118]

Configuration Files

Ansible官方文檔 Ansible Configuration Settings

變量 ANSIBLE_CONFIG 用於覆蓋默認配置文件

配置文件路徑

file explanation
/etc/ansible/ansible.cfg 配置文件,可選
~/.ansible.cfg 覆蓋默認配置,可選

Command Line Tools

Ansible提供如下命令

command explanation
ansible Define and run a single task ‘playbook’ against a set of hosts
ansible-config View, edit, and manage ansible configuration.
ansible-connection
ansible-console REPL console for executing Ansible tasks.
ansible-doc plugin documentation tool
ansible-galaxy
ansible-inventory
ansible-playbook Runs Ansible playbooks, executing the defined tasks on the targeted hosts.
ansible-pull pulls playbooks from a VCS repo and executes them for the local host
ansible-vault encryption/decryption utility for Ansible data files

Components

Ansible通過playbook進行配置、部署工作,具體功能由各module實現。爲提升代碼的複用(reuse)性,可使用role組織playbook,而role的創建可通過Ansible Galaxy實現。

關於playbook,中文被翻譯爲劇本,但個人認爲 藍圖任務清單 更爲貼切、更易於理解。

Modules

moduleAnsible中佔據重要地位,目前有如下模塊:

所有模塊 All Modules列表。

Ansible一直在開發、維護中,每當一個版本釋出,某些模塊中的指令可能會被廢除,或添加新的指令,建議經常翻閱官方文檔

Getting Started

如何使用Ansible,詳見 Getting Started

Bibliography

References

Change Logs

  • 2016.03.27 12:31 Sun Asia/Beijing
    • 初稿修改完成
  • 2016.03.28 10:58 Mon Asia/Beijing
    • 添加Bibliography
  • 2018-08-05 10:05 Sun Asia/Shanghai
    • 勘誤,更新,遷移到新Blog