Keep learning, keep living...

0%

ctrcrictl都是Kubernetes环境中管理容器的命令行工具。但它们的目的和使用方法有所不同。

crictl是基于KubernetesCRI: Container Runtime Interface接口规范来管理容器, ctr是containerd自带的容器管理工具, 本身和Kubernetes无关。

Kubernetes使用crictl来管理任意兼容CRI接口的容器运行时。

containerd相比于docker,增加了namespace的概念,每个imagecontainer都在各自的namespace下可见。目前kubernetes使用k8s.io作为namespace名称。

阅读全文 »

LSM: Linux Security Modules是内核中对象访问控制机制。最早的基于访问主体(subject)的身份或者所属组(User,Group,Other)的访问控制机制被称为DAC: Discretionary Access Control, 在许多安全性要求较高的场景下不能适用。于是Linux内核中实现了MAC: Mandatory Access Control机制,来表达访问主体(Subject)是否有权限对访问客体(Object)进行相应操作(Operation), 这个实现就是LSM框架。

在具体实现上,内核会在相应对象访问前进行相应操作的检测,以系统调用为例来看, 如图:

来自链接

阅读全文 »

计算机加电后,首先会执行刷在ROM/NVRAM中的系统固件代码。系统固件(BIOS/UEFI)完成自身的一系列工作(如硬件自检(POST: Power-On Self-Test)后,需要引导操作系统启动。固件可以从NVRAM中读取启动设备列表,按设备顺序尝试进行引导。

阅读全文 »

之前的文章<<CentOS7配置Console GUI/TUI程序>>介绍了在CentOS7Console界面上配置GUI/TUI可视化程序的几种方法。尽管这些GUI程序可以简化系统的配置难度,但对于界面要求复杂的专用场景较不是很适用,比如需要支持鼠标操作等。但安装完整的一套桌面环境,对服务器的资源占用又较大,这种场景下,可以只安装X Windowopenbox来支撑运行完整图形界面程序。

X Window被设计为Client/Server架构。Server负责图形设备和外部设备的处理来显示画图和处理外设操作,而图形界面程序作为Client只是通知Server进行相应的操作,如画线,显示字符等等。ClientServer之间不要求位于同一台计算机,它们之间可以通过网络进行协议传输。ClientServer的角色和我们日常网络访问所说的ClientServer相比。一般我们日常通过SSH登录服务器,我们所看到界面和操作外设的一端做为客户端,我们所使用的应用位于服务端。而在X Window体系下。我们看到界面和操作外设的一端是X Server, 而图形界面程序运行的一端是X Client

对于任一X Client来说,它并不知晓其他X Client的存在,对于他们在同一X Server上如何排放,需要另一个组件来完成,这就是窗口管理器, 它也是一个X Client,只是它负责的是其他X Client的管理, 示意图如下:

阅读全文 »

近期开发的C++程序遇到一个关于locale的问题。程序在通过SSH直接登录到root用户后,运行程序会崩溃,而通过其他用户SSH登录后,再切换到root用户后,程序则运行正常。

1
2
terminate called after throwing an instance of 'std::runtime_error'
what(): locale::facet::_S_create_c_locale name not valid

根据locale文档中的描述:

1
2
3
4
5
6
7
8
9
10
11
std::locale::locale(const char * __s)	[explicit]

Named locale constructor.

Constructs a copy of the named C library locale.

Parameters:
s Name of the locale to construct.

Exceptions:
std::runtime_error if s is null or an undefined locale.

可以得知,指定的locale不存在。

Google上查到一般解决方案是设置环境变量LC_ALL=C可以解决。

阅读全文 »

Docker默认的网络模式是bridge模式, 在宿主机上创建一个Linux bridge:docker0,并分配一个网段给该网桥使用。该模式下启动的容器,会分配一个该网段的IP, 并通过veth-pair接入网桥。为了能够从宿主机外部访问容器,需要在创建容器时指定-p参数,在宿主机上将某个宿主机的端口映射到容器的端口。
如:

1
docker run --rm  -itd -p 80:80 nginx

本文来简要分析一下从宿主机外访问bridge网络模式下docker容器的数据包路径。

整体的网络架构如图所示:

阅读全文 »

之前的两篇文章<<nf_ct_deliver_cached_events崩溃分析>><<nf_ct_deliver_cached_events崩溃修复或规避方案>>介绍了nf_conntrack模块中的一个BUG的原因和规避方案。触发BUG的原因在于NFQUEUE操作位于ipv4_conntrack_inipv4_confirm两个函数之间,于是本可以无中断执行完成的两个函数之间出现了CPU调度,导致大量conntrack entry冲突。各HOOK函数执行顺序如图:

阅读全文 »

最近遇到一个CentOS8环境上的内核崩溃问题,内核版本号为4.18.0-305.3.1.el8.x86_64,崩溃堆栈为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
crash> bt
PID: 2310003 TASK: ffff99f4ee683e80 CPU: 1 COMMAND: "Verdict2"
#0 [ffffb71241e375e8] machine_kexec at ffffffffbc66156e
#1 [ffffb71241e37640] __crash_kexec at ffffffffbc78f99d
#2 [ffffb71241e37708] crash_kexec at ffffffffbc79088d
#3 [ffffb71241e37720] oops_end at ffffffffbc62434d
#4 [ffffb71241e37740] no_context at ffffffffbc67262f
#5 [ffffb71241e37798] __bad_area_nosemaphore at ffffffffbc67298c
#6 [ffffb71241e377e0] do_page_fault at ffffffffbc673267
#7 [ffffb71241e37810] page_fault at ffffffffbd0010fe
[exception RIP: __pv_queued_spin_lock_slowpath+410]
RIP: ffffffffbc73cbda RSP: ffffb71241e378c0 RFLAGS: 00010282
RAX: 0000000000003ffe RBX: ffff99f4a6ffc624 RCX: 0000000000000001
RDX: 0000000000003fff RSI: 0000000000000000 RDI: 0000000000000000
RBP: ffff99f576e6ac00 R8: 0000000000000000 R9: ffff99f56428e200
R10: 0000000032950000 R11: 0000000000000002 R12: ffffffffbcaaa6d0
R13: ffff99f576e6ac14 R14: 0000000000000001 R15: 0000000000080000
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018
#8 [ffffb71241e378f8] queued_write_lock_slowpath at ffffffffbc73df3c
#9 [ffffb71241e37910] bpf_sk_reuseport_detach at ffffffffbc842ff9
#10 [ffffb71241e37928] reuseport_detach_sock at ffffffffbcdc2c25
#11 [ffffb71241e37940] sk_destruct at ffffffffbcd7ac33
#12 [ffffb71241e37950] nf_queue_entry_release_refs at ffffffffbce1c1e4
#13 [ffffb71241e37960] nf_reinject at ffffffffbce1c52e
#14 [ffffb71241e37998] nfqnl_recv_verdict at ffffffffc095a81f [nfnetlink_queue]
#15 [ffffb71241e37a10] nfnetlink_rcv_msg at ffffffffc09552be [nfnetlink]
#16 [ffffb71241e37b88] netlink_rcv_skb at ffffffffbce07a3c
#17 [ffffb71241e37bd8] nfnetlink_rcv at ffffffffc0955d08 [nfnetlink]
#18 [ffffb71241e37c18] netlink_unicast at ffffffffbce0725e
#19 [ffffb71241e37c58] netlink_sendmsg at ffffffffbce07524
#20 [ffffb71241e37cc8] sock_sendmsg at ffffffffbcd751fc
#21 [ffffb71241e37ce0] ____sys_sendmsg at ffffffffbcd7551b
#22 [ffffb71241e37d58] ___sys_sendmsg at ffffffffbcd76b9c
#23 [ffffb71241e37eb0] __sys_sendmsg at ffffffffbcd76c67
#24 [ffffb71241e37f38] do_syscall_64 at ffffffffbc60420b
#25 [ffffb71241e37f50] entry_SYSCALL_64_after_hwframe at ffffffffbd0000ad
阅读全文 »

之前的文章<<nf_ct_deliver_cached_events崩溃分析>>分析了nf_conntrack内核模块中存在的一个BUG。由于CentOS7一直没有修复该问题,甚至到当前最新的CentOS8 streamkernel-4.18.0-383.el8版本,这个问题依旧没有修复,这样就无法通过升级官方内核的方法来解决该问题了,只能我们自己来想办法进行修复或规避。

最直观的思路是修改代码后重新编译相关的内核模块进行替换。但在我们无法直接控制的环境中替换模块不是太理想,理想的方案还是能在我们的内核模块中进行修复或者规避。

类似于LivePatch的思路,可以直接HOOK存在BUG的函数:nf_conntrack_confirm, 重新实现正确的逻辑。但该函数是inline函数, 在内核中没有符号:

1
2
3
4
5
6
7
8
9
[root@k8smaster ~]# cat /proc/kallsyms |grep nf_conntrack_confirm
ffffffffc0664050 r __ksymtab___nf_conntrack_confirm [nf_conntrack]
ffffffffc0667b59 r __kstrtab___nf_conntrack_confirm [nf_conntrack]
ffffffffc06647b0 r __kcrctab___nf_conntrack_confirm [nf_conntrack]
ffffffffc06570e0 t __nf_conntrack_confirm [nf_conntrack]

[root@k8smaster ~]# cat /proc/kallsyms |grep ipv4_confirm
ffffffffb5e9b470 t ipv4_confirm_neigh
ffffffffc061c280 t ipv4_confirm [nf_conntrack_ipv4]
阅读全文 »

udev机制是Linux kernel的设备管理机制. 当内核检测到设备插拔后, 会发送事件给用户态的udevd进程. 用户态udevd进程根据事件信息匹配不同规则从而进行不同的处理逻辑.

CentOS7中使用的是systemd中实现的udevd进程. udev规则文件的扩展名为.rules, 主要位于两个目录:

  • /etc/udev/rules.d/: 自定义规则
  • /usr/lib/udev/rules.d/: 系统自带规则

udev规则是以规则文件名按字母顺序进行匹配处理的, 一般文件名中会带有数字前缀, 如:50-udev-default.rules. 处理顺序与规则放在哪个目录下无关, 但如果不同目录下规则文件同名, /etc/udev/rules.d下的文件会覆盖/usr/lib/udev/rules.d/下的文件.

阅读全文 »