Ansible簡明教程

Ansible是當下比較流行的自動化運維工具,可經過SSH協議對遠程服務器進行集中化的配置管理、應用部署等,常結合Jenkins來實現自動化部署。html

除了Ansible,還有像SaltStack、Fabric(曾經管理100多臺服務器上的應用時也曾受益於它)、Puppet等自動化工具。相比之下,Ansible最大的優點就是無需在被管理主機端部署任何客戶端代理程序,經過SSH通道就能夠進行遠程命令的執行或配置的下發,足夠輕量級,但同時功能很是強大,且各項功能經過模塊來實現,具有良好的擴展性。不足之處是Ansible只支持在Linux系統上安裝,不支持Windows。nginx

若是你須要在多於一臺服務器上作相同的操做,那麼建議你使用Ansible之類的自動化工具,這將極大提升你的操做效率。c++

環境搭建

1.找一臺主機用於作管理服務器,在其上安裝Ansibleshell

yum -y install ansible

Ansible基於Python實現,通常Linux系統都自帶Python,因此能夠直接使用yum安裝或pip安裝。vim

安裝完後,在/etc/ansible/目錄下生成三個主要的文件或目錄,tomcat

[root@tool-server ~]# ll /etc/ansible/
total 24
-rw-r--r--. 1 root root 19179 Jan 30  2018 ansible.cfg
-rw-r--r--. 1 root root  1136 Apr 17 15:17 hosts
drwxr-xr-x. 2 root root     6 Jan 30  2018 roles
  • ansible.cfg: Ansible的配置文件
  • hosts:登記被管理的主機
  • roles:角色項目定義目錄,主要用於代碼複用

2.在/etc/ansible/hosts文件中添加須要被管理的服務器節點服務器

[root@tool-server ~]# vim /etc/ansible/hosts
[k8s]
192.168.40.201
192.168.40.202
192.168.40.205
192.168.40.206

[k8s]表示將下面的服務器節點分到k8s的組中,後面執行命令時可指定針對某個組執行。微信

3.生成SSH KEY,並copy到被管理節點上,實現免密SSH訪問併發

在管理節點執行 ssh-keygen 生成SSH KEY,而後copy到各被管理節點上運維

ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.40.201

上面命令將~/.ssh/id_rsa.pub文件內容添加到被管理節點的/root/.ssh/authorized_keys文件中,實現管理節點到被管理節點的免密SSH訪問。

4.調試Ansible

針對k8s服務器組執行ping,驗證Ansible到各被管理節點的連通性

[root@tool-server ~]# ansible k8s -m ping
192.168.40.201 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.40.205 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.40.202 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}
192.168.40.206 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Ansible只須要在管理主機上安裝,而後打通管理主機到各被管理主機的SSH免密訪問便可進行集中化的管理控制,不需在被管理主機安裝任何代理程序。

Ansible命令

Ansible的命令格式爲, ansible 主機羣組名 -m 命令模塊名 -a "批量執行的操做"

其中-m不是必須的,默認爲command模塊,-a也不是必須的,表示命令模塊的參數,好比前面的ping模塊就沒有參數。

可使用 ansible-doc -l 列出全部可用的命令模塊, ansible-doc -s 模塊名 查看指定模塊的參數信息

經常使用命令模塊

1.command
command是Ansible的默認模塊,不指定-m參數時默認使用command。command能夠運行遠程主機權限範圍內的全部shell命令,但不支持管道操做

# 查看k8s分組主機內存使用狀況
ansible k8s -m command -a "free -g"

2.shell
shell基本與command相同,但shell支持管道操做

#shell支持管道操做 |grep Mem
ansible k8s -m shell -a "free -g|grep Mem"

3.script
script就是在遠程主機上執行管理端存儲的shell腳本文件,至關於scp+shell

# /root/echo.sh爲管理端本地shell腳本
ansible k8s -m script -a "/root/echo.sh"

4.copy
copy實現管理端到遠程主機的文件拷貝,至關於scp

