?Ansible

Ansible


ansible簡介

ansible playbooks

ansible部署{keepalived+nginx{httpd, mysql, php}}


ansible簡介

Ansible is a radically simple configuration-management, application deployment, task-execution, and multinode orchestration engine. 
Ansible是一款輕量級自動化運維工具,由Python語言開發,結合了多種自動化運維工具的特性,實現了批量系統配置、批量應用部署、批量命令執行等功能;ansible是基于模塊化實現批量操作的。

ansible特點: 
模塊化、部署簡單、工作于agentless模式、默認使用ssh協議、支持自定義模塊、支持Palybook等 

ansiblestruct.png

  • Ansible: 核心程序;

  • Modules: 包括 Ansible 自帶的核心模塊及自定義模塊;

  • Plugins: 完成模塊功能的補充,包括連接插件、郵件插件等;

  • Playbooks: 網上很多翻譯為劇本,個人覺得理解為編排更為合理;定義 Ansible 多任務配置文件,有 Ansible 自動執行;

  • Host Inventory: 定義 Ansible 管理主機的清單,ansible只能管理Inventory中定義的主機

使用Paramiko,PyYAML和Jinja2三個Python的核心庫實現 
部署簡單:agentless; 
支持自定義模塊,使用任意語言編寫

問題:不同環境的目標系統如何對相同服務定制不同配置 
如讓httpd偵聽在不同的端口之上。

安裝ansible

解決依賴關系

1.yum -y install python-jinja2 PyYAML python-paramiko python-babel python-crypto

ansible程序包被Fedora-epel所收入,因此安裝前需配置好epel倉庫的yum源;

1.yum install ansible

使用ansible前提條件

ansible基于SSH連接至host,因此有必要讓ansible通過ssh-key連接主機。為了避免Ansible下發指令時輸入目標主機密碼,通過證書簽名達到SSH無密碼是一個好的方案,推薦使用ssh-keygen與ssh- copy-id來實現快速證書的生成和公鑰下發,其中ssh-keygen生成一對密鑰,使用ssh-copy-id來下發生成的公鑰。具體操作如下:

  • 生成 SSH公玥和私鑰文件 
    ssh-kengen -t rsa -P ' '

  • 拷貝公玥文件到目標主機的ssh認證文件中 
    ssh-copy-id -i ~/.ssh/id_rsa.pub root@HostIP

  • 連接測試 
    ssh root@HostIP

注意: 如果不配置主機免密鑰登錄,可以在/etc/ansible/hosts中定義用戶和密碼,主機ip地址,和ssh端口,這樣也可以進行免密碼訪問,但是這個/hosts文件要保護好。

主要文件

程序:/usr/bin/ansible/usr/bin/ansible-playbook/usr/bin/ansible-doc 
配置文件:/etc/ansible/ansible.cfg 
主機清單:/etc/ansible/hosts 
插件目錄:/usr/share/ansible_plugins

配置文件

Host Inventory

Inventory是一個簡單的從外部資源尋找主機,主機組的成員,和變量信息的程序 – 可以是個 SQL 數據庫,一個 CMDB 解決方案,或者是 LDAP。這個概念來自 Puppet (叫”External Nodes Classifier”),工作方式也是類似的。

Ansible 通過讀取默認的主機清單配置/etc/ansible/hosts,可以同時連接到多個遠程主機上執行任務,默認路徑可以通過修改 ansible.cfg 的 hostfile 參數指定路徑。

在主機清單文件中定義host組,便于執行命令時指定在哪些主機使用,也可在palybook文件調用這些定義好的主機名稱。

1.[dbserver]  []表示主機的分組名,可以按照功能,系統進行分類,便于進行操作
2.192.168.10.2
3.one.example.com
4.www.bds.com:5309         #支持指定ssh端口5309
5.jumper ansible_ssh_port=5309 ansible_ssh_host=192.168.10.2   #設置主機別名為jumper
6.www[01:50].bds.com       #支持通配符匹配www01.bds.com www02.bds.com
7.[web]                    #提醒下這里面字母是隨便定義的
8.web-[a:f].bds.com        #支持字母匹配 web-a.bds.com ..web-f.bds.com
9.
10.# 為主機指定類型和連接用戶
11.[bds]
12.Localhost  ansible_connection=local
13.other1.example.com ansible_connection=ssh ansible_ssh_user=deploy
14.other2.example.com ansible_connection=ssh ansible_ssh_user=deploy
15.ansible hosts配置文件中支持指令等

1, ansible_ssh_host : 
指定主機別名對應的真實 IP,如:100 ansible_ssh_host=192.168.1.100,隨后連接該主機無須指定完整 IP,只需指定 100 即可 
2, ansible_ssh_port : 
指定連接到這個主機的 ssh 端口,默認 22 
3, ansible_ssh_user: 
連接到該主機的 ssh 用戶 
4, ansible_ssh_pass: 
連接到該主機的 ssh 密碼(連-k 選項都省了),安全考慮還是建議使用私鑰或在命令行指定-k 選項輸入 
5, ansible_sudo_pass: sudo 密碼 
6, ansible_sudo_exe: sudo 命令路徑 
7, ansible_connection : 
連接類型,可以是 local、ssh 或 paramiko,ansible1.2 之前默認為 paramiko 
8, ansible_ssh_private_key_file : 私鑰文件路徑 
9, ansible_shell_type : 
目標系統的 shell 類型,默認為 sh,如果設置 csh/fish,那么命令需要遵循它們語法 
10, ansible_python_interpreter : 
python 解釋器路徑,默認是/usr/bin/python,但是如要要連BSD系統的話,就需要該指令修改 python 路徑 
11, ansible__interpreter : 
這里的”*”可以是 ruby 或 perl 或其他語言的解釋器,作用和 ansible_python_interpreter 類似

