如何在Kubernetes集群中把Vault用起来

简介: ## 1 Vault是什么? 如何在云上应用中管理和保护用户的敏感信息是一个经常令开发者头疼的问题,用户的密码口令,证书秘钥等私密信息时常未经加密被随意的放置在配置文件,代码仓库或是共享存储里,而对于普通的开发者来说,设计和实现一套完整的秘钥管理系统是一个很大的挑战。且不论令人生畏的加解密算法,很多的云应用仍然将一些敏感配置信息仅仅经过base64等一些简单的hash运算就放置在某个公共的配

1 Vault是什么?

如何在云上应用中管理和保护用户的敏感信息是一个经常令开发者头疼的问题,用户的密码口令,证书秘钥等私密信息时常未经加密被随意的放置在配置文件,代码仓库或是共享存储里,而对于普通的开发者来说,设计和实现一套完整的秘钥管理系统是一个很大的挑战。且不论令人生畏的加解密算法,很多的云应用仍然将一些敏感配置信息仅仅经过base64等一些简单的hash运算就放置在某个公共的配置中心上,而很多时候这些敏感信息会从应用的某行异常日志或是某段监控告警中泄露出去;不仅如此,对于一个集中式的秘钥管理系统,如何面向用户进行更细粒度的访问鉴权也是一个难题。

image.png

Vault的出现给了上述问题一个解决方案,它是HashiCorp公司(旗下还有Vagrant,Terraform,Consul等知名产品)维护的开源软件,它的设计思想基于云原生背景下动态基础设施的特点,在云上的不同网络层以及不同的服务之间已经很难找到传统的信任边界,服务之间更加强调以身份(identity)为核心的认证和访问控制,而不是像传统静态基础设施中以IP、主机地址作为信任凭证。为此Vault提供了以下几个功能点:

  • Secret存储形式的多样性,任意的kv形式敏感信息(如数据库密码,证书,ssh登录秘钥,openapi身份凭证等);
  • 存储格式的多样性,支持插件式的存储引擎扩展,可对接如AWS,Consul,NoSQL,KV,PKI,SSH等多种插件引擎;
  • 支持与各类平台的认证对接,可动态生成认证凭据或配置信息;
  • 支持基于Shamir算法的私钥分割完成Vault后端的加封和解封操作,同时支持高可用的部署形态;
  • 支持各类secret的动态生成,续租,撤销和滚动更新;
  • 完备的审计日志;
  • 完备的CLI和RESTful API

2 Vault与k8s的集成

Vault松耦合的架构使其支持与多种secret引擎和相应的存储后端对接,同时支持与多种认证服务器的交互
本节我们主要介绍Vault与k8s的集成。

2.1 Vault在Kubernetes中的应用场景

Vault作为企业级的secret管理工具,是一些大客户在业务上云过程中的安全强需求,尤其是国外市场。在Kubernetes集群中主要有以下应用场景:

  • 作为部署在Kubernetes集群中的应用对外提供秘钥管理服务,支持与多家主流云厂商秘钥服务以及多种secrets形式的对接,支持多种数据库服务的存储对接,同时支持多种认证形式的对接。
  • 作为一个公共的加密服务(Encryption as a Service)而不做后端存储的对接,帮助用户应用剥离繁琐的加密加解密逻辑。
  • 面向政府、金融等对数据安全规格有很高要求的客户,Vault支持基于Two-man原则利用私钥分割算法对后端服务进行加解封,并结合k8s的高可用部署形态为企业提供更加安全可靠的secret管理能力。
    当然这里只是列举了一些Vault原生提供的能力,作为一个在Kubernetes集群上直接运行的安全应用,任何一个面向k8s的应用工具都可以利用其安全能力。

2.2 安装Vault

Vault支持helm化安装,在其官方文档中我们可以找到关于启动参数的详细配置说明,同时在阿里云容器服务的应用目录apphub中我们也可以通过控制台在ACK集群中方便的安装Vault
image.png

