「Groovy」- 操作 HTML 文档

问题描述
在 Jenkins Pipeline 中,我们需要对 HTML 文档进行多种操作。之前使用 XMLParser 及 XMLSlurper 库操作 HTML 文档时遇到很多问题,因为 HTML 文档结构松散(比如没有结束标签等等),不是标准的 XML 文件,因此导致 XML 解析失败。
该笔记将整理:在 Groovy 中,操作 HTML 文档的常用方法
解决方案
方案一、使用 Jsoup 类库
项目主页:jsoup Java HTML Parser, with the best of HTML5 DOM methods and CSS selectors.
获取文档的 DOM 对象:Parsing and traversing a Document: jsoup Java HTML parser
使用选择器选择元素:Use selector-syntax to find elements: jsoup Java HTML parser
元素的查找、获取、操作:Use DOM methods to navigate a document: jsoup Java HTML parser
方案二、使用 TagSoup 类库
我们未验证该方法,只是阅读 Grape 手册时发现该方法,这里仅简单记录:

// find the PDF links of the Java specifications
@Grab(group=’org.ccil.cowan.tagsoup’, module=’tagsoup’, version=’1.2.1′)
def getHtml() {
def parser = new XmlParser(new org.ccil.cowan.tagsoup.Parser())
parser.parse(“https://docs.oracle.com/javase/specs/”)
}
html.body.’**’.a.@href.grep(~/.*\.pdf/).each{ println it }

方案一、使用 Jsoup 类库
简单的入门示例

@Grab(group=’org.jsoup’, module=’jsoup’, version=’1.10.1′)
import org.jsoup.Jsoup
import org.jsoup.nodes.* // Element
import org.jsoup.select.* // Elements

def htmlString = “<html><head><title>Title of Page</title></></head>&l[……]

READ MORE

「Robots exclusion standard」- robots.txt

屏蔽搜索引擎机器人:

User-agent: *
Disallow: /

参考文献
Robots exclusion standard – Wikipedia[……]

READ MORE

「Kubernetes」- 通过 RKE 创建高可用 Kubernetes 集群 | RKE (Rancher Kubernetes Engine)

认识
Rancher Kubernetes Engine (RKE) 是一个 CNCF 认证的 Kubernetes 发行版,完全在 Docker 容器中运行。它适用于裸机和虚拟化服务器。 RKE 解决了安装复杂的问题,这是 Kubernetes 社区的一个常见问题。使用 RKE,Kubernetes 的安装和操作既简单又容易自动化,并且完全独立于您运行的操作系统和平台。只要你能运行受支持的 Docker 版本,你就可以使用 RKE 部署和运行 Kubernetes;
简单说,通过 RKE 工具,我们能够快速部署 Kubernetes 集群:在 YAML 中,通过定义主机 SSH 连接信息,RKE 将负责完成后续的 Kubernetes 部署任务。
该笔记将记录:通过 RKE 快速部署 Kubernetes Cluster 的流程,以及相关问题的解决方案。
解决方案
参考 Rancher Docs/RKE Kubernetes Installation 文档,以获取详细的部署及维护细节,该笔记仅包含部署过程的概述。
第一步、准备节点
配置 Kernel 参数:

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl –system

安装 Docker 服务:Docker 20.10.1
第二步、安装工具
安装 RKE 命令:rke_linux-amd64 v1.3.15
第三步、定义配置
Upgrade from k8s v1.23 to v1.24 fails due to restarting kubelet. · Issue #38160 · rancher/rancher
通过 rke config 命令,来创建集群(按照提示填写参数即可):

# rke config –name cluster.yml
[+] Cluster Level SSH Private Key Path [~/.ssh/id_rsa]:
[+] Number of Hosts [1]: 5

# vim cluster.yaml

… enable_cri_dockerd: true

补充说明:
1)定义多个 control-plane 节点,则当通过 RKE 部署集群时会自动部署高可用。
其他常用命令:

// 查看 rke 支持 Kub[……]

READ MORE

「KUBERNETES」- kubeadm | 集群部署工具

认识
Kubeadm 是 Kubernetes 中的一个工具,其用于初始化、升级、管理 Kubernetes 集群。
组成
WIP
构建
命令安装
通过 kubeadm 部署集群时,通常会安装 kubeadm 命令,所以具体的安装方法不再展开。
配置 BASH 补全

# 首先,需要安装 bash-complete 包,因为 kubectl 依赖于它。
apt-get install bash-completion # Debian
yum install bash-completion # CentOS

# 然后,启用 kubectl 补全
echo “source <($(which kubeadm) completion bash)” >> ~/.bashrc
source ~/.bashrc

性质
部署集群
`kubeadm init`用于在机器上启动 Kubernetes 控制平面,生成初始的节点配置,以及设置群集的网络和其他核心设置。
增加节点
`kubeadm join`命令用于将节点添加到集群中。该命令需要在已经用`kubeadm init`初始化的集群中运行。
集群升级
kubeadm 也支持升级 Kubernetes 集群,可以很容易地从一个版本升级到另一个版本。
集群配置文件(kubeadm-config)
Kubernetes/kubeadm Configuration (v1beta3)
kubeadm confighttps://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-config/
kubeadm Configuration (v1beta3): ClusterConfiguration, …https://kubernetes.io/docs/reference/config-api/kubeadm-config.v1beta3/
获取集群配置文件:

# kubeadm config print init-defaults > kubeadm-config.yaml

# kubeadm init –config=kubeadm-config.yaml –upload-certs

提取 kubeadm-config 文件:

export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}’ > kubeadm.[……]

READ MORE

「KUBERNETES-ADDONS」- NFS StorageClass

