如何在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可能造成的秘钥泄露,在整体安全性上要高出不少。大家可以根据实际应用场景选择适合自己的方式。

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
目录
相关文章
|
5天前
|
Kubernetes 微服务 容器
Aspire项目发布到远程k8s集群
Aspire项目发布到远程k8s集群
32 2
Aspire项目发布到远程k8s集群
|
9天前
|
存储 运维 监控
Kubernetes 集群监控与日志管理实践
【5月更文挑战第28天】在微服务架构日益普及的当下,容器编排工具如 Kubernetes 已成为运维工作的核心。有效的集群监控和日志管理是确保系统稳定性和服务可靠性的关键。本文将深入探讨 Kubernetes 集群的监控策略,以及如何利用现有的工具进行日志收集、存储和分析,以实现对集群健康状况的实时掌握和问题快速定位。
|
10天前
|
存储 监控 Kubernetes
Kubernetes 集群监控与日志管理实践
【5月更文挑战第27天】 在微服务架构日益普及的当下,容器化技术与编排工具如Kubernetes已成为现代云原生应用的基石。然而,随着集群规模的不断扩大和复杂性的增加,如何有效监控和管理这些动态变化的服务成为了维护系统稳定性的关键。本文将深入探讨Kubernetes环境下的监控策略和日志管理的最佳实践,旨在为运维人员提供一套系统的解决思路,确保应用性能的最优化和问题的快速定位。
|
6天前
|
运维 Kubernetes 调度
【kubernetes】关于k8s集群的污点、容忍、驱逐以及k8s集群故障排查思路
【kubernetes】关于k8s集群的污点、容忍、驱逐以及k8s集群故障排查思路
|
6天前
|
Kubernetes 微服务 容器
Aspire项目发布到win11本地k8s集群
Aspire项目发布到win11本地k8s集群
14 0
Aspire项目发布到win11本地k8s集群
|
7天前
|
运维 Prometheus 监控
Kubernetes 集群的监控与维护策略
【5月更文挑战第30天】 在微服务架构日益普及的背景下,容器编排工具如Kubernetes成为确保服务高效运行的关键。本文聚焦于Kubernetes集群的监控和维护,首先探讨了监控系统的重要性及其对集群健康的影响,随后详细介绍了一套综合监控策略,包括节点性能监控、应用服务质量跟踪以及日志管理等方面。此外,文章还提出了一系列实用的集群维护技巧和最佳实践,旨在帮助运维人员预防故障发生,快速定位问题,并确保集群长期稳定运行。
|
7天前
|
Prometheus 监控 Kubernetes
Kubernetes 集群的监控与日志管理实践深入理解PHP的命名空间与自动加载机制
【5月更文挑战第30天】 在容器化和微服务架构日益普及的背景下,Kubernetes 已成为众多企业的首选容器编排工具。然而,随之而来的挑战是集群的监控与日志管理。本文将深入探讨 Kubernetes 集群监控的最佳实践,包括节点资源使用情况、Pods 健康状态以及网络流量分析等关键指标的监控方法。同时,我们也将讨论日志聚合、存储和查询策略,以确保快速定位问题并优化系统性能。文中将介绍常用的开源工具如 Prometheus 和 Fluentd,并分享如何结合这些工具构建高效、可靠的监控和日志管理系统。
|
7天前
|
Prometheus 监控 Kubernetes
Kubernetes 集群的监控与维护最佳实践
【5月更文挑战第30天】 在现代云计算环境中,容器编排工具如Kubernetes已成为部署和管理微服务的关键。随着其日益广泛的应用,对集群进行有效的监控和维护显得尤为重要。本文将深入探讨Kubernetes集群监控的策略,并分享维护的最佳实践,以确保系统的稳定性和性能优化。我们将从监控工具的选择、关键指标的跟踪到故障排除流程等方面进行详细阐述,并提供实用的操作建议。
|
7天前
|
存储 运维 Kubernetes
Kubernetes 集群的持续性能优化策略
【5月更文挑战第30天】 在动态且日益复杂的云计算环境中,保持 Kubernetes 集群的高性能和稳定性是一个持续的挑战。本文将探讨一系列实用的性能优化策略,旨在帮助运维专家识别并解决可能影响集群性能的问题。我们将从节点资源配置、网络优化、存储管理以及集群监控等方面入手,提供一系列经过实践检验的调优技巧,并分享最佳实践案例。这些策略不仅有助于提升现有集群的性能,也为规划新的 Kubernetes 部署提供了参考依据。
|
7天前
|
运维 Kubernetes 监控
Kubernetes 集群的持续性能优化实践
【5月更文挑战第30天】 在动态且日益复杂的云原生环境中,维持 Kubernetes 集群的高性能运行是一个持续的挑战。本文将探讨一系列针对性能监控、问题定位及优化措施的实践方法,旨在帮助运维专家确保其 Kubernetes 环境能够高效、稳定地服务于不断变化的业务需求。通过深入分析系统瓶颈,我们不仅提供即时的性能提升方案,同时给出长期维护的策略建议,确保集群性能的可持续性。

推荐镜像

更多