#拷貝本地echo.sh文件到k8s組中遠程主機的/tmp目錄下,所屬用戶、組爲 root ,權限爲 0755
ansible k8s -m copy -a "src=/root/echo.sh dest=/tmp/ owner=root group=root mode=0755"

5.yum
軟件包安裝或刪除

ansible k8s -m yum -a "name=wget state=latest"

其中state有以下取值:

  • 針對安裝,可取值「present,installed,latest」,present,installed即普通安裝,二者無區別,latest是使用yum mirror上最新的版本進行安裝
  • 針對刪除,可取值「absent,removed」,二者無差異

6.service
對遠程主機的服務進行管理

ansible k8s -m service -a "name=nginx state=stoped"

state可取值「started/stopped/restarted/reloaded」。

7.get_url
在遠程主機上下載指定URL到本地

ansible k8s -m get_url -a "url=http://www.baidu.com dest=/tmp/index.html mode=0440 force=yes"

8.setup
獲取遠程主機的信息

ansible k8s -m setup

9.file
管理遠程主機的文件或目錄

ansible k8s -m file -a "dest=/opt/test state=touch"

state可取值

  • directory:建立目錄
  • file:若是文件不存在,則建立
  • link:建立symbolic link
  • absent:刪除文件或目錄
  • touch: 建立一個不存在的空文件

10.cron
管理遠程主機的crontab定時任務

ansible k8s -m cron -a "name='backup servcie' minute=*/5 job='/usr/sbin/ntpdate  time.nist.gov >/dev/null 2>&1'"

支持的參數

  • state: 取值present表示建立定時任務,absent表示刪除定時任務
  • disabled: yes表示註釋掉定時任務,no表示接觸註釋

Ansible playbook

Ansible的playbook由一個或多個play組成,play的功能就是爲歸爲一組的主機編排要執行的一系列task,其中每個task就是調用Ansible的一個命令模塊。

playbook的核心元素包括:

  • hosts:執行任務的遠程主機組或列表
  • tasks:要執行的任務列表
  • variables:內置變量或自定義的變量
  • templates:使用模板語法的文件,一般爲配置文件
  • handlers:和notify結合使用,由特定條件觸發,通常用於配置文件變動觸發服務重啓
  • tags:標籤,可在運行時經過標籤指定運行playbook中的部分任務
  • roles:

playbook文件遵循yaml的語法格式,運行命令的格式爲 ansible-playbook <filename.yml> ... [options], 經常使用options包括

  • --syntax 檢查playbook文件語法是否正確
  • --check 或 -C 只檢測可能會發生的改變,但不真正執行操做
  • --list-hosts 列出運行任務的主機
  • --list-tags 列出playbook文件中定義全部的tags
  • --list-tasks 列出playbook文件中定義的全部任務集
  • --limit 只針對主機列表中的某個主機或者某個組執行
  • -f 指定併發數,默認爲5個
  • -t 指定某個或多個tags運行(前提playbook中有定義tags)
  • -v 顯示過程 -vv -vvv更詳細

下面以批量安裝Nginx爲例,儘量介紹playbook各核心元素的用法。

定義palybook yaml文件nginx_playbook.yml

