使用K3s 从零部署 CloudNativePG:打造 Homelab 统一 PostgreSQL 平台
K3s 从零部署 CloudNativePG:打造 Homelab 统一 PostgreSQL 平台前言在很多 CloudNativePG 教程中,通常只会介绍如何安装 Operator 并创建一个 PostgreSQL 集群。 但在实际 Homelab 场景中,我们更希望: 整个 K3s 集群共用一套 PostgreSQL 服务 支持 Spring Boot 项目 支持 Gitea 支持 Immich 支持未来新增应用 能够通过固定 IP 从局域网访问数据库 保留未来扩容多节点 K3s 的能力 因此本文不只是介绍 CloudNativePG 的安装,而是介绍如何将其建设为 Homelab 的统一 PostgreSQL 平台。 环境说明K3s 节点1192.168.31.215 路由器小米路由器 DHCP 配置: 1192.168.31.5 - 192.168.31.229 MetalLB 地址规划12345192.168.31.230 postgres192.168.31.231 ingress192.168.31.232 gitea192.168.31.233 ar...
从零开始:在 K3s 中部署 CloudNativePG 并成功实现外部直连(全流程实战)
前言本文是在我的Homelab 单节点 K3s(IP: 192.168.0.103)上部署 CloudNativePG (CNPG) 1.29 版本。 123kubectl get nodesNAME STATUS ROLES AGE VERSIONearzer Ready control-plane 53d v1.35.4+k3s1 过程安装 kubectl-cnpg 插件(强烈推荐)CloudNativePG 提供了一个非常强大的 kubectl 插件,可以帮助你轻松查看数据库状态、进行主备切换、查看日志等。 在你的控制端(或 K3s 节点上)运行以下命令安装: 1curl -sSfL https://github.com/cloudnative-pg/cloudnative-pg/raw/main/hack/install-cnpg-plugin.sh | sudo sh -s -- -b /usr/local/bin 如果你是中国用户,你可以使用gh-proxy来加速 1curl -sSfL https://gh-...
🚀 记一次本地 Homelab 环境 Gitea 升级迁移与 Actions (CI/CD) 完美集成实战
🚀 记一次本地 Homelab 环境 Gitea 升级迁移与 Actions (CI/CD) 完美集成实战📌 前言最近对本地 Homelab 服务器的私有代码托管平台 Gitea 进行了一次大版本升级迁移(升级至 v1.26)。原本以为只是一次简单的 docker compose up,没想到中间经历了数据库连错库、旧运行器残留、以及 Gitea Actions (Act Runner) 容器网络隔离等一连串经典的暗坑。 本文将完整记录这次迁移过程、踩坑原因以及最终如何完美集成兼容 GitHub Actions 语法的 Gitea Actions 并成功跑通 Go 自动化编译 的全案。 🛠️ 第一阶段:大版本迁移与数据库踩坑在新的服务器上,我准备好了原有的数据卷 ./data 并编写了新的 docker-compose.yaml。然而初次启动后,发现网页端一片空白,原有的代码仓库、组织和用户全都不见了! 🔍 踩坑原因检查 docker-compose.yaml 发现,在环境变量中误指定了一个全新的数据库名: 12- GITEA__database__NAME=...
2026年5月8号面试总结
前言2026年5月8号有一场面试,是对方架构师来面试的我。总的来说,面试的效果不是很好。面试的岗位是前端岗位,但是问的很多是后端架构的设计,我认为我的准备不是很好,我需要继续努力补全自己。 问题Java的虚拟线程问题:Java的虚拟线程是什么,怎么创建? 回答如下: 在Java 21中,引入了虚拟线程(Virtual Threads)来简化和增强并发性,这使得在Java中编程并发程序更容易、更高效。 虚拟线程,也称为“用户模式线程(user-mode threads)”或“纤程(fibers)”。该功能旨在简化并发编程并提供更好的可扩展性。虚拟线程是轻量级的,这意味着它们可以比传统线程创建更多数量,并且开销要少得多。这使得在自己的线程中运行单独任务或请求变得更加实用,即使在高吞吐量的程序中也是如此。 在Java 21中创建和使用虚拟线程有多种方法: 1. 使用静态构建器方法Thread.startVirtualThread方法将可运行对象作为参数来创建,并立即启动虚拟线程,具体如下代码: 123456Runnable runnable = () -> { S...
2026年5月7号面试总结
前言2026年5月7号有两场面试,本文记录了自己预先准备面试题和面试中遇到的问题。 笔试防抖 (Debounce)原理:在事件被触发 $n$ 秒后再执行回调,如果在这 $n$ 秒内又被触发,则重新计时。适用于:搜索框输入、窗口大小调整 1234567891011121314function debounce<T extends (...args: any[]) => void>( func: T, wait: number): (...args: Parameters<T>) => void { let timeout: ReturnType<typeof setTimeout> | null = null; return function (this: any, ...args: Parameters<T>) { if (timeout) clearTimeout(timeout); timeout = setTimeout(() => { func.a...
使用 Resend + Golang 发送邮件的完整踩坑与解决方案
使用 Resend + Golang 发送邮件的完整踩坑与解决方案在实际开发中,我尝试使用 Resend 的 SMTP 服务结合 Golang 发送邮件(用于重置密码等场景),过程中踩了多个典型坑。本文从 错误现象 → 原因分析 → 最终正确方案 进行完整总结。 一、背景目标: 使用 Golang 发送 HTML 邮件 接入 Resend SMTP 支持自定义域名发信(提升送达率) 二、Resend SMTP 基本认知(关键)Resend 的 SMTP 和传统 SMTP 有一个重要区别: 类型 含义 示例 SMTP Username 登录用户名 resend(固定) SMTP Password API Key re_xxx From(发件人) 邮件发送地址 noreply@xxx.com 👉 重点:Username ≠ From 三、踩坑记录(按时间顺序) ❌ 问题 1:501 Bad sender address syntax1501 Error: Bad sender address syntax 原因1auth := smtp.Plai...
无 Docker Desktop + Colima + Docker Compose v2 标准化方案
无 Docker Desktop + 纯 CLI + Colima + Docker Compose v2 标准化方案一、背景在 macOS 环境中,Docker Desktop 虽然开箱即用,但存在以下问题: 资源占用高(CPU / 内存) 启动慢 商业使用存在许可限制 与开发环境(如 k8s / 自定义 runtime)耦合较重 因此,采用以下组合替代: Colima + Docker CLI + Compose v2 Plugin 目标是实现: 轻量级 Docker 运行环境 完整 CLI 操作体验 原生支持 docker compose(v2) 二、整体架构1234567891011121314151617docker CLI ↓docker context (colima) ↓unix socket (~/.colima/default/docker.sock) ↓Colima VM (container runtime)````---## 三、环境安装### 1. 安装基础工具```bashbrew install doc...
优雅实现 Git 多账号切换:基于 SSH Config 与 includeIf 的环境隔离方案
优雅实现 Git 多账号切换:基于 SSH Config 与 includeIf 的环境隔离方案在日常开发中,我们经常需要在一台电脑上同时处理个人开源项目和公司业务项目。最核心的痛点有两个: SSH Key 冲突:GitHub 默认只识别一对密钥,多账号如何无感切换? 提交身份混淆:如何在公司项目中自动使用公司邮箱,在个人项目中自动使用个人邮箱? 本文分享一种“一次配置,永久生效”的自动化方案。 1. 目录结构规划首先,建议按用途将项目存放在不同的父目录下,这是自动化切换的前提。 123Workspaces/├── personal/ # 存放个人项目└── company/ # 存放公司项目 2. 生成独立的 SSH 密钥为每个账号生成专属的密钥对,不要覆盖默认的 id_ed25519。 12345# 生成个人账号密钥ssh-keygen -t ed25519 -C "personal@email.com" -f ~/.ssh/id_ed25519_personal# 生成公司账号密钥ssh-keygen -t ed25519 -C "...
从 Demo 到生产级:Kite 在 K3s 上的 PostgreSQL 与 Ingress 部署实战
从 Demo 到生产级:Kite 在 K3s 上的高可用数据库与 HTTPS 部署实践引言在之前的文章 《玩转 K8s 面板:轻量级 Kite 安装全记录 (K3s 篇)》 中,我们快速搭建了测试环境。但随着使用深入,原方案的局限性开始显现。今天我们将进行一次彻头彻尾的“生产级”改造。 1. 原方案的痛点:为什么不能用于生产?原方案最大的问题在于数据持久化。 默认 SQLite 的风险:原方案依赖 Pod 内部或本地路径的 SQLite 数据库。在 Kubernetes 环境下,Pod 是随毁随建的(Stateless)。 数据丢失:一旦节点重启、Pod 漂移或进行版本升级,所有用户配置、AI 工作流数据将全部丢失。 不可扩展性:SQLite 不支持多实例并发写入,限制了未来的水平扩展。 2. 外部数据库集成:计算与存储分离为了实现数据持久化,我们将数据库移出 K3s 集群,部署在独立的服务器(192.168.31.220)上。 2.1 数据库初始化在 PG 服务器上执行: 1234CREATE DATABASE kite_db;CREATE USER kite_user...
技术复盘:基于 OAuth 2.0 规范的 Spring Boot 鉴权标准化改造
现状与需求在 Hoteler 项目的开发测试阶段,由于原有的登录接口 /token 采用非标设计(自定义 JSON 结构、Header 传参),导致 Swagger UI (SpringDoc) 无法识别认证状态,必须手动复制 Token 并粘贴至 Authorize 框中,测试效率低。 目标:实现符合 OAuth 2.0 Password Grant 规范的接口,对接 Swagger UI 自动鉴权流。 协议参考本次改造主要参考了以下关于 OAuth 2.0 协议实现的标准逻辑: 理解OAuth 2.0 OAuth 2.0 的一个简单解释 OAuth 2.0 的四种方式 GitHub OAuth 第三方登录示例教程 技术实现方案响应报文的标准化(Schema Mapping)OAuth 2.0 规定 Access Token Response 的根路径必须包含 access_token。为兼容原有业务对象 UserToken,采用接口注入方式扩展响应体: 12345678910public interface OAuth2Compatible { ...
