ansible

ansible可以批量管理多臺主機。通過調用各個功能模塊、ssh連接、發送python腳本、遠程主機上的一些命令來完成管理各被控端,所以不用給各被管理節點專門安裝客戶端工具。


不過一般需要事先配置ansible端能基於密鑰認證的方式聯繫各被管理節點。

如果要用密碼的方式,要啓用主配置文件中的ask_pass  = True,並安裝上sshpass軟件即可


目錄:

一、介紹

二、常用模塊介紹

三、playbook

四、roles


wKioL1a8AeKzFMFhAABZ2m7AMb4382.png


想深入瞭解的朋友請看這裏:http://www.ansible.com.cn/

或這裏:http://docs.ansible.com/


一、介紹:

模塊化,調用特定的模塊來完成特定任務;
基於Python語言實現,由Paramiko, PyYAML和Jinja2三個關鍵模塊>實現;
支持自定義模塊
支持playbook: 可以把多個任務編排好,一次性的執行完。
冪等性:多次執行的結果是一樣的。


ansible命令的使用方式還是很簡單的:

ansible <host-pattern> [-f forks] [-m module_name] [-a args]

host_pattern 是來指定主機的,可以是單臺主機,也可以是主機組。前提是要在ansible的hosts配置文件中指定。

-f 指定一次批量管理的主機數量。 可以說就是併發管理數量。 與總的數量沒有關係。

-m 指定模塊。

-a  模塊參數


它所有的管理功能都是由各個模塊所提供,查看模塊使用方法:

ansible-doc [-M module_path] [-l] [-s] [module...]

-M 查看模塊的詳細信息,要指定模塊的路徑

-l   列出所有模塊。

-s  查看模塊使用方式。


安裝:

ansible依賴於Python 2.6或更高的版本、paramiko、PyYAML及Jinja2。

編譯安裝

# yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto
# python setup.py build
# python setup.py install
# mkdir /etc/ansible
# cp -r examples/* /etc/ansible


注意:不同版本的ansible的功能差異可能較大。

我這裏就直接yum安裝了。

環境:

系統: CentOS Linux release 7.1.1503 (Core)

軟件: ansible-1.9.2-1.el7


看一下所生成的文件:

/etc/ansible
/etc/ansible/ansible.cfg          #ansible主配置文件。  一般不用修改,如果想自定義一下,請看上面的網址。
/etc/ansible/hosts                   #主配置文件中所指定的主機清單文件 
/etc/ansible/roles                   #用來定義roles的目錄
/usr/bin/ansible                      
/usr/bin/ansible-doc
/usr/bin/ansible-galaxy
/usr/bin/ansible-playbook
.....


首先我們需要在hosts裏面定義各被管主機。這個文件被稱爲inventory文件。

[root@localhost ~]# vim /etc/ansible/hosts      
[wserver]
172.16.40.11
172.16.40.12

[dbserver]
172.16.40.20

這個文件裏面都是一些定義主機的例子,我這裏把它們註釋了,添加了上面幾個。

inventory文件遵循INI文件風格,中括號中的是組名,可以用各個組名錶示多個主機。 也可以用all來表示所有主機。 當然也可以使用單個主機。同一個主機可以出現在多個組中。

此外,當如若目標主機使用了非默認的SSH端口,還可以在主機名稱之後使用冒號加端口號來標明。

如: 172.16.40.11:22022

組還可以包含其它的組,組嵌套。


在這裏如果所管理主機的系統版本不一樣也沒問題,因爲ansible會檢測主機的系統參數並做出不同的設置。但並不是絕對不會有問題。

每次執行操作會發送python腳本到客戶端的   對應用戶家目錄下的.ansible/tmp目錄下面。 具體作用暫時不清楚,可能是用來收集信息、執行任務和調用本地的命令的吧。


二、常用模塊介紹:

這裏只是常用的部分,詳細的可以用ansible-doc來查看。如查看一下user模塊。

[root@localhost ~]# ansible-doc -s user

