所有的pod都是基于ubuntu docker镜像构建的。然而,在ubuntu上将ca证书添加到信任列表的方法(使用dpkg-reconfigure ca-certificates)在这个pod上不再起作用。当然,即使我成功地将ca证书添加到一个pod的信任根上,当另一个pod启动时它就会消失。
我搜索了Kubernetes文档,惊讶地发现除了配置证书与API服务通信之外,没有找到任何其他内容,而这不是我正在寻找的。如果需要在pod之间建立安全通道,应该是非常普遍的情况。有什么想法吗?
更新编辑,读取选项3:
如果我处于您的情境中,我可以想到3种解决问题的方法:
(我能提供的唯一完整解决方案,不幸的是我的其他解决方案只是半个解决方案,感谢Paras Patidar/以下网站 :)
将证书添加到配置映射中:
假设你的PEM文件为my-cert.pem
kubectl -n <namespace-for-config-map-optional> create configmap ca-pemstore — from-file=my-cert.pem
将配置映射作为容器现有CA根位置的卷挂载: 在卷挂载中,将该配置映射的文件作为一个对应于/etc/ssl/certs/目录下的文件的一对一关系进行挂载
apiVersion: v1
kind: Pod
metadata:
name: cacheconnectsample
spec:
containers:
- name: cacheconnectsample
image: cacheconnectsample:v1
volumeMounts:
- name: ca-pemstore
mountPath: /etc/ssl/certs/my-cert.pem
subPath: my-cert.pem
readOnly: false
ports:
- containerPort: 80
command: [ "dotnet" ]
args: [ "cacheconnectsample.dll" ]
volumes:
- name: ca-pemstore
configMap:
name: ca-pemstore
我认为这里的想法是/etc/ssl/certs/是pod信任的tls证书的位置,而subPath方法允许您添加一个文件,而不会清除含有k8s secrets的文件夹的内容。
如果所有的pod都共享这个mountPath,那么你可能能够为每个命名空间添加一个存在的pod和configmap,但这只对静态命名空间有用。但是如果这是真的,那么你的所有pod都会信任那个证书。
Option 2):
理论上,您应该能够利用cert-manager + external-dns + Lets Encrypt Free +公共域名来替换自签名证书。在您的集群中,cert-manager的最终结果是自动生成由Lets Encrypt Free签名的k8s tls secret,他们有一个dns01挑战可以用来证明您拥有该证书,这意味着即使没有入口/即使集群仅用于私有网络,您也应该能够利用该解决方案。
Option 3):
我认为switchboard.op的答案可能是最好的/应该成为被接受的答案。这个东西可以在运行时完成,但我认为它永远不应该在运行时完成,因为在运行时完成这个操作非常hacky且充满了边缘情况/没有一个通用的解决方案。
同时,我的Option 1只是部分正确的。仅仅将ca.crt挂载到pod上是不够的。在该文件挂载到pod之后,您需要运行一个命令来信任它。这意味着您可能需要覆盖pod的启动命令。例如,您不能做像连接数据库(默认启动命令)然后更新受信任的CA证书的命令。您必须覆盖启动文件以手工编写、覆盖默认启动脚本、更新受信任的CA证书、连接数据库。问题是Ubuntu、RHEL、Alpine和其他操作系统有不同的位置,您必须在其中安装CA证书,并且有时需要不同的命令来信任CA证书,因此在集群中应用于所有pod以更新其ca.cert的运行时通用解决方案并非不可能,但会需要大量的if语句和变异的webhooks/复杂性。如果您只需要能够为单个pod动态更新它,则可以使用手工制作的每个pod解决方案。
switchboard.op的答案是我要回答的方式。通过将自定义的ca.cert信任嵌入到新的自定义docker镜像中,构建一个新的自定义docker镜像。这是一种通用的解决方案,并大大简化了YAML的一面。在docker镜像方面,这相对容易做到。
COPY my-cert.crt /usr/local/share/ca-certificates/
RUN update-ca-certificates
如果你试图在运行时更新信任,事情会变得更加复杂。我自己没有做过这个操作,但你可以尝试创建一个包含证书的configMap
,将其挂载到上面提到的路径中的容器中,然后使用入口点脚本在主进程之前运行update-ca-certificates
。
update-ca-certificates
的方式是,如果容器未以 root 用户身份运行,则很可能会失败... initContainers 是另一个更复杂的选项。 - Gert van den Berg仅供好奇,这里是一个使用初始化容器方法的清单示例。
---
apiVersion: v1
kind: ConfigMap
metadata:
name: demo
data:
# in my case it is CloudFlare CA used to sign certificates for origin servers
origin_ca_rsa_root.pem: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
---
apiVersion: v1
kind: Pod
metadata:
name: demo
labels:
name: demo
spec:
nodeSelector:
kubernetes.io/os: linux
initContainers:
- name: init
# image: ubuntu
# command: ["/bin/sh", "-c"]
# args: ["apt -qq update && apt -qq install -y ca-certificates && update-ca-certificates && cp -r /etc/ssl/certs/* /artifact/"]
# # alternative image with preinstalled ca-certificates utilities
image: grafana/alpine:3.15.4
command: ["/bin/sh", "-c"]
args: ["update-ca-certificates && cp -r /etc/ssl/certs/* /artifact/"]
volumeMounts:
- name: demo
# note - we need change extension to crt here
mountPath: /usr/local/share/ca-certificates/origin_ca_rsa_root.crt
subPath: origin_ca_rsa_root.pem
readOnly: false
- name: tmp
mountPath: /artifact
readOnly: false
containers:
- name: demo
# note - even so init container is alpine base, and this one is ubuntu based everything still works
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: tmp
mountPath: /etc/ssl/certs
readOnly: false
volumes:
- name: demo
configMap:
name: demo
# will be used to pass files between init container and actual container
- name: tmp
emptyDir: {}
以及它的使用:
kubectl apply -f demo.yml
kubectl exec demo -c demo -- curl --resolve foo.bar.com:443:10.0.14.14 https://foo.bar.com/swagger/v1/swagger.json
kubectl delete -f demp.yml
注意事项:
实际上这有点丑陋和庞大,但至少它能够工作并证明了概念。使用简单ConfigMap的解决方法不起作用,因为curl会读取ca-certificates.crt文件,而在该方法中没有对其进行修改。
kubectl -n my-namespace create configmap my-cert --from-file=root_ca_only.crt
...
volumes:
- name: my-cert
configMap:
defaultMode: 420
name: my-cert
...
...
volumeMounts:
- mountPath: /usr/local/share/ca-certificates/root_ca_only.crt
name: my-cert
subPath: root_ca_only.crt
...
lifecycle:
postStart:
exec:
command:
- sh
- -c
- sleep 10; update-ca-certificates
Secret
而不是ConfigMap
来部署根CA证书。 - Umar Farooq Khawaja