ansible进阶03

管理任务执行

提权

  • ansible在进行远程管理时,推荐使用普通用户登录。
  • 普通用户在执行管理操作时,需要切换成root账号
[student@warktest inventory-review]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops           # ssh登录账号

[privilege_escalation]
become=True                  # 配置需要提权
become_method=sudo           # 提权方法为sudo
become_user=root             # 切换成root账号执行命令
become_ask_pass=False        # sudo执行命令时,不需交互输入密码

在play中单独设置提权

  • 例:
---
- name: Become the user "manager"
  hosts: webservers
  become: true     # 在play上提权
  tasks:
    - name: Show the user used by this play
      debug:
        var: ansible_user_id

- name: Do not use privilege escalation
  hosts: webservers
  become: false      # 这个play在执行时,不需要提权
  tasks:
    - name: Show the user used by this play
      debug:
        var: ansible_user_id

# 使用ansible.cfg中的配置
- name: Use privilege escalation based on defaults
  hosts: webservers
  tasks:
    - name: Show the user used by this play
      debug:
        var: ansible_user_id

在task中设置提权

  • 例:
---
- name: Play with two tasks, one uses privilege escalation
  hosts: all
  become: false          # play级别不提权
  tasks:
    - name: This task needs privileges
      yum:
        name: perl
        state: installed
      become: true       # 该task需要提权
      
    - name: This task does not need privileges
      shell: perl -v
      register: perlcheck
      failed_when: perlcheck.rc != 0

在block上设置提权

  • 可以把一组任务放到block中。
  • 在block级别设置需要或不需要提权。block中的所有任务都得到了修改。
- name: Deploy web services
  hosts: webservers
  become: false
  tasks:
    - block:
       - name: Ensure httpd is installed
         yum:
           name: httpd
           state: installed
       - name: Start and enable webserver
         service:
           name: httpd
           state: started
           enabled: yes
      become: true
      
   - name: Test website from itself, do not become
     uri:
       url: http://{{ ansible_host }}
       return_content: yes
     register: webpage
     failed_when: webpage.status != 200

在role角色中的提权

  • 为role中的任务提权有两个方法:
    • 在role中直接设置
    • 在调用role的playbook中设置(推荐)
- name: Example play with one role
  hosts: localhost
  roles:
    - role: role-name
      become: true

通过变量设置提权

  • 组变量
webservers:
  hosts:
    servera.lab.example.com:
    serverb.lab.example.com:
  vars:
    ansible_become: true
  • 主机变量
webservers:
 hosts:
   servera.lab.example.com:
     ansible_become: true
   serverb.lab.example.com:
  • play变量
---
- name: Example play using connection variables
  hosts: webservers
  vars:
    ansible_become: true
  tasks:
    - name: Play will use privilege escalation even if inventory says no
      yum:
        name: perl
        state: installed

控制任务执行

任务执行顺序

  • ansible总是执行roles中的task,然后再执行play中tasks中定义的任务,不管在playbook中的书写顺序是什么样的。
---
- name: Ensure Apache is deployed
  hosts: www1.example.com
  gather_facts: no
  tasks:
    - name: Open the firewall
      firewalld:
        service: http
        permanent: yes
        state: enabled
        
  roles:     # 虽然后书写的,但是比上面的tasks先运行
  - role: apache
import或include角色
  • 使用include_role模块,可以动态引入角色。
  • 使用import_role模块,可以静态导入角色。
  • import_role在playbook执行之前进行导入,导入完成后进行语法检查。
  • include_role在playbook执行到该角色时,才导入它。
  • include_role示例:
---
- name: Executing a role as a task
  hosts: remote.example.com
  tasks:
    - name: A normal task
      debug:
        msg: 'first task'
    - name: A task to include role2 here
      include_role:
        name: role2
    - name: Another normal task
      debug:
        msg: 'second task'
定义pre或post任务
  • pre_tasks定义在role之前执行的任务

  • post_tasks定义在tasks这后执行的任务

  • 例:

---
- name: Deploying New Application Version
  hosts: webservers
  pre_tasks:
    # Stop monitoring the web server to avoid sending false alarms
    # while the service is updating.
    - name: Disabling Nagios for this host
      nagios:
        action: disable_alerts
        host: "{{ inventory_hostname }}"
        services: http
      delegate_to: nagios-srv
      
  roles:
    - role: deploy-content
    
  tasks:
    - name: Restarting memcached
      service:
        name: memcached
        status: restarted
      notify: Notifying the support team

    # Confirm that the application is fully operational
    # after the update.
    - name: Validating the new deployment
      uri:
        url: "http://{{ inventory_hostname }}/healthz"
        return_content: yes
      register: result
      failed_when: "'OK' not in result.content"

  post_tasks:
    - name: Enabling Nagios for this host
      nagios:
        action: enable_alerts
        host: "{{ inventory_hostname }}"
        services: http
      delegate_to: nagios-srv

  handlers:
    # Send a message to the support team through Slack
    # every time the memcached service is restarted.
    - name: Notifying the support team
      slack:
        token: G922VJP25/D923DW937/3Ffe373sfhRE6y52Fg3rvf5GlK
        msg: 'Memcached on {{ inventory_hostname }} restarted'
      delegate_to: localhost
      become: false
  • playbook在执行的时候,有固定的顺序:

    1. pre_tasks
    2. pre_tasks触发的handlers中的任务
    3. roles
    4. tasks
    5. roles或tasks触发的handlers中的任务
    6. post_tasks
    7. post_tasks触发的handlers中的任务
  • roles和tasks中的任务全部执行完,才会执行它们notify通知的、handlers中的任务。如果希望handlers中的任务立即执行,可以使用meta模块:

---
- name: Updating the application configuration and cache
  hosts: app_servers
  tasks:
    - name: Deploying the configuration file
      template:
        src: api-server.cfg.j2
        dest: /etc/api-server.cfg
      notify: Restart api server
      
    - name: Running all notified handlers
      meta: flush_handlers   # 立即执行handlers中被notify的任务
      
    - name: Asking the API server to rebuild its internal cache
      uri:
        url: "https://{{ inventory_hostname }}/rest/api/2/cache/"
        method: POST
        force_basic_auth: yes
        user: admin
        password: redhat
        body_format: json
        body:
          type: data
          delay: 0
        status_code: 201

  handlers:
    - name: Restart api server
      service:
        name: api-server
        state: restarted
        enabled: yes
侦听handlers
  • 侦听handlers的目的是任务中notify时,handlers中的多个任务被执行。
  • 例:
---
- name: Testing the listen directive
  hosts: localhost
  gather_facts: no
  become: no
  tasks:
    - debug:
        msg: Trigerring the handlers
      notify: My handlers  # 触发执行handlers中的My handlers任务
      changed_when: true

handlers:
  # Listening to the "My handlers" event
  - name: Listening to a notification
    debug:
      msg: First handler was notified
    listen: My handlers # 侦听My handlers,如果它运行,这个任务也运行
    
  # As an example, this handler is also triggered because
  # its name matches the notification, but no two handlers
  # can have the same name.
  - name: My handlers
    debug:
      msg: Second handler was notified
[student@warktest httpd_alias]$ cat  install_httpd_alias.yml 
---
- name: Add apache alias
  hosts: prod
  become: yes
  tasks:
    - name: check if directory exists
      stat:
        path: /etc/httpd
      register: httpd_dir

    - name: create directory if ti doesn't exist
      file: 
        path: /etc/httpd
        state: directory
      when: not httpd_dir.stat.exists

    - name: copy alias file
      copy:
        src: alias.conf
        dest: /etc/httpd/conf.d
      notify: install and restart httpd     #通告的后面listen的任务

  handlers:
  - name: check if httpd is installed
    command: "rpm -q httpd"
    register: httpd_installed
    failed_when: false
    changed_when: false
    listen: install and restart httpd

  - name: install httpd
    yum:
      name: httpd
      state: present
    when: httpd_installed.rc != 0
    listen: install and restart httpd

  - name: restart httpd
    service:
      name: httpd
      state: restarted
    listen: install and restart httpd

主机执行顺序控制

  • 默认情况下,如果playbook的任务需要在很多主机上执行,则按主机清单中的列出顺序执行。
  • 通过关键字order,可以改变执行顺序。
