前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >K8S与Vault集成,进行Secret管理

K8S与Vault集成,进行Secret管理

作者头像
没有故事的陈师傅
发布于 2021-02-01 03:07:01
发布于 2021-02-01 03:07:01
3.1K00
代码可运行
举报
文章被收录于专栏:运维开发故事运维开发故事
运行总次数:0
代码可运行

Vault 是用于处理和加密整个基础架构秘钥的中心管理服务。Vault 通过 secret 引擎管理所有的秘钥,Vault 有一套 secret 引擎可以使用。

其主要有以下功能:

  • 安全密钥存储:任意的key/value Secret都可以存储到Vault中,Vault会对这些Secret进行加密并持久化存储。后端存储支持本地磁盘、cosul等;
  • 动态密钥:Vault可以动态生成Secret,在租约到期后会自动撤销它们;
  • 数据加密:Vault可以加密和解密数据,安全团队可以自定义加密参数;
  • 租赁和续订:Vault 中的所有机密都有与其关联的租约。在租约结束时,Vault 将自动撤销该机密。客户端可以通过内置续订 API 续订租约;
  • 吊销:Vault具有对秘密吊销的内置支持。Vault 可以撤销单个机密,还可以撤销一个机密树,例如由特定用户读取的所有机密或特定类型的所有机密。在发生入侵时,吊销有助于关键滚动和锁定系统;

安装

在Linux主机上安装

在Linux主机上安装比较简单,只需要下面三步:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 安装包管理工具
$ sudo yum install -y yum-utils
# 添加源
$ sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
# 安装vault
$ sudo yum -y install vault

在K8S中安装

vault提供了helm包,可以使用helm进行安装。

!! 版本说明:

  • Helm 3.0+
  • Kubernetes 1.9+
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 添加repo仓库
$ helm repo add hashicorp https://helm.releases.hashicorp.com
# 更新本地仓库
$ helm repo update
# 安装vault
$ helm install vault hashicorp/vault

起服务端

!! 这里仅针对主机上安装的vault,在K8S集群中使用helm安装的vault默认已经起了服务端了。

这里已经在主机上安装了vault。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ vault version
Vault v1.6.1 (6d2db3f033e02e70202bef9ec896360062b88b03)

然后以开发默认运行一个Vault服务端,正式环境不用开发模式。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ vault server -dev -dev-listen-address=0.0.0.0:8200 &
......
WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.

You may need to set the following environment variable:

    $ export VAULT_ADDR='http://0.0.0.0:8200'

The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.

Unseal Key: killR+cPfTR7P7HoYRt5SsMySMDv2w9WD7ljcxpXB+Q=
Root Token: s.pd4FBsC1pamE21nLv3fszdI1

Development mode should NOT be used in production installations

然后可以通过http://ip:8200/ui进行访问。

image.png

填入生成的Token,即可登录。

image.png

配置K8S与Vault通信

要使K8S能正常读取Vault中的Secret,则必须保证K8S和Vault能正常通信。

!! PS:我这里是采用Kubeadm安装的K8S集群,版本1.18.9

(1)添加环境变量,其中IP地址根据实际情况填写

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ export VAULT_ADDR=http://192.168.0.153:8200

(2)开启K8S认证方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/

(3)添加K8S集群配置信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ vault write auth/kubernetes/config \
    kubernetes_host=https://192.168.0.153:6443 \
    kubernetes_ca_cert=@/etc/kubernetes/pki/ca.crt
Success! Data written to: auth/kubernetes/config

(4)创建权限策略

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ cat <<EOF | vault policy write vault-demo-policy -
> path "sys/mounts" { capabilities = ["read"] }
> path "secret/data/demo/*" { capabilities = ["read"] }
> path "secret/metadata/demo/*" { capabilities = ["list"] }
> EOF
Success! Uploaded policy: vault-demo-policy

创建一个用于演示的demo策略。

(5)创建一个认证角色

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ vault write auth/kubernetes/role/vault-demo-role \
>     bound_service_account_names=vault-serviceaccount \
>     bound_service_account_namespaces=default \
>     policies=vault-demo-policy \
>     ttl=1h
Success! Data written to: auth/kubernetes/role/vault-demo-role

角色名是vault-demo-role,认证方式是RBAC认证,绑定的用户是vault-serviceaccount,策略是vault-demo-policy

(6)创建密钥

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ vault kv put secret/demo/database username="coolops" password=123456
Key              Value
---              -----
created_time     2021-01-25T08:22:35.134166877Z
deletion_time    n/a
destroyed        false
version          1

