Ansible16:Playbook高級用法

本地執行

若是但願在控制主機本地運行一個特定的任務,可使用local_action語句。ios

假設咱們須要配置的遠程主機剛剛啓動,若是咱們直接運行playbook,可能會由於sshd服務還沒有開始監聽而致使失敗,咱們能夠在控制主機上使用以下示例來等待被控端sshd端口監聽:web

- name: wait for ssh server to be running
  wait_for
      port: 22 
      host: "{{ inventory_hostname }}" 
      search_regex: OpenSSH
  connection: local

任務委託

在有些時候,咱們但願運行與選定的主機或主機組相關聯的task,可是這個task又不須要在選定的主機或主機組上執行,而須要在另外一臺服務器上執行。shell

這種特性適用於如下場景:數據庫

  • 在告警系統中啓用基於主機的告警
  • 向負載均衡器中添加或移除一臺主機
  • 在dns上添加或修改針對某個主機的解析
  • 在存儲節點上建立一個存儲以用於主機掛載
  • 使用一個外部程序來檢測主機上的服務是否正常

可使用delegate_to語句來在另外一臺主機上運行task:服務器

- name: enable alerts for web servers
  hosts: webservers
  tasks:
    - name: enable alerts
      nagios: action=enable_alerts service=web host="{{ inventory_hostname }}"
      delegate_to: nagios.example.com

若是delegate_to: 127.0.0.1的時候,等價於local_actionapp

任務暫停

有些狀況下,一些任務的運行須要等待一些狀態的恢復,好比某一臺主機或者應用剛剛重啓,咱們須要須要等待它上面的某個端口開啓,此時就須要將正在運行的任務暫停,直到其狀態知足要求。負載均衡

Ansible提供了wait_for模塊以實現任務暫停的需求ssh

wait_for模塊經常使用參數:命令行

  • connect_timeout:在下一個任務執行以前等待鏈接的超時時間
  • delay:等待一個端口或者文件或者鏈接到指定的狀態時,默認超時時間爲300秒,在這等待的300s的時間裏,wait_for模塊會一直輪詢指定的對象是否到達指定的狀態,delay即爲多長時間輪詢一次狀態。
  • host:wait_for模塊等待的主機的地址,默認爲127.0.0.1
  • port:wait_for模塊待待的主機的端口
  • path:文件路徑,只有當這個文件存在時,下一任務纔開始執行,即等待該文件建立完成
  • state:等待的狀態,即等待的文件或端口或者鏈接狀態達到指定的狀態時,下一個任務開始執行。當等的對象爲端口時,狀態有started,stoped,即端口已經監聽或者端口已經關閉;當等待的對象爲文件時,狀態有present或者started,absent,即文件已建立或者刪除;當等待的對象爲一個鏈接時,狀態有drained,即鏈接已創建。默認爲started
  • timeout:wait_for的等待的超時時間,默認爲300秒

示例:

#等待8080端口已正常監聽,纔開始下一個任務,直到超時
- wait_for: 
    port: 8080 
    state: started  
    
#等待8000端口正常監聽,每隔10s檢查一次,直至等待超時
- wait_for: 
    port: 8000 
    delay: 10 
    
#等待8000端口直至有鏈接創建
- wait_for: 
    host: 0.0.0.0 
    port: 8000 
    delay: 10 
    state: drained
    
#等待8000端口有鏈接創建,若是鏈接來自10.2.1.2或者10.2.1.3,則忽略。
- wait_for: 
    host: 0.0.0.0 
    port: 8000 
    state: drained 
    exclude_hosts: 10.2.1.2,10.2.1.3 
    
#等待/tmp/foo文件已建立    
- wait_for: 
    path: /tmp/foo 

#等待/tmp/foo文件已建立,並且該文件中須要包含completed字符串    
- wait_for: 
    path: /tmp/foo 
    search_regex: completed 

#等待/var/lock/file.lock被刪除    
- wait_for: 
    path: /var/lock/file.lock 
    state: absent 
    
#等待指定的進程被銷燬
- wait_for: 
    path: /proc/3466/status 
    state: absent 
    
#等待openssh啓動,10s檢查一次
- wait_for: 
    port: 22 
    host: "{{ ansible_ssh_host | default(inventory_hostname) }}" search_regex: OpenSSH 
    delay: 10

滾動執行

默認狀況下,ansible會並行的在全部選定的主機或主機組上執行每個task,但有的時候,咱們會但願可以逐臺運行。最典型的例子就是對負載均衡器後面的應用服務器進行更新時。一般來說,咱們會將應用服務器逐臺從負載均衡器上摘除,更新,而後再添加回去。咱們能夠在play中使用serial語句來告訴ansible限制並行執行play的主機數量。

下面是一個在amazon EC2的負載均衡器中移除主機,更新軟件包,再添加回負載均衡的配置示例:

- name: upgrade pkgs on servers behind load balancer
  hosts: myhosts
  serial: 1
  tasks:
    - name: get the ec2 instance id and elastic load balancer id
      ec2_facts:

    - name: take the host out of the elastic load balancer id
      local_action: ec2_elb
      args:
        instance_id: "{{ ansible_ec2_instance_id }}"
        state: absent

    - name: upgrade pkgs
      apt: 
          update_cache: yes 
          upgrade: yes

    - name: put the host back n the elastic load balancer
      local_action: ec2_elb
      args:
        instance_id: "{{ ansible_ec2_instance_id }}"
        state: present
        ec2_elbs: "{{ items }}"
      with_items: ec2_elbs

在上述示例中,serial的值爲1,即表示在某一個時間段內,play只在一臺主機上執行。若是爲2,則同時有2臺主機運行play。

通常來說,當task失敗時,ansible會中止執行失敗的那臺主機上的任務,可是繼續對其餘 主機執行。在負載均衡的場景中,咱們會更但願ansible在全部主機執行失敗以前就讓play中止,不然極可能會面臨全部主機都從負載均衡器上摘除而且都執行失敗致使服務不可用的場景。這個時候,咱們可使用serial語句配合max_fail_percentage語句使用。max_fail_percentage表示當最大失敗主機的比例達到多少時,ansible就讓整個play失敗。示例以下:

- name: upgrade pkgs on fservers behind load balancer
  hosts: myhosts
  serial: 1
  max_fail_percentage: 25
  tasks:
    ......

假如負載均衡後面有4臺主機,而且有一臺主機執行失敗,這時ansible還會繼續運行,要讓Play中止運行,則必須超過25%,因此若是想一臺失敗就中止執行,咱們能夠將max_fail_percentage的值設爲24。若是咱們但願只要有執行失敗,就放棄執行,咱們能夠將max_fail_percentage的值設爲0。

只執行一次

某些時候,咱們但願某個task只執行一次,即便它被綁定到了多個主機上。例如在一個負載均衡器後面有多臺應用服務器,咱們但願執行一個數據庫遷移,只須要在一個應用服務器上執行操做便可。

可使用run_once語句來處理:

- name: run the database migrateions
  command: /opt/run_migrateions
  run_once: true

還能夠與local_action配合使用,以下:

- name: run the task locally, only once
  command: /opt/my-custom-command
  connection: local
  run_once: true

還能夠與delegate_to配合使用,讓這個只執行一次的任務在指定的機器上運行:

- name: run the task locally, only once
  command: /opt/my-custom-command
  run_once: true
  delegate_to: app.a1-61-105.dev.unp

設置環境變量

咱們在命令行下執行某些命令的時候,這些命令可能會須要依賴環境變量。好比在安裝某些包的時候,可能須要經過代理才能完成完裝。或者某個腳本可能須要調用某個環境變量才能完成運行。

ansible 支持經過environment關鍵字來定義一些環境變量。

在以下場景中可能須要用到環境變量:

  • 運行shell的時候,須要設置path變量
  • 須要加載一些庫,這些庫不在系統的標準庫路徑當中

下面是一個簡單示例:

---
- name: upload a remote file to aws s3
  hosts: test
  tasks:
    - name: install pip
      yum:
        name: python-pip
        state: installed
    
    - name: install the aws tools
      pip:
        name: awscli
        state: present
    
    - name upload file to s3
      shell aws s3 put-object --bucket=my-test-bucket --key={{ ansible_hostname }}/fstab --body=/etc/fstab --region=eu-west-1
      environment:
        AWS_ACCESS_KEY_ID: xxxxxx
        AWS_SECRET_ACCESS_KEY: xxxxxx

事實上,environment也能夠存儲在變量當中:

- hosts: all
  remote_user: root
  vars:
    proxy_env:
      http_proxy: http://proxy.example.com:8080
      https_proxy: http://proxy.bos.example.com:8080
  tasks:
    - apt: name=cobbler state=installed
      environment: proxy_env

交互式提示

在少數狀況下,ansible任務運行的過程當中須要用戶輸入一些數據,這些數據要麼比較祕密不方便,或者數據是動態的,不一樣的用戶有不一樣的需求,好比輸入用戶本身的帳戶和密碼或者輸入不一樣的版本號會觸發不一樣的後續操做等。ansible的vars_prompt關鍵字就是用來處理上述這種與用戶交互的狀況的。

- hosts: all
   remote_user: root
   vars_prompt:
      - name: share_user
        prompt: "what is your network username?"
        private: yes
 
      - name: share_pass
        prompt: "what is your network password"
        private: yes
        
    tasks:
      - debug:
          var: share_user
      - debug:
          var: share_pass

vars_prompt經常使用選項說明:

  • private: 默認爲yes,表示用戶輸入的值在命令行不可見
  • default:定義默認值,當用戶未輸入時則使用默認值
  • confirm:若是設置爲yes,則會要求用戶輸入兩次,適合輸入密碼的狀況
相關文章
相關標籤/搜索