Kubernete的ConfigMap是否可写?

use*_*858 5 kubernetes kubernetes-helm

是否可以直接修改安装的文件configMap?我们有一个应用程序读取configMap类型为的配置文件,并且如果configMap与其他Pod共享并且Pod重新启动,则该应用程序应能够编辑该文件,并且更改应保留。

如果configMap这并不意味着要这样做,那么我们应该consul继续保存配置吗?

Rya*_*son 6

是的,configmap 不可写。如果要与configmap中的文件进行交互,则可以将文件放在可写卷中并装入该卷。或者,您可以按照建议使用集中式配置,如领事。鉴于应用程序正在动态写入此数据,您可以认为它是状态而不是配置。然后可以将其存储在数据库中。另一个选择可以是分布式缓存,例如redis或hazelcast。


sta*_*cks 5

AFAIK 对 a 的更改ConfigMap只会存在于本地内存中。
也就是说,更改对其他 Pod 不可见,并且在 Pod 重新启动时,更改将丢失。

一种解决方案是使用kubectl配置应用程序中的二进制文件或 kubernetes APIConfigMap在配置更改后重新创建。

例如kubectl apply -f /path/to/updated/config.yaml


Cae*_*sar 5

从配置映射的用途来看,@RyanDawson 可能是正确的,但从技术角度来看,它们非常可写。如果你这么做了,你的同伴也不会很差。以 Flink 为例,它通过将其写入配置映射来管理其 HA 状态。

虽然 @stacksonstacks 认为可以使用 kubectl 写入配置映射是正确的,但这只是一半的方法:如果您想从应用程序更新配置映射,这意味着您需要从 k8s 上的应用程序内部对配置映射进行写访问。而且您不太可能希望将您的个人 k8s API 访问令牌秘密存储。

解决此访问问题的最佳解决方案是为应该写入 configmap 的 pod 提供一个服务帐户。该服务帐户需要绑定到允许实际访问的角色。通过服务帐户,Pod 将获得对秘密令牌的访问权限,/var/run/secrets/kubernetes.io/serviceaccount/该令牌可用于访问 kubernetes API。kubectl 也会自动获取此令牌。

我在 kubernetes 文档中找不到完整的示例设置(您可能需要从rbacserviceaccount页面收集详细信息),因此我将添加一个示例设置,该示例设置会持续更新当前时间的 configmap:

---
# Equivalent to whatever would be your application
apiVersion: apps/v1
kind: Deployment
metadata:
  name: configmap-updater
  labels:
    app: configmap-updater
spec:
  selector:
    matchLabels:
      name: configmap-updater
  template:
    metadata:
      labels:
        name: configmap-updater
    spec:
      serviceAccountName: configmap-update-sa # secrets automounted at /var/run/secrets/kubernetes.io/serviceaccount/
      containers:
      - name: configmap-updater-container
        image: archlinux
        # You could also use kubectl patch configmap hello -p '{"data": {"now":"'$(date +%s)'"}}'
        # But I couldn't find an image that has kubectl preinstalled on the spot,
        # so here you go: curl api client
        command: 
          - bash
          - -euc
          - |
            sec=/var/run/secrets/kubernetes.io/serviceaccount
            while true; do
              sleep 10;
              curl -sS \
                   -H "Authorization: Bearer $(cat $sec/token)" \
                   -H "Content-Type: application/json-patch+json" \
                   --cacert $sec/ca.crt \
                   --request PATCH \
                   --data '[{"op": "replace", "path": "/data", "value": {"now":"'$(date +%s)'","updater":"'$(cat /etc/hostname)'"}}]' \
                   https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/default/configmaps/hello
            done
---
# The configmap to be updated
apiVersion: v1
kind: ConfigMap
metadata:
  name: hello
---
# And the access setup
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: configmap-update-sa
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: configmap-update-binding
subjects:
- kind: ServiceAccount
  name: configmap-update-sa
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: configmap-update-role
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: configmap-update-role
# Benefit of using RBAC over giving your personal access token as a secret to your application: You can pinpoint which access you want to allow
rules:
- apiGroups: [""] # Empty string for kubernetes system
  resources: [configmaps]
  resourceNames: [hello]
  verbs: [patch]
Run Code Online (Sandbox Code Playgroud)

(我已经在 minikube 中对此进行了测试,并且知道它在 EKS 中有效。如果这种方法在某些地方不起作用,我很乐意了解它。)

如果更新配置映射以保存状态感觉太脏,一种可能是创建自定义资源定义并为其提供一些状态属性。这可能会更好地表达您的意图。但是您将无法将 CRD 作为文件挂载,并且从 kubernetes 的角度来看,它将非常相同,只是一些数据发生了变化。