另外Vault的默认安装也集成了其控制台的安装,通过负载均衡服务或ingress路由的方式我们可以在公网访问其UI,在vault pod的日志中我们可以找到登录使用的root token,在控制台中可以方便的设定与存储引擎和认证方式的对接,同时还可以进行基于策略的访问控制配置。
image.png

2.3 认证方式的集成

当用户希望在k8s pod的业务逻辑中与Vault服务端通讯,获取需要的secrets时,首先Vault会对这个pod中的请求进行认证,那么这个pod中的Vault请求认证凭据应该如何获取呢?如上所述,Vault后端支持多种认证方式的对接,对于Kubernetes,Vault支持基于K8s Service Account Token的认证。

使用上,Vault管理员首先需要在后端enable kubernetes的认证方式,生成一个与Vault交互的指定sa,然后通过CLI或API将sa token和集群ca,公网地址等信息写入到Vault后端中,并配置与vault后端的ACL策略绑定。详细步骤请参见官方文档

当然在pod应用中可以并不局限于一定使用基于sa的kubernetes认证方式。比如[kubernetes-vault]( https://github.com/Boostport/kubernetes-vault
)。该项目使用Vault中的[AppRole](https://www.vaultproject.io/docs/auth/approle.html
)认证方式,在该认证模式中,管理员可以为不同的pod创建不同的Vault原生role模型并绑定到对应的policy上,同时可以基于role创建secret_id,secret_id对应的token可作为与Vault进行认证的临时凭证。kubernetes-vault利用了AppRole的认证交互模式,首先已经完成安装的kubernetes-vault controller会去Watch集群中所有pod的创建,当发现新建pod的部署模板中有指定annotation的init-container存在时,controller会根据模板中指定的vault role id去Vault请求获取其对应的secret_id并发送给init-container中kubernetes-vault的客户端,在应用容器启动前kubernetes-vault客户端用controller返回的secret_id和role_id去Vault请求真正的login token并最终写入到与应用pod共享的挂载目录中;同时客户端会根据token过期时间进行定时的轮转,保证其可用性。下图为kubernetes-vault工作流程图:

image.png

在社区也存在不少基于k8s与Vault进行认证对接的其他方案,其设计思路大同小异,基本都采用了通过init-container或sidecar方式引入一个额外的客户端去Vault请求指定认证模式下的短时凭证并共享给业务容器使用。
在容器服务控制台的应用目录apphub中,我们同样可以找到kubernetes-vault,方便开发者使用helm直接在集群指定命名空间一键部署。Vault也计划在后续自己的官方版本helm chart中增加配置项以支持上述登录认证secret的动态注入。

3 Vault与阿里云RAM的集成

当我们在应用中需要访问阿里云资源时,需要使用RAM账号对应的AK或是STS临时credentials作为访问相应资源接口的凭证。如果使用账号AK,如何使其能够被应用逻辑获取的同时保证AK的安全性一直是一个头疼的问题;如果使用临时sts token,由于其时效性,我们也需要在考虑安全性的同时思考如何进行临时访问凭证的轮转。相比较两种方式,使用sts临时凭证的方式肯定在安全上是更为推荐的方式,同时对这种动态secret的安全管理也正是Vault的优势所在。本节我们来介绍下Vault与阿里云RAM在认证方式和secret管理引擎上的集成。

3.1 认证方式的集成

首先在认证方式上,Vault服务端的role模型可以与RAM role进行一对一的映射匹配,用户可以使用Vault提供的OpenAPI或是CLI,通过传入扮演RAM role返回的临时凭证调用GetCallerIdentity接口,然后Vault服务端会根据请求返回的角色arn id在其后端存储中查找是否有对应的权限策略配置,如果存在则认证成功并返回一个可用于调用Vault其他后端接口的访问token。

3.2 Vault Secret引擎与RAM的集成

