为何出现‘Error: JWT_KEY must be defined’错误?K8s密钥问题排查
问题与解决方案
问题背景
在Windows 10系统上通过Docker Desktop运行Docker+Kubernetes项目时,执行ts-node-dev src/index.ts启动应用触发如下错误:
> auth@1.0.0 start > ts-node-dev src/index.ts [INFO] 11:03:41 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.8.2, typescript ver. 4.7.4) Error: JWT_KEY must be defined at E:\adv\shop_back\auth\src\index.ts:7:11 at Generator.next (<anonymous>) at E:\adv\shop_back\auth\src\index.ts:8:71 at new Promise (<anonymous>) at __awaiter (E:\adv\shop_back\auth\src\index.ts:4:12) at start (E:\adv\shop_back\auth\src\index.ts:5:26) at Object.<anonymous> (E:\adv\shop_back\auth\src\index.ts:25:1) at Module._compile (node:internal/modules/cjs/loader:1105:14) at Module._compile (E:\adv\shop_back\auth\node_modules\source-map-support\source-map-support.js:521:25) at Module.m._compile (C:\Users\A\AppData\Local\Temp\ts-node-dev-hook-2465378030590002.js:69:33) [ERROR] 11:03:48 Error: JWT_KEY must be defined
尝试创建JWT密钥时执行:
kubectl create secret generic jwt-secret --from-literal JWT_KEY=this_is_the_jwt_key
收到错误提示:
error: failed to create secret secrets "jwt-secret" already exists
此前为其他测试项目创建过同名密钥,值为JWT_KEY=asdf。当前存在两个疑问:
- Kubernetes的密钥存储位置在哪里?
- 集群中已有密钥,为何新项目本地启动仍失败?
相关文件信息
index.ts(注:用户标注为index.js,实际为TypeScript文件)
import mongoose from "mongoose"; import { app } from "./app"; const start = async () => { if (!process.env.JWT_KEY) { throw new Error("JWT_KEY must be defined"); } if (!process.env.MONGO_URI) { throw new Error("MONGO_URI must be defined"); } try { await mongoose.connect(process.env.MONGO_URI, {}); console.log("Connected to MongoDb"); } catch (err) { console.error(err); } app.listen(3000, () => { console.log("Listening on port 3000!!!!!!!!"); }); }; start();
kubectl get secrets输出结果
kubectl get secrets NAME TYPE DATA AGE jwt-secret Opaque 1 38d
deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: auth-depl spec: replicas: 1 selector: matchLabels: app: auth template: metadata: labels: app: auth spec: containers: - name: auth image: tester/auth env: - name: MONGO_URI value: 'mongodb://auth-mongo-srv:27017/auth' - name: JWT_KEY valueFrom: secretKeyRef: name: jwt-secret key: JWT_KEY --- apiVersion: v1 kind: Service metadata: name: auth-srv spec: selector: app: auth ports: - name: auth protocol: TCP port: 3000 targetPort: 3000
问题解析与解决办法
1. 本地启动报错的核心原因
直接用ts-node-dev在本地启动应用时,Kubernetes的Secret不会自动注入到本地进程的环境变量中。K8s的Secret注入逻辑仅在集群内的Pod容器中生效,本地运行的Node.js进程读取的是Windows系统的环境变量,而非K8s集群存储的Secret。
2. Kubernetes Secret的存储位置
Kubernetes的所有配置数据(包括Secret)默认存储在集群的etcd分布式键值数据库中(Docker Desktop内置的K8s集群同样遵循此规则)。你无法直接访问etcd的文件系统,但可以通过kubectl命令操作Secret:
- 查看现有Secret的明文值:
(K8s会对Secret值进行Base64编码存储,因此需要解码查看明文)kubectl get secret jwt-secret -o jsonpath='{.data.JWT_KEY}' | base64 --decode
3. 解决启动问题的三种方案
方案一:本地手动设置环境变量启动
在Windows终端中先设置环境变量,再启动应用:
- PowerShell命令:
$env:JWT_KEY="this_is_the_jwt_key" $env:MONGO_URI="mongodb://localhost:27017/auth" # 注意本地MongoDB地址与K8s内部地址不同 ts-node-dev src/index.ts - CMD命令:
set JWT_KEY=this_is_the_jwt_key set MONGO_URI=mongodb://localhost:27017/auth ts-node-dev src/index.ts
方案二:更新K8s集群中的Secret值
如果需要让K8s Pod使用新的JWT_KEY值,需更新已存在的Secret:
- 直接更新(无需删除旧Secret):
kubectl create secret generic jwt-secret --from-literal JWT_KEY=this_is_the_jwt_key --dry-run=client -o yaml | kubectl apply -f - - 或先删除再创建:
kubectl delete secret jwt-secret kubectl create secret generic jwt-secret --from-literal JWT_KEY=this_is_the_jwt_key
更新Secret后,需重启Pod让新值生效:
kubectl rollout restart deployment auth-depl
方案三:用.env文件管理本地环境变量
创建.env文件放在项目根目录:
JWT_KEY=this_is_the_jwt_key MONGO_URI=mongodb://localhost:27017/auth
安装dotenv包读取.env文件:
npm install dotenv
在index.ts开头引入并加载:
import dotenv from 'dotenv'; dotenv.config();
此后本地启动时会自动读取.env中的环境变量,无需每次手动设置。
内容的提问来源于stack exchange,提问作者GoodMan
相关产品推荐
相关产品推荐