帶=號的表示必選項。

http://docs.ansible.com/ansible/modules_by_category.html


user: 用戶管理

state={present|absent}   #present表示創建,absent表示刪除。
force=yes          #強制刪除用戶。 一般情況下用戶在已登錄狀態下是不能刪除的。相當於userdel -f
remove=yes     #在刪除用戶的時候,同時刪除家目錄與mail spool。相當於userdel -r    
system=yes   #創建的系統用戶   
uid                #指定uid
shell             #指定shell
password       #用來指定密碼,要用已加密的密碼。

上面的password後面的密碼可以用openssl passwd 來生成。但是好像只能是md5加密的。

[root@localhost ~]# openssl passwd --help
Usage: passwd [options] [passwords]
where options are
-crypt             standard Unix password algorithm (default)
-1                 MD5-based password algorithm
.....

例:

[root@localhost ~]# openssl passwd -1 
Password: 
Verifying - Password: 
$1$.0isU960$NDoCtqtkDBa2q9TQJYQml1

[root@localhost ~]# ansible all -m user -a 'name=test1 password="$1$.0isU960$NDoCtqtkDBa2q9TQJYQml1"'
172.16.40.11 | success >> {
    "changed": true,                                                                                                                        
    "comment": "",                                                                                                                          
    "createhome": true,                                                                                                                     
    "group": 1007,                                                                                                                          
    "home": "/home/test1",                                                                                                                  
    "name": "test1",                                                                                                                        
    "password": "NOT_LOGGING_PASSWORD",                                                                                                     
    "shell": "/bin/bash",                                                                                                                   
    "state": "present",                                                                                                                     
    "system": false,                                                                                                                        
    "uid": 1007                                                                                                                             
} 
.....

刪除:

[root@localhost ~]# ansible all -m user -a 'name=test1 state=absent'


group: 組管理

  action: group
      gid                    # Optional `GID' to set for the group.
      name=             # Name of the group to manage.
      state                 # Whether the group should be present or not on the remote host.
      system             # If `yes', indicates that the group created is a system group.

與user差不多,而且參數也就只有這幾個。


cron:  管理cron計劃任務

      day                    # Day of the month the job should run ( 1-31, *, */2, etc )
      hour                   # Hour when the job should run ( 0-23, *, */2, etc )
      job                    # The command to execute. Required if state=present.
      minute                 # Minute when the job should run ( 0-59, *, */2, etc )
      month                  # Month of the year the job should run ( 1-12, *, */2, etc )
      name=                  # Description of a crontab entry.
      state                  # Whether to ensure the job is present or absent.
      user                   # The specific user whose crontab should be modified.
      weekday                # Day of the week that the job should run ( 0-6 for Sunday-Saturday, *, etc )
      .....

只要使用過cron,我想也不用過多解釋吧。state與上面的模塊一個意思,時間參數不寫表示*。

name用來描述任務,andible也用它來識別各個添加的任務,才能用來刪除不同的任務。

如果有name相同的任務,會覆蓋。


例:

[root@localhost ~]# ansible wserver -m cron -a 'name=sync_time minute=*/5 job="/sbin/ntpdate 172.16.0.1 > /dev/null;/sbin/hwclock -w"'

連到一臺主機看一下crontab。

[root@localhost ~]# crontab -l
*/15 * * * * /sbin/ntpdate 172.16.0.1 > /dev/null;/sbin/hwclock > /dev/null    #這個是原來就有的。
#Ansible: sync_time                #這個就是我們剛添加的。
*/5 * * * * /sbin/ntpdate 172.16.0.1 > /dev/null;/sbin/hwclock -w

刪除:

[root@localhost ~]# ansible wserver -m cron -a 'name=sync_time state=absent'


例: 添加每2天的2:30備份/etc目錄到/var/backup下。

[root@localhost ~]# ansible wserver -m cron -a 'name=etc_tar minute=30 hour=2 day=*/2 job="/bin/tar -Jcf /var/backup/`/bin/date "+\\%Y\\%m\\%d-\\%H\\%M"`.tar.xz /etc"'

