Kubernetes 阿里云 CSI 配置 Secret 示例

这块资料太少了,所以我只能通过源码来了解一些信息,目前配置分四种。

  1. 环境变量 ACCESS_KEY_ID ACCESS_KEY_SECRET
  2. 环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID ALIBABA_CLOUD_ACCESS_KEY_SECRET
  3. 通过本地的配置文件,涉及到 AES 的加密
  4. 服务器授权了 RAM 角色

前两种配置都一样,只是引入的 KEY 不一样。

1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: Secret
metadata:
name: addon.csi.token
namespace: kube-system
type: Opaque
stringData:
ACCESS_KEY_ID: LTAI5tDDgmhfufF1Xe7d4BFe
ACCESS_KEY_SECRET: pRdMbfstF22WB0lIIgBPf1PejqcRvV

stringData 是明文模式,你可以换成 data,但值需要 base64.

我们可以执行 kubectl create -f filename.yaml 来添加。

最后我们需要给 csi-provisioner 添加环境变量。

https://raw.githubusercontent.com/kubernetes-sigs/alibaba-cloud-csi-driver/384d41b48d04ea8656f77d265fa24f9fd8984e97/deploy/nas/nas-provisioner.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
image: registry.cn-hangzhou.aliyuncs.com/acs/csi-plugin:v1.18.8.47-906bd535-aliyun
imagePullPolicy: "Always"
args:
- "--endpoint=$(CSI_ENDPOINT)"
- "--v=2"
- "--driver=nas"
env:
- name: CSI_ENDPOINT
value: unix://var/lib/kubelet/csi-provisioner/driverplugin.csi.alibabacloud.com-replace/csi.sock
- name: MAX_VOLUMES_PERNODE
value: "15"
- name: SERVICE_TYPE
value: "provisioner"
# 下方就是我们引入的两个新环境变量
- name: ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: addon.csi.token
key: ACCESS_KEY_ID
- name: ACCESS_KEY_SECRET
valueFrom:
secretKeyRef:
name: addon.csi.token
key: ACCESS_KEY_SECRET

第三种比较麻烦了,涉及到 AES 的加密,不能单纯的 base64。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 来源: https://learnku.com/articles/63966

// CBCEncrypt AES-CBC 加密
// key 必须是 16(AES-128)、24(AES-192) 或 32(AES-256) 字节的 AES 密钥;
// 初始化向量 iv 为随机的 16 位字符串 (必须是16位),
// 解密需要用到这个相同的 iv,因此将它包含在密文的开头。
func CBCEncrypt(plaintext string, key string) string {
defer func() {
if err := recover(); err != nil {
fmt.Println("cbc decrypt err:", err)
}
}()

block, err := aes.NewCipher([]byte(key))
if err != nil {
return ""
}

blockSize := len(key)
padding := blockSize - len(plaintext)%blockSize // 填充字节
if padding == 0 {
padding = blockSize
}

// 填充 padding 个 byte(padding) 到 plaintext
plaintext += string(bytes.Repeat([]byte{byte(padding)}, padding))
ciphertext := make([]byte, aes.BlockSize+len(plaintext))
iv := ciphertext[:aes.BlockSize]
if _, err = rand.Read(iv); err != nil { // 将同时写到 ciphertext 的开头
return ""
}

mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[aes.BlockSize:], []byte(plaintext))

return base64.StdEncoding.EncodeToString(ciphertext)
}

下面 JSON 是必须要的配置,其中 keyring 就是我们上面用到来加密的 key. access.key.idaccess.key.secretsecurity.tokenkeyring 这些都是要经过 AES 才可以的,其中 security.token 熟悉的话我们知道是用来临时秘钥的,这里是一定需要存在的,经过 AES 加密我们可以用一个空字符串,目前我是将过期时间设置很久,如果你的 security.token 存在实际值,但可能还是要给一个具体失效时间。

1
2
3
4
5
6
7
{
"access.key.id":"wb7pu7IETy8VXuhbN7JSpNsOGRgWL2Ht5odkDP+7lpsc6Djc2Dyi8eQM+FSksfUy",
"access.key.secret":"aCnNEE9zfQS8LZDJh1BzlU03TLcMNY86RtTA3rMS3gU6e1JXGzcLF04cU3dvQS59",
"security.token":"C15VO+jvANDs8tYv8Vu5OYitCKX+PzLgoe9Nfyh4vHXZMPzQq8UMSaByP4oqa6Te",
"keyring":"XFrMijCnyjF0jRYM57hzftB28F0nSbyz",
"expiration":"2099-01-01T00:00:00Z"
}

上面内容的存储,我们需要弄成一个 JSON 字符串然后再进行一个 base64.

1
2
3
4
5
6
7
8
9
kind: Secret
apiVersion: v1
metadata:
name: addon.csi.token
namespace: kube-system
data:
addon.token.config: >-
eyJhY2Nlc3Mua2V5LmlkIjoid2I3cHU3SUVUeThWWHVoYk43SlNwTnNPR1JnV0wySHQ1b2RrRFArN2xwc2M2RGpjMkR5aThlUU0rRlNrc2ZVeSIsImFjY2Vzcy5rZXkuc2VjcmV0IjoiYUNuTkVFOXpmUVM4TFpESmgxQnpsVTAzVExjTU5ZODZSdFRBM3JNUzNnVTZlMUpYR3pjTEYwNGNVM2R2UVM1OSIsInNlY3VyaXR5LnRva2VuIjoiQzE1Vk8ranZBTkRzOHRZdjhWdTVPWWl0Q0tYK1B6TGdvZTlOZnloNHZIWFpNUHpRcThVTVNhQnlQNG9xYTZUZSIsImtleXJpbmciOiJYRnJNaWpDbnlqRjBqUllNNTdoemZ0QjI4RjBuU2J5eiIsImV4cGlyYXRpb24iOiIyMDM4LTAxLTAxVDAwOjAwOjAwWiJ9
type: Opaque

不需要对容器进行修改,里面默认就有导入了。

第四种就是控制台操作了,进入到服务器的详情页添加 RAM 角色就可以了。

另外源码中还是存在一种 OIDC 的方式,不过我不太了解,具体你可以研究下。

往上