ansible學習

ansible

與salt對比

  • 相同
    • 都是爲了同時在多臺機器上執行相同的命令
    • 都是python開發
  • 不同
    • agent(saltstack需要安裝、ansible不需要)
    • 配置(salt配置麻煩,ansible基本不用配置)
    • 學習路線(salt比較陡峭,ansible比較平緩)
    • 第三方工具(salt比較少)
    • 開源社區的對接(salt比較少)
    • 現有用戶(salt還是ansible少一些)
    • 二次開發擴展的能力(ansible比較差,尤其是2.0以後)
    • 大規模併發(200以內一樣,200以上salt會好一些,當然我們也可以對ansible做一些配置使其在200以上追上salt)
    • Windows的支持(salt會好很多)

安裝

yum install -y ansible

查看ansible生成的命令,用到的命令

ansible            
ansible-doc        
ansible-galaxy(下載第三方插件)        
 ansible-playbook

查看ansible 安裝生成的

rpm -ql ansible |more
/etc/ansible
/etc/ansible/ansible.cfg #配置文件
/etc/ansible/hosts #主要文件

hosts文件詳解

cat /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 #你可以寫ip地址也可以寫hostnames
#   - A hostname/ip can be a member of multiple groups #一個主機可以被多個主機組包含

可以在hosts文件中填寫的內容

 ansible_ssh_host
  ansible通過ssh連接的IP或者FQDN
ansible_ssh_port
  SSH連接端口
ansible_ssh_user
  默認SSH連接用戶
ansible_ssh_pass
  SSH連接的密碼(這是不安全的,ansible極力推薦使用--ask-pass選項或使用SSH keys)
ansible_sudo_pass
  sudo用戶的密碼
ansible_connection
  SSH連接的類型:local,ssh,paramiko,在ansible 1.2之前默認是paramiko,後來智能選擇,優先使用基於ControlPersist的ssh(支持的前提)
ansible_ssh_private_key_file
  SSH連接的公鑰文件

查看ansible的命令幫助

ansible <host-pattern> [options]

-a MODULE_ARGS 模塊參數
-m MODULE_NAME 模塊名稱

-f forks 指定一次執行的機器

-C 測試

--list-hosts 查看運行的機器

-v 輸出詳細信息

第一個ansible程序

ansible test -m ping

獲取文檔

ansible-doc --help
-s 指定模塊名稱
-l 列出所有的模塊

操作日誌

/var/log/message

命令相關

shell command script
command模塊 [執行遠程命令]
    ansible all -a 'echo "hello world"'
    ansible all -a 'pwd'
    ansible all -a 'echo "oldboy"|passwd --stdin user1' #直接輸出結果
script模塊 [在遠程主機執行主控端的shell/python腳本 ]  (使用相對路徑)
ansible all -m script -a 'a.sh'  #執行本地腳本
ansible all -a 'ls /'       #查看文件目錄
shell模塊 [執行遠程主機的shell/python腳本,支持管道]
ansible all -m shell -a 'echo oldboy|passwd --stdin user1'  #設置密碼
ansible all -m shell -a 'cat /etc/shadow|grep user1'    #查看用戶
ansible all -m shell -a 'python a.py'  #執行遠程腳本

文件相關

copy
  dest 目標地址
  src 本地地址  
  mode 權限 wrx/755
  owner  屬主
  group  屬組
  backup
  content   直接寫內容,可以用轉移符號
    ansible all -m copy -a 'dest=/data src=/data/a.txt'   #複製單個文件
    ansible all -m copy -a 'src=/etc/init.d dest=/data/'   
    ansible all -m copy -a 'src=/etc/init.d/ dest=/data'  #如果帶/則複製裏面的內容,不帶/則複製目錄,如果是目錄的話,則會遞歸複製
    ansible all -m copy -a 'content="hello world" dest=/data/test.txt' 直接輸入內容
file
  path
  src
  state
    file file代表拷貝後是文件
    link link代表最終是個軟鏈接
    directory directory代表文件夾
    hard hard代表硬鏈接
    touch touch代表生成一個空文件
    absent absent代表刪除
        ansible all -m file -a 'dest=/data/html state=directory'   #創建目錄
        ansible all -m file -a 'dest=/data/html2 state=link src=/etc'  #創建軟鏈接
        ansible all -m file -a 'dest=/data/a.txt state=touch'
        ansible all -m file -a 'dest=/data/a.txt state=absent' 刪除
fetch   
    dest
    src
    ansible 10.211.55.14 -m fetch -a 'src=/data/test.txt dest=/data'

