如何配置 Jinja 配置文件以包含基于通用值的服务检查?

How to configure a Jinja configuration file to include service checks based on generic values?

我公司的ansible被配置为为某些服务构建Nagios模板。

例如:

      define service {
            use                     rabbit-critical-service         ; Name of service template to use
            service_description     RabbitMQ {{ queue_name }} queue size
            check_command                   check_graphite_data!1000!15000!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value
            host_name               {{ rabbitmq_server }}
            notifications_enabled   1
            servicegroups           rabbitmq
    }

该模板会自动为所有队列使用相同的阈值构建检查。队列名称在 ansible_playbooks/roles/nagios/defaults/main.yml 下的不同文件中配置,并使用 Jinja 自动生成。

我的任务是让我能够以一种稍微简单的方式编辑配置,以便为某些特定检查包含不同的阈值,但我很难理解如何去做。

我想过类似的事情: 添加到 service_check 模板类似这样的东西:

{% if queue_size_specific_vars is not defined %}
create the check using the current configuration...
{% else %}
create the check using the specific configuration which will be found in the `default/main.yml` file in the newly created generic value "queue_size_specific_vars" which is supposed to include two values, one for warning value and one for critical value.
{% endif %}

我的问题是:

  1. How do I achieve my goal (while taking into consideration two values instead of one)?
  2. I'm not sure this is the best way to achieve my goal, do you know a better way to do so?

编辑#1:

看来我没有解释清楚,让我向您展示模板的更大部分:

{% for queue_name in queues %}
define service {
        use                     rabbit-critical-service         ; Name of service template to use
        service_description     RabbitMQ {{ queue_name }} queue active consumers
        check_command                   check_graphite_data!0.9!0.9!rabbitmq._.rabbitmq_consumers.{{ queue_name }}!reverse
        host_name               {{ rabbitmq_server }}
        notifications_enabled   1
        servicegroups           rabbitmq
        max_check_attempts      4
}

{% if vars_production is not defined %}
define service {
        use                     generic-service
        service_description     RabbitMQ {{ queue_name }} queue read/write ratio
        check_command                   check_graphite!'http://{{ graphite_server }}:{{ graphite_port }}/render/?from=-10minutes&target=scale(divideSeries(offset(prod-rabbit-1.rabbitmq._.rabbitmq_messages.{{queue_name}}.value,1),offset(derivative(sumSeries(prod-rabbit-1.rabbitmq._.rabbitmq_deliver_get.{{queue_name}})),1)),100)&rawData'!1500!2000!avg
        host_name               {{ rabbitmq_server }}
        notifications_enabled   1
        servicegroups           rabbitmq
        max_check_attempts      4
}
{% endif %}
define service {
        use                     rabbit-critical-service         ; Name of service template to use
        service_description     RabbitMQ {{ queue_name }} queue size
        check_command                   check_graphite_data!1000!15000!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value
        host_name               {{ rabbitmq_server }}
        notifications_enabled   1
        servicegroups           rabbitmq
}

{% endfor %}

这意味着我应该实施的更改应该在队列级别而不是在主机名中,因为 ansible "knows" 仅托管而不 "know" 队列。

我们需要为每个队列设置 "RabbitMQ {{ queue_name }} queue size" 的选项,其余的都使用默认值。 我期望做的更改应该在模板文件本身中进行。

示例:

{% if special_queue_exists %}
do ....
{% else %}
create it in the normal method
{% endif %}

编辑#2:

我的经理希望我以类似于这样的方式来做: 我已经有了包含所有队列的文件,我们称这个文件为 "queues_file"。 他希望我创建另一个文件,其中将包含一个特定检查值列表(警告和关键),我们称这个文件为 "specific_values".

然后做这样的事情:

queues_with_specific_metrics:
  - entities:
    - warn: "1000"
    - crit: "20000"

然后检查我正在 运行 宁(来自 for 循环)的队列是否在 "specific_values" 文件中有特定的配置,如果有,那么 "specific_values" 文件应该覆盖默认文件。 然后,我可以这样做:

{{ queues_with_specific_metrics.queue.warn | default(1000) }}

我是 Ansible 和 Jinja 的新手,这就是为什么我不太容易理解,对此深表歉意。

编辑#3: 我已经按照您的建议编辑了配置,但我不确定如何编写 if 语句...