# 查看
$ vault kv get secret/demo/database
====== Metadata ======
Key              Value
---              -----
created_time     2021-01-25T08:22:35.134166877Z
deletion_time    n/a
destroyed        false
version          1

====== Data ======
Key         Value
---         -----
password    123456
username    coolops

(7)在K8S集群中创建RBAC权限

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: vault-serviceaccount

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: vault-clusterrolebinding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
  - kind: ServiceAccount
    name: vault-serviceaccount
    namespace: default

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: vault-secretadmin-role
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["*"]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: vault-secretadmin-rolebinding
subjects:
- kind: ServiceAccount
  name: vault-serviceaccount
roleRef:
  kind: Role
  name: vault-secretadmin-role
  apiGroup: rbac.authorization.k8s.io

创建RBAC配置文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl apply -f rbac.yaml 
serviceaccount/vault-serviceaccount created
clusterrolebinding.rbac.authorization.k8s.io/vault-clusterrolebinding created
role.rbac.authorization.k8s.io/vault-secretadmin-role created
rolebinding.rbac.authorization.k8s.io/vault-secretadmin-rolebinding created

在K8S中使用Vault中的Secret

要获取到Vault中的Secret,有两种方式:

  • 使用vault agent在initContainer中将secret取出来
  • 使用vault SDK在程序中获取

使用initContainer方式

!! 下面是官方的一个demo。

流程图如下:

image

(1)创建ConfigMap

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apiVersion: v1
data:
  vault-agent-config.hcl: |
    # Comment this out if running as sidecar instead of initContainer
    exit_after_auth = true

    pid_file = "/home/vault/pidfile"

    auto_auth {
        method "kubernetes" {
            mount_path = "auth/kubernetes"
            config = {
                role = "vault-demo-role"
            }
        }

        sink "file" {
            config = {
                path = "/home/vault/.vault-token"
            }
        }
    }

    template {
    destination = "/etc/secrets/index.html"
    contents = <<EOT
    <html>
    <body>
    <p>Some secrets:</p>
    {{- with secret "secret/demo/database" }}
    <ul>
    <li><pre>username: {{ .Data.data.username }}</pre></li>
    <li><pre>password: {{ .Data.data.password }}</pre></li>
    </ul>
    {{ end }}
    </body>
    </html>
    EOT
    }
kind: ConfigMap
metadata:
  name: example-vault-agent-config
  namespace: default

template允许将Vault里保存的Secret保存到文件。

创建pod

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
apiVersion: v1
kind: Pod
metadata:
  name: vault-agent-example
  namespace: default
spec:
  serviceAccountName: vault-serviceaccount 

  volumes:
  - configMap:
      items:
      - key: vault-agent-config.hcl
        path: vault-agent-config.hcl
      name: example-vault-agent-config
    name: config
  - emptyDir: {}
    name: shared-data

  initContainers:
  - args:
    - agent
    - -config=/etc/vault/vault-agent-config.hcl
    - -log-level=debug
    env:
    - name: VAULT_ADDR
      value: http://192.168.0.153:8200
    image: registry.cn-hangzhou.aliyuncs.com/rookieops/vault:1.6.1 
    name: vault-agent
    volumeMounts:
    - mountPath: /etc/vault
      name: config
    - mountPath: /etc/secrets
      name: shared-data

  containers:
  - image: nginx
    name: nginx-container
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: /usr/share/nginx/html
      name: shared-data

!! 注意serviceAccountName需和之前配置的保持一致

待pod运行后,可以正常获取到vault里的Secret,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ kubectl get po -o wide
NAME                                    READY   STATUS    RESTARTS   AGE    IP               NODE            NOMINATED NODE   READINESS GATES
nfs-client-prosioner-598d477ff6-fmgwf   1/1     Running   8          65d    172.16.7.140     ecs-968f-0005   <none>           <none>
traefik-5b8bb6787-dn96j                 1/1     Running   0          65d    172.16.7.138     ecs-968f-0005   <none>           <none>
vault-agent-example                     1/1     Running   0          106s   172.16.235.231   k8s-master      <none>           <none>

$ curl 172.16.235.231
<html>
<body>
<p>Some secrets:</p>
<ul>
<li><pre>username: coolops</pre></li>
<li><pre>password: 123456</pre></li>
</ul>

</body>
</html>

使用SDK方式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import (
    "fmt"
    "io/ioutil"

    vaultApi "github.com/hashicorp/vault/api"
)

var (
    vaultHost           string
    vaultCAPath         string
    vaultServiceAccount string
    vaultJWTPath        string
)