---
- hosts: 192.168.40.201,192.168.40.205 # 主機列表,也能夠是/etc/ansible/hosts中定義的主機分組名
  remote_user: root # 遠程用戶
  vars:             # 自定義變量
     version: 1.16.1
  vars_files:
     - ./templates/nginx_locations_vars.yml


  tasks:
     - name: install dependencies          # 定義任務的名稱
       yum: name={{item}} state=installed  # 調用模塊,具體要作的事情,這裏使用with_items迭代多個yum任務安裝必要的依賴
       with_items:
          - gcc
          - gcc-c++
          - pcre
          - pcre-devel
          - zlib
          - zlib-devel
          - openssl
          - openssl-devel
     - name: download nginx                # 經過get_url模塊下載nginx
       get_url: url=http://nginx.org/download/nginx-{{version}}.tar.gz dest=/tmp/ mode=0755 force=no
     - name: unarchive                     # 經過unarchive模塊解壓nginx
       unarchive: src=/tmp/nginx-{{version}}.tar.gz dest=/tmp/ mode=0755 copy=no
     - name: configure,make and install    # 經過shell模塊執行shell命令編譯安裝
       shell: cd /tmp/nginx-{{version}} && ./configure --prefix=/usr/local/nginx && make && make install
     - name: start nginx                   # 經過shell模塊執行shell命令啓動nginx
       shell: /usr/local/nginx/sbin/nginx
     - name: update config                 # 經過template模塊動態生成配置文件下發到遠程主機目錄
       template: src=nginx.conf.j2 dest=/usr/local/nginx/conf/nginx.conf
       notify: reload nginx                # 在結束時觸發一個操做,具體操做經過handlers來定義
       tags: reload                        # 對任務定義一個標籤,運行時經過-t執行帶指定標籤的任務

  handlers:
     - name: reload nginx                  # 與notify定義的內容對應
       shell: /usr/local/nginx/sbin/nginx -s reload

1. 變量

在上面的示例中使用vars定義了變量version,在tasks中經過{{version}}進行引用。Ansible支持以下幾種定義變量的方式

1.在playbook文件中定義
前面示例已經說明

2.命令行指定
在執行playbook時經過-e指定,如ansible-playbook -e "version=1.17.9" nginx_playbook.yml, 這裏指定的變量將覆蓋playbook中定義的同名變量的值

3.hosts文件中定義變量
在/etc/ansible/hosts文件中也能夠定義針對單個主機或主機組的變量,如

[nginx]
192.168.40.201 version=1.17.9 # 定義單個主機的變量
192.168.40.205 
[nginx:vars]  # 定義整個組的統一變量
version=1.16.1

4.在獨立的yaml文件中定義變量
專門定義一個yaml變量文件,而後在playbook文件中經過var_files引用,如

# 定義存放變量的文件
[root@ansible ]# cat var.yml
version: 1.16.1

# 編寫playbook
[root@ansible ]# cat nginx_playbook.yml
---
- hosts: nginx
  remote_user: root
  vars_files:     # 引用變量文件
    - ./var.yml   # 指定變量文件的path(這裏能夠是絕對路徑,也能夠是相對路徑)

5.使用setup模塊獲取到的變量
前面介紹setup模塊可獲取遠程主機的信息,可在playbook中直接引用setup模塊獲取到的屬性,好比系統版本: ansible_distribution_major_version

2. 模板

playbook模板爲咱們提供了動態的配置服務,使用jinja2語言,支持多種條件判斷、循環、邏輯運算、比較操做等。應用場景就是定義一個模板配置文件,而後在執行的時候動態生成最終的配置文件下發到遠程主機。通常將模板文件放在playbook文件同級的templates目錄下,這樣在playbook文件中能夠直接引用,不然須要經過絕對路徑指定,模板文件後綴名通常爲 .j2。

本例中,咱們將nginx.conf配置文件做爲模板文件,添加須要動態配置的內容,並定義一個變量文件,經過vars_files引入:vars_files: ./templates/nginx_locations_vars.yml

# 模板文件
[root@tool-server nginx-deploy]# vim templates/nginx.conf.j2
 ...
 server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        # 這裏的內容動態生成
        {% for location in nginx_locations %}
        location {{location.path}} {
           proxy_pass {{location.proxy}};
        }
        {% endfor %}

        location / {
            root   html;
            index  index.html index.htm;
        }
 ...
# 獨立的自定義變量文件,用於填充模板文件中的變量
[root@tool-server nginx-deploy]# vim templates/nginx_locations_vars.yml

nginx_locations:
  - {"path": "/cns", "proxy": "http://192.168.40.202/cns"}
  - {"path": "/admin", "proxy": "http://192.168.40.202/admin"}

3. handlers

handlers和notify結合使用,由特定條件觸發,通常用於配置文件變動觸發服務重啓。在本例中咱們在配置文件變動時,經過notify定義了一個「reload nginx」的操做,而後在handlers部分定義「reload nginx」操做——經過shell模塊調用nginx的reload來從新加載配置。

