AWS/Ansible - 如何从动态清单中定义的主机访问 roles/hosts 中的事实?

AWS/Ansible - How to access facts across roles/hosts from host defined in dynamic-inventory?

我目前正在设置一些 Ansible 角色来设置 Kubernetes 集群。到目前为止,我有一个角色来配置幂等 EC2(1x Master / 2x Worker)和后续角色来设置这些 master/worker 具有 Docker/Kubernetes 依赖关系的节点。我正在使用 AWS ec2.ini/.py dynamic-inventory 来发现由我的 create_ec2 角色提供的实例的 IP。

我在尝试使用从主节点检索的加入命令将我的工作人员加入集群时遇到了问题。我有 2 个单独的角色用于 master 和 worker 供应。在主人的任务中,我得到了加入命令:

kubeadm token create --print-join-command

然后注册一个变量,然后我用它来设置主机事实:

set_fact:
  join_command: "{{ join_command_stdout.stdout_lines[0] }}"

我遇到的问题是当我尝试在我的工作节点上访问这个事实时 运行 我的工作角色。我正在尝试通过以下方式访问事实:

"{{ hostvars['tag_Type_master'].join_command }} --ignore-preflight-errors all  >> node_joined.txt"

但是它失败了,因为我为 hostvars 提供的主机显然是未定义的..

作为参考,我在我的动态清单中保存了这个值(IP 省略):

  "tag_Type_master": [
    "1.2.3.4"

我收到的错误是:

"{"msg": "The task includes an option with an undefined variable. The error was: \"hostvars['tag_Type_master']\" is undefined"

我正在努力弄清楚如何访问我的动态清单中定义的 EC2 实例的主机事实。

我曾尝试将 EC2 IP 直接补充到 hostvars (hostvars['1.2.3.4'].join_command) 中,但是任务只是挂起,什么也不做。

我也试过放入一个 Magic 变量 (hostvars['inventory_hostname].join_command) 但无济于事。

似乎人们已经成功地从静态清单文件中定义的主机访问主机事实,但是由于 EC2 服务器的动态特性,将在其上创建集群我无法使用这种方法。

run.yml:

  name: Setup K8s master node
  hosts: tag_Name_kube_master    
  gather_facts: true    
  roles:    
  - setup_kube_master


  name: Setup K8s worker nodes
  hosts: tag_Name_kube_worker
  gather_facts: true
  roles: 
  - setup_kube_worker

setup_kube_master/tasks/set_fact.yml:

  name: Get join command for workers    
  shell: kubeadm token create --print-join-command    
  register: join_command_stdout    
  name: Persist variable for workers    
  set_fact:    
   join_command: "{{ join_command_stdout.stdout_lines[0] }}"

setup_kube_worker/tasks/get_fact.yml:

  name: join cluster
  shell: "{{ hostvars['tag_Type_master'].join_command }} --ignore-preflight-errors all  >> node_joined.txt"    
  args:    
   chdir: $HOME    
   creates: node_joined.txt

因此,您自己解决此问题的方法是使用 debug: 任务来显示整个事实缓存并自行查找关系:

- name: show the state of affairs
  debug: var=hostvars verbosity=0

然而,话虽如此,我很确定 tag_Type_master 被定义为 ,因此不会出现在 hostvars 中,因为-- 顾名思义 -- 它是 vars for hosts 而不是 vars for groups

您必须执行一级间接访问才能获得属于该组成员的主机:

- hosts: tag_Name_kube_worker
  tasks:
  - name: promote the "join_command" fact from the masters group
    set_fact:
      join_command: '{{ some_master.join_command }}'
    vars:
      some_master: '{{ hostvars[groups["tag_Type_master"][0]] }}'

为了简洁起见,我对 some_master 的定义进行了一些改动——在生产代码中,您可能希望实际检查该组是否存在并且其内容不为空等等,但我大约 80% 确定它会像写的那样工作

你会希望它出现在 run.yml 中,介于 hosts: tag_Type_masterhosts: tag_Type_worker 之间,以弥合两组之间的事实差距,并使工人看起来好像join_command 事实一直如此


另外,虽然这不是您所要求的,但如果您要使用 "kubernetes.io/role/master": "" and/or "kubernetes.io/role": "master" 标记这些实例,您将受益于已经拥有 cloud-provider is expecting。我不知道在 ec2.py 中会是什么样子,但我确信使用 ansible-inventory -i ec2.py --list

可以很便宜地找出答案

我用相应的 kubernetes.io/role: worker 标记工作人员,尽管我很确定 AWS 云提供商不关心它,而是选择只在现有的 metadata.labels 上使用ELB注册等节点