究竟什么是「内卷」

过去的这一年里,不断的有人在我耳边说起一个词「内卷」,但是我让说这个词的人解释一下自己所说的这个词的含义,却没有人能够用一句话解释清楚这个词。所以在我的笔记中就一直留着这一个词条,让我不断的去思考「内卷」一词的含义。一般来说,我在没有弄明白某一个概念之前,不会在日常生活中反复的去使用。但周围反复在用的人实在太多了,所以整理一下过去我听到的,以及看到的。

内卷的几个表达场景

我周围的人通常在这几个场景中会用到「内卷」这个词:

  • 在大多数的语境中,我们会说互联网行业的竞争,以及在这个竞争下的程序员为主体的人形成了内卷的趋势,表现形式就是加班越来越严重
  • 我也听到有人形容《鱿鱼游戏》说是反应韩国的内卷
  • 同样在学习,比如高考的竞争中也有「内卷」的趋势

但究竟什么是内卷,如果是恶性竞争,那么我们为什么要发明一个词来表达重复的含义?

什么是内卷

那接下来我们就从最原本的含义来探究一下「内卷」。

字典上的定义

内卷对应的英文单词是 involution。involution 在 American Heritage English 上的解释:

  • the state of being involved 被卷入的状态
  • intricacy, 复杂性,复杂化的状态和过程
  • 在医学上:
    • A decrease in size of an organ, as of the uterus following childbirth.(器官在大小上的萎缩,例如生育之后女性子宫的萎缩。)
    • A progressive decline or degeneration of normal physiological functioning occurring as a result of the aging process.(因年龄增长而出现的身体正常功能的持续衰退或退化。)
  • 在植物学上:
    • Having the margins rolled inward,边缘内卷,形容植物枝叶内卷的特性

英文单词 involution 有内卷,退化的含义。

哲学定义

在哲学领域,内卷化一词最早被提及是 18 世纪德国哲学家 [[康德]] 的《批判力批判》,康德将 involution 和 Entwicklung(演化)进行了区分。

他在《批判力批判》中将「内卷化」定义成与「演化」相对的概念,「演化」形容事物从无到有、从低级到高级的发展过程,而「内卷化」则指的是事物在原有的基础之上,不断向内发展,不断复杂化的过程,这个过程中,并没有新事物诞生。1

人类学家定义

美国人类学家 Goldennweiser(Alexander Aleksandrovich Goldenweiser) 将内卷化定义成在某一个状态下,无法稳定,也无法转变为新的状态,只能不断内部运动,变得复杂的文化模式。2

农业领域

美国人类学家 Clifford Geertz ,在《农业内卷化——印度尼西亚的生态变化过程》(Agricultural Involution: The Processes of Ecological Change in Indonesia)中,借用 Goldenweiser 内卷化的概念研究爪哇岛的水稻农业,提出了 agricultural involution(农业化内卷)的概念。他认为水稻种植造成了社会复杂性,但没有促成技术或政治的变革,这个过程被他称为「内卷化」,Geertz 的使用,使得「内卷化」一词在人类学家和社会学家之间广为流传。

Geertz 在书中提到,1830 年以后爪哇受到了两方面的限制:

  • 增长的人口压力
  • 阻碍本地经济作物种植和商业部门发展的帝国主义

面对土地短缺采用了共同分担贫穷的模式,引起工业变革的失败3

国内学者的研究

而在国内对「内卷」一词的引用则是在黄宗智的《长江三角洲小农家庭与乡村发展》中,作者把内卷化这一概念用于中国经济发展与社会变迁的研究,他把通过在有限的土地上投入大量的劳动力来获得总产量增长的方式,即边际效益递减的方式,将一种没有发展的增长称为「内卷化」。

内卷化含义的扩大

但是在「内卷化」一词进入公众领域之后,其含义发生了巨大变化,在网络上,随着传播,内卷一词的语义发生了偏差。人们往往用其来指代恶性竞争、过度竞争,底层淘汰等现象。

总结

总结上面的这些定义,尽管在哲学、社会学等等不同领域中,不同学者都对内卷化展开了研究,但是对内卷化都有各自不同的定义,这些定义不尽相同,目前也没有一个统一的定义。

但是能看到一些统一性的地方:

  • 复杂化,相同的一件事情不断发展越来越复杂
  • 不断发展,却不会产生新的事物、思想

对于社会整体而言,内卷是一个停滞不前,无法转变的状态,虽然看着再不断发展,但是无法产生新的事物。而对于社会中的个体而言,内卷则使得个体投入更多,但却收获相同的结果,在边际效应上退化,对个体而言不管如何努力、改变都无法促进变革。

造成内卷的原因

信息不对称

在这里我无法再进一步探究内卷的原因,我也无法得知为什么整个社会会掉进这样的陷阱,我知道只有当市场上的人能够充分的去发明新的事物,能够自由的表达自己的观点,即使这个事物的发明可能带来灾难,即使这个观点可能是错误的,但只有这样的自由,才能不让社会陷入一潭死水,只有自由的讨论才能使得真理在辩论中脱颖而出。在信息公开透明、可以自由交流的社会中,信息的流动会弥补信息的不对称,从而使得社会中的个体能够根据自己所获得的信息做出决策,从而提高生产效率,从而发展出新的理论。就像[[密尔]]在[[论自由]]一书中所说,迫使意见不能被表达这是对整个人类的掠夺。

内卷化的误读

在我们日常生活中所讨论的内卷一词早已超出了其原本的含义,甚至在某一些地方的使用是错误的,只掩盖了原来的一些问题。很多人所说的「内卷」,其实并不是「内卷」。

就像之前看到的豆瓣短文

有人将职场学历要求越来越高视为内卷。事实上,这并不是内卷。例如一个工程师、银行经理的招聘要求从本科到硕士,从硕士到名校硕士,这其实是社会对岗位人才的要求越来越高,而不是内卷。 一个单位加班越来越严重,只要加班是有效的,这也不叫内卷,这属于劳动剥削。 将资本、风投偏爱低技术含量产业(例如共享单车、社区团购、滴滴这种的),而非原研药、精密机床、机器人这些高技术产业视为内卷。其实这也不是内卷。热钱真正偏爱的,是收益周期短的服务行业,“共享经济”、滴滴、美团、拼多多、游戏产业……这些看上去是互联网科技产业,其实它们是互联网加持的服务业,它们提供的是交通、配送、游戏娱乐、餐饮、购物等等服务。资本热钱真正偏爱的收益周期短、好讲故事的服务业。而这些生活服务产业又都是大众化服务,所以我们经常会在媒体宣传上、身边生活中看到这些服务产品(例如共享单车、美团骑手、游戏广告等),于是就会形成了资本只喜欢这种产业的错觉。实际上,高技术产业——造精密机床、造飞机、造机器人……这些技术产业都有它们自己的体系,只是它们离我们的生活较远,我们不太了解而已。所以这也算不上内卷。这属于是风投资本倾向于收益周期短、曝光率较高的服务业。如果真要靠投资共享单车那点钱去研究飞机、造芯片,那国家怎么可能发展呢?高科技企业自有其发展的政策、金融、市场体系。 将所有的加班都视为「内卷」这实际上掩盖了劳动法保障不健全的问题。假如劳动法保障够刚性,当暗示加班成为一种人人鄙视的违法行为时,加班生态是绝对可以好转的。而乱用内卷概念,则会把责任归于员工身上,反而忽略了法律制度、企业的问题,这就掩盖了真实的问题所在。

正确的使用「内卷」一词,才能让我们有针对性的解决问题,而不是像现在这样任其随意被滥用,从而掩盖真正能够被解决的问题。

reference

  1. 康德.判断力批判·第 2 版[M].北京:人民出版社,2002. 

  2. McGee, R. Jon; Warms, Richard L. Critical Contributions to Anthropology. Theory in Social and Cultural Anthropology: An Encyclopedia. SAGE Publications. 2013-08-28. ISBN 9781506314617 

  3. Cohen, Jeffrey H.; Dannhaeuser, Norbert. Involution and modernisation. Economic Development: An Anthropological Approach. Rowman Altamira. 2002-04-23. ISBN 9780759116696 


2021-11-03 thinking , involution