查看一下:

#Ansible: etc_tar
30 2 */2 * * /bin/tar -Jcf /var/backup/`/bin/date +\%Y\%m\%d-\%H\%M`.tar.xz /etc


ping: 探測主機是否在線

[root@localhost ~]# ansible all -m ping

這個模塊沒有參數,只是用來探測主機是否在線的。


file: 文件管理

path=            #表示文件路徑,必選項。
mode            #表示設置權限
owner            #屬主  
group             #屬組
state=directory      #創建目錄或修改目錄權限。
state=touch            #創建文件或修改文件權限。
state=file                 #修改文件權限。
state=link                #創建文件的符號鏈接。src=源文件   path=鏈接文件
state=absent           #刪除文件或目錄。

創建目錄是遞歸創建的,也就是會自動創建所需的目錄。 而文件或鏈接文件都不行。


例:創建目錄。

[root@localhost ~]# ansible wserver -m file -a 'path=/var/backup/ state=directory'
[root@localhost ~]# ansible wserver -m file -a 'path=/tmp/6/7/8/9  state=directory'

例:創建鏈接文件。把etc目錄鏈接至/tmp/etc。

[root@localhost ~]# ansible wserver -m file -a 'path=/tmp/etc src=/etc  state=link'


copy: 複製文件

content          #代替src,設置文件中的內容爲指定的內容。如果目標文件不存在,則自動創建隨機名稱文件。
                                   #如果原來文件有數據,則覆蓋。  暫時不知道有什麼用。
src                    #源文件路徑。
owner              #屬主。
group                #屬組。
mode                #權限。   
dest=                 #目標路徑。
backup              #覆蓋文件之前,先備份。 yes/no


例: 把/etc/nginx目錄複製到遠程主機的/etc/下面。

[root@localhost ~]# ansible wserver -m copy -a 'src=/etc/nginx dest=/etc/'


例:複製本地的/home/star/httpd.conf文件到遠程主機的/etc/httpd/conf/目錄下,並修改權限。

ansible wserver -m copy -a 'src=/home/star/httpd.conf owner=root group=root mode=644 dest=/etc/httpd/conf/'


例: 修改遠程主機的/var/listen文件內容爲, 第一行listen=80 第二行listen=8080

[root@localhost ~]# ansible wserver -m copy -a 'content="listen=80\nlisten=8080\n" dest=/var/listen'

查看一下遠程主機的這個文件:

[root@localhost ~]# ssh 172.16.40.11 'cat /var/listen'
listen=80
listen=8080


template:模板複製文件

也是用來複制數據的,只不過文件中的數據可以用變量替換,爲不同的主機附加不同的變量,會把文件中定義的變量在發送之前轉換爲給對應主機所定義的變量的值,也就可以實現不同的主機所複製的文件中的數據是不同的。

而同組中主機定義不同的變量可以通過定義主機變量來實現

主機變量:定義在inventory中的主機之後的變量

如:

/etc/ansible/hosts文件中的主機後面加上變量。

[wserver]
172.16.40.11 port=8800
172.16.40.12 port=8888

要複製的源文件中引用變量可以這樣: Listen ` port `

但我這裏好像說當前版本中template不支持命令行使用

[root@localhost ~]# ansible wserver -m template -a 'src=/home/star/http.conf dest=/etc/httpd/conf'
172.16.40.11 | FAILED => in current versions of ansible, templates are only usable in playbooks
172.16.40.12 | FAILED => in current versions of ansible, templates are only usable in playbooks

一會兒在playbooks的時候再來說明template模塊。 其它變量也在那裏說明。


yum: yum安裝軟件,也有apt,zypper。

