如何在Molecule各步骤间传递预配置Kubernetes集群的连接信息?
你碰到的这个问题确实是Molecule用delegated驱动时的典型痛点——因为每个测试步骤(prepare、converge、verify、cleanup)都是独立的ansible-playbook进程,上下文没法直接在进程间共享。不过有几个实用的办法能解决这个问题,我来给你梳理下:
1. 用Molecule临时目录存储集群信息文件
这是最直接且常用的方案:在prepare步骤里调用API获取集群信息,把内容写入Molecule为每个测试实例创建的临时目录文件中,后续步骤通过读取这个文件拿到信息。
示例代码:
在prepare playbook中保存集群信息:
- name: 从API获取可用K8s集群信息 uri: url: "http://your-cluster-api.example.com/get-available" method: GET return_content: yes register: cluster_api_result - name: 将集群信息写入临时文件 copy: content: "{{ cluster_api_result.json | to_nice_yaml }}" dest: "{{ molecule_ephemeral_directory }}/cluster_details.yml"
在converge/verify playbook中加载信息:
- name: 加载预存的K8s集群信息 include_vars: file: "{{ molecule_ephemeral_directory }}/cluster_details.yml"
这里用molecule_ephemeral_directory变量是关键——它是Molecule自动生成的独立临时目录,能避免不同测试实例的信息互相干扰。
2. 通过环境变量传递信息
你也可以把集群信息导出为环境变量,让后续步骤通过环境变量读取。需要注意的是,要把环境变量写入Molecule能识别的配置文件中,确保跨进程生效。
示例代码:
在prepare步骤生成.env文件:
- name: 生成集群信息环境变量文件 copy: content: | K8S_SERVER={{ cluster_api_result.json.api_server }} K8S_TOKEN={{ cluster_api_result.json.auth_token }} K8S_NAMESPACE={{ cluster_api_result.json.test_namespace }} dest: "{{ molecule_ephemeral_directory }}/cluster_env"
在molecule.yml中配置加载环境变量:
provisioner: name: ansible playbooks: prepare: prepare.yml converge: converge.yml verify: verify.yml # 让所有步骤加载这个环境变量文件 env_file: "{{ molecule_ephemeral_directory }}/cluster_env"
之后在playbook里就能通过{{ lookup('env', 'K8S_SERVER') }}直接引用这些变量了。
3. 自定义Molecule钩子(进阶方案)
如果上述方法不够灵活,你可以写一个简单的Molecule预执行钩子(比如pre-converge钩子),在每个需要集群信息的步骤前自动调用API并注入变量。这种方式需要写少量Python代码,适合复杂场景。
比如在molecule/hooks/pre_converge.py中添加逻辑:
import requests import os from molecule import logger log = logger.get_logger(__name__) def main(): api_url = "http://your-cluster-api.example.com/get-available" response = requests.get(api_url) cluster_data = response.json() # 将信息写入环境变量,供Ansible读取 os.environ["K8S_SERVER"] = cluster_data["api_server"] os.environ["K8S_TOKEN"] = cluster_data["auth_token"] log.info("Fetched K8s cluster info and set environment variables") if __name__ == "__main__": main()
然后在molecule.yml中启用这个钩子:
hooks: pre_converge: - command: python molecule/hooks/pre_converge.py
为什么全局fact/host_var行不通?
你之前的思路没毛病,但确实受限于Molecule的执行机制:每个步骤都是独立的Ansible进程,进程结束后内存中的fact和变量就会被销毁,没法跨进程传递。所以必须借助外部存储(文件、环境变量)来做中间介质。
内容的提问来源于stack exchange,提问作者Timbo

