Ansible中管道传递至json_query无结果问题排查
问题:Ansible中使用json_query解析kubectl输出为空的问题
问题场景
在Ansible剧本中需要等待cert-manager生成的Let's Encrypt证书就绪后,再执行后续任务,编写了对应任务但发现json_query返回空字符串,无法正确判断证书状态。
原Ansible任务
- name: Get TLS certificate secret and wait until ready command: cmd: 'kubectl get certificate tls-rancher-ingress -n cattle-system -ojson' register: certificate_result changed_when: (certificate_result.stdout | community.general.json_query('status.conditions[0].status') == '"True"') retries: 10 delay: 30
kubectl命令输出的JSON
{ "apiVersion": "cert-manager.io/v1", "kind": "Certificate", "metadata": { "creationTimestamp": "2024-05-27T23:19:38Z", "generation": 2, "name": "tls-rancher-ingress", "namespace": "cattle-system", "resourceVersion": "2331753", "uid": "30b816cd-f548-4bf7-90d2-47a0406cdbb1" }, "spec": { "commonName": "rancher.example.com", "dnsNames": [ "rancher.example.com" ], "issuerRef": { "kind": "ClusterIssuer", "name": "letsencrypt-prod" }, "secretName": "tls-rancher-ingress" }, "status": { "conditions": [ { "lastTransitionTime": "2024-05-28T00:38:38Z", "message": "Certificate is up to date and has not expired", "observedGeneration": 2, "reason": "Ready", "status": "True", "type": "Ready" } ], "notAfter": "2024-08-25T23:38:35Z", "notBefore": "2024-05-27T23:38:36Z", "renewalTime": "2024-07-26T23:38:35Z", "revision": 2 } }
调试任务及现象
添加调试任务后,发现json_query始终返回空:
- name: Debug changed_when debug: msg: "DEBUG: {{ certificate_result.stdout | community.general.json_query('status.conditions[0].status') }}"
原因分析
你判断的没错,问题核心是**certificate_result.stdout是字符串格式,而json_query需要接收JSON对象(Python字典)才能解析**。直接将字符串传给json_query,它无法识别结构,因此返回空结果。
解决方案
方案1:转换字符串为JSON对象后使用json_query
先通过from_json过滤器把stdout字符串转为JSON对象,再传给json_query,同时注意判断值不需要额外加引号:
- name: Get TLS certificate secret and wait until ready command: cmd: 'kubectl get certificate tls-rancher-ingress -n cattle-system -ojson' register: certificate_result changed_when: (certificate_result.stdout | from_json | community.general.json_query('status.conditions[0].status') == 'True') retries: 10 delay: 30
方案2:直接通过字典访问(更简洁)
转换为JSON对象后,直接用字典索引访问目标值,无需json_query:
- name: Get TLS certificate secret and wait until ready command: cmd: 'kubectl get certificate tls-rancher-ingress -n cattle-system -ojson' register: certificate_result changed_when: (certificate_result.stdout | from_json).status.conditions[0].status == 'True' retries: 10 delay: 30
方案3:使用Ansible k8s_info模块(最佳实践)
避免直接调用kubectl,改用Ansible官方的k8s_info模块,自动处理JSON解析,还能精准筛选Ready类型的条件(避免conditions顺序变化导致判断错误):
- name: Wait for TLS certificate to be ready k8s_info: api_version: cert-manager.io/v1 kind: Certificate name: tls-rancher-ingress namespace: cattle-system register: certificate_result until: certificate_result.resources[0].status.conditions | selectattr('type', 'equalto', 'Ready') | map(attribute='status') | first == 'True' retries: 10 delay: 30
内容的提问来源于stack exchange,提问作者Lasse Michael Mølgaard
相关产品推荐
相关产品推荐

