在Kubernetes中是否有一种方法可以跨命名空间共享机密?
我的使用情况是:我为所有命名空间使用相同的私有注册表,并且我想避免为每个命名空间创建相同的机密。
在Kubernetes中是否有一种方法可以跨命名空间共享机密?
我的使用情况是:我为所有命名空间使用相同的私有注册表,并且我想避免为每个命名空间创建相同的机密。
秘密API对象存储在命名空间中。它们只能被相同命名空间的Pod引用。基本上,您需要为每个命名空间创建该密钥。
有关更多详细信息,请参见此处: Kubernetes文档/概念/配置/Secrets
它们只能被同一命名空间中的 pod 引用。但您可以将 secret 从一个命名空间复制到另一个命名空间。以下是将 default
命名空间中的 localdockerreg
密钥复制到 dev
命名空间的示例:
它们只能被同一命名空间中的 pod 引用。但您可以将 secret 从一个命名空间复制到另一个命名空间。以下是将 default
命名空间中的 localdockerreg
密钥复制到 dev
命名空间的示例:
kubectl get secret localdockerreg --namespace=default --export -o yaml | kubectl apply --namespace=dev -f -
###更新###
在 Kubernetes v1.14 中,--export
标志已被弃用。因此,使用 -oyaml
标志的以下命令将在即将推出的版本中正常工作,无需警告。
kubectl get secret localdockerreg --namespace=default -oyaml | kubectl apply --namespace=dev -f -
如果源命名空间不一定是默认值,则为下面或以下。kubectl get secret localdockerreg --namespace=default -oyaml | grep -v '^\s*namespace:\s' | kubectl apply --namespace=dev -f -
--export
标志)时,出现错误提示“所提供选项的命名空间不匹配”。kubectl 版本为 1.15。我认为你可能需要在这两个 kubectl 命令之间使用 sed
或其他工具来从输出的 YAML 中删除命名空间。 - Matt Dodge$ kubectl get secret <SECRET> --namespace <NS-SRC> -oyaml | grep -v '^\s*namespace:\s' | kubectl apply --namespace <NS-DST> -f -
附注:未测试其他对象类型,但应该可以正常工作。另外,如果您要移动,请不要忘记删除源。 - Costa Shapiro接受的答案是正确的:Secrets 只能被同一命名空间中的 pod 引用。如果您想自动化“同步”或仅在命名空间之间复制 secret,这里有一个提示。
要自动化跨命名空间共享或同步 secret,请使用 ClusterSecret 操作员:
https://github.com/zakkg3/ClusterSecret
kubectl get secret <secret-name> -n <source-namespace> -o yaml \
| sed s/"namespace: <source-namespace>"/"namespace: <destination-namespace>"/\
| kubectl apply -n <destination-namespace> -f -
如果您安装了 jq,我们可以使用 @Evans Tucker 的解决方案。
kubectl get secret cure-for-covid-19 -n china -o json \
| jq 'del(.metadata["namespace","creationTimestamp","resourceVersion","selfLink","uid"])' \
| kubectl apply -n rest-of-world -f -
秘密是有命名空间的资源,但您可以使用Kubernetes扩展来复制它们。我们使用这个方法自动将存储在秘密中的凭据或证书传播到所有命名空间,并保持同步(修改源并更新所有副本)。 请参阅 Kubernetes Reflector (https://github.com/EmberStack/kubernetes-reflector)。
该扩展允许您通过注释自动复制和同步跨命名空间的秘密:
在源机密上添加注释:
annotations:
reflector.v1.k8s.emberstack.com/reflection-auto-enabled: "true"
这将在所有命名空间中创建秘钥的副本。您可以使用以下方法限制创建副本的命名空间:
reflector.v1.k8s.emberstack.com/reflection-allowed-namespaces: "namespace-1,namespace-2,namespace-[0-9]*"
该扩展支持ConfigMaps和cert-manager证书。免责声明:我是Kubernetes Reflector扩展的作者。
--export
已经被废弃。
sed
不适合用于编辑YAML或JSON。
以下是使用 jq
删除我们不需要的命名空间和其他元数据的示例:
kubectl get secret cure-for-covid-19 -n china -o json \
| jq 'del(.metadata["namespace","creationTimestamp","resourceVersion","selfLink","uid"])' \
| kubectl apply -n rest-of-world -f -
ownerReferences
。因此,新的 jq
字符串看起来像这样:
jq 'del(.metadata["namespace","creationTimestamp","resourceVersion","selfLink","uid", "ownerReferences"])'
- phyatt使用RBAC授权服务账户在原始命名空间中使用密钥。但是,不建议在命名空间之间共享密钥。
另一种选择是使用 kubed,这是 Jetstack 公司在提供 cert-manager 时推荐的众多选项之一。 这里是他们提供的链接。
kubed
,而是将其列为三个推荐之一。 - Mohammed Noureldin基于@Evans Tucker的回答,但使用白名单而不是在jq过滤器中删除来仅保留我们想要的内容。
kubectl get secret cure-for-covid-19 -n china -o json | jq '{apiVersion,data,kind,metadata,type} | .metadata |= {"annotations", "name"}' | kubectl apply -n rest-of-world -f -
本质上相同,但保留标签。
kubectl get secret cure-for-covid-19 -n china -o json | jq '{apiVersion,data,kind,metadata,type} | .metadata |= {"annotations", "name", "labels"}' | kubectl apply -n rest-of-world -f -
我想帮助澄清其他答案中发现的两个错误信息。
imagePullSecret
。当然,RBAC可以允许在Pod中运行的应用程序使用kubernetes API或客户端库从另一个命名空间读取Secret。(请参见下面奖励部分中的最小工作示例。)
但是,当共享要在Pod规范的imagePullSecret
字段中使用的Secret时,此方法不起作用。原因如下:
kubelet
,它本身并未在Pod中运行,也没有关联的ServiceAccount。imagePullSecret
只能引用同一命名空间内的Secret。请参阅API参考。kubectl
即可将Secret从一个命名空间复制到另一个命名空间。(无需使用jq
或sed
。)诀窍是模拟应用JSON补丁以将命名空间编辑到现有Secret上,以获取新的Secret文档。
kubectl patch secret \
-n SOURCE-NAMESPACE SECRET-NAME \
--type=json -p='[{"op": "replace", "path": "/metadata/namespace", "value": "DESTINATION-NAMESPACE"}]' \
-o yaml --dry-run=client |
kubectl apply -f -
我不会进一步解释这个示例,因为它不适用于 OP 所谈论的那种秘密。然而,我认为对于那些像我一样被 RBAC 解决方案误导的人来说,这将是有帮助的。
apiVersion: v1
kind: Namespace
metadata:
name: secret-owner-namespace
---
apiVersion: v1
kind: Namespace
metadata:
name: secret-reader-namespace
---
apiVersion: v1
kind: Secret
metadata:
name: example-secret
namespace: secret-owner-namespace
type: Opaque
data:
# echo -n secret-value | base64
SECRET_KEY: c2VjcmV0LXZhbHVl
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader-role
# NOTE: Reader's role is defined inside owner's namespace.
# That is how `resourcesNames` below can be resolved.
namespace: secret-owner-namespace
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["example-secret"]
verbs: ["get", "watch", "list"]
---
# Allow pods in secret-reader-namespace to read the example-secret by:
# binding the default ServiceAccount of the secret-reader-namespace
# to the Role of secret-reader-role.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: secret-reader-rolebinding
namespace: secret-owner-namespace
subjects:
- kind: ServiceAccount
name: default
apiGroup: ""
namespace: secret-reader-namespace
roleRef:
kind: Role
name: secret-reader-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: v1
kind: ConfigMap
metadata:
name: secret-reading-code-configmap
namespace: secret-reader-namespace
data:
read-secret.py: |
from kubernetes import client, config
config.load_incluster_config()
with client.ApiClient() as api_client:
api_instance = client.CoreV1Api(api_client)
name = 'example-secret'
namespace = 'secret-owner-namespace'
api_response = api_instance.read_namespaced_secret(name, namespace)
print(api_response)
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: secret-reader-deployment
namespace: secret-reader-namespace
labels:
app: secret-reader-example
spec:
replicas: 1
selector:
matchLabels:
app: secret-reader-example
template:
metadata:
labels:
app: secret-reader-example
spec:
containers:
- name: secret-reading-container
image: python
command: ["/bin/sh","-c"]
args: ["pip install --no-cache-dir --upgrade kubernetes ; python read-secret.py ; sleep infinity"]
workingDir: /opt/code
volumeMounts:
- name: secret-reading-code-volume
mountPath: "/opt/code"
readOnly: true
volumes:
- name: secret-reading-code-volume
configMap:
name: secret-reading-code-configmap
从@NicoKowe改进
一行代码将一个命名空间中的所有密钥复制到另一个命名空间
$ for i in `kubectl get secrets | awk '{print $1}'`; do kubectl get secret $1 -n <source-namespace> -o yaml | sed s/"namespace: <source-namespace>"/"namespace: <target-namespace>"/ | kubectl apply -n <target-namespace> -f - ; done