第3章 令牌化平台开发环境搭建
做令牌化平台,第一步就是把开发环境搞利索。别小看这件事——我在好几个项目里见过有人卡在环境搭建上,一卡就是半天。说白了,环境乱套,后面所有CI/CD管线都会跟着翻车。
3.1 本地开发环境清单
你需要的工具,我列个表,方便你对照安装。不一定全按版本号来,但尽量和团队保持一致。
| 工具 | 用途 | 推荐版本 | 备注 |
|---|---|---|---|
| Git | 代码版本控制 | ≥ 2.30 | 别忘了配置SSH Key |
| IDE(VS Code / GoLand) | 代码编写与调试 | 最新稳定版 | 建议装Docker、Kubernetes插件 |
| Go 1.20+ | 令牌代理、控制平面开发 | ≥ 1.20 | 注意GOPATH与GOROOT |
| Docker Engine + Compose | 容器化运行依赖服务 | ≥ 24.0 | macOS用Docker Desktop |
| kubectl | 本地操作Kubernetes | ≥ 1.28 | 版本与集群保持一致 |
| Kind 或 Minikube | 本地单节点K8s集群 | Kind ≥ 0.20 | 我个人偏向Kind,启动快 |
| Helm | Kubernetes包管理 | ≥ 3.12 | 后面部署用得多 |
| jq / yq | 命令行JSON/YAML处理 | 最新 | 调试时救命神器 |
.tool-versions 文件里,配合 asdf 统一管理,换机器也不慌。3.2 依赖管理:先搞定Docker Compose
令牌化平台不是单体,它依赖一堆基础设施:Redis缓存、PostgreSQL持久化、Vault密钥存储、OAuth2服务……你不可能全在本地装一遍实体服务。所以,Docker Compose是标配。
我在做过的一个项目里,第一次搭环境直接把PostgreSQL的端口暴露到宿主机,结果同事的本地也跑了PostgreSQL,冲突了半小时……后来大家统一用Compose,所有服务跑在自定义网络里,互不干扰。
这是咱们项目里的 docker-compose.dev.yml 核心片段:
version: "3.9"
services:
postgres:
image: postgres:15
environment:
POSTGRES_DB: tokenpad
POSTGRES_USER: tokenadmin
POSTGRES_PASSWORD: devpassword
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
vault:
image: hashicorp/vault:1.15
cap_add:
- IPC_LOCK
environment:
VAULT_DEV_ROOT__ID: root-
ports:
- "8200:8200"
-engine:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "8080:8080"
depends_on:
- postgres
- redis
- vault
environment:
DB_HOST: postgres
REDIS_HOST: redis
VAULT_ADDR: http://vault:8200
volumes:
pgdata:
3.3 Kubernetes本地集群搭建
Docker Compose只是第一步。真正的令牌化平台最终跑在Kubernetes上——服务发现、弹性伸缩、密钥分发全靠K8s。本地开发也得模拟这个环境,否则代码写完一上K8s就崩,那得多尴尬。
我推荐用 Kind(Kubernetes in Docker),轻量、快,而且支持加载本地镜像。安装就一行:
brew install kind # macOS
# 或
go install sigs.k8s.io/kind@v0.20.0
创建集群的配置:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30000
hostPort: 80
protocol: TCP
- containerPort: 30001
hostPort: 443
protocol: TCP
然后执行 kind create cluster --config kind-config.yaml。等1-2分钟,一个单节点K8s集群就好了。对比一下几种方案:
| 方案 | 启动速度 | 资源占用 | 网络模拟 | 我的建议 |
|---|---|---|---|---|
| Kind | 快(< 2 min) | 低(~1GB内存) | 通过端口映射 | 日常开发首选 |
| Minikube | 中等(3-5 min) | 中(~2GB内存) | 原生CNI+Ingress | 需要测试更真实网络时用 |
| K3s(本地) | 中等 | 很低(512MB) | 完整K8s API | 资源紧张时可以试试 |
| Docker Desktop K8s | 快 | 中 | 原生 | 但版本更新慢,不推荐 |
3.4 在本地K8s里部署令牌化平台
有了本地集群,就能把Docker Compose那套搬上K8s了。但注意,Compose里定义的 service 名称不能直接当K8s Service用。得写Deployment + Service + ConfigMap。
举个例子,-engine的Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: -engine
labels:
app: -engine
spec:
replicas: 1
selector:
matchLabels:
app: -engine
template:
metadata:
labels:
app: -engine
spec:
containers:
- name: engine
image: tokenpad/-engine:local
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: "postgres-service"
- name: REDIS_HOST
value: "redis-service"
- name: VAULT_ADDR
value: "http://vault-service:8200"
然后生成Service、PostgreSQL StatefulSet、Redis Deployment等,一次性kubectl apply -f dev-k8s/。你可能会问:“每次改代码都要重新 build 镜像、再导入 Kind 里,太麻烦了吧?”
没错,所以我会写一个 dev-up.sh 脚本:
#!/bin/bash
kind load docker-image tokenpad/-engine:local
kubectl delete pod -l app=-engine --force
kubectl apply -f dev-k8s/
这样改完代码,docker build -t tokenpad/-engine:local . && ./dev-up.sh,30秒内重新部署完成。
3.5 开发环境搭建全景图
整个流程串起来,就是下面这张图。从你的笔记本电脑出发,一路搭到能跑通令牌颁发流程。
3.6 一些避坑经验
- 镜像 tag 乱用 latest:我曾经在本地一直
:latest,后来CI管道也拉到了同一个tag,结果第二天本地改完镜像没更新tag,CI用了旧包,排查了俩小时。教训:开发环境用:local,CI用:commit-sha。 - K8s namespace 混淆:本地开发默认在
defaultnamespace,但我通常建一个dev-ns。否则和CI共用同一个集群(有的团队就这么干)会互相污染。 - 端口冲突:尤其是
8080,你可能本地跑了其他服务。我习惯在kind-config.yaml里把宿主机端口映射成8081:30000,灵活调整。 - 环境变量硬编码:把Vault地址、数据库密码直接写在 Deployment YAML 里。改一次全集群都要重应用。建议用 ConfigMap 和 Secret,并统一维护一个
dev-secrets.yaml。
git pull 后跑一遍 make dev-setup(我们项目里定义的目标),自动检查工具版本、拉取最新镜像、重置本地数据。自动化永远比手工靠谱。