当我们需要在业务应用逻辑中使用阿里云资源时,通常需要通过角色扮演的方式获取一个RAM返回的临时凭证,然后通过这个临时凭证完成与RAM的鉴权过程。由于凭证的时效性,我们在保证其安全性的同时还要维护一个对应的秘钥轮转机制。Vault的secret引擎实现了与阿里云RAM的对接插件,帮助我们安全、动态的管理RAM凭证,其主要步骤 如下:

1.开启后端引擎

2.在RAM控制台为Vault服务器创建专属子账号并绑定定制化权限策略

3.获取Vault子账号对应的AK并通过Vault CLI/API写入到后端指定路径下

4.在Vault后端写入业务中希望获取的RAM凭证所对应的策略定义或角色,其中策略定义支持inline和remote策略两种形式,所谓inline模式是指直接在api请求中写入策略模板,remote模式指写入RAM中存在的策略类型和名称,比如:

$ vault write alicloud/role/policy-based \
    remote_policies='name:AliyunOSSReadOnlyAccess,type:System' \
    remote_policies='name:AliyunRDSReadOnlyAccess,type:System'

角色模式需要用户指定希望被扮演的角色arn,另外需要Vault子账号在该角色的受信实体里,一个示例如下:

$ vault write alibaba/role/role-based \
role_arn='acs:ram::5138828231865461:role/hastrustedactors'

5.在具体的业务应用中,只需要通过调用Vault的creds/policy-based或role-based接口即可动态获取相应的RAM访问凭证,下面是一个角色扮演返回临时token的CLI调用示例:

$ vault read alicloud/creds/role-based
Key                Value
---                -----
lease_id           alicloud/creds/role-based/f3e92392-7d9c-09c8-c921-575d62fe80d9
lease_duration     59m59s
lease_renewable    false
access_key         STS.L4aBSCSJVMuKg5U1vFDw
secret_key         wyLTSmsyPGP1ohvvw8xYgB29dlGI8KMiH2pKCNZ9
security_token     CAESrAIIARKAAShQquMnLIlbvEcIxO6wCoqJufs8sWwieUxu45hS9AvKNEte8KRUWiJWJ6Y+YHAPgNwi7yfRecMFydL2uPOgBI7LDio0RkbYLmJfIxHM2nGBPdml7kYEOXmJp2aDhbvvwVYIyt/8iES/R6N208wQh0Pk2bu+/9dvalp6wOHF4gkFGhhTVFMuTDRhQlNDU0pWTXVLZzVVMXZGRHciBTQzMjc0KgVhbGljZTCpnJjwySk6BlJzYU1ENUJuCgExGmkKBUFsbG93Eh8KDEFjdGlvbkVxdWFscxIGQWN0aW9uGgcKBW9zczoqEj8KDlJlc291cmNlRXF1YWxzEghSZXNvdXJjZRojCiFhY3M6b3NzOio6NDMyNzQ6c2FtcGxlYm94L2FsaWNlLyo=
expiration         2018-08-15T21:58:00Z

4 如何在k8s应用中使用Vault Secret

在了解了Vault的基本概念以及与Kubernetes的认证交互流程后,我们进入客户最为关心的话题。如何在k8s pod应用中方便地获取Vault服务端管理的secret。社区针对此问题也有激烈的讨论和不少相关解决方案,方案主要集中在两个方向:

**[定时同步进程](https://github.com/hashicorp/vault/issues/7364
)**:使用一个同步进程定时地从Vault服务端获取指定范围的秘钥更新并同步到k8s集群中的secret模型,代表的项目有vaultingkube 和[secrets-manager]( https://github.com/tuenti/secrets-manager
) 。其主要设计思想也不尽相同,以secrets-manager为例,首先用户可以通过CRD定义在Vault中关注的secret数据源,然后secrets-manager对应的controller会在Reconcile函数中定时对比指定管理范围内的k8s secret和vault secret的状态,如果不一致则进行一次调协。而用户在pod应用中可以直接引用原生secret模型中的内容获取远端Vault服务器中的秘钥。
当然社区中也存在一些对这种秘钥同步方案的质疑,比如认为该方案在秘钥同步的传输过程和用户pod使用原生secret的rest交互中会增加攻击面,但是该方案在部署实施上比较友好,也得到了很多用户的支持。

