永久配置
$ vim ~/.tmux.conf
+ set -g history-limit 5000
# 注:默认为2000行,这里设置为5000行
动态配置
$ tmux set-option history-limit 5000
$ tmux
运行时配置
$ tmux
<C-B> :set-option history-limit 5000
永久配置
$ vim ~/.tmux.conf
+ set -g history-limit 5000
# 注:默认为2000行,这里设置为5000行
动态配置
$ tmux set-option history-limit 5000
$ tmux
运行时配置
$ tmux
<C-B> :set-option history-limit 5000
用户在做电子调查报告或者填写一些资料表,会遇到一些word文档中有小方框【□】,需要在里面打钩【√】
方法一:将光标定位于需要打钩的地方,选择【插入】→【符号】→【其他符号】,在弹出的符号栏里,字体选择【Windings2】,然后便可以找到现成的打钩样式,点击插入,再关闭即可。
方法二:把光标定位于需要打钩的地方,输入大写字母R。选中字母R,鼠标右键,在菜单栏中选择”字体”, 在西文字体栏目中,将字体改为【Windings2】,点击下方确定按钮。(提示:如果要打叉,把R改成T即可)
方法三:将光标定位于要打钩的地方,输入2611。选中2611,同时按住键盘的Alt+X键。(提示:如果需要打叉,只要把2611改成2612即可)
个人比较喜欢方法三。
大致流程如下:
helm repo add harbor https://myharbor.mydomain.com/chartrepo/myproject --username myusername --password mypassword
helm plugin install https://github.com/chartmuseum/helm-push
helm repo add chartmuseum http://localhost:8080
helm cm-push mychart/ chartmuseum
该清单搜集人类创造的最先进最好用的开源 AIGC APP 方案,包括但不限于对话、识图、生图、TTS、知识库、多模态、工作流编排,主要搜集支持自托管,可容器化部署的方案。
欢迎补充。
目前探索较好的工作流,LobeChat 日常AI对话,数据云同步;ChatGPT Web Midjourney Proxy 用来文生图;n8n 构建复杂工作流。

49.2K (2024-12-20)
77.8K (2024-12-20)

19.1K (2024-12-20)

51.8K (2024-12-20)结合 uniapi 等服务,还挺好用。 References: https://t.me/FindBlog/553

5.6K (2024-12-20)
52.1K (2024-12-20):ollama 和 :cuda 标签镜像,带来无忧体验。# 命令轻松访问它们。SearXNG、Google PSE、Brave Search、serpstack、serper、Serply、DuckDuckGo、TavilySearch、SearchApi 和 Bing 等提供商进行网络搜索,并将结果直接注入聊天体验。# 命令将网站无缝集成到聊天体验中。此功能允许您将网页内容直接整合到对话中,增强互动的丰富度和深度。Github: https://github.com/langgenius/dify/
55.8K (2024-12-24)根技术是指那些能够催生和支撑一系列衍生技术的基础性技术,它们在科技发展中起着关键的作用。了解根技术的基本概念对于把握技术发展趋势和方向具有重要意义。
鉴于主流学术界以及政策制定部门至今还很少关注到根技术、根产业这样极为重要的问题,几乎还看不到有价值的研究成果,为便于对相关问题的阐述,本文对根技术、根产业做一些释义工作。
所谓根技术,是指能够衍生出并支撑着一个或多个技术簇的技术,可以为整个技术树成长的各个环节及末端持续赋能。根技术具有三大属性:一是技术全新性。主要来自颠覆性技术、突破性技术和新技术,是典型的“从0到1”的科研成果。这种全新属性,使其实现了对旧的根技术的全面颠覆或跨越,再造或重构了其所波及领域的底层技术逻辑,或者产生了新的技术范式,创立了新的底层技术逻辑。二是技术高分蘖性。一个根技术可以同时蘖生出一个乃至多个枝干技术,进而形成“独根成林”之生态,快速产生从技术创新到颠覆多个产业应用模式的爆发效果。三是技术多维应用性。一项根技术通常具有相当程度的泛在性,不仅对其自身领域具有颠覆性、突破性和新创性,且对相关产业领域技术产生重大影响,重塑相关领域技术格局,具有典型的指数效应。
根产业是根技术的产业化结果,是指依据根技术建立的产业链“根部”部分。根产业具有三个显著特征:一是共性架构性。根产业一般不生产面向市场终端的产品或服务,而是以根技术为核心搭建起一个新的产业基础或共性体系,包括技术实现、工艺流程、统一标准、商业模式等。根产业的这种属性,使其对整个产业链具有完全的掌控力,可以精准地“断枝”“去冗”。二是超强稳定性。根产业一旦形成,通常在其全生命周期都会保持相对稳定,由其衍生出的干产业、枝产业可能会不断更新,甚至淘汰,但根产业部分则持续生机勃勃,这就使根产业表现出“根部长青”的活力。三是多向赋能性。根产业是多个相关产业之根,同一根产业之上可以演化出多姿多彩的干、枝、杈、叶、花、果等,具有多向赋能性。
由于根技术与根产业的特殊属性,决定了基于根技术形成的根产业,不仅具有产业主导效应,还具有显著的产业回顾效应、产业旁侧效应和前向效应,在创造新产业的同时,对传统产业、相关产业、未来产业进行颠覆式创新。
因此,各个国家在国际技术、产业竞争中,表面上是创新链、产业链和价值链竞争,深层次则是根技术、根产业的竞争。哪个国家或经济体掌控的根技术、根产业数量越多,质量越高,就会在相关领域的竞争中占据绝对优势,甚至会形成“根霸权”。换言之,当今世界已经发展到“得根技术者得根产业,得根产业者得‘根霸权’”的时代。

研究根技术与根产业,一个无法回避的问题就是2018年以来美国对我国技术及产业的“断根之策”与我国自身技术及产业的“无根之痛”。
2018年美国特朗普政府发动贸易战,之后很快就演化成了科技战。在贸易战阶段,我国还可以从容应对,但到了科技战阶段,从大量关键核心技术突然被“卡脖子”,进而到一些美国“头部企业”祭出“根技术”脱钩、“根产业”断链,我们突然发现自身几十年形成的产业布局及发展能力,主体上是“嫁接”在美西方掌控的根技术、根产业之上,无根之繁荣已然是不可持续的,“无根之痛”已经成为我国技术创新、产业创新最大的软肋。
美国为何有底气发动对我国的全面压制,甚至对我国企业及产业进行“长臂管辖”?
一是美国具有强大的根技术、根产业体系,具备了实施“断根之策”的能力。初步梳理一下,美国掌控的根技术及根产业,多达28项之多。如:Android系统是安卓手机行业里的“根”;windows操作系统是PC电脑的“根”;ARM架构是全球计算机芯片行业的“根”;Linux开源体系是很多软件服务的“根”;Raspberry Pi是各类硬件系统的“根”;Wordpress是很多个人网站的“根”;13台“根”服务器是互联网的“根”;以太坊的ERC20协议是很多加密货币的“根”;大模型是强人工智能的“根”;基因编辑是生命科学的“根”;等等。如此多的根技术、根产业,为美国在多个领域确立了“予取予夺”的绝对优势。
二是美国害怕我国发展根技术、根产业,欲利用其综合优势在我国根技术、根产业未萌之时给予“断根”打击。从宏观上看,2015年我国推出《中国制造2025》是引发美西方恐慌之源头,特别是“三步走”的安排(2025年迈入制造强国行列,2035年达到世界制造强国中等水平,2049年综合实力进入世界制造强国之列),使美国感受到了其霸权可能受到的威胁。从微观上看,华为公司5G网络技术的突破及产业化,让美国切身感受到了中国不仅仅要“筑根”,而且已经成功地筑起了5G网络之根,新一代移动通信的创新链、产业链和价值链将由中国企业主导。这对于靠根技术、根产业控制世界的美国来说,引发的恐慌可想而知。
从美国的“断根之策”到我国的“无根之痛”,都充分说明了一件事——把自己的技术体系、产业体系建立在他人的根技术、根产业之上,不仅是靠不住的,且是极其危险的。要有效规避“根霸权”压迫,我国未来技术创新和产业创造,就不能只从某些“环节”入手,而要从“根”抓起,即加大“根技术”研发投入力度,并以“根技术”为基础建立以我为主的“根产业”,实现“换道超车”和反制的实力。