认识
使用 PV + PVC 方式使用存储比较麻烦,因为每次都需要集群管理员提前进行 PV 定义。而通过 StorageClass 资源,管理员仅需进行 PV 定义,PV 资源将由集群动态创建。当开发者通过 PVC 申请存储资源时,需要在 PVC 中指定使用 StorageClass 名称,然后集群会动态创建 PV 资源。
该笔记将记录:在 Kubernetes 中,如何使用 StorageClass + PVC 提供存储服务,以及相关问题解决方法;
官网:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
文档:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner/blob/master/README.md
仓库:https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
构建
通过 Helm 部署
我们倾向于通过 HELM 进行部署,其主要目的是能够容易进行配置管理;
通过命令行直接指定参数进行安装(鉴于无法进行配置参数的管理,废弃该做法):

helm -n kube-storage-nfs –create-namespace \
install nfs-subdir-external-provisioner \
nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
–set image.repository=easzlab/nfs-subdir-external-provisioner \
–set nfs.server=192.168.10.193 \
–set nfs.path=/srv/nfs/k8s-storage \
–set storageClass.name=nas-client-provisioner

通过 Helm 导出 values.yaml 文件,并执行安装:

// 安装服务

helm repo add nfs-subdir-external-provisioner[……]

READ MORE

「HOMELAB/ARCHITECTURE」- 家庭实验室架构(version 2.0):引入动态路由协议,简化网络配置

问题描述
路由条目配置繁琐
在 version 1.0 中,我们面临如下问题:
1)随着终端设备的增加、网段数量的增加,我们需要配置更多的路由条目。在多个终端网络的场景中,针对每个终端网络,我们需要配置 N*(N-1)/2 条路由;
2)同时,为了保证路由条目能够正常工作,需要提前规划 L2TP LAC 分配到的网络地址,然后配置终端网络的网关使用固定地址接入。如果终端网络的网关设备每次分配到不同的地址,则需要修改静态路由配置;
解决方案
在新版本中,我们需要解决繁琐的配置问题:(1)LAC 不需要关心 LNS 分配的地址;(2)也不需要手工配置路由来实现互通;
针对上述需求,能够通过 OSPF 动态路由协议实现。当 LAC 接入并分配到地址之后,各个网络终端的 OSPF 通告对应的网段,实现快速网络互通;
虽然需要静态路由,但也不影响使用。而在思考改进该缺点的时候,我们得到创建分布式的低廉数据中心的灵感;
# 04/24/2022 我们的目标很简单:利用当前公网架构,将分散在各地理位置的资源集结到一起,形成大型逻辑网络。于是便产生如下拓扑(相关的技术细节不再赘述,该图已披露出关键的技术要点)
原理简述
组成部分
即 Homelab 的组成部分;
我们的 Homelab 包含 5 个部分:
1)数据中心及其网络(DC-HIVE):指我们家中的小型数据机房,其中运行各种设备及服务,用于为给其他环境提供服务;
2)便携电脑及其网络(DC-LAPTOP):指我们笔记本(工作环境),需要接入到 DC-HIVE 中来访问相关服务;
3)云服务器及其网络(DC-CLOUD):指云服务器环境(运行部分对外公开的应用服务),需要接入到 DC-HIVE 中来访问相关服务;
4)家庭办公及其网络(DC-HOME):指我们家中网络,提供终端(笔记本、手机)接入,需要接入到 DC-HIVE 中来访问相关服务;
5)其他环境及其网络(DC-XXXXX):指其他的网络环境,比如我们办公室的办公电脑,如果想要访问 DC-HIVE 服务,也需要接入;
网络结构
通过 L2TP 协议,终端数据中心接入相同网络;
通过 OSPF 协议,完成通告 LAN / L2TP 路由,实现各个终端网络环境的快速互通;

针对家中数据中心,出口设备为 Huawei AR 1220E-S 企业路由器,所以也具备 OSPF + L2TP 功能;
针对笔记本的网关,运行 pfSense 防火墙,所以能够运行 OSPF 协议,并其携带 L2TP LAC 服务;
计算服务
针对家里服务器,其运行 PVE 环境,来提供虚拟化,并运行各种测试环境;
存储服务
在家庭网络中,通过 OpenMediaVault 服务,来提供 NFS 存储,作[……]

READ MORE

「Groovy」- 正则表达式

该笔记将记录:在 Groovy 中,常用正则表达式,以及常见问题处理。
解决方案
使用 ~string 即可定义 java.util.regex.Pattern 对象。例如 ~”[Gg]roovy” 或者 ~/[Gg]roovy/ 格式
使用 =~ 即可定义 java.util.regex.Matcher 对象

// java.util.regex.Pattern
def pattern = ~/\S+er\b/

// java.util.regex.Matcher
def matcher = “My code is groovier and better when I use Groovy there” =~ pattern

assert matcher instanceof java.util.regex.Matcher

// 或者
def matcher = “My code is groovier and better when I use Groovy there” =~ /\S+er\b/
assert matcher instanceof java.util.regex.Matcher

判断字符串是否匹配正则表达式
使用 ==~ 操作符:

assert “2009” ==~ /\d+/

String regex = /^somedata(:somedata)*$/
assert “somedata” ==~ regex

// 注意事项:
// 如果是多行字符串,应该用 =~ 判断,而 ==~ 会返回 false

判断是否包含某个字符串
使用 =~ 操作符(Matcher):

if (“My code is groovier and better when I use Groovy there” =~ /\S+er\b/) {
println “At least one element matches the pattern…”
}

使用 ==~ 操作符(Boolean):

if (“My code is groovier and better when I use Groovy there” ==~ /\S+er\b/) {
println “At least one element matches the pattern…”
}

示例的两种方式是不同的:
1)前者,在 if 语句中的是 Matcher 对象,只检查字符串是否包含与 Matcher 对象匹配的内容
2)后者,在 if 语句中的是 Boolean 对象,可类比于调用 matcher.matches() 方法,进行严格匹配
注意事项:
1)符号两侧是不能交[……]