conf_file         #設定遠程yum安裝時所依賴的配置文件。如配置文件沒有在默認的位置。
disable_gpg_check    #是否禁止GPG checking,只用於`present' or `latest'。
disablerepo   #臨時禁止使用yum庫。 只用於安裝或更新時。
enablerepo    #臨時使用的yum庫。只用於安裝或更新時。
name=            #所安裝的包的名稱
state               #present安裝, latest安裝最新的, absent 卸載軟件。
update_cache  #強制更新yum的緩存。


例:安裝httpd。

這裏只是說明一下conf_file的用法,yum的倉庫文件沒有在/etc/yum.repos.d/目錄下的話。

[root@localhost ~]# ansible wserver -m yum -a 'name=httpd state=present conf_file="/root/local.repo"'


如果庫本來是禁止使用的,就要用enablerepo來臨時使用這個庫。

這裏的yum庫文件已經在/etc/yum.repos.d/目錄下了,不需要conf_file指定配置文件了。

[root@localhost html]# ansible wserver -m yum -a 'name=httpd state=present enablerepo=local'

這裏的庫ID 就是local.


卸載:

[root@localhost html]# ansible wserver -m yum -a 'name=httpd state=absent'

注意:返回的數據的    "changed": true, 


安裝包組,只要在名稱前面加上@就可以了。

如:安裝開發工具的包組:

[root@localhost html]# ansible dbserver -m yum -a 'name="@Development Tools" state=present'


service: 服務程序管理


arguments            #命令行提供額外的參數
enabled                 #設置開機啓動。
name=                  #服務名稱
runlevel                #開機啓動的級別,一般不用指定。
sleep                     #在重啓服務的過程中,是否等待。如在服務關閉以後等待2秒再啓動。
state                      #started啓動服務, stopped停止服務, restarted重啓服務, reloaded重載配置。

啓動httpd服務:

[root@localhost html]# ansible all -m service -a 'name=httpd state=started'

設置開機啓動:

[root@localhost ~]# ansible all -m service -a 'name=httpd enabled=yes'

重啓服務:

[root@localhost ~]# ansible all -m service -a 'name=httpd sleep=2 state=restarted'


command: 直接執行命令,默認模塊,可以不用指定。

顯示所有主機時間:

[root@localhost ~]# ansible all -a 'date'
172.16.40.20 | success | rc=0 >>
Thu Feb 11 16:04:37 CST 2016

172.16.40.12 | success | rc=0 >>
Thu Feb 11 16:04:37 CST 2016

172.16.40.11 | success | rc=0 >>
Thu Feb 11 16:04:37 CST 2016


這個模塊與shell差不多,但是不能執行管道類的操作,如:

wKioL1a8SOWQtOUxAABDd8hs1KY380.png

還有點不同是,command是在當前shell所執行的命令,而shell是在子shell中執行的命令。但是在被控端和管理端用pstree查看進程的時候,卻也沒發現不一樣的。這個說法現在是有點不明白。


shell: 直接執行命令,參數一般也用不到。

這個可以執行管道類的命令,如:

wKiom1a8THvTuM8_AABlMTYCPyE033.png


script:發送腳本到各被管理節點,並執行。同樣不需要參數。

[root@localhost ~]# ansible all -m script -a 'test.sh'

直接在-a 後面指定腳本即可。


selinux: 管理selinux。

conf     #指定應用selinux的配置文件。
state=enforcing|permissive|disabled           #對應於selinux配置文件的SELINUX。
policy=targeted|minimum|mls        #對應於selinux配置文件的SELINUXTYPE

關閉selinux:

[root@localhost ~]# ansible all -m selinux -a 'state=disabled'

在selinux處於enforceing狀態下的時候好像只能用permissive。

在state非disabled的情況下必須要指定policy。


setup:獲取指定主機的facts。

facts是由正在通信的遠程目標主機發回的信息,這些信息被保存在ansible變量中。

[root@localhost ~]# ansible 172.16.40.11 -m setup

 返回很多對應主機的信息,在後面的操作中可以根據不同的信息來做不同的操作。如redhat系列用yum安裝,而debian系列用apt來安裝軟件。



三、playbook。

