第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.0macOS用Docker Desktop
kubectl本地操作Kubernetes≥ 1.28版本与集群保持一致
Kind 或 Minikube本地单节点K8s集群Kind ≥ 0.20我个人偏向Kind,启动快
HelmKubernetes包管理≥ 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:
注意!开发环境用的密码、都是明文暴露的,仅限本地使用。千万不要把这个Compose文件直接放到CI或生产环境。

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秒内重新部署完成。

本地K8s环境的核心价值:让你在提交代码前就能验证K8s原生的服务发现、密钥挂载、健康检查机制。有些坑早发现,早快乐。

3.5 开发环境搭建全景图

整个流程串起来,就是下面这张图。从你的笔记本电脑出发,一路搭到能跑通令牌颁发流程。

令牌化平台开发环境搭建流程 macOS / Linux / Windows Git + IDE + SDK Docker Engine + Compose Kind / Minikube + kubectl Postgres + Redis + Vault -engine 本地镜像 Deploy dev K8s 本地令牌颁发校验通过 注意:本地K8s用 kind load docker-image 同步镜像,避免每次push到远端仓库 依赖服务(Postgres/Redis/Vault)建议用 Helm Chart 统一版本,不要手工改

3.6 一些避坑经验

  • 镜像 tag 乱用 latest:我曾经在本地一直 :latest,后来CI管道也拉到了同一个tag,结果第二天本地改完镜像没更新tag,CI用了旧包,排查了俩小时。教训:开发环境用 :local,CI用 :commit-sha。
  • K8s namespace 混淆:本地开发默认在 default namespace,但我通常建一个 dev-ns。否则和CI共用同一个集群(有的团队就这么干)会互相污染。
  • 端口冲突:尤其是 8080,你可能本地跑了其他服务。我习惯在 kind-config.yaml 里把宿主机端口映射成 8081:30000,灵活调整。
  • 环境变量硬编码:把Vault地址、数据库密码直接写在 Deployment YAML 里。改一次全集群都要重应用。建议用 ConfigMap 和 Secret,并统一维护一个 dev-secrets.yaml。
养成习惯:每次 git pull 后跑一遍 make dev-setup(我们项目里定义的目标),自动检查工具版本、拉取最新镜像、重置本地数据。自动化永远比手工靠谱。