zinit 作者删库事件以及后续代替方案

前两天在新机器上使用我的 dotfiles 配置的时候,本来会自动安装 zinit,并进行一些初始化配置,但突然发现卡在了 zinit 配置拉取的过程中,还以为 GitHub 权限配置的问题,但仔细看了一下发现作者把整个仓库,以及个人页面都给删除了。 https://github.com/zdharma/zinit 这个仓库显示 404,我还以为产生了错觉,因为刚刚从 Google 点击跳转过来,Google 的结果还在,但自己一搜就发现原来真的是作者本人把仓库删除了。

所以也没有办法,除了我本地的一份缓存,最近一次提交还是 6 月份,所以只能搜索一下看看还有没有人有最新的备份,然后就看到了 GitHub 上之前贡献者新建的社区维护的仓库。把我 dotfiles 中的地址替换成该仓库目前暂时没有遇到任何问题。

另外要注意如果用到了如下的插件也要响应地替换:

zdharma/zinit   -> zdharma-continuum/zinit
zdharma/fast-syntax-highlighting   -> zdharma-continuum/fast-syntax-highlighting
zdharma/history-search-multi-word -> zdharma-continuum/history-search-multi-word

我个人也备份了一份代码 https://github.com/einverne/zinit 有兴趣可以看看。

不过我个人还是建议切换到社区维护的版本上。

一点感想

我不对作者的行为做任何评价,因为我并不清楚发生了什么,但是无疑这种删库的行为已经伤害了曾经的使用者,以及曾经贡献过代码的开发者。代码容易恢复,当作者仓库的 wiki 内容已经只能从 Google Cache 中恢复了,这无疑会对使用者造成一些困扰。

从这件事情延伸到生活中,以及这两天刚刚发生的 [[Notability]] 买断制更改为订阅模式造成的恶劣舆论影响,让我不经去思考,在如今这样的严重依赖数字化的生活中保持安定。在过去的经历中,已经让我渐渐地养成习惯,尽量去使用[[自由软件]](能够获取源码),尽量去使用跨平台能导出可使用数据的软件(比如 Obsidian 即使再用不了,我还可以用任何编辑器去编辑我的笔记),如果有离线可用的,绝不用在线服务(Obsidian 相较于 Notion,Notion 开始就不在我的备选方案)。虽然已经这样的做法已经渐渐地让我不会再受到服务关闭的影响,但于此同时我需要考虑的东西就变得多了,数据安全问题,数据备份的问题,这只是涉及数字资产。

但生活中比数字资产重要多的东西也非常多,要做好任何重要的东西可能丢失的备份策略,如果丢失身份证呢,如果在旅行的过程中丢失了护照呢,或者手机失窃了呢? 去备份任何你生活需要依赖的东西,不要将手机和身份证放到一起,不要将银行卡和任何证件放到一起,去备份你生活中产生的任何个人的数据

reference


2021-10-31 zinit , github , repository

升级 Gogs(Docker) 从 0.11.91 到 0.12.3

很早之前在 QNAP 上就已经安装过老版本的 Gogs,一路升级到 0.11.91 之后很久没有更新,看了一下用的镜像还是 2020 年 2 月份的,看到 Gogs 也已经迭代了好几个版本,正好这一次做迁移,把 Gogs 从 QNAP 迁移到 VPS 上,随便想着也升级一下 Gogs 的版本。

因为之前使用 Docker 安装的,所以迁移的步骤也比较简单,两个部分数据,一部分是 MySQL 数据库,mysqldump 迁移导入即可,另一部分是写的磁盘持久化部分,tar 打包,scp 或 rsync 传输也比较快。

修改配置文件

Gogs 升级到 0.12.x 的时候官方有一些配置发生了变化,我的所有配置文件都在 ~/gogs 文件夹下,所以我需要修改:

vi ~/gogs/gogs/conf/app.ini

然后修改其中的配置。官方的 0.12.0 的 changelog 已经写的非常清楚了,将这些修改都更改了。

❯ cat ~/gogs/gogs/conf/app.ini
BRAND_NAME = Gogs
RUN_USER = git
RUN_MODE = dev

[database]
TYPE  = mysql
HOST     = db_host:3306
NAME     = gogs
USER     = gogs
PASSWORD   = BTxax
SSL_MODE = disable
PATH     = data/gogs.db

[repository]
ROOT = /data/git/gogs-repositories

[server]
DOMAIN           = git.example.com
HTTP_PORT        = 3000
EXTERNAL_URL     = https://git.example.com
DISABLE_SSH      = false
SSH_PORT         = 10022
START_SSH_SERVER = false
OFFLINE_MODE     = false

[mailer]
ENABLED = false

[service]
REQUIRE_EMAIL_CONFIRMATION = false
ENABLE_NOTIFY_MAIL = false
DISABLE_REGISTRATION   = false
ENABLE_CAPTCHA         = true
REQUIRE_SIGNIN_VIEW    = false

[picture]
DISABLE_GRAVATAR        = false
ENABLE_FEDERATED_AVATAR = false

[session]
PROVIDER = file

[log]
MODE      = file
LEVEL     = Info
ROOT_PATH = /app/gogs/log

[security]
INSTALL_LOCK = true
SECRET_KEY   = Mj

可以大致参考我的,但不是每一个选项都要一致,最好自行查看每个选项的含义

cp app.ini app.ini.bak
sed -i \
  -e 's/APP_NAME/BRAND_NAME/g' \
  -e 's/ROOT_URL/EXTERNAL_URL/g' \
  -e 's/LANDING_PAGE/LANDING_URL/g' \
  -e 's/DB_TYPE/TYPE/g' \
  -e 's/PASSWD/PASSWORD/g' \
  -e 's/REVERSE_PROXY_AUTHENTICATION_USER/REVERSE_PROXY_AUTHENTICATION_HEADER/g' \
  -e 's/\[mailer\]/\[email\]/g' \
  -e 's/\[service\]/\[auth\]/g' \
  -e 's/ACTIVE_CODE_LIVE_MINUTES/ACTIVATE_CODE_LIVES/g' \
  -e 's/RESET_PASSWD_CODE_LIVE_MINUTES/RESET_PASSWORD_CODE_LIVES/g' \
  -e 's/ENABLE_CAPTCHA/ENABLE_REGISTRATION_CAPTCHA/g' \
  -e 's/ENABLE_NOTIFY_MAIL/ENABLE_EMAIL_NOTIFICATION/g' \
  -e 's/GC_INTERVAL_TIME/GC_INTERVAL/g' \
  -e 's/SESSION_LIFE_TIME/MAX_LIFE_TIME/g' \
  app.ini

使用命令 sed 替换。1

修改 Docker Compose 配置

然后在新的 VPS 上使用 docker-compose:

version: "3"
services:
  gogs:
    image: gogs/gogs:0.12.3
    container_name: gogs
    restart: always
    volumes:
      - ~/gogs:/data
    ports:
      - "10022:22"
    environment:
      VIRTUAL_HOST: git.example.com
      VIRTUAL_PORT: 3000
      LETSENCRYPT_HOST: git.example.com
      LETSENCRYPT_EMAIL: admin@example.info

networks:
  default:
    external:
      name: nginx-proxy

因为我使用 Nginx Proxy 做反向代理,如果需要可以去除掉。

然后直接 docker-compose up -d 启动即可。

这个时候我遇到一些问题。查看日志

less ~/gogs/gogs/log/gogs.log
2021/10/30 07:35:18 [ INFO] Gogs 0.12.3
2021/10/30 07:35:18 [FATAL] [...o/gogs/internal/route/install.go:75 GlobalInit()] Failed to initialize ORM engine: auto migrate "LFSObject": Error 1071: Specified key was too long; max key length is 767 bytes

会发现报错,这个错误 GitHub issue 上面也有人报错,之前因为迁移,没有来得及查看,后来仔细查看 Gogs 其他日志:

less ~/gogs/gogs/log/gorm.log

发现 gorm 日志中在创建 lfs_object 表的时候发生了错误。

