ansible入門教程

Ansible是一個配置管理和配置工具,類似於Chef,Puppet或Salt。這是一款很簡單也很容易入門的部署工具,它使用SSH連接到服務器並運行配置好的任務,服務器上不用安裝任何多餘的軟件,只需要開啓ssh,所有工作都交給client端的ansible負責。 
關於Ansible的一個好處是,將bash腳本轉換爲可執行任務是非常容易的。我們可以編寫自己的配置程序,但是Ansible更加乾淨,因爲它可以自動在執行任務之前獲取上下文。ansible任務是冪等的,沒有大量額外的編碼,ansible可以一次又一次地安全運,而bash命令這種冪等性。 
ansible使用“facts”來確保任務的冪等安全運行, 它是在運行任務之前收集的系統和環境信息。ansible使用這些facts來檢查狀態,看看是否需要改變某些東西以獲得所需的結果。這使得ansible可以讓服務器一次又一次地運行可複製的任務。

1 安裝

當然我們需要先安裝Ansible。任務可以從任何可安裝的機器上運行。

1.1 Ubuntu

在Ubuntu 16.04上安裝Ansible的方法。

sudo apt-get install -y ansible
  • 1

apt-get安裝的ansible版本很低,建議使用pip方式安裝

sudo pip install ansible
  • 1

2 配置

ansible的默認配置文件路徑爲 /etc/ansible,然而,一個常見的用途是將其安裝在一個virtualenv中,在這種情況下,我們一般不會使用這些默認文件。我們可以根據需要在本地目錄中創建配置文件。

2.1 管理服務器:Inventory文件

您可以創建一個inventory文件,用於定義將要管理的服務器。這個文件可以命名爲任何名字,但我們通常會命名爲hosts或者項目的名稱。 
在hosts文件中,我們可以定義一些要管理的服務器。這裏我們將定義我們可能要在“web”標籤下管理的兩個服務器。標籤是任意的。

[web]
192.168.22.10
192.168.22.11
  • 1
  • 2
  • 3

現在已經夠好了,如果需要,我們可以定義主機範圍,多個組,可重用變量,並使用其他花哨的設置,包括創建動態的inventory。 
當我們在本地機器運行ansible時,我們不需要關心inventory文件中的內容,我將告訴您在本地和遠程服務器上運行ansible。現在,讓我們將hosts文件設置爲指向本地主機local和remote虛擬遠程主機。 
hosts文件:

[local]
127.0.0.1

[remote]
192.168.1.2
  • 1
  • 2
  • 3
  • 4
  • 5

與本地主機和遠程服務器連接的命令。

2.2 基礎:運行命令

我們開始對服務器運行任務。ansible會假定你的服務器具有SSH訪問權限,通常基於SSH-Key。因爲Ansible使用SSH,所以它需要能夠SSH連接到服務器。但是,ansible將嘗試以正在運行的當前用戶身份進行連接。如果我正在運行ansible的用戶是ubuntu,它將嘗試以ubuntu連接其他服務器。

# Run against localhost
$ ansible -i ./hosts --connection=local local -m ping