playbook就是一個用yaml語法把多個模塊堆起來的一個文件而已。

yaml: http://www.yaml.org


3.1: 結構介紹

playbooks核心元素:
Tasks            定義任務
Variables      定義變量
Templates      定義模板
Handlers        Notify 處理
Roles


除了核心元素以外還有額外的元素,而每個元素也包含了獨有的元素。

YAML參考了多種語言,其中就有python。所以在寫playbook的時候,段落縮進很重要。

看一下下面這個例子,最外圍就是主要的元素,而各個主元素裏面還有各個子元素。


每一個-開始表示一個列表的開始,到下一個-之前結束,也可以說這之間就是一個項目,一齣戲。

各個列表之間是沒有關係的,我們只要區分開也就不混亂了。tasks裏面就是模塊的使用了,所以整體來說結構還是很直觀的。

        - hosts: 172.16.100.68        #定義主機
          vars:                      #定義變量
               var1: value
               var2: value
          tasks:                    #定義任務
               - name:           #任務名稱。
                                        #這裏就可以開始用模塊來執行具體的任務了。
               - name:

               - name:

          handlers:             #定義觸發通知所作的操作。裏面也是跟tasks一樣,用模塊定義任務。
               - name:

          remote_user:             #遠程主機執行任務時的用戶。一般都是root,一般也不用指定。
        - hosts: 172.16.100.69
          vars:
          tasks:
          handlers:
          remote_user:


-表示一個列表的開始,一個列表表示一個獨立的整體結構,而列表裏面的元素(表項)是由字典組成的,字典中存儲的就是各個要定義的鍵值。如:tasks是字典的鍵,裏面的各部分是值。只不過這部分同時又是列表。

vars是用來定義變量的,所以裏面的各變量都是字典而不是列表。只不過vars是字典的鍵,裏面的兩項是字典的值,而這個值同樣也是字典。

網上有的說每一個-表示一個表項。不過意思差不多,只不過最外圍加了一個列表而已。不過這樣好亂啊。

這裏跟使用沒有關係,如果感覺混亂就不用管了。瞭解一下python的話也就容易理解了。


結構差不多也就是這樣了,來補充點:
各字典項的鍵冒號與值之間要有空格。  如:hosts: abc

字典項要與-之間有空格。表示在結構內。並不是說Hosts特殊要在-的後面。 它也可以在下面的一行開始。如:

-
  hosts:
  tasks:


-表示列表的開始,後面的hosts跟下面的vars之類的都是同一級。不過要注意前面都要有兩個空格的縮進,表示在此結構內。就好像是第一級結構爲- ,  每二級結構與第一級結構之間要用空格隔開。


3.2:變量

變量名僅能由字母、數字和下劃線組成,且只能以字母開頭。

變量種類:
1、facts:由遠程主機發回的主機屬性信息,這些信息被保存在ansible變量中;無須定義,可直接調用;
2、自定義變量:
        2.1、通過命令行傳遞: ansible-playbook  指令後面指定變量:--extra-vars "var1= var2=" ,簡寫 -e “vars="

        2.2、通過roles傳遞
        2.3、主機變量:定義在inventory中的主機之後的變量
        2.4、組變量:定義在inventory中的組上的變量。如:

[wserver]
172.16.40.11 port=8800
172.16.40.12 port=8888

[wserver:vars]
port=80

[dbserver]
172.16.40.20

[dbserver:vars]
port=3306


       2.5、在playbook的vars元素下面定義變量.

3.3 使用:

實現目標:

1、wserver組主機安裝httpd。

2、複製本機已配置好的httpd配置文件到各主機。

3、啓動httpd,並設置開機啓動。

[root@localhost ~]# vim httpd.yml

- hosts: wserver
  remote_user: root
  tasks:
        - name: install httpd
          yum: name=httpd state=present
        - name: copy httpd configuration
          copy: src=/root/httpd dest=/etc/
        - name: start httpd
          service: name=httpd state=started
        - name: boot httpd start
          service: name=httpd enabled=yes

