【问题标题】:Docker_swarm module - join_token parameter for ansible not workingDocker_swarm 模块 - ansible 的 join_token 参数不起作用
【发布时间】:2019-10-04 08:21:30
【问题描述】:

这是我的 ansible 剧本,任务是从 docker_swarm 模块文档中复制的,所以它应该可以工作:

  - name: Init a new swarm with default parameters
    docker_swarm:
      state: present
      advertise_addr: "{{ manager_ip }}:2377"
    register: rezult
    when: "ansible_default_ipv4.address == '{{ manager_ip }}'"


  - name: Add nodes
    docker_swarm:
      state: join
      advertise_addr: "{{ manager_ip }}"
      join_token: rezult.swarm_facts.JoinTokens.Worker
      remote_addrs: "{{ manager_ip }}:2377"
    when: "ansible_default_ipv4.address != '{{ manager_ip }}'"

它使用“manager_ip”--extra-var 初始化一个集群管理器 但它在“添加节点任务”中失败并出现此错误:

fatal: [vm2]: FAILED! => {"changed": false, "msg": "Can not join the Swarm Cluster: 500 Server Error: Internal Server Error (\"invalid join token\")"}

如果我在 join_token 之后将 "'{{ }}'" 放在 "rezult.swarm_facts.JoinTokens.Worker" 周围,我会得到:

fatal: [vm2]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'swarm_facts'\n\nThe error appears to be in '/home/ansible/docker-ansible/docker.yml': line 47, column 5, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n  - name: Add nodes\n    ^ here\n"}

如果我将调试消息放入 rezult.swarm_facts.JoinTokens.Worker 我得到正确的令牌:

ok: [opensuse1] => {
    "msg": "SWMTKN-1-5p7brhxxz4gzu716t78tt5woj7h6aflq0kdwvzwlbbe7ct0ba7-e59bg0t79q67ogd61ydwxc5yq"
}

如果我在服务器上通过 docker swarm join 命令手动使用该令牌,我希望与管理器合并它可以工作。因此变量具有正确的值并且节点之间的连接起作用。但我就是无法让 join_token 工作。我正在使用 python 2.7.5 运行 ansible 2.8.5。

我知道我可以使用 shell 模块,但我不想这样做。

【问题讨论】:

  • 另外,我在使用 shell 模块时遇到了同样的第二个错误。我认为 ansible 在它“!='{{ manager_ip }}'”的服务器上运行时忘记了“rezult”中的内容。这令人沮丧。

标签: docker module ansible swarm


【解决方案1】:

这样的东西对我有用:

---
- name: Init swarm on the first node
  community.general.docker_swarm:
    state: present
    advertise_addr: "{{ ansible_host }}"
  register: result
  when: inventory_hostname == groups['swarm_managers'][0]

- name: Get join-token for manager nodes
  set_fact:
    join_token_manager: "{{ hostvars[groups['swarm_managers'][0]].result.swarm_facts.JoinTokens.Manager }}"

- name: Get join-token for worker nodes
  set_fact:
    join_token_worker: "{{ hostvars[groups['swarm_managers'][0]].result.swarm_facts.JoinTokens.Worker }}"

- name: Join other managers
  community.general.docker_swarm:
    state: join
    join_token: "{{ join_token_manager }}"
    advertise_addr: "{{ ansible_host }}"
    remote_addrs: "{{ hostvars[groups['swarm_managers'][0]].ansible_host }}"
  when:
    - inventory_hostname in groups['swarm_managers']
    - inventory_hostname != groups['swarm_managers'][0]

- name: Join workers
  community.general.docker_swarm:
    state: join
    join_token: "{{ join_token_worker }}"
    advertise_addr: "{{ ansible_host }}"
    remote_addrs: "{{ hostvars[groups['swarm_managers'][0]].ansible_host }}"
  when:
    - inventory_hostname not in groups['swarm_managers']

swarm_managers 组中,有管理员,此清单中的所有其他主机都是工作人员。

【讨论】:

  • 喜欢这个,但您不会错过“获取加入令牌”任务中的when: inventory_hostname == groups['swarm_managers'][0] 吗?
  • @LennartRolland 在初始化任务之后,唯一知道加入令牌的主机是groups['swarm_managers'][0]。我们希望这些令牌可用于库存中的所有主机。因此,在接下来的 2 个任务中,每个主机都通过从 groups['swarm_managers'][0]hostvars[groups['swarm_managers'][0]] 部分)获取这些变量来设置 join_token_xxx 事实。我能想到的唯一可以在这里添加的whenwhen: inventory_hostname in groups['swarm_managers'] 用于Get join-token for manager nodes 任务,反之亦然用于Get join-token for worker nodes 任务
【解决方案2】:

我认为 achempion 是正确的,问题是 OP 变量 rezult.swarm_facts.JoinTokens.Worker 没有被评估,而是作为某种对象提供。

rezult.swarm_facts.JoinTokens.Worker 替换为"{{ rezult.swarm_facts.JoinTokens.Worker }}",它应该可以工作。

我意识到 OP 可能已经继续前进,但我花了很长时间试图找出一个非常相似的问题,这似乎为我解决了这个问题。

【讨论】:

    【解决方案3】:

    由于我没有足够的声誉来发表评论 - 这是您的剧本任务中的另一个错误。你使用:

      - name: Add nodes
        docker_swarm:
          state: join
          advertise_addr: "{{ manager_ip }}"
          join_token: rezult.swarm_facts.JoinTokens.Worker
          remote_addrs: "{{ manager_ip }}:2377"
        when: "ansible_default_ipv4.address != '{{ manager_ip }}'"
    

    ...将advertise_addr 分配给错误 ip 地址。这仍然允许您的节点加入,但会弄乱它们的覆盖网络配置(没有节点可以相互 ping 通,导致网络不断故障)。我建议改用ssh connection ip

      - name: Add nodes
        docker_swarm:
          state: join
          advertise_addr: "{{ ansible_ssh_host }}"
          join_token: rezult.swarm_facts.JoinTokens.Worker
          remote_addrs: "{{ manager_ip }}:2377"
        when: "ansible_default_ipv4.address != '{{ manager_ip }}'"
    

    也只需看看documentation examples

    - name: Add nodes
      community.docker.docker_swarm:
        state: join
        advertise_addr: 192.168.1.2
        join_token: SWMTKN-1--xxxxx
        remote_addrs: [ '192.168.1.1:2377' ]
    

    ...它也使用不同的 IP 地址。

    我不得不承认:我也爱上了它,花了几个小时才解决。我希望其他人在通过复制您的 sn-p 犯同样的错误之前看到这个答案。

    【讨论】:

      【解决方案4】:

      我认为这里的问题来自rezult.swarm_facts.JoinTokens.Worker。在调试信息中,它显示为 "msg": "SWMTKN-1-5p7..." 但 Ansible 配置中的 join_token: 选项期望它只是普通令牌,没有额外的包装器,如 "msg": 等等。

      【讨论】:

      • 我不认为“msg”是这里的问题,任何调试消息中都有。你设法弄清楚这一点吗?我也有同样的问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-21
      • 1970-01-01
      • 2021-11-05
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 2022-10-16
      相关资源
      最近更新 更多