如何使用yq依据上下文信息而非索引更新数组元素?
如何通过匹配环境变量名称更新Kubernetes Pod配置
问题背景
现有一个kube-vip的Pod配置文件,需要更新其中vip_address环境变量的value值。目前用的是依赖索引位置的命令:
cat $file | yq e '.spec.containers[].env[2].value="sdf"'
但这种方式不可靠,因为环境变量的顺序可能变动。想改成通过匹配name: vip_address的方式来更新对应的value,尝试了下面的命令但没达到预期:
yq e '. | select(.spec.containers[].env[].name=="vip_address") | .value="sdf"'
原Pod配置如下:
apiVersion: v1 kind: Pod metadata: creationTimestamp: null name: kube-vip namespace: kube-system spec: containers: - args: - start env: - name: vip_arp value: "true" - name: vip_leaderelection value: "true" - name: vip_address value: - name: vip_interface value: eth0 - name: vip_leaseduration value: "15" - name: vip_renewdeadline value: "10" - name: vip_retryperiod value: "2" image: ghcr.io/kube-vip/kube-vip:v0.3.5 imagePullPolicy: IfNotPresent name: kube-vip resources: {} securityContext: capabilities: add: - NET_ADMIN - SYS_TIME volumeMounts: - mountPath: /etc/kubernetes/admin.conf name: kubeconfig hostNetwork: true volumes: - hostPath: path: /etc/kubernetes/admin.conf type: FileOrCreate name: kubeconfig status: {}
解决方案
可以用yq的条件筛选+原地修改语法,直接定位目标环境变量并更新,正确命令如下:
命令1(保留完整配置输出)
cat $file | yq e '.spec.containers[].env[] |= (select(.name == "vip_address") .value = "sdf")'
命令2(更简洁的写法,适用于mikefarah/yq v4+)
yq e '.spec.containers[].env[] | select(.name == "vip_address") .value = "sdf"' $file
命令解释
.spec.containers[].env[]:遍历所有容器下的所有环境变量项select(.name == "vip_address"):精准筛选出name为vip_address的环境变量.value = "sdf":给筛选出的项设置新的value值|=操作符用来原地修改原文档,确保整个Pod配置都被保留,不会只输出修改后的单个环境变量
修改后的效果
更新后,vip_address的value会被正确设置,其余配置保持不变:
env: - name: vip_arp value: "true" - name: vip_leaderelection value: "true" - name: vip_address value: "sdf" - name: vip_interface value: eth0 # 其余环境变量内容不变
内容的提问来源于stack exchange,提问作者Jiri Kremser
相关产品推荐
相关产品推荐