軟件相關

pip
ansible all -m pip -a 'name=django==1.11'
yum
 name
 state
    absent  #卸載
    installed  #安裝
    latest     #安裝最新的版本
    present    #安裝
    removed    #卸載
        ansible all -m yum -a 'name=python-pip state=latest'
        ansible all -m yum -a 'name=nginx state=latest'
        ansible all -m yum -a 'name=nginx state=absent'

service

name
state
 ansible all -m service -a 'name=nginx state=started'
 ansible all -m service -a 'name=nginx state=stopped'

cron

name
weekday 周
hour 時
day 天
minute 分鐘
month 月
job
state
  absent  #刪除
  present  #創建
ansible all -m cron -a 'name=testjob  minute=1 job=ntpdate'
ansible all -m cron -a 'name=testjob  state=absent'

user

name
password
shell
state
uid
group
groups
update_password 
home
ansible all -m user -a 'name=usertest'
ansible all -m user -a 'name=usertest state=absent'

group

gid
name
state  #present 創建  absent 刪除
system #是否是系統組
ansible all -m group -a 'name=usertest '
ansible all -m group -a 'name=usertest state=absent'

playbook 劇本(注意空格)先收集主機

Playbooks 與 ad-hoc 相比,是一種完全不同的運用 ansible 的方式,是非常之強大的.

簡單來說,playbooks 是一種簡單的配置管理系統與多機器部署系統的基礎.與現有的其他系統有不同之處,且非常適合於複雜應用的部署.

Playbooks 可用於聲明配置,更強大的地方在於,在 playbooks 中可以編排有序的執行過程,甚至於做到在多組機器間,來回有序的執行特別指定的步驟.並且可以同步或異步的發起任務.

---
- 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 中的每一個 play,個別地選擇操作的目標機器是哪些,以哪個用戶身份去完成要執行的步驟(called tasks)

---
- hosts: webservers
  remote_user: root

task list

每一個 play 包含了一個 task 列表(任務列表).一個 task 在其所對應的所有主機上(通過 host pattern 匹配的所有主機)執行完畢之後,下一個 task 纔會執行.有一點需要明白的是(很重要),在一個 play 之中,所有 hosts 會獲取相同的任務指令,這是 play 的一個目的所在,也就是將一組選出的 hosts 映射到 task.
在運行 playbook 時(從上到下執行),如果一個 host 執行 task 失敗,這個 host 將會從整個 playbook 的 rotation 中移除. 如果發生執行失敗的情況,請修正 playbook 中的錯誤,然後重新執行即可.
每個 task 的目標在於執行一個 moudle, 通常是帶有特定的參數來執行.在參數中可以使用變量(variables).
modules 具有”冪等”性,意思是如果你再一次地執行 moudle(譯者注:比如遇到遠端系統被意外改動,需要恢復原狀),moudle 只會執行必要的改動,只會改變需要改變的地方.所以重複多次執行 playbook 也很安全.
每一個 task 必須有一個名稱 name,這樣在運行 playbook 時,從其輸出的任務執行信息中可以很好的辨別出是屬於哪一個 task 的. 如果沒有定義 name,‘action’ 的值將會用作輸出信息中標記特定的 task.

tasks:
  - name: make sure apache is running
    service: name=httpd state=running

比較特別的兩個 modudle 是 command 和 shell ,它們不使用 key=value 格式的參數,而是這樣:

tasks:
  - name: disable selinux
    command: /sbin/setenforce 0

使用 command module 和 shell module 時,我們需要關心返回碼信息,如果有一條命令,它的成功執行的返回碼不是0, 你或許希望這樣做:

tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand || /bin/true
tasks:
  - name: run this command and ignore the result
    shell: /usr/bin/somecommand
    ignore_errors: True

如果 action 行看起來太長,你可以使用 space(空格) 或者 indent(縮進) 隔開連續的一行:

tasks:
  - name: Copy ansible inventory file to client
    copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
            owner=root group=root mode=0644

在 action 行中可以使用變量.假設在 ‘vars’ 那裏定義了一個變量 ‘vhost’ ,可以這樣使用它:

tasks:
  - name: create a virtual host file for {{ vhost }}
    template: src=somefile.j2 dest=/etc/httpd/conf.d/{{ vhost }}

檢查語法錯誤

--syntax-check

tags

tags:install

在anible-playbook -t 指定tag

Handlers: 在發生改變時執行的操作

上面我們曾提到過,module 具有”冪等”性,所以當遠端系統被人改動時,可以重放 playbooks 達到恢復的目的. playbooks 本身可以識別這種改動,並且有一個基本的 event system(事件系統),可以響應這種改動.

