如何使用Kubernetes yaml文件设置动态值?

onl*_*ine 35 templates yaml config key-value kubernetes

例如,部署yaml文件:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: guestbook
      spec:
        container:
          - name: guestbook
            image: {{Here want to read value from config file outside}}
Run Code Online (Sandbox Code Playgroud)

ConfigMapKubernetes 有一个功能,但它也将键/值写入yaml文件.有没有办法设置环境变量的关键?

whi*_*s11 35

你不能自动完成,你需要使用外部脚本来"编译"你的模板,或者使用@Jakub建议的helm.

您可能希望使用自定义bash脚本,可能与CI管道集成.

给定一个deploy.yml.template与您提供的模板非常相似的模板yml文件,您可以使用以下内容:

#!/bin/bash

# sample value for your variables
MYVARVALUE="nginx:latest"

# read the yml template from a file and substitute the string 
# {{MYVARNAME}} with the value of the MYVARVALUE variable
template=`cat "deploy.yml.template" | sed "s/{{MYVARNAME}}/$MYVARVALUE/g"`

# apply the yml with the substituted value
echo "$template" | kubectl apply -f -
Run Code Online (Sandbox Code Playgroud)


Jak*_*kub 19

我认为无法通过Kubernetes中的变量或Config Map设置图像。但是您可以使用例如Helm来使您的部署更加灵活和可配置。


jon*_*ckt 12

经过尝试sedenvsubst我发现Kustomize是最优雅、最原生的 Kubernetes 方式。作为替代方案,yq有时也会派上用场。

使用 Kustomize 更改图像名称

安装CLI kustomize(例如在 Mac 上)并在与您的目录相同的目录中brew install kustomize创建一个名为的新文件:kustomization.yamldeployment.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - deployment.yaml
Run Code Online (Sandbox Code Playgroud)

现在使用kustomize edit set image命令更改图像名称

# optionally define image name
IMAGE_NAME=ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061

# replace image tag
kustomize edit set image $IMAGE_NAME
Run Code Online (Sandbox Code Playgroud)

最后将您的 kustomized 应用deployment.yml到您的集群中,kubectl apply -k directory/where/your/kustomization/file/is如下所示:

kubectl apply -k .
Run Code Online (Sandbox Code Playgroud)

deployment.yml为了进行调试,如果运行以下命令,您可以看到结果kustomize build .

$ kustomize build .
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: guestbook
    spec:
      containers:
        - image: ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061
          name: guestbook
Run Code Online (Sandbox Code Playgroud)

替代方案:使用 yq 更改图像名称

安装 YAML 处理器 yq(例如通过 homebrew brew install yq),定义变量并让 yq 进行替换:

# define image name
IMAGE_NAME=ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061

# replace image tag
yq e ".spec.template.spec.containers[0].image = \"$IMAGE_NAME\"" -i deployment.yaml
Run Code Online (Sandbox Code Playgroud)

现在你deployment.yaml得到的是新的图像版本,然后看起来像这样:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: guestbook
    spec:
      containers:
        - image: ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061
          name: guestbook
Run Code Online (Sandbox Code Playgroud)

仅供参考:您的deployment.yamlKubernetes 配置不是真正有效的 -template.spec.container不应驻留在metadata标签下 - 而且它的拼写为containers


Cel*_*nHC 11

一条线:

cat app-deployment.yaml | sed "s/{{BITBUCKET_COMMIT}}/$BITBUCKET_COMMIT/g" | kubectl apply -f -
Run Code Online (Sandbox Code Playgroud)

在yaml中:

  ...
  containers:
  - name: ulisses
    image: niceuser/niceimage:{{BITBUCKET_COMMIT}}
  ...
Run Code Online (Sandbox Code Playgroud)

  • 你们都应该获得“猫的无用使用奖”(http://porkmail.org/era/unix/award.html)!sed可以自行读取文件,其余所有参数都解析为输入文件路径。 (2认同)

M U*_*M U 8

您也可以envsubst在部署时使用。

例如

cat $app/deployment.yaml | envsubst | kubectl apply ...
Run Code Online (Sandbox Code Playgroud)

它将文件中的所有变量替换为其值。在部署到多个环境时,我们已经在CI上成功使用了这种方法,并且还将CI_TAG等注入到部署中。

  • 没有 cat 也可以:`envsubst <deployment.yaml | kubectl 应用-f-` (31认同)
  • 您只需将 $YOUR_ENV_NAME 放入文件中即可。 (4认同)
  • 您是否有“envsubset”和“deployment”的示例,以便我们可以看到变量声明和锚点的语法? (2认同)

小智 8

这种事情非常容易ytt

deployment.yml

#@ load("@ytt:data", "data")
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: guestbook
      spec:
        container:
          - name: guestbook
            image: #@ data.values.image
Run Code Online (Sandbox Code Playgroud)

values.yml

#@data/values
image: nginx@sha256:fe2fa7bb1ceb86c6d9c935bc25c3dd8cbd64f2e95ed5b894f93ae7ffbd1e92bb
Run Code Online (Sandbox Code Playgroud)

然后...

$ ytt -f deployment.yml -f values.yml | kubectl apply -f -
Run Code Online (Sandbox Code Playgroud)

或者甚至更好,使用ytt的堂兄,kapp以获得高度控制的部署体验:

$ ytt -f deployment.yml -f values.yml | kapp deploy -a guestbook -f -
Run Code Online (Sandbox Code Playgroud)


Isu*_*nga 7

yaml 不会从另一个 yaml 文件读取值。作为替代方法,您可以尝试这个。

kind: Pod
metadata:
  creationTimestamp: null
  annotations:
    namespace: &namespaceId dev
    imageId: &imgageId nginx
    podName: &podName nginx-pod
    containerName: &containerName nginx-container
  name: *podName
  namespace: *namespaceId
spec:
  containers:
  - image: *imgageId
    name: *containerName
    resources: {}
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
Run Code Online (Sandbox Code Playgroud)

  • @AdamHughes 更好,因为这种方法的值有单一的事实来源。这很重要,因为例如您忘记替换全部,或者一个值存在拼写错误。无需检查所有内容,只需此参考即可。想象一下一个非常长的连接字符串,在文件中的多个位置维护会很乏味。 (2认同)

小智 6

我创建了一个名为的脚本kubectl_create并使用它来运行 create 命令。它将替换环境变量中引用的模板中的任何值。

#!/bin/bash
set -e
eval "cat <<EOF
$(<$1)
EOF
" | kubectl create -f -

Run Code Online (Sandbox Code Playgroud)

例如,如果模板文件有:

apiVersion: v1
kind: Service

metadata:
  name: nginx-external
  labels:
    app: nginx

spec:
  loadBalancerIP: ${PUBLIC_IP}
  type: LoadBalancer
  ports:
  - name: http
    port: 80
    targetPort: 80
  - name: https
    port: 443
    targetPort: 443

  selector:
    app: nginx
Run Code Online (Sandbox Code Playgroud)

运行kubectl_create nginx-service.yaml,然后在运行实际的 kubectl create 命令之前,环境变量 PUBLIC_IP 将被替换。