更新k8s的ConfigMap或Secret而不删除现有的内容

140

我一直在使用K8S ConfigMap和Secret来管理我们的属性。我的设计非常简单,将属性文件保存在git库中,并使用构建服务器(例如Thoughtworks GO)将它们自动部署为ConfigMaps或Secrets(根据选择条件)到我的k8s集群。

目前,我发现必须经常删除现有的ConfigMap和Secret并创建新的来更新,这真的不太高效,如下所示:

  1. kubectl delete configmap foo

  2. kubectl create configmap foo --from-file foo.properties

是否有一种简单而好的方法可以使上述操作只需一步,并且比删除当前的方式更加高效?潜在地,我现在正在做的可能会危及使用这些configmaps的容器,因为如果容器试图在旧的configmap被删除而新的configmap没有被创建时进行挂载,就会出问题。


我刚刚创建了一个项目,可以自动将ConfigMap映射到环境变量中,对某些人可能很有用。https://github.com/Acanguven/kubernetes-configmap-update - Ahmet Can Güven
6个回答

232
你可以通过 kubectl create configmap 命令获取 YAML 并将其导入到 kubectl apply 中,像这样:
kubectl create configmap foo --from-file foo.properties -o yaml --dry-run=client | kubectl apply -f -

5
管道命令是正确的选择,我没有考虑到 --dry-run,这似乎是该命令的关键部分! - James Jiang
5
这个模式同样适用于 Secrets,除了这里展示的 ConfigMaps 的例子以外。 - rwehner
4
尝试在 Kubernetes 1.10 上进行此操作,但我一直收到错误消息 error: error validating "STDIN": error validating data: [apiVersion not set, kind not set]; if you choose to ignore these errors, turn validation off with --validate=false - yee379
2
这是1.10版本中的一个错误,在1.10.1版本中已经解决 - 请参见https://github.com/kubernetes/kubernetes/issues/61780和https://github.com/kubernetes/kubernetes/pull/61808。 - Jordan Liggitt
8
好的回答。使用kubectl apply而不是kubectl replace,可以同时适用于新的和现有的configmap。 - nahsh
显示剩余5条评论

46

供日后参考,kubectl replace现在是实现此操作的一种非常方便的方式。

kubectl replace -f some_spec.yaml可让您更新完整的configMap(或其他对象)。

直接在此处查看文档和示例。

从帮助中复制/粘贴:

# Replace a pod using the data in pod.json.
kubectl replace -f ./pod.json

# Replace a pod based on the JSON passed into stdin.
cat pod.json | kubectl replace -f -

# Update a single-container pod's image version (tag) to v4
kubectl get pod mypod -o yaml | sed 's/\(image: myimage\):.*$/\1:v4/' | kubectl replace -f -

# Force replace, delete and then re-create the resource
kubectl replace --force -f ./pod.json

4
这里缺少了“--from-file”要求。Configmap不仅可以从yaml文件创建,也可以从任意文件创建。 - Dave Hillier
@sébastien-portebois 谢谢!我不知道 --force 选项,它允许我们在第一次创建 ConfigMap 时使用 <dry-run ConfigMap creation> | kubectl replace --force -f - 命令。但我不确定删除 ConfigMap 是否安全,因为 Pod 可能由于找不到 ConfigMap 而中断。也许更好的方法是使用 <dry-run ConfigMap creation> | kubectl apply -f -?这个点由 @karthic-c 提出,你认为呢? 还有 @jordan-liggitt,你怎么看? - Alex MM
“apply”和什么不同? - Marc

41

对于configMap的小修改,请使用edit

kubectl edit configmap <cfg-name>

这将在vi编辑器中打开configMap。进行更改并保存。


5
好的。然而,正如OP所提到的,这是关于如何通过自动化流程来实现目标,例如在我的情况下使用ThoughtWorks Go作为构建服务器。 - James Jiang

35

kubectl replace 如果一个 configmap 不存在会失败:

$ kubectl create configmap foo --from-file foo.properties -o yaml --dry-run=client | kubectl replace -f -

Error from server (NotFound): error when replacing "STDIN": configmaps "falco-config" not found

最佳解决方案是使用kubectl apply,如果configmap不存在,则会创建configmap,否则会更新configmap:

$ kubectl create configmap foo --from-file foo.properties -o yaml --dry-run=client | kubectl apply -f -

configmap/falco-config configured


7
我觉得你的意思是,“如果一个configmap不存在,kubectl replace会失败”。 - David Dooling
3
这个答案需要被提升或以某种方式获得可见性,因为很多人最终会来到这个页面,寻找一个具有幂等性的解决方案,其中包括配置创建... - Rads
考虑在kubectl create命令中添加“--save-config”。 - Stevo Slavić
1
有一个“—force”标志,可以避免错误并创建它。我还认为apply会执行覆盖,并且可能不会删除您删除的任何键。 - Marc

12

复制现有configmap:

kubectl get configmap foo -o yaml > foo.yaml

然后进行修改并使用apply命令,这样应该可以工作。

kubectl apply -f foo.yaml

注意:如果您遇到以下任何问题,请在现有配置映射中包含最新的“resourceVersion”并重试。
“无法完成对配置映射“foo”的操作:对象已被修改;请将更改应用于最新版本并重试。”

2

你可以考虑使用 GitOps 来实现它。在我的案例中,我使用 ArgoCD 作为 gitops 工具,它会检测 Github 中的 K8S yaml 文件,然后自动应用更改。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接