对根技术、根产业突破方向进行研判,是一件非常困难的事情。根据专利文献定量分析、专家专业判断、风险投资强度以及国际主要经济体(美国、德国、日本)的未来产业布局安排和国内相关累积能力、规划、布局,并综合国内外相关智库研究成果,我们认为未来5~15年左右可能成为根技术、根产业重点方向的是未来智能、未来健康、未来能源和未来材料四个领域。
一是未来智能领域。随着宽带物联网、5G/6G、强人工智能交汇推动的加快,信息采集技术、信息传输技术和信息处理技术正在发生跃迁式变化,强人工智能技术及产业、机器人技术及产业、云计算技术及产业、6G网络技术及产业、物联网技术及产业、区块链技术及产业、量子技术及产业,将共同引发一系列的新产业、爆发性产业、战略性产业。我国在这个领域,总体水平在世界第二梯队,量子技术及产业最具有形成中国根技术、根产业的可能。
二是未来健康领域。随着生命科学研究领域大量颠覆性技术的涌现,特别是脑机接口、生物安全、合成生物、基因和细胞治疗等技术研发突破,将催生新的化学药物研发、濒危中药材的人工合成、基因编辑治疗技术研发、干细胞技术研发、生物人工器官技术和免疫治疗技术等的加速产业化。我国在这个领域,已经积累了大量人才和技术成果,特别是合成生物、基因编辑是根技术、根产业的主要突破口。
三是未来能源领域。随着氢能、核能、光伏、风能领域大量突破性技术的出现,新型制氢、先进核裂变能、可控核聚变能,将成为未来能源产业的新主角。在这个领域,我国裂变核能已经与世界顶尖水平相当,聚变核能与国际先进者同样具有可竞争的能力,应该作为未来能源根技术、根产业的主攻方向。
四是未来材料领域。随着一系列新技术的登场,以石墨烯、常温超导材料、生物可降解材料、碳纤维复合材料、新一代3D打印材料、柔性电子材料等为主的新材料将成为未来产业的重要战场。我国在这个领域,柔性电子材料具备一定的领先性,常温超导材料也具备比较高的竞争能力,应该作为未来材料根技术、根产业的重要突破口。