ansible.cfg

默認的forks=5,即一次fork 5個ansible進程與目標主機通信,fact緩存路徑等 
如:

1.[defaults]
2.gathering = smart
3.fact_caching = redis
4.fact_caching_timeout = 86400
5.# seconds

命令使用

ansible

1.ansible <host-pattern> [-f forks] [-m module_name] [-a "args"]
2.    -m MODULE_NAME # 默認為command,可省略
3.
   -a MODULE_ARGS, --args=MODULE_ARGS # 除了shell和command以為的模塊都有內置的Args
4.
   -k,-ask-pass # 提示輸入ssh的密碼,而不是使用基于ssh的密鑰認證
5.
   -sudo # 指定使用sudo獲得root權限
6.
   -K,-ask-sudo-pass # 提示輸入sudo密碼,與–sudo一起使用
7.
   -C,-check # 測試此命令執行會改變什么內容,不會真正的去執行

ansible-doc

Show Ansible module documentation

1.ansible-doc -h
2.ansible-doc -l # List available modules
3.ansible-doc -s module_name # Show playbook snippet for specified module(s)

ansible-playbook

1.ansible-playbook [options] <filename.yml>
2.
3.#tags指定與查看
4.     --list-tags
5.
    -t, TAGS_NAME, --tags=TAGS
6.
    --skip-tags=SKIP_TAGS
7.
    --start-at-task=START_AT
8.

9.#測試執行    
10.     --list-hosts # 受影響的host
11.
    --list-tasks # 會執行的tasks
12.

13.#傳遞變量
14.     -e VARNAME=VALUE, --extra-vars=VARS #內部預制變量可被-e覆蓋
15.

16.#額外的主機清單、fork進程數    
17.     -i PATH, --inventory=PATH
18.
    -f NUM, --forks=NUM
19.

20.#檢查語法,模擬執行  
21.     --syntax-check # perform a syntax check on the playbook
22.
    -C, --check # don't make any changes; instead, try to predict some of the changes that may occur

常用模塊

  1. ping:探測目標主機是否存活;

  2. command:在遠程主機執行命令;默認的module 
    ansible all -m command -a "hostname "

  3. shell:在遠程主機上調用shell解釋器運行命令,支持shell的各種功能,例如管道等 ; 
    ansible all -m shell -a "cat /etc/passwd| grep root " 
    注意:command和shell模塊的核心參數直接為命令本身;而其它模塊的參數通常為“key=action”格式;

  4. copy: C o p i e s f i l e s t o r e m o t e l o c a t i o n s . 
    用法: 
    (1) 復制文件:-a “src= dest= ” 
    (2) 給定內容生成文件:-a “content= dest= ” 
    其它參數:mode, owner, group, …

  5. file:S e t s a t t r i b u t e s o f f i l e s 
    用法: 
    (1) 創建目錄:-a “path= state=directory” 
    (2) 創建鏈接文件:-a “path= src= state=link” 
    (3) 刪除文件:-a “path= state=absent“

  6. fetch:F e t c h e s a f i l e f r o m r e m o t e n o d e s

  7. cron:M a n a g e c r o n . d a n d c r o n t a b e n t r i e s . 
    -a ” ” 
    minute= 
    hour= 
    day= 
    month= 
    weekday= 
    job= 
    name= 
    user= 
    state={present|absent}

  8. hostname:M a n a g e h o s t n a m e 
    name=

  9. yum:M a n a g e s p a c k a g e s w i t h t h e I ( y u m ) p a c k a g e m a n a g e r 
    (1) name= state={present|latest} 
    (2) name= state=absent

  10. service:M a n a g e s e r v i c e s . 
    name= 
    state={started|restarted|stoped|reloaded} 
    started 
    stopped 
    restarted 
    enabled= 
    runlevel=

  11. group: A d d o r r e m o v e g r o u p s 
    name= 
    state= 
    system= 
    gid= 
    state={present|absent} 
    ansible db -m group -a 'name=test gid=1000'

  12. user:M a n a g e u s e r a c c o u n t s 
    name= 
    group= 
    groups= 
    comment= 
    uid= 
    system= 
    shell= 
    expires= 
    home= 
    state={present|absent} 
    ansible all -m user -a 'name=DBA uid=505 home=/Data/dba shell=/sbin/nologin' 
    ansible db -m user -a 'name=budongshu uid=506 state=absent'

  13. setup:G a t h e r s f a c t s a b o u t r e m o t e h o s t s 
    收集系統信息,作為可用的變量: 
    “device”: “eno16777736” 
    “address”: “10.1.22.106” 
    “ansible_distribution”: “CentOS” 
    “ansible_distribution_major_version”: “7” 
    “ansible_fqdn”: “localhost.localdomain”, 
    “ansible_hostname”: “cent6”, 
    “ansible_interfaces”: [ 
    “lo”, 
    “eth1”, 
    “eth0” 
    ], 
    …… 
    結構體類型的fact引用: 
    {{ ansible_eth0.ipv4.address }} 
    {{ ansible_eth0[“ipv4”][“address”] }} 
    {{ ansible_all_ipv4_addresses[0] }}

  14. template 
    template使用了Jinjia2格式作為文件模板,進行文檔內變量的替換的模塊。他的每次使用都會被ansible標記為changed狀態。

  15. script:自動復制腳本到遠程節點,并運行 
    ansible all -m script -a 'ansible_test.sh'