READ MORE

「NETWORKING」- 防火墙 | FIREWALL-APPLIANCE | 硬件 | 软件

安全无处不在。路由器和交换机构建了互联互通的网络,带来便利的同时也带来了安全隐患。例如,在网络边界,企业有了如下安全诉求:外部网络安全隔离、内部网络安全管控、内容安全过滤、入侵防御、防病毒。保障数据的安全性是继保障数据的可用性之后最为重要的一项工作。
认识
“防火墙”一词起源于建筑领域,用来隔离火灾,阻止火势从一个区域蔓延到另一个区域。引入到通信领域,防火墙这一具体设备通常用于两个网络之间有针对性的、逻辑意义上的隔离。这种隔离是选择性的,隔离“火”的蔓延,而又保证“人”可以穿墙而过。这里的“火”是指网络中的各种攻击,而“人”是指正常的通信报文;
防火墙作为公网与内网之间的保护屏障,在保障数据的安全性方面起着至关重要的作用;
防火墙的主要功能都是依据策略对穿越防火墙自身的流量进行过滤,但有软件或硬件之分,我们这里主要讨论软件防火墙;
组成
防火墙策略 | 可以基于流量的源目地址、端口号、协议、应用等信息来定制,然后防火墙使用预先定制的策略规则监控出入的流量,若流量与某一条策略规则相匹配,则执行相应的处理,反之则丢弃。这样一来,就能够保证仅有合法的流量在企业内网和外部公网之间流动了;
构造
软件防火墙
在操作系统中,通常包含软件防火墙,例如 iptable、firewalld 等等;
硬件防火墙
在通信领域中,防火墙是一种安全设备。它用于保护一个网络区域免受来自另一个网络区域的攻击和入侵,通常被应用于网络边界,例如企业互联网出口、企业内部业务边界、数据中心边界等;

性质
WIP
应用
针对软件防火墙
1)在操作系统中使用,提供操作系统的网络安全;
针对硬件防火墙

在工作中,我们接触最多的应用场景是 企业边界防护;
改进
防火墙可以替代路由器吗?
DeepSeek / 防火墙可以替代路由器吗
部分场景可以替代:

小型网络/家庭网络:现代集成设备(如家用“无线路由器”)通常合并了NAT、简易防火墙和路由功能。
企业边缘网络:下一代防火墙(NGFW)可能支持静态路由/BGP,可直接连接ISP,替代简单路由器。

部分情况不可替代:

复杂路由需求:如多ISP负载均衡、动态路由协议(BGP)、MPLS等。
高性能转发:路由器专为高速数据包转发优化,防火墙深度检测会引入延迟。
网络分层设计:大型企业需分层部署(核心路由器→防火墙→内部交换机),各司其职。

简而言之,取决于具体需求。如果能够满足需求,则可以替代。如果无法满足,可不可替代。
参考
Wikipedia/Firewall
Wikipedia/iptables:https://en.wikipedia.org/wiki/Iptables
iptables 主页:http://www.netfilter.o[……]

READ MORE

「LAPTOP」- 改进工作的推进:pfSense and OpenMediaVault

我们确实对整个模型进行改进

1)替换 Host 系统为 Linux 发行版
Ubuntu 20.04 LTS + VirtualBox 6.1.32
2)引入存储(OpenMediaVault)
使用 OpenMediaVault 作为存储,目前主要是将其作为网络文件系统来使用:(1)在多个 Guest 间通过网络分享文件和数据;(2)将数据从 Linux Guest 脱离出来,数据备份工作转移到存储服务层面;
3)替换 OpenWrt 组件(OPNSense)
我们引入 pfSense 防火墙,以利用其中的 FRR 模块与 L2TP 模块;
# 02/12/2022 pfSense
关于 OPNSense 与 pfSense 对比:
1)Which Operating System should I have on my router? Is pfSense better than OPNSense?
2)pfSense® vs OPNSense – which firewall OS is better?
我们开始尝试使用 pfSense 系统,原因是我们需要功能更加丰富的企业路由系统,能够完成企业组网:
1)OpenWrt 功能过于简单,需要安装很多扩展,且不适用于企业级场景;
2)OPNSense 不支持 L2TP VPN 技术;
后续的改进工作
使用 VMware Workstation 虚拟化技术,原因在于 VirtualBox 提供的共享剪贴板经常失效,无法在虚拟机之间实现文本的复制粘贴;
替换桌面环境为 LXDE 或 LXQT 以减少资源占用,同时在状态栏中显示 CPU MEM NET DSK 等等资源的使用情况(Ubuntu 22.04 LTS 新版桌面仅能显示文字,而无法再显示图形化的资源使用情况,即我们使用的 GNOME Shell Extenstions / System Monitor 无法像以前一样);[……]

READ MORE

「Groovy」- CPS

# CPS – Continuation Passing Style
Continuation Passing Style (CPS) is a style of programming in which the remainder of the program is passed explicitly as a parameter, as opposed to that being handled implicitly represented as call stack.
参考文献
What’s meaning of CPS in jenkins. what’s the full name of CPS?Basics of Continuation Passing Style[……]

READ MORE

「EYE」- 视力保护、护眼行动 | EYE-PRODUCTION | Eye Production | Eyesight Decline and Protection

WIP 学习关于眼睛的知识

方案
以下是一些保护眼睛的方法:
佩戴合适的眼镜
如果发现视力下降,应及时佩戴合适的眼镜或进行治疗。
一、保持良好的用眼习惯
1)控制用眼时间。避免长时间连续用眼,定时休息眼睛。

或,使用电脑或手机等电子设备时,每 30-40min 就应该停下来,向远处眺望几分钟,让眼睛得到放松。

或,闭目养神片刻,或者进行一些简单的眼部按摩,如轻轻揉按眼周穴位,缓解眼睛疲劳。
2)保持正确的用眼姿势

