K8S与Vault集成,进行Secret管理

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: K8S与Vault集成,进行Secret管理

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


其主要有以下功能:


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


安装


在Linux主机上安装


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


# 安装包管理工具
$ 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+


# 添加repo仓库
$ helm repo add hashicorp https://helm.releases.hashicorp.com
# 更新本地仓库
$ helm repo update
# 安装vault
$ helm install vault hashicorp/vault


起服务端


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


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


$ vault version
Vault v1.6.1 (6d2db3f033e02e70202bef9ec896360062b88b03)


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


$ 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进行访问。


640.png


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


640.png


配置K8S与Vault通信


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


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


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


$ export VAULT_ADDR=http://192.168.0.153:8200


(2)开启K8S认证方式


$ vault auth enable kubernetes
Success! Enabled kubernetes auth method at: kubernetes/


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


$ 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)创建权限策略


$ 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)创建一个认证角色


$ 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)创建密钥


$ 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权限


---
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配置文件


$ 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。


流程图如下:


640.png


(1)创建ConfigMap


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


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,如下:


$ 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方式


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集成依旧是一个不错的方案。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
4月前
|
Prometheus Kubernetes 监控
Prometheus 与 Kubernetes 的集成
【8月更文第29天】随着容器化应用的普及,Kubernetes 成为了管理这些应用的首选平台。为了有效地监控 Kubernetes 集群及其上的应用,Prometheus 提供了一个强大的监控解决方案。本文将详细介绍如何在 Kubernetes 集群中部署和配置 Prometheus,以便对容器化应用进行有效的监控。
225 1
|
4月前
|
Kubernetes Devops 持续交付
DevOps实践:使用Docker和Kubernetes实现持续集成和部署网络安全的守护盾:加密技术与安全意识的重要性
【8月更文挑战第27天】本文将引导读者理解并应用DevOps的核心理念,通过Docker和Kubernetes的实战案例,深入探讨如何在现代软件开发中实现自动化的持续集成和部署。文章不仅提供理论知识,还结合真实示例,旨在帮助开发者提升效率,优化工作流程。
|
2月前
|
Kubernetes 关系型数据库 MySQL
|
4月前
|
运维 Kubernetes 容器
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
【Azure K8S】演示修复因AKS密钥过期而导致创建服务不成功的问题(The provided client secret keys for app ****** are expired)
|
2月前
|
存储 Kubernetes 数据安全/隐私保护
k8s学习--Secret详细解释与应用
Secret 支持四种类型: - **Opaque Secrets**:存储任意类型机密数据,需自行加密。 - **Service Account Token Secrets**:自动管理 API 访问令牌。 - **Docker Registry Secrets**:存储 Docker 私有仓库认证信息。 - **TLS Secrets**:存储 TLS 证书和私钥,用于加密通信。
247 0
|
4月前
|
Prometheus Kubernetes 监控
Grafana 与 Kubernetes 的集成
【8月更文第29天】Grafana 是一个开源的仪表板和可视化平台,它支持多种数据源,可以用来创建美观的仪表板和图表。Kubernetes (K8s) 是一个流行的容器编排平台,用于自动化容器应用的部署、扩展和管理。将 Grafana 与 Kubernetes 集成起来,可以方便地监控 Kubernetes 集群的状态和性能指标。本文将详细介绍如何配置和使用 Grafana 来监控 Kubernetes 集群。
149 2
|
4月前
|
存储 Kubernetes 数据安全/隐私保护
k8s学习笔记之ConfigMap和Secret
k8s学习笔记之ConfigMap和Secret
|
4月前
|
Kubernetes jenkins 持续交付
Kubernetes CI/CD 集成:持续交付的最佳实践
【8月更文第29天】随着微服务架构和容器化的普及,Kubernetes 成为了运行容器化应用的事实标准。为了确保应用能够快速迭代并稳定发布,持续集成/持续部署(CI/CD)流程变得至关重要。本文将介绍如何将 Kubernetes 集成到 CI/CD 流程中,并提供一些最佳实践。
345 1
|
4月前
|
Kubernetes jenkins 持续交付
在K8S中,Jenkins如何集成K8S集群?
在K8S中,Jenkins如何集成K8S集群?
|
4月前
|
Kubernetes jenkins 持续交付
Jenkins 与 Kubernetes 的集成:实现高效的资源管理和自动化部署
【8月更文第31天】随着微服务架构的普及,Kubernetes 已经成为了容器编排的事实标准。Kubernetes 提供了一种强大的方式来管理容器化的应用程序,而 Jenkins 则是持续集成与持续部署(CI/CD)领域的一个重要工具。将 Jenkins 与 Kubernetes 集成,不仅可以充分利用 Kubernetes 的资源管理能力,还能通过 Jenkins 实现自动化构建、测试和部署,从而提高开发效率和部署速度。本文将详细介绍如何将 Jenkins 集成到 Kubernetes 环境中,并提供具体的代码示例。
520 0

热门文章

最新文章

推荐镜像

更多