ansible各模塊簡單示例

1.ansible websrv -m ping
2.ansible all -m command -a "ifconfig"
3.ansible all -m shell -a "echo alice|passwd --stdin alice"
4.ansible all -m copy -a "content='hello\n1' dest=/tmp/test.ansible mode=640"
5.
6.ansible all -m file -a "path=/tmp/test.ansible mode=777"
7.ansible all -m file -a "path=/tmp/test.ansible state=absent"
8.ansible all -m file -a "path=/tmp/testdir state=directory"
9.ansible all -m file -a "path=/tmp/test.ansible.link src=/tmp/test.ansible state=link"
10.
11.ansible all -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 10.1.0.1 &> /dev/null' name=ntptime"
12.ansible all -m cron -a "name=ntptime state=absent"
13.
14.ansible all 10.1.0.68 -m setup
15.
16.ansible websrv -m yum -a "name=httpd state=present"
17.
18.ansible websrv -m service -a "name=httpd state=started enabled=true"

ansible playbooks

playbook是由一個或多個“play”組成的列表。play的主要功能在于將事先歸并為一組的主機裝扮成事先通過ansible中的task定義好的角色。從根本上來講,所謂task無非是調用ansible的一個module。將多個play組織在一個playbook中,即可以讓它們聯同起來按事先編排的任務一項一項執行,一項task可能指定了多個host,且默認并行執行5個fork進程。

playbook內容組成

  • 核心元素: 

    1. tasks:任務,有模塊定義的操作列表

    2. vas:變量

    3. tempaltes:模板,使用了Jinjia2格式作為文件模板

    4. handlers:由特定條件觸發的Tasks;

    5. roles:角色

  • 基本組件 

    1. Hosts:指定目標主機

    2. remote_user:在遠程主機上以哪個用戶身份執行; 
      sudo_user:非管理員需要用于sudo權限

    3. tasks:任務列表 
      模塊:模塊參數 
      格式: 
      (1)action: module arguments 
      如: name、tags、with_items、notify、when、…… 
      (2)module: arguments 
      如: yum、copy、template、service、command、shell、……

host、user

playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執行任務。hosts用于指定要執行指定任務的主機,其可以是一個或多個由冒號分隔主機組;remote_user則用于指定遠程主機上的執行任務的用戶,如

1.- hosts: webnodes
2.
   remote_user: root

remote_user也可用于各task中。也可以通過指定其通過sudo的方式在遠程主機上執行任務,其可用于play全局或某任務;此外,甚至可以在sudo時使用sudo_user指定sudo時切換的用戶。

1.- hosts: webnodes
2.
 remote_user: root
3.  tasks:
4.    - name: test connection
5.
     ping:
6.      remote_user: alice
7.      sudo: yes

vars

和 Facts 相反, 變量是一些值,或字典,列表的名稱(可以是標量值–整數,布爾型,或字符串,字典,列表),然后變量可以應用在模板和劇本里面。他們是聲明的東西,不是獲取遠程系統的當前狀態或性質(這是Facts)

(1) 內置的facts變量通過 setup 模塊獲??; 
(2) 自定義變量:

  1. 命令行傳遞;

1.ansible-playbook -e VAR=VALUE playbook.yml
  1. Inventory還可以使用參數: 
    用于定義ansible遠程連接目標主機時使用的屬性,而非傳遞給playbook的變量;

1.    ansible_ssh_host
2.    ansible_ssh_port
3.    ansible_ssh_user
4.    ansible_ssh_pass
5.    ansible_sudo_pass
6.    ...
  1. 在playbook中定義變量

1. - hosts: webservers
2.    vars:
3.    http_port: 80
  1. 在hosts Inventory中為每個主機定義專用變量值; 
    (a) 向不同的主機傳遞不同的變量 ; 
    IP/HOSTNAME variable_name=value 
    (b) 向組內的所有主機傳遞相同的變量 ; 
    [groupname:vars] 
    variable_name=value

  2. 在角色調用時傳遞

1.roles:
2.- { role: ROLE_NAME, var: value, ...}
  • 調用方式: 
    {{ var_name }}

  • 結構體類型的fact變量引用: 
    {{ ansible_eth0.ipv4.address }} 
    {{ ansible_eth0[“ipv4”][“address”] }} 
    {{ ansible_all_ipv4_addresses[0] }}

  • 變量優先級總結: 
    命令行傳遞的外部變量優先級高;vars定義的變量優先級大于host Iventroy傳遞的變量,具體如下: 

    1. extra vars (在命令行中使用 -e)優先級最高

    2. 然后是在inventory中定義的連接變量(比如ansible_ssh_user)

    3. 接著是大多數的其它變量(命令行轉換,play中的變量,included的變量,role中的變量等)

    4. 然后是在inventory定義的其它變量

    5. 然后是由系統發現的facts

    6. 然后是 “role默認變量”, 這個是最默認的值,很容易喪失優先權

命令行傳遞變量

1.- hosts: websrv
2.   remote_user: root
3.   tasks:
4.   - name: install rpm
5.   yum: name={{ rpmName }} state=
6.
7.ansible-playbook -C -e rpmName=vsftpd web.yml

playbook文件定義變量

1.- hosts: websrv
2.   remote_user: root
3.   vars:
4.   - rpmName=memcached
5.   - rpmName=mysql
6.   tasks:
7.   - name: install rpm
8.   yum: name={{ rpmName }}

