1

我有大约 200-300 个 yaml 文件,我想要实现的是仅更改图像:我的几个 yaml 文件中的选项,我有一个可以获取所需 yaml 文件的 shell 脚本,我只想实现改变图像:key only。

解决方案尝试:

使用了一个工具yq v4:

for i in ${deployment[@]}
 do
 yq eval '( select(.spec.template.spec.containers[0].image |= "gcr.io/myrepo/mynginx:1.2.3"'  deployment-$i.yaml
done

此命令的作用是实现更改映像的预期结果,但它还将更改附加到部署文件的所有部分,例如在文件中每个规范的末尾:

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: portal-1
        spec:
          selector:
            matchLabels:
              component: portal-1
              role: ui
          replicas: 1
          template:
            metadata:
              labels:
                component: reactportal
                role: ui
            spec:
              containers:
                - name: portal
                  image: gcr.io/myrepo/mynginx:4.52 <<< Desired CHange Happens Here >>>
        ---
        
        apiVersion: extensions/v1beta1
        kind: Ingress
        metadata:
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$1
        nginx.ingress.kubernetes.io/enable-cors: "false"
        nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com"
      name: portal-ingress
    spec:
      rules:
        - host: mydomain.com
          http:
            paths:
              - backend:
                  serviceName: portal-svc
                  servicePort: 80
                path: /(.*)
 template:                                                  <<<< THIS IS ALSO GETTING APPENDED >>>
        spec:
          containers:
            - image: gcr.io/myrepo/mynginx:1.2.3

如何在不将图像附加到部署文件的每个部分的情况下获得所需的结果?

4

2 回答 2

1

这应该会给你预期的结果:

for i in ${deployment[@]}; do
  yq eval '.spec|=select(.selector.matchLabels.component=="portal-1")
                 .template.spec.containers[0].image =
                    "gcr.io/myrepo/mynginx:1.2.3"' deployment-$i.yaml
done
于 2021-05-07T17:23:09.920 回答
1

它必须是yq吗?

我会用一个相当简单bash的单行来做到这一点,使用sed

for i in {1..3}; do sed -i "s/image.*/image: mysql:latest/" deployment-$i.yaml; done

上面的命令搜索字符串,"image"然后是任何其他字符,直到行尾(因此它需要整个字符串image: "my-fancy-image-name")并将其替换为全新的字符串 - 在上面的示例中,新字符串是image: mysql:latest.

选项-i--in-place用于就地编辑文件,即编辑原始文件并使用新内容保存。

唯一的假设是您的部署文件有一个固定的命名约定,即上述示例的正确名称是:deployment-1.yamldeployment-2.yaml

如果您想像示例中那样将图像名称放在双引号中,可以这样做:

for i in {1..3}; do sed -i "s/image.*/image: \"gcr.io\/myrepo\/mynginx:1.2.3\"/" deployment-$i.yaml; done

如您所见,某些对sed命令具有特殊含义的字符,例如"/必须用\字符转义,以便它们可以在替换字符串中使用。

实际上,使用上述脚本时还有一个假设,即"image"字符串在您的Deployment. 如果是这种情况,您无需担心添加g全局替换选项(搜索字符串的每次出现)。上面的示例将仅在"image"字符串第一次出现时执行替换,这应该满足您的要求。如果您有多个容器的部署,例如一个 init 容器或 sidecar,那么您很可能不会对将image此类部署中的每一个都更改为相同的单个值感兴趣。

于 2021-05-07T15:51:40.760 回答