当它们的configmap被更改/更新时,我如何自动重新启动Kubernetes pod和与部署相关的pod ?
我知道有关于在配置映射发生变化时自动重启pod的讨论,但据我所知,这在Kubernetes 1.2中还没有。
因此(我认为)我想做的是“滚动重新启动”与使用配置映射的pod相关联的部署资源。在Kubernetes中,在不改变实际模板的情况下强制滚动重启部署是否可能?如果可能的话,如何实现?这是目前最好的方式还是有更好的选择?
当它们的configmap被更改/更新时,我如何自动重新启动Kubernetes pod和与部署相关的pod ?
我知道有关于在配置映射发生变化时自动重启pod的讨论,但据我所知,这在Kubernetes 1.2中还没有。
因此(我认为)我想做的是“滚动重新启动”与使用配置映射的pod相关联的部署资源。在Kubernetes中,在不改变实际模板的情况下强制滚动重启部署是否可能?如果可能的话,如何实现?这是目前最好的方式还是有更好的选择?
当前回答
我发现最好的方法是运行Reloader
它允许您定义要监视的配置映射或秘密,当它们更新时,将执行部署的滚动更新。这里有一个例子:
你有一个部署foo和一个名为foo- ConfigMap的ConfigMap。您希望在每次更改configmap时滚动部署的pod。你需要运行Reloader:
kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
然后在部署中指定这个注释:
kind: Deployment
metadata:
annotations:
configmap.reloader.stakater.com/reload: "foo-configmap"
name: foo
...
其他回答
在配置映射更新时向pod发送信号是一个正在工作的功能(https://github.com/kubernetes/kubernetes/issues/22368)。
你总是可以写一个自定义的pid1来通知confimap已经改变并重新启动你的应用程序。
您还可以例如:在两个容器中挂载相同的配置映射,在第二个容器中暴露一个http健康检查,如果配置映射内容的哈希值发生变化,该检查将失败,并将其作为第一个容器的活动探测(因为pod中的容器共享相同的网络名称空间)。当探测失败时,kubelet将为您重新启动第一个容器。
当然,如果您不关心pod在哪些节点上,您可以简单地删除它们,复制控制器将为您“重新启动”它们。
考虑使用kustomize(或kubectl apply -k),然后利用它强大的configMapGenerator特性。例如,来自:https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/configmapgenerator/
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
# Just one example of many...
- name: my-app-config
literals:
- JAVA_HOME=/opt/java/jdk
- JAVA_TOOL_OPTIONS=-agentlib:hprof
# Explanation below...
- SECRETS_VERSION=1
然后在部署中引用my-app-config即可。当使用kustomize构建时,它会自动查找并更新my-app-config的引用,并使用更新的后缀,例如my-app-config-f7mm6mhf59。
额外的好处是,更新秘密:我还使用此技术强制重新加载秘密(因为它们以同样的方式受到影响)。虽然我个人完全单独管理我的秘密(使用Mozilla sops),但您可以将配置映射与您的秘密捆绑在一起,例如在您的部署中:
# ...
spec:
template:
spec:
containers:
- name: my-app
image: my-app:tag
envFrom:
# For any NON-secret environment variables. Name is automatically updated by Kustomize
- configMapRef:
name: my-app-config
# Defined separately OUTSIDE of Kustomize. Just modify SECRETS_VERSION=[number] in the my-app-config ConfigMap
# to trigger an update in both the config as well as the secrets (since the pod will get restarted).
- secretRef:
name: my-app-secrets
然后,像我上面所做的那样,在ConfigMap中添加一个像SECRETS_VERSION这样的变量。然后,每次更改my-app-secrets时,只需增加SECRETS_VERSION的值,这除了触发kustomize'd ConfigMap名称的更改外,没有其他用途,这也应该导致重新启动pod。然后就变成:
我发现最好的方法是运行Reloader
它允许您定义要监视的配置映射或秘密,当它们更新时,将执行部署的滚动更新。这里有一个例子:
你有一个部署foo和一个名为foo- ConfigMap的ConfigMap。您希望在每次更改configmap时滚动部署的pod。你需要运行Reloader:
kubectl apply -f https://raw.githubusercontent.com/stakater/Reloader/master/deployments/kubernetes/reloader.yaml
然后在部署中指定这个注释:
kind: Deployment
metadata:
annotations:
configmap.reloader.stakater.com/reload: "foo-configmap"
name: foo
...
目前这个问题的最佳解决方案(在兄弟回答的https://github.com/kubernetes/kubernetes/issues/22368链接中有深入引用)是使用部署,并将configmap视为不可变的。
当您想要更改配置时,请创建一个带有您想要进行更改的新ConfigMap,并将部署指向新的ConfigMap。如果新的配置被破坏,部署将拒绝缩小您的工作ReplicaSet。如果新的配置有效,那么旧的ReplicaSet将被缩放为0副本并删除,新的pod将使用新的配置启动。
虽然没有编辑ConfigMap那么快,但是更安全。
另一种方法是将其插入部署的命令部分:
...
command: [ "echo", "
option = value\n
other_option = value\n
" ]
...
或者,为了使它更像configmap,使用一个额外的部署,它只会在命令节中托管该配置,并在其上执行kubectl create,同时在其名称中添加一个唯一的“版本”(比如计算内容的哈希值),并修改所有使用该配置的部署:
...
command: [ "/usr/sbin/kubectl-apply-config.sh", "
option = value\n
other_option = value\n
" ]
...
我可能会发布kubectl-apply-config.sh,如果它最终能够工作的话。
(不要那样做;看起来太糟糕了)