---
- name: Testing host order
  hosts: web_servers
  order: sorted    # 按字母顺序排序
  tasks:
    - name: Creating a test file in /tmp
      copy:
      content: 'This is a sample file'
      dest: /tmp/test.out

order取值:

  • inventory:默认值。按主机清单中的书写顺序。
  • reverse_inventory:按主机清单中的书写的相反顺序。
  • sorted:按字母顺序。
  • reverse_sorted:按字母,反序。
  • shuffle:随机。

运行选择的任务

给资源打标签

  • 当使用非常大的、或很复杂的playbook时,有可能只希望运行其中的一部分play或tasks。

  • 可以给资源通过tags打标签,将来实现运行一部分资源的功能。

  • 在运行playbook时,可以通过--tags选项来指定相应的play或tasks。

  • 可以为以下资源打标签:

  • 标记任务。这是最常见的方式

 - name: Install application  
  hosts: dbservers
  vars:
    packages:
      - postfix
      - mariadb-server
  tasks:
    - name: Ensure that packages are installed
      yum:
        name: "{{ packages }}"
        state: installed
      tags:
        - install
  • 为Play打标签。
- name: Setup web services
 hosts: webservers
 tags:
   - setup
 tasks:
   - name: Install http daemon
     yum:
       name: httpd
       state: present
  • include_tasks导入的任务设置全局标签
tasks:
  - name: Include common web services tasks
    include_tasks: common.yml
    tags:
      - webproxy
      - webserver
  • 在roles部分为角色打标签。如,为databases角色打两个标签:
roles:
  - { role: databases, tags: ['production', 'staging'] }
  • 给block的任务打标签。
---
- name: Setup httpd service

  tasks:
    - name: Notify start of process
      debug:
        msg: Beginning httpd setup
        
    - block:
        - name: Ensure httpd packages are installed
         yum:
           name:
             - httpd
             - php
             - git
             - php-mysqlnd
            state: present

        - name: Ensure SELinux allows httpd connections to a remote database
          seboolean:
            name: httpd_can_network_connect_db
            state: true
            persistent: true
            
        - name: Ensure httpd service is started and enabled
          service:
            name: httpd
            state: started
            enabled: true
      tags:
        - webserver
    • 管理打标签的资源

  • 在执行playbook时,可以通过--tags指定具有哪些标签的资源需要执行。

  • 在执行playbook时,可以通过--skip-tags指定具有哪些标签的资源需要跳过,不执行。

# 执行具有webserver标签的资源
[user@demo ~]$ ansible-playbook main.yml --tags webserver

# 跳过具有webserver标签的资源
[user@demo ~]$ ansible-playbook main.yml --skip-tags webserver
  • 执行任务时,可以指定多个标签
# 执行拥有install或setup标签的资源
[user@demo ~]$ ansible-playbook main.yml --tags install,setup
  • 通过--list-tags列出playbook中的标签资源。
[student@demo examples]$ ansible-playbook playbook.yml --list-tags
playbook: playbook.yml
 play #1 (webservers): Setup web services TAGS: [setup]
 TASK TAGS: [setup]
 play #2 (webservers): Teardown web services TAGS: [teardown]
 TASK TAGS: [teardown]

特殊的标签

  • always标签。当为资源打上always标签后,即使执行playbook时,在--tags中没有提定它,该资源也会执行。如果需要跳过always标签,可以使用--skip-tags always
  • never标签。作用与always相反。当为资源打上never标签后,执行playbook时,该资源不会执行。如果需要执行never标签对应的资源,可以使用--tags never
  • tagged标签。只要资源打上了标签,就属于tagged。
  • untagged标签。没有打过标签的资源,属于untagged。
  • all标签。包括所有的任务,不管任务是否打过标签。

优化执行速度

优化playbook

优化架构
  • 使用最新的ansible版本。
  • 控制节点离被管理节点“近一些”。
禁用facts
  • ansible默认会运行一个收集facts变量的任务。
  • 如果不需要这些变量,禁用该任务,可以提升速度。