wKioL1a8faqRwgUQAAA1abdNwDM345.png

執行過程。用ansible-playbook來執行playbook文件。文件擴展名隨意,我這裏習慣用yml了。

wKioL1a8famA_w5nAADCBtKPAGc725.png

***表示發生變化,綠色表示未變化,紅色表示錯誤。 ok=5  changed=4 表示完成了5個,其中4個發生變化。


查看httpd是否啓動:

[root@localhost ~]# ansible wserver -m shell -a 'ss -tnlp'            #直接查看信息,但多了以後。。。
[root@localhost ~]# ansible wserver -m shell -a 'ss -tnlp' | grep httpd | wc -l     #可以直接用wc來計數。

是否開機啓動:

[root@localhost ~]# ansible wserver -m shell -a 'systemctl status httpd'
或者:
[root@localhost ~]# ansible wserver -m shell -a 'systemctl status httpd' | grep enabled | wc -l

條件判斷

如果要管理有主機中有不同系列的系統,這裏只是做個比喻。正常情況下應該連繫統版本都是相同的。

比如有一臺ubuntu的主機,因爲它的軟件管理用的是apt-get。在ansible裏面是用apt模塊來操作的。而且配置文件也不一樣,軟件的名稱也不一樣,服務腳本也不一樣。額,複雜了好像。

只要在一個任務的最後加上when就可以了,意思是說只有當後面的條件滿足的時候才執行此任務。

條件變量就是facts類的變量。可以用ansible 主機 -m setup來查看,上面模塊部分也說了。可以用ansible_os_family這個變量。

wKioL1a8j0yQcyfaAAASa_qPiYc681.png

wKiom1a8jvCyT6tPAAATtIJtQMI735.png


httpd.yml

- hosts: wserver
  remote_user: root
  tasks:
        - name: install httpd redhat
          yum: name=httpd state=present
          when: ansible_os_family == "RedHat"
        - name: copy httpd configuration
          copy: src=/root/httpd dest=/etc/
          when: ansible_os_family == "RedHat"

        - name: install apache2 debian
          apt: name=apache2 state=present
          when: ansible_os_family == "Debian"
        - name: copy apache2 configuration
          copy: src=/root/apache2 dest=/etc/
          when: ansible_os_family == "Debian"

        - name: start httpd
          service: name=httpd state=started
          when: ansible_os_family == "RedHat"
        - name: boot httpd start
          service: name=httpd enabled=yes
          when: ansible_os_family == "RedHat"


        - name: start apache2
          service: name=apache2 state=started
          when: ansible_os_family == "Debian"
        - name: boot apache2 start
          service: name=apache2 enabled=yes
          when: ansible_os_family == "Debian"

wKioL1a8j4Hgv1r7AACzJcxOmAY815.png

執行效果:

wKioL1a8kEnjQWKqAAEGXPj-U0A311.png

wKiom1a8j-6Ak4zMAAB9cvHEfMk653.png

這裏因爲apache2的配置文件沒有修改,與安裝完成所生成的配置一模一樣,通過檢驗發現一樣就不會再複製了。所以是綠色的字。

有沒有發現這樣麻煩的不是一星半點啊。


再貼一個刪除這些軟件的:

- hosts: wserver
  remote_user: root
  tasks:
        - name: stop httpd
          service: name=httpd state=stopped
          when: ansible_os_family == "RedHat"
        - name: erase httpd
          yum: name=httpd state=absent
          when: ansible_os_family == "RedHat"
        - name: erase /etc/httpd
          file: path=/etc/httpd state=absent
          when: ansible_os_family == "RedHat"

        - name: stop apache2
          service: name=apache2 state=stopped
          when: ansible_os_family == "Debian"
        - name: erase apache2
          apt: name=apache2 state=absent purge=yes
          when: ansible_os_family == "Debian"
        - name: erase /etc/apache2
          file: path=/etc/apache2 state=absent
          when: ansible_os_family == "Debian"


標籤:

有時候只想用這個文件中的複製配置文件的功能,而不想再每一項都檢查,雖然也沒什麼問題。

- hosts: wserver
  remote_user: root
  tasks:
        - name: install httpd redhat
          yum: name=httpd state=present

        - name: copy httpd configuration
          copy: src=/root/httpd dest=/etc/
          tags: config                                                #加了一個tags.

        - name: start httpd
          service: name=httpd state=started

        - name: boot httpd start
          service: name=httpd enabled=yes

wKiom1a8k9fxY0_4AACPy9YK-8s601.png

我這裏的httpd給重新安裝了,所以配置文件是不同的,纔會顯示changed。不然會是綠色的ok。

現在只執行了config標符所指定的任務了。 我這裏忘了把hosts文件中的172.16.40.1去掉了。

那麼複製完配置文件以後應該重載配置文件纔對。可是就算再添加一個任務,因爲我們指定了標籤也不會執行。那麼就可以用handlers啦。


handlers:

也是task任務,但只有其關注的條件滿足時,纔會被觸發執行。這裏的條件其實就是發生修改。

如果我們複製配置文件和遠程主機上的一樣,那就不會觸發了。

- hosts: wserver
  remote_user: root
  tasks:
        - name: install httpd redhat
          yum: name=httpd state=present

        - name: copy httpd configuration
          copy: src=/root/httpd dest=/etc/
          notify: reload httpd                            #添加了一行這個。用以觸發名稱爲reload httpd的handlers。
          tags: config

        - name: start httpd
          service: name=httpd state=started

        - name: boot httpd start
          service: name=httpd enabled=yes
  handlers:
        - name: reload httpd
          service: name=httpd state=reloaded

現在配置文件沒有修改之前:

wKioL1a8l2rxtZffAABmdXa4rmo705.png

修改之後:

wKioL1a8l42T9gdXAACNBDeWXYE133.png


templates:
用於生成文本文件(配置文件);模板文件中可使用jinja2表達式,表達式要定義在` `,也可以簡單地僅執行變量替換;我們這裏也只來演示一下變量替換的。

如我想給不同的主機的配置文件所監聽的端口不一樣。

可以通過主機變量,定義/etc/ansible/hosts文件:

[wserver]
172.16.40.11 port=8800
172.16.40.12 port=8888

修改要複製過去的配置文件,

httpd.conf

Listen {{ port }}        #httpd的配置文件,listen用來監聽端口。在複製之前ansible會把{{ port }}替換爲對應主機所設置的變量值。

現在的playbook文件:爲了節省篇幅,我這裏把現在用不到都刪了。而因爲是修改端口,所以把reload改成了restart。

- hosts: wserver
  remote_user: root
  tasks:
        - name: template httpd configuration
          template: src=/root/httpd/conf/httpd.conf dest=/etc/httpd/conf/         #src好像不能再指目錄了。
          notify: restart httpd

  handlers:
        - name: restart httpd
          service: name=httpd state=restarted

wKiom1a8nGvCvm4pAACPRS3QHYM246.png

一臺主機監聽在8800,一臺主機監聽在8888。


迭代:

如果想要批量創建多個用戶怎麼辦,當然用script模塊最簡單了,不過這裏也只是來說明一下問題而已:

在task中調用內置的item變量;在某個task後面使用with_items語句來定義元素列表;

- hosts: wserver
  remote_user: root
  tasks:
        - name: create test user
          user: name={{ item }} state=present
          with_items:
                - test1
                - test2
                - test3
                - test4

wKiom1a8n7yRWI8iAAAgqFLHFSk335.png

wKioL1a8oBfhthJ1AAC9CUt8YzA592.png


而上面所指定item還可以有子集, 可以用字典來表示item中的各個鍵值,而不只是用表示單個值。

如:

- hosts: wserver
  remote_user: root
  tasks:
        - name: create test user
          user: name={{ item.user }} group={{ item.group }} state=present
          with_items:
                - { user: "test10", group: "root" }
                - { user: "test11", group: "root" }
                - { user: "test12", group: "root" }

