如何利用GCP标签在Ansible Play中动态设置ansible_fqdn?
解决Ansible动态构建GCP实例FQDN的问题
问题背景
将GCP作为Ansible inventory源时,GCP默认不会暴露虚拟机实例的FQDN,ansible_host被设置为实例的IP地址。为了通过域名管理实例,给GCP实例添加了domainmembership标签(值为域名前缀),固定域名后缀为.somedomain,希望动态构建ansible_fqdn并将ansible_host替换为对应的FQDN,但执行Playbook时出现hostvars['domain1']未定义的错误。
原Playbook代码
--- - name: Patching - pre checks hosts: "{{ target_hosts | default('all') }}" gather_facts: false pre_tasks: - name: Include environment variables for GCP Windows Domain Members include_vars: dir: group_vars/gcp when: - labels.domainmembership is defined - '"windows" in labels.operatingsystem' - name: Set facts for identified GCP Domain Members ansible.builtin.set_fact: domainlabel_secondpart: '{{ ".somedomain" }}' ansible_fqdn: "{{ hostvars[labels.domainmembership] + domainlabel_secondpart }}" ansible_host: "{{ ansible_hostname_full }}" cacheable: yes when: - labels.domainmembership is defined - '"windows" in labels.operatingsystem'
错误信息
TASK [Set facts for identified GCP Domain Members] ***************************** fatal: [server1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: \"hostvars['domain1']\" is undefined. \"hostvars['domain1']\" is undefined The error appears to be in '/runner/project/pre-checks-test.yml': line 36, column 7, but may be elsewhere in the file depending on the exact syntax problem. The offending line appears to be: - name: Set facts for identified GCP Domain Members ^ here "}
GCP实例Inventory信息示例
{ "ansible_host": "10.0.0.2", "canIpForward": false, "cpuPlatform": "Intel Cascade Lake", "creationTimestamp": "2023-04-26T23:55:38.932-07:00", "deletionProtection": false, "name": "server1", "project": "someproject", "startRestricted": false, "status": "RUNNING", "labels": { "domainmembership": "domain1", "operatingsystem": "windows" } }
错误原因
错误出在ansible_fqdn的赋值逻辑:hostvars[labels.domainmembership]试图调用名为domain1的主机对应的变量,但domain1只是GCP实例的标签值,并非Ansible inventory中的主机名,因此该变量不存在。
修正方案
直接使用GCP实例的domainmembership标签值与固定后缀拼接,生成FQDN,同时将ansible_host设置为这个FQDN即可。修正后的set_fact任务如下:
- name: Set facts for identified GCP Domain Members ansible.builtin.set_fact: ansible_fqdn: "{{ labels.domainmembership }}.somedomain" ansible_host: "{{ ansible_fqdn }}" cacheable: yes when: - labels.domainmembership is defined - '"windows" in labels.operatingsystem'
说明
- 直接拼接
labels.domainmembership和.somedomain得到完整FQDN,无需借助hostvars - 将
ansible_host直接设置为刚生成的ansible_fqdn,替代原来的IP地址 - 保留
cacheable: yes确保该事实可以在后续Play或任务中复用
验证
修正后执行Playbook,目标实例的ansible_fqdn会被设置为domain1.somedomain,ansible_host也会更新为该FQDN,后续任务将通过域名而非IP连接实例。
内容的提问来源于stack exchange,提问作者J1raya
相关产品推荐
相关产品推荐