[student@warktest myansible]$ cat mytest.yml
---
- name: test play
  hosts: servera
  tasks:
    - name: display hello
      debug:
        msg: "Hello World"
[student@warktest myansible]$ time ansible-playbook mytest.yml
... ...
real    0m2.060s
user    0m0.955s
sys     0m0.207s

[student@warktest myansible]$ cat mytest.yml
---
- name: test play
  hosts: servera
  gather_facts: False    # 不收集facts变量
  tasks:
    - name: display hello
      debug:
        msg: "Hello World"
[student@warktest myansible]$ time ansible-playbook mytest.ym
... ...
real    0m0.712s
user    0m0.607s
sys     0m0.102s
  • 如果在其他任务中需要facts变量,就不能关闭它了。或者是使用其他变量替代。如ansible_facts['hostname']ansible_hostnameinventory_hostname替代。
[student@warktest myansible]$ cat mytest.yml
---
- name: test play
  hosts: servera
  gather_facts: False
  tasks:
    - name: display hello
      debug:
        msg: "Hello World from {{ansible_hostname}}"
# 运行playbook报错。因为ansible_hostname是facts变量,收集facts变量已经被禁用了
[student@warktest myansible]$ ansible-playbook mytest.yml

# 可以使用inventory_hostname这个主机清单变量替换
[student@warktest myansible]$ cat mytest.yml
---
- name: test play
  hosts: servera
  gather_facts: False
  tasks:
    - name: display hello
      debug:
        msg: "Hello World from {{inventory_hostname}}"
[student@warktest myansible]$ ansible-playbook mytest.yml
增加并发数
  • ansible在执行任务时,默认每5台主机一组。该组执行完一项任务后,第2组再执行、第3组再执行,依次类推,直到所有主机执行完任务。然后,再进入下一个任务的执行。

  • 可以在运行playbook时,通过-f选项指定并发数

  • 也可以在配置文件中修改:

[user@demo ~]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops
forks=100
避免使用循环安装软件
  • yum模块支持同时安装多个包,不需要使用循环
---
- name: Install the packages on the web servers
  hosts: web_servers
  become: True
  gather_facts: False
  tasks:
    - name: Ensure the packages are installed
      yum:
        name:
          - httpd
          - mod_ssl
          - httpd-tools
          - mariadb-server
          - mariadb
          - php
          - php-mysqlnd
       state: present
       
# 以上playbook相当于执行了以下命令:
[root@demo ~]# yum install httpd mod_ssl httpd-tools \
> mariadb-server mariadb php php-mysqlnd
  • 注意, 不是所有的模块都支持统一设置。比如启动服务,只能使用循环:
- name: Starting the services on the web servers
  hosts: web_servers
  become: True
  gather_facts: False
  tasks:
    - name: Ensure the services are started
      service:
        name: "{{ item }}"
        state: started
        enabled: yes
      loop:
        - httpd
        - mariadb
高效上传文件
  • copy模块可以上传文件

  • 如果有大量文件,经常上传,使用 synchronize 将会更有效率,它的底层使用的是rsync。

---
- name: Deploy the web content on the web servers
 hosts: web_servers
 become: True
 gather_facts: False
 tasks:
 - name: Ensure web content is updated
   synchronize:
     src: web_content/
     dest: /var/www/html
使用template模块
  • 当一个文件中有很多内容需要修改时,不建议使用lineinfile或者replace模块。

  • 建议使用template模块结合jinja2模板,修改文件。

---
- name: Configure the Apache HTTP Server
 hosts: web_servers
 become: True
 gather_facts: False
 tasks:
   - name: Ensure proper configuration of the Apache HTTP Server
     lineinfile:
       dest: /etc/httpd/conf/httpd.conf
       regexp: "{{ item.regexp }}"
       line: "{{ item.line }}"
       state: present
    loop:
      - regexp: '^Listen 80$'
        line: 'Listen 8181'
      - regexp: '^ServerAdmin root@localhost'
        line: 'ServerAdmin support@example.com'
      - regexp: '^DocumentRoot "/var/www/html"'
        line: 'DocumentRoot "/var/www/web"'
      - regexp: '^<Directory "/var/www/html">'
        line: '<Directory "/var/www/web">'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值