2026-06-06 00:00:00
感觉我的生活似乎相当简单,毕业后直接进了某网安公司实习、然后就慢慢悠悠待了六年,直到今天。
毕竟是人生的第一次,感觉应该写点什么纪念一下。
刚毕业的时候是 2020 年,选了一个网安公司。当时进这个公司非常重要的一点是,我对网安行业非常有兴趣(初高中「捣鼓」过很多东西,还玩过渗透,甚至年少无知黑过别人论坛 - 幸好人家没报警),而且这家公司还运营着我曾经经常逛的一个安全论坛
当年也正值网安行业如日中天,开心入职了。刚入职的时候其实福利相当可以,各种下午茶、福利、多余的假期、奖金等等,各种活动也不少。
入职的时候面的是 Python ,还记得进公司的时候接手的是当时的一个老项目加功能。读这个项目源码的时候真的非常痛苦,具体记不清了,但大概也就是不遵守命名规范、没有注释、没有类型注解、没有测试这些,我梳理代码的过程中加了一些注释,然后做好了功能,然后提交代码。
然后 Code Review 过程有两件事情让我至今印象十分深刻
不过巧的是,我的代码质量被另一个团队的 leader 看到欣赏了,把我要了过去 —— 所以这也是我在真正招我入职的这个 leader 手里做的唯一一个项目
在新的小组,用 Python 做了一个新项目以后,就遇到了公司决定放弃 Python 转 Java 😂 所以我那个 Python 项目在线上好像也就存活了一个月
之后,既然公司决定转 Java 了,那我自然是…… 去写 Go……
没错,我所在的新部门因为是中间件部门,因此没有受到应用层转 Java 的影响,而是可以选择合适(喜欢)的语言完成,在职期间我基本上可以说把 Python 2, Python 3, Golang, Java, JavaScript (TypeScript), Rust 玩的都挺明白(主打一个想学什么语言就用什么做)
在这个部门工作的时候非常开心 —— 即使那时候我知道我的能力已经远超我的薪资了我也没有走,我经常觉得好像工作氛围要比钱重要的多。
然而,在这期间,网安行业走下坡路,公司也开始了各种「骚操作」,取消各种奖金、晚发至最后取消年终奖、强制加班(我入职的时候承诺了每天工作 8h 、周末双休 - 当时也确实做到了,但后面就变成了要求工作 9.5h )等,我因为氛围 & 做的东西我比较开心其实也都默默忍了下来。
转折点(开始想离开了)应该是两个因素一起构成的。一是我当时的 leader 因为不满公司 9.5h 的工时制度而离职(公司为了逼他离职甚至做出了在他头顶装摄像头的离谱举动),二则是公司突然搞了一个「王牌项目」,而我也正式从专门的基础架构/中间件的开发去转做了业务开发
坦白说,这是一个非常有前景的项目,但也是一个十分困难的项目 —— 当时的说法是「我们是第一个,没有竞争对手」而我觉得是「因为其他家都知道不可能实现所以我们是第一个」—— 这件事情几年后到了现在也是正确的,我们可以说仍然没有任何同类竞品、到今天也没有
当时我是负责其中的安全动态爬虫的,简单说就是给你一个 url 你要争取全自动的、完美的爬取到整个网站、触发所有可能的 API 请求(然后交由后面的环节做漏扫) —— 这是一个可能在现在基于 AI Agent 来做爬虫都难以达成的目标 —— 但在当时就被要求去做到极致,其中有一段时间一直淹没在对各种奇葩网站的适配,十分痛苦
但其实虽然觉得困难,但我还挺喜欢挑战困难的,所以虽然痛苦,我也一直没有什么一定必须要走的想法
AI 时代来了。我进了 AI 安全项目组。
这次我要做的产品是 AI 网关。
这其实是一个对我来说毫无挑战的项目。作为一个「精通」各种网络协议、代理协议,手搓过 MitM 实现的人,这个需求对我来说简直太简单了 —— 它对我来说最大的难点就是作为一名 ADHD 我怎么说服自己去做这么一个「无聊」的项目。
anyway ,就当做个「 Build your own nginx 」这种练习了,轻松搞定。
但是让我始料未及的是,我又接到了很多 AI 网关的需求 —— 这不正常吗?这正常吗?还记得我开篇吗,我在的是一个「网络安全公司」!而我在的项目组是做 AI 安全的!
4 月我接到了大量的 AI 网关方面的需求,多上游负载均衡、协议转换、计费…… 我其实挺不理解的,为什么会有人期望让一个安全产品支持这些功能。。这不是后面接一个 Kong 甚至开源的 New API / litellm 就能解决的嘛?我们产品经理其实也不理解 —— 也没有客户提 —— 是伟大的 CEO 同志提出的。
而与此同时,一个安全产品却又不给安全研究方面的资源。。只有一位研究员还需要在多个产品之间提供支持、要求训练小模型不给卡。。。
(当然,现在好很多了,但是项目组中网关的研发已经有数个,安全研究人员目前却仍然只有一个。。)
与此同时,公司正在实行 All in AI 的政策 —— 坦白说,我觉得方向是对的,然而实行却一言难尽
先说我负责的 AI 网关。4 月直接接到了海量的、人力根本不可能完成的需求,而上面给的解决方案就是 —— 用 AI —— 并且号称给「无限的 AI Token 」 —— 然后对于项目的要求是「做出来就行,不要求质量」。
「无限的 AI Token 」,听起来很美好是吧?结果给的是某个廉价中转的 API Key —— 这个离谱的廉价中转的可用性是我见过、甚至听过的最差的 —— 一个流式请求的 TTFT 平均 1min 、最长能干到 3min 的中转你们听说过吗?(对比下,直连 OpenAI / Claude 官方基本在数秒)
哦对,几分钟的 TTFT 还是后话,4 月初刚刚给到我的时候,它甚至根本没办法正常使用当时最先进的 gpt 模型 —— 非常稳定的,不开思考(默认 none thinking )就是智障、开了思考会无限等待直到超时。
(当然,当时秉持着绝不自费打工的想法,我申请到了 ChatGPT Pro 报销 —— 没强制要求发票,invoice 就给报了,这点公司倒是挺好的,我还以为到财务那里会卡我呢)
AI 现在的发展阶段到处是什么样子?我觉得是一个挺尴尬的境界。AI 可以去完成一些简单的任务、复杂的任务、甚至多步工作流的任务,AI 也能完成一些小项目的完整维护。
但是对于一个 AI 网关这种量级的项目呢?我的评价是,根本无法正常维护 —— 哪怕是最先进的 gpt-5.5 。
被迫用 AI 开始这种级别的「 Vibe Coding 」我其实是极度痛苦的。因为给的时间去完整审阅 AI 代码是不可能的,我只能尽力保证大方向的架构是我期望的、而放任中间的细节由 AI 把控。
我的「掌控欲」其实还挺强的。我之前几乎可以保证只要我交付出去的代码,几乎不会有我写的 bug ;而我自己没测出来的 bug ,测试也几乎不可能测出来 —— 我有另一个中大规模的项目,完全由我开发、没有测试介入、运行数年、在无数个不同的环境中新装、升级,累计 bug 数不超过 10
但是现在呢?我再也不敢直接去笃定的说「配置问题」了,而是接到可能的 bug 永远要自己先审查一遍 —— 当然,我做了个 AI Skill 让 AI 完成这件事情 —— 但这种事情带来的心智负担是我不能/不愿意接受的。
而且也算是不得不对代码质量放任了。之前做 Code Review 我都会非常仔细的一行行代码看,包括考虑各种性能和可能的边界条件。而现在呢?别说审查了,我自己都不知道哪里会埋雷。看了下只要 CI 过了、别提交不该提交的文件、没有什么明显改动不该改的文件,就 Merge 了。
—— 哦,说到 CI ,可能只有我负责的项目有 CI 这种东西吧,公司完全不管
—— 当然,没有 CI ,也没有 CD ;我明确提过,这种 AI 的代码 bug 会很多,必须要做到遇到 bug 敏捷开发、快速迭代、快速上线(目前是采用月发版、中间非常紧急的 hotfix 才会手动去部署升级 —— 但我现在几乎每天都能发现 AI 之前埋藏的数个惊喜),要搭建好 CI/CD 做好自动的上线,正好趁着新项目直接上全套的 k8s + helm + argocd —— 然而,nobody cares —— 没有人敢使用新技术、没有人敢担拍板的责任
与此同时,公司正在执行更加激进的 AI 政策。
配备统一的(公司自己开发的)( Vibe Coding 的)(极其难用的)(充满 bug 的) AI 工具,禁止使用自己的工具、禁止使用自己的 API Key ,将 AI 使用率纳入考评、所有 commit 必须 AI 提交……
CEO 期望的肯定是「降本增效」,但如此激进的政策,我也很难说公司到底是先驱还是先烈了。
至于离职的导火索,则是公司又开始了一个新的离谱的制度 —— 之前制度好歹「装一下」有个什么征求意见期,这次直接当天公布、当天实行、不完成就罚款。
坦白说,在公司工作还是挺轻松的,但是各种制度太恶心了。技术部氛围其实还是相当好的,但是上面离谱的 CEO 和 HRD 可以说把公司搞的乌烟瘴气(听说每年流动率能有 1/3 这个离谱的数量)。
断断续续,不知道写啥,纯属觉得应该画个句号,写个流水账记录下吧。
下一步怎么走也没想好,先去玩玩?自己做点什么?再换一家小而美不加班的公司?
无贷未婚无娃在这种情况下,还挺自由的 XD
2026-01-24 09:18:00
在学习 Race 或原子操作时,往往会有一个很经典的示例
1 |
#include <stdio.h> |
用 ./race 2000 5 来运行它,最终会创建 5 个线程并发对一个全局变量自增,因为这个「自增」操作不是原子的,所以最终的更新结果往往是一个小于 10000 的数字
但是,如果把这个代码翻译成 Python
1 |
import sys |
你会发现无论执行 python race.py 2000 5 多少次,最终的结果永远是稳定的 10000 —— 竞争消失了
没错,稍有经验的人几乎可以一下子反应过来这是 GIL 的锅!
Python 3.10 起引入了一个优化,并不是所有操作都会去进行获取 + 释放 GIL 的操作。而我们想要产生竞态的核心逻辑 [LOAD_GLOBAL counter, LOAD_CONST 1, INPLACE_ADD, STORE_GLOBAL counter] 正好都不在这些 GIL 操作上,因此上述代码看似是两个线程并行,但实际上是分开执行的,所以并没有产生竞争、没有同时读写一个全局变量的情况出现,导致无法复现
既然它是 GIL 导致的,那我们关了 GIL 不就好了🤔 Python 3.13 起开始有了一个 free-threaded 版本(常称为 python3.13t ),将 GIL 剔除了,所以我们如果直接用这种不含 GIL 的发行版去执行上面的程序,可以发现竞态成功复现了
既然问题出在我们的代码「过于简单」以至于不会给 GIL 释放锁的机会,那我们就手动给它引入释放的机会就好了,最简单方法就是利用「函数返回」—— 我们只需要将 += 1 替换成一个函数调用即可
1 |
import sys |
counter += one() 的指令是 [LOAD_GLOBAL counter, CALL_FUNCTION x, INPLACE_ADD, STORE_GLOBAL counter] ,而其中的 CALL_FUNCTION 会触发 GIL 切换检查,即在读写的过程中给了 GIL 释放锁的机会、允许了竞争
不过注意一点,因为现在 GIL 是 time-based switching,默认要 5ms 才会触发一次线程切换,所以每轮多跑几次,例如用
pythonrace.py200000 5- 少了的话在现代 CPU 上可能根本来不及满足切换的条件程序就运行完了
2025-10-16 13:52:00
NULL 有一个很重要的特性:NULL 与任何值的运算结果都是 NULL
1 |
SELECT 1 = 1; -- true |
这也就意味着,对于存在列 col BOOLEAN NULLABLE 的表,如果一行中 col 列的值为 NULL,则下面的四条查询都不会包含这行
1 |
-- 等于自不必说 |
我们其实基本都知道这点,所以我们在进行不等运算时通常会用 IS NULL / IS NOT NULL 特殊处理 NULL 列
1 |
SELECT * FROM "table" WHERE col is null OR col != true; -- 筛选 col = null 或 false |
但其实,除了 IS NULL, IS 操作符后面还可以跟随 BOOL 值,那么,用 IS NOT 其实是一个更加精准的不等于操作
1 |
SELECT * FROM "table" WHERE col IS NOT true; -- 筛选 col = null 或 false |
而对于不是 bool 类型的 nullable 列,我们则可以搭配使用 = != 与 IS
1 |
-- 筛选 col = null 或任何不为 1 的值 |
NULL 与任何值的运算结果都是 NULL,但在函数中则不一定(取决于具体实现)
以连接字符串为例,如果中间存在 NULL,用 || 连接属于运算符,中间任何一项为 NULL 则结果为 NULL,而用 concat 连接则是函数,中间出现的 NULL 会被忽略
1 |
SELECT 'hello-' || NULL || 'world'; -- null |
NULL 与任何值的运算结果都是 NULL,但在布尔逻辑中则不一样…… 试试看能不能说出下面的返回值
1 |
select not NULL; |
1 |
select not NULL; -- NULL |
那么自运算,无论「未知的反面」还是「未知和未知」「未知或未知」都是未知,也因此都是 NULL
OR 的逻辑则是「有任何一个值为 TRUE 就是 TRUE」,因此,在 NULL 参与的运算中,存在 TRUE 则为 TRUE,不存在 TRUE 则为 NULL(继续未知)
AND 的逻辑则是「有任何一个值为 FALSE 就是 FALSE」,因此,在 NULL 参与的运算中,存在 FALSE 则为 FALSE,不存在 FALSE 则为 NULL(继续未知)
在聚合时,如果对 NULL 值进行聚合,它的数值是被完全忽略的 —— 一个例子是 avg,如果对 1, 2, 3, 4, NULL 做 avg,结果是 (1+2+3+4)/4
如果期望给 NULL 在聚合时一个默认值,可以用 coalesce 函数为它赋一个「默认值」
上面已经提过 coalesce 函数了,再说一句就是,coalesce 函数可以接受多个参数(而不只是两个),会返回第一个非 NULL 值
例如用 coalesce(first_name, nickname, email) 取用户「昵称」
pg 中还存在一个 nullif 函数,接收两个值,如果两个值相等则返回 NULL 否则返回第一个值,等价于 CASE WHEN a = b THEN NULL ELSE a END
这个函数主要用来「将零值转换为空值」;举个例子就是
1 |
SELECT |
还有就是搭配 NULL 的「可转换为其他类型」的特性
1 |
SELECT |
虽然大概率不会引起混淆,但还是说一下,虽然我们用 psql 规则看到 NULL 值就像是文本一样,但它的底层传输是二进制,PG 规定用 len = -1 代表 NULL 值,所以不存在它与空字符串、null 字符串等混淆的情况
另外,特殊的,在 COPY 中,如果用的 text format(PG 的消息协议中,对于一个值存在 text 和 binary 两种 format),那么会用 \N 代表 NULL 值
参考:https://www.postgresql.org/docs/current/protocol-message-formats.html 中的 Query, Parse, Bind, RowDescription, DataRow
当行中有任一列值为 NULL 时,「行头」HeapTupleHeaderData 中的 t_infomask 字段内的 HEAP_HASNULL flag 会被标记为 1,此时在行头后面、其余数据前面会增加一个 null bitmap,用位图的形式存储所有列的 NULL 情况,且如果某一列的值为 null,后面的 data 中将不会出现这一列的信息
另外,null bitmap 除了用来处理 NULL 值,还会用来处理 drop column —— 当一列被删除时其实际上依然存在着,只是后面所有的行都会带有 null bitmap 将这一列标记为 NULL(更事实上,删除列是懒删除,行内的数据都还在,只有下次更新行时才会清理这些数据 —— 当然,清理的方式也是将它标记为 NULL);
参考:https://www.postgresql.org/docs/current/storage-page-layout.html
2025-10-06 11:12:00
我之前的 Zeabur 集群是独立跑在一台物理机上的,物理机相比云服务器的劣势之一就是底层存储的数据安全性 —— 云服务器的硬盘通常是由云服务商保证了安全性不同,物理硬盘坏了就是坏了
而不幸的是,不久前我就遇到了…… 所有数据差点消失,幸亏坏的盘并没有完全坏,以只读方式还能读(只是不能写)算是挽留了我的数据
但那以后我就一直在思考怎么保证数据安全,经过数个不同的方案研究,我最终的选择是 —— 将整机移动到 PVE 中 然后在 PVE 的底层使用 RAID 1 硬盘
方案敲定,行动开始 —— 我整个的迁移不太具有可复制性,因此写一篇完整的「迁移指南」确实不太有意义,但中间确确实实遇到了一些小问题,我觉得记录下来还是比较有价值的
💡 我两台机器(原 Zeabur 物理机和新的在 PVE 里面装的虚拟机):
- 在同一个机房
- 都是用的 RHEL 系的系统
- 内部文件系统都是 LVM + xfs
我的 PVE 并不是在安装时就直接做好 RAID1 的,因此保证安全性的第一点是将 PVE 的硬盘改成 RAID1
⚠️ 需要注意的是,RAID 只是冗余,不是备份也无法替代备份
这次我的迁移也顺便把备份加上了,但备份又是一个较大的话题,因此本文不会写备份相关的内容,如果未来有机会我会单独写一篇文章,不过可以顺便说一嘴的是,我选用的备份方案是 Velero
我没有阵列卡,那么硬盘改 RAID 就只能是通过软 RAID 来组,在 Linux 下组软 RAID 有两种办法,一是利用 mdadm 组 RAID,另一种则是用 lvm 组 RAID;二者各有优劣,我为了灵活性选择了 lvm 的方案 —— 我现在是 2 块 1TB 的硬盘,使用 lvm 的话后面扩容可以很方便的通过加 1 块 2TB 的硬盘来得到完整的 2TB 可用 RAID1 空间,而如果不用 lvm 虽然也能实现但相对来说更加麻烦,且有难以避免的 degrade 时段
哦对,还有,做冗余不能只将数据做冗余,也要考虑引导,都是老步骤,复制下 ELF 分区、重做下 grub 引导,没什么值得说的,有什么问题问问 ChatGPT 它应该能相当完美的回答。
假设我们现在的环境是:原有的数据卷 /dev/sda3、原有的 VG pve、原有的 LV pve/root /pve/swap pve/data、新的数据卷 /dev/sdb3
首先将新的数据卷转换为 PV pvcreate /dev/sdb3 然后将它加入至 VG vgextend pve /dev/sdb3
将 pve/root 转换为 RAID1 十分简单:一行命令 lvconvert --type raid1 -m1 pve/root /dev/sda3 /dev/sdb3 搞定
pve/swap 是个 swap 分区,没有做 RAID1 的必要,我们跳过
难点来到了 pve/data 这个逻辑卷 —— 它不是一个普通的 LV 而是一个 Thin Pool,如果我们直接执行 lvconvert --type raid1 -m1 pve/data /dev/sda3 /dev/sdb3 LVM 会报错 Operation not permitted on LV pve/data type thinpool.
可以认为 Thin Pool 是一个「逻辑逻辑卷」,它事实上分成了 meta 和 data 两部分(通过 lvs -a 命令可以看到,它是用 pve/data_tmeta 和 pve/data_tdata 组合而成的),所以我们说是对它做 RAID1 但事实上想做的是对它底层依赖的 meta 和 data 做 RAID1 —— 这样,Thin Pool 本身和从这个 Thin Pool 所分配出去的子 LV 也都是 RAID1 了。
所以我们要做的是,将它的底层数据卷转换为 RAID1 即可:
1 |
lvconvert --type raid1 -m1 pve/data_tmeta /dev/sda3 /dev/sdb3 |
然后等待 lvs -a 的输出中 Cpy%Sync 列变为 100% 即为 RAID 转换完成。
哦对,还有一件事情,虽然示例中我用的另一块盘也是 SATA 盘做例子,但事实上我的另一块盘是 NVME 的,因此我上面说的「pve/swap 不用做 RAID1」之外,我其实还将 pve/swap 给移动到了新的盘上
将 LV 从一个 PV 移动到另一个 PV 的命令:pvmove -n pve/swap /dev/sda3 /dev/nvme0n1p3
物理机迁移到 PVE 最直接的方法就是直接做整盘磁盘镜像然后导入,这种方案没什么可说的,也是最简单的
但是基于下面几个原因
我最后放弃了整盘迁移的方案,而是选择 rsync 拷贝 k3s 相关的数据:
/usr/local/bin/k3s-killall.sh 停止整个集群、删除给 zeabur 用的 ssh key、在 zeabur 中删除这个服务器我之前使用的防火墙时 ufw,它简单易用,但有一个非常重要的缺陷:只要 k8s 暴露的端口,它没办法阻止
因此,趁着这次,换回 firewalld 了;根据 Zeabur 的说明和 k3s 文档,需要执行下面的内容放行相关流量
1 |
firewall-cmd --permanent --zone=public --add-service=ssh # 22 |
注:我个人不建议放开 30000-32767 —— 我询问过 Zeabur 支持人员,不放开这些端口不会影响 Zeabur 本身的能力,只是非 http 类型的端口映射无法被访问。Zeabur 会默认将所有端口都暴露到公网,部分端口所对应的服务可能有安全问题,所以我的建议是不要添加 30000-32767 两台规则,而仅在确实需要访问映射的端口时再添加
注 2:如果你是基于你自己需要的目的去访问内部服务(如数据库、Redis),我非常不建议你将这些服务暴露到公网,而是应当使用 zproxy 通过代理访问这些内部服务(当然,你需要将 zproxy 本身使用的端口放开)
zeabur 和 k3s 本身对于「本机 IP 」有一定的偏好,如果要改的话比较麻烦,所以简单起见,我的选择是:
假设原机器 IP 1.1.1.1,现在新的机器 IP 2.2.2.2,我将两个机器的 IP 对调下就好了
云主机换个 IP 轻轻松松,物理机换个 IP 就很麻烦,特别是远程物理机换 IP(好吧,其实可以直接登录 IPMI 在 Remote console 里面改 IP 的,但我们当这个不存在)
不过挺好的一点是,我可以通过引入一个新的临时 IP 让这两台机器都不离线的情况下对调下 IP
💡 我这两台机器在同一个内网、网关相同、DNS 相同,都是手动指定的 IP 没有使用 DHCP
假设两台机器的网卡都是 eno1、临时 IP 是 3.3.3.3
流程是:
/usr/local/bin/k3s-killall.sh 把整个机器的 k3s 停掉nmcli con mod eno1 +ipv4.addresses "3.3.3.3/24" && nmcli dev reapply eno1 让这个机器有 1.1.1.1 和 3.3.3.3 两个 IPnmcli con mod eno1 -ipv4.addresses "1.1.1.1/24" && nmcli dev reapply eno1 让这台机器只剩下 3.3.3.3 一个 IPnmcli con mod eno1 +ipv4.addresses "1.1.1.1/24" && nmcli dev reapply eno1 让这个机器有 1.1.1.1 和 2.2.2.2 两个 IPnmcli con mod eno1 -ipv4.addresses "2.2.2.2/24" && nmcli dev reapply eno1 让这台机器只剩下 1.1.1.1 一个 IPnmcli con mod eno1 +ipv4.addresses "2.2.2.2/24" && nmcli dev reapply eno1 让这个机器有 2.2.2.2 和 3.3.3.3 两个 IPnmcli con mod eno1 -ipv4.addresses "3.3.3.3/24" && nmcli dev reapply eno1 让这台机器只剩下 2.2.2.2 一个 IP🤷 显得繁琐了点,但其实不难
主要有两部分的信息我们需要迁移
我们需要用 rsync 同步下面的文件/目录到新的集群:
/etc/rancher/k3s k3s 配置及连接集群的凭证/var/lib/rancher/k3s/server/db/ k3s 数据库/var/lib/rancher/k3s/server/token k3s 内部授权 token/var/lib/rancher/k3s/storage 使用的 local volume 的存储路径同步时使用的命令为(在原机器上执行)
1 |
P=/etc/rancher/k3s # 依次使用上面所需要同步的路径 |
在启动前,删掉下面的目录(k3s 启动时会自动重新创建)
/var/lib/rancher/k3s/server/cred/var/lib/rancher/k3s/server/tls我为虚拟机分配了 512GB 的硬盘,但我没想到的是我使用的 Automatic Disk Partition 竟然将绝大多数空间给了 /home 导致我迁移数据一半告诉我没空间了 = =
幸好,虽然这个奇怪的硬盘分区有点烦人,但 RHEL 系一律使用 LVM —— 它也只是个 LV 而已!简简单单,删掉这个 LV 把空间匀给 root 就好了
对了,删除 /home 挂载点要记得改 /etc/fstab,不然下次系统可能启动不起来
因为 Zeabur 不允许同一个 IP 有两个 Dedicated Server 出现,所以安装的过程中是使用了一个新的 IP 装的
在迁移完,如果想用回原来的 IP,需要修改 /etc/systemd/system/k3s.service.env 文件里面的 K3S_NODE_NAME
然后启动起来看看 kubectl get nodes,如果还有原来的 IP 的 Node,删了就好
我数据迁移完一启动各种飙红,仔细一看原来是 Pod 数量超限(默认 110),需要修改 kubelet 配置
在 /var/lib/rancher/k3s/agent/etc/kubelet.conf.d 目录下,创建一个 01-max-pods.conf ,里面写
1 |
apiVersion: kubelet.config.k8s.io/v1beta1 |
然后执行 systemctl restart k3s 就好
哦对,这个其实我之前就改过,但是迁移的时候漏了,你可以看看原来机器的 /var/lib/rancher/k3s/agent/etc/kubelet.conf.d 目录下有没有除了 00-k3s-defaults.conf 以外的文件,有的话最好前面 rsync 的时候直接一起迁移了,省事
2025-09-19 08:27:00
ChatGPT 目前已经成了我的长期订阅选择
一方面,GPT-5(和原来的 o3)体验确实好,可以在思考的过程去搜索、执行代码简直是王炸
另一方面,Codex 写代码是真的强,绝大多数能力已经能超过 Claude 了,只有 Codex 软件本身的用户体验差了一点
还有一点,Codex 自带 PR 代码审查!而且是完全免费的,完全可以替代掉 Code Rabbit / Cursor 之类的产品了
这一切只要 $20 真的很值
Proton Visionary 依然在我的订阅列表中
但我已经越来越少用它了,目前没有退订一方面这东西退订需要 Deactivate 邮件地址。。另一方面则是我的上古版 Visionary 价格太香了(现在退了再买差不多涨价了得有 70%)
目前我已经停用了绝大多数 Proton 的组件,只在使用 SimpleLogin 和 Mail。
btw,如果你也在用 Proton Mail 但是不想用它的官方客户端(官方客户端实在太难用了,改版前难用,改版后不但难用 bug 还多)可以考虑各种第三方邮件客户端 + protonmail-bridge-docker 方案
AD:Proton Visionary 可以分享给他人加入,如果你想加入我的家庭组请发邮件给我 [email protected],价格为 92 天 ¥109
没错,我依然订阅着 Cursor 🤔 Cursor 在折腾它的 plan 把自己折腾的残废的情况下,我依然在订阅着它😂
首先一点,Cursor Tab 是真的强,市面上没有对手。我最初就是完全因为 Tab 而订阅的 Cursor,而现在也经常用它来修一些 AI 搞不定的复杂逻辑。
另外,看似 Cursor 涨价了,但作为老用户还能继续享受一个月 500 次(Opt out of new pricing)。而现在的 500 次是不再限制 20 个工具调用的 500 次,比 max 只差在了 context 长度上(但我基本都会拆分好任务再给 AI,达到 200k 的次数屈指可数 —— 而且就算达到了 Cursor 也会自动 compact),所以整体依然很香(至少在强制 usage-based billing 之前很香😂)
在 AI 时代,一个独享的家宽 IP 可能已经是想流畅使用各种服务的必备品了;之前的 IP Royal 虽然便宜但是质量真的不敢说好,目前换成了 lisa,相当棒
AD:要购买欢迎使用我的推广链接 https://lisahost.com/aff.php?aff=3372
Dler 的服务我觉得已经回到了原来的水平,所以我目前也回到了 Diamond Plan,我觉得目前它又一次成为了我心目中的第一(至少比某 N 家强 emm)
曾经我是 Premium 订阅,在今年中升级到了 Lifetime
对于想学习 k8s、网络、Linux 的,很推荐这个平台,Learn by doing 的形式,边学习边实践还有对应的测试,绝对比单纯看某些文档/博客更适合学习
而且,在过去一年的更新中,iximiuz labs 增加了不少新功能,对我最重要的就是自定义 Playground —— 想学习/体验下什么产品,可以快速创建一个去测试,而且多机器的设计也可以自由去测试集群相关功能。
还有一些仍然在订阅的,但与《2024Q3 订阅 Recap》相比没什么变化或没什么想写的,就不再赘述了,在这里列个清单,感兴趣的可以回看我之前的 Recap
首当其冲的自然是 Claude 了;其实到现在 Claude 都是桌面 MCP 做的最好的、Claude Code 也是综合体验最好的,奈何 Opus 持续降智的同时 Codex GPT-5 太强了而且性价比真的高……
我曾经对于 Monica 十分满意(可以回看我上次的 Recap)
奈何,它家就是出了 Manus 的那家,然后重心转移了之后 Monica 就再也没什么新功能了,对于新模型的支持也不积极,高级模型还出了个积分制额外收费……
不过最重要的还是,ChatGPT Plus 已经成为了我的常订,而我对于 Claude、Gemini 等模型也没那么高的需求了
当然,如果你想要一个大而全又没那么贵的解决方案,Monica 还是一个很棒的选择(其实我现在依然用者它的浏览器插件,简单的问题随时划词问下体验也不错),如果你想订阅,欢迎使用我的邀请链接 https://monica.im/?ref=bryan
感觉 GitHub Copilot 已经跟不上现在这个时代了……
作为 Cursor + JetBrains 双持的我,前者自不用说,Copilot 对我而言毫无吸引力,而后者嘛
JetBrains 的 AI Assistant 已经自带了 AI 补全,将模式改成 Creative 后(我其实不太理解为啥它不是默认 - 可能是这个模式更耗费服务器资源?)体验十分棒。美中不足的是 NES(Next Edit Suggestions)还在 beta 且仅支持特定语言(没一个我在写的 = =),但 Copilot 虽然支持但也不咋地。。还不如免费的 Trae 呢😂
综上,👋 Copilot —— 一个我从内测就开始用的插件,一个几乎重塑了我的编码习惯的插件
我曾经是一个 Serverless 的「爱好者」,我觉得它是未来
奈何,现在越来越感觉到对于一个标准的应用来说,数据库是不可或缺的,而在 Serverless 的环境下,用户-边缘计算服务-数据库的延迟会变得十分明显,造成极差的用户体验
我目前几乎所有的服务都已迁移到 fly.io 和 zeabur —— 与之对应,Cloudflare Workers 也退订了
目前我已将 RSS 完全切换到了我自己写的 1Space,也因此退订了 Inoreader
不过,虽然退订了,但我没想到的是,过去的一年多 Inoreader 竟然获得了若干更新 —— 很神奇的事情,获取是换了个激进的产品经理吧,一个停止了七八年没大更新的服务突然更新/优化了不少
这不是我想退订,是官网登录系统直接挂了,给开发者发邮件/微信都不回!
哎,再没有通过 RSS 稳定订阅微信公众号的方式了
🤷 现在只能,已经不看微信公众号了
2025-08-01 08:21:00
2023 年 4 月我在 xlog 下写下了第一篇博客。xlog 真的是一个我很喜欢的博客平台,好看,对于 markdown 的第一方支持,不用考虑部署、图床等问题,自带 AI Summary、自带双语翻译,真的是一切只需要「写」即可,哦对,更重要的是,依赖于区块链技术,虽然你写的文章是在平台上的,但所有数据都依然属于你,且所有数据都是永久保存。
然而,两年过去了,xlog 这个平台虽然还在,但我认为它已经死了。GitHub 更新已基本停滞,没有人处理 issue、没有人审阅 pr,xlog 官网上充满了 spam,也没有人去管理社区。
其实这一切的原因都很好理解 —— xlog 的开发者 DIYGod 转去做 Folo 了。是啊,Folo 相比于 xlog 绝对是更有前景的项目,也更容易讲故事……
xlog 已被放弃,再加上 xlog 的母公司 RSS3 最近的动荡,我觉得是时候从 xlog 迁移走了。
我其实无比庆幸,两年前的时候我是打算把我所有博客迁移到 xlog 的。但是我的博客用的是 /yyyy/mm/dd/xxx 的 url 格式,而 xlog 并不支持这种格式,因而我一直是用 blog.singee.me 作为博客主域名 + articles.singee.me 作为 xlog 博客域名的,然后通过自动化将内容进行同步,且配置 xlog 博客的链接作为 Canonical URL。
这让我这次的迁移十分简单:将我原始博客的链接删掉、将 articles.singee.me 的原链接进行跳转即可!
嗯…… 唯一的副作用,通过 RSS 订阅我的博客的人应该会因为 id 变化了重新看一遍我的博客。其实这个是可以解决的,因为我之前 blog.singee.me 的 RSS 是通过 patch 了 hexo-generator-feed 实现的,完全可以特殊处理,但考虑到经历这个事件以后我应该不会再考虑这种「奇葩」的两处链接的形式了,所以我就把之前的 patch 回滚了,顺便增加一下我博客的曝光度 emm
anyway,博客又回来了,我又回到了原来的工作流:Notion 写作 + 同步到博客。已经这样写了两个博客了,一切都挺好,和两年前相比仿佛什么都没变 XD