func main() {
    // K8S的token
    vaultJWTPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
    // sa名字
    vaultServiceAccount = "vault-serviceaccount"

    tlsConfig := &vaultApi.TLSConfig{
        CACert:   vaultCAPath,
        Insecure: false,
    }

    config := vaultApi.DefaultConfig()
    // vault地址
    config.Address = fmt.Sprintf("https://%s", vaultHost)
    config.ConfigureTLS(tlsConfig)

    client, _ := vaultApi.NewClient(config)
    buf, _ := ioutil.ReadFile(vaultJWTPath)
    jwt := string(buf)

    options := map[string]interface{}{
        "jwt":  jwt,
        "role": vaultServiceAccount,
    }
    loginSecret, _ := client.Logical().Write("auth/kubernetes/login", options)
    client.SetToken(loginSecret.Auth.ClientToken)
    
    // secret地址
    secret, _ := client.Logical().Read("database/creds/tx")
    fmt.Println(secret)
}

最后

Vault是一个很好的工具,可以相对安全的管理一些敏感信息,不过通过上面的步骤可以看到配置相对复杂,维护成本相对较高,不过Kubernetes和Vault集成依旧是一个不错的方案。

参考:

  • https://github.com/hashicorp/vault
  • https://github.com/hashicorp/vault-helm
  • https://www.vaultproject.io/docs/agent
  • https://www.vaultproject.io/docs/agent/template
  • https://learn.hashicorp.com/tutorials/vault/agent-kubernetes
  • https://medium.com/getamis/vault-kubernetes-integration-63ce46d47550

公众号:运维开发故事

github:https://github.com/orgs/sunsharing-note/dashboard