hosts Inventory傳遞變量

1.[websrv]
2.10.1.0.6 rpmName=httpd
3.10.1.0.7 rpmName=nginx

Inventory組共用變量

1.[websrv]
2.10.1.0.6 rpmName=httpd
3.10.1.0.7 rpmName=nginx
4.
5.[websrv:vars]
6.rpmName=nginx

用于定義ansible遠程連接目標主機時使用的屬性,而非傳遞給playbook的變量

1.[websrv]
2.10.1.0.6 ansible_ssh_user= ansible_ssh_pass= ansible_sudo_pass=
3.10.1.0.7 rpmName=nginx

調用role時傳遞變量

1.roles:
2.   - { role: apache, http_port: 8080 }
3.   - { role: app_user, name: Terry  }
4.   - { role: app_user, name: John   }

handlers

用于當關注的資源發生變化時采取一定的操作?!皀otify”這個action可用于在每個play的最后被觸發,這樣可以避免多次有改變發生時每次都執行指定的操作,取而代之,僅在所有的變化發生完成后一次性地執行指定操作。在notify中列出的操作稱為handler,也即notify中調用handler中定義的操作。這意味著服務可以被反彈僅僅他們需要重啟的時候。Handler 不僅僅可以用于重啟服務,但是重啟服務是最通用的用法。

1.- name: template configuration file
2.          template: src=template.j2 dest=/etc/foo.conf
3.          notify:
4.             - restart memcached
5.             - restart apache  
6.
7.#handler是task列表,這些task與前述的task并沒有本質上的不同。
8.        handlers:
9.            - name: restart memcached
10.              service:  name=memcached state=restarted
11.            - name: restart apache
12.              service: name=apache state=restarted

tasks

play的主體部分是task list。task list中的各任務按次序逐個在hosts中指定的所有主機上執行,即在所有主機上完成第一個任務后再開始第二個。在運行自下而下某playbook時,如果中途發生錯誤,所有已執行任務都將回滾,因此,在更正playbook后重新執行一次即可。

task的目的是使用指定的參數執行模塊,而在模塊參數中可以使用變量。模塊執行是冪等的,這意味著多次執行是安全的,因為其結果均一致。

每個task都應該有其name,用于playbook的執行結果輸出,建議其內容盡可能清晰地描述任務執行步驟。如果未提供name,則action的結果將用于輸出。

Tags

Ansible 允許給playbook里面的資源通過自定義的關鍵字打上標簽,然后只運行與關鍵字一致的部分代碼。 例如,可能有個完成的 OS 配置,然后特定的步驟標記為 “ntp” ,然后運行 “ntp” 步驟來重新配置時間服務器信息。

1.tasks: 
2.    tags: ntp

template

Ansible 很容易的傳輸文件到遠端系統上面,但是它經常需要替換一些變量在其它的文件里面。變量可以來自 清單文件,Host Vars, Group Vars,或者 Facts。Templates 使用 Jinja2 模板引擎同樣可以包含邏輯控制像循環和 if 語句。

Jinja2 is a template engine written in pure Python. It provides a Django inspired non-XML syntax but supports inline expressions and an optional sandboxed environment.

Jinja2語法介紹:

  • 字面量: 
    字符串:使用單引號或雙引號; 
    數字:整數、浮點數; 
    列表:[item1, item2, …] 
    元組:(item1, item2, …) 
    字典:{key1:value1, key2:value2, …} 
    布爾型:true/false

  • 算術運算: 
    +, -, , /, //, %, *

  • 比較操作: 
    ==, !=, >, <, >=, <=

  • 邏輯運算:and, or, not

執行模板文件中的腳本,并生成結果數據流,需要使用template模塊;

1.template:
2.        src=
3.        dest=
4.        mode=
5.        onwer=
6.        group=

此外,template模塊只能在playbook文件中使用,不能在命令行調用 
【nothing】ansible websrvs -m copy -a “src=/root/nginx.conf dest=/tmp/nginx.conf” 
【error】ansible websrvs -m template -a “src=/root/nginx.conf dest=/tmp/nginx.conf”

例:在nginx配置文件中使用模板變量

1.- hosts: wevsrv
2.   remote_user: root
3.   tasks:
4.    - name: install rpm
5.       yum: name=nginx state=latest
6.       template: src=/root/nginx.conf.j2 dest=/etc/nginx/nginx.conf
7.       tags: newconf
8.       notify: reload nginx
9.    - name: start nginx
10.       service: name=nginx state=started enabled=true
11.    handlers:
12.    - name: relaod nginx
13.       shell: /usr/sbin/nginx
-s reload
14.
15.vi nginx.conf
16.    worker_processes {{ ansible_process_vcpus }}

when條件測試

一個可選的關鍵字來決定這個任務是不是應該指向,如果再 “when:” 關鍵字這里的表達式是是不正確的,這個任務會被忽略。When語句包含Jinja2表達式。

1.tasks:
2.    - name:
3.      when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6"
4.
5.tasks:
6.    - command: echo {{ item }}
7.      with_items: [ 0, 2, 4, 6, 8, 10 ]
8.      when: item > 5
9.
10.roles:
11.  - { role: amp, DBName: mysql, DBService: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }

item循環

需要重復執行的任務,如同時安裝一組程序或者重復一個輪詢步驟直到收到某個特定結果。 
對迭代項的引用,固定變量名為”item”,使用with_item屬性給定所有的元素列表:

  • 元素列表:字符串,字典

