iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 29
0
Kubernetes

在地端建置Angular+ASP.NET Core的DevOps環境系列 第 29

day29_ansible07_其他_include,limit,tags,changed_when,failed_when,除錯

前言

今天是ansible相關基礎的最後一篇啦,
也是蠻重要蠻基礎的,當然還有很多沒寫到,
但學過基礎後,未來遇到沒學過的再去查官網手冊應該就很好上手啦

include

https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_includes.html

include跟import的差異

include跟import我也分不清楚,官網是寫英文

  • All import* statements are pre-processed at the time playbooks are parsed.
  • All include* statements are processed as they are encountered during the execution of the playbook.

剛剛google到中文的文章
參考:
ansible中的include,include_tasks和import_tasks的差別
http://drmingdrmer.github.io/tech/devops/2018/02/03/ansible-import-include.html

tasks:
- import_tasks: common_tasks.yml # 會去跑common_tasks.yml裡面的task
  vars:
    wp_user: timmy # 可以傳參數進去

# or
- include_tasks: common_tasks.yml

# 也可以在handlers:裡使用
handlers:
- include_tasks: more_handlers.yml
# or
- import_tasks: more_handlers.yml

===

來介紹一些比較冷門的參數

ansible-playbook的「--limit」,限制只跑該host

https://docs.ansible.com/ansible/latest/user_guide/intro_patterns.html

$ ansible-playbook xxx.yml --limit webserver01 # 只跑webserver01
$ ansible-playbook site.yml --limit @retry_hosts.txt # 要跑的清單可寫在檔案

在tasks裡面加「--tags」

tasks:
    - yum:
        name: "{{ item }}"
        state: installed
      loop:
         - httpd
         - memcached
      tags:
         - packages # 幫這個task加tag: packages

    - template:
        src: templates/src.j2
        dest: /etc/foo.conf
      tags:
         - configuration
         - packages # 同樣的tag可以下給很多tasks        

加完後有什麼神奇功效呢?

# 只跑tags為「configuation、packages」的tasks
$ ansible-playbook example.yml --tags "configuration,packages"
$ ansible-playbook example.yml --list-tasks # 列出tasks
$ ansible-playbook example.yml --list-tags # 列出tags
# 不跑tags為「packages」裡的tasks
$ ansible-playbook example.yml --skip-tags "packages"
  • role、import_role、import_tasks都可以加tags
roles:
  - role: webserver
    vars:
      port: 5000
    tags: [ 'web', 'foo' ]

- import_role:
    name: myrole
  tags: [web,foo]


- import_tasks: foo.yml
  tags: [web,foo]

可以用block:把tasks包起來,對block:下tags

  • 每個tasks都下tags不是很麻煩嗎?
- block:
    - name: First task to run
    ...
    - name: Second task to run
    ...
  tags:
    - mytag
    - always # 特殊的tag,一定都會跑,除了用--skip-tags always排除。類似 hosts:all


tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]
# never跟debug,預設不跑這些tasks,只有特別標記要跑時才會跑
# 還有3個特殊tag => tagged、untagged、all
# tagged : 只標記有下過tag的
# untagged : 只標記有沒被下過tag的
# all : all tasks 預設都是 --tags all

===

(idempotence_changed)

when,failed_when

changed_when

https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html#overriding-the-changed-result

當shell、command或其他modules的task執行時,
該modules通常會自行判斷「是否有影響機器狀態」來回報「已更改」狀態(changed status)

  • changed_when: False
    有時你會根據return code或output知道這些task沒有進行任何更改,
    並希望override「changed」result,使其不要出現在report output或不要去觸發handlers
tasks:
  - shell: /usr/bin/billybass --mode="take me to the river"
    register: bass_result
    changed_when: "bass_result.rc != 2" # 當 != 2,才是有變更的

		- name: get active sites
  			shell: ls -1 /etc/nginx/sites-enabled
  			register: active
  			changed_when: "active.stdout_lines != sites.keys()" 
            # 當判斷式為true,才是有changed


  # this will never report 'changed' status
  - shell: wall 'beep'
    changed_when: False 

===

failed_when

https://docs.ansible.com/ansible/latest/user_guide/playbooks_error_handling.html#controlling-what-defines-failure
個人覺得這蠻重要的
很像

  • try{...}cache{要接的例外}
  • failed_when: 要接的例外
    範例:
# Ansible 提供的方式
- name: Fail task when the command error output prints FAILED
  command: /usr/bin/example-command -x -y -z # 1、故意打錯指令
  register: command_result # 2、指令的結果存到command_result
  failed_when: "'FAILED' in command_result.stderr" # 3、去抓例外
# return code:
- name: Fail task when both files are identical
  raw: diff foo/file1 bar/file2
  register: diff_cmd
  failed_when: diff_cmd.rc == 0 or diff_cmd.rc >= 2 # 用return code判斷
# 當command failed時,就印出FAILED
- name: this command prints FAILED when it fails
  command: /usr/bin/example-command -x -y -z
  register: command_result
  ignore_errors: True
# 如果前一個指令沒成功,就發msg: "the command failed"
- name: fail the play if the previous command did not succeed
  fail:
    msg: "the command failed"
  when: "'FAILED' in command_result.stderr"

===

再來來介紹一些除錯可能會用到的東西

Start and Step

https://docs.ansible.com/ansible/latest/user_guide/playbooks_startnstep.html

  • Start-at-task
    從某個task開始執行
$ ansible-playbook playbook.yml --start-at-task="install packages"
  • Step
    一步一步跑,每個task都會停下來
$ ansible-playbook playbook.yml --step
Perform task: configure ssh (y/n/c):
# y 執行task
# n 跳過這個task
# c 執行所有剩下的tasks

===

Check Mode ("Dry Run")

https://docs.ansible.com/ansible/latest/user_guide/playbooks_checkmode.html

--check

不會對遠端系統做任何變更
所有支援check mode的modules,會回報預測會做的更改
不支援check mode的modeules,不會執行,也不會回報

  • 在ansible-playbook下--check
$ ansible-playbook foo.yml --check

  • 寫在playbook
tasks:
  - name: this task will make changes to the system even in check mode
    command: /something/to/run --even-in-check-mode
    check_mode: no # run in normal mode

  - name: this task will always run under checkmode and not change the system
    lineinfile:
        line: "important config"
        dest: /path/to/myconfig.conf
        state: present
    check_mode: yes # run in check mode
    ignore_errors: "{{ ansible_check_mode }}" # 在check mode時就會自動忽略error    

--diff

會有大量output,最好一次只跑一個host

  • 單獨使用:
    報告所做的更改

  • --diff與--check一起使用:
    執告已經進行的更改

  • 下指令

$ ansible-playbook foo.yml --check --diff --limit foo.example.com
  • 寫在playbook
tasks:
  - name: this task will not report a diff when the file changes
    template:
      src: secret.conf.j2
      dest: /etc/secret.conf
      owner: root
      group: root
      mode: '0600'
    diff: no

===

debug - Print statements during execution

https://docs.ansible.com/ansible/latest/modules/debug_module.html

Parameters

  • msg : 要輸出的message,預設是 Hello world!
  • var : 輸出到變數,不能跟msg共用
  • verbosity : 設一個等級,預設0,全部顯示(數字愈高愈不會顯示到)
    例如verbosity=3,要下-vvv才看得到(但-vvv會多很多你不需要看到的訊息)
# Example that prints the loopback address and gateway for each host
# 沒條件,一定會跑
- debug:
    msg: "System {{ inventory_hostname }} has uuid {{ ansible_product_uuid }}"
# 當ansible_default_ipv4.gateway is defined才輸出msg
- debug:
    msg: "System {{ inventory_hostname }} has gateway {{ ansible_default_ipv4.gateway }}"
  when: ansible_default_ipv4.gateway is defined

- shell: /usr/bin/uptime
  register: result
# 如果不清楚 register: result 的資料型態,可以利用這招,把變數印出來看
- debug:
    var: result  # 把result,放到debug的var
    verbosity: 2

- name: Display all variables/facts known for a host
  debug:
    var: hostvars[inventory_hostname] 
    # 利用debug顯示變數hostvars[inventory_hostname]
    verbosity: 4

會出現紅字

- debug: msg="something wrong !!!"
  failed_when: check_point is not defined
TASK [debug] *******
fatal: [hostname]: FAILED! => {
  ...
}

--syntax-check

$ ansible-playbook -v -syntax-check playbook.yml

明天用一個role做ansible的總結,
後天PO參賽心得喔~


上一篇
day28_ansible06_variables_with_dict,group_vars,vars_files
下一篇
dayXX_[end]_呼~終於完賽了~純聊天~
系列文
在地端建置Angular+ASP.NET Core的DevOps環境31

尚未有邦友留言

立即登入留言