读书、写字、使用电子设备时,要保持正确的姿势。眼睛与书本、屏幕的距离应适中,通常,眼睛距离书本应保持 30cm 左右,距离电脑屏幕应保持 50cm 以上。

坐姿要端正,不要弯腰驼背或趴在桌子上。

要注意光线的亮度和角度,避免在过暗或过亮的环境下用眼。

3)多眨眼

正常情况下,人每分钟会眨眼 15 到 20 次,但在专注于某些事情时,眨眼次数会减少,这会导致眼睛干涩。因此,要提醒自己多眨眼,保持眼睛的湿润。

二、注意用眼环境
1)合适的光线
– 用眼环境的光线要适宜,既不能太暗也不能太亮。过暗的环境会使眼睛看东西吃力,容易导致眼睛疲劳和近视;过亮的环境则会刺激眼睛,对眼睛造成伤害。
– 例如,在阅读时,可以选择光线柔和的台灯,避免灯光直射眼睛。在使用电子设备时,可以调整屏幕亮度,使其与周围环境的亮度相适应。
2)保持空气湿润
– 干燥的空气会使眼睛干涩,尤其是在长时间使用空调或暖气的环境中。可以使用加湿器增加空气湿度,缓解眼睛干涩。
– 也可以在身边放置一杯水,或者经常用清水洗脸,增加眼睛周围的湿度。
三、合理饮食
1)多吃富含维生素的食物,维生素对眼睛的健康非常重要。

维生素 A 可以预防眼睛干涩和夜盲症,富含维生素 A 的食物有胡萝卜、菠菜、南瓜等;

维生素 C 可以增强眼睛的抵抗力,预防眼部疾病,富含维生素 C 的食物有柑橘、草莓、猕猴桃等。

维生素 E、B 族维生素等也对眼睛有好处,可以通过多吃坚果、豆类、全麦食品等食物来补充。

2)摄入富含叶黄素和玉米黄素的食物

叶黄素和玉米黄素是视网膜黄斑区域的主要色素,可以过滤蓝光,保护眼睛免受紫外线和自由基的伤害。富含叶黄素和玉米黄素的食物有绿色蔬菜、玉米、蛋黄等。

3)控制糖分摄入

过多的糖分摄入会影响眼睛的健康,增加近视的风险。因此,要控制甜食和饮料的摄入,保持饮食的均衡。

四、适当运动和休息
1)户外活动
– 户外活动可以让眼睛接触自然光线,促进视网膜分泌多巴胺,抑制眼轴的增长,从而预防近视。每天保证至少 2 小时的户外活动时间,对眼睛的健康非常有益。
-[……]

READ MORE

「INGRESS-NGINX-CONTROLLER」- 常见问题处理

简单 Ingress Controller 管理

# 查看生成的配置文件
kubectl exec -it -n “ingress-nginx” nginx-ingress-controller-67956bf89d-fv58j cat /etc/nginx/nginx.conf

# 查看当前 Nginx 版本
kubectl exec -it $POD_NAME -n $POD_NAMESPACE — /nginx-ingress-controller –version

[Sol.] Nginx Ingress Controller 是否会自动加载 TLS 证书?
Cert Manager 负责 Certificate 的续期,在续期成功后,Certificate 关联的 Secret 也将被更新;
我们的疑问是 Nginx Ingress 是否会自动加载新的 Secret 以使 TLS 更新,还需需要手动 reload 配置?
我们猜测 Nginx Ingress Controller 能够自动加载新的 Secret 内容,原因是:如果 Cert Manager 更新完 Secret,还需要 Reload Ingress 的话,那么 Cert Manager 需要适配各种 Ingress Controller 实现,来完成 reload 动作。如果不是这样的话,那么 Kubernetes 就要提供一种机制,让来通知 Ingress Controller 需要 reload 配置;
然后,根据 https://github.com/cert-manager/cert-manager/issues/1816#issuecomment-506509695 的只言片语,我们更加认为 Ingress Controller 应该自动检测 Secret 的变化;
[Sol.] NGINX master process died (-1): signal: illegal instruction (core dumped)
process exit with code 132 #390.25.0 crashes at backend reload maybe due to recent OpenResty changes #4311
问题描述
环境概述

CentOS Linux release 7.4.1708 (Core)
Kubernetes v1.12.1
Docker version 18.06.1-ce, build e68fc7a
Helm v3.0.0-beta.3

在集群中部署 Nginx Ingress Controller 组件,但是在某两个节点(node3、node4)中 ngin[……]

READ MORE

「nil」- 问题修复及改进:LXQT + VMware Workstation

使用 VMware Workstation 虚拟化技术,共享剪贴板问题得以解决,现在能够在虚拟机之间实现文本的复制粘贴;
使用 LXQT 桌面环境,Host 资源占用得以降低,同时能够通过 Widgets 来显示系统资源的使用情况,进而解决 Ubuntu 22.04 仅能显示文本的问题;
后续的改进工作
暂无需要改进的工作或增加的技术方案;
LXQT 锁屏并恢复之后,会提示 Screen Saver Error Failed to run “xdg-screensaver lock”. Ensure … 错误,暂未解决;[……]

READ MORE

「HOMELAB」- 功能 | 特性

Synology DSM https://172.31.253.202:5001/
GitLab | https://vcs.platform.d3rm.org
GitHub
Gitee
Jenkins | https://ci.devops.d3rm.org
Container Registry

Alibaba Cloud CR
Docker Hub
Registry Mirror

https://lizj4175.mirror.aliyuncs.com
DNS and Domain Name

Router 53
Alibaba Cloud DNS[……]

READ MORE

「HOMELAB/DC-LAPTOP」- 可移动数据中心的构想与实现

