【问题标题】:Ansible, Boto, AWS - Invalid type for parameter containerDefinitions[0].memoryAnsible、Boto、AWS - 参数 containerDefinitions[0].memory 的类型无效
【发布时间】:2017-01-26 06:58:56
【问题描述】:

我在 Amazon ECS 上的 docker 容器中运行了几项服务,并且正在为每项服务分配总系统内存的百分比。

在我的 ansible/roles/ecs_cluster_init/defaults/main.yaml 文件中,我有以下条目:

docker_memory_limit_service1: 17
docker_memory_limit_service2: 12
docker_memory_limit_service3: 16
docker_memory_limit_service4: 10
docker_memory_limit_service5: 16
docker_memory_limit_service6: 10
total_system_memory : 2048

服务 1 应该获得总系统内存的 17%,而服务 4 只获得 10%。这是为了轻松适应实例大小的变化。

在我的 ansible/roles/ecs_cluster_init/vars/main.yaml 文件中(部分):

ecs_task_definitions:
  - name: "service1"
    elb: "{{ elb_creation_output.results[0].elb.dns_name }}"
    image: "{{ service1_docker_image }}"
    port: "{{ ports.service1 }}"
    memory: "{{ ( total_system_memory * ( docker_memory_limit_service1|int / 100 ))|int|abs }}"

为清楚起见,将服务内存值转换为百分比(除以 100),然后确定总系统内存的那部分。

在我的 ansible/roles/ecs_cluster_init/tasks/main.yaml 文件中,我有:

## ECS Task and Service Definitions
- block:
    - name: Create ECS Service1 Task Definitions
      ecs_taskdefinition:
        region: "{{ region }}"
        containers:
          - name: "{{ item.name }}"
            cpu: 0
            essential: true
            image: "{{ item.image }}"
            memory: {{ item.memory|int|abs }}
            mountPoints: "{{ item.mounts }}"
            environment: "{{ item.env_vars }}"
            portMappings: "{{ item.portmap }}"
            entryPoint:
              - "java"
              - "-Xms{{ java_heap_size_initial }}"
              - "-Xmx{{ java_heap_size_max }}"
              - "-DlogDir=/host"
              - "-Dcom.sun.net.ssl.checkRevocation=false"
              - "-jar"
              - "/app.jar"
            logConfiguration:
              logDriver: "{{ ecs_task_log_configuration.logDriver }}"
              options:
                max-size: "{{ ecs_task_log_configuration.options.max_size }}"
                max-file: "{{ ecs_task_log_configuration.options.max_file }}"
        family: "{{ service_prefix }}-{{ item.name }}-{{ env_name }}"
        state: present
        increment_revision: true
        volumes: "{{ item.volumes }}"
      register: service1_task_definition
      with_items: "{{ ecs_task_definitions }}"

当我为角色运行剧本时,我收到以下错误:

TASK [ecs_cluster_create : Create ECS Service1 Task Definitions] ****************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: Invalid type for parameter containerDefinitions[0].memory, value: 204, type: <type 'str'>, valid types: <type 'int'>, <type 'long'>

知道我做错了什么或者我缺少指定内存值的地方应该是 int 吗?

【问题讨论】:

  • 可以尝试添加|to_json过滤器{{ item.memory|int|to_json }}
  • 应用您的建议后,我仍然收到相同的错误消息。

标签: ansible boto3 amazon-ecs


【解决方案1】:

Ansible/Jinja 的一个已知问题是模板化后无法保留 int 类型。
换句话说|int 是双括号内的整数,但是当你关闭大括号时变成字符串。

但 Ansible 在模板化后保留了复杂类型,如 dicts/list,所以你可以这样做:

- name: Create ECS Service1 Task Definitions
  ecs_taskdefinition:
    region: "{{ region }}"
    containers: "{{'['+dict(name=item.name, cpu=0, image=item.image, memory=item.memory|int)|to_json+']'}}"
  with_items: "{{ ecs_task_definitions }}"

我已经缩短了示例

这样我们构造了一个字符串,它是一个 JSON 列表,可以在模板化后进行 ansible 转换。

【讨论】:

  • to_json 过滤器后面的“+”有什么作用?
  • dict(...)|to_json 为您提供 JSON 字符串,然后将 []+ 字符串连接添加到两侧,因为容器应该是一个列表(根据您的示例)。
  • 如果容器列表也包含一个列表,我将如何格式化它?我已经更新了我原来的问题以显示我所指的入口点列表。
  • 在 Python 中查看 lists。但在您的情况下,使用entryPoint=('java^-Xms'+java_heap_size_initial+'^...^/app.jar').split('^') 会很方便。我在任何参数中使用^ 字符作为不存在的字符来形成单个字符串,然后将其拆分为列表。
  • 你不能做嵌套模板,所以entryPoint=('jav‌​a^-Xms'+java_heap_size_initial+'^-Xmx'+java_heap_size_max+'^-DlogDir=/host^-Djava.security.egd=file:/dev/./urandom^-D‌​com.sun.net.ssl.chec‌​kRevocation=false^-j‌​ar^/app.jar').split(‌​'^')。这很难看,我知道...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
相关资源
最近更新 更多