# Run against remote server
$ ansible -i ./hosts remote -m ping
127.0.0.1 | success >> {
    "changed": false,
    "ping": "pong"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

如果你是在cygwin下運行,遇到了“Failed to connect to the host via ssh: mux_client_request_session: read from master failed”的錯誤,可以執行:

ansible -i ./hosts remote -v -m ping -u root --private-key=~/.ssh/id_rsa
  • 1

使用–connection=local告訴ansible不嘗試通過SSH運行命令,因爲我們只是影響本地主機。但是,我們仍然需要一個hosts文件,告訴我們連接到哪裏。 
在任何情況下,我們可以看到從ansible得到的輸出是一些JSON,它告訴我們Task(我們對ping模塊的調用)是否進行了任何更改和結果。

命令說明:

-i ./hosts - 設置庫存文件,命名爲 hosts
remote,local,all-使用這個標籤的下定義的服務器hosts清單文件。“all”是針對文件中定義的每個服務器運行的特殊關鍵字
-m ping- 使用“ping”模塊,它只是運行ping命令並返回結果
-c local| --connection=local - 在本地服務器上運行命令,而不是SSH

一些常用命令:
-i PATH --inventory=PATH 指定host文件的路徑,默認是在/etc/ansible/hosts
--private-key=PRIVATE_KEY_FILE_PATH 使用指定路徑的祕鑰建立認證連接
-m DIRECTORY --module-path=DIRECTORY 指定module的目錄來加載module,默認是/usr/share/ansible
-c CONNECTION --connection=CONNECTION 指定建立連接的類型,一般有ssh ,local
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.2.1 模塊(Modules)

ansible使用“模塊”來完成大部分的任務。模塊可以做安裝軟件,複製文件,使用模板等等。

模塊是使用Ansible 的方法

因爲它們可以使用可用的上下文(“Facts”),以便確定要完成任務需要做什麼操作。 
如果我們沒有模塊,我們將運行任意的shell命令,我們也可以使用bash腳本。這是一個任意shell命令看起來像在Ansible(它使用的shell模塊!):

# Run against a local server
ansible -i ./hosts local --connection=local -b --become-user=root \
    -m shell -a 'apt-get install nginx'

# Run against a remote server
ansible -i ./hosts remote -b --become-user=root all \
    -m shell -a 'apt-get install nginx'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

這裏,sudo apt-get install nginx命令將使用“shell”模塊運行。 
命令說明:

-b - “成爲”,在運行命令時告訴可以成爲另一個用戶。
--become-user=root - 以用戶“root”運行以下命令(例如,使用命令使用“sudo”)。我們可以在此定義任何現有的用戶。
-a 用於將任何參數傳遞給定義的模塊 -m
  • 1
  • 2
  • 3

但是這並不是特別強大。儘管能夠一次在所有服務器上運行這些命令,但是我們仍然只能完成任何bash腳本可能執行的操作。如果我們使用了更合適的模塊,我們可以運行命令來保證結果。可靠的模塊確保我們可以一次又一次地運行相同的任務,而不會影響最終結果。 
要在Debian / Ubuntu服務器上安裝軟件,“apt”模塊將運行相同的命令,但確保冪等。

# Run against a local server
ansible -i ./hosts local --connection=local -b --become-user=root \
    -m apt -a 'name=nginx state=installed update_cache=true'

127.0.0.1 | success >> {
    "changed": false
}

# Run against a remote server
ansible -i ./hosts remote -b --become-user=root \
    -m apt -a 'name=nginx state=installed update_cache=true'

127.0.0.1 | success >> {
    "changed": false
}

or:
ansible -i ./hosts remote -v -m apt -a 'name=nginx state=installed update_cache=true' -u test -s -K --private-key=~/.ssh/id_rsa
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

這將使用apt模塊來更新存儲庫緩存並安裝Nginx(如果沒有安裝)。 
運行任務的結果是”changed”: false。這表明沒有變化; 我已經使用該shell模塊安裝了Nginx 。好的是,我可以一遍又一遍地運行這個命令,而不用擔心它會改變預期的結果 - Nginx已經安裝,Ansible知道,並且不嘗試重新安裝它。 
命令說明:

-i ./hosts - 設置inventory文件,命名爲 hosts
-b - “成”,告訴可以成爲另一個用戶來運行命令
--become-user=root - 以用戶“root”運行以下命令(例如,使用“sudo”命令)
local| remote - 從庫存文件中的本地或遠程定義的主機上運行
-m apt- 使用apt模塊
-a 'name=nginx state=installed update_cache=true' - 提供apt模塊的參數,包括軟件包名稱,所需的結束狀態以及是否更新軟件包存儲庫緩存

常用命令:
-u USERNAME --user=USERNAME 指定移動端的執行用戶
-U SUDO_USERNAME --sudo-user=USERNAME
-s --sudo -u指定用戶的時候,使用sudo獲得root權限
-k --ask-pass  提示輸入ssh的密碼,而不是使用基於ssh的密鑰認證
-K --ask-sudo-pass 提示輸入sudo密碼,與--sudo一起使用
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

我們可以通過這種特殊方式運行我們所需要的所有任務(通過模塊),但是讓我們來做這個更具管理性。我們將把這個任務移動到一個Playbook中,它可以運行和協調多個Tasks。

2.3 劇本(Playbooks)

Playbook可以運行多個任務,並提供一些更高級的功能。讓我們將上述任務移到一本劇本中。在ansible中劇本(playbooks)和角色(roles)都使用Yaml文件定義。 
創建文件nginx.yml:

---
# hosts could have been "remote" or "all" as well
- hosts: local
  connection: local
  become: yes
  become_user: root
  tasks:
   - name: Install Nginx
     apt:
       name: nginx
       state: installed
       update_cache: true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

此任務與我們的ad-hoc命令完全相同,包括設置本地連接的使用。 
這將使用inventory文件中[local]標籤下的服務器hosts。 
如果我們沒有使用本地連接,我們會這樣做:

---
- hosts: remote
  become: yes
  become_user: root
  tasks:
   - name: Install Nginx
     apt:
       name: nginx
       state: installed
       update_cache: true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

這將使用inventory文件中[remote]標籤下的服務器hosts。

在我們的Tasks文件中使用become並become_user再次使用Ansible來sudo以root用戶身份運行命令,然後傳遞Playbook文件。

使用一個yaml playbook文件,我們需要使用這個ansible-playbook命令,現在就更容易運行:

$ ansible-playbook -i ./hosts nginx.yml

PLAY [local] ******************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [Install Nginx] *********************************************************
ok: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1                  : ok=2    changed=0    unreachable=0    failed=0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

我們在運行過程中獲得了一些有用的反饋,包括“可執行任務”運行及其結果。在這裏我們看到所有運行都OK,但沒有改變。我已經安裝了Nginx

2.3.1 處理程序(Handlers)

處理程序與任務完全相同(它可以做task可以做的任何事),但只有當另一個任務調用它時纔會運行。您可以將其視爲事件系統的一部分; 處理程序將通過其偵聽的事件調用進行操作。 
這對於運行任務後可能需要的“輔助”操作非常有用,例如在配置更改後安裝或重新加載服務後啓動新服務。

---
# Example shows using the local machine still
# Remove 'connection' and set hosts to 'remote' for a remote connection
- hosts: local
  connection: local
  become: yes
  become_user: root
  tasks:
   - name: Install Nginx
     apt:
       name: nginx
       state: installed
       update_cache: true
     notify:
      - Start Nginx

  handlers:
   - name: Start Nginx
     service:
       name: nginx
       state: started
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

這裏我們添加一個notify指令到安裝任務。這將在任務運行後通知名爲“Start Nginx”的處理程序。

然後我們可以創建名爲“Start Nginx”的處理程序。此處理程序是通知“Start Nginx”時調用的任務。 
這個特定的處理程序使用服務模塊,它可以啓動,停止,重啓,重新加載(等等)系統服務。在這種情況下,我們告訴Ansible,我們要啓動Nginx。 
讓我們再次運行這本Playbook:

$ ansible-playbook -i ./hosts nginx.yml

PLAY [local] ******************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [Install Nginx] *********************************************************
ok: [127.0.0.1]

NOTIFIED: [nginx | Start Nginx] ***********************************************
ok: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1                  : ok=2    changed=0    unreachable=0    failed=0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

我們得到類似的輸出,但是這次Handler是運行的。 
通知程序只在運行任務時運行。

Note:如果我已經安裝了Nginx,則安裝Nginx任務將不會運行,通知程序也將不會被調用。

我們可以使用Playbook來運行多個任務,添加變量,定義其他設置,甚至包括其他的劇本。

2.3.2 更多的任務(More Tasks)

接下來,我們可以爲此Playbook添加更多的任務,並探索其他一些功能。

---
# Example shows using the local machine still
# Remove 'connection' and set hosts to 'remote' for a remote connection
- hosts: local
  connection: local
  become: yes
  become_user: root
  vars:
   - docroot: /var/www/serversforhackers.com/public
  tasks:
   - name: Add Nginx Repository
     apt_repository:
       repo: ppa:nginx/stable
       state: present
     register: ppastable

   - name: Install Nginx
     apt:
       pkg: nginx
       state: installed
       update_cache: true
     when: ppastable|success
     notify:
      - Start Nginx

   - name: Create Web Root
     file:
      path: '{{ docroot }}'
      mode: 775
      state: directory
      owner: www-data
      group: www-data
     notify:
      - Reload Nginx

  handlers:
   - name: Start Nginx
     service:
       name: nginx
       state: started

    - name: Reload Nginx
      service:
        name: nginx
        state: reloaded
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

現在有三個任務:

Add Nginx Repository- 使用apt_repository模塊添加Nginx穩定PPA以獲取最新的穩定版本的Nginx 。
Install Nginx - 使用Apt模塊安裝Nginx。
Create Web Root - 最後創建一個Web根目錄。
  • 1
  • 2
  • 3

新的register和when指令,可以實現在某些事情發生後讓ansible執行任務的功能。

Note: 您還可以註冊模塊操作的結果,並使用定義的變量根據註冊(register)的變量值有條件(when)地執行操作。例如,註冊通過shell模塊運行命令的結果可以讓您訪問該命令的stdout。

同時還使用了一個變量。docroot變量在定義vars部分。然後將其用作創建定義目錄的文件模塊的目標參數。

需要注意的是,path配置使用括號{{ var-name }},這是Jinja2的模板。爲了使Ansible能夠在括號內解析Jinja2模板變量,該行必須是單引號或雙引號 - 例如,path: ‘{{ docroot }}’而不是path: {{ docroot }}。不使用引號將導致錯誤。 
這個playbook可以用通常的命令運行:

ansible-playbook -i ./hosts nginx.yml
  • 1

所以,我們已經運行了一些ad-hoc命令,使用了可複製的模塊,並將一些相關任務組織到一個手冊中。

接下來,我們將通過將Playbook組織成一個角色進一步獲得可靠性,這有助於我們組織相關項目,如文件和模板,同時還幫助我們組織更復雜的相關任務和操作。

2.4 角色(roles)

角色很適合組織多個相關任務並封裝完成這些任務所需的數據。例如,安裝Nginx可能涉及添加軟件包存儲庫,安裝軟件包和設置配置。 
此外,真實的配置通常需要額外的數據,如變量,文件,動態模板等等。這些工具可以與Playbook一起使用,但是我們可以通過將相關任務和數據組織成一個角色(role, 相關的結構)很快就能做得更好。 
角色有一個這樣的目錄結構:

roles
  rolename
   - files
   - handlers
   - meta
   - templates
   - tasks
   - vars
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在每個子目錄中(eg: files,handlers等等),Ansible將自動搜索並讀取叫做main.yml的yaml文件。 
接下來我們將分解nginx.yml文件內容爲不同的組件,並將每個組件放在相應的目錄中,以創建一個更乾淨,更完整的配置工具集。

2.4.1 創建角色(Creating a Role)

我們可以使用ansible-galaxy命令來創建一個新角色。此工具可用於將角色保存到Ansible的公共註冊表,但是我通常只是使用它來在本地創建role的基礎目錄結構。

我們來看看如何設置:

# Head to our previously created directory
cd ~/ansible-example

# In case we left our virtualenv at some point 
source .venv/bin/activate

# Create a roles directory
mkdir roles
cd roles

# Bootstrap a new role named "nginx"
ansible-galaxy init nginx
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

目錄名稱roles是一種慣例,在運行一個playbook時可以用來查找角色。該目錄應該始終被命名roles,但並不強制。在roles目錄中運行 ansible-galaxy init nginx 命令將創建新角色所需的目錄和文件。

我們來看看我們新建的nginx角色的每個部分~/ansible-example/roles/nginx。

2.4.2 文件(files)

首先,在files目錄中,我們可以添加我們要複製到我們的服務器中的文件。對於nginx,我經常複製H5BP的Nginx組件配置。我只需從Github下載最新的信息,進行一些調整,並將它們放入files目錄中。

~/ansible-example
 - roles
 - - nginx
 - - - files
 - - - - h5bp
  • 1
  • 2
  • 3
  • 4
  • 5

我們稍後會看到,H5BP配置文件將通過複製模塊添加到服務器。

2.4.3 處理程序(handlers)

我們可以把曾經在nginx.yml 劇本中的定義的所有處理程序放入到handlers目錄中。約定必須包含main.yml文件。

handlers/main.yml 內容:

---
- name: Start Nginx
  service:
    name: nginx
    state: started

- name: Reload Nginx
  service:
    name: nginx
    state: reloaded
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

一旦handlers/main.yml中的處理程序定義好了,我們可以自由地從其他的yaml配置中引用它們。

2.4.4 元(meta)

meta目錄中的main.yml文件包含Role元數據,包含的依賴關係。如果這個角色依賴於另一個角色,我們可以在這裏定義。例如,nginx角色取決於安裝SSL證書的ssl角色。約定必須包含main.yml文件。 
meta/main.yml 內容:

---
dependencies:
  - { role: ssl }
  • 1
  • 2
  • 3

如果我調用了“nginx”角色,它將嘗試首先運行“ssl”角色。 
否則我們可以省略此文件,或將角色定義爲沒有依賴關係:

---
dependencies: []
  • 1
  • 2

2.4.5 模板(templates)

基於Python的Jinja2模板引擎(和django的模板引擎很類似),模板文件可以包含模板變量。這裏的文件應該以.j2爲類型後綴(eg.uwsgi.j2),提倡但是不強制,也可以取其他的名字。類似於files,在templates目錄中沒有main.yml文件,只包含.j2後綴的模板文件。 
這是一個Nginx服務器(“虛擬主機”)配置的例子。請注意,它使用了稍後在vars/main.yml文件中定義的一些變量。 
我們的示例中的Nginx配置文件位於templates/serversforhackers.com.conf.j2:

server {
    # Enforce the use of HTTPS
    listen 80 default_server;
    server_name {{ domain }};
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl default_server;

    root /var/www/{{ domain }}/public;
    index index.html index.htm index.php;

    access_log /var/log/nginx/{{ domain }}.log;
    error_log  /var/log/nginx/{{ domain }}-error.log error;

    server_name {{ domain }};

    charset utf-8;

    include h5bp/basic.conf;

    ssl_certificate           {{ ssl_crt }};
    ssl_certificate_key       {{ ssl_key }};
    include h5bp/directive-only/ssl.conf;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location = /favicon.ico { log_not_found off; access_log off; }
    location = /robots.txt  { log_not_found off; access_log off; }

    location ~ \.php$ {
        include snippets/fastcgi.conf;
        fastcgi_pass unix:/var/run/php7.1-fpm.sock;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

這是一個相當標準的用於PHP應用程序的Nginx配置。這裏有三個變量:

域 
ssl_crt 
ssl_key 
這三個變量將在變量部分(vars)中定義。

2.4.6 變量(vars)

在使用任務集成所有事情之前,讓我們來看看變量。該vars目錄包含一個main.yml文件(如handlers和meta目錄一樣),在main.yml中我們可以列出將要使用的所有變量。 
以下是該vars/main.yml文件的內容:

---
domain: serversforhackers.com
ssl_key: /etc/ssl/sfh/sfh.key
ssl_crt: /etc/ssl/sfh/sfh.crt
  • 1
  • 2
  • 3
  • 4

我們可以在這個角色的其他地方使用這三個變量。我們在上面的模板中看到它們的使用,但是我們也可以在我們定義的任務中看到它們。

Note:如果您有敏感信息添加到變量文件中,則可以使用ansible-vault加密文件,下面將對此進行說明。

2.4.7 任務(tasks)

終於到了將一切都是放在一系列的任務中的時候了。 
使用角色時運行的主文件是tasks/main.yml文件。看看我們的用例將會是什麼樣的:

---
- name: Add Nginx Repository
  apt_repository:
    repo: ppa:nginx/stable
    state: present

- name: Install Nginx
  apt:
    pkg: nginx
    state: installed
    update_cache: true
  notify:
    - Start Nginx

- name: Add H5BP Config
  copy:
    src: h5bp
    dest: /etc/nginx
    owner: root
    group: root

- name: Disable Default Site Configuration
  file:
    dest: /etc/nginx/sites-enabled/default
    state: absent

# `dest` in quotes as a variable is used!
- name: Add SFH Site Config
  register: sfhconfig
  template:
    src: serversforhackers.com.j2
    dest: '/etc/nginx/sites-available/{{ domain }}.conf' 
    owner: root
    group: root

# `src`/`dest` in quotes as a variable is used!
- name: Enable SFH Site Config
  file:
    src: '/etc/nginx/sites-available/{{ domain }}.conf'
    dest: '/etc/nginx/sites-enabled/{{ domain }}.conf'
    state: link

# `dest` in quotes as a variable is used!
- name: Create Web root
  file:
    dest: '/var/www/{{ domain }}/public'
    mode: 775
    state: directory
    owner: www-data
    group: www-data
  notify:
    - Reload Nginx

# `dest` in quotes as a variable is used!
- name: Web Root Permissions
  file:
   dest: '/var/www/{{ domain }}'
   mode: 775
   state: directory
   owner: www-data
   group: www-data
   recurse: yes
  notify:
    - Reload Nginx
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64

這一系列任務使得Nginx能被完整的安裝。任務按照出現的順序完成以下工作:

1 添加nginx / stable庫
2 安裝並啓動Nginx
3 添加H5BP配置文件
4 從sites-enabled目錄中刪除文件的符號鏈接來禁用默認的Nginx配置
5 將serversforhackers.com.conf.j2虛擬主機模板複製到Nginx配置中,渲染模板
6 通過將其符號鏈接到sites-enabled目錄來啓用Nginx服務器配置
7 創建Web根目錄
8 更改項目根目錄的權限(遞歸),該目錄位於之前創建的Web根目錄之上
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

有一些新的模塊(和一些我們已經涵蓋的新用途),包括複製,模板和文件模塊。通過設置每個模塊的參數,我們可以做一些有趣的事情,例如確保文件“不存在”(如果存在則刪除它們)的state: absent,或者通過創建一個文件作爲符號鏈接的state: link。您應該檢查每個模塊的文檔,以查看可以用它們完成哪些有趣和有用的事情。

2.4.8 運行角色(Running the Role)

要對服務器運行一個或多個角色,我們將重新使用另一個playbook。該playbook與roles目錄位於同一個目錄中,同一層級。當我們用ansible-playbook命令運行的時候需要先cd進入到該目錄中。 
讓我們創建一個“主”的yaml文件(被ansible-playbook命令執行的文件),該文件定義要使用的角色以及運行它們的主機: 
文件~/ansible-example/server.yml位於與roles目錄相同的目錄中:

---
# run locally here, yadda yadda yadda
- hosts: local
  connection: local
  roles:
    - nginx
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

所以,我們只是定義角色,而不是在本Playbook文件中定義所有的變量和任務。角色負責具體細節。

然後我們可以運行角色:

ansible-playbook -i ./hosts server.yml
  • 1

以下是運行Nginx角色的Playbook文件的輸出:

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [127.0.0.1]

TASK: [nginx | Add Nginx Repository] ******************************************
changed: [127.0.0.1]

TASK: [nginx | Install Nginx] *************************************************
changed: [127.0.0.1]

TASK: [nginx | Add H5BP Config] ***********************************************
changed: [127.0.0.1]

TASK: [nginx | Disable Default Site] ******************************************
changed: [127.0.0.1]

TASK: [nginx | Add SFH Site Config] *******************************************
changed: [127.0.0.1]

TASK: [nginx | Enable SFH Site Config] ****************************************
changed: [127.0.0.1]

TASK: [nginx | Create Web root] ***********************************************
changed: [127.0.0.1]

TASK: [nginx | Web Root Permissions] ******************************************
ok: [127.0.0.1]

NOTIFIED: [nginx | Start Nginx] ***********************************************
ok: [127.0.0.1]

NOTIFIED: [nginx | Reload Nginx] **********************************************
changed: [127.0.0.1]

PLAY RECAP ********************************************************************
127.0.0.1                  : ok=8   changed=7   unreachable=0    failed=0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

我們將所有各種組件放在一起,形成一致的角色,現在已經安裝並配置了Nginx!

2.5 事實(Facts)

請注意,運行劇本時的第一行總是“收集事實”。 
在運行任何任務之前,Ansible將收集有關其配置的系統的信息。這些被稱爲事實,並且包括廣泛的系統信息,如CPU核心數量,可用的ipv4和ipv6網絡,掛載的磁盤,Linux發行版等等。

事實在“任務”或“模板”配置中通常很有用。例如,Nginx通常設置爲使用與CPU內核一樣多的工作處理器。知道這一點,您可以選擇如下設置nginx.conf.j2文件的模板:

user www-data;
worker_processes {{ ansible_processor_cores }};
pid /var/run/nginx.pid;

# And other configurations...
  • 1
  • 2
  • 3
  • 4
  • 5

或者如果你具有多個CPU的服務器,則可以使用:

user www-data;
worker_processes {{ ansible_processor_cores * ansible_processor_count }};
pid /var/run/nginx.pid;

# And other configurations...
  • 1
  • 2
  • 3
  • 4
  • 5

所有的ansible facts全局變量都是以“anisble_”爲前綴,並且可以在其他任何地方使用。 
嘗試對你的本地機器運行以下內容以查看可用的事實:

# Run against a local server
# Note that we say to use "localhost" instead of defining a hosts file here!
ansible -m setup --connection=local localhost

# Run against a remote server
ansible -i ./hosts remote -m setup
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

2.6 加密(Vault)

我們經常需要將敏感數據存儲在我們的模板,文件或變量文件中; 這樣安全性有一定要求的情況是不可避免的(當我們將這些敏感數據文件推送到遠程Git倉庫時,這是一個痛苦的事情)。Ansible有一個叫做Ansible Vault的解決方案。 
Vault允許您加密任何Yaml文件,通常將其作用與變量文件,Vault不會加密文件和模板,只能使用Yaml文件。 
在創建加密文件時,系統會詢問您必須使用的密碼,以便稍後在調用角色或Playbook時進行編輯。 
將密碼保存在安全的地方。

例如我們可以創建一個新的變量文件:

ansible-vault create vars/main.yml
Vault Password:
  • 1
  • 2

輸入加密密碼後,該文件將在您的默認編輯器(通常是Vim或Nano)中打開。 
默認使用的編輯器由EDITOR環境變量定義。默認值通常是Vim。如果您不是Vim用戶,可以通過設置環境變量來快速更改:

EDITOR=nano ansible-vault edit vars/main.yml
  • 1

在大多數情況下,我們將使用ansible-vault create|edit /path/to/file.yml。更多可用的命令如下:

create - 創建一個新文件並進行加密
decrypt - 從加密文件創建明文文件
edit - 編輯已經存在的加密文件
encrypt - 加密現有的純文本文件
rekey - 在加密文件中設置新密碼
  • 1
  • 2
  • 3
  • 4
  • 5

如果你有一個現有的配置文件要加密,請使用 ansible-vault encrypt /path/to/file.yml。

示例: users角色

我們創建一個名爲“users”的角色:

cd ~/ansible-example/roles
ansible-galaxy init users
  • 1
  • 2

創建新用戶並設置密碼時,我使用Vault 。在用戶角色中,您可以設置帶有用戶密碼和公鑰的變量文件,以添加到用戶的authorized_keys文件(從而提供SSH訪問權限)。公共SSH密鑰在技術上是安全的,一般公衆可以看到 - 所有人都可以使用它來允許你訪問自己的服務器。在沒有配對私鑰的情況下,公鑰是不能獲得系統訪問權限的,我們沒有將密鑰加入此角色。 
以下是可以使用Vault創建和加密的示例變量文件。在編輯它時,它是純文本。

~/ansible-example/roles/users/vars/main.yml:

admin_password: $6$lpQ1DqjZQ25gq9YW$mHZAmGhFpPVVv0JCYUFaDovu8u5EqvQi.Ih
deploy_password: $6$edOqVumZrYW9$d5zj1Ok/G80DrnckixhkQDpXl0fACDfNx2EHnC
common_public_key: ssh-rsa ALongSSHPublicKeyHere
  • 1
  • 2
  • 3

請注意,用戶的密碼也是散列的。您可以閱讀Ansible有關生成加密密碼的文檔,用戶模塊需要設置用戶密碼。作爲一個快速入門,它在Ubuntu上看起來像這樣:

# The whois package makes the mkpasswd
# command available on Ubuntu
$ sudo apt-get install -y whois

# Create a password hash
$ mkpasswd --method=SHA-512
Password:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

這將生成一個散列密碼供你與user模塊一起使用。

Note:變量文件中的密碼是散列的,但我仍然喜歡加密包含散列密碼的yaml文件。這些文件通常包含未標記的數據,如API令牌或SSH私鑰,使加密非常重要。

一旦你設置了用戶密碼並將公鑰添加到變量文件中,我們就可以加密此文件,然後在任務中使用這些加密變量。

ansible-vault encrypt roles/users/vars/main.yml
  • 1

然後我們可以編輯我們的任務文件,使用(加密)變量添加新用戶:

這是文件~/ansible-example/roles/users/tasks/main.yml:

---
- name: Create Admin User
  user:
    name: admin
    password: '{{ admin_password }}'
    groups: sudo
    append: yes
    shell: /bin/bash

- name: Add Admin Authorized Key
  authorized_key:
    user: admin
    key: '{{ common_public_key }}'
    state: present

- name: Create Deploy User
  user:
    name: deploy
    password: '{{ deploy_password }}'
    groups: www-data
    append: yes
    shell: /bin/bash

- name: Add Deployer Authorized Key
  authorized_key:
    user: deploy
    key: '{{ common_public_key }}'
    state: present
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

這些任務使用該user模塊來創建新用戶,傳遞變量文件中設置的密碼。 
它還使用該authorized_key模塊將SSH公鑰作爲SSH授權密鑰添加到每個用戶的服務器中。 
加密變量的使用像在常規任務文件中使用一樣。但是,爲了運行此角色,我們需要告訴Ansible請求輸入vault密碼,以便它可以解密變量。 
編輯我們的server.ymlPlaybook文件,調用user角色:

---
# Local connection here, yadda yadda yadda
- hosts: local
  connection: local
  sudo: yes
  roles:
    - nginx
    - user
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

要運行此Playbook,我們需要告知Ansible請求vault的密碼,因爲我們正在運行包含加密文件的角色:

ansible-playbook --ask-vault-pass -i ./hosts server.yml
  • 1

3 總結

本篇文章帶着做了如下工作:

  1. 安裝了ansible
  2. 配置了ansible inventory文件(僅在不使用connection: local 時才需要)
  3. 同時在多個服務器上執行冪等的 ad-hoc命令
  4. 創建一個基本的Playbook來運行多個任務(tasks),並使用了處理程序(handlers)
  5. 將多個任務抽象爲一個角色,以保持所有Nginx相關的操作在一個角色內 
    • 展示瞭如何設置依賴關係
    • 展示瞭如何註冊任務的“依賴”執行關係,當一個任務執行成功後再執行另一個任務
    • 展示瞭如何在我們的任務中使用更多的模板,文件和變量
  6. 展示瞭如何整合使用ansible事實(facts)
  7. 展示瞭如何使用ansible的vault來增加我們的變量的安全性
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章