爱生活,爱运维

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维开发故事 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java NIO:浅析I/O模型
也许很多朋友在学习NIO的时候都会感觉有点吃力,对里面的很多概念都感觉不是那么明朗。在进入Java NIO编程之前,我们今天先来讨论一些比较基础的知识:I/O模型。下面本文先从同步和异步的概念 说起,然后接着阐述了阻塞和非阻塞的区别,接着介绍了阻塞IO和非阻塞IO的区别,然后介绍了同步IO和异步IO的区别,接下来介绍了5种IO模型,最后介绍了两种和高性能IO设计相关的设计模式(Reactor和Proactor)。   以下是本文的目录大纲:   一.什么是同步?什么是异步?   二.什么是阻塞?什么是非阻塞
范蠡
2018/04/04
6910
Java NIO:浅析I/O模型
一文读懂高性能网络编程中的I/O模型
随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力。本文(和下篇《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》)旨在为大家提供有用的高性能网络编程的I/O模型概览以及网络服务进程模型的比较,以揭开设计和实现高性能网络架构的神秘面纱。
JackJiang
2018/09/06
1.4K0
socket&io高性能
最近看到篇好文章《IO多路复用》,记得早期学习时,也去探索过select、poll、epoll的区别,但后来也是没有及时记录总结,也忘记了,学习似乎就是在记忆与忘记中徘徊,最后在心中留下的火种,是熄灭还是燎原就看记忆与忘记间的博弈
码农戏码
2021/04/29
1K0
socket&io高性能
CPU突然被打满的原因(全方位分析)
代码中存在无限循环或者条件判断错误导致的死循环,使得CPU一直在执行相同的操作,导致CPU利用率达到100%。
公众号:码到三十五
2024/03/19
1.3K0
一篇文章告诉你真实场景下服务端接口性能问题是如何解决的
作为Java后端开发者,我们创作的许多代码直接影响着用户的使用体验。如果后端代码性能不佳,用户在访问网站时就必须花费更多时间等待服务器响应。这可能引发用户投诉甚至用户流失问题。
@派大星
2024/04/15
1630
一篇文章告诉你真实场景下服务端接口性能问题是如何解决的
彻底搞懂高性能I/O之道
本文介绍操作系统I/O工作原理,Java I/O设计,基本使用,开源项目中实现高性能I/O常见方法和实现,彻底搞懂高性能I/O之道
用户1260737
2019/11/15
1.2K0
深入探讨I/O模型:Java中的阻塞和非阻塞和其他高级IO应用
I/O(Input/Output)模型是计算机科学中的一个关键概念,它涉及到如何进行输入和输出操作,而这在计算机应用中是不可或缺的一部分。在不同的应用场景下,选择正确的I/O模型是至关重要的,因为它会影响到应用程序的性能和响应性。本文将深入探讨四种主要I/O模型:阻塞,非阻塞,多路复用,signal driven I/O,异步IO,以及它们的应用。
程序那些事
2023/10/20
2030
Java 的 I/O 类库的基本架构 转
I/O 问题是任何编程语言都无法回避的问题,可以说 I/O 问题是整个人机交互的核心问题,因为 I/O 是机器获取和交换信息的主要渠道。在当今这个数据大爆炸时代,I/O 问题尤其突出,很容易成为一个性能瓶颈。正因如此,所以 Java 在 I/O 上也一直在做持续的优化,如从 1.4 开始引入了 NIO,提升了 I/O 的性能。关于 NIO 我们将在后面详细介绍。
wuweixiang
2018/10/11
3290
Java I/O不迷茫,一文为你导航!
学习过计算机相关课程的童鞋应该都知道,I/O 即输入Input/ 输出Output的缩写,最容易让人联想到的就是屏幕这样的输出设备以及键盘鼠标这一类的输入设备,其广义上的定义就是:数据在内部存储器和外部存储器或其他周边设备之间的输入和输出;
我没有三颗心脏
2018/09/14
5360
Java I/O不迷茫,一文为你导航!
Java I/O专题
NIO虽然提供了非阻塞的方法,但是NIO的IO行为还是同步的,对于NIO来说,我们的业务线程是在IO操作准备好时,得到通知,接着就由这个线程自行进行I/O操作,IO操作本身是同步的。
Steve Wang
2022/05/10
2430
高性能实践IO之Reactor模式
讲到高性能IO绕不开Reactor模式,它是大多数IO相关组件如Netty、Redis在使用的IO模式,为什么需要这种模式,它是如何设计来解决高性能并发的呢?
用户9184480
2024/12/19
1450
高性能实践IO之Reactor模式
NIO (New I/O)
NIO 是一种同步非阻塞的 I/O 模型,Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer 等抽象。
happyJared
2019/08/07
4590
NIO (New I/O)
详解 Java 中 4 种 I/O 模型
同步、异步、阻塞、非阻塞都是和I/O(输入输出)有关的概念,最简单的文件读取就是I/O操作。而在文件读取这件事儿上,可以有多种方式。
Java技术栈
2019/01/02
6870
高性能IO编程设计
? 首先,在讲述高性能IO编程设计的时候,我们先思考一下何为“高性能”呢,如果自己来设计一个web体系服务,选择BIO还是NIO的编程方式呢?其次,我们可以了解下构建一个web体系服务中,为了能够支撑
keithl
2020/04/07
1.2K0
Java体系之IO设计演进
在先前的文章《Unix之IO模型》已经讲述到5种IO模型以及对应的同步异步和阻塞非阻塞相关核心概念,接下来看下Java的IO模型在服务端的网络编程中是如何演进,注意这里用启动Java程序表示一个JVM进程,而JVM进程中以多线程方式进行协作,这里讲述以线程为主展开.
keithl
2020/04/07
4290
深入分析 I/O 的工作机制
不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符,所以I/O操作的都是字节而不是字符。但是我们的程序中通常操作的数据都是字符形式的。
BUG弄潮儿
2021/11/19
2500
深入分析 I/O 的工作机制
Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式
Java I/O模型 同步 vs. 异步 同步I/O 每个请求必须逐个地被处理,一个请求的处理会导致整个流程的暂时等待,这些事件无法并发地执行。用户线程发起I/O请求后需要等待或者轮询内核I/O操作完成后才能继续执行。 异步I/O 多个请求可以并发地执行,一个请求或者任务的执行不会导致整个流程的暂时等待。用户线程发起I/O请求后仍然继续执行,当内核I/O操作完成后会通知用户线程,或者调用用户线程注册的回调函数。 阻塞 vs. 非阻塞 阻塞 某个请求发出后,由于该请求操作需要的条件不满足,请求操作一直阻塞,
Jason Guo
2018/06/19
7090
NIO (New I/O)
NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了 NIO 框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。
崔笑颜
2020/06/08
8020
5种调优Java NIO和NIO.2的方式?
Java NIO(New Input/Output)——新的输入/输出API包——是2002年引入到J2SE 1.4里的。Java NIO的目标是提高Java平台上的I/O密集型任务的性能。过了十年,很多Java开发者还是不知道怎么充分利用NIO,更少的人知道在Java SE 7里引入了更新的输入/输出 API(NIO.2)。这篇教程展示了5个在Java编程的一些常见场景里使用NIO和NIO.2包的简单示例。
技术从心
2019/08/07
8050
Java I/O 模型的演进
什么是同步?什么是异步?阻塞和非阻塞又有什么区别?本文先从 Unix 的 I/O 模型讲起,介绍了5种常见的 I/O 模型。而后再引出 Java 的 I/O 模型的演进过程,并用实例说明如何选择合适的 Java I/O 模型来提高系统的并发量和可用性。
九州暮云
2019/08/21
3900
Java I/O 模型的演进
相关推荐
Java NIO:浅析I/O模型
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档