CSI插件形式集成:该方案基于CSI plugin将Vault中的秘钥通过volume的形式挂载到pod应用中。
secrets-store-csi-driver 通过实现一套基于CSI规范的driver机制可以对接不同厂商的后端存储,而Vault secret的driver(secrets-store.csi.k8s.com)允许kubelet将各类企业级秘钥存储中的secret通过volume挂载,一旦attach动作完成,秘钥数据即挂载到了容器对应的文件系统中。在CSI driver的基础上,不同的秘钥管理后端可以实现定制化的provider去对接CSI driver框架中的规定接口。provider的功能概括如下:

  • 对接后端秘钥管理系统,提供秘钥获取等必须的接口实现
  • 适配当前CSI driver的接口定义
  • 通过框架中的回调函数无需调用Kubernetes API即可将从后端获取的秘钥数据挂载到指定路径下

HashiCorp官方也基于此框架实现了一套对接Vault的Provider。这里我们以此为例具体来看下在一个k8s pod应用中如何通过CSI plugin的方式使用Vault中管理的secret秘钥。

1 首先我们创建一个开启了CSI存储插件的ACK集群,然后参考文档在集群中部署Vault服务端,为了便于验证这里我们使用dev模式省去unseal解封等流程,同时配置provider与Vault交互的认证模式和相应的访问控制策略

image.png
然后通过cli向Vault后端写入测试数据
image.png

2 通过官方提供的helm方式安装Secret Store CSI Driver,命令如下:

helm install . -n csi-secrets-store --namespace dev --set providers.vault.enabled=true

安装成功后如下图所示:
image.png

3 在集群中创建secretproviderclasses实例用于Secret Store CSI Driver与Vault的参数对接,一个示例如下,注意这里的vault服务端地址可通过kubectl get service vault获取。
image.png

4 最后我们来看下如何在应用pod中对接上述provider实例获取对应的Vault秘钥。这里pod对于上述vault provider的使用分为两种方式:

1)如果pod运行的目标集群版本在v1.15.0以上,且集群apiserver和节点kubelet manifest配置均开启了 CSIInlineVolume=true的feature-gates,则我们可以在pod中的volume字段内置声明需要使用的csi provider实例。

kind: Pod
apiVersion: v1
metadata:
  name: nginx-secrets-store-inline
spec:
  containers:
  - image: nginx
    name: nginx
    volumeMounts:
    - name: secrets-store-inline
      mountPath: "/mnt/secrets-store"
      readOnly: true
  volumes:
    - name: secrets-store-inline
      csi:
        driver: secrets-store.csi.k8s.com
        readOnly: true
        volumeAttributes:
          secretProviderClass: "vault-foo"

2)如果目标集群不支持CSI的Inline Volume特性,我们需要首先创建使用csi的pv和对应的pvc实例,一个pv模板示例如下:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-vault
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadOnlyMany
  persistentVolumeReclaimPolicy: Retain
  csi:
    driver: secrets-store.csi.k8s.com
    readOnly: true
    volumeHandle: kv
    volumeAttributes:
      providerName: "vault"
      roleName: "example-role"
      vaultAddress: http://172.21.12.21:8200
      vaultSkipTLSVerify: "true"
      objects:  |
        array:
          - |
            objectPath: "/foo"
            objectName: "bar"
            objectVersion: ""

在pod实例模板中引用指定pvc即可在pod中获取到vault,这里我们在ACK集群以pv/pvc模式为例创建一个nginx应用容器实例并在其中挂载上文中我们创建的secretproviderclasses实例:
image.png

