Ansible 的網站上將之解釋爲 「一個超級簡單的 IT 自動化引擎,能夠自動進行雲供給、配置管理、應用部署、服務內部編排,以及其餘不少 IT 需求。」 經過在一個集中的位置定義好服務器集合,Ansible 能夠在多個服務器上執行相同的任務。html
若是你對 Bash 的 for 循環很熟悉,你會發現 Ansible 操做跟這很相似。區別在於 Ansible 具備冪等性。通俗來講就是 Ansible 通常只有在確實會發生改變時才執行所請求的動做。好比,假設你執行一個 Bash 的 for 循環來爲多個機器建立用戶,像這樣子:node
for server in serverA serverB serverC; do ssh ${server} "useradd myuser"; done
這會在 serverA、serverB,以及 serverC 上建立 myuser 用戶;然而無論這個用戶是否存在,每次運行這個 for 循環時都會執行 useradd 命令。一個幕等的系統會首先檢查用戶是否存在,只有在不存在的狀況下才會去建立它。固然,這個例子很簡單,可是冪等工具的好處將會隨着時間的推移變得愈加明顯。nginx
Ansible 會將 Ansible playbooks 轉換成經過 SSH 運行的命令,這在管理類 UNIX 環境時有不少優點:web
若你使用的是 Fedora,輸入下面命令:sql
sudo dnf install ansible -y
若運行的是 CentOS,你須要爲 EPEL 倉庫配置額外的包,而後再使用 yum 來安裝 Ansible:shell
sudo yum install epel-release -y sudo yum install ansible -y
對於基於 Ubuntu 的系統,能夠從 PPA 上安裝 Ansible:數據庫
sudo apt-get install software-properties-common -y sudo apt-add-repository ppa:ansible/ansible sudo apt-get update sudo apt-get install ansible -y
若你使用的是 macOS,那麼推薦經過 Python PIP 來安裝:apache
sudo pip install ansible
更多版本安裝參見Ansible安裝指南centos
Ansible 使用一個 INI 風格的文件來追蹤要管理的服務器,這種文件被稱之爲庫存清單Inventory。默認狀況下該文件位於 /etc/ansible/hosts。數組
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
# - 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 # 192.168.1.100 192.168.2.19 [dbservers] 192.168.2.15 # 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 [redhats] 192.168.2.15 [debians] 192.168.2.19 ## ## 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
每一個分組由中括號和組名標識(像這樣 [webservers] ),是應用於一組服務器的任意組名。一臺服務器能夠存在於多個組中,沒有任何問題。在這個案例中,我有根據操做系統進行的分組(debians、redhats),也有根據服務器功能進行的分組(webservers、dbservers)。Ansible 主機文件能夠處理比這複雜的多的狀況。
臨時命令是你能夠鍵入的命令,它可使你快速完成某些操做,但不想保存以備後用。
這是一個開始學習Ansible,在學習playbook(劇本)語言以前,能夠用來作基礎知識的好方法。
command模塊:
默認使用command模塊。
ansible all -a 'ls -al'
shell模塊:
功能相似command模塊,可是shell模塊更強大。可使用 |、$
等特殊符號。
ansible all -m shell -a 'ls -al | grep root'
file模塊
用來操做file,更改文件屬性、擁有者、建立、刪除文件等操做。
#建立文件,設置權限,擁有權 ansible all -m file -a "path=/srv/foo/b.txt mode=600 owner=root group=root state=touch" #建立目錄,設置權限,擁有權 ansible all -m file -a "path=/root/test mode=755 owner=root group=root state=directory" #刪除操做 ansible all -m file -a "path=/root/test state=absent" #link操做 ansible all -m file -a "src=/path path=/path state=link"
yum模塊
centos系統用來安裝、刪除package。
#安裝package。 ansible redhats -m yum -a 'name=httpd state=present' #刪除package。 ansible redhats -m yum -a 'name=httpd state=absent'
service模塊
centos系統用來操做服務項模塊。
ansible redhats -m service -a 'name=httpd state=started' #enabled:開機啓動 ansible redhats -m service -a 'name=httpd state=started enabled=yes'
copy模塊
用來向受控端移動文件操做。
ansible redhats -m copy -a 'src=本地path dest=遠端path' #backup:備份 ansible redhats -m copy -a 'src=本地path dest=遠端path backup=yes'
fetch模塊
用來向控制端移動文件操做。
ansible redhats -m fetch -a 'src=遠端path dest=本地path' #backup:備份 ansible redhats -m fetch -a 'src=遠端path dest=本地path backup=yes'
setup模塊
用來獲取系統消息,獲取到的信息,均爲ansible中自帶的變量,能夠在playbook中直接使用。
ansible all -m setup -a 'filter=**os**'
user模塊
用來操做系統帳戶
ansible redhats -m user -a 'name=hello system=yes shell=/sbin/nologin uid=80 password=123456 home=yes state=present'
group模塊
用來操做系統用戶組
ansible redhats -m group -a 'name=hello system=yes gid=80 state=present'
template模塊
用來向受控端推送文件,與copy模塊比較,template模塊能夠根據系統特性,推送不一樣內容的同名文件。具體形式,在playbook中講解。
劇本是真正簡單的配置管理和多機部署系統的基礎,與現有的系統不一樣,它很是適合部署複雜的應用程序。
劇本能夠聲明配置,它們能夠實現受控主機執行命令的操做,即便不一樣的命令須要在特定的機器進行執行。他們能夠同步或異步執行命令。
儘管能夠運行/usr/bin/ansible主程序來執行臨時任務,但更方便將劇本保留在源代碼管理中,並用於推送你的配置或確保遠程系統的配置符合規範。
ansible playbook(劇本)就是包含 ansible 指令的 YAML 格式的文件。
--- - hosts: all remote_user: root tasks: - name: run command shell: ls -al
劇本能夠包含多個劇本。你可能有一本首先針對Web服務器,而後針對數據庫服務器的劇本。例如:
--- - hosts: webservers remote_user: root tasks: - name: ensure apache is at the latest version yum: name: httpd state: latest - name: write the apache config file template: src: /srv/httpd.j2 dest: /etc/httpd.conf - hosts: databases remote_user: root tasks: - name: ensure postgresql is at the latest version yum: name: postgresql state: latest - name: ensure that postgresql is started service: name: postgresql state: started
playbook採用YAML語法。特別注重空格和tab的使用。一個YAML文件中至少存在一個playbook。
hosts:在整個劇本中某任務裏,咱們須要指定哪些主機去執行咱們的寫的操做命令。
#選取在host文件中標籤爲web的主機 --- - hosts: web #選取在hosts文件中標籤爲redhats的主機 --- - hosts: redhats #選取hosts文件中去重以後的所有主機 --- - hosts: all
remote_user:爲劇本、任務定義遠程用戶
#以root用戶權限登陸,在ansible.cfg配置中,默認使用root身份進行登陸 --- - hosts: all remote_user: root #以hello用戶權限登陸,此時須要注意,因爲配置ssh key時,配置爲root免密碼登陸,因此以hello用戶登陸時,須要在執行命令中使用 -k 參數,也能夠將hello用戶配置爲免密碼登陸。 --- - hosts: all remote_user: hello
tasks:playbook中的任務,一個playbook應該存在一個tasks,每一個任務的目標是執行帶有特定參數的模塊。變量能夠在模塊的參數中使用。
become:爲任務更改遠程用戶,若是使用become,可能須要輸入用戶密碼,在ansible-playbook
命令中使用--ask-become-pass
or -K
參數
#本playbook等同於在主機上以hello用戶權限執行 sudo service nginx start --- - hosts: all remote_user: hello tasks: - service: name=nginx state=started become: yes become_method: sudo #本playcook等同於以root身份進行ssh登陸,而後將用戶換爲hello。接下來的全部任務(tasks)都以hello用戶身份執行。 --- - hosts: webservers remote_user: root become: yes become_user: hello
name:每一個任務中的動做能夠指定名字,用於在執行playbook時進行output。若是不指定,就根據動做類型進行output。
#本playbook在進行output時,執行的任務標籤爲start nginx service --- - hosts: all remote_user: root tasks: - name: start nginx service service: name=nginx state=started
ignore_errors:每一個任務中的每一個動做在執行時,都有可能會出錯,有時主機一旦出錯,會致使以前全部執行完畢的tasks所有回滾。想要跳過一些能夠忽略的錯誤,須要使用該參數。
#本playbook在進行start httpd服務時,若是執行過程當中遇到錯誤,仍然會繼續執行,不會發生回滾操做。 --- - hosts: all remote_user: root tasks: - name: start httpd service service: name=httpd state=started ignore_errors: True #若是是使用shell模塊的狀況,便可使用以下方法忽略錯誤。 --- - hosts: all remote_user: root tasks: - name: run command shell: ls -al || /bin/true
vars:爲playbook定義變量。在編寫playbook時,有時須要設置變量,執行不一樣動做。
#使用變量進行安裝httpd服務 --- - hosts: redhats remote_user: root vars: - pkname: httpd tasks: - name: yum {{ pkname }} service yum: name={{ pkname }} #使用變量執行動做時,須要使用 =。
vars_files:爲playbook定義變量文件。
#使用變量文件中定義的變量進行安裝httpd服務 --- - hosts: redhats remote_user: root vars_files: - var.yml tasks: - name: yum {{ pkname }} service yum: name={{ pkname }} #var.yml內容格式 pkname: httpd
(ansible中變量使用優先級爲-e
> tasks變量
> hosts 變量
> inventory變量
)
template:template爲ansible中的一個模塊,放在這裏講,是由於在Ad-Hoc
模式中template幾乎不被使用,template模塊用於實現複雜功能,template模塊使用jinja2語言。
#template模塊,相似於copy模塊,可是copy模塊只能copy相同文件到受控端。template模塊能夠根據變量,生成不一樣文件上傳到特定受控端。 --- - hosts: webservers remote_user: root tasks: - name: copy conf template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
handlers:若是動做對主機發生了更改,即去執行相對應操做。與notify配合使用。
--- - hosts: redhats remote_user: root tasks: - name: copy conf template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf notify: - restart nginx handlers: - name: restart nginx service: name=nginx state=restarted
when:用於跳過特定主機上的特定動做,條件判斷。
tasks: - name: "shut down Debian flavored systems" command: /sbin/shutdown -t now when: ansible_facts['os_family'] == "Debian" #使用括號對條件進行分組 tasks: - name: "shut down CentOS 6 and Debian 7 systems" command: /sbin/shutdown -t now when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or (ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")
ansible中的循環都是藉助迭代來實現的。基本都是以"with_"開頭。如下是常見的幾種循環。
#安裝httpd、nginx、vsftpd服務 --- - hosts: redhats tasks: - yum: name={{ item }} state=installed with_items: - httpd - nginx - vsftpd #指定文件列表,而後使用grep搜索出給定文件列表中包含"www.example.com"字符串的文件 --- - hosts: redhats tasks: - shell: grep -Rl "www\.example\.com" "{{ item }}" with_items: - file1 - file2 - file3 register: match_file #將with_items迭代後的結果註冊爲變量時,其註冊結果也是列表式的,且其key爲"results"。 - debug: msg="{% for i in match_file.results %} {{i.stdout}} {% endfor %}" #上面,是使用for循環進行引用的。若是不使用for循環,那麼就須要使用數組格式。 - debug: var=match_file.results[0].stdout - debug: var=match_file.results[1].stdout - debug: var=match_file.results[2].stdout #with_items迭代的是列表項,也能迭代列表中的各字典 --- - hosts: localhost tasks: - shell: echo "name={{item.name}},age={{item.age}}" with_items: - {name: zhangsan,age: 32} - {name: lisi,age: 33} - {name: wangwu,age: 35} register: who - debug: msg="{% for i in who.results %} {{i.stdout}} {% endfor %}"
#使用"with_dict"迭代時,使用"item.key"表示字典的key,"item.value"表示字典的值。 --- - hosts: redhats tasks: - debug: msg="{{item.key}} & {{item.value}}" with_dict: { address: 1,netmask: 2,gateway: 3 } #直接引用playbook中定義的vars --- - hosts: redhats gather_facts: False vars: user: longshuai_key: name: longshuai gender: Male xiaofang_key: name: xiaofang gender: Female tasks: - name: print hash loop var debug: msg="{{ item.key }} & {{ item.value.name }} & {{ item.value.gender }}" with_dict: "{{ user }}"
--- - hosts: redhats tasks: - copy: src="{{item}}" dest=/tmp/ with_fileglob: - /tmp/*.sh - /tmp/*.py
#with_lines能夠將命令行的輸出結果按行迭代 --- - hosts: redhats tasks: - copy: src="{{item}}" dest=/tmp/yaml with_lines: - find /tmp -type f -name "*.yml"
#嵌套迭代是指屢次迭代列表項 --- - hosts: localhost tasks: - debug: msg="{{item[0]}} & {{item[1]}}" with_nested: - [a,b] - [1,2,3]
以上這些,只是接觸到ansible這款自動化運維工具以後,經過自主學習得到到的一點皮毛知識,若是各位讀者以爲做者哪裏說得不正確、不嚴謹。能夠留言討論。