wKioL1a8obmBXEyGAABCGSydaTk976.png

wKiom1a8oVyhsw6eAADBfCgaLKk626.png


一直沒有介紹vars自定義變量,這裏我們來看一下。

wKioL1a8owSDvH0TAABVoQkYmLI981.png

wKioL1a8owbhT9JnAADBXjvIw_w359.png

這樣想創建什麼用戶,就可以直接修改vars裏面的變量就可以。


四、roles。

roles只是把任務給分離出去了。只要在playbook文件中調用此role就可執行這些任務。

如我們定義了一個很複雜的任務,但是要用在另外的主機組或只想用於單臺主機的時候就要修改這個文件,總修改也不是辦法。 可以複製多份,但有時候也不夠靈活。

所以就可以用role把任務主體分離出來,只在playbook中寫一些額外的東西,如變量,主機等等。


roles用於實現“代碼複用”。

roles以特定的層次型格式組織起來playbook中的各主元素(vars, tasks, handlers)。每一個主元素都以一個目錄來表示。


各目錄如下:

files:此角色中用到的所有文件均放置於此目錄中; 對應於copy模塊。
templates:Jinja2模板文件存放位置;  對應於template模塊。
tasks:任務列表文件;裏面可以有多個文件,但至少有一個叫做main的文件;
handlers:處理器列表文件;裏面可以有多個文件,但至少有一個叫做main的文件;
vars:變量字典文件;裏面可以有多個文件,但至少有一個叫做main的文件;
meta:此角色的特殊設定及依賴關係;


在/etc/ansible/roles/目錄下面的目錄就是各個單獨的rule。調用的時候直接調用目錄名稱。

[root@localhost createweb]# pwd
/etc/ansible/roles/createweb
[root@localhost createweb]# ls
files  handlers  meta  tasks  templates  vars
[root@localhost createweb]# tree -L 2
.
├── files                    #存放copy用到的文件。
│   ├── config
│   ├── httpd
│   ├── index.php
│   ├── iptables.bak.conf
│   └── rc.local
├── handlers             #定義handlers。
│   └── main
├── meta
├── tasks                    #定義任務。
│   └── main
├── templates           #存放template模塊用到的文件。
│   └── httpd.conf
└── vars                     #定義變量。
    └── main


如我這裏的tasks/main文件:

效果就是:安裝httpd,創建所需要的網頁目錄,創建日誌目錄,複製所有配置文件,複製php測試頁面。並啓動httpd。

- name: install httpd
  yum: name=httpd state=present
- name: install php
  yum: name=php state=present
- name: install mod_ssl
  yum: name=mod_ssl state=present

#create http_page file
- name: create directory
  file: state=directory path={{ http_page_path_www }}
  file: state=directory path={{ http_page_path_myadm }}

#create log_file directory
- name: create log directory
  file: state=directory path={{ http_log_path_www }}
  file: state=directory path={{ http_log_path_myadm }}

- name: copy all web config
  copy: src=httpd dest=/etc/
  notify: restart httpd

- name: copy php_test file
  copy: src=index.php dest=/web/vhosts/www/
  copy: src=index.php dest=/web/vhosts/myadm/

- name: start httpd and enabled
  service: name=httpd state=started enabled=yes

handlers/main

- name: restart httpd
  service: name=httpd state=restarted

vars/main  

http_port: 8000

http_log_path_www: /var/log/httpd/www
http_log_path_myadm: /var/log/httpd/myadm

http_page_path_www: /web/vhosts/www
http_page_path_myadm: /web/vhosts/myadm


定義playbook:

- hosts: wserver
  roles:
       - createweb


我這個的執行結果在遠程主機上有點問題。不過大體上也就是這種結構,在playbook的roles裏面還可以定義很參數,這裏就先不介紹了,以後有時間再來改改。


謝謝瀏覽,如有錯誤還請指出。j_0022.gif

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章