**全面拥抱容器化 **。
Ubuntu 24 只需安装 Docker 和 k3d,剩下的繁重工作全部交给Kubernetes集群。
📊 整体架构一览
#mermaid-svg-4M6dPl6OfXunVsY6{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4M6dPl6OfXunVsY6 .error-icon{fill:#552222;}#mermaid-svg-4M6dPl6OfXunVsY6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4M6dPl6OfXunVsY6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4M6dPl6OfXunVsY6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4M6dPl6OfXunVsY6 .marker.cross{stroke:#333333;}#mermaid-svg-4M6dPl6OfXunVsY6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4M6dPl6OfXunVsY6 p{margin:0;}#mermaid-svg-4M6dPl6OfXunVsY6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4M6dPl6OfXunVsY6 .cluster-label text{fill:#333;}#mermaid-svg-4M6dPl6OfXunVsY6 .cluster-label span{color:#333;}#mermaid-svg-4M6dPl6OfXunVsY6 .cluster-label span p{background-color:transparent;}#mermaid-svg-4M6dPl6OfXunVsY6 .label text,#mermaid-svg-4M6dPl6OfXunVsY6 span{fill:#333;color:#333;}#mermaid-svg-4M6dPl6OfXunVsY6 .node rect,#mermaid-svg-4M6dPl6OfXunVsY6 .node circle,#mermaid-svg-4M6dPl6OfXunVsY6 .node ellipse,#mermaid-svg-4M6dPl6OfXunVsY6 .node polygon,#mermaid-svg-4M6dPl6OfXunVsY6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4M6dPl6OfXunVsY6 .rough-node .label text,#mermaid-svg-4M6dPl6OfXunVsY6 .node .label text,#mermaid-svg-4M6dPl6OfXunVsY6 .image-shape .label,#mermaid-svg-4M6dPl6OfXunVsY6 .icon-shape .label{text-anchor:middle;}#mermaid-svg-4M6dPl6OfXunVsY6 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4M6dPl6OfXunVsY6 .rough-node .label,#mermaid-svg-4M6dPl6OfXunVsY6 .node .label,#mermaid-svg-4M6dPl6OfXunVsY6 .image-shape .label,#mermaid-svg-4M6dPl6OfXunVsY6 .icon-shape .label{text-align:center;}#mermaid-svg-4M6dPl6OfXunVsY6 .node.clickable{cursor:pointer;}#mermaid-svg-4M6dPl6OfXunVsY6 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4M6dPl6OfXunVsY6 .arrowheadPath{fill:#333333;}#mermaid-svg-4M6dPl6OfXunVsY6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4M6dPl6OfXunVsY6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4M6dPl6OfXunVsY6 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4M6dPl6OfXunVsY6 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4M6dPl6OfXunVsY6 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4M6dPl6OfXunVsY6 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4M6dPl6OfXunVsY6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4M6dPl6OfXunVsY6 .cluster text{fill:#333;}#mermaid-svg-4M6dPl6OfXunVsY6 .cluster span{color:#333;}#mermaid-svg-4M6dPl6OfXunVsY6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4M6dPl6OfXunVsY6 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4M6dPl6OfXunVsY6 rect.text{fill:none;stroke-width:0;}#mermaid-svg-4M6dPl6OfXunVsY6 .icon-shape,#mermaid-svg-4M6dPl6OfXunVsY6 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4M6dPl6OfXunVsY6 .icon-shape p,#mermaid-svg-4M6dPl6OfXunVsY6 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4M6dPl6OfXunVsY6 .icon-shape .label rect,#mermaid-svg-4M6dPl6OfXunVsY6 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4M6dPl6OfXunVsY6 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4M6dPl6OfXunVsY6 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4M6dPl6OfXunVsY6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ☸️ k3d K8s 集群
🖥️ Ubuntu 24 宿主机
应用平面
中间件
数据平面
kubectl/helm
浏览器访问
读写
缓存
生产/消费
消费/生产
读写
读写
数据流
存储模型/文件
Docker Engine
k3d CLI
kubectl
Helm
LoadBalancer
端口映射
MinIO
对象存储
Flink Operator
- TaskManager
Spark Job
(按需运行)
MySQL
Redis
Kafka
KRaft 模式
SpringBoot AI 应用
Node.js 前端
👤 开发者
🧱 阶段一:Ubuntu 24 宿主机基础环境准备
这一步是为整个平台打地基,确保你的 Ubuntu 具备运行 K8s 的能力。
1️⃣ 安装必要系统工具
bash
sudo apt update
sudo apt install -y curl wget git vim net-tools
2️⃣ 安装 Docker Engine
Ubuntu 24 默认不带 Docker,需手动安装:
bash
# 卸载旧版本及可能冲突的包(严格按照官方推荐列表)
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
sudo apt remove -y $pkg
done
# 安装依赖
sudo apt install -y ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 添加稳定版仓库(此处文件名改为 docker-ce.list 更规范,与原路径仅名称不同)
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker-ce.list > /dev/null
# 更新并安装
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
启动 Docker 并设置开机自启:
bash
sudo systemctl enable docker --now
sudo usermod -aG docker $USER # 将当前用户加入 docker 组,避免每次 sudo
⚠️ 重要提示 :
usermod后,当前 Shell 的组信息不会立即刷新。您需要退出当前终端并重新登录,或者执行以下命令之一来立即生效(推荐前者):
- 方法一(重新登录):
exit后重新 SSH 连接。- 方法二(临时切换):执行
newgrp docker(会进入新 Shell,键入exit可返回原 Shell)。
✅ 验证 :重新登录后,执行docker run hello-world应看到欢迎信息。
资源分配建议:
- Docker 默认不限制宿主机资源(即容器可占用全部物理资源)。若需限制,可在
/etc/docker/daemon.json中配置cgroup参数,但通常情况下默认即可。 - 硬件最低参考 (根据实际负载调整):
- 轻量级测试/开发:2核 CPU、4GB 内存、30GB 空闲磁盘
- 生产或运行多个容器:建议 4核 CPU 起步、16GB 内存起步、50GB+ 空闲磁盘(具体视容器数量和应用类型而定)。
3️⃣ 安装 k3d 与 kubectl
k3d 能在 Docker 中极速创建 K8s 集群,kubectl 是 K8s 的命令行工具。
bash
# 安装 k3d(使用官方脚本,需 sudo 写入 /usr/local/bin)
curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | sudo bash
# 安装 kubectl(自动适配 amd64 / arm64 架构)
ARCH=$(dpkg --print-architecture) # 自动获取架构,例如 amd64 或 arm64
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${ARCH}/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
rm -f kubectl # 清理当前目录下载的临时文件
验证:
bash
k3d --version
kubectl version --client
4️⃣ 安装 Helm(K8s 包管理器)
bash
# 官方安装脚本(需 sudo 写入 /usr/local/bin)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | sudo bash
验证:
bash
helm version
💡 友情提示 :如果您的 Ubuntu 系统架构恰好是
arm64(例如 Apple Silicon 虚拟机或 AWS Graviton),修正后的kubectl安装命令会自动匹配linux/arm64版本,无需手动修改。若您想确认当前架构,可运行dpkg --print-architecture查看。
k3d安装缺少sudo:官方脚本默认将二进制安装到/usr/local/bin,非 root 用户直接执行会因权限不足而失败,必须加sudo。
kubectl下载后未清理 :下载的二进制文件会残留在当前目录,建议执行完毕后删除(rm -f kubectl)。**
Helm安装/usr/local/bin需要 root 权限。
⛵ 阶段二:拉起本地 K8s 集群
我们使用 k3d 创建一个轻量级但功能完整的集群,模拟分布式环境。
bash
k3d cluster create ai-bigdata-cluster \
--servers 1 \
--agents 2 \
-p "8080-8090:8080-8090@loadbalancer" \
-p "30000-30100:30000-30100@loadbalancer"
参数解释:
--servers 1:1 个 control-plane 节点--agents 2:2 个 worker 节点(用于运行工作负载)-p:将宿主机端口段映射到 K8s 负载均衡器,便于外部访问
查看集群状态:
bash
kubectl get nodes -o wide
如果看到 3 个节点状态均为 Ready,说明你的 K8s 港口已准备就绪 🎉。
🗄️ 阶段三:数据端 ------ 部署大数据组件
在云原生架构下,我们不再手动配置 XML,而是使用 Helm Chart 和 Operator 一键部署。
1️⃣ 部署对象存储(替代 HDFS):MinIO
HDFS 在容器环境中运维复杂,推荐使用 S3 兼容的对象存储(如 MinIO)作为数据湖底座。
bash
helm repo add minio https://charts.min.io/
helm install minio minio/minio \
--set mode=standalone \
--set rootUser=admin \
--set rootPassword=admin123
暴露 Web 控制台(端口 9001):
bash
kubectl port-forward svc/minio 9001:9001
访问 http://localhost:9001,可用 admin/admin123 登录,创建 bucket 用于后续数据存储。
2️⃣ 部署 Flink 集群(使用 Operator)
Flink Kubernetes Operator 能管理 Flink 作业的生命周期。
bash
helm repo add flink-operator https://downloads.apache.org/flink/flink-kubernetes-operator/
helm install flink-operator flink-operator/flink-kubernetes-operator
之后,你可以提交 FlinkDeployment CRD 来启动 JobManager 和 TaskManager(具体 YAML 后续文章详解)。
3️⃣ 部署 Spark 环境(按需运行)
Spark 原生支持 K8s,无需常驻集群,直接提交任务即可:
bash
kubectl run spark-pi --image=apache/spark:latest \
--restart=Never -- spark-submit --class org.apache.spark.examples.SparkPi \
--master k8s://https://kubernetes.default.svc \
--deploy-mode cluster ...
🔥 阶段四:应用端 ------ 部署中间件与业务服务
应用端组件(MySQL、Redis、Kafka)同样跑在 K8s 中,与大数据平台处于同一内网,通信延迟极低。
📦 一键部署 MySQL、Redis
bash
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install mysql bitnami/mysql --set auth.rootPassword=root123
helm install redis bitnami/redis --set auth.password=redis123
🐘 部署 Kafka(使用 KRaft 模式,无需 ZooKeeper)
KRaft
传统 Kafka 依赖 ZooKeeper 存储元数据,增加了运维复杂度。KRaft (Kafka Raft)是 Apache Kafka 2.8+ 引入的新模式,将元数据管理内置到 Kafka 自身,省去了外部协调组件,部署更简单、性能更高。
部署命令(Bitnami Chart 默认开启 KRaft)
bash
helm install kafka bitnami/kafka \
--set replicaCount=3 \
--set persistence.size=10Gi \
--set zookeeper.enabled=false \
--set kraft.enabled=true \
--set kraft.clusterId=$(openssl rand -hex 6) \
--set listeners.client.protocol=PLAINTEXT \
--set listeners.controller.protocol=PLAINTEXT \
--set listeners.interbroker.protocol=PLAINTEXT \
--set service.type=ClusterIP
说明:
replicaCount=3:3 个 broker 节点,保证高可用。persistence.size=10Gi:每个 broker 分配 10GB 持久化存储。zookeeper.enabled=false和kraft.enabled=true明确使用 KRaft。clusterId:集群唯一标识,用随机数生成。- 监听协议都用
PLAINTEXT(本地测试),生产环境请启用 TLS/SCRAM。
验证 Kafka 部署
bash
kubectl get pods -l app.kubernetes.io/name=kafka
所有 Pod 状态应为 Running。
创建 Topic(示例)
我们可以创建一个测试主题 ai-events,分区 3,副本 2:
bash
kubectl exec -it kafka-0 -- kafka-topics.sh \
--create --topic ai-events \
--partitions 3 --replication-factor 2 \
--bootstrap-server localhost:9092
查看主题列表:
bash
kubectl exec -it kafka-0 -- kafka-topics.sh --list --bootstrap-server localhost:9092
🧠 Kafka 核心速览
| 概念 | 说明 |
|---|---|
| Topic | 消息的逻辑分类,类似数据库的"表" |
| Partition | Topic 物理分片,每个分区有序,提供并行能力 |
| Replica | 分区副本,Leader 负责读写,Follower 同步数据 |
| ISR | In-Sync Replicas,与 Leader 保持同步的副本集合 |
| Producer | 生产者,发送消息到指定 Topic 的分区 |
| Consumer | 消费者,从 Topic 拉取消息,支持消费组(Group) |
| ACK 机制 | acks=0 不等待确认;acks=1 Leader 确认;acks=-1 (all) ISR 全部确认,可靠性最高 |
| KRaft 元数据 | 使用 Raft 协议选举 Controller,管理所有元数据,不再依赖 ZooKeeper |
#mermaid-svg-Mz6afTddxB9ADNmp{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Mz6afTddxB9ADNmp .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Mz6afTddxB9ADNmp .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Mz6afTddxB9ADNmp .error-icon{fill:#552222;}#mermaid-svg-Mz6afTddxB9ADNmp .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Mz6afTddxB9ADNmp .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Mz6afTddxB9ADNmp .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Mz6afTddxB9ADNmp .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Mz6afTddxB9ADNmp .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Mz6afTddxB9ADNmp .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Mz6afTddxB9ADNmp .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Mz6afTddxB9ADNmp .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Mz6afTddxB9ADNmp .marker.cross{stroke:#333333;}#mermaid-svg-Mz6afTddxB9ADNmp svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Mz6afTddxB9ADNmp p{margin:0;}#mermaid-svg-Mz6afTddxB9ADNmp .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Mz6afTddxB9ADNmp .cluster-label text{fill:#333;}#mermaid-svg-Mz6afTddxB9ADNmp .cluster-label span{color:#333;}#mermaid-svg-Mz6afTddxB9ADNmp .cluster-label span p{background-color:transparent;}#mermaid-svg-Mz6afTddxB9ADNmp .label text,#mermaid-svg-Mz6afTddxB9ADNmp span{fill:#333;color:#333;}#mermaid-svg-Mz6afTddxB9ADNmp .node rect,#mermaid-svg-Mz6afTddxB9ADNmp .node circle,#mermaid-svg-Mz6afTddxB9ADNmp .node ellipse,#mermaid-svg-Mz6afTddxB9ADNmp .node polygon,#mermaid-svg-Mz6afTddxB9ADNmp .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Mz6afTddxB9ADNmp .rough-node .label text,#mermaid-svg-Mz6afTddxB9ADNmp .node .label text,#mermaid-svg-Mz6afTddxB9ADNmp .image-shape .label,#mermaid-svg-Mz6afTddxB9ADNmp .icon-shape .label{text-anchor:middle;}#mermaid-svg-Mz6afTddxB9ADNmp .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Mz6afTddxB9ADNmp .rough-node .label,#mermaid-svg-Mz6afTddxB9ADNmp .node .label,#mermaid-svg-Mz6afTddxB9ADNmp .image-shape .label,#mermaid-svg-Mz6afTddxB9ADNmp .icon-shape .label{text-align:center;}#mermaid-svg-Mz6afTddxB9ADNmp .node.clickable{cursor:pointer;}#mermaid-svg-Mz6afTddxB9ADNmp .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Mz6afTddxB9ADNmp .arrowheadPath{fill:#333333;}#mermaid-svg-Mz6afTddxB9ADNmp .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Mz6afTddxB9ADNmp .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Mz6afTddxB9ADNmp .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Mz6afTddxB9ADNmp .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Mz6afTddxB9ADNmp .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Mz6afTddxB9ADNmp .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Mz6afTddxB9ADNmp .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Mz6afTddxB9ADNmp .cluster text{fill:#333;}#mermaid-svg-Mz6afTddxB9ADNmp .cluster span{color:#333;}#mermaid-svg-Mz6afTddxB9ADNmp div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Mz6afTddxB9ADNmp .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Mz6afTddxB9ADNmp rect.text{fill:none;stroke-width:0;}#mermaid-svg-Mz6afTddxB9ADNmp .icon-shape,#mermaid-svg-Mz6afTddxB9ADNmp .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Mz6afTddxB9ADNmp .icon-shape p,#mermaid-svg-Mz6afTddxB9ADNmp .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Mz6afTddxB9ADNmp .icon-shape .label rect,#mermaid-svg-Mz6afTddxB9ADNmp .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Mz6afTddxB9ADNmp .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Mz6afTddxB9ADNmp .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Mz6afTddxB9ADNmp :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Kafka 集群
key hash
轮询
自定义
拉取
拉取
拉取
副本同步
副本同步
Broker 1
Broker 2
Broker 3
Topic: ai-events
Partition 0
Leader: B1
Partition 1
Leader: B2
Partition 2
Leader: B3
生产者
消费者组 group-1
🧩 开发并部署 SpringBoot AI 应用(集成 Kafka)
1. 在 application.yml 中配置 Kafka
yaml
spring:
kafka:
bootstrap-servers: kafka:9092 # K8s 内部 Service 名称
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
consumer:
group-id: ai-consumer-group
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
spring.json.trusted.packages: "*"
2. 编写生产者与消费者
java
@Service
public class KafkaProducerService {
@Autowired
private KafkaTemplate<String, Object> kafkaTemplate;
public void sendEvent(String topic, Object event) {
kafkaTemplate.send(topic, event);
}
}
@Slf4j
@Component
public class KafkaConsumer {
@KafkaListener(topics = "ai-events", groupId = "ai-consumer-group")
public void listen(MyEvent event) {
log.info("Received event: {}", event);
// 处理业务逻辑...
}
}
3. 打包 Docker 镜像并导入 k3d
bash
# 在项目根目录执行
mvn clean package
docker build -t my-ai-app:latest .
k3d image import my-ai-app:latest -c ai-bigdata-cluster
4. 部署到 K8s(编写 Deployment + Service)
springboot-deploy.yaml 示例:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-ai-app
spec:
replicas: 2
selector:
matchLabels:
app: my-ai-app
template:
metadata:
labels:
app: my-ai-app
spec:
containers:
- name: app
image: my-ai-app:latest
ports:
- containerPort: 8080
env:
- name: SPRING_KAFKA_BOOTSTRAP_SERVERS
value: "kafka:9092"
---
apiVersion: v1
kind: Service
metadata:
name: my-ai-app-svc
spec:
type: ClusterIP
selector:
app: my-ai-app
ports:
- port: 8080
targetPort: 8080
bash
kubectl apply -f springboot-deploy.yaml
🌐 开发并部署 Node.js 前端
同样打包 Docker 镜像,导入 k3d,部署为 NodePort 服务,以便浏览器访问:
bash
# 构建镜像
docker build -t my-frontend:latest .
k3d image import my-frontend:latest -c ai-bigdata-cluster
frontend-deploy.yaml(使用 NodePort 暴露 30000 端口):
yaml
apiVersion: v1
kind: Service
metadata:
name: frontend-svc
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
nodePort: 30000
然后通过 http://localhost:30000 访问你的前端页面。
📋 关键端口与访问方式
| 组件 | K8s Service | 宿主机映射端口 | 访问方式 |
|---|---|---|---|
| MinIO API | minio:9000 | 无(内部) | 应用通过内网 minio:9000 |
| MinIO Console | minio:9001 | kubectl port-forward 9001 |
http://localhost:9001 |
| MySQL | mysql:3306 | 无(内部) | 应用通过 mysql:3306 |
| Redis | redis:6379 | 无(内部) | 应用通过 redis:6379 |
| Kafka Broker | kafka:9092 | 无(内部) | 应用通过 kafka:9092 |
| SpringBoot App | my-ai-app-svc:8080 | 无(内部) | 前端通过内网调用 |
| Node.js 前端 | frontend-svc:80 | 30000 (NodePort) | 浏览器 http://localhost:30000 |
| 额外服务端口 | - | 8080-8090 / 30000-30100 | 可扩展映射更多服务 |
🧹 总结
- 若需停止集群:
k3d cluster stop ai-bigdata-cluster- 若需彻底删除:
k3d cluster delete ai-bigdata-cluster- 生产中请配置持久化存储(PV/PVC)和网络策略,确保数据安全。