(1)基于字符串的循環列表(行值)

1.  - hosts: wevsrv
2.
   remote_user: root
3.    tasks:
4.    - name: install rpm
5.
     yum: name={{ item }} state=latest
6.      with_items:
7.      - httpd
8.
     - php
9.
     - php-mysql
10.
     - php-mbstring
11.
     - php-gd
12.
     - mysql-server
13.
     - mysql

(2) 基于字典的循環列表 
相當于給同一個action設定不同的值(列值)

1.  - hosts: all
2.    remote_user: root
3.    tasks:
4.    - name: create groups
5.      yum: name={{ item }} state=present
6.      with_items:
7.      - ops1
8.      - ops2
9.    - name: create users
10.      user: name={{ item.name }} group={{ item.group }} state=present
11.      with_items:
12.      - { name: 'h1', group: 'ops1' }
13.      - { name: 'h2', group: 'ops2' }

PyYAML庫

YAML is a data serialization format designed for human readability and interaction with scripting languages.

YAML是一個可讀性高的用來表達資料序列的格式。YAML參考了其他多種語言,包括:XML、C語言、Python、Perl以及電子郵件格式RFC2822等。Clark Evans在2001年在首次發表了這種語言,另外Ingy d?t Net與Oren Ben-Kiki也是這語言的共同設計者。

YAML Ain’t Markup Language,即YAML不是XML。不過,在開發的這種語言時,YAML的意思其實是:”Yet Another Markup Language”(仍是一種標記語言)。其特性有:

YAML的可讀性好 
YAML和腳本語言的交互性好 
YAML使用實現語言的數據類型 
YAML有一個一致的信息模型 
YAML易于實現 
YAML可以基于流來處理 
YAML表達能力強,擴展性好

更多的內容及規范參見:http://www.yaml.org

YAML語法

YAML的語法和其他高階語言類似,并且可以簡單表達清單、散列表、標量等數據結構。其結構(Structure)通過空格來展示,序列(Sequence)里的項用”-“來代表,Map里的鍵值對用”:”分隔。下面是一個示例:

1.  - hosts: 
2.
   remote_user:root
3.    vars:
4.     var_name: value
5.     http_port: 80
6.     max_clients: 256
7.     ……
8.    tasks:
9.    - name: ensure apache is at the latest version
10.
     yum: name=httpd state=latest
11.      tags: tag_name
12.      notify: handler_name
13.    - name:
14.
     ……
15.    handlers:
16.    - name: handler_name
17.
     MODULE

playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的用戶身份執行任務。hosts用于指定要執行指定任務的主機,其可以是一個或多個由冒號分隔主機組;remote_user則用于指定遠程主機上的執行任務的用戶。

YAML文件擴展名通常為.yaml,如example.yaml或main.yml;

YAML坑

YAML語法要求如果值以{{ foo }}開頭的話我們需要將整行用雙引號包起來. 
錯誤:

1.- hosts: app_servers
2.  vars:
3.      app_path: {{ base_path }}/22

正確:

1.- hosts: app_servers
2.  vars:
3.       app_path: "{{ base_path }}/22"

palybook文件示例

(1)增加用戶并指定組

1.vi addgrp.yml
2.- hosts:websrv
3.  remote_user:root
4.  tasks:
5.  - name: create group ops
6.    group: name=ops system=true
7.  - name: create user alice
8.    user: name=alice group=ops system

(2)安裝httpd程序

1.vi httpd.yml
2.- hosts: websrv
3.
 remote_user: root
4.  tasks:
5.  - name: install httpd.
6.
   yum: name=httpd
7.  - name: conf
8.
   copy: src=./src/httpd.conf dest=/etc/httpd/conf/httpd.conf
9.    tages: newconf
10.    notify: restart httpd..
11.  - name: start
12.
   service: name=httpd state=started  
13.  handlers:
14.  - name: restart httpd..
15.
   service: name=httpd state=restarted
16.  handlers:
17.  - name: reload httpd..
18.
   shell: /usr/sbin/service httpd reload

roles

一個 Role 可以包含特定的變量值,特定的任務,特定的觸發器等東西。因為 Role 的文件結構,roles 可以是再次利用的單元,可以讓你在其它 playbooks 中共享一些行為。

一個完整的role以特定的層級目錄結構進行組織的tasks、variables、handlers、templates、files等;
role_struct: 
files/:存放有copy或script等模塊調用的文件; 
tasks/:至少有一個main.yml用于定義主task,其他文件應被main.yml包含調用; 
handlers/:至少有一個main.yml用于定義主handler,其他文件應被main.yml包含調用; 
templates/:存放有template模塊調用的模板文件; 
meta/:至少有一個main.yml用于定義當前role的特殊設定及依賴關系,其他文件應被main.yml包含調用 
default/:至少有一個main.yml用于定義默認的變量;

簡單的role示例

  • 創建roles目錄結構 
    mkdri -p /etc/ansible/roles/{nginx,mysql,httpd}/{files,tasks,handlers,vars,templates,meta,default}

  • 編輯任務文件:vi /nginx/tasks/main.yml

1.- name: copy nginx
2.   copy: src=nginx-1.10   dest=/tmp/
3.- name: install nginx
4.   yum: name=/tmp/nginx-1.10
5.- name: install conf file
6.  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
7.  tags: newconf
8.  notify: reload nginx
9.- name: install conf file
10.  template: src=default.conf.j2 dest=/etc/nginx/conf.d/default.conf
11.  tags: newconf
12.  notify: reload nginx
13.- name: start nginx
14.  service: name=nginx state=started

  • 編輯關聯任務:vi /nginx/handlers/main.yml