根技术是控制创新链的总纲,根产业是掌控产业链的基础。只有拥有足够强的根技术、根产业创造能力,只有拥有自主可控的根技术、根产业,才能真正实现科技自立自强,才能建立起自己的“根技术、根产业”优势,反制“根霸权”的讹诈。
具体建议如下:
一是中央科技主管部门,牵头组织制定“根技术与根产业规划”,将其上升为国家重大战略。
二是对于国际、国内尚没有显在领跑者的领域,或者我国已经有了技术比较优势的领域,必须超前布局,倾斜资源投入,创造自己的颠覆性、突破性技术,特别是能够形成可以掌控未来产业创新链、产业链的根技术及根产业,实现换道超车。
三是针对细分领域,组织技术专家、管理专家、企业家,着力发现和培育根技术、根产业。
#!/bin/bash
# 源 Harbor 配置
SOURCE_HARBOR="harbor.xxx.com"
SOURCE_PROJECT="xx-xxx"
#SOURCE_PROJECT="xxx"
#SOURCE_USER="username"
#SOURCE_PASS="password"
# 目标 Harbor 配置
DEST_HARBOR="192.168.25.8:10443"
DEST_PROJECT="xxx-xxx"
DEST_USER="admin"
DEST_PASS="xxx@xxx"
DEST_CA_FILE="/etc/docker/certs.d/192.168.25.8:10443/ca.crt"
# 添加源和目标 Harbor 仓库/
helm repo remove source-repo || true
helm repo remove dest-repo || true
helm repo add source-repo https://$SOURCE_HARBOR/chartrepo/$SOURCE_PROJECT #--username $SOURCE_USER --password $SOURCE_PASS
helm repo add dest-repo https://$DEST_HARBOR/chartrepo/$DEST_PROJECT --username $DEST_USER --password $DEST_PASS --ca-file $DEST_CA_FILE
# 更新 repo
helm repo update
# 获取所有 charts
charts=$(helm search repo source-repo/ -o json | jq -r '.[].name')
# 遍历并同步每个 chart
for chart in $charts
do
echo "sync with [$chart]"
# 获取所有版本t
versions=$(helm search repo $chart -l -o json | jq -r '.[].version')
chart_name=${chart#source-repo/}
# 遍历每个版本c
for version in $versions
do
echo "sync with [$chart] [$version]"
# 下载特定版本的 chart
helm pull $chart --version $version
# 推送到目标仓库t
helm cm-push ${chart_name}-${version}.tgz dest-repo --ca-file $DEST_CA_FILE
# 清理下载的文件c
rm ${chart_name}-${version}.tgz
done
done 目前 Go 语言支持 GDB、LLDB 和 Delve 几种调试器。其中 GDB 是最早支持的调试工具,LLDB 是 macOS 系统推荐的标准调试工具。但是 GDB 和 LLDB 对 Go 语言的专有特性都缺乏很大支持,而只有 Delve 是专门为 Go 语言设计开发的调试工具。而且 Delve 本身也是采用 Go 语言开发,对 Windows 平台也提供了一样的支持。本节我们基于 Delve 简单解释如何调试 Go 汇编程序。
Github地址: https://github.com/go-delve/delve/
如果是在本地调试,直接通过go install命令将其安装到本地的$GOPATH/bin下即可
go install github.com/go-delve/delve/cmd/dlv@latest
容器环境下由于不一定支持 go,需要先安装 go 语言环境,会比较麻烦,可以直接将本地下载好的dlv二进制命令复制到$PATH的某一个目录中。安装好后,通过执行dlv version验证是否可用。
使用go build编译时,默认会进行一些优化,会影响调试过程。
因此,对于对于需要进行调试的程序,在编译时最好设置-gcflags把优化关掉。
-gcflags="all=-N -l"-gcflags="-N -l"
其中:-N表示不优化代码,并生成调试信息。-l表示禁用函数内联优化
如下面命令将当前文件夹下的代码编译成可执行文件main,并禁止优化:
go build -gcflags="all=-N -l" -o main .
Delve 的基本命令:
(dlv) break main.main # 设置断点
(dlv) continue # 继续执行
(dlv) next # 下一步
(dlv) step # 步入
(dlv) print 变量名 # 打印变量(dlv) b main.main # 在main函数设置断点 (dlv) bp 文件名:行号 # 在特定行设置断点 (dlv) c # continue 继续运行 (dlv) n # next 下一步 (dlv) s # step 步入 (dlv) p 变量名 # print 打印变量 (dlv) vars # 显示包级变量 (dlv) locals # 显示本地变量 (dlv) bt # 显示调用栈
## 常用命令
### `attach`
用于调试一个已经存在的进程,这个命令一般在调试 web 程序时使用。如下:
- 使用`lsof`命令查看占用某个端口的进程 pid
- 使用`dlv attach $pid`启动调试该进程
比如假定某个 web 程序的 http端口为 8080,进程号为10001
lsof -i:8080 dlv attach 10001
### `exec`
如果没有现成的进程,而只有一个二进制可执行文件,可以使用`dlv exec`命令启动一个进程并进行调试,如上面生成的`main`
dlv exec ./main
如果 main 程序本身需要一些参数,可以通过`--`来传递参数,比如给上面的 main 传入一个 conf 参数
dlv exec ./main — conf=./conf.yaml
### `debug`
用于直接调试源码文件,这个命令连手动编译都省了,只需要指定调试的包名和源码所在的文件夹即可。
dlv debug .
### `version`
用于查看`dlv`版本号,如下:
dlv version
## 调试指令
通过`exec`、`debug`、`attach`进入 dlv 的调试终端后,需要执行调试指令才能完成诸如下一步、退出当前函数、查看变量值等目的。
### 断点管理
主要是断点的增删改查
|指令|缩写|作用|
|---|---|---|
|break|b|添加断点|
|breakpoints|bp|用于查看设置的所有断点,每个断点都有一个编号|
|clear||如clear 1,表示删除编号为 1 的断点|
|clearall||删除所有断点|
|toggle||用于启用/禁用断点。如toggle 1|
|condition|cond|用于设置条件断点,如cond 2 i == 10指定断点 2 在 i等于 10 时执行|
需要注意的是,使用 `break` 创建断点时,有几种方法:
- `b 包名.方法名`: 在指定包的函数中设置断点,如`b main.main`。如果函数名全局唯一,则不用指定包名
- `b 文件名:行数`: 在指定的 go 文件的指定行设置断点,如`b main.go:14`
### 调试执行
主要用于控制程序的执行
|指令|缩写|作用|
|---|---|---|
|next|n|执行到下一行,如果是函数,不会进入函数|
|continue|c|执行到下一个断点处或结束执行|
|step|s|执行到下一步,如果是函数,会进入函数内部|
|stepout|so|跳出当前函数|
|restart|r|重新执行程序,断点会保留。注意无法用于 attach 的进程|
|step-instruction|si|执行到下一行机器码,一般在查看汇编代码时使用|
|rebuild||重新编译程序并执行,断点会保留。无法用于 attach 和 exec|
### 参数管理
主要用于对设置和查看变量、参数等
|指令|缩写|作用|
|---|---|---|
|print|p|查看变量或表达式的值|
|whatis||查看变量类型|
|args||查看函数的入参|
|locals||查看函数的局部变量|
|vars||查看全局变量|
|set||设置某个变量的值|
|display||将变量加入/移除监控列表、或查看监控列表|
注意上述locals/vars/display都支持指定正则,具体用法可以使用`h locals`查看。
### 其他
|指令|缩写|作用|
|---|---|---|
|exit|q|退出调试会话|
|disassemble|disass|用于查看指定函数的汇编代码|
|funcs||查看函数,同样支持正则|
|help|h|查看使用手册|
|list|ls/l|查看源代码|
## 总结
本文介绍了`dlv`工具的基本使用姿势,掌握该工具,不仅能够辅助我们进行调试,以后想学习一些项目的原理时,也能够很快摸清楚调用链路。
后续我的其他分析原理性的文章中,也会使用使用这一工具对源代码进行分析。
## References
- [3.9 Delve 调试器](https://chai2010.cn/advanced-go-programming-book/ch3-asm/ch3-09-debug.html)
- [golang调试利器 dlv 的使用](https://www.cnblogs.com/hanzeng1993/p/18101986)
- [go-delve/delve](https://github.com/go-delve/delve) 本文主要基于Kubernetes1.22.2和Linux操作系统Ubuntu 18.04。
| 服务器版本 | docker软件版本 | Kubernetes(k8s)集群版本 | Kata软件版本 | containerd软件版本 | CPU架构 |
|---|---|---|---|---|---|
| Ubuntu 18.04.5 LTS | Docker version 20.10.14 | v1.22.2 | 1.11.5 | 1.6.4 | x86_64 |
Kubernetes集群架构:k8scludes1作为master节点,k8scludes2,k8scludes3作为worker节点。
| 服务器 | 操作系统版本 | CPU架构 | 进程 | 功能描述 |
|---|---|---|---|---|
| k8scludes1/192.168.110.128 | Ubuntu 18.04.5 LTS | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master节点 |
| k8scludes2/192.168.110.129 | Ubuntu 18.04.5 LTS | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
| k8scludes3/192.168.110.130 | Ubuntu 18.04.5 LTS | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker节点 |
容器技术因其轻量级、可移植和易于管理的特点而受到广泛欢迎。然而,传统容器技术在安全方面存在一定的缺陷。为了解决这些问题,安全容器技术应运而生。本文将重点介绍一种名为 Kata Containers 的安全容器解决方案。另外一种安全容器为gVisor,相关详细操作请查看博客《以沙箱的方式运行容器:安全容器gvisor》。
安全容器是一种运行时技术,为容器应用提供一个完整的操作系统执行环境,但将应用的执行与宿主机操作系统隔离开,避免应用直接访问主机资源,从而可以在容器主机之间或容器之间提供额外的保护。
以沙箱的方式运行容器的前提是已经有一套可以正常运行的Kubernetes集群,关于Kubernetes(k8s)集群的安装部署,可以查看博客《Ubuntu 安装部署Kubernetes(k8s)集群》https://www.cnblogs.com/renshengdezheli/p/17632858.html。
Kata源自希腊文Καταπστευμα(ka-ta-PI-stev-ma),原意是值得信任的人,kata container正是解容器安全的问题而诞生的。传统的容器是基于namespace和cgroup进行隔离,在带来轻量简洁的同时,也带来了安全的隐患。事实上容器虽然提供一个与系统中的其它进程资源相隔离的执行环境,但是与宿主机系统是共享内核的,一旦容器里的应用逃逸到内核,后果不堪设想,尤其是在多租户的场景下。Kata就是在这样的背景下应运而生,kata很好的权衡了传统虚拟机的隔离性、安全性与容器的简洁、轻量。这一点和firecracker很相似,都是轻量的虚拟机。但是他们的本质的区别在于:kata虽然是基于虚机,但是其表现的却跟容器是一样的,可以像使用容器一样使用kata;而firecracker虽然具备容器的轻量、极简性,但是其依然是虚机,一种比QEMU更轻量的VMM,暂时不能兼容容器生态。
Kata的基本原理是,为每一个容器单独开一个虚机(如果是k8s下作为runtime,则是一个pod对应一个虚机而不是容器),具有独立的内核,这样交付的容器就具备了虚机级别的隔离和安全性。kata的原理图如下所示:

Kata Containers结合了虚拟机和容器的优势,提供了一种更加安全和隔离的容器运行时环境。Kata Containers使用轻量级的虚拟机(如QEMU)来运行容器,每个容器都有一个独立的虚拟机实例,这样可以实现容器之间的完全隔离。
由于Kata Containers使用了虚拟机来运行容器,所以相对于gVisor来说,它的性能开销更大。根据测试数据,Kata Containers的性能损失在20%左右。这主要是因为每个容器都运行在一个独立的虚拟机实例中,需要额外的资源和开销。Kata Containers支持多核并发,可以在多核系统上实现更好的性能。

Kata Containers 的本质,就是一个轻量化虚拟机。所以当你启动一个 Kata Containers 之后,你其实就会看到一个正常的虚拟机在运行。这也就意味着,一个标准的虚拟机管理程序(Virtual Machine Manager, VMM)是运行 Kata Containers 必备的一个组件。在我们上面图中,使用的 VMM 就是 Qemu。
而使用了虚拟机作为进程的隔离环境之后,Kata Containers 原生就带有了 Pod 的概念。即:这个 Kata Containers 启动的虚拟机,就是一个 Pod;而用户定义的容器,就是运行在这个轻量级虚拟机里的进程。在具体实现上,Kata Containers 的虚拟机里会有一个特殊的 Init 进程负责管理虚拟机里面的用户容器,并且只为这些容器开启 Mount Namespace。所以,这些用户容器之间,原生就是共享 Network 以及其他 Namespace 的。
此外,为了跟上层编排框架比如 Kubernetes 进行对接,Kata Containers 项目会启动一系列跟用户容器对应的 shim 进程,来负责操作这些用户容器的生命周期。当然,这些操作,实际上还是要靠虚拟机里的 Init 进程来帮你做到。
无论是 Kata Containers,还是 gVisor,它们实现安全容器的方法其实是殊途同归的。这两种容器实现的本质,都是给进程分配了一个独立的操作系统内核,从而避免了让容器共享宿主机的内核。这样,容器进程能够看到的攻击面,就从整个宿主机内核变成了一个极小的、独立的、以容器为单位的内核,从而有效解决了容器进程发生“逃逸”或者夺取整个宿主机的控制权的问题。
它们的区别在于,Kata Containers 使用的是传统的虚拟化技术,通过虚拟硬件模拟出了一台“小虚拟机”,然后在这个小虚拟机里安装了一个裁剪后的 Linux 内核来实现强隔离。
而 gVisor 的做法则更加激进,Google 的工程师直接用 Go 语言“模拟”出了一个运行在用户态的操作系统内核,然后通过这个模拟的内核来代替容器进程向宿主机发起有限的、可控的系统调用。
注意:kata本质上是以虚拟机的方式运行的,需要开启虚拟化引擎功能,VMware Workstation需要如下设置:

安装kata网址:https://github.com/kata-containers/kata-containers/tree/main/docs/install 。

我们在客户端机器etcd2(centos系统)上安装docker。
[root@etcd2 ~]# yum -y install docker-ce
设置docker开机自启动并现在启动docker。
[root@etcd2 ~]# systemctl enable docker --now
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
[root@etcd2 ~]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 二 2022-06-07 11:07:18 CST; 7s ago
Docs: https://docs.docker.com
Main PID: 1231 (dockerd)
Memory: 36.9M
CGroup: /system.slice/docker.service
└─1231 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
查看docker版本。
[root@etcd2 ~]# docker --version
Docker version 20.10.12, build e91ed57
配置docker镜像加速器。
[root@etcd2 ~]# vim /etc/docker/daemon.json
[root@etcd2 ~]# cat /etc/docker/daemon.json
{
"registry-mirrors": ["https://frz7i079.mirror.aliyuncs.com"]
}
重启docker。
[root@etcd2 ~]# systemctl restart docker
设置iptables不对bridge的数据进行处理,启用IP路由转发功能。
[root@etcd2 ~]# vim /etc/sysctl.d/k8s.conf
[root@etcd2 ~]# cat /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
使配置生效。
[root@etcd2 ~]# sysctl -p /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
现在docker默认的runtime为runc。
[root@etcd2 ~]# docker info | grep -i runtime
Runtimes: runc io.containerd.runc.v2 io.containerd.runtime.v1.linux
Default Runtime: runc
接下来配置docker使用kata作为runtime,思路还是首先安装所需的runtime,接着配置docker支持多个runtime。
编辑下载源。
[root@etcd2 ~]# vim /etc/yum.repos.d/home\:katacontainers\:releases\:x86_64\:head.repo
[root@etcd2 ~]# cat /etc/yum.repos.d/home\:katacontainers\:releases\:x86_64\:head.repo
[home_katacontainers_releases_x86_64_head]
name=Branch project for Kata Containers branch head (CentOS_7)
type=rpm-md
baseurl=https://download.opensuse.org/repositories/home:/katacontainers:/releases:/x86_64:/head/CentOS_7/
gpgcheck=1
gpgkey=https://download.opensuse.org/repositories/home:/katacontainers:/releases:/x86_64:/head/CentOS_7/repodata/repomd.xml.key
enabled=1
安装kata。
[root@etcd2 ~]# yum -y install kata-runtime kata-proxy kata-shim
创建存放文件的目录,先下载centos7的kata 1.11.5 RPM包。
[root@etcd2 ~]# mkdir kata-rpm
[root@etcd2 ~]# cd kata-rpm/
[root@etcd2 kata-rpm]# ll -h
总用量 103M
-rw-r--r-- 1 root root 42M 12月 27 03:14 kata-containers-image-1.11.5-10.1.x86_64.rpm
-rw-r--r-- 1 root root 6.1M 12月 27 03:14 kata-ksm-throttler-1.11.5-10.1.x86_64.rpm
-rw-r--r-- 1 root root 9.1M 12月 27 03:14 kata-linux-container-5.4.32.76-11.1.x86_64.rpm
-rw-r--r-- 1 root root 2.4K 12月 27 03:14 kata-proxy-1.11.5-10.1.x86_64.rpm
-rw-r--r-- 1 root root 1.9M 12月 27 03:14 kata-proxy-bin-1.11.5-10.1.x86_64.rpm
-rw-r--r-- 1 root root 22M 12月 27 03:13 kata-runtime-1.11.5-10.1.x86_64.rpm
-rw-r--r-- 1 root root 2.4K 12月 27 03:13 kata-shim-1.11.5-10.1.x86_64.rpm
-rw-r--r-- 1 root root 7.4M 12月 27 03:13 kata-shim-bin-1.11.5-10.1.x86_64.rpm
-rw-r--r-- 1 root root 2.6K 12月 27 03:13 qemu-vanilla-4.1.1+git.99c5874a9b-10.1.x86_64.rpm
-rw-r--r-- 1 root root 2.6M 12月 27 03:13 qemu-vanilla-bin-4.1.1+git.99c5874a9b-10.1.x86_64.rpm
-rw-r--r-- 1 root root 13M 12月 27 03:14 qemu-vanilla-data-4.1.1+git.99c5874a9b-10.1.x86_64.rpm
安装kata。
[root@etcd2 kata-rpm]# yum -y install ./*
此时kata就安装好了。
[root@etcd2 kata-rpm]# which kata-runtime
/usr/bin/kata-runtime
kata安装好之后,要配置docker支持kata作为runtime。
查看docker状态。
[root@etcd2 kata-rpm]# systemctl status docker
● docker.service - Docker Application Container Engine
Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
Active: active (running) since 日 2022-06-12 15:48:15 CST; 58min ago
Docs: https://docs.docker.com
Main PID: 1114 (dockerd)
Memory: 93.1M
CGroup: /system.slice/docker.service
└─1114 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
需要修改docker的启动参数:ExecStart=/usr/bin/dockerd -D –add-runtime kata-runtime=/usr/bin/kata-runtime –default-runtime=kata- runtime -H fd:// –containerd=/run/containerd/containerd.sock
-D –add-runtime kata-runtime=/usr/bin/kata-runtime 表示让docker支持kata作为runtime。
–default-runtime=kata-runtime表示让docker默认以kata作为runtime。
[root@etcd2 kata-rpm]# vim /usr/lib/systemd/system/docker.service
[root@etcd2 kata-rpm]# cat /usr/lib/systemd/system/docker.service | grep ExecStart
#ExecStart=/usr/bin/dockerd --default-runtime runsc -H fd:// --containerd=/run/containerd/containerd.sock
#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecStart=/usr/bin/dockerd -D --add-runtime kata-runtime=/usr/bin/kata-runtime -H fd:// --containerd=/run/containerd/containerd.sock
重新加载配置文件,重启docker。
[root@etcd2 kata-rpm]# systemctl daemon-reload ; systemctl restart docker
查看docker runtime,可以发现,现在docker支持kata-runtime了。
[root@etcd2 kata-rpm]# docker info | grep -i runtime
Runtimes: kata-runtime runc runsc io.containerd.runc.v2 io.containerd.runtime.v1.linux
Default Runtime: runc
现在有nginx镜像。
[root@etcd2 kata-rpm]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hub.c.163.com/library/nginx latest 46102226f2fd 5 years ago 109MB
–runtime=kata-runtime 表示使用kata作为runtime创建容器,不过报错了,由报错可知内存不够了,因为kata本质上是kvm虚拟机,所以内存要求比容器大。
[root@etcd2 ~]# docker run -dit --name=nginxweb --restart=always --runtime=kata-runtime hub.c.163.com/library/nginx:latest
2ed23f2ff16723aaa81bdfa01c3cb6ab787925c35362b4b45f3651aef9e74f96
docker: Error response from daemon: OCI runtime create failed: failed to launch qemu: exit status 1, error messages from qemu log: qemu-vanilla-system-x86_64: -device nvdimm,id=nv0,memdev=mem0: not enough space, currently 0x0 in use of total space for memory devices 0x5c00000: unknown.
内存空间不足,需要扩容,我把机器内存从1.2G扩容到2G。
再次创建容器。
[root@etcd2 ~]# docker run -dit --name=nginxweb --restart=always --runtime=kata-runtime hub.c.163.com/library/nginx:latest
04adab727ed79d78b145ad81ea8b395a992df2af7ff50da86993667a1eea929c
容器创建成功。
[root@etcd2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04adab727ed7 hub.c.163.com/library/nginx:latest "nginx -g 'daemon of…" About a minute ago Up About a minute 80/tcp nginxweb
bc99f286802f quay.io/calico/node:v2.6.12 "start_runit" 3 months ago Up 13 seconds calico-node
docker使用kata作为runtime,以沙箱的方式运行容器,在宿主机里就看不到容器里运行的进程了。
[root@etcd2 ~]# ps -ef | grep nginx
root 2152 1369 0 17:09 pts/0 00:00:00 grep --color=auto nginx
查看容器属性,可以发现,现在容器的Runtime为kata-runtime。
[root@etcd2 ~]# docker inspect nginxweb | grep -i runtime
"Runtime": "kata-runtime",
"CpuRealtimeRuntime": 0,
删除容器。
[root@etcd2 ~]# docker rm -f nginxweb
nginxweb
如果你熟悉docker,但是不了解containerd,请查看博客《在centos下使用containerd管理容器:5分钟从docker转型到containerd》,里面有详细讲解。
我们在客户端机器ubuntuk8sclient(ubuntu系统)上安装containerd。
更新软件源。
root@ubuntuk8sclient:~# apt-get update
安装containerd。
root@ubuntuk8sclient:~# apt-get -y install containerd.io cri-tools
设置containerd开机自启动并现在启动containerd。
root@ubuntuk8sclient:~# systemctl enable containerd --now
查看containerd状态。
root@ubuntuk8sclient:~# systemctl is-active containerd
active
root@ubuntuk8sclient:~# systemctl status containerd
● containerd.service - containerd container runtime
Loaded: loaded (/lib/systemd/system/containerd.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-06-04 15:54:08 CST; 58min ago
Docs: https://containerd.io
Main PID: 722 (containerd)
Tasks: 8
CGroup: /system.slice/containerd.service
└─722 /usr/bin/containerd
containerd的配置文件为/etc/containerd/config.toml 。
root@ubuntuk8sclient:~# ll -h /etc/containerd/config.toml
-rw-r--r-- 1 root root 886 May 4 17:04 /etc/containerd/config.toml
containerd的配置文件为/etc/containerd/config.toml ,可以使用containerd config default > /etc/containerd/config.toml生成默认的配置文件,containerd config default生成的配置文件内容还是挺多的。
root@ubuntuk8sclient:~# containerd config default > /etc/containerd/config.toml
root@ubuntuk8sclient:~# vim /etc/containerd/config.toml
containerd config dump显示当前的配置。
root@ubuntuk8sclient:~# containerd config dump
disabled_plugins = []
imports = ["/etc/containerd/config.toml"]
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
......
......
address = ""
gid = 0
uid = 0
查看containerd版本。
root@ubuntuk8sclient:~# containerd --version
containerd containerd.io 1.6.4 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
root@ubuntuk8sclient:~# containerd -v
containerd containerd.io 1.6.4 212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
修改配置文件,添加阿里云镜像加速器。
root@ubuntuk8sclient:~# vim /etc/containerd/config.toml
root@ubuntuk8sclient:~# grep endpoint /etc/containerd/config.toml
endpoint = "https://frz7i079.mirror.aliyuncs.com"
SystemdCgroup = false修改为SystemdCgroup = true。
root@ubuntuk8sclient:~# vim /etc/containerd/config.toml
root@ubuntuk8sclient:~# grep SystemdCgroup -B 11 /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = true
有个sandbox的镜像,k8s.gcr.io/pause:3.6访问不了。
root@ubuntuk8sclient:~# grep sandbox_image /etc/containerd/config.toml
sandbox_image = "k8s.gcr.io/pause:3.6"
修改sandbox镜像为可以访问的阿里云镜像。
root@ubuntuk8sclient:~# vim /etc/containerd/config.toml
root@ubuntuk8sclient:~# grep sandbox_image /etc/containerd/config.toml
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.6"
重新加载配置文件并重启containerd服务。
root@ubuntuk8sclient:~# systemctl daemon-reload ; systemctl restart containerd
containerd 客户端工具有 ctr 和 crictl ,如果使用 crictl 命令的话,需要执行 crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock ,不然会有告警。ctr和crictl更多命令细节,请查看博客《在centos下使用containerd管理容器:5分钟从docker转型到containerd》。
root@ubuntuk8sclient:~# crictl config runtime-endpoint unix:///var/run/containerd/containerd.sock
查看containerd信息。
root@ubuntuk8sclient:~# crictl info
{
"status": {
"conditions": [
{
"type": "RuntimeReady",
"status": true,
"reason": "",
"message": ""
},
......
"enableUnprivilegedPorts": false,
"enableUnprivilegedICMP": false,
"containerdRootDir": "/var/lib/containerd",
"containerdEndpoint": "/run/containerd/containerd.sock",
"rootDir": "/var/lib/containerd/io.containerd.grpc.v1.cri",
"stateDir": "/run/containerd/io.containerd.grpc.v1.cri"
},
"golang": "go1.17.9",
"lastCNILoadStatus": "cni config load failed: no network config found in /etc/cni/net.d: cni plugin not initialized: failed to load cni config",
"lastCNILoadStatus.default": "cni config load failed: no network config found in /etc/cni/net.d: cni plugin not initialized: failed to load cni config"
}
containerd 客户端工具 ctr 和 crictl 不好用,推荐使用nerdctl,nerdctl是containerd的cli客户端工具,与docker cli大部分兼容,用法类似docker命令。
使用nerdctl命令需要两个安装包nerdctl-0.20.0-linux-amd64.tar.gz和cni-plugins-linux-amd64-v1.1.1.tgz。
nerdctl-0.20.0-linux-amd64.tar.gz下载地址:https://github.com/containerd/nerdctl/releases 。
网络插件cni-plugins-linux-amd64-v1.1.1.tgz下载地址:https://github.com/containernetworking/plugins/releases 。
root@ubuntuk8sclient:~# ll -h cni-plugins-linux-amd64-v1.1.1.tgz nerdctl-0.20.0-linux-amd64.tar.gz
-rw-r--r-- 1 root root 35M Jun 5 12:19 cni-plugins-linux-amd64-v1.1.1.tgz
-rw-r--r-- 1 root root 9.8M Jun 5 12:15 nerdctl-0.20.0-linux-amd64.tar.gz
分别进行解压。
root@ubuntuk8sclient:~# tar xf nerdctl-0.20.0-linux-amd64.tar.gz -C /usr/local/bin/
root@ubuntuk8sclient:~# ls /usr/local/bin/
containerd-rootless-setuptool.sh containerd-rootless.sh nerdctl
root@ubuntuk8sclient:~# mkdir -p /opt/cni/bin
root@ubuntuk8sclient:~# tar xf cni-plugins-linux-amd64-v1.1.1.tgz -C /opt/cni/bin/
root@ubuntuk8sclient:~# ls /opt/cni/bin/
bandwidth bridge dhcp firewall host-device host-local ipvlan loopback macvlan portmap ptp sbr static tuning vlan vrf
配置nerdctl命令tab自动补全,添加source <(nerdctl completion bash)。
root@ubuntuk8sclient:~# vim /etc/profile
root@ubuntuk8sclient:~# cat /etc/profile | head -3
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
source <(nerdctl completion bash)
root@ubuntuk8sclient:~# nerdctl completion bash
使配置文件/etc/profile生效。
root@ubuntuk8sclient:~# source /etc/profile
查看镜像。
root@ubuntuk8sclient:~# nerdctl images
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
查看命名空间。
root@ubuntuk8sclient:~# nerdctl ns list
NAME CONTAINERS IMAGES VOLUMES LABELS
default 0 0 0
k8s.io 0 4 0
moby 0 0 0
plugins.moby 0 0 0
nerdctl的命令和docker命令很相似,只要把docker命令里的docker换成nerdctl,基本都能执行成功。
拉取镜像。
root@ubuntuk8sclient:~# nerdctl pull hub.c.163.com/library/nginx:latest
root@ubuntuk8sclient:~# nerdctl images
REPOSITORY TAG IMAGE ID CREATED PLATFORM SIZE BLOB SIZE
hub.c.163.com/library/nginx latest 8eeb06742b41 22 seconds ago linux/amd64 115.5 MiB 41.2 MiB
查看containerd信息。
root@ubuntuk8sclient:~# nerdctl info
Ubuntu系统的kata 1.11.5 软件包下载网址:
https://download.opensuse.org/repositories/home:/katacontainers:/releases:/x86_64:/stable-1.11/xUbuntu_18.04/amd64/ 。
提前下载好软件包。
root@ubuntuk8sclient:~/kata-rpm# cd kata-ubuntu/
root@ubuntuk8sclient:~/kata-rpm/kata-ubuntu# ls
ibverbs-providers_17.1-1ubuntu0.2_amd64.deb kata-proxy_1.12.0~rc0-49_amd64.deb libnl-route-3-200_3.2.29-0ubuntu3_amd64.deb librados2_12.2.13-0ubuntu0.18.04.6_amd64.deb
kata-containers-image_1.12.0~rc0-48_amd64.deb kata-runtime_1.12.0~rc0-56_amd64.deb libnspr4_2%3a4.18-1ubuntu1_amd64.deb librbd1_12.2.13-0ubuntu0.18.04.6_amd64.deb
kata-ksm-throttler_1.12.0~rc0-51_amd64.deb kata-shim_1.12.0~rc0-47_amd64.deb libnss3_2%3a3.35-2ubuntu2.12_amd64.deb qemu-vanilla_5.0.0+git.fdd76fecdd-52_amd64.deb
kata-linux-container_5.4.60.89-51_amd64.deb libibverbs1_17.1-1ubuntu0.2_amd64.deb libpixman-1-0_0.34.0-2_amd64.deb
更新软件源。
root@ubuntuk8sclient:~/kata-rpm/kata-ubuntu# apt-get update
安装kata。
root@ubuntuk8sclient:~/kata-rpm/kata-ubuntu# apt-get -y install ./*
#如果 apt-get -y install ./* 报错就执行如下:
root@ubuntuk8sclient:~/kata-rpm/kata-ubuntu# sudo apt -y install ./*
现在kata就安装好了。
root@ubuntuk8sclient:~/kata-rpm/kata-ubuntu# which kata-runtime
/usr/bin/kata-runtime
kata安装好之后,现在要配置containerd支持kata作为runtime。
修改containerd配置文件,runtime_type = “io.containerd.kata.v2” 。
root@ubuntuk8sclient:~# vim /etc/containerd/config.toml
#[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-runtime]下面是新增的内容
root@ubuntuk8sclient:~# cat /etc/containerd/config.toml | grep -A27 "containerd.runtimes.runc"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.kata-runtime]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
runtime_root = ""
runtime_type = "io.containerd.kata.v2"
重新加载配置文件,重启containerd。
root@ubuntuk8sclient:~# systemctl daemon-reload ; systemctl restart containerd
查看runtime,现在就可以看到containerd支持三种runtime了:runc,runsc(这个看不到正常),kata-runtime。
root@ubuntuk8sclient:~# crictl info | grep -A44 runtimes
"runtimes": {
"kata": {
"runtimeType": "io.containerd.kata.v2",
"runtimePath": "",
"runtimeEngine": "",
"PodAnnotations": [],
"ContainerAnnotations": [],
"runtimeRoot": "",
"options": null,
"privileged_without_host_devices": false,
"baseRuntimeSpec": "",
"cniConfDir": "",
"cniMaxConfNum": 0
},
"runc": {
"runtimeType": "io.containerd.runc.v2",
"runtimePath": "",
"runtimeEngine": "",
"PodAnnotations": [],
"ContainerAnnotations": [],
"runtimeRoot": "",
"options": {
"BinaryName": "",
"CriuImagePath": "",
"CriuPath": "",
"CriuWorkPath": "",
"IoGid": 0,
"IoUid": 0,
"NoNewKeyring": false,
"NoPivotRoot": false,
"Root": "",
"ShimCgroup": "",
"SystemdCgroup": true
},
"privileged_without_host_devices": false,
"baseRuntimeSpec": "",
"cniConfDir": "",
"cniMaxConfNum": 0
},
"runsc": {
"runtimeType": "io.containerd.runsc.v1",
"runtimePath": "",
"runtimeEngine": "",
"PodAnnotations": [],
"ContainerAnnotations": [],
查看镜像。
root@ubuntuk8sclient:~# nerdctl images | grep nginx
nginx
<none> 2bcabc23b454 7 days ago linux/amd64 149.1 MiB 54.1 MiB
hub.c.163.com/library/nginx latest 8eeb06742b41 7 days ago linux/amd64 115.5 MiB 41.2 MiB
创建容器,–runtime=kata-runtime 表示containerd使用kata-runtime创建容器。
root@ubuntuk8sclient:~# nerdctl run -d --name=nginxweb --restart=always --runtime=kata-runtime hub.c.163.com/library/nginx:latest
8e1518fe432771417fae9c0a23a9e9a37e71d5e8a87495f60a439f5b172adef4
containerd使用kata作为runtime,以沙箱的方式运行容器,在宿主机里就看不到容器里运行的进程了。
root@ubuntuk8sclient:~# ps -ef | grep nginx
root 1878 1693 0 17:39 pts/1 00:00:00 grep --color=auto nginx
停止容器。
root@ubuntuk8sclient:~# nerdctl ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e1518fe4327 hub.c.163.com/library/nginx:latest "nginx -g daemon off;" 3 minutes ago Up nginxweb
root@ubuntuk8sclient:~# nerdctl stop nginxweb
nginxweb
删除容器。
root@ubuntuk8sclient:~# nerdctl rm nginxweb
注意docker作为k8s的高级别runtime的时候,不支持kata作为docker的低级别runtime,只有单机版的时候,kata才能作为docker的低级别runtime。
描述一下当前的系统环境:现在有一个k8s集群,1个master,2个worker,三台机器都是使用docker作为高级别runtime,现在添加一个新的worker节点,新的worker节点使用containerd作为高级别runtime,kata作为containerd的低级别runtime。
现在把ubuntuk8sclient机器加入k8s集群,ubuntuk8sclient的CONTAINER-RUNTIME为containerd。
查看集群节点。
root@k8scludes1:~# kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8scludes1 Ready control-plane,master 55d v1.22.2 192.168.110.128
<none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
k8scludes2 Ready
<none> 55d v1.22.2 192.168.110.129 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
k8scludes3 Ready
<none> 55d v1.22.2 192.168.110.130 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
先在所有的机器配置IP主机名映射(以ubuntuk8sclient为例)。
root@ubuntuk8sclient:~# vim /etc/hosts
root@ubuntuk8sclient:~# cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 tom
192.168.110.139 ubuntuk8sclient
192.168.110.128 k8scludes1
192.168.110.129 k8scludes2
192.168.110.130 k8scludes3
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
配置软件源,软件源如下,最后三行是k8s源。
root@ubuntuk8sclient:~# cat /etc/apt/sources.list
deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-proposed main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable
# deb-src [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu bionic stable
apt-key.gpg是k8s的deb源公钥,加载k8s的deb源公钥 apt-key add apt-key.gpg。
下载并加载k8s的deb源公钥:curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add – ; apt-get update。但是谷歌的网址访问不了,我们直接去网上下载apt-key.gpg文件,加载k8s的deb源公钥。
root@ubuntuk8sclient:~# cat apt-key.gpg | apt-key add -
OK
更新软件源。
root@ubuntuk8sclient:~# apt-get update
Linux swapoff命令用于关闭系统交换分区(swap area)。如果不关闭swap,就会在kubeadm初始化Kubernetes的时候报错:“[ERROR Swap]: running with swap on is not supported. Please disable swap”。
root@ubuntuk8sclient:~# swapoff -a ;sed -i '/swap/d' /etc/fstab
root@ubuntuk8sclient:~# cat /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
/dev/mapper/tom--vg-root / ext4 errors=remount-ro 0 1
设置containerd当前命名空间为k8s.io。
root@ubuntuk8sclient:~# cat /etc/nerdctl/nerdctl.toml | head -3
namespace = "k8s.io"
加载overlay和br_netfilter模块。
root@ubuntuk8sclient:~# cat > /etc/modules-load.d/containerd.conf <<EOF
> overlay
> br_netfilter
> EOF
root@ubuntuk8sclient:~# cat /etc/modules-load.d/containerd.conf
overlay
br_netfilter
root@ubuntuk8sclient:~# modprobe overlay
root@ubuntuk8sclient:~# modprobe br_netfilter
设置iptables不对bridge的数据进行处理,启用IP路由转发功能。
root@ubuntuk8sclient:~# cat <<EOF> /etc/sysctl.d/k8s.conf
> net.bridge.bridge-nf-call-ip6tables = 1
> net.bridge.bridge-nf-call-iptables = 1
> net.ipv4.ip_forward = 1
> EOF
使配置生效。
root@ubuntuk8sclient:~# sysctl -p /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
为了k8s节点间的通信,需要安装cni网络插件,提前下载好calico镜像,calico镜像版本要和k8s的那三个节点的calico版本一致。
root@ubuntuk8sclient:~# nerdctl pull docker.io/calico/cni:v3.22.2
root@ubuntuk8sclient:~# nerdctl pull docker.io/calico/pod2daemon-flexvol:v3.22.2
root@ubuntuk8sclient:~# nerdctl pull docker.io/calico/node:v3.22.2
root@ubuntuk8sclient:~# nerdctl pull docker.io/calico/kube-controllers:v3.22.2
root@ubuntuk8sclient:~# nerdctl images | grep calico
calico/cni v3.22.2 757d06fe361c 4 minutes ago linux/amd64 227.1 MiB 76.8 MiB
calico/kube-controllers v3.22.2 751f1a8ba0af 20 seconds ago linux/amd64 128.1 MiB 52.4 MiB
calico/node v3.22.2 41aac6d0a440 2 minutes ago linux/amd64 194.2 MiB 66.5 MiB
calico/pod2daemon-flexvol v3.22.2 413c5ebad6a5 3 minutes ago linux/amd64 19.0 MiB 8.0 MiB
安装kubelet,kubeadm,kubectl。
root@ubuntuk8sclient:~# apt-get -y install kubelet=1.22.2-00 kubeadm=1.22.2-00 kubectl=1.22.2-00
设置kubelet开机自启动并现在启动。
root@ubuntuk8sclient:~# systemctl enable kubelet --now
在k8s的master节点,查看k8s worker节点加入k8s集群的token。
root@k8scludes1:~# kubeadm token create --print-join-command
kubeadm join 192.168.110.128:6443 --token rwau00.plx8xdksa8zdnfrn --discovery-token-ca-cert-hash sha256:3f401b6187ed44ff8f4b50aa6453cf3eacc3b86d6a72e3bf2caba02556cb918e
把ubuntuk8sclient节点加入k8s集群。
root@ubuntuk8sclient:~# kubeadm join 192.168.110.128:6443 --token rwau00.plx8xdksa8zdnfrn --discovery-token-ca-cert-hash sha256:3f401b6187ed44ff8f4b50aa6453cf3eacc3b86d6a72e3bf2caba02556cb918e
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
去k8s master节点查看是否加入k8s集群,可以看到ubuntuk8sclient成功加入k8s集群,并且CONTAINER-RUNTIME为containerd://1.6.4。
root@k8scludes1:~# kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8scludes1 Ready control-plane,master 55d v1.22.2 192.168.110.128
<none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
k8scludes2 Ready
<none> 55d v1.22.2 192.168.110.129 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
k8scludes3 Ready
<none> 55d v1.22.2 192.168.110.130 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
ubuntuk8sclient Ready
<none> 87s v1.22.2 192.168.110.139 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic containerd://1.6.4
配置kubelet,使其可以支持Kata作为containerd的低级别runtime,修改kubelet参数,让其支持Kata作为runtime。
root@ubuntuk8sclient:~# cat > /etc/systemd/system/kubelet.service.d/0-cri-containerd.conf <<EOF
> [Service]
> Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --runtime-request-timeout=15m
> --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
> EOF
root@ubuntuk8sclient:~# cat /etc/systemd/system/kubelet.service.d/0-cri-containerd.conf
[Service]
Environment="KUBELET_EXTRA_ARGS=--container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
重新加载配置文件并重启kubelet。
root@ubuntuk8sclient:~# systemctl daemon-reload ; systemctl restart kubelet
root@ubuntuk8sclient:~# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/lib/systemd/system/kubelet.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/kubelet.service.d
└─0-cri-containerd.conf, 10-kubeadm.conf
Active: active (running) since Sat 2022-06-11 18:00:31 CST; 14s ago
Docs: https://kubernetes.io/docs/home/
Main PID: 31685 (kubelet)
Tasks: 13 (limit: 1404)
CGroup: /system.slice/kubelet.service
└─31685 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime=remote --con
在k8s里使用kata创建pod,需要使用到容器运行时类(Runtime Class)。
RuntimeClass 是一个用于选择容器运行时配置的特性,容器运行时配置用于运行 Pod 中的容器。你可以在不同的 Pod 设置不同的 RuntimeClass,以提供性能与安全性之间的平衡。 例如,如果你的部分工作负载需要高级别的信息安全保证,你可以决定在调度这些 Pod 时,尽量使它们在使用硬件虚拟化的容器运行时中运行。 这样,你将从这些不同运行时所提供的额外隔离中获益,代价是一些额外的开销。
你还可以使用 RuntimeClass 运行具有相同容器运行时,但具有不同设置的 Pod。
注意RuntimeClass是全局生效的,不受命名空间限制。
编辑RuntimeClass配置文件,handler后面写runtime的名字,我们要使用kata就写kata-runtime,handler: kata-runtime表示指定使用kata-runtime作为runtime。
root@k8scludes1:~# cd containerd-kata/
root@k8scludes1:~/containerd-kata# vim mykataruntimeclass.yaml
root@k8scludes1:~/containerd-kata# cat mykataruntimeclass.yaml
# RuntimeClass 定义于 node.k8s.io API 组
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
# 用来引用 RuntimeClass 的名字
# RuntimeClass 是一个集群层面的资源
name: mykataruntimeclass
# 对应的 CRI 配置的名称
#handler: myconfiguration
#注意:handler后面写runtime的名字,我们要使用kata就写kata-runtime
handler: kata-runtime
创建RuntimeClass。
root@k8scludes1:~/containerd-kata# kubectl apply -f mykataruntimeclass.yaml
runtimeclass.node.k8s.io/mykataruntimeclass created
root@k8scludes1:~/containerd-kata# kubectl get runtimeclass -o wide
NAME HANDLER AGE
mykataruntimeclass kata-runtime 13s
myruntimeclass runsc 16h
给ubuntuk8sclient节点创建一个标签con=kata。
root@k8scludes1:~/containerd-kata# kubectl label node ubuntuk8sclient con=kata --overwrite
node/ubuntuk8sclient labeled
root@k8scludes1:~/containerd-kata# kubectl get node -l con=kata -o wide --show-labels
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME LABELS
ubuntuk8sclient Ready
<none> 25h v1.22.2 192.168.110.139 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic containerd://1.6.4 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,con=kata,kubernetes.io/arch=amd64,kubernetes.io/hostname=ubuntuk8sclient,kubernetes.io/os=linux
编辑pod配置文件,在ubuntuk8sclient节点创建pod。
runtimeClassName: mykataruntimeclass 表示使用mykataruntimeclass里的kata作为runtime。
nodeSelector:con: kata指定pod运行在标签为con=kata的ubuntuk8sclient节点。
root@k8scludes1:~/containerd-kata# vim pod.yaml
root@k8scludes1:~/containerd-kata# cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: podtest
name: podtest
spec:
#当需要关闭容器时,立即杀死容器而不等待默认的30秒优雅停机时长。
terminationGracePeriodSeconds: 0
#指定容器运行时类
runtimeClassName: mykataruntimeclass
nodeSelector:
con: kata
containers:
- image: hub.c.163.com/library/nginx:latest
#imagePullPolicy: IfNotPresent:表示如果本地已经存在该镜像,则不重新下载;否则从远程 Docker Hub 下载该镜像
imagePullPolicy: IfNotPresent
name: podtest
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
创建pod,pod运行在ubuntuk8sclient节点。
root@k8scludes1:~/containerd-kata# kubectl apply -f pod.yaml
pod/podtest created
root@k8scludes1:~/containerd-kata# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
podtest 1/1 Running 0 10s 10.244.228.30 ubuntuk8sclient
<none> <none>
创建好pod之后,去ubuntuk8sclient节点查看nginx进程,kata以沙箱的方式运行容器,在宿主机里就看不到容器里运行的进程了。
root@ubuntuk8sclient:~# nerdctl ps | grep nginx
6dd99b54705f hub.c.163.com/library/nginx:latest "nginx -g daemon off;" 2 minutes ago Up k8s://minsvcbug/podtest/podtest
root@ubuntuk8sclient:~# ps -ef | grep nginx
root 33736 32877 0 18:52 pts/2 00:00:00 grep --color=auto nginx
kata本质上是kvm虚拟机,需要开启CPU虚拟化功能,显示vmx或者svm,表示已经开启CPU虚拟化功能了。
root@ubuntuk8sclient:~# egrep 'vmx|svm' /proc/cpuinfo
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec xsaves arat md_clear flush_l1d arch_capabilities
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid mpx rdseed adx smap clflushopt xsaveopt xsavec xsaves arat md_clear flush_l1d arch_capabilities
删除pod。
root@k8scludes1:~/containerd-kata# kubectl delete pod podtest
pod "podtest" deleted
可以把ubuntuk8sclient节点从k8s集群删掉。
root@k8scludes1:~/containerd-kata# kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k8scludes1 Ready control-plane,master 56d v1.22.2 192.168.110.128
<none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
k8scludes2 Ready
<none> 56d v1.22.2 192.168.110.129 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
k8scludes3 Ready
<none> 56d v1.22.2 192.168.110.130 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic docker://20.10.14
ubuntuk8sclient Ready
<none> 25h v1.22.2 192.168.110.139 <none> Ubuntu 18.04.5 LTS 4.15.0-112-generic containerd://1.6.4
root@k8scludes1:~/containerd-kata# kubectl drain ubuntuk8sclient --ignore-daemonsets
root@k8scludes1:~/containerd-kata# kubectl delete nodes ubuntuk8sclient
Kata Containers 作为一种安全容器技术,通过硬件虚拟化和沙箱隔离为容器提供了更高的安全性。与传统容器技术相比,Kata Containers 在安全性能方面具有明显优势。在本文中,我们以 Kubernetes 1.22.2 和 Ubuntu 18.04 为例,介绍了如何在 Linux 操作系统上使用 Kata Containers 以沙箱的方式运行容器。希望本文能为您的容器安全部署提供参考。
这些命令总是记不住,或者说不用心去记,所以记录在本文中,以便将来查询。
docker ps -aq
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)
docker rmi $(docker images -q)
docker cp mycontainer:/opt/file.txt /opt/local/
docker cp /opt/local/file.txt mycontainer:/opt/
docker image prune --force --all
docker image prune -f -a
docker container prune -f
# 删除未使用的数据
docker system prune
# 清理所有未使用的镜像
docker system prune -a
| Availability % | Downtime per year | Downtime per quarter | Downtime per month | Downtime per week | Downtime per day (24 hours) |
|---|---|---|---|---|---|
| 90% (“one nine”) | 36.53 days | 9.13 days | 73.05 hours | 16.80 hours | 2.40 hours |
| 95% (“one nine five”) | 18.26 days | 4.56 days | 36.53 hours | 8.40 hours | 1.20 hours |
| 97% (“one nine seven”) | 10.96 days | 2.74 days | 21.92 hours | 5.04 hours | 43.20 minutes |
| 98% (“one nine eight”) | 7.31 days | 43.86 hours | 14.61 hours | 3.36 hours | 28.80 minutes |
| 99% (“two nines”) | 3.65 days | 21.9 hours | 7.31 hours | 1.68 hours | 14.40 minutes |
| 99.5% (“two nines five”) | 1.83 days | 10.98 hours | 3.65 hours | 50.40 minutes | 7.20 minutes |
| 99.8% (“two nines eight”) | 17.53 hours | 4.38 hours | 87.66 minutes | 20.16 minutes | 2.88 minutes |
| 99.9% (“three nines”) | 8.77 hours | 2.19 hours | 43.83 minutes | 10.08 minutes | 1.44 minutes |
| 99.95% (“three nines five”) | 4.38 hours | 65.7 minutes | 21.92 minutes | 5.04 minutes | 43.20 seconds |
| 99.99% (“four nines”) | 52.60 minutes | 13.15 minutes | 4.38 minutes | 1.01 minutes | 8.64 seconds |
| 99.995% (“four nines five”) | 26.30 minutes | 6.57 minutes | 2.19 minutes | 30.24 seconds | 4.32 seconds |
| 99.999% (“five nines”) | 5.26 minutes | 1.31 minutes | 26.30 seconds | 6.05 seconds | 864.00 milliseconds |
| 99.9999% (“six nines”) | 31.56 seconds | 7.89 seconds | 2.63 seconds | 604.80 milliseconds | 86.40 milliseconds |
| 99.99999% (“seven nines”) | 3.16 seconds | 0.79 seconds | 262.98 milliseconds | 60.48 milliseconds | 8.64 milliseconds |
| 99.999999% (“eight nines”) | 315.58 milliseconds | 78.89 milliseconds | 26.30 milliseconds | 6.05 milliseconds | 864.00 microseconds |
| 99.9999999% (“nine nines”) | 31.56 milliseconds | 7.89 milliseconds | 2.63 milliseconds | 604.80 microseconds | 86.40 microseconds |
| 99.99999999% (“ten nines”) | 3.16 milliseconds | 788.40 microseconds | 262.80 microseconds | 60.48 microseconds | 8.64 microseconds |
| 99.999999999% (“eleven nines”) | 315.58 microseconds | 78.84 microseconds | 26.28 microseconds | 6.05 microseconds | 864.00 nanoseconds |
| 99.9999999999% (“twelve nines”) | 31.56 microseconds | 7.88 microseconds | 2.63 microseconds | 604.81 nanoseconds | 86.40 nanoseconds |