defaults/main.yml 包含所有队列名称的列表。

我打开了一个名为 spec_params.yml 的新文件,它作为 main.yml 文件位于默认文件夹中。

spec_params.yml 文件:

nagios_specific_queue_params:
  queue1: {}
  entities:
    warn: 2000
    crit: 20000

rabbitmq.cfg.j2的相关部分:

{% if queue_name in nagios_specific_queue_params %}
define service {
        use                     rabbit-critical-service         ; Name of service template to use
        service_description     RabbitMQ {{ queue_name }} queue size
        check_command           check_graphite_data!{{ queues[queue_name] ['warn'] |default(1000) }}!{{ queues[queue_name] ['crit'] | default(15000) }}!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value
        host_name               {{ rabbitmq_server }}
        notifications_enabled   1
        servicegroups           rabbitmq
}
{% else %}
define service {
        use                     rabbit-critical-service         ; Name of service template to use
        service_description     RabbitMQ {{ queue_name }} queue size
        check_command                   check_graphite_data!1000!15000!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value
        host_name               {{ rabbitmq_server }}
        notifications_enabled   1
        servicegroups           rabbitmq
}
{% endif %}

当我 运行 剧本时,出现以下错误:

fatal: [monitoring] => {'msg': "TypeError: argument of type 'StrictUndefined' is not iterable", 'failed': True}
fatal: [monitoring] => {'msg': 'One or more items failed.', 'failed': True, 'changed': False, 'results'

知道为什么会失败吗?

提前致谢

roles//defaults/ 中的变量可以被任何上层变量覆盖(/vars、group_vars、host_vars 和 inventory vars 中的变量)。

因此,如果您定义一个变量 queue_size,在默认情况下您可以在 group/host_vars 文件中覆盖它。

# file: roles/nagios/deaults/main.yml
queue_size: "1000!15000"

# file: host_vars/host1.yml
queue_size: "2000!25000"

# file: host_vars/host2.yml
queue_size: "1000!5000"

# file: roles/nagios/templates/check.j2
      define service {
            use                     rabbit-critical-service         ; Name of service template to use
            service_description     RabbitMQ {{ queue_name }} queue size
            check_command                   check_graphite_data!{{ queue_size }}!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value
            host_name               {{ rabbitmq_server }}
            notifications_enabled   1
            servicegroups           rabbitmq
    }

这应该可以回答您的两个问题。如果您想要更清晰的 vars 文件,您还可以指定 queue_size_minqueue_size_max

编辑: 为了更好地解释我在评论中的意思:

你有两种方法(我能想到的)来解决这个问题:

首先:使用一个单独的文件,其中包含非默认队列的值。这可能更干净,但您必须保留原始 var 文件中存在的所有队列:

# file vars/original_file.yml
queues: 
  - queue1
  - entities

# file vars/specific.yml
queue_with_specific_metrics:
    queue1: {}
    entities:
       warn: 1000
       crit: 15000

其次:编辑原始文件以在需要时包含特定值

queues:
   queue1: {}
   entities:
        warn: 1000
        crit: 2000

在任何一种情况下,您都可以更改模板以采用值或分配默认值:

# case 1
check_command check_graphite_data!{{ queue_with_specific_metrics[queue_name]['warn'] | default(1000) }}!{{ queue_with_specific_metrics[queue_name]['crit'] | default(800) }}!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value}

check_command check_graphite_data!{{ queues[queue_name]['warn'] | default(1000) }}!{{ queues[queue_name]['crit'] | default(800) }}!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value}

这是我为完成任务所做的步骤:

nagios/defaults/main.yml 中,我添加了:

nagios_queue_size_default_values:
  warn: 1000
  crit: 15000
nagios_queue_size_override_values:
  entities_prod_whatever_2:
    warn: 600
    crit: 900

然后,在 rabbitmq.cfg.j2 中,我将检查命令更改为这个:

check_command     check_graphite_data!{{ nagios_queue_size_override_values.get(queue_name, nagios_queue_size_default_values).warn }}!{{ nagios_queue_size_override_values.get(queue_name, nagios_queue_size_default_values).crit }}!rabbitmq._.rabbitmq_messages.{{ queue_name }}.value

运行 剧本现在根据需要创建模板。