1.- name: reload nginx
2.    shell: nginx -s reload
  • 編輯playbook變量:vi vars/main.yml

1.nginxport: "8080"
  • 編輯模板文件:vi nginx.conf.j2 default.conf.j2 
    cp /etc/nginx/nginx.conf roles/nginx/templates/nginx.conf.j2 
    cp /etc/nginx/conf.d/default.conf roles/nginx/templates/default.conf.j2

1.worker_processes  {{ ansible_processor_vcpus }};
2.listen       {{ ngxport }};
  • 編輯role調用文件:vi palynginx.yml

1.- hosts: websrv
2.
 remote_user: root
3.  roles:
4.  - { playnginx, var_name:value,…… }
5.
 - memcache
  • 檢查整個role語法、測試執行 
    ansible-playbook --syntax-check playnginx.yml 
    ansible-playbook -C playnginx.yml

  • 調用執行playbook文件 
    ansible-playbook playnginx.yml

總結

    ansible作為運維工具中遠程命令執行工具,能夠實現:批量部署應用程序、系統配置、批量命令執行等功能,是一款較輕量化的Python程序。ansible經過不斷的發展,具有模塊化、部署簡單、工作于agentless模式、使用ssh協議、支持自定義模塊、支持Palybook等特點。 
    Playbooks 可用于收集主機配置信息,更強大的地方在于 playbooks 中可以編排有序的任務執行過程,甚至于做到在多組機器間來回有序的執行指定步驟任務,且可以同步或異步的發起任務。

更多信息:http://www.ansible.com.cn/docs/

ansible部署{keepalived+nginx+{httpd, mysql, php}}

架構圖.jpg

ansible部署AMP環境

同時兼容CentOS 6 與Cent OS 7系統

目錄結構

1./etc/ansible/roles/lamp/
2.├── default
3.├── files
4.├── handlers
5.│   └── main.yml
6.├── meta
7.├── tasks
8.│   └── main.yml
9.├── templates
10.│   ├── httpd-2.2.conf.j2
11.│   └── httpd-2.4.conf.j2
12.└── vars
13.    └── main.yml

tasks/main.yml

  1. 使用yum模塊安裝httpd、php、php-mysql

  2. 根據DBName變量安裝mysql程序

  3. 根據HttpConf變量并使用模板向httpd.conf文件傳遞變量,同時觸發重載httpd服務

  4. 啟動httpd服務(省略php.ini文件的復制)

  5. 根據DBService變量啟動mysql服務

  6. 根據fact變量定制每臺web服務器的index.html

  7. 創建測試數據庫,授權LocalIP變量,即ansible主機的變量

1.- name: install httpd php
2.  yum: name={{ item }} state=present
3.  with_items:
4.  - httpd
5.  - php
6.  - php-mysql
7.- name: install mysql
8.  yum: name={{ DBName }}-server state=present
9.- name: copy httpd.conf
10.  template: src={{ HttpConf }} dest=/etc/httpd/conf/httpd.conf
11.  tags: NewHttpConf
12.  notify: reload httpd
13.- name: start httpd
14.  command: /usr/sbin/apachectl start
15.- name: start mysql
16.  service: name={{ DBService }} state=started
27.- name: create index.html
28.  copy: content='<h1> Web Servers in {{ ansible_hostname }}, Host IP is {{ ansible_all_ipv4_addresses[0] }}, System Version is {{ ansible_distribution }} {{ ansible_distribution_version }} </h1>' dest=/var/www/html/index.html
31.- name: create testdb
32.  command: mysql -e 'CREATE DATABASE testdb;GRANT ALL ON testdb.* TO "testuser"@"{{ LocalIP }}" IDENTIFIED BY "mage";FLUSH PRIVILEGES'

handlers/main.yml

1.- name: reload httpd
2.  service: name=httpd state=reloaded

vars/main.yml

1.htport: 80

templates/

  1. vi httpd-2.2.conf.j2

1.Listen       {{ htport }};
  1. vi httpd-2.4.conf.j2

1.Listen       {{ htport }};

host iventory

/etc/ansible/hosts

1.[websrv]
2.10.1.22.105
3.10.1.22.100
4.
5.[websrv:vars]
6.LocalIP=10.1.253.29

roles調用

ngxproxy.yml

