【问题标题】:Can I create a file or replace content of a file using Kubernetes?我可以使用 Kubernetes 创建文件或替换文件的内容吗?
【发布时间】:2020-01-16 22:25:10
【问题描述】:

我有一个 React 应用程序,它使用在构建步骤中准备的静态文件托管在 nginx 容器中。我遇到的问题是 API URL 然后被硬编码在 js 文件中,当我想将应用程序部署到不同的环境时遇到问题。

所以基本上我已经将带有 localhost API URL 变量的 config.js 文件放在公共目录中,然后将其加载到 index.html 文件部分的应用程序中。这适用于本地环境。当我想将它部署到测试或生产环境时,问题就来了。

我发现可以将 configMap 与卷挂载一起使用,但据我所知,这需要我提前为每个环境准备一个文件。我希望能够使用我在 Azure DevOps 库中设置的变量来填充 API URL 值。

所以我的问题是,是否有办法使用 Kuberentes/Helm 替换 nginx 容器中的 config.js 文件中的值,或者我是否可以使用 Azure DevOps 管道任务来替换 pre-准备好 config.js 文件并使用 Kubernetes 挂载它?

不确定我想要做什么是否清楚,但希望你能理解它......

config.js

window.env = {
    API_URL: 'http://localhost:8080'
};

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>My application</title>
    <!--
      config.js provides all environment specific configuration used in the client
    -->
    <script src="%PUBLIC_URL%/config.js"></script>
  </head>
  ...

【问题讨论】:

  • 将应用程序配置与部署管道编排器紧密耦合并不是一个好主意。我个人会使用 configmaps。
  • 你能详细说明为什么这不是一个好主意吗?
  • 因为除了在该管道编排工具中创建和管理的管道之外,您无法运行可靠的部署。这使得在该工具的上下文之外进行测试变得困难,并且将来切换到不同的编排平台变得复杂。
  • 好的,这很好。我想这样做的原因是能够在管道中更轻松地添加和删除环境,而无需更改任何代码。正如您所说,如果将应用程序移动到另一个编排平台,它将不会那么好。
  • 可以知道这张票的进度吗?以下两种方法对您有实际帮助吗?如果没有,请不要犹豫,在下面发表评论。

标签: kubernetes azure-devops


【解决方案1】:

您可以通过多种方式实现这一目标。以下是少数。

1.ConfigMap

实现这一目标的最有效和最好的方法,例如添加的 cmets 之一。您可以使用单个配置映射执行类似的操作。

示例 ConfigMap 可能看起来像这样

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.definitionName }}-{{ .Values.envName }}-configmap
  namespace: {{ .Values.Namespace }}
data:
  API_URL: '{{ pluck .Values.envName .Values.API_URL | first }}'

helm 图表中的示例值文件如下所示

API_URL:
  dev: dev.mycompany.io
  staging: staging.mycompany.io
  test: test.mycompany.io
  prod: mycompany.io

在 helm install 或 helm upgrade run 之前,在 Azure devOps 中添加一个步骤以在 CI/CD 管道上运行 bash 命令,但请确保已安装 yq 工具来执行此操作。或者你可以使用任何工具来做同样的事情。

yq w -i values.yaml envName dev

整个过程将您的配置文件替换为API_URLdev.mycompany.io,正如我在yq 工具中提供的dev

但是,如果您对使用 yq 工具或其他工具感到困惑,您可以为每个环境分别设置多个值文件,并在部署中更改 helm install 步骤。

helm install ./path --values ./dev-values.yaml

但是,如果您有多个值文件并操作要从 helm install 中选择的值,您的配置图应该看起来像这样

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Values.definitionName }}-{{ .Values.envName }}-configmap
  namespace: {{ .Values.Namespace }}
data:
  API_URL: '{{ .Values.API_URL }}'

嗯,这是一种做事方式。

2.操作Dockerfile

您也可以使用 dockerfile 执行此操作,类似 dockerfile 中的此步骤将替换文件的值。

RUN sed -i "s/env/dev.mycompany.io/" /app/config.js

但由于每个环境的 url 都是唯一的,您可以使用 ARG 获取值

ARG url

RUN sed -i "s/env/${url}" /app/config.js

在您的构建管道期间,您需要有一个 docker build 任务,并在该任务下将 url 的值作为参数传递,您可以看到任务中的参数列添加此 --build-arg url=dev.mycompany.io

这是向config.js 文件添加值的另一种方法,但它也添加了四个(基于四个环境)docker 构建。因此,您的代理将忙于为每个 git 提交构建四个不同的图像并将其他构建排队。如果您觉得该命令在 Dockerfile 中不起作用,请在您的 docker 文件中添加 RUN cat /app/config.js,您可以调试正在发生的事情并检查值是否在您更改时更新。

同样值得商榷,这是好是坏,但我个人更喜欢第一个,因为我在一小时内提交了很多次,但如果 url 发生变化,你不需要更改你的代码库,你只需要更新你的 docker build管道。所以有点值得商榷。

还有其他方法可以做到这一点。但这两个实现起来有点简单。

希望这有帮助。

【讨论】:

  • 感谢您的回答,正如您所说,在这种情况下,选项 2 不是一个好选择,因为它占用了额外的资源并且需要更长的时间来完成。我会看看第一个选项,看看我是否可以让它发挥作用。
【解决方案2】:

除了@BinaryBullet 提供的方法外,您还可以尝试另一种方法,它可以利用一个Azure DevOps 任务来替换config.js 文件的内容 在此.js 之前与 Kubernetes 一起应用。

Replace Tokens


这个任务的使用很简单。

第一步:

自行配置Token prefix:

第二步:

然后将此Token prefix 应用到您希望将其替换为各种值的config.js 文件中动态

第三步:

不要忘记在变量选项卡中指定您希望传递给config.js的值:

注意:variable name 必须与您在config.js 中配置的相同。在任务运行过程中,它会根据替换格式#{}#same variable name将对应的变量值注入到config.js文件中。

例如,我在第二个屏幕截图中使用了apiurl,所以在这里我添加了一个变量apiurl 并给它一个值,我希望这个值可以在构建时替换到这个config.js 文件中。


构建结果:

这个替换令牌任务没有限制。它可以用于各种类型的文件。请参阅我的另一个类似答案:#1

希望这是可以帮助您实现期望的一个。

【讨论】:

  • 感谢您的回答,这个选项似乎更符合我在 Azure DevOps 中配置它的要求。我将与 BinaryBullet 的第一个选项一起评估它,看看在我的情况下最好使用什么。
【解决方案3】:

我最终做的是这样设置:

首先我添加了一个configmap.yaml来生成config.js文件

apiVersion: v1
kind: ConfigMap
metadata:
  name: config-frontend
data:
  config.js: |-
    window.env = {
      API_URL: "{{ .Values.service.apiUrl }}"
    }

Values.service.apiUrl 来自“打包和部署 Helm 图表”任务中提供的参数 --set service.apiUrl=$(backend.apiUrl)

然后我在deployment.yaml中添加了一个volume mount来替换nginx容器中的config.js文件

...
containers:
  ...
  volumeMounts:
    - name: config-frontend-volume
      readOnly: true
      mountPath: "/usr/share/nginx/html/config.js"
      subPath: "config.js"
volumes:
  - name: config-frontend-volume
    configMap:
      name: config-frontend

这成功了,现在我可以根据我要部署到的环境控制 Azure DevOps 管道中的变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-16
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 1970-01-01
    相关资源
    最近更新 更多