• 17.RedHat认证-Ansible自动化运维(下)


    17.RedHat认证-Ansible自动化运维(下)

    这个章节讲ansible的变量,包括变量的定义、变量的规则、变量范围、变量优先级、变量练习等。

    以及对于tasks的控制,主要有loop循环作业、条件判断等

    变量

    介绍

    Ansible支持变量功能,能将value存储到变量中,这样就能在Ansible项目中重复使用,这样就可以简化项目的创建和维护,减少错误率。

    变量提供了一个变量提供了一种方便的方法来管理ansible项目中给定环境的动态值。 变量可以是要创建的用户,要安装的包,要启动的服务,要删除的文件,要从互联网下载的文件等等

    规则

    变量由必须以字母开头的字符串组成,并且只能包含字母,数字和下划线组成。

    无效变量有效变量
    web serverweb_server
    remote.fileremote_file
    1st filefile_1或file1
    remoteserver$1remote_server_1或remote_server1

    定义变量

    变量几乎可以定义在ansible项目中的任意位置。然而这有三种基本的范围级别:
    1.Globe scope:从命令行设置变量或Ansible配置文件中设置变量
    2.play scope: 在play和相关结构中设置变量
    3.host scope: 通过inventory在主机组或单个主机中设置变量,fact采集变量或者register

    如果在一个级别上定义了名字相同的两个变量,会选择先定义的那个。 在inventory中定义的变量会被
    playbook中定义的覆盖,playbook中定义的变量会被命令行定义的变量覆盖。
    http://docs.ansible.com/ansible/playbooks_variables.html 变量说明详细文档

    playbook中定义变量

    当写playbook时,管理员可以在task中使用它们自己定义的变量。例如一个叫做web_package的变量可以
    被被定义为httpd,然后使用yum模块来调用这个变量,进而安装httpd包

    声明定义

    playbook变量可以通过多种方式进行定义。一个最简单的方式就是在playbook的开头通过vars定义,例如

    在这里插入图片描述

    文件定义

    也可以在playbook中通过指定外部文件作为变量文件

    在这里插入图片描述

    主机变量和组变量

    inventory变量直接应用到被管理主机有两种方式:
    1.应用到特定主机
    2.应用到特定组
    主机变量优先级高于组变量,但是在playbook中定义的主机变量优于这两种方式

    变量定义

    在这里插入图片描述

    这种定义变量的方式让inventory的管理更复杂了。因为在同一个文件中包含了主机和变量,并且使用了不同的语法。

    将变量的定义放在一个文件中,例如放在当前的目录下的var目录下的vars.yml

    [student@workstation playbook-review]$ vim test.yml 
    - name: this is a var test
      hosts: all
      vars_files:
        - var/vars.yml  # 相对路径,推荐写相对路径
      tasks:
        - name: debug module test
          debug:
            msg: "{{ user  }} is very handsome ,but {{ user  }} is very pool"
            
    # 在var目录下定义了user变量
    [student@workstation playbook-review]$ cd var/
    [student@workstation var]$ cat vars.yml 
     user: ztf
    
    # 执行playbook 
    [student@workstation playbook-review]$ ansible-playbook test.yml  
    

    上面这种定义变量的方式让inventory的管理更复杂了。因为在同一个文件中包含了主机和变量,并且使用了不同的语法。

    使用group_vars和host_vars目录

    其实大多数生产环境里,尽最大可能将变量和inventory文件以及playbook文件分开来写,看着清爽。

    不要混在一起,非常不利于维护和阅读

    使用这两个目录就可以解决上面的问题,解耦文件,生产环境中用的多。

    很简单,在你的playbook目录下创建两个这样的目录,分别是 group_varshost_vars目录

    记住,文件名强制必须一样,不能改变。

    然后就很简单了,如果你是针对主机组设置变量,就在group_vars目录下创建一个主机组名称相同的文件。

    举个例子,假设你的inventory文件里有一个主机组 production,里面有两个主机 servera serverb

    [production]

    servera

    serverb

    然后你就在group_vars目录下创建同名的主机组的文件 就叫 production,然后在这个文件里定义的变量都会应用在这个production主机组里

    其次,如果你是针对主机设置变量,就在host_vars目录下创建一个主机名称相同的文件。方法如上。

    练习playbook变量

    [kiosk@foundation0 ~]$ ssh workstation
    
    [student@workstation ~]$ lab data-variables start
    
    [student@workstation ~]$ cd data-variables/
    
    [student@workstation data-variables]$ cat inventory 
    [webserver]
    servera.lab.example.com
    
    [student@workstation data-variables]$ cat ansible.cfg 
    [defaults]
    inventory   = inventory
    remote_user = devops
    
    [privilege_escalation]
    become      = true
    
    
    # 创建playbook 
    [student@workstation data-variables]$ vim playbook.yml
    [student@workstation data-variables]$ cat playbook.yml
    --------------------------- 内容如下 ----------------------------------------------------------
    ---
    - name: Deploy and start Apache HTTPD service
      hosts: webserver
      vars:
        web_pkg: httpd
        firewall_pkg: firewalld
        web_service: httpd
        firewall_service: firewalld
        python_pkg: python3-PyMySQL
        rule: http
    
      tasks:
        - name: Required packages are installed and up to date
          yum:
            name:
              - "{{ web_pkg }}"
              - "{{ firewall_pkg }}"
              - "{{ python_pkg }}"
            state: latest
       
        - name: The {{ firewall_service }} service is started and enabled
          service:
            name: "{{ firewall_service }}"
            enabled: true
            state: started
    
        - name: The {{ web_service }} service is started and enabled
          service:
            name: "{{ web_service }}"
            enabled: true
            state: started
    
        - name: Web content is in place
          copy:
            content: "Example web content"
            dest: /var/www/html/index.html
    
        - name: The firewall port for {{ rule }} is open
          firewalld:
            service: "{{ rule }}"
            permanent: true
            immediate: true
            state: enabled
    
    - name: second play Verify the Apache service
      hosts: localhost
      become: false
      tasks:
        - name: Ensure the webserver is reachable
          uri:
            url: http://servera.lab.example.com
            status_code: 200
    -------------------------------------------------------------------------------------
    # 运行playbook,结果正确
    [student@workstation data-variables]$ ansible-playbook playbook.yml
    
    
    ------------------------------ 【警戒线】 -------------------------------
    
    #【注意】在这个例子中,定义的变量是在playbook文件里,我们运用之前所学知识,将变量定义在外部的单独文件里。
    [student@workstation data-variables]$ mkdir variables
    [student@workstation data-variables]$ cd variables/
    [student@workstation variables]$ vim web.yml
    -------------------------------------------------------
    web_pkg: httpd
    firewall_pkg: firewalld
    web_service: httpd
    firewall_service: firewalld
    python_pkg: python3-PyMySQL
    rule: http
    -------------------------------------------------------
    # 修改playbook.yml
    [student@workstation data-variables]$ vim playbook.yml 
      vars_files:
        - variables/web.yml
    
    # 运行效果正确。
    [student@workstation data-variables]$ ansible-playbook playbook.yml 
    
    
    ------------------------------ 【警戒线】 -------------------------------
    # 再运用group_vars和host_vars的知识再来修改
    # 这里的inventroy文件里只有主机组,那么我们创建一个group_vars
    
    [student@workstation data-variables]$ mkdir group_vars
    [student@workstation data-variables]$ cd group_vars/
    [student@workstation group_vars]$ vim webserver
    [student@workstation group_vars]$ cd ..
    [student@workstation data-variables]$ vim playbook.yml 
    # 这一步修改playbook.yml文件,就是去掉 vars_files:- variables/web.yml 这个变量文件这两行。
    
    # 然后再执行,执行效果正确。
    [student@workstation data-variables]$ ansible-playbook playbook.yml 
    
    # 练习完还原环境即可
    [student@workstation data-variables]$ lab data-variables finish
    

    加密敏感数据

    通过 vault 来加密一些敏感数据,例如密码,令牌等

    [student@workstation playbook-review]$ cd var
    [student@workstation var]$ ls
    vars.yml
    [student@workstation var]$ ansible-vault create test.yml # 创建加密文件
    New Vault password: 
    Confirm New Vault password: 
    
    # 查看加密文件内容(如果你直接使用cat去查看,就是一堆加密的字母)
    [student@workstation var]$ ansible-vault view test.yml 
    Vault password: 
    user: ztf
    
    # 编辑加密文件
    [student@workstation var]$ ansible-vault edit test.yml 
    Vault password: 
     
     
     # 加密现有的文件
    [student@workstation var]$ ansible-vault encrypt vars.yml 
    New Vault password: 
    Confirm New Vault password: 
    Encryption successful
    
    # 解密现有的文件
    [student@workstation var]$ ansible-vault decrypt test.yml 
    Vault password: 
    Decryption successful
    [student@workstation var]$ cat test.yml 
    user: ztf
    
    # 改密码
    [student@workstation var]$ ansible-vault rekey vars.yml 
    Vault password: 
    New Vault password: 
    Confirm New Vault password: 
    Rekey successful
    

    ansible vault 练习

    [student@workstation ~]$ lab data-secret start
    
    [student@workstation data-secret]$ ansible-vault edit secret.yml 
    密码是redhat
    去掉注释符号,保存退出
    
    [student@workstation data-secret]$ vim create_user.yml
    
    ---
    - name: Create user accounts for all our servers
      hosts: devservers
      become: True
      remote_user: devops
      vars_files:
        - secret.yml
      tasks:
        - name: Creating user from secret.yml
          user:
            name: {{ username }}
            password: {{ pwhash }}
    
    
    
    [student@workstation data-secret]$ ansible-playbook --ask-vault-pass create_user.yml 
    
    [student@workstation ~]$ lab data-secret finish
    

    Facts变量(重要)

    Ansible facts是在一个被管理主机上通过ansible自动被发现的变量。facts包含特定的主机信息,这些主机信息可以像正
    plays,conditionals,loops或者其它场景下,不同的应用场景取决于从被管理主机上采集的value类型

    常见的facts变量

    从被管理主机上可以搜集到facts包含:
    1.主机名
    2.内核版本
    3.网卡
    4.地址
    5.操作系统版本
    6.环境变量
    7.CPU的数量
    8.可用内存或者空闲内容
    9.可用磁盘空间

    使用场景

    使用facts来检索被管理主机的状态是非常方便的,而且还可以基于这些状态做不同的动作,例如:
    1.一个主机可以通过条件task判断如果系统的内核版本不匹配则重启切换到最新的内核版本。
    2.通过fact检索的内存情况来自定义mysql的配置文件
    3.在配置文件中使用的IPv4地址可以基于fact来设置

    运行原理

    每个play都会在第一个task之前自动运行setup模块,以便搜集fact。在Ansible2.3版本,通常这个task会被报告成“
    Facts”,在以前的版本通常会被报告执行setup。你不需要在你的play中运行setup,它会自动运行。
    如果你想看到setup模块的内容,你可以通过ad hoc命令运行

    [student@workstation data-secret]$ ansible servera.lab.example.com -m setup
    

    关闭facts采集

    有时候,你可能不想在你的paly中开启facts采集。为什么会有这样的情况有几点原因:
    1.你不想在你的paly中使用facts
    2.你想提升你的play速度
    3.你想减少负载
    可能被管理主机不能运行setup模块,比如需要在采集facts之前需要安装前置软件

    在这里插入图片描述

    Task控制

    loop循环

    在这里插入图片描述

    这里的{{item}} 是固定的,固定写法就是这样。不能变

    条件判断

    语法

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    多条件判断

    在这里插入图片描述

    条件判断和循环结合

    在这里插入图片描述

    loop循环练习

    [student@workstation ~]$ lab control-flow start
    [student@workstation ~]$ cd control-flow/
    [student@workstation control-flow]$ ls
    ansible.cfg  inventory
    [student@workstation control-flow]$ cat ansible.cfg inventory 
    [defaults]
    inventory=inventory
    remote_user=devops
    
    [privilege_escalation]
    become=True
    become_method=sudo
    become_user=root
    become_ask_pass=False
    [database_dev]
    servera.lab.example.com
    
    [database_prod]
    serverb.lab.example.com
    
    [student@workstation control-flow]$ cat playbook.yml 
    ---
    - name: this is a first play
      hosts: database_dev
      vars:
        mariadb_packages:
                - mariadb-server
                - python3-PyMySQL
      tasks:      
        - name: install pkg
          yum:
            name: "{{ item  }}"
            state: present
          loop: "{{ mariadb_packages }}"
          
        - name: start db service
          service:
            name: mariadb
            state: started
            enabled: true
    
    
    [student@workstation control-flow]$ ansible-playbook playbook.yml 
    
    
    [student@workstation control-flow]$ ansible database_prod -m command -a 'cat /etc/redhat-release' -u devops --become
    serverb.lab.example.com | CHANGED | rc=0 >>
    Red Hat Enterprise Linux release 8.0 (Ootpa)
    
    
    [student@workstation ~]$ lab control-flow finish
    

    handlers练习

    [student@workstation ~]$ lab control-handlers start
    [student@workstation ~]$ cd control-handlers/
    [student@workstation control-handlers]$ ls
    ansible.cfg  configure_db.yml  inventory
    
    [student@workstation control-handlers]$ vim configure_db.yml 
    
    [student@workstation control-handlers]$ cat configure_db.yml 
    ---
    - name: Installing MariaDB server
      hosts: databases
      vars:
        db_packages:
          - mariadb-server
          - python3-PyMySQL
        db_service: mariadb
        resources_url: http://materials.example.com/labs/control-handlers
        config_file_url: "{{ resources_url }}/my.cnf.standard"
        config_file_dst: /etc/my.cnf
      tasks:
        - name: install pkg
          yum:
            name: "{{ db_packages }}"
            state: present
          notify:
            - set db password
    
        - name: start service
          service:
            name: "{{ db_service }}"
            state: started
            enabled: true
        
        - name: download db cfg
          get_url:
            url: "{{ config_file_url }}"
            dest: "{{ config_file_dst  }}"
            owner: mysql
            group: mysql
            force: yes
          notify:
            - restart db service
    
      handlers:
           - name: restart db service
             service:
               name: "{{ db_service }}"
               state: restarted
           - name: set db password
             mysql_user:
               name: root
               password: redhat
               
               
               
    [student@workstation control-handlers]$ ansible-playbook configure_db.yml 
    
    假设如果你的tasks运行错误,就不会通知handlers,那么此时你在写之前,就应该加上,force_handlers: yes
    即使错了,也会通知handlers,不会影响运行。
    ---
    - hosts: all
    force_handlers: yes
    
    
    但是,如果你忘记加了,但是已经运行过playbook了,那么你就要在要被通知的tasks手动加上changed_when: true
    
      tasks:
        - name: install pkg
          yum:
            name: "{{ db_packages }}"
            state: present
            changed_when: true  # 让changed的状态改变就行
          notify:
            - set db password
    
    
    [student@workstation ~]$ lab control-handlers finish
    

    错误控制的练习

    [student@workstation ~]$ lab control-errors start
    [student@workstation control-errors]$ cat playbook.yml 
    ---
    - name: test
      hosts: databases
      vars:
        web_package: http
        db_package: mariadb-server
        db_service: mariadb
    
      tasks:
        - name: install httpd pkg
          yum:
            name: "{{ web_package  }}"
            state: present
        
        - name: install mariadb-server
          yum:
            name: "{{ db_package }}"
            state: present
            
    [student@workstation control-errors]$ ansible-playbook playbook.yml # 运行后会报错
    
    # 加一个忽略错误的命令
    [student@workstation control-errors]$ cat playbook.yml 
    ---
    - name: test
      hosts: databases
      vars:
        web_package: http
        db_package: mariadb-server
        db_service: mariadb
    
      tasks:
        - name: install httpd pkg
          yum:
            name: "{{ web_package  }}"
            state: present
          ignore_errors: yes # 忽略错误
        - name: install mariadb-server
          yum:
            name: "{{ db_package }}"
            state: present
             
    [student@workstation control-errors]$ ansible-playbook playbook.yml  # 错误被跳过
    
    
    # 添加一个block
    ---
    - name: test
      hosts: databases
      vars:
        web_package: http
        db_package: mariadb-server
        db_service: mariadb
    
      tasks:
        - name: add block
          block:
            - name: install httpd pkg
              yum:
                name: "{{ web_package  }}"
                state: present
          rescue:
             - name: install mariadb-server
               yum:
                 name: "{{ db_package }}"
                 state: present
                 
                 
    [student@workstation control-errors]$ ansible-playbook playbook.yml 
    
    当block里的东西运行失败了,他还是会运行rescue的代码
    
    
    # 加了always,如果block是对的,那么rescue是不会运行的,就直接运行always了
    ---
    - name: test
      hosts: databases
      vars:
        web_package: httpd
        db_package: mariadb-server
        db_service: mariadb
    
      tasks:
        - name: add block
          block:
            - name: install httpd pkg
              yum:
                name: "{{ web_package  }}"
                state: present
          rescue:
             - name: install mariadb-server
               yum:
                 name: "{{ db_package }}"
                 state: present
          always:
            - name: add a always
              service:
                name: "{{ db_service }}"
                state: started
                
    [student@workstation ~]$ lab control-errors finish
    
  • 相关阅读:
    【mysql 提高查询效率】Mysql 数据库查询好慢问题解决
    解锁新技能《Redis ACL SETUSER命令》
    图文并茂quasar2.6+vue3+ts+vite创建项目并引入mockjs,mockjs 拦截ajax请求的原理是什么,quasar为什么要使用boot?
    css 样式实战
    外包干了3个月,技术倒退2年。。。
    嵌入式开发人员使用基于组件的固件的5个理由
    JS(JavaScript)入门语法,语法+示例,非常详细!!!
    python--- MySQL字段约束条件,外键约束条件,表关系
    绿色信贷数据合集(更新至2021年)
    【Visual Leak Detector】在 VS 高版本中使用 VLD
  • 原文地址:https://blog.csdn.net/CNNUMBER/article/details/139940458