2021/10/30 07:33:49 [log] [gogs.io/gogs/internal/db/db.go:166] Error 1071: Specified key was too long; max key length is 767 bytes
2021/10/30 07:33:49 [sql] [gogs.io/gogs/internal/db/db.go:166] [823.087µs] CREATE TABLE `lfs_object` (`repo_id` bigint,`oid` varchar(255),`size` bigint NOT NULL,`storage` varchar(255) NOT NULL,`created_at` DATETIME NOT NULL , PRIMARY KEY (`repo_id`,`oid`)) ENGINE=InnoDB [] (0 rows affected)

结合之前在 changelog 中看到的,升级到 0.12.x 之后 Gogs 会自动创建这张表,而创建失败了自然就无法启动报 502 错误了。

看这个错误 Error 1071,一看就是 MySQL 的错误。

Error 1071: Specified key was too long; max key length is 767 bytes

我的机器上使用的是 MariaDB,然后 gogs 数据库默认使用的是 utf8mb4_general_ci collation,默认情况下索引长度会有问题,所以将数据库的默认 collation 改成 utf8_general_ci 即可。

使用 phpmyadmin 修改 collation

登录 phpmyadmin 选中数据库 gogs,然后在 Operations 最下面可以看到 Collation 设置,直接修改保存即可。

使用命令行修改 collation

ALTER DATABASE <database_name> CHARACTER SET utf8 COLLATE utf8_general_ci;

2021-10-30 gogs , gitlab , github , git , docker , linux , mysql

修复 Ubuntu 18.04 网络设置中无有线设置的问题

在 Ubuntu 18.04 网络配置中,某一次升级之后就发现网络配置中心里面少了有线网络配置。

为了恢复有线网络配置,需要手动修改 NetworkManager 的配置文件。

首先查看 interfaces 文件中内容。

❯ sudo cat /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback

确保该配置文件正确。

然后修改 NetworkManager.conf 文件

sudo vi /etc/NetworkManager/NetworkManager.conf

将文件中的 :

managed=false

修改为

managed=true

然后修改 10-globally-managed-devices.conf 配置文件,添加有线设备:

sudo vi /usr/lib/NetworkManager/conf.d/10-globally-managed-devices.conf

修改为:

[keyfile]
unmanaged-devices=*,except:type:ethernet,except:type:wifi,except:type:wwan

注意其中的 except: type: ethernet 这一部分。

最后重启 NetworkManager

sudo service network-manager restart

最后就能够在网络配置中心中手动配置有线网络连接。

reference


2021-10-24 ubuntu , network-manager , net

So you Start 独服 Proxmox VE 配置 RAID 10

之前购买的 So you Start(OVH 旗下品牌) 的独服,配置有 4 块 2T 的硬盘,但是 So you Start 后台默认的 RAID 级别是 RAID1,这样使得可用的空间只有 8T 中的 2T,25% 的使用率,虽然硬盘安全性级别比较高(允许多块硬盘损坏的情况下依然不丢数据),但是空间可用率太低了,所以折中一下可以使用 RAID-10(允许一块硬盘损坏而不丢失数据),这里就记录一下如何把 So you Start 的独服从 RAID-1 级别在线调整成 RAID-10。正常情况下 OVH 旗下的主机品牌,包括 OHV,So you Start, Kimsufi 都可以适用本教程,其他独服的操作也类似。

前提知识

  • mdadm, fdisk 等基础命令的使用
  • 对 RAID 级别有基础的了解
  • 了解 Linux 下分区

几个主要的步骤

  • 首先使用 So you Start 后台的系统安装工具,使用默认的 RAID1 安装 Debian Buster
  • 然后在线调整 RAID1 到 RAID10
  • 在 Debian 基础之上安装 [[Proxmox VE]]

主要分成后面几个步骤(具体的操作步骤和演示可以参考后文):

mdadm /dev/md1 --fail /dev/sdc1
mdadm /dev/md1 --remove /dev/sdc1
wipefs -a /dev/sdc1
mdadm --grow /dev/md1 --raid-devices=2

first think about a partitioning scheme. usually there is no need to absolutely put everything on a single large partition. proxmox for instance puts disk images and whatnot into /var/lib/vz which then is an ideal mount point for a split partition.

Install Debian

首先在 So you Start 后台管理面板中使用 Reinstall 重新安装系统。

  • 使用 Custom 安装
  • 在下一步分区中,使用 RAID1 安装系统,可以根据自己的需要调整分区大小,如果怕麻烦可以,可以把所有空间划分给 / 然后留一定空间给 swap。比如我的机器是 32G 的,可以给 16G swap,然后剩余的空间都划给 /。如果熟悉 Linux 的分区,并且想要自己定义剩下的空间给 RAID-x,或 ZFS,或 LVM,可以划分一个比如 2G 给 /boot 分区,然后划分240G 给 / 然后 16G 给 swap,之后可以把 / 从 RAID1 调整为 RAID10

安装完成进入系统:

debian@pve:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 10 (buster)
Release:        10
Codename:       buster

Reshape RAID

重新调整 RAID 级别。需要特别感谢 LET 上面的 Falzo 根据他所提供的详细步骤我才完成了 RAID1 到 RAID10 的在线调整。

大致的步骤需要先将 RAID1 调整为 RAID0,然后在调整为 RAID10.

首先来查看一下默认的 RAID 信息:

root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid1 sda2[0] sdc2[1] sdd2[3] sdb2[2]
      511868928 blocks super 1.2 [4/4] [UUUU]
      bitmap: 2/4 pages [8KB], 65536KB chunk

unused devices: <none>

可以看到有一个 md2 RAID,使用了 raid1,有四个分区分别是 sda2, sdc2, sdd2, sdb2 组合而成。

查看硬盘信息(模糊掉敏感的一些标识信息):

root@pve:~# fdisk -l
Disk /dev/sdb: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: HGST HUS7-----AL
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: B411C4C1-EA13-42F1-86D8-DC-------115

Device          Start        End    Sectors   Size Type
/dev/sdb1        2048    1048575    1046528   511M EFI System
/dev/sdb2     1048576 1025048575 1024000000 488.3G Linux RAID
/dev/sdb3  1025048576 1058603007   33554432    16G Linux filesystem


Disk /dev/sdc: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: HGST HUS7-----AL
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: DA108B72-B409-4F9E-8FF1-0D---------8

Device          Start        End    Sectors   Size Type
/dev/sdc1        2048    1048575    1046528   511M EFI System
/dev/sdc2     1048576 1025048575 1024000000 488.3G Linux RAID
/dev/sdc3  1025048576 1058603007   33554432    16G Linux filesystem


Disk /dev/sdd: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: HGST HUS-----0AL
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: DC27A340-79CB-437E-952F-97A-------A8

Device          Start        End    Sectors   Size Type
/dev/sdd1        2048    1048575    1046528   511M EFI System
/dev/sdd2     1048576 1025048575 1024000000 488.3G Linux RAID
/dev/sdd3  1025048576 1058603007   33554432    16G Linux filesystem


Disk /dev/sda: 1.8 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: HGST HU------0AL
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 76C633FE-ACC3-40FA-A111-2C--------C8

Device          Start        End    Sectors   Size Type
/dev/sda1        2048    1048575    1046528   511M EFI System
/dev/sda2     1048576 1025048575 1024000000 488.3G Linux RAID
/dev/sda3  1025048576 1058603007   33554432    16G Linux filesystem
/dev/sda4  3907025072 3907029134       4063     2M Linux filesystem


Disk /dev/md2: 488.2 GiB, 524153782272 bytes, 1023737856 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

然后可以通过 mdadm 命令 reshape RAID1,这一步可以直接在线执行,完全不需要 [[IPMI]] 等等额外的工具。

在线将 RAID1 转变成 RAID10 的步骤可以参考这篇文章 作者写的非常清楚。[[Converting RAID1 to RAID10 online]]

具体的步骤可以查看如下:

root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid1 sda2[0] sdc2[1] sdd2[3] sdb2[2]
      511868928 blocks super 1.2 [4/4] [UUUU]
      bitmap: 2/4 pages [8KB], 65536KB chunk