问题描述
现在,在我们的工作环境中,以笔记本为办公平台,在其上完成例如编码、远程、文档处理等等工作。对于其他数据资源,则保存在远程文件托管服务(例如 NAS 或云盘服务等等)中,通过网络进行远程访问及数据备份;
但是,该方案的最大问题是我们无法保证网络总是可用或高速,在某些特殊工作环境中,或无法访问网络,或网络速度受限,或网络质量不稳定,导致我们无法访问远程文件托管服务中的资源;
所以,我们尝试将经常访问的数据资源本地化,即将常用访问的数据直接保存在笔记本电脑上,并在其上运行备份服务以将我们的数据备份到远程文件托管服务。鉴于此,即使网络资源成为瓶颈,也不会影响我们对数据资源的访问,而远程文件托管服务则作为 极低频访问资源的存储 及 笔记本数据备份的后端存储 而存在;
但是,随着办公平台的扩大,我们平时不得不以 Linux 系统为主要办公环境,但是有的时候会用到 Windows 系统,尤其是需要运行仅支持 Windows 平台的软件(例如企业微信、钉钉、微信等等)。我们尝试更换 Macbook,但并不能解决问题;两个笔记本,携带也不方便;通过 Wine 方案,仅能解决部分软件的运行问题,仍旧存在部分软件无法通过 Wine 来运行;
所以,我们尝试在虚拟机中运行操作系统,将我们的办公环境迁移到虚拟机。我们在宿主机中运行 Linux 操作系统,并在其中部署桌面虚拟化(例如 VirtualBox 等等),并在虚拟机中运行 Windows 操作系统。同时,借助虚拟机的 Guest Additions 组件,实现宿主机与虚拟机之间互操作(例如文件共享、复制粘贴等等)
但是,很多时候两个操作系统(Windows/Linux)都要使用相同的服务。例如:或为了提供网络质量,两个操作系统都需要使用网络加速服务;或为了访问办公网络,两个操作系统都要接入企业 VPN 服务;
所以,我们开始思考,既然虚拟机的流量是通过 NAT 进行网络访问,那能不能在虚拟化中运行路由器操作系统,然后所有的虚拟机操作系统将数据包发往路由器操作系统,而路由器操作系统的其他接口负责将数据包发送到外部网络。这样的网络模型就更加贴近于现实环境的终端网络,事情也变得越来越疯狂……(2018-12-13)
关键词:可移动数据中心、边缘数据中心、便携式数据中心、虚拟数据中心
解决方案
# 12/13/2018 根据我们的想法进行描绘,整个系统原型类似如下:

+————————————————-+
| OpenWrt | Windows VM | Linux VM | … |
+————————————————-+
| LINUX +[……]

READ MORE

「HOMELAB」- 软路由 | Software Router

该部分将记录:我们已知的路由器系统对比,及相关问题的解决办法(侧重于功能特性本身);
我们需要选择路由器操作系统,通过软件的方式来实现我们的边缘数据中心的网关设备;
针对特定路由器操作系统,根据需求,我们将关注:

底层系统:该路由器操作系统所基于的现有操作系统,是否能够虚拟化环境内运行;
应用规模:是否能够支持大规模的企业级应用场景,作为企业路由网关运行;
功能特性:具备丰富的网络功能 ⇒ 除了基本路由功能,还要支持企业级组网技术;
协议许可:开源、免费,能够在商业环境中使用(非 GPL 许可);[……]

READ MORE

「NGINX-INGRESS-CONTROLLER」- 部署(针对无负载均衡的场景)

问题描述
仅当在 Kubernetes Cluster 中部署 Ingress Controller 之后,我们定义的 Ingress 资源才能生效。当然 Ingress Controller 有很多实现,比如 NGINX Ingress Controller、Traefik Ingress Controller、HAProxy Ingress 等等(参考 Ingress Controllers | Kubernetes 页面);
针对我们的场景,我们使用 NGINX Ingress Controller 实现,这完全是基于我们具有很多 Nginx 使用经验,此外 Nginx 完全能满足我们的需要。即使日后 NGINX Ingress Controller 无法满足需求,我们亦可安装其他 Ingress Controller 实现,它们之间能够并存;
该笔记将记录:在 Kubernetes Cluster 中,如何部署 NGINX Ingress Controller 组件,以及相关问题处理;
解决方案
我们参照官方 Installation Guide 文档,并结合我们自身需求,我们整理出此文,所以该笔记是环境相关的,并不一定适合每种环境;
我们强烈建议参照官方文档,并结合自己的环境进行部署;
# 07/02/2022 该笔记是我们早期(12/09/2019)学习时的部署笔记,这里面里面存在许多不成熟的做法(比如 LoadBalancer 部分)。现在我们已经在集群中部署 MetalLB 组件,完全能够通过 LoadBalancer Service 来暴露 Nginx 服务,而不再需要使用 HostNetwork 这种做法。但是我们依旧保留该笔记,以用于日后可能会出现的某些特殊场景;
第一步、下载并且部署
我们为 Kubernetes v1.18.9 on Bare-metal 环境(自建 Kubernetes 集群);
如果是在 minikube、AWS、Azure 中部署,需要执行不同的命令,参考 Installation Guide 文档;
v1.4.0 ⇒ 1.25, 1.24, 1.23, 1.22
Helm Chart: 4.3.0
Manifest: https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.4.0/deploy/static/provider/cloud/deploy.yaml
官方提供 deploy.yaml 部署文件:

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/dep[……]

READ MORE

「Java」- 将对象写入文件,并从文件中读取

问题描述
在使用 Selenium 时,我们需要保存 Cookie 信息,以便于下次自动化测试时能够恢复(为了保存登录状态);
解决办法
我们可以将 Cookie 对象保存到文件中,然后下次自动化测试时再从文件中读取该对象;
为了表述问题,我们仅仅记录对象的保存和读取方法,而不会涉及 Selenium 细节;
将对象写入文件