相比于secrets-manager等采用secret定时同步的方式,使用CSI对接指定Vault secret provider实例的方式虽然在实施步骤上比较复杂,同时在应用中也无法动态获取Vault后端secret的变更,但是该方案避免了secret在同步链路上频繁传输的安全风险,同时也客服了之前describe po可能造成的秘钥泄露,在整体安全性上要高出不少。大家可以根据实际应用场景选择适合自己的方式。

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
2月前
|
人工智能 算法 调度
阿里云ACK托管集群Pro版共享GPU调度操作指南
本文介绍在阿里云ACK托管集群Pro版中,如何通过共享GPU调度实现显存与算力的精细化分配,涵盖前提条件、使用限制、节点池配置及任务部署全流程,提升GPU资源利用率,适用于AI训练与推理场景。
266 1
|
2月前
|
弹性计算 监控 调度
ACK One 注册集群云端节点池升级:IDC 集群一键接入云端 GPU 算力,接入效率提升 80%
ACK One注册集群节点池实现“一键接入”,免去手动编写脚本与GPU驱动安装,支持自动扩缩容与多场景调度,大幅提升K8s集群管理效率。
240 89
|
7月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
ACK One 的多集群应用分发,可以最小成本地结合您已有的单集群 CD 系统,无需对原先应用资源 YAML 进行修改,即可快速构建成多集群的 CD 系统,并同时获得强大的多集群资源调度和分发的能力。
287 9
|
7月前
|
资源调度 Kubernetes 调度
从单集群到多集群的快速无损转型:ACK One 多集群应用分发
本文介绍如何利用阿里云的分布式云容器平台ACK One的多集群应用分发功能,结合云效CD能力,快速将单集群CD系统升级为多集群CD系统。通过增加分发策略(PropagationPolicy)和差异化策略(OverridePolicy),并修改单集群kubeconfig为舰队kubeconfig,可实现无损改造。该方案具备多地域多集群智能资源调度、重调度及故障迁移等能力,帮助用户提升业务效率与可靠性。
|
9月前
|
存储 Kubernetes 监控
K8s集群实战:使用kubeadm和kuboard部署Kubernetes集群
总之,使用kubeadm和kuboard部署K8s集群就像回归童年一样,简单又有趣。不要忘记,技术是为人服务的,用K8s集群操控云端资源,我们不过是想在复杂的世界找寻简单。尽管部署过程可能遇到困难,但朝着简化复杂的目标,我们就能找到意义和乐趣。希望你也能利用这些工具,找到你的乐趣,满足你的需求。
853 33
|
9月前
|
Kubernetes 开发者 Docker
集群部署:使用Rancher部署Kubernetes集群。
以上就是使用 Rancher 部署 Kubernetes 集群的流程。使用 Rancher 和 Kubernetes,开发者可以受益于灵活性和可扩展性,允许他们在多种环境中运行多种应用,同时利用自动化工具使工作负载更加高效。
495 19
|
9月前
|
人工智能 分布式计算 调度
打破资源边界、告别资源浪费:ACK One 多集群Spark和AI作业调度
ACK One多集群Spark作业调度,可以帮助您在不影响集群中正在运行的在线业务的前提下,打破资源边界,根据各集群实际剩余资源来进行调度,最大化您多集群中闲置资源的利用率。
|
12月前
|
Prometheus Kubernetes 监控
OpenAI故障复盘 - 阿里云容器服务与可观测产品如何保障大规模K8s集群稳定性
聚焦近日OpenAI的大规模K8s集群故障,介绍阿里云容器服务与可观测团队在大规模K8s场景下我们的建设与沉淀。以及分享对类似故障问题的应对方案:包括在K8s和Prometheus的高可用架构设计方面、事前事后的稳定性保障体系方面。
|
9月前
|
Prometheus Kubernetes 监控
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
309 0
OpenAI故障复盘丨如何保障大规模K8s集群稳定性
|
11月前
|
缓存 容灾 网络协议
ACK One多集群网关:实现高效容灾方案
ACK One多集群网关可以帮助您快速构建同城跨AZ多活容灾系统、混合云同城跨AZ多活容灾系统,以及异地容灾系统。

推荐镜像

更多