(當發生改動時)’notify’ actions 會在 playbook 的每一個 task 結束時被觸發,而且即使有多個不同的 task 通知改動的發生, ‘notify’ actions 只會被觸發一次.

舉例來說,比如多個 resources 指出因爲一個配置文件被改動,所以 apache 需要重新啓動,但是重新啓動的操作只會被執行一次.

- name: template configuration file
  template: src=template.j2 dest=/etc/foo.conf
  notify:
     - restart memcached
     - restart apache

‘notify’ 下列出的即是 handlers.
Handlers 也是一些 task 的列表,通過名字來引用,它們和一般的 task 並沒有什麼區別.Handlers 是由通知者進行 notify, 如果沒有被 notify,handlers 不會執行.不管有多少個通知者進行了 notify,等到 play 中的所有 task 執行完成之後,handlers 也只會被執行一次.

handlers:
    - name: restart memcached
      service:  name=memcached state=restarted
    - name: restart apache
      service: name=apache state=restarted

ansible2.2以後可以寫listen,我們來監聽一個時間,

handlers:
    - name: restart memcached
      service:
        name: memcached
        state: restarted
      listen: "restart web services"
    - name: restart apache
      service:
        name: apache
        state:restarted
      listen: "restart web services"

tasks:
    - name: restart everything
      command: echo "this task will restart the web services"
      notify: "restart web services"

執行一個playbook

ansible-playbook playbook.yml -f 10

Include

Include 指令看起來像下面這樣,在一個 playbook 中,Include 指令可以跟普通的 task 混合在一起使用:

tasks:
  - include: tasks/foo.yml

變量

變量命名規則

變量名可以爲字母,數字以及下劃線.變量始終應該以字母開頭

還有其它地方可以獲取變量,這些變量是自動發現的,而不是用戶自己設置的.

Facts通過訪問遠程系統獲取相應的信息. 一個例子就是遠程主機的IP地址或者操作系統是什麼. 使用以下命令可以查看哪些信息是可用的:

ansible hostname -m setup
{{ ansible_nodename }}

註冊變量

變量的另一個主要用途是在運行命令時,把命令結果存儲到一個變量中.不同模塊的執行結果是不同的.運行playbook時使用-v選項可以看到可能的結果值.

    • 
      hosts: web_servers
      tasks:
    • shell: /usr/bin/foo
      register: foo_result
      ignore_errors: True
    • shell: /usr/bin/bar
      when: foo_result.rc == 5

命令行中傳遞變量

除了vars_promptvars_files也可以通過Ansible命令行發送變量.如果你想編寫一個通用的發佈playbook時則特別有用,你可以傳遞應用的版本以便部署:

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"

其它場景中也很有用,比如爲playbook設置主機羣組或用戶.

---

- hosts: '{{ hosts }}'
  remote_user: '{{ user }}'

  tasks:
     - ...

ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"

變量的來源

  • 通過setup獲取

  • 用戶自定義

    • 通過命令行傳遞 -e

    • playbook傳遞

    • 
      vars:
    • name:name-value
      name2:name2-value

    hosts配置文件中定義

    ​ 直接在主機後面定義

    [hostgourpname:vars]
    name:name-value

訪問複雜變量數據

有些提供的facts,比如網絡信息等,是一個嵌套的數據結構.訪問它們使用簡單的 {{ foo }} 語法並不夠用,當仍然很容易.如下所示:

{{ ansible_eth0["ipv4"]["address"] }}
{{ ansible_eth0.ipv4.address }}

條件判斷

when: 條件==“條件”

循環

通常你想在一個任務中幹很多事,比如創建一羣用戶,安裝很多包,或者重複一個輪詢步驟直到收到某個特定結果.

標準循環

爲了保持簡潔,重複的任務可以用以下簡寫的方式:

- name: add several users
  user: name={{ item }} state=present groups=wheel
  with_items:
     - testuser1
     - testuser2

嵌套循環

- hosts: all
  remote_user: root
  tasks:
  - name: add user
    user: name={{ item[0] }} groups={{ item[1] }}
    with_nested:
    - ["old1","old2"]
    - ["nginx,docker"]

Ansible Galaxy

Ansible Galaxy 是一個自由網站,網站提供所有類型的由社區開發的 roles,這對於實現你的自動化項目是一個很好的參考。網站提供這些 roles 的排名、查找以及下載。

應用實例