Foo fooObject = new Foo()
new ObjectOutputStream(new FileOutputStream(“/tmp/foo.bin”)).writeObject(fooObject)

对文件读取对象

Foo fooObject = (Foo) new ObjectInputStream(new FileInputStream(“/tmp/foo.bin”)).readObject()

注意事项
在 Groovy 中,该方法并不适用,会产生 java.lang.ClassNotFoundException: com.k4nz.example.Foo 异常。解决方法参考 Groovy/Write an Object to File and Read it 笔记;
参考文献
How to Write an Object to File in JavaJava IO: ObjectInputStream[……]

READ MORE

「NGINX-INGRESS-CONTROLLER」- 通过 HELM 部署

为了能够很好的进行配置管理,我们现在已经开始使用 HELM 来完成应用的部署。这里我们将使用 HELM 来部署 Ingress Nginx Controller 组件。该笔记将记录:在 Kubernetes Cluster 中,通过 HELM 部署 Ingress Nginx Controller 的方法,以及相关问题的解决办法。
NGINX Ingress Controller/Installation Guide
版本选择
Supported Versions table | https://github.com/kubernetes/ingress-nginx?tab=readme-ov-file#supported-versions-table
部署方式
https://kubernetes.github.io/ingress-nginx/deploy/

Manifest
Helm Chart[……]

READ MORE

「Sphinx」- 全文搜索引擎

Sphinx and Coreseek
Sphinx
Sphinx 是一种开源的全文搜索引擎,被广泛应用于网站、应用程序、文档、邮件等的搜索和索引功能。Sphinx 支持多种语言,包括 PHP、Python、Java、Ruby 等,具有高效、快速和可扩展性等优点;
Sphinx 的工作原理是基于索引的全文搜索,它把文本数据转换成索引形式,然后根据用户的查询条件搜索出匹配的结果。Sphinx 支持多种查询模式,包括全文查询、布尔查询、短语查询、通配符查询等;
Sphinx 还具有一些高级功能,例如支持实时索引、分布式搜索、自定义分词器、自定义排序规则等。此外,Sphinx 还提供了强大的 API 和 Web 界面,方便用户进行索引管理和搜索结果分析;
总之,Sphinx 是一款强大的全文搜索引擎,能够满足各种搜索需求,并且具有高效、快速、可扩展性等优点,适用于各种规模的应用;
Coreseek
主页:http://www.coreseek.cn 已经关闭
coreseek 是一款基于 sphinx 开源的搜索引擎,专门为用户提供免费的中文全文检索系统,coreseek 被称为带有中文分词的 sphinx,与 sphinx 不同的是 coreseek 增加了一个带有中文分司的词库
目前 coreseek 的官网已经不能访问,且该开源项目已不再维护,但这并不妨碍我们使用 coreseek 进行全文搜索,中文分词
Open Source Search Server v2.1.1-release
Homepage: http://sphinxsearch.com/
Book: http://shop.oreilly.com/product/9780596809539.do%EF%BC%9B 介绍 Sphinx;
Download Page: http://sphinxsearch.com/downloads/release/
Download Link: http://sphinxsearch.com/files/sphinx-2.2.11-release.tar.gz
Manual: http://sphinxsearch.com/docs/latest/index.html%EF%BC%9B 源码目录下的 doc/sphinx.html 是当前版本的文档;
Installation: http://sphinxsearch.com/docs/latest/installation.html
编译后产生的二进制文件:

indexer: “全文索引“生成工具;

searchd: 后台服务,负责执行对”全文索引“的搜索;

spelldump: 命令行工具,使用 ispell 或 MyS[……]

READ MORE

「GITLAB/CICD」- Runner,安装,升级

问题描述
GitLab CI/CD 已经集成到 GitLab 服务中。除此之外,我们还需要安装 GitLab Runner 服务;
解决方案
参考 Install GitLab Runner | GitLab 页面
通过 APT / RPM 部署(推荐)
Install GitLab Runner manually on GNU/Linux | GitLabInstall GitLab Runner using the official GitLab repositories | GitLab
建议参考官方文档,这里仅作记录:

# ——————————————————— # 方法一、手动安装:每次下载 .deb 文件并安装

wget https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_amd64.deb
dpkg -i gitlab-runner_amd64.deb

# ——————————————————— # 方法二、仓库安装:添加仓库,并进行安装;

# for Ubuntu

curl -L “https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh” | sudo bash
apt-cache madison gitlab-runner
apt-get install gitlab-runner=16.4.0

通过 Docker Compose 部署
Run GitLab Runner in a container | GitLab

version: ‘3’

services:
gitlab-runner:
image: gitlab/gitlab-runner:alpine-v12.6.0
restart: always
volumes:
– ./config/${HOSTNAME}/:/etc/gitlab-runner/
– ./config/ssh-key/:/ssh-key/
– /var/run/docker.sock:/var/run/docker.sock
– /etc/localtime:/etc/localtime

1)./config/${HOSTNAME}:鉴于该文件需要在很多主机中复用,所以才将主机名作为配置目录名;
2)./config/ssh-key[……]

READ MORE

「LAPTOP」- 新的使用需求

针对笔记本,我们提出新的使用需求,例如 运行 SolidWorks 软件、通过手写板记录笔记、使笔记本具有多个屏幕 等等;
而现有的笔记本方案(可移动数据中心),仅能运行多个操作系统,而无法发挥笔记本本身的硬件特性(例如 显卡、指纹 等等);
并且,我们依旧是将 Linux 作为主要生产操作系统,其他操作系统较少使用(针对我们常用办公软件,其多具备 Linux 版本);
综上,针对可移动数据中心的方案,其已经无法满足我们的使用需求,我们需要根据自己的工作场景,重新设置笔记本;[……]

READ MORE

「Groovy」- 处理日期时间