1.- hosts: websrv
2.  remote_user: root
3.  tags: amp
4.  roles:
5.  - { role: lamp, DBName: mysql, DBService: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
6.  - { role: lamp, DBName: mariadb, DBService: mariadb, HttpConf: httpd-2.4.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
7.#  - { role: httpd, tags: start mysql, DBName: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }

play and check

執行playbook 

play.jpg

 
訪問we1和web2 

test.jpg

 
訪問測試數據庫 

TEST2.jpg

ansible部署nginx反代服務器

同時兼容 CentOS 6 與 CentOS 7 系統

目錄結構

1./etc/ansible/roles/ngxproxy/
2.├── default
3.├── files
4.│   ├── nginx-1.10.0-1.el7.ngx.x86_64.rpm
5.│   └── nginx-1.10.2-1.el6.ngx.x86_64.rpm
6.├── handlers
7.│   └── main.yml
8.├── meta
9.├── tasks
10.│   └── main.yml
11.├── templates
12.│   ├── default.conf.j2
13.│   └── nginx.conf.j2
14.└── vars
15.     └── main.yml

tasks/main.yml

  1. 根據rpmName變量復制nginx程序包到目標主機

  2. 根據rpmName安裝nginx程序包

  3. 基于模板復制nginx.conf和default.conf文件到目標主機,并觸發重載nginx服務,且已經配置好upstrem server

  4. 啟動nginx服務

1.- name: copy nginx rpm
2.  copy: src={{ rpmName }} dest=/tmp
3.- name: install nginx
4.  yum: name=/tmp/{{ rpmName }} state=present
5.  tags: copyrpm
6.  notify: remove rpm
9.
- name: install conf
10.  template: src={{ item.src }} dest={{ item.dest }}
12.
 notify: nginx reload
13.  with_items:
14.  - { src: 'nginx.conf.j2', dest: '/etc/nginx/nginx.conf' }
15.  - { src: 'default.conf.j2', dest: '/etc/nginx/conf.d/default.conf' }
16.- name: start nginx
17.  service: name=nginx state=started

handlers/main.yml

1.- name: nginx reload
2.  shell: "/usr/sbin/nginx -s reload"
3.- name: remove rpm
4.  shell: "/bin/rm /tmp/{{ rpmName }}"

vars/main.yml

1.ngxport: 80

templates/

  1. vi default.conf.j2

1.listen       {{ ngxport }};
2.location / {
3.    #root   /usr/share/nginx/html;
4.    index  index.html index.htm;
5.    proxy_pass http://websrv;
6.}

  1. vi nginx.conf.j2

1.worker_processes  {{ ansible_processor_vcpus }};
2.http{
3.    upstream websrv {
4.        server 10.1.22.105;
5.        server 10.1.22.100;
6.        }
7.}

files/

  1. nginx-1.10.0-1.el7.ngx.x86_64.rpm

  2. nginx-1.10.2-1.el6.ngx.x86_64.rpm

host iventory

/etc/ansible/hosts

1.[ngxproxy]
2.10.1.253.66 rpmName=nginx-1.10.2-1.el6.ngx.x86_64.rpm
3.10.1.22.106 rpmName=nginx-1.10.0-1.el7.ngx.x86_64.rpm

roles調用

ngxproxy.yml

1.- hosts: ngxproxy
2.
 remote_user: root
3.  tags: ngxproxy
4.  roles:
5.  - ngxproxy

play and check

執行playbook 

play.jpg

 
訪問兩臺代理服務器均能輪詢web1、web2 

test.jpg

ansible部署keepalived

同時兼容 CentOS 6 與 CentOS 7 系統,采用雙主模型的keepalived配置高可用nginx代理服務器。

目錄結構

1./etc/ansible/roles/keepalived/
2.├── default
3.├── files
4.├── handlers
5.│   └── main.yml
6.├── meta
7.├── tasks
8.│   └── main.yml
9.├── templates
10.│   ├── keepalived.conf.j2
11.│   └── notify.sh
12.└── vars

tasks/main.yml

  1. 使用yum安裝keepalivcd

  2. 基于模板復制keepalived.conf和notify.sh腳本到目標主機,并觸發重載keepalived服務,且已經配置好了雙主模型的keepalived

  3. 啟動keepalived服務

1.- name: install keepalived
2.  yum: name=keepalived state=present
3.- name: copy keepalived.conf,notify script
4.  template: src={{ item.src }} dest=/etc/keepalived/{{ item.dest }}
5.  tags: NewConf
6.  notify: reload keepalived
7.  with_items:
8.  - { src: keepalived.conf.j2, dest: keepalived.conf }
9.  - { src: notify.sh, dest: notify.sh }
10.- name: start keepalived
11.  service: name=keepalived state=started

handlers/main.yml

1.- name: reload keepalived
2.  service: name=keepalived state=reloaded

templates/

  1. vi keepalived.conf.j2

1.! Configuration File for keepalived
2.
3.global_defs {
4.   notification_email {
5.     root@localhost
6.   }
7.   notification_email_from keepalived@jasonmc.com
8.   smtp_server localhost
9.   smtp_connect_timeout 30
10.   router_id node1
11.   vrrp_mcast_group4 224.22.29.1
12.}
13.vrrp_script chk_down {
14.    script "[[ -f /etc/keepalived/down ]]&& exit 1 || exit 0"
15.    interval 1
16.    weight -5
17.}
18.vrrp_script chk_nginx {
19.    script "killall -0 nginx && exit 0 || exit 1"
20.    interval 1
21.    weight -5
22.}
23.
24.vrrp_instance VI_1 {
25.    state {{ VI_1 }}
26.    interface {{ IFACE }}
27.    virtual_router_id 10
28.    priority 96
29.    advert_int 10
30.    authentication {
31.        auth_type PASS
32.        auth_pass 1a7b2ce6
33.    }
34.    virtual_ipaddress {
35.        10.1.253.11 dev {{ IFACE }}
36.    }
37.    track_script {
38.    chk_down
39.    chk_nginx
40.    }
41.    notify_master "/etc/keepalived/notify.sh master"
42.    notify_backup "/etc/keepalived/notify.sh backup"
43.    notify_fault "/etc/keepalived/notify.sh fault"
44.}
45.
46.vrrp_instance VI_2 {
47.    state {{ VI_2 }}
48.    interface {{ IFACE }}
49.    virtual_router_id 11
50.    priority 100
51.    advert_int 11
52.    authentication {
53.        auth_type PASS
54.        auth_pass a3d1e9b0
55.    }
56.    virtual_ipaddress {
57.        10.1.253.12 dev {{ IFACE }}
58.    }
59.    track_script {
60.    chk_down
61.    chk_nginx
62.    }
63.    notify_master "/etc/keepalived/notify.sh master"
64.    notify_backup "/etc/keepalived/notify.sh backup"
65.    notify_fault "/etc/keepalived/notify.sh fault"
66.}
  1. vi notify.sh

1.#!/bin/bash
2.#
3.receiver='root@localhost'
4.notify() {
5.    mailsubject="$(hostname) to $1,vip floating."
6.    content="$(date '+%F %T') vrrp state transion, $(hostname) changed to be $1"
7.    echo "$content" | mail -s "$mailsubject" $receiver
8.}
9.case $1 in
10.    master)
11.        notify master
12.        ;;
13.    backup)
14.        notify backup
15.        ;;
16.    fault)
17.        notify fault
18.        ;;
19.    *)
20.        echo "Usage $(basename $0) {master|backup|fault}"
21.        exit 1
22.        ;;
23.esac

