【问题标题】:Using ansible to manage disk space使用 ansible 管理磁盘空间
【发布时间】:2014-11-17 21:02:13
【问题描述】:

简单的问题:如果分区利用率超过一定百分比,我想删除一些文件。

我可以通过“ansible_mounts”访问“size_total”和“size_available”。即:

ansible myhost -m setup -a 'filter=ansible_mounts'
myhost | success >> {
"ansible_facts": {
    "ansible_mounts": [
        {
            "device": "/dev/mapper/RootVolGroup00-lv_root", 
            "fstype": "ext4", 
            "mount": "/", 
            "options": "rw", 
            "size_available": 5033046016, 
            "size_total": 8455118848
        }, 

如何访问这些值,以及如何使用 Ansible 根据它们有条件地执行操作?

【问题讨论】:

    标签: ansible


    【解决方案1】:

    Slava 的答案肯定是在正确的轨道上,这是我使用的:

    - name: test for available disk space
      assert:
        that: 
          - not {{ item.mount == '/' and ( item.size_available < item.size_total - ( item.size_total|float * 0.8 ) ) }}
          - not {{ item.mount == '/var' and ( item.size_available < item.size_total - ( item.size_total|float * 0.8 ) ) }}
      with_items: ansible_mounts
      ignore_errors: yes
      register: disk_free
    
    - name: free disk space
      command: "/some/command/that/fixes/it"
      when: disk_free|failed
    

    断言任务只是测试一个条件,通过设置ignore_errors,并将测试结果注册到一个新变量中,我们可以在稍后执行一个条件任务,而不是在断言结果失败时失败。

    测试本身可能会更有效地编写,但会以可读性为代价。所以我在示例中没有使用多列表循环。在这种情况下,任务会遍历挂载文件系统列表中的每个项目(一个 ansible 创建的事实,称为 ansible_mounts。)

    通过否定测试,我们避免了不在列表中的文件系统挂载失败,然后简单的数学处理其余部分。让我感到困惑的部分是 size_available 和 size_total 变量是字符串,因此 jinja 过滤器在计算百分比之前将它们转换为浮点数。

    【讨论】:

    • 当我尝试这个时,我收到了这个错误:“错误是:'unicode object' has no attribute 'mount'”
    • 'no attribute "mount"' 问题的答案是使用:with_items: '{{ ansible_mounts }}' ...但是,该示例似乎也中断(至少在 Ans 2.2 .1.0 ) 尝试在列表上使用 |failed 构造时。 .. 我可以让断言正常工作,但无法让 |failed 部分正常工作。
    • 在 Ansible 的更新版本上使用 when: disk_free is failed
    【解决方案2】:

    就我而言,我只关心根分区。但是我发现在使用上面 frameloss 的示例时,我需要一个否定的“或”条件,因为每个挂载点都会针对断言进行测试。如果存在多个挂载点,则意味着断言将始终失败。在我的示例中,我直接测试 size_available 是否小于 size_total 的 50%,而不是像 frameloss 那样计算。

    其次,至少在我使用的 ansible 版本中,必须在 with_items 的变量周围包含 {{ }}。我在上面的示例中没有犯的一个错误是没有将 'when' 子句与 'fail' 指令对齐。 (如果犯了那个错误,那么解决方案就行不通了……)

    # This works with ansible 2.2.1.0
    - hosts: api-endpoints
      become: True
      tasks:
    
        - name: Test disk space available
          assert:
            that:
                - item.mount != '/' or {{ item.mount == '/' and item.size_available > (item.size_total|float * 0.4) }}
          with_items: '{{ ansible_mounts }}'
          ignore_errors: yes
          register: disk_free
    
        - name: Fail when disk space needs attention
          fail:
             msg: 'Disk space needs attention.'
          when: disk_free|failed
    

    【讨论】:

      【解决方案3】:

      我没有测试它,但我建议尝试这样的事情:

      file:
         dest: /path/to/big/file
         state: absent
         when: "{% for point in ansible_mounts %}{% if point.mount == '/' and point.size_available > (point.size_total / 100 * 85) %}true{% endif %}{% endfor %}" == "true"
      

      在本例中,我们遍历挂载点并找到“/”,然后计算利用率是否超过 85%,如果为真,则打印“真”。接下来,我们比较该字符串并决定是否应该删除该文件。

      灵感来自以下博客中的示例:https://blog.codecentric.de/en/2014/08/jinja2-better-ansible-playbooks-templates/

      【讨论】:

        【解决方案4】:

        我的解决方案

        - name: cleanup logs, free disk space below 20%
          sudo: yes
          command: find /var -name "*.log" \( \( -size +50M -mtime +7 \) -o -mtime +30 \) -exec truncate {} --size 0 \;
          when: "item.mount == '/var' and ( item.size_available < item.size_total * 0.2 )"
          with_items: ansible_mounts
        

        如果可用磁盘空间低于 20%,这将截断卷 /var 上超过 7 天且超过 50M 或超过 30 天的所有 *.log 文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-06-16
          • 2019-12-12
          • 1970-01-01
          • 2020-07-12
          • 2013-03-01
          • 2020-08-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多