4. 標籤

playbook文件中,若是隻想執行某一個或幾個任務,則能夠給任務打標籤,在運行的時候經過 -t 選擇帶指定標籤的任務執行,也能夠經過 --skip-tags 選擇不帶指定標籤的任務執行。好比在本例中,咱們在「update config」的task上加了「reload」的標籤,若是後面再修改配置,咱們只須要執行「update config」的task並觸發reload nginx就好了,能夠這麼執行playbook

[root@tool-server nginx-deploy]# ansible-playbook -t reload nginx_playbook.yml

5. when

能夠在task上添加when表示當某個條件達到了該任務才執行,如

tasks:
    - name: install nginx
      yum: name=nginx state=installed
    - name: update config for system6
      template: src=nginx.conf.j2 dest=/usr/local/nginx/conf/nginx.conf
      when: ansible_distribution_major_version == "6"   # 判斷系統版本,爲6才執行上面的template配置的文件

6. roles

roles就是將變量、文件、任務、模板及處理器放置在單獨的目錄中,並能夠在playbook中include的一種機制,通常用於主機構建服務的場景中,但也能夠是用於構建守護進程等場景。

roles的目錄結構,默認的roles目錄爲/etc/ansible/roles

roles:          # 全部的角色項目必須放在roles目錄下
  project:      # 具體的角色項目名稱,好比nginx、tomcat
    files:     # 用來存放由copy或script模塊調用的文件
    templates: # 用來存放jinjia2模板,template模塊會自動在此目錄中尋找jinjia2模板文件
    tasks:     # 此目錄應當包含一個main.yml文件,用於定義此角色的任務列表,此文件可使用include包含其它的位於此目錄的task文件。
      main.yml
    handlers:  # 此目錄應當包含一個main.yml文件,用於定義此角色中觸發條件時執行的動做
      main.yml
    vars:      # 此目錄應當包含一個main.yml文件,用於定義此角色用到的變量
      main.yml
    defaults:  # 此目錄應當包含一個main.yml文件,用於爲當前角色設定默認變量
      main.yml
    meta:      # 此目錄應當包含一個main.yml文件,用於定義此角色的特殊設定及其依賴關係
      main.yml

咱們將上面的例子經過roles改造一下

[root@tool-server ~]# cd /etc/ansible/roles/
[root@tool-server roles]# mkdir -p nginx/{tasks,vars,templates,handlers}
...#建立各目錄的mian.yml文件,並將對應的內容加入文件中

#最終目錄結構
[root@tool-server roles]# tree  .
.
└── nginx
    ├── handlers
    │   └── main.yml # 上例handlers部分的內容,直接 -name開頭,不須要再加 `handlers:`
    ├── tasks
    │   └── main.yml # tasks部份內容,直接-name開頭,不須要加tasks,能夠將各個task拆分爲多個文件,而後在main.yml中經過 `- include: install.yml` 形式的列表引入
    ├── templates
    │   └── main.yml # templates/nginx.conf.j2的內容
    └── vars
        └── main.yml # templates/nginx_locations_vars.yml的內容

5 directories, 4 files

最後,在playbook中經過roles引入,

[root@ansible roles]# vim nginx_playbook.yml
---
- hosts: nginx
  remote_user: root
  roles:
    - role: nginx # 指定角色名稱

roles將playbook的各個部分進行拆分組織,主要用於代碼複用度較高的場景。

總結

Ansible是功能強大但又很輕量級的自動化運維工具,基於SSH協議批量對遠程主機進行管理,不只可用於平常的服務維護,也可與Jenkins等CI/CD工具結合實現自動化部署。若是你須要在多於一臺服務器上作重複又稍顯複雜的操做,那麼建議你使用Ansible,這將極大提升你的操做效率,而且全部操做文檔化,更易維護與遷移。


歡迎關注做者公衆號:空山新雨的技術空間
微信公衆號

相關文章
相關標籤/搜索