Linux自學筆記——Ansible
運維工作:系統安裝(物理機、虛擬機器)à 程式包安裝、配置、服務啟動 à 批量操作 à 程式釋出 à 監控
OS Provisioning:
物理機:PXE、Cobbler
虛擬機器:Image Templates
Configuration:
Puppet(ruby)
Saltstack(python)
Chef
Cfengine
Command and Control:
Fabric
預釋出驗證:
新版本的程式碼先發布到伺服器(跟線上環境配置完全相同,只是未接入到排程器)
程式釋出:
不能影響使用者體驗;
系統不能停機;
不能導致系統故障或造成系統完全不可用;
灰度釋出:
釋出路徑:
/webapp/tuangou-1.1
/webapp/tuangou
/webapp/tuangou-1.2
/webapp/tuangou是一個軟連線,本來指向/webapp/tuangou-1.1,釋出時,將/webapp/tuangou指向/webapp/tuangou-1.2,如發生錯誤,會滾到1.1.版本
在排程器上下線一批主機(maintanance) --> 關閉服務 --> 部署新版本的應用程式 --> 啟動服務 --> 在排程器上啟用這一批伺服器;
自動化灰度釋出:指令碼、釋出平臺;
運維工具的分類:
Agent:puppet,func
Agentless:ansible,fabric
Ssh
Ansible:自動化運維部署工具
Ansible的特性:
模組化,呼叫特定的模組,完成特定的任務;
基於python語言實現,由Paramiko、pyYAML和Jinjia2三個關鍵模組;
部署簡單,agentless;
主從模式;
支援自定義模組;
支援playbook;
冪等性;
一、 Ansible的配置使用:
ansible通過ssh實現配置管理、應用部署、任務執行等功能,因此,需要事先配置ansible端能基於金鑰認證的方式聯絡各被管理節點。
配置檔案:
/etc/ansible/ansible.cfg 核心配置
/etc/ansible/hosts 主機清單
/usr/share/ansible_plugins/
程式:
ansible
ansible-doc 可以獲取幫助文件
ansible-playbook 劇本
基本用法:
Ansible <host-pattern> [-f forks] [-m module_name] [-a args]
args:
key-value
Note:command模組要執行命令無須為key=value格式,而是直接給出要執行的命令即可;
常用模組:
command
-a ‘COMMAND’
user
-a ‘name= state={present|absent} system= uid= ’
group
-a ‘name= gid= state= system= ’
cron
-a ‘name= minute= hour= day= month= weekday= job= user= state= ’
copy
-a ‘dest= src= mode= owner= group= ’
file
-a ‘path= mode= owner= group= state={directory|link|touch|absent|…} src= ’
ping
沒有引數
yum
-a ‘name state={present|latest|absent}’
service
-a ‘name= state={started|stopped|restarted} enabled=’
shell
-a ‘COMMAND’
script
-a ‘/path/to/script’
setup
用法演示:
環境:四臺虛擬機器,兩臺centos7,兩臺centos6,其中一臺centos7作為管理節點,另外三臺作為被管理端。
管理端:192.168.19.203(centos7)
被管理端:192.168.19.200(centos7),192.168.19.143(centos6),192.168.19.144(centos6)
1. 配置基於金鑰認證連線被管控主機;(安全)
管理端:
在主機中hosts檔案中新增對映:
在管理端測試:
2. 對ansible配置檔案備份,並編輯配置主機清單(/etc/ansible/hosts);
3. 可以獲取使用幫助;
基於以上環境,以下將對ansible的模組用法進行一一演示:
1. command模組
1) 獲取所有主機的ip地址:
2) 給webserver組的兩臺主機新增一個centos使用者,並其新增密碼也為centos;
驗證:可以發現密碼新增失敗;
Note:command命令不支援管道傳輸,所以可以用shell模組通過管道傳輸;
2. shell模組
1) 給上面建立的centos使用者設定密碼為centos(通過管道方式)
2) 驗證:密碼新增成功
3. user模組
1) 用user模組為所有主機建立redhat使用者;
2) 也可以刪除使用者;
4. group模組
5. cron模組:管理週期性任務
1) 建立自定義任務,每個五分鐘向控制主機同步一下時間;
2) 測試遠端主機檢視;
6. copy模組
1) 複製管控主機上的/etc/fstab檔案到被控主機的/tmp目錄下,檔名為fstab.ansible
2) 測試;
7. file模組
1) 改變檔案屬性;
2) 建立檔案;
3) 建立連結檔案;
測試:
4) 建立目錄檔案;
8. ping模組
9. yum模組
1) 為webserver主機安裝nginx:
2) 解除安裝nginx
10. service模組
開啟webserver上的nginx服務;
11. script模組
12. setup
二、 YAML
1. YAML介紹
YAML是一個可讀性高的用來表達資料序列的格式。YAML參考了其它多種語言,包括:XML、c語言、Python、Perl以及電子郵件格式RFC2822等。
YAML Ain't Markup Language,即YAML不是XML。不過,在開發的這種語言時,YAML的意思其實是:"Yet Another Markup Language"(仍是一種標記語言)。其特性:
YAML可讀性好;
YAML和指令碼語言的互動性好;
YAML使用實現語言的資料型別
YAML有一個一致的資訊模型
YAML易於實現;
YAML可以基於流來處理;
YAML表達能力強,擴充套件性好;
2. 語法
YAML的語法和其他高階語言類似,並且可以簡單表達清單、散列表、標量等資料結構。其結構(Structure)通過空格來展示,序列(Sequence)裡的項用"-"來代表,Map裡的鍵值對用":"分隔。下面是一個示例。
name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age 13
gender: Female
YAML副檔名通常為.yaml,如example.yaml。
1) list
列表的所有元素均使用“-”開頭,例如:
#A list of tasty fruits
- Apple
- Orange
- Strawberry
- Mango
2) directory
字典通過key與vale進行標識,例如:
# An employee record
name:Example Developer
job:Develper
skill:Elite
也可以將key:value放置於{}中進行表示,例如:
# An employee record
{name: Example Developer, job: Developer, skill: Elite}
三、 ansible基礎元素
1. 變數
1) 變數命名
變數名僅能由字母、數字和下劃線組成,且只能以字母開頭。
2) facts
facts是由正在通訊的遠端目標主機發回的資訊,這些資訊被儲存在ansible變數中。要獲取指定的遠端主機所支援的所有facts,可使用如下命令進行:
#ansible HOSTNAME -m setup
3) register
把任務的輸出定義為變數,然後用於其他任務,示例如下:
tasks:
- shell: /usr/bin/foo
register: foo_result
ignore_errors: True
4) 通過命令列傳遞變數
在執行playbook的時候也可以傳遞一些變數供playbook使用,示例如下:
ansible-playbook test.yaml --extra-vars=“hosts=www user=claude”
ansible-playbook test.yaml -e “hosts=www user=claude”
5) 通過roles傳遞變數
當給一個主機應用角色的時候可以傳遞變數,然後在角色內使用這些變數,示例如下:
- hosts: webservers
roles:
- common
- { role: foo_app_instance, dir: '/web/htdocs/a.com', port: 8080 }
2. Incentory
Ansible的主要功能在於批量主機操作,為了編輯地使用其中的部分主機,可以在inventory file中將其分組命名。預設的inventory file為/etc/ansible/hosts
Inventory file可以有多個,且也可以通過Dynamic Inventory來動態生成。
1) Inventory檔案格式
Inventory檔案遵循INI檔案風格,中括號中的字元為組名。可以將同一個主機同時歸併到多個不同的組中;此外,當如若目標主機使用了非預設的SSH埠,還可以在主機名稱之後使用冒號加埠號來標明。
ntp.magedu.com
[webservers]
www1.magedu.com:2222
www2.magedu.com
[dbservers]
db1.magedu.com
db2.magedu.com
db3.magedu.com
如果主機名稱遵循相似的命名模式,還可以使用列表的方式標識各主機,例如:
[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com
2) 主機變數
可以在inventory中定義主機時為其新增築基變數以便於在playbook中使用。例如:
[webservers]
www1.magedu.com http_port=80 maxRequestsPerChild=808
www2.magedu.com http_port=8080 maxRequestsPerChild=909
3) 組變數
組變數是指賦予給指定組內所有主機上的playbook中可用的變數。例如:
[webservers]
www1.magedu.com
www2.magedu.com
[webservers:vars]
ntp_server=ntp.magedu.com
nfs_server=nfs.magedu.com
4) 組巢狀
在inventory中,組還可以包含其他的組,並且也可以向組中的主機指定變數。不過,這些變數只能在ansible-playbook中使用,而ansible不支援。例如:
[apache]
httpd1.magedu.com
httpd2.magedu.com
[nginx]
ngx1.magedu.com
ngx2.magedu.com
[webservers:children]
apache
nginx
[webservers:vars]
ntp_server=ntp.magedu.com
5) Inventory引數
Ansible基於ssh連線inventory中指定的遠端主機時,還可以通過引數指定其互動方式;這些引數如下所示:
ansible_ssh_host
The name of the host to connect to, if different from the alias you wish to give to it.
ansible_ssh_port
The ssh port number, if not 22
ansible_ssh_user
The default ssh user name to use.
ansible_ssh_pass
The ssh password to use (this is insecure, we strongly recommend using --ask-pass or SSH keys)
ansible_sudo_pass
The sudo password to use (this is insecure, we strongly recommend using --ask-sudo-pass)
ansible_connection
Connection type of the host. Candidates are local, ssh or paramiko. The default is paramiko before Ansible 1.2, and 'smart' afterwards which detects whether usage of 'ssh' would be feasible based on whether ControlPersist is supported.
ansible_ssh_private_key_file
Private key file used by ssh. Useful if using multiple keys and you don't want to use SSH agent.
ansible_shell_type
The shell type of the target system. By default commands are formatted using 'sh'-style syntax by default. Setting this to 'csh' or 'fish' will cause commands executed on target systems to follow those shell's syntax instead.
ansible_python_interpreter
The target host python path. This is useful for systems with more than one Python or not located at "/usr/bin/python" such as \*BSD, or where /usr/bin/python is not a 2.X series Python. We do not use the "/usr/bin/env" mechanism as that requires the remote user's path to be set right and also assumes the "python" executable is named python, where the executable might
be named something like "python26".
ansible\_\*\_interpreter
Works for anything such as ruby or perl and works just like ansible_python_interpreter. This replaces shebang of modules which will run on that host.
3. 條件測試
如果需要根據變數、facts或此前任務的執行結果來作為某task執行與否的前提時要用到條件測試。
1) When語句
在task後新增when子句即可啟用條件測試;when語句支援Jinja2表示式語法。例如:
tasks:
- name: "shutdown Debian flavored systems"
command: /sbin/shutdown -h now
when: ansible_os_family == "Debian"
when語句中還可以使用Jinja2的大多“filter”,例如要忽略此前某語句的錯誤並基於其結果(failed或者sucess)執行後面指定的語句,可使用類似如下形式:
tasks:
- command: /bin/false
register: result
ignore_errors: True
- command: /bin/something
when: result|failed
- command: /bin/something_else
when: result|success
- command: /bin/still/something_else
when: result|skipped
此外,when語句中還可以使用facts或playbook中定義的變數。 、
4. 迭代
當有需要重複性執行任務時,可以使用迭代機制。其使用格式為將需要迭代的內容定義為item變數引用,並通過with_items語句來指明迭代的元素列表即可。例如:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
上面語句的功能等同於下面的語句:
- name: add user testuser1
user: name=testuser1 state=present groups=wheel
- name: add user testuser2
user: name=testuser2 state=present groups=wheel
事實上,with_items中可以使用元素還可為hashes,例如:
- name: add several users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1', groups: 'wheel' }
- { name: 'testuser2', groups: 'root' }
四、 ansible playbooks
playbook是由一個或多個“play”組成的列表。Play的主要功能在於將事先歸併為一組的主機裝扮成事先通過ansible中的task定義好的角色。從根本上來講,所謂task無非是呼叫ansible的一個module。將多個play組織在一個playbook中,即可以讓它們聯同起來按事先編排的機制同唱一臺大戲。下面是一個簡單示例。
- hosts: webnodes
vars:
http_port: 80
max_clients: 256
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: name=httpd state=latest
- name: ensure apache is running
service: name=httpd state=started
handlers:
- name: restart apache
service: name=httpd state=restarted
1. playbook基礎元件
1) hosts和users
playbook中的每一個play的目的都是為了讓某個或某些主機以某個指定的使用者身份執行任務。Hosts用於指定要執行指定任務的主機,其可以是一個或多個由冒號分隔主機組:remote_user則用於指定遠端主機上的執行任務的使用者。如上面示例中的
-hosts: webnodes
remote_user: root
不過,remote_user也可用於各task中。也可以通過指定其通過sudo的方式在遠端主機上執行任務,其可用於play全域性或某任務;此外,是指可以在sudo時使用sudo_user時切換的使用者。
- hosts: webnodes
remote_user: mageedu
tasks:
- name: test connection
ping:
remote_user: mageedu
sudo: yes
2) 任務列表和action
Play的主體部分是task list。Task list中的各任務按次序逐個在hosts中指定的所有主機上執行,即在所有主機上完成第一個任務後再開始第二個。在執行自下而上mouplaybook時,如果中途發生錯誤,所有已執行任務都將回滾,因此,在更正playbook後重新執行一次即可。
Task的目的是使用指定的引數執行模組,而在模組引數中可以使用變數。模組執行時冪等的,這意味著多次執行時安全的,因為其結果均一致。
每個task都應該有其name,用於playbook的執行結果輸出,建議其內容儘可能清晰地描述任務執行的步驟。如果未提供name,則action的結果將用於輸出。
定義task的可以使用“action:module options”或“module:options”的格式,推薦使用後者以實現向後相容。如果action一行的內容過多,也中使用在行首使用幾個空白字元進行換行。
tasks:
- name: make sure apache is running
service: name=httpd state=started
在眾多模組中,只有command和shell模組僅需要給定一個列表而無需使用“key=value”格式,例如:
tasks:
- name: disable selinux
command: /sbin/setenforce 0
如果命令或指令碼的退出碼不為零,可以使用如下方式替代:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
或者使用ignore_errors來忽略錯誤資訊:
-tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
3) handlers
用於當關注的資源發生變化時採取一定的操作。
“notify”這個action可用於在每一個play的最後被觸發,這樣可以避免多次有改變發生時滅磁都執行指定的操作,取而代之,僅在所有的變化發生後一次性的執行指定操作。在notify中列出的操作稱為handler,也即notify中呼叫handler定義的操作。
- name: template configuration file
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handler是task列表,這些task與前述的task並沒有本質上的不同。
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
案例:
heartbeat.yaml
- hosts: hbhosts
remote_user: root
tasks:
- name: ensure heartbeat latest version
yum: name=heartbeat state=present
- name: authkeys configure file
copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/authkeys
- name: authkeys mode 600
file: path=/etc/ha.d/authkeys mode=600
notify:
- restart heartbeat
- name: ha.cf configure file
copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/ha.cf
notify:
- restart heartbeat
handlers:
- name: restart heartbeat
service: name=heartbeat state=restarted
五、 roles
ansible自1.2版本引入的新特性用於層次性、結構化地組織playbook。Roles能夠根據層次型結構自動裝載變數檔案、tasks以及handlers等。要使用roles只需在playbook中使用include指令即可。簡單來講,roles就是通過分別將變數、檔案任務、模板及處理器放置於單獨的目錄中,並可以便捷地include它們的一種機制。roles一般用於基於主機構建服務的場景中,但也可以是用於構建守護程序等場景中。
一個roles的案例如下所示:
site.yml
webservers.yml
dbservers.yml
roles/
common/
files/
templates/
tasks/
handlers/
vars/
meta/
webservers/
files/
templates/
tasks/
handlers/
vars/
meta/
而在playbook中,可以這樣使用roles:
---
- hosts: webservers
roles:
- common
- webservers
也可以向roles傳遞引數,例如:
- hosts: webservers
roles:
- common
- { role: foo_app_instance, dir: '/opt/a', port: 5000 }
- { role: foo_app_instance, dir: '/opt/b', port: 5001 }
甚至也可以條件式地使用roles,例如:
---
- hosts: webservers
roles:
- { role: some_role, when: "ansible_os_family == 'RedHat'" }
1. 建立role的步驟
1) 建立以roles命名的目錄;
2) 在roles目錄中分別建立以各角色名稱命名的目錄,如webservers等;
3) 在每個角色命名的目錄中分別建立files、handlers、meta、tasks、templates和vars目錄;用不到的目錄可以建立為空目錄,也可以不建立;
4) 在playbook檔案中,呼叫各角色;
2. role內個各目錄中可用的檔案
1) tasks目錄:至少應該包含一個名為main.yml的檔案,其定義了此角色的任務列表;此檔案可以使用include包含其它的位於此目錄中的task檔案;
2) files目錄:存放由copy或script等模組呼叫的檔案;
3) templates目錄:template模組會自動在此目錄中尋找Jinja2模板檔案;
4) handlers目錄:此目錄應當包含一個main.yml檔案,用於定義此角色用到的各handler;在handler中使用include包含的其它的handler檔案也應該位於此目錄中;
5) vars目錄:應當包含一個main.yml檔案,用於定義此角色用到的變數;
6) meta目錄:應當包含一個main.yml檔案,用於定義此角色的特殊設定及其依賴關係;ansible1.3及其以後的版本才支援;
7) default目錄:為當前角色設定預設變數時使用此目錄;應當包含一個main.yml檔案;
六、 tags
tags用於讓使用者選擇執行playbook中的部分程式碼。ansible具有冪等性,因此會自動跳過沒有變化的部分,即便如此,有些程式碼為測試其確實沒有發生變化的時間依然會非常地長。此時,如果確信其沒有變化,就可以通過tags跳過此些程式碼片斷。
Ansible-playbook -t TAGS(--tags=TAGS)
Ansible-playbook –h 可以獲取具體用法。
演示1:編排劇本,簡單建立組和使用者,安裝並開啟服務;
1. 首先定義yaml格式的列表;
2. 可以看一下匹配的主機,任務列表
3. 測試執行;
演示2:利用handler,當httpd的配置檔案發生修改時,重啟httpd服務;
1. 準備httpd模板配置檔案;
將埠改為8080;
2. 編輯yaml列表檔案,定義playbook;
3. 測試執行;
4. 再次執行一次;配置檔案沒有發生改變,所以不會執行handler任務;
演示3:給指定任務定義tags;
1. 在以上檔案的基礎上編輯定義playbook;
2. 當我們只是修改了配置檔案,確保服務已經安裝並且啟動時,我們只需執行tags的任務即可;
以上可見,只執行了標記tags的任務,可以避免浪費很多資源。
演示4:變數
方法一:通過命令列傳遞
1. 配置playbook;
2. 命令列傳遞安裝程式包;
方法二:在playbook中直接定義變數值;
1. 定義playbook;
2. 執行命令即可;
方法三:在hosts Inventory中為每個主機定義專用變數值;
方法四:在hosts Inventory中定義組變數,向組內所有的主機傳遞相同的變數;
演示5:template,基於模板複製配置檔案;以下定義一個完整的nginx 的playbook;
1. 準備模板檔案,將worker_processes的值修改為一個變數,;
其中ansible_processor_vcpus為ansible內建變數;
2. 定義一個完整的nginx的playbook;
3. 測試執行;
演示6:角色roles;
1. 進入/etc/ansible/roles目錄,在此目錄中分別建立以各角色名稱命名的目錄,並在每個角色命名的目錄下分別建立files、handlers、meta、tasks、templates和vars目錄;用不到的目錄的可以建立為空目錄,也可以不建立;
2. 首先定義nginx角色的tasks目錄,如需呼叫一些模組,它會自動到對應的目錄中獲取檔案內容;
3. 定義tasks需要用到的模組目錄的內容;
1) handlers目錄
2) 準備templates的模板檔案,並修改其程序數為系統變數,並自定義監聽埠變數;
3) 準備vars目錄下的自定義變數;
4) 定義的檔案樹狀圖;
4. 定義playbook呼叫roles;
5. 確保/etc/ansible/ansible.cfg定義的roles路徑與剛才編輯的一致;
6. 測試執行;
轉載於:https://blog.51cto.com/claude666/2072287