该笔记将记录:在 Apache Groovy 中,与时间有关的常用操作。
Patterns for Formatting and Parsinghttps://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#patterns
Predefined Formattershttps://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#predefined
常用转义字符

println new Date().format(“yyyy-MM-dd’T’HH:mm:ssZ”)
println new Date().format(“yyyy-MM-dd’T’HH:mm:ssXXX”)

// 通过 ” 针对字符转义

Timestamp to Date String
soapui – Convert milliseconds to yyyy-MM-dd date-time format in Groovy – Stack Overflow

def timestamp = Long.valueOf(“1726244425”)
print new Date( timestamp * 1000 ).format(“yyyyMMdd.HHmmss.SSS”)

String => Date(“万能方法”)
很多时候,我们使用的日期格式比较随意,因此需要告诉 Parser 我们的日期格式:

def input = ‘2021-03-23T19:46:22+08:00’
def pattern = “yyyy-MM-dd’T’HH:mm:ssX”
def date = Date.parse(pattern, input)
assert date.toString() == ‘Tue Mar 23 19:46:22 CST 2021’

// T:因为这里 T 是普通字符,所以需要使用 ‘ 进行转义处理
// X:ISO 8601 time zone,参考 Java 7 / java.text.SimpleDateFormat 文档。

将时间增加若干长度(e.g. currentDate + 5 seconds)

import groovy.time.TimeCategory

currentDate = new Date()
use( TimeCategory ) {
after30Mins = currentDate + 5.seconds
}

判断 | 时间是否在某范围内

public[……]

READ MORE

「APACHE-GROOVY」- 常见问题处理

[Sol.] Unable to load extension class
apache – Groovy – groovy-datetime module – Stack Overflow
在执行 Groovy 脚本时,每次都会产生如下错误:

# groovy –version
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on
Feb 12, 2021 2:35:37 PM org.codehaus.groovy.runtime.m12n.MetaInfExtensionModule newModule
WARNING: Module [groovy-datetime] – Unable to load extension class [org.apache.groovy.datetime.extensions.DateTimeExtensions]
Feb 12, 2021 2:35:37 PM org.codehaus.groovy.runtime.m12n.MetaInfExtensionModule newModule
WARNING: Module [groovy-datetime] – Unable to load extension class [org.apache.groovy.datetime.extensions.DateTimeStaticExtensions]
Groovy Version: 2.5.7 JVM: 1.7.0_79 Vendor: Oracle Corporation OS: Linux

因为 JDK 版本较旧,没有该方法,所以导致出现上述错误;
将 JDK 版本更新到 8 即可解决该问题:

# groovy -version
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on
Groovy Version: 2.5.7 JVM: 1.8.0_73 Vendor: Oracle Corporation OS: Linux[……]

READ MORE

「Groovy」- 常用文件操作

基本操作(增删改查)
增(创建文件)
How to create text file using Groovy? – Stack Overflow

def newFile = new File(“/path/to/file”)
newFile.createNewFile() // 此时,将创建空文件,如果文件存在,则返回 false 值

def newFile = new File(“/path/to/file”)
newFile.text = “xxxxx” // 此时,将创建文件,并写入内容

删(移除文件)
Delete a file with groovy

def file = new File(“/path/to/file”)
file.delete() // 删除文件

改(修改文件)

File file = new File(“out.txt”)

file.write “First line\n”
file << “Second line\n”
file.append(“hello\n”)

println file.text

查 | 获取内容,检查文件是否存在、可读、……
Groovy: reading and writing files – appending contentHow to read a file in Groovy into a string? – Stack Overflow

File file = new File(“out.txt”)

// 获取文件全部内容
println file.getText(‘UTF-8’)
println file.text

// 判断文件的某些属性
println file.exists()
println file.canRead()
println file.isDirectory()

// 获得文件的输入流(读取)
def inputStream = file.newInputStream()

路径操作

// 获取绝对路径
file.getAbsolutePath()

// 获取父级路径
file.getParent() // => return a String
file.getParentFile() // => return a File object

以行为单位,遍历文件内容

File file = new File(“/path/to/file”)

// 第一种方法
def lines = file.readLines() // String[]
for (line in lines) {
// …
}

// 第二种方法
file.[……]

READ MORE

「Rack, Shelf, PDU, …」- 机柜及相关配件

Rack, Shelf, PDU, …
网络机柜(Rack)
https://item.taobao.com/item.htm?id=44838446538
尺寸:60 x 60 x 160cm
颜色:黑色 VL(立柱 1.4 其余 0.8)
层板托盘(Shelf)
https://item.taobao.com/item.htm?id=37998439619
颜色:VL 600*600 机柜专用(475*300)
尺寸:0x0x0cm
光纤配线架
ODF(optical distribution frame,光纤配线架):光纤配线架(柜)主要应用于骨干网、城域网及接入光纤光缆网络,具有主干光缆的连接、成端、分配、分光和调度功能。
参考文献
19-inch rack – Wikipedia原来16A和10A的插座区别这么大,千万不要装错!电源插座16A和10A如何区分?[……]

READ MORE

「KUBERNETES-OBJECTS」- Service | 服务 | Exposing Applications | 学习笔记