你現在已經學過 tasks 和 handlers,那怎樣組織 playbook 纔是最好的方式呢?簡單的回答就是:使用 roles ! Roles 基於一個已知的文件結構,去自動的加載某些 vars_files,tasks 以及 handlers。基於 roles 對內容進行分組,使得我們可以容易地與其他用戶分享 roles 。
如果 roles/x/tasks/main.yml 存在, 其中列出的 tasks 將被添加到 play 中
如果 roles/x/handlers/main.yml 存在, 其中列出的 handlers 將被添加到 play 中
如果 roles/x/vars/main.yml 存在, 其中列出的 variables 將被添加到 play 中
如果 roles/x/meta/main.yml 存在, 其中列出的 “角色依賴” 將被添加到 roles 列表中 (1.3 and later)
所有 copy tasks 可以引用 roles/x/files/ 中的文件,不需要指明文件的路徑。
所有 script tasks 可以引用 roles/x/files/ 中的腳本,不需要指明文件的路徑。
所有 template tasks 可以引用 roles/x/templates/ 中的文件,不需要指明文件的路徑。
所有 include tasks 可以引用 roles/x/tasks/ 中的文件,不需要指明文件的路徑。

production                # inventory file for production servers 關於生產環境服務器的清單文件
stage                     # inventory file for stage environment 關於 stage 環境的清單文件

group_vars/
   group1                 # here we assign variables to particular groups 這裏我們給特定的組賦值
   group2                 # ""
host_vars/
   hostname1              # if systems need specific variables, put them here 如果系統需要特定的變量,把它們放置在這裏.
   hostname2              # ""

library/                  # if any custom modules, put them here (optional) 如果有自定義的模塊,放在這裏(可選)
filter_plugins/           # if any custom filter plugins, put them here (optional) 如果有自定義的過濾插件,放在這裏(可選)

site.yml                  # master playbook 主 playbook
webservers.yml            # playbook for webserver tier Web 服務器的 playbook
dbservers.yml             # playbook for dbserver tier 數據庫服務器的 playbook

roles/
    common/               # this hierarchy represents a "role" 這裏的結構代表了一個 "role"
        tasks/            #
            main.yml      #  <-- tasks file can include smaller files if warranted
        handlers/         #
            main.yml      #  <-- handlers file
        templates/        #  <-- files for use with the template resource
            ntp.conf.j2   #  <------- templates end in .j2
        files/            #
            bar.txt       #  <-- files for use with the copy resource
            foo.sh        #  <-- script files for use with the script resource
        vars/             #
            main.yml      #  <-- variables associated with this role
        defaults/         #
            main.yml      #  <-- default lower priority variables for this role
        meta/             #
            main.yml      #  <-- role dependencies

    webtier/              # same kind of structure as "common" was above, done for the webtier role
    monitoring/           # ""
    fooapp/               # ""

site.yml

在 site.yml 中,我們包含了一個定義了整個基礎設施的 playbook.注意這個 playbook 是非常短的, 因爲它僅僅包含了其他 playbooks.記住, playbook 不過就是一系列的 plays:

---
# file: site.yml
- include: webservers.yml
- include: dbservers.yml

在諸如 like webservers.yml 的文件中(同樣也在頂層結構),我們僅僅將 Web 服務器組與對應的 role 行爲做映射.同樣值得注意的是這也非常的短小精悍.例如:

---
# file: webservers.yml
- hosts: webservers
  roles:
    - common
    - webtier

理念是我們能夠通過 “運行”(running) site.yml 來選擇整個基礎設施的配置.或者我們能夠通過運行其子集 webservers.yml 來配置. 這與 Ansible 的 “–limit” 類似,而且相對的更爲顯式:

ansible-playbook site.yml --limit webservers
ansible-playbook webservers.yml

接下來的示例任務文件展示了一個 role 是如何工作的.我們這裏的普通 role 僅僅用來配置 NTP,但是如果我們想的話,它可以做更多:

---
# file: roles/common/tasks/main.yml

- name: be sure ntp is installed
  yum: pkg=ntp state=installed
  tags: ntp

- name: be sure ntp is configured
  template: src=ntp.conf.j2 dest=/etc/ntp.conf
  notify:
    - restart ntpd
  tags: ntp

- name: be sure ntpd is running and enabled
  service: name=ntpd state=running enabled=yes
  tags: ntp

這是個處理文件樣例.作爲一種審覈,它只有當特定的任務報告發生變化時會被觸發,並在每個 play 結束時運行:

---
# file: roles/common/handlers/main.yml
- name: restart ntpd
  service: name=ntpd state=restarted
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章