host iventory

/etc/ansible/hosts

1.[ngxproxy]
2.10.1.253.66
3.10.1.22.106

roles調用

ngxproxy.yml

1.- hosts: ngxproxy
2.  remote_user: root
3.  tags: ngxproxy
4.  roles:
5.  - { role: keepalived, VI_1: MASTER, VI_2: BACKUP, IFACE: eno16777736, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
6.  - { role: keepalived, VI_1: BACKUP, VI_2: MASTER, IFACE: eth0, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }

play and check

執行playbook 

play.jpg

 
訪問VIP1與VIP2均能輪詢web1、web2 

test.jpg

合并調用roles的palybook

hosts

1.[ngxproxy]
2.10.1.253.66 rpmName=nginx-1.10.2-1.el6.ngx.x86_64.rpm
3.10.1.22.106 rpmName=nginx-1.10.0-1.el7.ngx.x86_64.rpm
4.
5.[websrv]
6.10.1.22.105
7.10.1.22.100
8.
9.[websrv:vars]
10.LocalIP=10.1.253.29

keneweb.yml

1.- hosts: websrv
2.  remote_user: root
3.  tags: amp
4.  roles:
5.  - { role: lamp, DBName: mysql, DBService: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
6.  - { role: lamp, DBName: mariadb, DBService: mariadb, HttpConf: httpd-2.4.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
7.#  - { role: httpd, tags: start mysql, DBName: mysqld, HttpConf: httpd-2.2.conf.j2, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }
8.
9.- hosts: ngxproxy
10.  remote_user: root
11.  tags: ngxproxy
12.  roles:
13.  - ngxproxy
14.  - { role: keepalived, VI_1: MASTER, VI_2: BACKUP, IFACE: eno16777736, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7" }
15.  - { role: keepalived, VI_1: BACKUP, VI_2: MASTER, IFACE: eth0, when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "6" }

原創文章,作者:helloc,如若轉載,請注明出處:http://www.www58058.com/58041

(0)
hellochelloc
上一篇 2016-11-06
下一篇 2016-11-06

相關推薦

  • lvm基本應用

    前言 一種技術要知其然,還要知其所以然 lvm簡介 LVM是 Logical Volume Manager(邏輯卷管理)的簡寫,它是Linux環境下對磁盤分區進行管理的一種機制。普通的磁盤分區管理方式在邏輯分區劃分好之后就無法改變其大小,當一個邏輯分區存放不下某個文件時,這個文件因為受上層文件系統的限制,也不能跨越多個分區來存放,所以也不能同時放到別的磁盤上…

    Linux干貨 2016-05-21
  •   在服務器托管的過程中出現故障是不能完全避免的問題,可能是服務器硬盤出現硬件故障或者是防火墻遭到攻擊。那么服務器托管出現故障怎么辦?

      在服務器托管的過程中出現故障是不能完全避免的問題,可能是服務器硬盤出現硬件故障或者是防火墻遭到攻擊。那么服務器托管出現故障怎么辦?   服務器硬盤出現硬件故障時,大家應注意以下幾點:   1、硬盤出現異聲,此時磁頭已不正常尋址,為防止打傷盤體,需立即斷電不可拆解硬盤,需交有超凈間的專業公司拆開檢查。   2、BIOS不認盤,找不到硬盤,先請計算機工程師仔…

    Linux干貨 2016-04-05
  • 強大的vim編輯器

    vim編輯器 一、Vim編譯器的概述 vi: Visual Interface,文本編輯器 v 文本:ASCII, Unicode v  文本編輯種類:      行編輯器: sed      全屏編輯器:nano,   &nbs…

    Linux干貨 2016-08-12
  • shell腳本總結

    shell腳本簡要總結 腳本調試 bash -n /path/to/some_script檢測腳本中的語法錯誤 bash -x /path/to/some_script調試執行 變量 環境變量 變量聲明、賦值:export name=VALUEdeclare -x name=VALUE 變量引用:$name, ${name} 顯示所有環境變量: export…

    Linux干貨 2016-08-21
  • GPG——另一種加密信息的方式

    GPG ·使用gpg實現對稱加密 ·對稱加密file文件          gpg -c file          ls file.gpg ·在另一臺主機上解密file   &n…

    Linux干貨 2016-09-22
  • BIND 配置DNS服務器以及子域授權

    1、安裝bind      [root@www ~]# yum -y install bind 2、查看安裝生成的文件      [root@www ~]# rpm -ql bind | less 3、程序路徑     /var/named 4、配置…

    Linux干貨 2016-03-22
欧美性久久久久