认识
Pod 会被创建,并且还会消失,这由 ReplicaSets 控制。每个 Pod 都有自己的 IP 地址,但是这些 IP 地址不能视为可靠的。那么如果前端的一部分 Pod 依赖于后端的 Pod,那前端的这些 Pod 如何找出并追踪后端的 Pod?
组成
Service,服务,用于暴露 Pod 以供访问;
Service 是一个抽象,定义 Pod 的逻辑集合以及谁可以访问它们的策略(有时称为微服务)。Service 指向的 Pod 集由 Label Selector 确定(由写 Service 也没有选择器);
一个场景,后端运行某个镜像的三个副本,前端并不关心访问哪个副本。后端的 Pod 副本可能会变化,但是前端不应该去关心或者追踪后端的变化。Service 的抽象提供了这种解耦;
补充说明:对于 Kubernetes 本机应用程序,Kubernetes 提供了一个简单的 Endpoints API,只要服务中的 Pod 集发生变化,它就会更新。对于非本机应用程序,Kubernetes 提供基于虚拟 IP 的服务桥接,重定向到后端 Pod
性质
Huawei Cloud / 网络概述_云容器引擎 CCE_用户指南_Standard和Turbo集群用户指南_网络
定义服务(Defining a Service)
Service 也是一个 REST 对象,像 Pod 一样。将定义提交给 apiserver 来创建对象;
假设有个 Pod 暴露 9376 端口,并且标签为 app: MyApp,到该 Pod 集的 Service 可以这么定义:

# foo.yaml
# 定义一个服务
kind: Service
apiVersion: v1
metadata:
# 服务名
name: my-service
spec:
selector:
# 流量发往标签为「app: MyApp」的 Pod 上
app: MyApp
ports:
– protocol: TCP
port: 80
# 流量发往 Pod 的这个端口上;
targetPort: 9376

??? Service 会被分配一个 IP 地址(有时称为 Cluster IP),被服务代理使用。将连续评估 Service 的选择器,并将结果发布到名为“my-service”的 Endpoints 对象;
注意事项,Service 可以映射一个入口 port 到任何 targetPort。默认 port 和 targetPort 是相同的;
targetPort 也可以是一个字符串,指向后端 Pod 的端口名(由 containers.ports.name 定义),分配到该字符串的端口号可以在每个 Pod[……]

READ MORE

「GROOVY」- 函数与方法

函数 | Function
定义函数
Groovy – Methods

def methodName() {
//Method code
}

def methodName(parameter1, parameter2, parameter3) {
// Method code goes here
}

def someMethod(parameter1, parameter2 = 0, parameter3 = 0) {
// Method code goes here
}[……]

READ MORE

「USB-MEMSTICK」- USB 闪存驱动器 | USB Flash Drive | 1999

认识
优盘(U 盘 /USB 闪存盘)是一种便携式存储设备,采用闪存(Flash Memory)技术,通过USB 接口与电脑、手机(需 OTG 支持)等设备连接,实现数据存储和传输。
U 盘(最普遍、最常用的称呼)、闪存盘(强调其存储技术,正式名称)、优盘(音译自 “USB”,部分品牌推广的名称)、USB 驱动器(直译,较少用)、随身碟(台湾地区常用)、拇指盘(因其小巧,类似拇指大小),中国大陆:普遍叫 “U 盘”(如:“请把文件拷到 U 盘里。”),台湾地区:多用 “随身碟”(如:“資料存到隨身碟。”),正式 / 技术文档:可能用 “闪存盘” 或 “USB 闪存驱动器(USB Flash Drive)”。
组成
硬件

优盘虽然体积小,但内部结构精密,主要由以下几个核心部件组成:
闪存芯片(Flash Memory Chip)
– 作用:存储数据的核心部件,采用 NAND Flash 技术(非易失性存储,断电后数据不丢失)。
– 类型:
– SLC(单层单元):寿命长、速度快,但成本高(多用于工业级)。
– MLC(多层单元):平衡速度与寿命(中高端 U 盘)。
– TLC(三层单元):成本低,但寿命较短(主流消费级)。
– QLC(四层单元):容量大,但速度和耐用性较低。
主控芯片(Controller Chip)
– 作用:相当于 U 盘的“大脑”,负责管理:
– 数据读写
– 错误校正(ECC)
– 坏块管理
– 加密(部分高端 U 盘支持硬件加密)
– 常见品牌:群联(Phison)、慧荣(SMI)、擎泰(Skymedi)等。
USB 接口(USB Connector)
– 类型:
– USB-A(标准接口,兼容大多数电脑)。
– Type-C(正反插,适用于新设备)。
– 双接口(如 A+C,兼容手机和电脑)。
– 传输协议:USB 2.0 / 3.0 / 3.1 / 3.2(速度差异显著)。
PCB 电路板(Printed Circuit Board)
– 作用:连接闪存芯片、主控芯片和 USB 接口,提供电气通路。
– 材质:通常为玻璃纤维基板,部分高端 U 盘采用更耐用的设计。
外壳(Enclosure)
– 材质:塑料、金属或橡胶,影响散热和耐用性。
– 设计:
– 普通 U 盘:轻便简约。
– 防水 / 防震 U 盘:加固结构(如硅胶包裹、金属外壳)。
软件
固件(Firmware):存储在主控芯片中的低级程序,控制 U 盘操作。
– 影响兼容性、速度和稳定性。
– 部分品牌提供固件升级(修复 BUG 或提升性能)。
原理
插入电脑:USB 接口供电(5V),主控芯片初始化。[……]

READ MORE

「SEGMENT-ROUTING」- SRGB(Segment Routing Global Block)

SRGB(Segment Routing Global Block):用户指定的为 Segment Routing MPLS 预留的全局标签集合;
Q:为什么需要 SRGB?
A:SR 要求前缀 SID 全局有效。但是,在 MPLS 中设备的一部分标签空间可能被其他协议(例如 LDP,网络是不断演化的,在 SR 出现前,部分标签已经被占用,需要兼顾历史问题)占用,因此需指定明确的空间用于 SR 全局标签;
通过扩展的路由协议

每台设备通告自己的 SRGB 给域内的路由器;
节点通告 Prefix SID Index(前缀 SID 索引)后,各台设备分别根据 SRGB 来计算入站及出站 SID 值;

在实际部署中,建议设备采用统一的 SRGB,这个路径上的各个节点将记录得到相同的 SID,以便于管理。[……]

READ MORE