unused devices: <none>
root@pve:~# mdadm /dev/md2 --fail /dev/sdc2
mdadm: set /dev/sdc2 faulty in /dev/md2
root@pve:~# mdadm /dev/md2 --remove /dev/sdc2
mdadm: hot removed /dev/sdc2 from /dev/md2
root@pve:~# wipefs -a /dev/sdc2
/dev/sdc2: 4 bytes were erased at offset 0x00001000 (linux_raid_member): fc 4e 2b a9
root@pve:~# mdadm /dev/md2 --fail /dev/sdd2
mdadm: set /dev/sdd2 faulty in /dev/md2
root@pve:~# mdadm /dev/md2 --remove /dev/sdd2
mdadm: hot removed /dev/sdd2 from /dev/md2
root@pve:~# wipefs -a /dev/sdd2
/dev/sdd2: 4 bytes were erased at offset 0x00001000 (linux_raid_member): fc 4e 2b a9
root@pve:~# mdadm --grow /dev/md2 --raid-devices=2
raid_disks for /dev/md2 set to 2
root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid1 sda2[0] sdb2[2]
      511868928 blocks super 1.2 [2/2] [UU]
      bitmap: 3/4 pages [12KB], 65536KB chunk

unused devices: <none>
root@pve:~# mdadm --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid1
        Array Size : 511868928 (488.16 GiB 524.15 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 2
     Total Devices : 2
       Persistence : Superblock is persistent

     Intent Bitmap : Internal

       Update Time : Thu Oct 21 13:33:45 2021
             State : clean
    Active Devices : 2
   Working Devices : 2
    Failed Devices : 0
     Spare Devices : 0

Consistency Policy : bitmap

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 158

    Number   Major   Minor   RaidDevice State
       0       8        2        0      active sync   /dev/sda2
       2       8       18        1      active sync   /dev/sdb2
root@pve:~# sudo mdadm --grow /dev/md2 --level=0 --backup-file=/home/backup-md2
mdadm: level of /dev/md2 changed to raid0
root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid0 sdb2[2]
      511868928 blocks super 1.2 64k chunks

unused devices: <none>
root@pve:~# mdadm --misc --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid0
        Array Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 1
     Total Devices : 1
       Persistence : Superblock is persistent

       Update Time : Thu Oct 21 13:40:10 2021
             State : clean
    Active Devices : 1
   Working Devices : 1
    Failed Devices : 0
     Spare Devices : 0

        Chunk Size : 64K

Consistency Policy : none

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 163

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync   /dev/sdb2
root@pve:~# mdadm --grow /dev/md2 --level=10 --backup-file=/home/backup-md2 --raid-devices=4 --add /dev/sda2 /dev/sdc2 /dev/sdd2
mdadm: level of /dev/md2 changed to raid10
mdadm: added /dev/sda2
mdadm: added /dev/sdc2
mdadm: added /dev/sdd2
raid_disks for /dev/md2 set to 5
root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid10 sdd2[5] sdc2[4](S) sda2[3](S) sdb2[2]
      511868928 blocks super 1.2 2 near-copies [2/1] [U_]
      [>....................]  recovery =  0.5% (2835392/511868928) finish=50.8min speed=166787K/sec

unused devices: <none>
root@pve:~# mdadm --misc --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid10
        Array Size : 511868928 (488.16 GiB 524.15 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 2
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Thu Oct 21 13:42:49 2021
             State : active, degraded, recovering
    Active Devices : 1
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 3

            Layout : near=2
        Chunk Size : 64K

Consistency Policy : resync

    Rebuild Status : 1% complete

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 221

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync set-A   /dev/sdb2
       5       8       50        1      spare rebuilding   /dev/sdd2

       3       8        2        -      spare   /dev/sda2
       4       8       34        -      spare   /dev/sdc2
root@pve:~# mdadm --misc --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid10
        Array Size : 511868928 (488.16 GiB 524.15 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 2
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Thu Oct 21 13:47:58 2021
             State : active, degraded, recovering
    Active Devices : 1
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 3

            Layout : near=2
        Chunk Size : 64K

Consistency Policy : resync

    Rebuild Status : 11% complete

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 554

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync set-A   /dev/sdb2
       5       8       50        1      spare rebuilding   /dev/sdd2

       3       8        2        -      spare   /dev/sda2
       4       8       34        -      spare   /dev/sdc2
root@pve:~# mdadm --misc --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid10
        Array Size : 511868928 (488.16 GiB 524.15 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 2
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Thu Oct 21 13:48:29 2021
             State : clean, degraded, recovering
    Active Devices : 1
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 3

            Layout : near=2
        Chunk Size : 64K

Consistency Policy : resync

    Rebuild Status : 12% complete

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 588

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync set-A   /dev/sdb2
       5       8       50        1      spare rebuilding   /dev/sdd2

       3       8        2        -      spare   /dev/sda2
       4       8       34        -      spare   /dev/sdc2
root@pve:~# mdadm --grow /dev/md2 --raid-devices=4
root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid10 sdd2[5] sdc2[4] sda2[3] sdb2[2]
      511868928 blocks super 1.2 64K chunks 2 near-copies [4/3] [U_UU]
      [>....................]  reshape =  0.2% (1387520/511868928) finish=67.4min speed=126138K/sec

unused devices: <none>
root@pve:~# mdadm --misc --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid10
        Array Size : 511868928 (488.16 GiB 524.15 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Thu Oct 21 13:50:47 2021
             State : clean, degraded, reshaping
    Active Devices : 3
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 1

            Layout : near=2
        Chunk Size : 64K

Consistency Policy : resync

    Reshape Status : 1% complete
     Delta Devices : 2, (2->4)

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 725

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync set-A   /dev/sdb2
       5       8       50        1      spare rebuilding   /dev/sdd2
       4       8       34        2      active sync set-A   /dev/sdc2
       3       8        2        3      active sync set-B   /dev/sda2
root@pve:~# mdadm --misc --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid10
        Array Size : 511868928 (488.16 GiB 524.15 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Thu Oct 21 13:51:59 2021
             State : active, degraded, reshaping
    Active Devices : 3
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 1

            Layout : near=2
        Chunk Size : 64K

Consistency Policy : resync

    Reshape Status : 3% complete
     Delta Devices : 2, (2->4)

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 769

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync set-A   /dev/sdb2
       5       8       50        1      spare rebuilding   /dev/sdd2
       4       8       34        2      active sync set-A   /dev/sdc2
       3       8        2        3      active sync set-B   /dev/sda2
root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid10 sdd2[5] sdc2[4] sda2[3] sdb2[2]
      511868928 blocks super 1.2 64K chunks 2 near-copies [4/3] [U_UU]
      [====>................]  reshape = 21.8% (111798784/511868928) finish=59.6min speed=111736K/sec

unused devices: <none>
root@pve:~# mdadm --misc --detail /dev/md2
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid10
        Array Size : 511868928 (488.16 GiB 524.15 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Thu Oct 21 14:05:44 2021
             State : active, degraded, reshaping
    Active Devices : 3
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 1

            Layout : near=2
        Chunk Size : 64K

Consistency Policy : resync

    Reshape Status : 22% complete
     Delta Devices : 2, (2->4)

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 1345

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync set-A   /dev/sdb2
       5       8       50        1      spare rebuilding   /dev/sdd2
       4       8       34        2      active sync set-A   /dev/sdc2
       3       8        2        3      active sync set-B   /dev/sda2
root@pve:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev             16G     0   16G   0% /dev
tmpfs           3.2G  8.9M  3.2G   1% /run
/dev/md2        481G  1.5G  455G   1% /
tmpfs            16G     0   16G   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            16G     0   16G   0% /sys/fs/cgroup
/dev/sdd1       511M  3.3M  508M   1% /boot/efi
tmpfs           3.2G     0  3.2G   0% /run/user/1000
root@pve:~# lsblk
NAME    MAJ:MIN RM   SIZE RO TYPE   MOUNTPOINT
sda       8:0    0   1.8T  0 disk
├─sda1    8:1    0   511M  0 part
├─sda2    8:2    0 488.3G  0 part
│ └─md2   9:2    0 488.2G  0 raid10 /
├─sda3    8:3    0    16G  0 part   [SWAP]
└─sda4    8:4    0     2M  0 part
sdb       8:16   0   1.8T  0 disk
├─sdb1    8:17   0   511M  0 part
├─sdb2    8:18   0 488.3G  0 part
│ └─md2   9:2    0 488.2G  0 raid10 /
└─sdb3    8:19   0    16G  0 part   [SWAP]
sdc       8:32   0   1.8T  0 disk
├─sdc1    8:33   0   511M  0 part
├─sdc2    8:34   0 488.3G  0 part
│ └─md2   9:2    0 488.2G  0 raid10 /
└─sdc3    8:35   0    16G  0 part   [SWAP]
sdd       8:48   0   1.8T  0 disk
├─sdd1    8:49   0   511M  0 part   /boot/efi
├─sdd2    8:50   0 488.3G  0 part
│ └─md2   9:2    0 488.2G  0 raid10 /
└─sdd3    8:51   0    16G  0 part   [SWAP]
root@pve:~# cat /proc/mdstat
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md2 : active raid10 sdd2[5] sdc2[4] sda2[3] sdb2[2]
      511868928 blocks super 1.2 64K chunks 2 near-copies [4/3] [U_UU]
      [======>..............]  reshape = 32.9% (168472448/511868928) finish=49.0min speed=116718K/sec

unused devices: <none>

等待很长一段时间之后 RAID10 完成:

root@pve:~# mdadm --misc --detail /dev/md2 
/dev/md2:
           Version : 1.2
     Creation Time : Thu Oct 21 12:58:06 2021
        Raid Level : raid10
        Array Size : 1023737856 (976.31 GiB 1048.31 GB)
     Used Dev Size : 511868928 (488.16 GiB 524.15 GB)
      Raid Devices : 4
     Total Devices : 4
       Persistence : Superblock is persistent

       Update Time : Fri Oct 22 01:39:27 2021
             State : clean 
    Active Devices : 4
   Working Devices : 4
    Failed Devices : 0
     Spare Devices : 0

            Layout : near=2
        Chunk Size : 64K

Consistency Policy : resync

              Name : md2
              UUID : 0686b64f:07957a70:4e937aa2:23716f6e
            Events : 6536

    Number   Major   Minor   RaidDevice State
       2       8       18        0      active sync set-A   /dev/sdb2
       5       8       50        1      active sync set-B   /dev/sdd2
       4       8       34        2      active sync set-A   /dev/sdc2
       3       8        2        3      active sync set-B   /dev/sda2

Install Proxmox VE on Debian

完成 RAID10 的调整之后,如果磁盘还有剩余的空间,可以再分区,之后使用 ZFS,raidz 可以自己选择。

然后可以更具官方的教程,直接在 Debian 的基础之上安装 Proxmox VE。之后需要移除掉 cloud-init 否则网络配置会产生问题

reference

  • [[mdadm-command]]

2021-10-22 linux , raid , raid-10 , proxmox , pve , dedicated-server , hard-disk , backup , so-you-start , ovh

Ubuntu 20.04 使用 MergerFS

[[so-you-start]] 的独服有4块 2T 的硬盘,本来想配置一个 Soft RAID-10,但折腾了一个礼拜,重装了无数遍系统,配置了很多次,从 Ubuntu,Proxmox VE,Debian 都尝试了一遍,最终放弃了,想着充分利用其空间,使用 Proxmox VE,备份好数据,不用 RAID 了,毕竟如果使用默认的 RAID-1,我只能利用8T空间中的 2T 不到,而使用 RAID-10 也只能利用不到 4T 左右空间。至于使用单盘,所有的数据备份,和数据安全性的工作就完全依靠自己的备份去完成了。但是好处是可利用的空间大了。

Proxmox VE 硬盘直通

参考之前的文章Proxmox VE 硬盘直通,将 Proxmox VE 安装后剩下的三块硬盘直通给 Ubuntu。

root@pve:/var/lib/vz/dump# qm set 101 -scsi1 /dev/disk/by-id/ata-HGST_HUS726020ALA610_K5HWJ6NG
update VM 101: -scsi1 /dev/disk/by-id/ata-HGST_HUS726020ALA610_K5HWJ6NG
root@pve:/var/lib/vz/dump# qm set 101 -scsi2 /dev/disk/by-id/ata-HGST_HUS726020ALA610_K5J0ZUWA
update VM 101: -scsi2 /dev/disk/by-id/ata-HGST_HUS726020ALA610_K5J0ZUWA
root@pve:/var/lib/vz/dump# qm set 101 -scsi3 /dev/disk/by-id/ata-HGST_HUS726020ALA610_K5HW9RJG
update VM 101: -scsi3 /dev/disk/by-id/ata-HGST_HUS726020ALA610_K5HW9RJG

在 Ubuntu 虚拟机就可以看到:

einverne@sysubuntu:~$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0    7:0    0 61.9M  1 loop /snap/core20/1169
loop1    7:1    0 55.4M  1 loop /snap/core18/2128
loop2    7:2    0 70.3M  1 loop /snap/lxd/21029
loop3    7:3    0 67.3M  1 loop /snap/lxd/21545
loop5    7:5    0 32.4M  1 loop /snap/snapd/13270
loop6    7:6    0 32.5M  1 loop /snap/snapd/13640
sda      8:0    0   64G  0 disk 
├─sda1   8:1    0    1M  0 part 
└─sda2   8:2    0   64G  0 part /
sdb      8:16   0  1.8T  0 disk 
sdc      8:32   0  1.8T  0 disk 
sdd      8:48   0  1.8T  0 disk 
sr0     11:0    1 1024M  0 rom  

然后使用 fdiskparted 给硬盘进行分区,格式化之后,挂载到 /mnt:

root@sysubuntu:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.9G     0  1.9G   0% /dev
tmpfs           394M  1.1M  393M   1% /run
/dev/sda2        63G   10G   50G  17% /
tmpfs           2.0G  468K  2.0G   1% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/loop0       62M   62M     0 100% /snap/core20/1169
/dev/loop2       71M   71M     0 100% /snap/lxd/21029
/dev/loop1       56M   56M     0 100% /snap/core18/2128
/dev/loop3       68M   68M     0 100% /snap/lxd/21545
/dev/loop5       33M   33M     0 100% /snap/snapd/13270
/dev/loop6       33M   33M     0 100% /snap/snapd/13640
tmpfs           394M     0  394M   0% /run/user/1000
/dev/sdb1       1.8T   77M  1.7T   1% /mnt/sdb1
/dev/sdc1       1.8T   77M  1.7T   1% /mnt/sdc1
/dev/sdd1       1.8T   77M  1.7T   1% /mnt/sdd1

Install MergerFS

官方发布页面 下载最新的安装包:

wget https://github.com/trapexit/mergerfs/releases/download/2.32.6/mergerfs_2.32.6.ubuntu-bionic_amd64.deb
sudo dpkg -i mergerfs_2.32.6.ubuntu-bionic_amd64.deb

MergerFS 配置

MergerFS 可以将一组硬盘(JBOD)组合形成一个硬盘,类似于 RAID,但完全不同。

root@sysubuntu:~# mkdir -p /mnt/storage
root@sysubuntu:~# mergerfs -o defaults,allow_other,use_ino,category.create=mfs,minfreespace=100G,ignorepponrename=true,fsname=mergerFS /mnt/sdb1:/mnt/sdc1/:/mnt/sdd1/ /mnt/storage/
root@sysubuntu:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            1.9G     0  1.9G   0% /dev
tmpfs           394M  1.1M  393M   1% /run
/dev/sda2        63G   10G   50G  17% /
tmpfs           2.0G  468K  2.0G   1% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
/dev/loop0       62M   62M     0 100% /snap/core20/1169
/dev/loop2       71M   71M     0 100% /snap/lxd/21029
/dev/loop1       56M   56M     0 100% /snap/core18/2128
/dev/loop3       68M   68M     0 100% /snap/lxd/21545
/dev/loop5       33M   33M     0 100% /snap/snapd/13270
/dev/loop6       33M   33M     0 100% /snap/snapd/13640
tmpfs           394M     0  394M   0% /run/user/1000
/dev/sdb1       1.8T   77M  1.7T   1% /mnt/sdb1
/dev/sdc1       1.8T   77M  1.7T   1% /mnt/sdc1
/dev/sdd1       1.8T   77M  1.7T   1% /mnt/sdd1
mergerFS        5.4T  229M  5.1T   1% /mnt/storage

参数说明:

  • defaults: 开启以下 FUSE 参数以提升性能:atomic_o_trunc, auto_cache, big_writes, default_permissions, splice_move, splice_read, splice_write;
  • allow_other: 允许挂载者以外的用户访问。需要编辑 /etc/fuse.conf。
  • use_ino: 使用 mergerfs 而不是 libfuse 提供的 inode,使硬链接的文件 inode 一致;
  • category.create=mfs: Spreads files out across your drives based on available space;
  • minfreespace=100G: 最小剩余空间 100G,当写文件时,跳过剩余空间低于 100G 的文件系统
  • ignorepponrename=true: 重命名时保持原来的存储路径

最后编辑 /etc/fstab 来在启动时自动挂载。

使用 lsblk -f 查看:

root@sysubuntu:~# lsblk -f
NAME   FSTYPE   LABEL UUID                                 FSAVAIL FSUSE% MOUNTPOINT
loop0  squashfs                                                  0   100% /snap/core20/1169
loop1  squashfs                                                  0   100% /snap/core18/2128
loop2  squashfs                                                  0   100% /snap/lxd/21029
loop3  squashfs                                                  0   100% /snap/lxd/21545
loop5  squashfs                                                  0   100% /snap/snapd/13270
loop6  squashfs                                                  0   100% /snap/snapd/13640
sda                                                                       
├─sda1                                                                    
└─sda2 ext4           8ecce3ba-cd9f-494a-966a-d90fc31cd0fc   49.6G    16% /
sdb                                                                       
└─sdb1 ext4           50292f2c-0f85-4871-9c41-148038b31e24    1.7T     0% /mnt/sdb1
sdc                                                                       
└─sdc1 ext4           1de9b276-5a5d-41ac-989a-12bdc9ef4d0b    1.7T     0% /mnt/sdc1
sdd                                                                       
└─sdd1 ext4           420d99a9-de31-4df4-af93-6863f3284f3d    1.7T     0% /mnt/sdd1
sr0                                                                       

然后在 /etc/fstab 中配置:

/dev/disk/by-uuid/50292f2c-0f85-4871-9c41-148038b31e24 /mnt/sdb1 ext4 defaults 0 0
/dev/disk/by-uuid/1de9b276-5a5d-41ac-989a-12bdc9ef4d0b /mnt/sdc1 ext4 defaults 0 0
/dev/disk/by-uuid/420d99a9-de31-4df4-af93-6863f3284f3d /mnt/sdd1 ext4 defaults 0 0

/mnt/sdb1:/mnt/sdc1/:/mnt/sdd1 /mnt/storage   fuse.mergerfs defaults,allow_other,use_ino,category.create=mfs,minfreespace=100G,fsname=mergerfs 0 0

这样重启也会自动进行挂载。

注意 rtorrent 使用

如果要在 mergerfs 上使用 rtorrent 需要注意使用如下配置:

allow_other,use_ino,cache.files=partial,dropcacheonclose=true,category.create=mfs

reference


2021-10-21 linux , ubuntu , mergerfs , proxmox-ve , proxmox , raid , pve , dedicated-server

在 Linux 下使用 Clash For Windows 管理 Clash 订阅

早之前写过一篇文章,当时我直接使用命令行的方式使用 clash,但用过一段时间之后发现 Clash For Windows 支持了 Linux,所以切换到 Clash For Windows,用 UI 界面方便随时切换。

不要看这个 Clash For Windows 的名字有点歧义,实际上是全平台的,不是 Windows 专属的。Clash For Windows 在下文中会简称 CFW。

Clash for Windows 的优点:

  • 支持自动选择节点,可以根据延迟自动选择,也可以根据规则
  • 支持本地编辑规则
  • 支持查看当前订阅的流量等信息

更加详细的使用指南可以参考这个文档

CFW 使用

可以在 GitHub 下载,也可以使用镜像地址下载

下载完成后是一个压缩包,解压,并执行其中的 cfw 即可。

添加快捷方式,因为我使用 Cinnamon 是基于 Gnome ,所以可以执行如下命令添加一个快捷方式:

gnome-desktop-item-edit ~/.local/share/applications --create-new

在弹出的窗口中,填写 Name 和 Command

gnome new launcher

说明:

  • Name: 显示的名字
  • Command: cfw 的绝对路径

Dashboard:

Clash For Windows 页面:

在 Profile 页面上可以添加订阅地址,订阅地址可以在这里 获取。


2021-10-17 linux , clash , v2ray , proxy , shadowsocks

独服 Proxmox VE 配置 NAT 使虚拟机共用一个公网 IP

[[so-you-start]] 的独立服务器本来安装了 Ubuntu 20.04,后来想想为了充分利用 CPU 和内存,不如安装一个 [[Proxmox VE]] 然后在其基础之上再安装 Ubuntu 或者其他的系统测试。So you Start 通过后台安装 Proxmox 的过程比较简单,我直接使用了后台的 Proxmox VE 6 模板安装了 Proxmox。

So you Start 其他独立服务器提供商通常只会提供一个公网 IP,其他的 failover IP 可能需要购买(So you Start 可以使用 1.5$ 购买一个),如果不想多花这个购买 IP 的钱,可以配置 Proxmox VE 的虚拟机走 NAT,共用宿主机 Proxmox VE 的 IP,做一下端口转发。实际在一些 VPS 提供商那边也能看到 [[NAT VPS]],这类型的 VPS 就是共用同一个 IP 的 VPS,这一类的 VPS 通常比较便宜,但是可用的端口数量有限。

完成下文的配置之后大致的网络拓扑图是这样的:

proxmox ve nat

前提知识

在继续下文之前有一些前提知识需要了解,否则会理解起来有些困难。

Linux Bridge

Linux Bridge 一般翻译成网桥,相当于一个软件实现的交换机。

如果要配置成 NAT 网络,Proxmox VE 上所有的虚拟机共享一个网桥 vmbr1,通过 vmbr1 访问外部网络。

理论上 Proxmox VE 支持 4094 个网桥。默认情况下 Proxmox VE 会创建一个 vmbr0 的网桥,并和检测到的第一块网卡(eno3)桥接。可以查看网口的配置文件 /etc/network/interfaces 对应的信息:

root@pve:~# cat /etc/network/interfaces
# network interface settings; autogenerated
# Please do NOT modify this file directly, unless you know what
# you're doing.
#
# If you want to manage parts of the network configuration manually,
# please utilize the 'source' or 'source-directory' directives to do
# so.
# PVE will preserve these directives, but will NOT read its network
# configuration from sourced files, so do not attempt to move any of
# the PVE managed interfaces into external files!

auto lo
iface lo inet loopback

iface eno3 inet manual

iface eno4 inet manual

auto vmbr0
iface vmbr0 inet dhcp
    bridge-ports eno3
    bridge-stp off
    bridge-fd 0

NAT

[[NAT]] 全称是 Network Address Translation,在计算机网络中是网络地址转换的含义,也被叫做网络掩蔽,这是一种在 IP 数据包通过路由器或防火墙时重写来源 IP 地址或目的 IP 地址的技术。

在我们的 Proxmox VE 只有一个公网 IP 的情况下,如果要让多个虚拟机共享同一个 IP 地址对外提供服务,就需要用到 NAT 技术,让请求访问到宿主机的时候,转发到对应的虚拟机。

所有的虚拟机使用内部私有 IP 地址,并通过 Proxmox VE 的公网 IP 访问外部网络。我们会使用 iptables 来改写虚拟机和外部通信的数据包:

  • 对于虚拟机向外部网络发出的数据包,源地址是内网 IP,目标终端在返回数据的时候,无法把数据包发送对正确的路由,所以在发送出去前,将源地址替换成 Proxmox VE 的 IP 地址
  • 对于外部网络返回的数据包,将目的地址替换成对应虚拟机的 IP

NDP

[[NDP]] 全称是 Neighbor Discovery Protocol,简称 NDP,类似 IPv4 中的 ARP 协议。

配置 Proxmox VE NAT

上面的配置也提到了默认情况下 Proxmox VE 会创建一个 vmbr0 桥接找到的网卡。

首先查看一下网络接口:

root@pve:~# ip -f inet a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
4: vmbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    inet 51.xx.xx.xx/24 brd 51.xx.xx.xxx scope global dynamic vmbr0
       valid_lft 81976sec preferred_lft 81976sec

Proxmox VE 上使用 NAT 创建虚拟机的原理是,创建一个 Linux Bridge 并创建一个子网,然后将所有虚拟机包括宿主机都连接到这个子网内,再开启 [[iptables]] 的 NAT 功能。

创建 Linux Bridge

在安装网桥之前,首先安装:

apt install ifupdown2

然后登录 Proxmox VE 后台,创建 Linux Bridge,点击 PVE,然后选择 System -> Networks,然后点击创建。

填写 IP 和子网掩码,IP 地址填写个局域网的网段地址就行。其他项目不用填也不用改,保持默认(不用 IPv6 的情况下)。

  • IP 地址填写一个局域网地址:10.0.0.1/24

上面的配置创建了一个新的 vmbr1 网桥分配了一个子网 10.0.0.1/24,宿主机(网关)在子网的 IP 是 10.0.0.1。

创建完成之后,查看 /etc/network/interfaces,然后在对应的 vmbr1 后面修改成相应的配置(注意 vmbr1 下面的配置):

auto lo
iface lo inet loopback

iface eno3 inet manual

iface eno4 inet manual

auto vmbr0
iface vmbr0 inet dhcp
        bridge-ports eno3
        bridge-stp off
        bridge-fd 0

auto vmbr1
iface vmbr1 inet static
        address 10.0.0.1/24
        gateway 1.2.3.254  # 独立服务器IP前三个数加上 254
        bridge-ports none
        bridge-stp off
        bridge-fd 0
        post-up echo 1 > /proc/sys/net/ipv4/ip_forward
        post-up iptables -t nat -A POSTROUTING -s '10.0.0.0/24' -o vmbr0 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '10.0.0.0/24' -o vmbr0 -j MASQUERADE
        
        post-up iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 2022 -j DNAT --to 10.0.0.102:22
        post-down iptables -t nat -D PREROUTING -i vmbr0 -p tcp --dport 2022 -j DNAT --to 10.0.0.102:22

说明:

  • ip_forward 一行表示开启 IPv4 转发,这个是内核参数,将 Linux 当作路由器用的参数。一般来说,一个路由器至少要有两个网络接口,一个 WAN,一个 LAN,为了让 LAN 和 WAN 流量相同,需要内核上的路由
  • post-uppost-down 分别表示网卡启用和禁用之后,执行后面的命令
  • iptables 行表示,开启防火墙转发,-A 表示添加规则,配置一条 NAT 规则,源地址为 10.0.0.0/24 的流量,转发到 vmbr0 接口。
  • MASQUERADE 对 IP 地址数据包进行改写
  • 网卡关闭后 -D 删除这条规则
  • 最后 2 行是把虚拟机 10.0.0.102 上的 22 端口 NAT 到宿主机的 2022 端口,这样使得外部的网络可以通过 Proxmox VE 宿主机的 2022 端口访问虚拟机的 22 端口,可以直接使用上面的配置,或者手动执行下面的命令:

      iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 2022 -j DNAT --to 10.0.0.102:22
    

最后两行配置在网络配置中是为了让系统重启之后配置依然生效。否则 iptables 的转发就可能丢失。

启用网桥:

sudo ifup vmbr1

显示信息:

ip address show dev vmbr1

查看 iptables 配置是否生效:

iptables -L -t nat

结果:

root@pve:~# ip address show dev vmbr1
9: vmbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether 62:32:cf:9d:5d:f9 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.1/24 scope global vmbr1
       valid_lft forever preferred_lft forever
    inet6 fe80::6032:cfff:fe9d:5df9/64 scope link 
       valid_lft forever preferred_lft forever

重启网络:

sudo systemctl restart networking
systemctl status networking.service

通过上面的方式创建了 vmbr1 的网桥之后,再创建新的虚拟机就可以使用这个新的子网。因为这里没有配置 DHCP,所以虚拟机需要设定静态 IP 地址。

在我的真实操作中,我发现无论我怎么重启 systemctl restart networking 都无法使得 Proxmox VE 的网络配置生效,最后不得不重启服务器才可以。

虚拟机配置

在创建虚拟机的时候,记得在网络配置的时候选择 vmbr1,因为没有配置 DHCP 所以需要用下面的方式手动指定虚拟机的静态 IP 地址。

Ubuntu 虚拟机网络配置

Ubuntu 从上一个版本开始就使用 netplan 来管理网络配置,所以需要修改 netplan 的配置:

einverne@ubuntu2:~$ cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    ens18:
      addresses:
      - 10.0.0.102/24
      gateway4: 10.0.0.1
      nameservers:
        addresses:
        - 8.8.8.8
        - 8.8.4.4
  version: 2

注意配置其中的静态地址和网关。

  • 静态地址配置 10.0.0.0/24 网段下的地址,比如 10.0.0.102
  • gateway4 地址配置 vmbr1 网桥的地址
  • DNS 服务器可以使用 Google 的,也可以用 1.1.1.1 Cloudflare 的,或者 OVH,或者 So you Start 提供的都行

修改完成后执行:

netplan apply

之后可以使用如下命令测试连通性:

ping 1.1.1.1
ping google.com

Debian 虚拟机网络配置

Debian 上的网络配置如下:

einverne@debian:~$ cat /etc/network/interfaces.d/50-cloud-init
auto ens18
iface ens18 inet static
address 10.0.0.100
netmask 255.255.255.0
gateway 10.0.0.1
dns-nameserver 1.1.1.1
dns-nameserver 8.8.8.8

说明:

  • ens18 是 Debian 虚拟机的网络接口
  • address 填写 10.0.0.0/24 网段的静态地址
  • gateway 填入 vmbr1 的地址

然后重启网络:systemctl restart networking

如何调试

在配置的过程中遇到很多问题,可以用一下一些命令熟悉 Linux 下的网络配置。

iptalbes -L -t nat
ip a
ip route show
cat /proc/sys/net/ipv4/ip_forward
qm config <VMID>

遇到的问题

虚拟机 VM 内部无法访问互联网

在按照上述步骤配置后,登录 VM (Ubuntu 20.04) 内部,只能 Ping 通网关(10.0.0.1) 而无法 ping 通任何外部网络。

再经过一番调查之后发现在上述配置中的 iptables 转发并没有生效,并且重启网络也没有生效,所以我只能重启服务器解决。

端口映射

在启用 NAT 网络之后,如果要外部网络访问 VM 的端口,则需要开启 iptables 端口转发。

下面一句的含义就是将 Proxmox VE(vmbr0) 的 2022 端口转发到 10.0.0.102 这台虚拟机的 22 端口:

iptables -t nat -A PREROUTING -i vmbr0 -p tcp --dport 2022 -j DNAT --to 10.0.0.102:22

这样在外部互联网就可以通过 ssh -p 2022 root@<proxmox ip> 来访问 Proxmox VE 中的虚拟机了。

如果遇到要转发一组端口可以使用:

post-up   iptables -t nat -I PREROUTING -p tcp -i vmbr0 --dport 8000:9000 -j DNAT --to 10.0.0.102:8000-9000
post-down iptables -t nat -D PREROUTING -p tcp -i vmbr0 --dport 8000:9000 -j DNAT --to 10.0.0.102:8000-9000

延伸阅读

如果已经购买了 Failover IP,或者独立服务器提供了多个可用的 IP,那么也可以参考 这篇文章 配置 Proxmox VE 的虚拟机使用额外的 IP 地址。这样使用一台独立服务器就可以开多个 KVM 的 VPS 了。

reference


2021-10-15 proxmox , pve , linux , nat , networking , operating-system

命令行下使用 jdupes 删除重复的文件

很早之前整理过一篇文章介绍了几个之前在 Linux 上用过的用来快速找到重复文件并删除的文章,这么多年过去了,最后发现还是 jdupes 最好用,因为是 c 语言编写,可以在所有平台上面运行,并且速度远远好于其他的命令。

之前的文章对于 jdupes 总结的比较简单,所以这里单独再总结一下 jdupes 常用的几个例子。

查找文件夹下重复文件

查找文件夹下重复的文件,这也是最常见的需求,可以直接

jdupes -r path/to/dir

-r 参数在这里表示 --recurse 递归查找文件夹下所有的子文件夹。

删除重复内容

jdupes 在输出重复的内容的同时也提供了方法可以让用户自行选择删除哪个文件,或者自动发现并删除重复的文件。

注意:个人推荐每一次都手动选择需要删除的内容,否则请提前做好备份工作,防止文件丢失

jdupes 提供了 -d 选择,如果使用 -d 选项,jdupes 会弹出提示让用户选择是否删除重复文件:

jdupes -dr path/to/dir

如果确定自己不需要手动选择删除,可以使用 -N 选项,表示 --noprompt,谨慎使用该选项:

jdupes -r -N path/to/dir

查找两个文件夹下重复文件并删除第二个文件夹下的重复内容

有些时候文件在两个文件夹中,比如 dir1, dir2,需要实现的是将 dir2 中和 dir1 中重复的文件删除,而保留 dir1 中的文件,这个时候可以使用 -O 选项。

-O 选择可以让用户控制出现在第一条的文件,以便将其保留。

jdupes -nrdNO dir1 dir2

上面的命令会递归查找 dir1 和 dir2 中的文件,并自动将 dir2 中和 dir1 重复的文件删除。

reference


2021-10-12 jdupes , linux , file-manage , duplicate , tutorial , cli

So you Start 独服 Proxmox VE 虚拟机配置 Failover IP

最近买了一台 [[so-you-start]] 的独立服务器,开始的时候安装了 Ubuntu 没有充分利用独立服务器的优势,所以这两天把系统重新安装成了 [[Proxmox VE]],然后在上面又安装了 Ubuntu 20.04,So you Start 提供了额外可以购买的 16 个 [[Failover IPs]],Failover IP 本来是为了可以将服务器迁移到另外的服务器而提供的机制,但在 Proxmox VE 虚拟化技术系统下,可以给虚拟机也分配不同的 IP,这样就实现了从一台服务器虚拟化多个 VPS 的操作。

安装 Proxmox VE 的过程就不多说了,在 So you Start 或者 OVH 后台直接使用模板安装即可,我使用的 6.x 版本,没有升级到最新的 7 版本。

安装完成后使用 Ubuntu Server 的 ISO 镜像完成虚拟机的安装。

前提准备工作

  • 一台安装好 Proxmox VE 的独立主机
  • 新建一台可以登录的虚拟机,操作系统不限 (推荐 Debian/Ubuntu)
  • 购买好至少一个额外的 Failover IP

配置 Failover IP 到虚拟机

Create a Virtual MAC Address

首先到 So you Start 后台 IP,然后选择购买的 Failover IP,新增 virtual MAC 地址,然后复制该 MAC 地址备用。

比如:

02:01:00:78:95:aa

新增 MAC 地址可能有一点延迟,等待一小会儿生效即可。

Add virtual MAC to the NIC of a VM

然后需要在 Proxmox VE 虚拟机配置中将上述 MAC 地址配置。如果还没有安装虚拟机,可以参考 Proxmox VE 官网的教程

VM 配置前需要是关闭状态。

在 Proxmox VE 中,找到虚拟机的 Hardware

找到 Network Device 选项,默认情况下是一个随机生成的 MAC 地址:

点击 Edit,然后在 MAC address 一栏将上一步的虚拟 MAC 地址填入,并保存。

然后启动 VM,接下来需要配置虚拟机的网络接口。

Configuring Network Settings

配置虚拟机网络。

Debian 10

首先查看一下接口:

ip addr

除了一个 lo 应该能看到类似 ens18 这样的接口。

Debian 的网络接口配置在 vi /etc/network/interfaces:

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto ens18
iface ens18 inet static
address 192.0.2.1
netmask 255.255.255.0
gateway 203.0.113.254
dns-nameservers 208.67.222.222 208.67.220.220

说明:

  • 修改其中的 ens18 为自己的相应的配置
  • address 一行:192.0.2.1 修改为自己的 Failover IP
  • gateway 一行: 203.0.113.254 前3个字节的数字,修改成独立服务器 IP 地址的前三个字节 IP 地址,最后添加 254,比如独立服务器的 IP 是 1.2.3.4,那么使用 1.2.3.254 作为网关
  • 最后一行是 DNS 设置,可以使用上面使用的 OpenDNS,也可以使用任何其他的,比如 Cloudflare 的 1.1.1.1, 或者 Google 的 8.8.8.8

然后使得接口生效:

ip link set ens18 up

最后重启 networking:

systemctl restart networking

然后可以测试连通性:

ping 8.8.8.8

能够 ping,表示已经可以联网。

ping google.com

然后看一下 DNS 解析,如果域名无法解析,我这边情况是少了 /etc/resolv.conf,手工创建文件并写入:

nameserver 8.8.8.8

即可。

Ubuntu 18.04

Ubuntu 从 17 版本开始就使用 Netplan 来管理网络配置,所以和 Debian 有一些区别。

修改 netplan 配置文件,根据不同的系统可能配置文件路径不一样,请注意一下:

vi /etc/netplan/01-netcfg.yaml
vi /etc/netplan/00-installer-config.yaml

然后使用:

# This is the network config written by 'subiquity'
network:
  version: 2
  renderer: networkd
  ethernets:
    ens18:
      dhcp4: no
      dhcp6: no
      addresses:
        - 192.0.2.1/32  # 这里填写 failover ip(vMAC 地址需要提前配好)
        - 1111:2222:3333:6666::2/64 # 如果有 IPv6 地址也可以配上,an ipv6 from your server allocation
      gateway4: 1.2.3.254
      nameservers:
        addresses: [8.8.8.8, 1.1.1.1]
      routes:
      - to: 1.2.3.254/32
        via: 0.0.0.0
        scope: link

和上面的配置类似,对应替换即可。

然后使之生效:

sudo netplan apply

reference


2021-10-11 so-you-start , proxmox , proxmox-ve , pve , linux , ubuntu , failover-ip , network , ip

电子书

最近文章

  • 将字幕压制到视频中 本文总结一下将字幕文件压制到视频中的方式,(当然我个人是非常不喜欢直接将字幕压制到视频流中作为硬字幕压制的,但有些时候可能就是需要分享这样硬字幕的视频,比如视频网站,所以也会在下文总结一下)。
  • 解决 Clash for Windows 节点测速 timeout 问题 [[Clash for Windows]] 使用过程中一直没有什么问题,但是昨天心血来潮把 Clash for Windows 从 0.18.8 升级到了最新版本(0.20.5) ,然后发现节点全部 timeout。但可以排除的是这些节点肯定是可以用的,因为在手机上是完全没有问题的。
  • Arc 浏览器初印象 很早之前就在 Twitter 上看到有人分享了 Arc 浏览器的使用体验,说是非常惊艳,我就稍微的浏览了一下官网,抱持怀疑的态度先注册了一下体验,一直好奇到了 2022 年能够在浏览器上做出什么样的创新,自 Chrome 横空出世以来,快,安全迅速抢占了浏览器市场。剩下的一点点份额被 Firefox,Safari,Edge,[[Vivaldi]] 等等占据,早两年的时候我也写过一篇标题略微耸动的文章 —- 我可能要抛弃用了很多年的 Chrome 改用 Vivaldi ,但事实是 3年多过去了,我日常用的还是 Chrome,虽然 Google 在浏览器插件,隐私等等问题上这两年来一直被诟病,但至少还没有彻底地激怒我这个用户。
  • 使用开源 Wakapi 代替 WakaTime 统计编码时间 之前折腾 GitHub Profile 的时候发现了 [[WakaTime]] 这样一款统计编码时间的工具,之后在读 waka-readme 项目的时候发现,还有两个完全开源的后端兼容版本,一个是 Golang 编写的 [[wakapi]] ,一个是 Huskell 编写的 hakatime 。
  • 使用 WakaTime 统计编码时间 [[WakaTime]] 是为程序员打造的编码统计 Dashboard,可以同来统计项目,编程语言,IDE,编码时间等等内容。 之前在折腾 GitHub Profile 的时候发现的,可以在 GitHub Profile 页面中动态的展示最近的编程状态。