1. 程式人生 > 實用技巧 >Linux自學筆記——Ansible

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. 配置基於金鑰認證連線被管控主機;(安全)

管理端:

image.png

在主機中hosts檔案中新增對映:

image.png

在管理端測試:

image.png

2. 對ansible配置檔案備份,並編輯配置主機清單(/etc/ansible/hosts);

image.png

3. 可以獲取使用幫助;

image.png

基於以上環境,以下將對ansible的模組用法進行一一演示:

1. command模組

1) 獲取所有主機的ip地址:

image.png

2) 給webserver組的兩臺主機新增一個centos使用者,並其新增密碼也為centos;

image.png

驗證:可以發現密碼新增失敗;

image.png

Note:command命令不支援管道傳輸,所以可以用shell模組通過管道傳輸;


2. shell模組

1) 給上面建立的centos使用者設定密碼為centos(通過管道方式)

image.png

2) 驗證:密碼新增成功

image.png

3. user模組

1) 用user模組為所有主機建立redhat使用者;

image.png

2) 也可以刪除使用者;

image.png

4. group模組

image.png

5. cron模組:管理週期性任務

1) 建立自定義任務,每個五分鐘向控制主機同步一下時間;

image.png

2) 測試遠端主機檢視;

image.png

6. copy模組

1) 複製管控主機上的/etc/fstab檔案到被控主機的/tmp目錄下,檔名為fstab.ansible

image.png

2) 測試;

image.png

7. file模組

1) 改變檔案屬性;

image.png

2) 建立檔案;

image.png

3) 建立連結檔案;

image.png

測試:

image.png

4) 建立目錄檔案;

image.png

8. ping模組

image.png

9. yum模組

1) 為webserver主機安裝nginx:

image.png

2) 解除安裝nginx

image.png

10. service模組

開啟webserver上的nginx服務;

image.png

11. script模組

image.png

12. setup

image.png

二、 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格式的列表;

image.png

2. 可以看一下匹配的主機,任務列表

image.png

3. 測試執行;

image.png

演示2:利用handler,當httpd的配置檔案發生修改時,重啟httpd服務;

1. 準備httpd模板配置檔案;

image.png

將埠改為8080;

image.png

2. 編輯yaml列表檔案,定義playbook;

image.png

3. 測試執行;

image.png

4. 再次執行一次;配置檔案沒有發生改變,所以不會執行handler任務;

image.png

演示3:給指定任務定義tags;

1. 在以上檔案的基礎上編輯定義playbook;

image.png

2. 當我們只是修改了配置檔案,確保服務已經安裝並且啟動時,我們只需執行tags的任務即可;

image.png

以上可見,只執行了標記tags的任務,可以避免浪費很多資源。

演示4:變數

方法一:通過命令列傳遞

1. 配置playbook;

image.png

2. 命令列傳遞安裝程式包;

image.png

方法二:在playbook中直接定義變數值;

1. 定義playbook;

image.png

2. 執行命令即可;

image.png

方法三:在hosts Inventory中為每個主機定義專用變數值;

image.png

方法四:在hosts Inventory中定義組變數,向組內所有的主機傳遞相同的變數;

image.png

演示5:template,基於模板複製配置檔案;以下定義一個完整的nginx 的playbook;

1. 準備模板檔案,將worker_processes的值修改為一個變數,;

image.png

其中ansible_processor_vcpus為ansible內建變數;

image.png

2. 定義一個完整的nginx的playbook;

image.png

3. 測試執行;

image.png

演示6:角色roles;

1. 進入/etc/ansible/roles目錄,在此目錄中分別建立以各角色名稱命名的目錄,並在每個角色命名的目錄下分別建立files、handlers、meta、tasks、templates和vars目錄;用不到的目錄的可以建立為空目錄,也可以不建立;

image.png

2. 首先定義nginx角色的tasks目錄,如需呼叫一些模組,它會自動到對應的目錄中獲取檔案內容;

image.png

3. 定義tasks需要用到的模組目錄的內容;

1) handlers目錄

image.png

2) 準備templates的模板檔案,並修改其程序數為系統變數,並自定義監聽埠變數;

image.png

image.png

3) 準備vars目錄下的自定義變數;

image.png

4) 定義的檔案樹狀圖;

image.png

4. 定義playbook呼叫roles;

image.png

5. 確保/etc/ansible/ansible.cfg定義的roles路徑與剛才編輯的一致;

image.png

6. 測試執行;

image.png


轉載於:https://blog.51cto.com/claude666/2072287