L B T

记 录 过 去 的 经 验

版本信息

  • v7

常用指令

指令 (Prompt) 说明 示例
/imagine 画图指令 a samurai fox warrior in the snow, wearing red armor, cinematic lighting, dramatic pose, by greg rutkowski --ar 3:4 --v 6.0
/fast
/relax
模式切换。不同的模式对应画图的速度会因为优先级排队不同而不同 /fast 切换到 fast 模式
/info 查询 fastrelax 等模式的剩余时间 /info 指令示例
/settings 配置菜单 /settings 指令说明
/describe image
/describe url
上传本地图片进行编辑
通过链接上传图片进行编辑

常见参数

参数 说明 示例
--ar [4:3] 图片比例 /imagine a girl --ar 4:3
--s [0-1000] Style Midjourney 生成图片时的风格化程度,范围 0-1000 ,数值越高,AI 自由发挥的风格化程度越强;数值低则更贴近文字描述。 /imagine a girl --ar 4:3 --s 1000
--q [1/2/0.25] quality 控制图像渲染质量与所用时间/计算资源的权衡。
--q 1 :标准质量(默认值)
--q 2 :高质量(需要更多时间,图像细节更丰富)
--q 0.25 :低质量(快速预览用)
--no [apple] 生成的图片中 不要出现某个东西
可多重排除,例如: --no text --no logo --no watermark
:: 表示 :: 后面的为图片的主体
比如 hot dog 默认生成的是食物,如果想生成的是一只非常热的狗,需要使用 hot:: dog
hot::2 dog 中的 2 也可以用于指定 hot 的程度
/imagine hot dog
/imagine hot:: dog
/imagine hot::2 dog
--c [0-100] chaos 控制图像生成的多样性,越高结果越随机、不拘一格。指定默认生成的 4 张图片的差异程度,数字越小,4 张图片的风格越接近
--seed 以已有的图片为种子文件生成图片
--iw [0.1 - 3] Image Weight / 图像权重 。用于控制在混合 图像和文本提示时 ,图像的影响力有多大。
当你使用 /imagine 并上传了一张或多张图像,同时添加文字提示, --iw 让你可以决定这些图像在生成结果中的 说话权重
默认 --iw 1 (图像权重 = 文本提示的权重)
组合使用多张图像和 --iw 参数
/imagine https://yourimage.url/abc.jpg A warrior in golden armor --iw 2 --v 6.1
--iw 0.1--iw 10 (推荐范围)
- --iw 0.5 :图像影响较小,偏重文字描述
- --iw 1 :图像与文字影响力相当
- --iw 3 :图像主导风格和构图
--sref urlA::2 urlB::3 --sw [100-1000] 参考图片的风格以及比重,还可以对各个图片风格指定不同的参考比重( ::3 )
风格参考比重取值 100-1000 ,值越大,参考风格影响力越大
--cref urlA::2 urlB::3 --cw [0-100] 角色一致性参数,比重取值 0-100
100 默认值,使用脸部、头发和衣服,保持一致性
0 它只会关注脸部(适合更换服装/头发等)

info

/info 指令用于查询账号信息,包括 fastrelax 等模式的剩余时间

Subscription: Basic (Active yearly, renews next on May 20, 2026 at 5:30 PM)
Job Mode: Relaxed
Visibility Mode: Public
Fast Time Remaining: 195.25/200.0 minutes (97.63%)
Ranking Count: 0
Lifetime Usage: 4 images
Fast Usage: 4 images
Turbo Usage: 0 images
Relaxed Usage: 0 images

Queued Jobs (fast): 0
Queued Jobs (relax): 0
Running Jobs: None

settings

/settings 指令用于显示和配置选项。其中 绿色背景表示启用,灰色背景表示未启用

v7 版本支持 Personalization Mode ,在 Midjourney 提供的 200 张照片中全部选择你选择的照片后,Midjourney 会为你生成专属的 Personalization,创建照片时可使用。

Style 参考

seed 参数

参考已有的图片为种子文件生成图片

  1. 在 APP 中选择(鼠标滑动到图片上)已有的图片(风格参考图片),单击右上角的 ...more ) 并选择弹出菜单中的 Add Reaction
  2. 在搜索框中输入 :envelope: (信封),并选择下图中的信封点击
  3. Midjourney Bot 会发送这个图片的信息,其中包含 seed 840837654


  4. 在你自己的 APP 中,即可使用此 seed 值创建同风格的图片

以下方法更为快捷方便,直接在 Midjourney 的 web 页面中查看

Midjourney 一致性图片生成方法

参考文章

掌握 浏览器搜索语法 (特别是 Google、Bing、DuckDuckGo 等搜索引擎的高级搜索语法),可以大大提高你获取信息的效率,特别适合运维、程序员、学者等高效人群。

常用搜索语法大全(以 Google 为主)

语法 说明 用法示例
"关键词" 精确匹配整个短语 "nginx配置文件位置"
关键词1 OR 关键词2 匹配任一关键词( 注意大写 OR nginx OR apache
关键词1 关键词2
关键词1 AND 关键词2
同时满足多个关键词,即 AND 关系 这是浏览器默认得语法 nginx 配置 文件路径
nginx AND 配置 AND 文件路径
-关键词 排除包含该词的结果 mysql -mariadb
site:域名 仅搜索特定网站内的内容 site:stackoverflow.com nginx
intitle:关键词 仅搜索标题中含有关键词的页面 intitle:nginx
inurl:关键词 仅搜索 URL 中含有关键词的页面 inurl:config nginx
filetype:扩展名 搜索特定文件类型 filetype:pdf mysql 教程
related:网址 查找与该网址类似的网站 related:github.com
cache:网址 查看网页的缓存快照 cache:example.com
*(星号) nginx * configuration 通配符,表示任意词
before:YYYY-MM-DD / after: 搜索某个时间点前或后的内容(Google 支持) nginx config before:2020-01-01

多个关键词之间默认是 AND ,但如果你想控制词组必须连在一起,可以用引号包裹

"nginx 配置" "文件路径"

表示必须包含:

  • 短语 nginx 配置

  • 短语 文件路径

四柱八字 命盘中,以 日干 代表命主本人,周围的干支和日干的关系有十种状态,用 十神 来表示

  • 印枭 。。
十神 关系 正偏 说明
财星 我克者为财 - 异性者为 正财(财)
- 同性者为 偏财(才)
官杀 克我者为官杀 - 异性者为 正官(官)
- 同性者为 偏官(七杀、杀)
印枭 生我者为印枭 - 异性者为 正印(印)
- 同性者为 偏印(枭)
比劫 同我者为比劫 - 异性者为 劫财(劫)
- 同性者为 比肩(比)
食伤 我生者为食伤 - 异性者为 伤官(伤)
- 同性者为 食神(食)

十神类象

十神 优点 缺点 其他
比肩 自信 坚持己见,不听劝 比肩多容易合伙做事,帮身抗杀(杀克比肩)克财(比肩克财)助食伤(比劫生食伤)
劫财 勇猛 粗暴自负;容易狂 劫财多,容易破财
正印 优雅仁慈 依赖心,不爱动,懒 正印多,容易懒,得母亲偏爱,生我泄官杀克食伤
偏印(枭) 思维细腻 内向多疑
食神 口才好,想法多 空想幻想纠结 泄我生财克官杀
伤官 聪明,悟性高,创造力强 桀骜不驯,高冷,挑剔
正官 正直保守,秉公尚义 胆小怕事,过于谨慎 官主贵,有情(自律)约束。引财生印制劫
偏官(杀,七杀) 坚决果断,天生王者 个性偏激,招惹小人 杀主祸,事业名气权力,耗财生印功身制劫
正财 精打细算,勤俭持家 因小失大,不大气 财不大,稳定。生官杀,克印枭,泄伤食,坏印
偏财 慷慨豪爽,不拘小节 虚荣心强,炫富,花心 财大,不固定,众人财

偏财

  • 通常比较大
  • 不固定,三年不开张,开张吃三年
  • 众人财,如开公司,做生意,营销等
  • 喜欢炫、表面有钱,别人觉得有钱
  • 偏财旺,机会多,身边老板有钱人可能多

正财

  • 财不大但是可能很稳定,月月有,年年有,具体上线看实际情况
  • 至于小不小取决于是否有食伤生助; 正财星是否有根,正财星的力量
  • 正财正印正官透出,是典型的公务员、国企编制、大公司等

在八字命理体系中,判断一个人的八字是身强还是身弱是非常关键的一步,它犹如一把关键的钥匙,是开启后续分析如 性格特征、运势走向、用神、喜忌 等诸多方面的基础。

四柱八字

在八字命令体系中, 四柱八字 是分析命理的基本盘,它由 年柱月柱日柱时柱 构成,分别代表了人出生时的 的天干地支纪时。

年柱 月柱 日柱 时柱
天干
地支
藏干(继承 / 余气)
藏干(长生 / 中气)
藏干(本气)
-
-
乙木
-
-
癸水
-
己土
丁火
-
-
癸水
  • 日主 , 也称 日元本命元神 或者 日干 , 是 日柱中的天干 ,如以上 四柱八字中的 戊日主 代表命主本身,是整个八字的核心所在

  • 月令 , 也称 月支 , 在判断八字身强身弱的诸多因素中, 月令 占据这举足轻重的地位,是决定先天旺衰的关键所在。不同的季节对应着不同的五行旺相状态,而出生月份的地支所代表的五行,对日主五行的力量有着先天性的影响。 若 日主 的五行处于 当令 旺相状态,日主便处于 得令 状态,力量相对较强

  • 通根 , 天干中的五行,在地支也能找到对应的五行

    比如 甲木 ,在地支中能找到 寅木卯木 既是有根,并且是 强根 ;如果有 未土 ,因为 未藏己丁乙中气根 相比 本气根 会弱些;如果有 , 因为 辰藏戊乙癸 ,为 余气根 属于最弱的根。

  • 透干 , 地支中存在的五行,在天干中有对应的五行,则属于透干。 存在通根,也会存在透干 。如果 地支中存在的属性,天干中没有对应的属性(即不存在透干),则会比存在透干的属性弱一些

  • 无根 / 天干虚浮 / 虚浮无根 指天干对应的五行在地支中没有对应的属性

  • 天干的五行能量强于地干,天干代表会表现出来的特性,地支通常处于 伏藏 状态,不易被发现

四柱八字对应的信息

年柱 月柱 日柱 时柱
天干 父亲 兄弟 命主 儿子
地支 母亲 姐妹 配偶 女儿
父母宫 兄弟姐妹宫 夫妻宫 子女宫
年龄 1 - 18 岁 19 - 35 岁 36 - 54 岁 54 岁以后
身体部位 头部 胸背 腰腹 阴部、下肢、足
  • 年柱主要代表了 父母祖上 的信息

  • 兄弟宫也可以代表父母,但是更偏向于 母亲

  • 天干所表现的通常是能看得到的,地支通常存在 伏藏

年月日时之间的关联互动关系

关联 关系 说明
年月 父母关系或者祖父辈关系,主三十六之前的状态
年柱如果代表父亲,则月柱代表母亲
年月相合 : 父母关系好,三十岁前多贵人相助,年轻时做事容易成功
年月相冲 : 青年时期多奔波,不安稳,多白手起家,难得祖业,起点比较低
年日 - 父母与配偶的关系
年柱代表父母,日柱代表配偶,如婆媳关系,女婿和岳父岳母关系
- 也代表命主和祖业的关系
年日相合 : 父母和配偶关系融洽,也可能会得到祖业祖产
年日相冲 : 和祖辈关系不好,婆媳/翁婿关系不好,容易远离家乡发展
年时 - 子女关系
- 命主年轻时的事业和将来的事业状态好坏是否相同
年时相合 : 事业能够持续有成,事业能一直做到老;也代表后继有人,子女能成材
年冲时 : 家业难留,手下无强兵,自立自强
月日 - 兄弟姐妹和配偶的关系
- 18-55 岁之间
为人生事业、婚姻、感情最为重要的阶段
月日相合 : 出社会后,事业关系和夫妻关系都不错,夫妻间能互相扶持,多贵人帮扶
月柱为兄弟宫, 月日相合 也表示能得到兄弟朋友的帮扶
月冲日 : 家庭纠纷多,婚姻不稳定,是非多
月时 - 交友、合作伙伴、工作等 月时相合 : 容易和朋友合作投资赚钱,能有不错的表现
月冲时 : 看交友、合作伙伴; 子嗣凶顽,难管教,意外较多
日时 - 夫妻关系
- 亲子关系
日时相合 : 亲子关系和谐,子女能达到父母期望
日时相冲 : (工作等)变动大;子女不好管,长大后聚少离多

日主对应五行的特点

不同属性的日主会代表命主本人有不同的性格特征,这些天干出现命盘的其他地方也会产生作用,无需一定是 日主 ,只是出现在日主能量更强。出现在地支通常代表命主内心的想法(伏藏),不一定会直接显现出来

日干 特点
甲木 甲木为阳 ,为参天大树,上进,专一,有组织领导能力
乙木 乙木为阴 ,为花草藤曼,善于借势借力,重视朋友
丙火 丙火为阳火 ,为太阳之火,热烈(热情)耿直
丁火 丁火为阴火 ,为烛火炉火,黑暗中的明灯(光明),温暖,随遇而安,持久性较强
戊土 戊土为阳土 ,为大地高山城墙,稳重可靠,包容万物;固执,很难被改变
己土 己土为阴土 ,为田园之土,可塑性和包容性强,有牺牲精神,注重义气
庚金 庚金为阳金 ,为刀斧之金,刚直不屈,坚韧果断,一根筋,不懂变通
辛金 辛金为阴金 ,为珠玉之金,好面子,自尊心极强,一般会长得漂亮,爱好打扮,形象好
壬水 壬水为阳水 ,为江海河湖泊之水,宽宏大量,变化快,不稳定,适应能力强
癸水 癸水为阴水 ,为雨露之水,滋润万物,愿意帮助别人并会得到反哺,足智多谋,阴柔十足

旺衰强弱

旺衰强弱 是指八字中 日主(日干,日元,本命,身) 的状态

论命以日干为主,称之曰 身,身之强弱,关系最为紧要,故首论之。 《千里命稿》

判断强弱主要是为了判断 日干的状态取用神

日主强弱大致可以分为其中状态:

  • 从强
  • 太强
  • 偏强
  • 平衡
  • 偏弱
  • 太弱
  • 从弱

判断强弱使用以下步骤:

  1. 是否得令

    • 月支 被称为 月令,月令的力量会占到全局的 40-50%
    • 日主 得 月令之助(印枭比劫) 称为 得令

传统廿四节气歌

春雨惊春清谷天,夏满芒夏暑相连。
秋处露秋寒霜降,冬雪雪冬小大寒。
每月两节不变更,最多相差一两天。
上半年来六廿一,下半年来八廿三。

论节气歌 《渊海子平》

正月立春雨水节,二月惊蛰及春风。
三月清明并谷雨,四月立夏小满方。
五月芒种并夏至,六月小暑大暑当。
七月立秋还处暑,八月白露秋分忙。
九月寒露又霜降,十月立冬小雪降。
子月大雪冬至节,丑月小寒大寒昌。
寅月 卯月 辰月 巳月 午月 未月 申月 酉月 戌月 亥月 子月 丑月
立春 惊蛰 清明 立夏 芒种 小暑 立秋 白露 寒露 立冬 大雪 小寒
气 / 候 雨水 春风 谷雨 小满 夏至 大暑 处暑 秋风 霜降 小雪 冬至 大寒

*需要注意的是,天干地支中表示的月份,都是以节气中的节为分割,而不是公历或者农历中的整月分割,例如正月的开始是 立春,而不是正月初一*

比如公元 1993 年 2 月 4 号,为农历 正月十三 ,为节气 立春 ,那么子天干地支纪年法中, 正月初一到正月十二不属于正月( 甲寅月 )而是属于前一年的腊月( 癸丑月 ),正月十三到二月十二属于正月( 甲寅月

春季

说明 解释
立春 斗指东北,斗柄指向 ,立春是干支历 月的起始 立,是开始之意。万物复苏、生机勃勃,立春期间,气温上升,日照、降雨趋于增多
古代将立春分为三候: 一候东风解冻,二候蜇虫始振,三候鱼陟负冰 <span class=”hint–top hint–error hint–medium hint–rounded hint–bounce” aria-label=”候: 在节气中,将每个节气分为 3 候,每候大概 5 天
“>[1]
雨水 降雨开始,但降雨量级以小雨或毛毛细雨为主,太阳的直射点由南半球逐渐向赤道靠近。这时的北半球,日照时数和强度都在增加,气温回升较快,来自海洋的暖湿气流开始活跃,并渐渐向北挺进;冷暖交汇形成降雨。
雨水三候是: 一候獭祭鱼,二候鸿雁来,三候草木萌动
雨水三候对应的花信是 一候菜花,二候棠棣,三候李花
惊蛰 惊蛰是干支历 月的起始 时至惊蛰,阳气上升、气温回暖、春雷乍动、雨水增多,万物生机盎然
惊蛰三候为: 一候桃始华;二候仓庚鸣;三候鹰化为鸠
花信为: 一候桃花,二候杏花, 三候蔷薇
春风 春分又称为 日中日夜分仲春之月升分 等。这一天太阳直射地球赤道,南北半球昼夜平分。
清明 清明是干支历 月的起始 清明后雨水增多,大地呈现春和景明之象。草木始发新枝芽,万物开始生长,农民忙于春耕春种。
三候: 桐始华,田鼠化为鴽,虹始见,萍始生。
清明花信为: 一候桐花,二候麦花,三候柳花。
谷雨 谷雨就是 雨水生五谷 的意思,由于雨水滋润大地五谷得以生长,所以,谷雨就是 雨生百谷 。谚云 谷雨前后,种瓜种豆
三候: 第一候萍始生;第二候鸣鸠拂其羽;第三候为戴胜降于桑。
谷雨时节正值暮春,是牡丹花开的重要时段,因此,牡丹花也被称为 谷雨花 ,民间有 谷雨三朝看牡丹 的说法。

夏季

说明 解释
立夏 斗指东南,斗柄指向 ,立夏是干支历 月的起始 盛夏时节的正式开始
小满 气温升高,降雨增多。
三候是: 一候苦菜秀,二候靡草死,三候麦秋至
芒种 芒种是干支历 月的起始 字指麦类等作物的收获, 字是指谷黍类作物的播种, 芒种 二字表明一切作物都在 忙种 了,是农事最为繁忙的时节
三候: 一候螳螂生;二候鹏始鸣;三候反舌无声
夏至 太阳直射地面的位置到达一年的最北端,几乎直射北回归线,此时,北半球的白昼达最长。 夏至日阴气生而阳气始衰
三候: 一候鹿角解;二候蝉始鸣;三候半夏生。
小暑 小暑是干支历 月的起始 小暑意为天气开始炎热,但还没到最热。
三候: 一候温风至;二候蟋蟀居宇;三候鹰始鸷。
大暑 炎热至极
三候为: 一候腐草为萤;二候土润溽暑;三候大雨时行。

秋季

说明 解释
立秋 斗指西南,斗柄指向 ,立秋是干支历 月的起始 三候为: 初候凉风至,二候白露降,三候寒蝉鸣
处暑 即为 出暑 ,是炎热离开的意思。 气温由炎热向寒冷过渡的节气
三候: 一候鹰乃祭鸟;二候天地始肃;三候禾乃登。
白露 白露是干支历 月的起始 自白露节气开始,季风交替,夏季季风逐渐被冬季季风代替,冷空气逐步南移,天气明显变得凉爽。
三候是: 一候鸿雁来;二候玄鸟归;三候群鸟养羞。
秋风 秋分当日太阳直射赤道,全球各地昼夜等长。
三候: 一候雷始收声;二候蛰虫坯户;三候水始涸
寒露 小暑是干支历 月的起始 寒露节气是天气转凉的象征,如俗语所说, 寒露寒露,遍地冷露 ,寒露时的气温比白露时更低,地面的露水快要凝结成霜了。
三候: 一候鸿雁来宾;二候雀入大水为蛤;三候菊有黄华
霜降 天气渐冷、初霜出现。
三候: 一候豺乃祭兽;二候草木黄落;三候蜇虫咸俯

冬季

说明 解释
立冬 斗指西北,斗柄指向 ,立冬是干支历 月的起始 意味着生气开始闭蓄,万物进入休养、收藏状态。
三候: 一候水始冰;二候地始冻;三候雉入大水为蜃
小雪 三候: 一候虹藏不见;二候天气上升地气下降;三候闭塞而成冬
大雪 大雪是干支历 月的起始 三候为: 一候鹖鴠不鸣;二候虎始交;三候荔挺出
冬至 太阳直射地面的位置到达一年的最南端,几乎直射南回归线,这一天北半球的白昼最短,且越往北越短,黑夜最长。
冬至三候为: 一候蚯蚓结,二候麋角解,三候水泉动
小寒 小寒是干支历 月的起始 一年中最寒冷的时节
三候为: 一候雁北乡,二候鹊始巢,三候雉始鸲
大寒 三候: 一候鸡乳;二候征鸟厉疾;三候水泽腹坚

脚注:


  1. 1.候: 在节气中,将每个节气分为 3 候,每候大概 5 天

GIMP(GNU Image Manipulation Program) 是一个开源的专业的图像处理工具 [1]

常用操作

调整图像大小

调整图像大小参考文档

颜色操作

如何将新加元素的颜色调整为和图片上某个像素颜色完全一致

  1. 选择颜色拾取器工具

    在左侧工具栏中,点击 颜色拾取工具 (吸管图标),或快捷键 O 。接着鼠标点击图片上你想匹配的颜色。

  2. 将拾取的颜色用于新内容

    拾色后,GIMP 会自动将该颜色设为 前景色(在工具箱左下角可见)

    如果你是使用:

    • 文字工具 : 输入新文字后,在工具选项中点击 颜色 ,然后点击刚才的前景色。

    • 画笔/填充工具 : 直接使用前景色即可绘制或填充。

复制粘贴

如何将矩形选择工具选择的区域复制粘贴到其他区域

  1. 使用矩形选择工具

    在左侧工具栏选择 矩形选择工具 (快捷键:R)。在图像中框选你要复制的区域。

  2. 复制或剪切该区域

    • 复制 :快捷键 Ctrl + C (或 菜单:编辑 > 复制 )。
    • 剪切 (如果你想把原位置清除): Ctrl + X (或 菜单:编辑 > 剪切 )。
  3. 粘贴到新位置

    Ctrl + V (或 菜单:编辑 > 粘贴 )。 此时会出现一个名为 浮动选择(浮动图层) 的新图层,附着在原图上。

  4. 移动

    在左侧工具栏选择 移动工具 (十字箭头图标,快捷键:M)。 拖动粘贴的内容到你想要放置的位置。

  5. 锚定或新建图层

    如果你满意现在的位置,可以:

    • 锚定图层Ctrl + H图层 > 锚定图层 ,粘贴内容会并入原图。
    • 转为新图层 :右键 浮动图层 > 转为新图层 ,便于后续调整。

测量图片中元素大小

要测量图片中指定元素的精确大小(Pixel),可以参考以下方法

  • 使用 测量工具(Measure Tool)

    1. 在工具箱中点击 测量工具 (图标像一个圆规),或按快捷键 Shift + M鼠标点击图片上你要测量的起点 → 拖动到终点。状态栏会实时显示 距离(以像素为单位) ,如 Distance: XXX px
  • 使用 矩形选择工具 看宽高

    1. 选择 矩形选择工具 (快捷键 R ), 用鼠标拖出一个区域(框住你要测量的元素), 在 工具选项 面板或 状态栏 里,会显示所选区域的

      Position: X, Y
      Size: Width x Height(单位是 px)

抬高图片的某一个角

图片经常会出现某个角较低或较高的情况,此时想要调整图片是所有角处于完美的矩形状态,可以使用 透视工具(Perspective Tool)

  1. 工具箱里面选择 透视工具(Perspective Tool) 或使用快捷键 Shift + P
  2. **图片中会出现四个角,随 1313575799

GNU IMAGE MANIPULATION PROGRAM

脚注

  • JPEG - Joint Photographic Experts Group , 图像有损压缩标准 ,主要用于数码图像的存储和传输,

环境信息

  • Centos7 5.4.212-1
  • Docker 20.10.18
  • containerd.io-1.6.8
  • kubectl-1.25.0
  • kubeadm-1.25.0
  • kubelet-1.25.0

安装 ingress-nginx controller

此文档中的配置主要针对基于部署在裸机(安装通用 Linux 发行版的物理机或者云主机系统)上的 Kebernetes 集群

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.3.1/deploy/static/provider/cloud/deploy.yaml
mv deploy.yaml ingress-nginx-controller-v1.3.1.yaml

基于 hostNetwork 的 ingress-nginx controller

编辑 ingress-nginx-controllerDeployment 配置文件,在 Deployment 中的 .spec.template.spec 下添加字段 hostNetwork: true ,以使 ingress-nginx-controller 可以使用节点的主机网络提供对外访问

阅读全文 »

环境信息

  • Centos7 3.10.0-1160
  • Docker Engine - Community 23.0.3
  • kubernetes 1.21.2-0
  • kubernetes-cni-0.8.7-0

Kubernetes 对任何网络实现都规定了以下要求: [1]

  • 所有 Pod 都可以在不使用网络地址转换 (NAT) 的情况下与所有其他 Pod 通信。

    容器之间直接通信,不需要额外的 NAT,不存在源地址伪装的情况

  • 所有节点都可以在没有 NAT 的情况下与所有 Pod 通信。

    Node 与容器直接通信,不需要额外的 NAT

  • Pod 认为自己的 IP 与其他人认为的 IP 相同。

CNI

CNI 是 Kubernetes 容器网络的标准,CNI 是 Kubernetes 和底层网络插件之间的一个抽象层,为 Kubernetes 屏蔽了底层网络实现的负责度,同时解耦了 Kubernetes 和具体的网络插件实现。

安装 CNI

$ yum install kubernetes-cni

$ rpm -qa | grep kube
kubeadm-1.21.2-0.x86_64
kubectl-1.21.2-0.x86_64
kubelet-1.21.2-0.x86_64
kubernetes-cni-0.8.7-0.x86_64

$ rpm -ql kubernetes-cni-0.8.7-0
/opt/cni
/opt/cni/bin
/opt/cni/bin/bandwidth
/opt/cni/bin/bridge
/opt/cni/bin/dhcp
/opt/cni/bin/firewall
/opt/cni/bin/flannel
/opt/cni/bin/host-device
/opt/cni/bin/host-local
/opt/cni/bin/ipvlan
/opt/cni/bin/loopback
/opt/cni/bin/macvlan
/opt/cni/bin/portmap
/opt/cni/bin/ptp
/opt/cni/bin/sbr
/opt/cni/bin/static
/opt/cni/bin/tuning
/opt/cni/bin/vlan

Kubernetes 要使用 CNI,需要在 kubelet 启动时配置启动参数 --network-plugin=cni (默认配置,可使用 systemctl status kubelet -l 查看启动参数)。

kubelet 从 --cni-config-dir (默认为 /etc/cni/net.d/ )中读取网络插件的配置文件,并使用该文件中的 CNI 配置来配置每个 Pod 网络。如果该目录 ( /etc/cni/net.d/ )中有多个配置文件,则使用文件名字典序列中的第一个文件。

CNI 插件的二进制文件放置的目录是通过 kubelet 的 --cni-bin-dir 参数指定,默认为 /opt/cni/bin/

阅读全文 »

环境信息

  • etcd v3.5

etcd 官网安装指南
Github 下载链接

wget https://github.com/etcd-io/etcd/releases/download/v3.5.9/etcd-v3.5.9-linux-amd64.tar.gz

tar -xf etcd-v3.5.9-linux-amd64.tar.gz -C /usr/local/

ln -s /usr/local/etcd-v3.5.9-linux-amd64/etcd /usr/bin/
ln -s /usr/local/etcd-v3.5.9-linux-amd64/etcdctl /usr/bin/
ln -s /usr/local/etcd-v3.5.9-linux-amd64/etcdutl /usr/bin/

启动 etcd

# etcd
{"level":"warn","ts":"2023-10-05T02:16:52.853273Z","caller":"embed/config.go:673","msg":"Running http and grpc server on single port. This is not recommended for production."}
{"level":"info","ts":"2023-10-05T02:16:52.853914Z","caller":"etcdmain/etcd.go:73","msg":"Running: ","args":["etcd"]}
{"level":"warn","ts":"2023-10-05T02:16:52.853947Z","caller":"etcdmain/etcd.go:105","msg":"'data-dir' was empty; using default","data-dir":"default.etcd"}
{"level":"warn","ts":"2023-10-05T02:16:52.853994Z","caller":"embed/config.go:673","msg":"Running http and grpc server on single port. This is not recommended for production."}
{"level":"info","ts":"2023-10-05T02:16:52.854009Z","caller":"embed/etcd.go:127","msg":"configuring peer listeners","listen-peer-urls":["http://localhost:2380"]}
...

常用管理命令

etcd

查看版本信息

# etcd --version
etcd Version: 3.5.3
Git SHA: 0452feec7
Go Version: go1.16.15
Go OS/Arch: linux/amd64

创建集群

etcd 创建集群涉及参数说明

name 说明 命令行参数
name 每个集群成员的唯一名称 --name=etcd0
initial-advertise-peer-urls 群成员广播给集群其他成员(用于连接本节点)的 URL
默认为 http://IP:2380
--initial-advertise-peer-urls=http://10.0.0.10:2380
listen-peer-urls 在这些(一个或多个) URL 上监听其他集群成员的连接请求
通信包括了集群管理任务、数据同步和心跳检测等
http://10.0.0.10:2380,http://127.0.0.1:2380
listen-client-urls 该成员监听客户端连接的 URL。 默认端口 2379 --listen-client-urls=http://10.0.0.10:2379,http://127.0.0.1:2379
advertise-client-urls 该成员广播给客户端的 URL --advertise-client-urls=http://10.0.0.10:2379
initial-cluster 所有 etcd 成员的初始列表 --initial-cluster=etcd0=http://10.0.0.10:2380,etcd1=http://10.0.0.11:2380,etcd2=http://10.0.0.12:2380
data-dir etcd 数据的存储目录。 --data-dir=/var/lib/etcd
initial-cluster-token 初始集群的唯一标识符,用于区分不同的 etcd 集群 --initial-cluster-token=my-etcd-token
initial-cluster-state 初始集群状态,可以是 newexisting
通常在引导新集群时使用 new ,而在添加或删除成员时使用 existing
--initial-cluster-state=new
quota-backend-bytes etcd 的后端数据库大小的硬限制,默认是 2GB --quota-backend-bytes=3000000000
cert-file
key-file
用于 HTTPS 的证书和私钥 --cert-file=/etc/kubernetes/pki/etcd/server.crt
--key-file=/etc/kubernetes/pki/etcd/server.key
trusted-ca-file 客户端和对等体的验证所需的 CA 证书 --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
client-cert-auth 启用客户端证书验证,默认为 false --client-cert-auth

listen-peer-urlsinitial-advertise-peer-urls 的区别说明:

  • listen-peer-urls

    这个参数指定了 etcd 成员应该在哪些地址和端口上监听来自其他 etcd 成员的请求(数据同步、领导选举、集群更改等相关)

    主要用途是定义哪个网络接口和端口号应该被 etcd 服务绑定,以便它可以接收来自其他成员的连接

  • initial-advertise-peer-urls

    这个参数告诉 etcd 该如何 通告自己 给集群中的其他成员。这是其他集群成员用来联系此 etcd 成员的地址。

    主要用途是 当新成员加入集群时,它需要通知其他成员自己的存在,以及如何与自己通信 ,因此它必须是个其他节点可达的 Endpoints,如 http://0.0.0.0:2380 就不行。

    listen-client-urlsadvertise-client-urls 的区别同理

示例环境说明

主机 IP 角色
etcd1 172.17.0.2/16 etcd node
etcd2 172.17.0.3/16 etcd node
etcd3 172.17.0.4/16 etcd node

分别在 3 个节点上执行以下 3 条命令,创建集群

etcd1 执行命令:

etcd --data-dir=data.etcd --name etcd1 \
--initial-advertise-peer-urls http://172.17.0.2:2380 --listen-peer-urls http://172.17.0.2:2380,http://127.0.0.1:2380 \
--advertise-client-urls http://172.17.0.2:2379 --listen-client-urls http://172.17.0.2:2379,http://127.0.0.1:2379 \
--initial-cluster etcd1=http://172.17.0.2:2380,etcd2=http://172.17.0.3:2380,etcd3=http://172.17.0.4:2380 \
--initial-cluster-state new --initial-cluster-token etcd-cluster

etcd2 执行命令:

etcd --data-dir=data.etcd --name etcd2 \
--initial-advertise-peer-urls http://172.17.0.3:2380 --listen-peer-urls http://172.17.0.3:2380,http://127.0.0.1:2380 \
--advertise-client-urls http://172.17.0.3:2379 --listen-client-urls http://172.17.0.3:2379,http://127.0.0.1:2379 \
--initial-cluster etcd1=http://172.17.0.2:2380,etcd2=http://172.17.0.3:2380,etcd3=http://172.17.0.4:2380 \
--initial-cluster-state new --initial-cluster-token etcd-cluster

etcd3 执行命令:

etcd --data-dir=data.etcd --name etcd3 \
--initial-advertise-peer-urls http://172.17.0.4:2380 --listen-peer-urls http://172.17.0.4:2380,http://127.0.0.1:2380 \
--advertise-client-urls http://172.17.0.4:2379 --listen-client-urls http://172.17.0.4:2379,http://127.0.0.1:2379 \
--initial-cluster etcd1=http://172.17.0.2:2380,etcd2=http://172.17.0.3:2380,etcd3=http://172.17.0.4:2380 \
--initial-cluster-state new --initial-cluster-token etcd-cluster

检查节点健康状态

# ENDPOINT=http://172.17.0.3:2380,http://172.17.0.2:2380,http://172.17.0.4:2380

# etcdctl endpoint status --endpoints=$ENDPOINT -w table
+------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| http://172.17.0.3:2380 | 660aa483274d103a | 3.5.9 | 20 kB | false | false | 2 | 9 | 9 | |
| http://172.17.0.2:2380 | 69015be41c714f32 | 3.5.9 | 20 kB | true | false | 2 | 9 | 9 | |
| http://172.17.0.4:2380 | ad0233873e2a0054 | 3.5.9 | 20 kB | false | false | 2 | 9 | 9 | |
+------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

# etcdctl endpoint health --endpoints=$ENDPOINT -w table
+------------------------+--------+------------+-------+
| ENDPOINT | HEALTH | TOOK | ERROR |
+------------------------+--------+------------+-------+
| http://172.17.0.2:2380 | true | 2.44553ms | |
| http://172.17.0.3:2380 | true | 2.804559ms | |
| http://172.17.0.4:2380 | true | 2.580515ms | |
+------------------------+--------+------------+-------+

etcdctl

查看版本信息

# etcdctl version
etcdctl version: 3.5.3
API version: 3.5

etcd 集群管理

查看 etcd 集群成员列表

Kubernetes 中查看 etcd 集群成员列表使用如下命令

# kubectl exec -n kube-system -it etcd-k8s-master1 -- sh -c "ETCDCTL_API=3 etcdctl member list --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key"
3c087bf12db7a0f, started, k8s-master2, https://172.31.30.115:2380, https://172.31.30.115:2379, false
92e04392f8ad0046, started, k8s-master3, https://172.31.29.250:2380, https://172.31.29.250:2379, false
c71592552b3eb9bb, started, k8s-master1, https://172.31.30.123:2380, https://172.31.30.123:2379, false

指定输出格式为 table

# etcdctl member list --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key --write-out=table
+------------------+---------+-------------+----------------------------+----------------------------+------------+
| ID | STATUS | NAME | PEER ADDRS | CLIENT ADDRS | IS LEARNER |
+------------------+---------+-------------+----------------------------+----------------------------+------------+
| 3c087bf12db7a0f | started | k8s-master2 | https://172.31.30.115:2380 | https://172.31.30.115:2379 | false |
| 92e04392f8ad0046 | started | k8s-master3 | https://172.31.29.250:2380 | https://172.31.29.250:2379 | false |
| c71592552b3eb9bb | started | k8s-master1 | https://172.31.30.123:2380 | https://172.31.30.123:2379 | false |
+------------------+---------+-------------+----------------------------+----------------------------+------------+

输出内容说明如下:

  • 3c087bf12db7a0f : 集群中每一个成员的唯一 ID。
  • started : 集群成员的当前状态。 started 表示活动的。
  • k8s-master2 : etcd 集群成员的名字,通常与其主机名或节点名相对应
  • https://172.31.30.115:2380 : Peer URLs ,其他 etcd 成员用于与该成员通信的 URL。默认为 本地 IP 的 2380 端口
  • https://172.31.30.123:2379 : Client URLs ,客户端用于与 etcd 成员通信的 URL。默认为 本地 IP 的 2379 端口
  • Is Learner : 表示该成员是否是一个 learner 。Learner 是 etcd 的一个新功能,允许一个成员作为非投票成员加入集群,直到它准备好成为一个完全参与的成员。 false 表示它们都不是 learners

检查集群状态

检查单个节点的集群配置状态

# etcdctl --write-out=table endpoint status --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key
+----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| 127.0.0.1:2379 | c71592552b3eb9bb | 3.5.3 | 106 MB | false | false | 16 | 228198001 | 228198001 | |
+----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

查看所有节点的集群配置状态

# ENDPOINTS=https://172.31.30.115:2379,https://172.31.29.250:2379,https://172.31.30.123:2379

# etcdctl --write-out=table --endpoints=$ENDPOINTS endpoint status
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| ENDPOINT | ID | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| https://172.31.30.115:2379 | 3c087bf12db7a0f | 3.5.3 | 106 MB | true | false | 16 | 228199920 | 228199920 | |
| https://172.31.29.250:2379 | 92e04392f8ad0046 | 3.5.3 | 106 MB | false | false | 16 | 228199920 | 228199920 | |
| https://172.31.30.123:2379 | c71592552b3eb9bb | 3.5.3 | 106 MB | false | false | 16 | 228199920 | 228199920 | |
+----------------------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

# etcdctl --write-out=table --endpoints=$ENDPOINTS endpoint health
+----------------------------+--------+------------+-------+
| ENDPOINT | HEALTH | TOOK | ERROR |
+----------------------------+--------+------------+-------+
| https://172.31.30.115:2379 | true | 7.927976ms | |
| https://172.31.30.123:2379 | true | 8.011055ms | |
| https://172.31.29.250:2379 | true | 8.349179ms | |
+----------------------------+--------+------------+-------+
阅读全文 »

适用以下版本

  • Centos 7 内核升级
  • Centos 8 或 Rocky Linux 8 内核升级

环境息息

  • Centos7 3.10.0-1062.9.1.el7.x86_64
  • Rocky Linux 8

升级步骤

安装 centos-kernel

如果是 Centos 7 ,参考以下命令安装 centos-kernel

elrepo-kernel 中已经没有 Centos 7 相关的内核安装包

yum install centos-release

安装 elrepo 源

如果是 Centos 8 或 Rocky Linux 8,参考以下命令安装 elrepo

# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# rpm --import https://www.elrepo.org/RPM-GPG-KEY-v2-elrepo.org

# yum install https://www.elrepo.org/elrepo-release-8.el8.elrepo.noarch.rpm

# yum --disablerepo="*" --enablerepo="elrepo-kernel" list available
Last metadata expiration check: 0:00:14 ago on Fri 28 Feb 2025 11:42:09 AM HKT.
Available Packages
bpftool.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-core.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-devel.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-doc.noarch 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-headers.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-modules.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-modules-extra.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-tools.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-tools-libs.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-lt-tools-libs-devel.x86_64 5.4.290-1.el8.elrepo elrepo-kernel
kernel-ml.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-core.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-devel.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-doc.noarch 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-headers.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-modules.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-modules-extra.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-tools.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-tools-libs.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
kernel-ml-tools-libs-devel.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
perf.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
python3-perf.x86_64 6.13.5-1.el8.elrepo elrepo-kernel
阅读全文 »

strace 命令示例,详细使用说明请参考 man strace

# strace ls
execve("/usr/bin/ls", ["ls"], 0x7ffe75aa9350 /* 12 vars */) = 0
brk(NULL) = 0x556c51ed9000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffc20fecaf0) = -1 EINVAL (Invalid argument)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f2b1b0a2000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=34211, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 34211, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f2b1b099000
close(3) = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0\0\0\0\0\0\0\0"..., 832) = 832
...

strace 跟踪输出中包含

  • Syscall Name ,如 execveopenat
  • Arguments , 系统调用使用的参数,如 "/usr/bin/ls"AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC
  • Return Value ,系统调用的返回值以及简要说明信息, 如 = -1 EINVAL (Invalid argument)-1 ENOENT (No such file or directory)= 0

strace 命令常用选项

选项 说明 示例
-o filename
--output=filename
将跟踪内容写入指定文件而不是 STDOUT(默认值)
-p pid
--attach=pid
追踪 PIDs 对应的进程, Ctrl + C 结束追踪。 支持 , 、 空格 ( ) 、 TAB 键( \t )分割的多个 PID
-e expr 追踪表达式匹配的系统调用,表达式语法请参考 man strace
-c
--summary-only
仅输出调用的统计数据,不输出常规跟踪内容
-C
--summary
输出常规跟踪内容后,输出统计信息

环境信息

  • Centos 7
  • containerd.io-1.4.13-3

containerd 相关配置

默认配置文件

containerd 服务默认配置文件为 /etc/containerd/config.toml

/etc/containerd/config.toml
#root = "/var/lib/containerd"
#state = "/run/containerd"
#subreaper = true
#oom_score = 0

Containerd 有两个不同的存储路径,一个用来保存持久化数据,一个用来保存运行时状态。 [1]

/etc/containerd/config.toml
#root = "/var/lib/containerd"
#state = "/run/containerd"
  • root - 用来保存持久化数据,包括 Snapshots, Content, Metadata 以及各种插件的数据。每一个插件都有自己单独的目录,Containerd 本身不存储任何数据,它的所有功能都来自于已加载的插件。
  • state - 用来保存临时数据,包括 socketspid挂载点运行时状态 以及不需要持久化保存的插件数据。
/etc/containerd/config.toml
#oom_score = 0

Containerd 是容器的守护者,一旦发生内存不足的情况,理想的情况应该是先杀死容器,而不是杀死 Containerd。所以需要调整 Containerd 的 OOM 权重,减少其被 OOM Kill 的几率。 oom_score 其取值范围为 -10001000 ,如果将该值设置为 -1000 ,则进程永远不会被杀死,建议 Containerd 将该值设置为 -9990 之间。如果作为 Kubernetes 的 Worker 节点,可以考虑设置为 -999

containerd 服务配置文件

默认的 containerd 服务的配置为 /usr/lib/systemd/system/containerd.service

/usr/lib/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target

[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/bin/containerd

Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5

LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576

TasksMax=infinity
OOMScoreAdjust=-999

[Install]
WantedBy=multi-user.target

  • Delegate - 这个选项允许 Containerd 以及运行时自己管理自己创建的容器的 cgroups。如果不设置这个选项, systemd 就会将进程移到自己的 cgroups 中,从而导致 Containerd 无法正确获取容器的资源使用情况。

  • KillMode - 这个选项用来处理 Containerd 进程被杀死的方式。默认情况下, systemd 会在进程的 cgroup 中查找并杀死 Containerd 的所有子进程,这肯定不是我们想要的。 KillMode 字段可以设置的值如下:

    • control-group -(默认值)当前控制组里面的所有子进程,都会被杀掉
    • process - 只杀主进程。
    • mixed - 主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号
    • none - 没有进程会被杀掉,只是执行服务的 stop 命令。

    需要将 KillMode 的值设置为 process ,这样可以确保升级或重启 Containerd 时不杀死现有的容器。

Containerd 常用配置

Containerd 默认配置文件为 /etc/containerd/config.toml ,未在配置文件中配置的则使用默认配置,为了方便修改,可以使用以下命令将默认配置写入配置文件中

/etc/containerd/config.toml
containerd config default | sudo tee /etc/containerd/config.toml

在作为 Kubernetes 的 CRI 时,需要修改以下配置:

  • 启用 CRI 功能 。Containerd 默认禁用了 CRI 功能( disabled_plugins = ['cri'] ),要启用 cri ,将其注释或删除

  • 配置 cgroup v2 Kubernetes 的很多功能需要 cgroup v2 支持,Kubernetes 节点通常使用 cgroup v2 ,要配置 containerd 使用 cgroup v2 ,修改配置文件的 plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options 部分,将 SystemdCgroup 配置为 true 后重启 containerd 服务

    /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

客户端工具 ctr 使用

ctr 管理镜像

镜像下载

ctr image pull docker.io/library/nginx:alpine

列出本地镜像

$ ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:455c39afebd4d98ef26dd70284aa86e6810b0485af5f4f222b19b89758cabf1e 9.8 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -

将镜像挂载到本地目录

$ ctr image mount docker.io/library/nginx:alpine /mnt

$ ls /mnt
bin docker-entrypoint.d etc lib mnt proc run srv tmp var
dev docker-entrypoint.sh home media opt root sbin sys usr

卸载已挂载的镜像

ctr image unmount /mnt

ctr 管理 容器

创建容器

ctr container create docker.io/library/nginx:alpine nginx

容器创建后,并没有开始运行,只是分配了容器运行所需的资源及配置的数据结构,这意味着 namespacesrootfs 和容器的配置都已经初始化成功了,只是用户进程(这里是 nginx )还没有启动,容器(进程)状态的变化由 Task 对象实现,通过命令 ctr task 来管理。

启动 ctr container create 创建的容器

ctr task start nginx

以上命令启动之前创建的容器 nginx ,未指定其他参数时,容器中的进程在系统前台运行,如需后台运行,可以使用选项 -d

ctr task start nginx -d

也可以直接使用 run 命令,创建并启动容器

ctr run --rm -d docker.io/library/nginx:alpine nginx1

列出容器

ctr container ls

查看容器中进程的状态

$ ctr task ls
TASK PID STATUS
nginx1 5495 RUNNING

查看容器中运行的所有的进程

$ ctr task ps nginx1
PID INFO
5495 -
5531 -
5532 -
5533 -
5534 -

这里的 PID 是宿主机看到的 PID,不是容器中看到的 PID。

查看容器详细信息

ctr container info nginx

删除容器

停止/删除容器中的进程

ctr task delete nginx -f

ctr task pause nginx

以上命令 删除/停止容器中的进程,但是并不删除容器 ,执行以上命令后再执行以下命令,可删除容器

ctr container delete nginx

ctr 没有 stop 容器的功能,只能暂停或者杀死容器。

进入容器

ctr task exec -t --exec-id 1 nginx1 sh

执行 ctr task exec 进入容器,必须制定 --exec-id ,值可以随便指定。

namespace 管理

Containerd 相比于 Docker ,多了 Namespace 的概念,使用以下命令,查看所有的 Namespace

$ ctr ns ls
NAME LABELS
default
moby

docker 默认使用 moby 的 Namespace,要使用 ctr 命令查看 docker 创建的容器,需要使用选项 -n moby 指定命名空间,否则 ctr 默认使用 default 命名空间,无法看到 moby 命名空间中的资源

ctr -n moby container ls
CONTAINER IMAGE RUNTIME
17b16c3699cdb88a1ff80d8a7c84724eff393c42186775b58418c90bd178600f - io.containerd.runtime.v1.linux
27fc19226baa91251d63a375a7b1309122334cfb5ceb39aeb67ab1701b708464 - io.containerd.runtime.v1.linux

Kubernetes 默认使用 k8s.io 命名空间

ctr 没有配置或者环境变量可以来配置默认的 Namespace,在 Kubernetes 场景中,可以使用 alias 命令配置 ctr ,使其自动指向 k8s.io 的 Namespace

alias ctr='ctr -n k8s.io'

nerdctl

nerdctl 是为 Containerd 开发的完全兼容 Docker 命令行的工具,它可以使用和 docker 命令一样的语法来操作 containerd 中的容器。

nerdctl 官方说明文档

如果要使用 nerdctl 调试 Kubernetes 环境中的容器,需要指定 Namespace,示例如下:

# nerdctl --namespace k8s.io ps -a

如果是在 Kubernetes 环境中使用,为方便起见,可以添加环境变量:

# alias nerdctl='nerdctl --namespace k8s.io'

# nerdctl ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4de4c59a8913 registry.k8s.io/kube-controller-manager:v1.32.0 "kube-controller-man…" 2 days ago Up k8s://kube-system/kube-controller-manager-k8s-master/kube-controller-manager
6a9f17dffdb5 registry.k8s.io/pause:3.6 "/pause" 2 days ago Up k8s://kube-system/kube-controller-manager-k8s-master
3ae8ed830b63 registry.k8s.io/kube-scheduler:v1.32.0 "kube-scheduler --au…" 2 days ago Up k8s://kube-system/kube-scheduler-k8s-master/kube-scheduler
0cb15e8f5ac7 registry.k8s.io/pause:3.6 "/pause" 2 days ago Up k8s://kube-system/kube-scheduler-k8s-master
60ea2cfc01c8 registry.k8s.io/pause:3.6 "/pause" 2 days ago Up k8s://kube-system/kube-apiserver-k8s-master
eaf781314f4a registry.k8s.io/pause:3.6 "/pause" 2 days ago Up k8s://kube-system/etcd-k8s-master

脚注

环境信息

  • Centos7 5.4.212-1
  • Docker 20.10.18
  • containerd.io-1.6.8
  • kubectl-1.25.0
  • kubeadm-1.25.0
  • kubelet-1.25.0

POD 状态异常

CrashLoopBackOff

错误场景

Pod 状态显示 CrashLoopBackOff

$ kubectl get pods
NAME READY STATUS RESTARTS AGE
test-centos7-7cc5dc6987-jz486 0/1 CrashLoopBackOff 8 (111s ago) 17m

查看 Pod 详细信息

$ kubectl describe pod test-centos7-7cc5dc6987-jz486
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 18m default-scheduler Successfully assigned default/test-centos7-7cc5dc6987-jz486 to ops-kubernetes3
Normal Pulled 16m (x5 over 18m) kubelet Container image "centos:centos7.9.2009" already present on machine
Normal Created 16m (x5 over 18m) kubelet Created container centos7
Normal Started 16m (x5 over 18m) kubelet Started container centos7
Warning BackOff 3m3s (x71 over 18m) kubelet Back-off restarting failed container

结果显示, ReasonBackOffMessage 显示 Back-off restarting failed container

可能原因

Back-off restarting failed container 的原因,通常是因为,容器内 PID 为 1 的进程退出导致(通常用户在构建镜像执行 CMD 时,启动的程序,均是 PID 为 1)[1]

容器进程退出(命令执行结束或者进程异常结束),则容器生命周期结束。kubernetes 控制器检查到容器退出,会持续重启容器。针对此种情况,需要检查镜像,是否不存在常驻进程,或者常驻进程异常。

针对此种情况,可以单独使用 docker 客户端部署镜像,查看镜像的运行情况,如果部署后,容器中的进程立马结束或退出,则容器也会随之结束。

定位中也可以使用 kubectl describe pod 命令检查 Pod 的退出状态码。Kubernetes 中的 Pod ExitCode 状态码是容器退出时返回的退出状态码,这个状态码通常用来指示容器的执行结果,以便 Kubernetes 和相关工具可以根据它来采取后续的操作。以下是一些常见的 ExitCode 状态码说明:

  • ExitCode 0 : 这表示容器正常退出,没有错误。这通常是期望的结果。
  • ExitCode 1 : 通常表示容器以非正常方式退出,可能是由于应用程序内部错误或异常导致的。通常是容器中 pid 为 1 的进程错误而失败
  • ExitCode 非零 : 任何非零的状态码都表示容器退出时发生了错误。ExitCode 的具体值通常是自定义的,容器内的应用程序可以根据需要返回不同的状态码来表示不同的错误情况。你需要查看容器内应用程序的文档或日志来了解具体的含义。
  • ExitCode 137 : 通常表示容器因为被操作系统终止(例如, OOM-killer )而非正常退出。这可能是由于内存不足等资源问题导致的。
  • ExitCode 139 : 通常表示容器因为接收到了一个信号而非正常退出。这个信号通常是 SIGSEGV (段错误),表示应用程序试图访问无效的内存。
  • ExitCode 143 : 通常表示容器因为接收到了 SIGTERM 信号而正常退出。这是 Kubernetes 在删除 Pod 时发送的信号,容器应该在接收到该信号后做一些清理工作然后退出。
  • ExitCode 130 : 通常表示容器因为接收到了 SIGINT 信号而正常退出。这是当用户在命令行中按下 Ctrl+C 时发送的信号。
  • ExitCode 255 :通常表示未知错误,或者容器无法启动。这个状态码通常是容器运行时的问题,比如容器镜像不存在或者启动命令有问题。
阅读全文 »

PAT 认证

Github 为了安全考虑,在 Shell 中禁止使用帐号名称登陆,提供了更为安全的 PAT(Personal Access Token),PAT 的权限和创建它的用户权限相同,并且可以使用 Fine-grained personal access tokens 实现更细粒度的权限控制

参考以下步骤创建 PAT:

  1. 登录 GitHub。

  2. 点击右上角头像,进入 Settings

  3. 在左侧菜单中选择 Developer settings

  4. 选择 Personal access tokens ,然后点击 Generate new token

  5. 生成令牌并复制。

gh

Github 命令行工具 gh 常用操作

Login

参考以下示例使用命令 gh auth login 登陆 Github

# gh auth login
? Where do you use GitHub? GitHub.com
? What is your preferred protocol for Git operations on this host? HTTPS
? Authenticate Git with your GitHub credentials? Yes
? How would you like to authenticate GitHub CLI? Paste an authentication token
Tip: you can generate a Personal Access Token here https://github.com/settings/tokens
The minimum required scopes are 'repo', 'read:org', 'workflow'.
? Paste your authentication token: *********************************************************************************************
- gh config set -h github.com git_protocol https
✓ Configured git protocol
! Authentication credentials saved in plain text
✓ Logged in as user1

查看 Github 认证状态( gh auth status

# gh auth status
github.com
✓ Logged in to github.com account user1 (/root/.config/gh/hosts.yml)
- Active account: true
- Git operations protocol: https
- Token: github_pat_11BP5YWMA0XuC4iSW26eBN_***********************************************************

pull

参考以下示例使用命令 gh repo clone user1/resp1 clone 代码到本地

# gh repo clone user1/resp1
Cloning into 'resp1'...
remote: Enumerating objects: 27, done.
remote: Counting objects: 100% (27/27), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 27 (delta 12), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (27/27), 9.10 KiB | 9.10 MiB/s, done.
Resolving deltas: 100% (12/12), done.

如果报错: GraphQL: Resource not accessible by personal access token (repository.defaultBranchRef) ,则说明 PAT 权限不足。

环境信息

  • Centos 7

vim 配置

vim 启动时会读取 /etc/vimrc (全局配置) 和 ~/.vimrc (用户配置)

常用配置如下,使用 " 注释

/etc/vimrc
" 自动缩进 
set ai
set autoindent

" 保存历史命令数量
set history=50

" 右下角显示当前鼠标位置(行列数)
set ruler

" 鼠标位置所在行显示下划线
set cursorline

" 开启语法高亮
syntax on

" 高亮搜索结果
set hlsearch

" 搜索时不区分大小写
set ignorecase

" 将 tab 转换为空格
set expandtab

" tab 转换为4个空格
set tabstop=4

" 删除时,可以一次删除4个空格
set softtabstop=4

" 显示行数
set nu

" 禁用格式化指令。
set paste
阅读全文 »

环境信息

  • Centos 7 5.4.239-1

Linux 的 namespace 的作用是 隔离内核资 ,目前主要实现了以下 namespace

  • mount namespace - 文件系统挂载点
  • UTS namespace - 主机名
  • IPC namespace - POSIX 进程间通信消息队列
  • PID namespace - 进程 pid 数字空间
  • network namespace - network
  • user namespace - user ID 数字空间
  • cgroup - 资源使用控制
  • time - 隔离时钟(Clock)

其中,除了 network namespace ,其他 namespace 的操作需要使用 C 语言调用系统 API 实现。 network namespace 的增删改查功能已经集成到了 Linux 的 ip 工具集的 netns 子命令中

Linux 里面的 namespace 给处在其中的进程造成 2 个错觉:

  1. 它是系统里面唯一的进程
  2. 它独享系统的所有资源

默认情况下,Linux 里面的所有进程处在和宿主机相同的 namespace ,即初始 namespace 里,默认享有全局系统资源。

lsns 命令可以查看当前系统上存在哪些 Namespace

# lsns
NS TYPE NPROCS PID USER COMMAND
4026531834 time 251 1 root /lib/systemd/systemd --system --deserialize 52
4026531835 cgroup 224 1 root /lib/systemd/systemd --system --deserialize 52
4026531836 pid 224 1 root /lib/systemd/systemd --system --deserialize 52
4026531837 user 686 1 root /lib/systemd/systemd --system --deserialize 52
4026531838 uts 221 1 root /lib/systemd/systemd --system --deserialize 52
4026531839 ipc 224 1 root /lib/systemd/systemd --system --deserialize 52
4026531840 net 229 1 root /lib/systemd/systemd --system --deserialize 52
4026531841 mnt 213 1 root /lib/systemd/systemd --system --deserialize 52
4026531862 mnt 1 61 root kdevtmpfs
4026532219 mnt 1 1426338 root /lib/systemd/systemd-udevd
4026532220 uts 1 1426338 root /lib/systemd/systemd-udevd
4026532230 mnt 1 2124756 root /lib/systemd/systemd-logind
4026532231 uts 1 2124756 root /lib/systemd/systemd-logind
4026532232 mnt 1 1426274 systemd-timesync /lib/systemd/systemd-timesyncd
4026532233 mnt 1 1426257 root /usr/sbin/irqbalance --foreground
4026532326 mnt 1 2134793 root /usr/sbin/NetworkManager --no-daemon
4026532593 cgroup 7 937225 root python manage.py runserver 0.0.0.0:8080
4026532603 mnt 1 1416468 472 grafana server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:defau
4026532604 uts 1 1416468 472 grafana server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:defau
4026532605 ipc 1 1416468 472 grafana server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:defau
4026532606 pid 1 1416468 472 grafana server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:defau
4026532607 net 1 1416468 472 grafana server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:defau
4026532664 cgroup 1 1416468 472 grafana server --homepath=/usr/share/grafana --config=/etc/grafana/grafana.ini --packaging=docker cfg:defau
4026532665 mnt 1 1416534 1001 /opt/bitnami/blackbox-exporter/bin/blackbox_exporter --config.file=/etc/blackbox/blackbox.yml
4026532666 uts 1 1416534 1001 /opt/bitnami/blackbox-exporter/bin/blackbox_exporter --config.file=/etc/blackbox/blackbox.yml
4026532667 ipc 1 1416534 1001 /opt/bitnami/blackbox-exporter/bin/blackbox_exporter --config.file=/etc/blackbox/blackbox.yml
4026532668 pid 1 1416534 1001 /opt/bitnami/blackbox-exporter/bin/blackbox_exporter --config.file=/etc/blackbox/blackbox.yml
4026532669 net 1 1416534 1001 /opt/bitnami/blackbox-exporter/bin/blackbox_exporter --config.file=/etc/blackbox/blackbox.yml

想要查看某个进程都在哪些 namespace 中,可以找到进程 ID (PID),通过查看以下内容或者 namespace 信息

$ ps -elf | grep nginx
4 S root 32679 32659 0 80 0 - 2248 sigsus Apr07 ? 00:00:00 nginx: master process nginx -g daemon off;

$ ll /proc/32679/ns/
total 0
lrwxrwxrwx 1 root root 0 Apr 19 13:51 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Apr 19 13:51 ipc -> ipc:[4026534784]
lrwxrwxrwx 1 root root 0 Apr 19 13:51 mnt -> mnt:[4026534583]
lrwxrwxrwx 1 root root 0 Apr 19 13:51 net -> net:[4026534787]
lrwxrwxrwx 1 root root 0 Apr 19 13:51 pid -> pid:[4026534878]
lrwxrwxrwx 1 root root 0 Apr 19 13:51 pid_for_children -> pid:[4026534878]
lrwxrwxrwx 1 root root 0 Apr 19 13:51 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Apr 19 13:51 uts -> uts:[4026534877]

通过以上命令,可以看到 nginx 进程所属的 namespace,要查看系统初始 namespace ,可以查看 PID 为 1 的进程的 namespace 信息

$ ll /proc/1/ns/
total 0
lrwxrwxrwx 1 root root 0 Apr 19 13:53 cgroup -> cgroup:[4026531835]
lrwxrwxrwx 1 root root 0 Apr 19 13:53 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 Apr 19 13:53 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 Apr 19 13:53 net -> net:[4026531992]
lrwxrwxrwx 1 root root 0 Apr 19 13:53 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 19 13:53 pid_for_children -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 Apr 19 13:53 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 Apr 19 13:53 uts -> uts:[4026531838]

链接文件的内容的格式为 ns 类型: [inode number]。这里的 inode number 则用来标识一个 namespace,我们也可以把它理解为 namespace 的 ID。如果两个进程的某个 namespace 文件指向同一个链接文件,说明其相关资源在同一个 namespace 中。 [1]

脚注

环境信息

  • Centos 7 kernel 5.4.221

启动过程

systemd 管理的系统中,提供了工具 systemd-analyze 用于分析具体的启动过程,使用 systemd-analyze --help 查看使用帮助

检查系统启动时间

使用 systemd-analyze 命令会显示系统启动所用的时间,等同于 systemd-analyze time

# systemd-analyze 
Startup finished in 1.830s (kernel) + 36.827s (userspace) = 38.657s
graphical.target reached after 12.604s in userspace

systemd-analyze blame 列出系统上各个 Unit 启动的时间

# systemd-analyze blame
6.414s wazuh-agent.service
3.161s dracut-initqueue.service
2.473s network.service
1.004s watchdog.service
...
45ms sysstat.service
14ms plymouth-switch-root.service
14ms systemd-journald.service
4ms systemd-logind.service
3ms sys-kernel-config.mount
3ms initrd-udevadm-cleanup-db.service
3ms systemd-random-seed.service
2ms google-shutdown-scripts.service

列出系统各个 Unit 启动消耗的时间

# systemd-analyze critical-chain
The time when unit became active or started is printed after the "@" character.
The time the unit took to start is printed after the "+" character.

graphical.target @12.604s
└─multi-user.target @12.601s
└─skylight-agent.service @36.639s
└─network.target @9.073s
└─NetworkManager.service @8.795s +275ms
└─dbus.service @8.788s
└─basic.target @8.774s
└─sockets.target @8.772s
└─snapd.socket @8.766s +5ms
└─sysinit.target @8.669s
└─cloud-init.service @6.850s +1.811s
└─systemd-networkd-wait-online.service @4.970s +1.871s
└─systemd-networkd.service @4.864s +91ms
└─network-pre.target @4.850s
└─cloud-init-local.service @3.228s +1.620s
└─systemd-remount-fs.service @1.113s +93ms
└─systemd-fsck-root.service @1.030s +69ms
└─systemd-journald.socket @853ms
└─-.mount @692ms
└─-.slice @692ms

查看内存信息

内存相关概念说明:

  • VSS ,Virtual Set Size , VIRT - 虚拟耗用内存(包含共享库占用的内存), 通常 VIRT 是系统承诺分配给应用的内存,不是实际使用的内存
  • RSS , Resident Set Size , RES - 实际使用物理内存(包含共享库占用的内存)
  • PSS , Proportional Set Size - 实际使用的物理内存(比例分配共享库占用的内存)。 top 命令中的 SHR 列展示的就是共享库按比例分配给进程的内存
  • USS , Unique Set Size - 进程独自占用的物理内存(不包含共享库占用的内存)

系统内存使用量统计

free

$ free -h
total used free shared buff/cache available
Mem: 15Gi 7.8Gi 707Mi 449Mi 7.0Gi 6.9Gi
Swap: 30Gi 1.0Gi 29Gi

ps

例如查看使用内存排名前十的进程:

ps aux | sort -k4,4nr | head -n 10

sar 命令

使用 sar 命令检查系统上的内存及 Swap 使用情况

查看某个进程使用的内存量

比如检查 docker 使用的内存量,首先通过 ps 命令查询到 docker 的 PID 信息

$ ps -elf | grep docker
4 S root 1243 1 4 80 0 - 1067527 futex_ Jan03 ? 15:14:45 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

例如此处的 docker 进程的 PID 为 1243

  • 使用 top 命令动态查看 docker 使用的内存信息

    $ top -p 1243
    top - 11:47:40 up 14 days, 2:09, 3 users, load average: 0.65, 1.42, 1.70
    Tasks: 1 total, 0 running, 1 sleeping, 0 stopped, 0 zombie
    %Cpu(s): 1.0 us, 0.6 sy, 0.0 ni, 98.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
    KiB Mem : 32068748 total, 2494500 free, 18536188 used, 11038060 buff/cache
    KiB Swap: 0 total, 0 free, 0 used. 9586340 avail Mem

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    1243 root 20 0 4270108 1.4g 53956 S 1.0 4.6 914:55.80 dockerd
  • 使用 ps aux 命令查看内存使用量

    $ ps aux | grep 1243
    root 1243 4.5 4.6 4270108 1486460 ? Ssl Jan03 914:57 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

    输出结果中

    • 第 3、4 列 ( 4.5 4.6 ) 分别表示 cpu 使用率内存使用率
    • 第 5、6 列 ( 4270108 1486460 ) 分别表示 虚拟内存使用量物理内存使用量 ,单位为 k
  • 通过进程的 status 文件查看内存使用

    $ cat /proc/1243/status
    Name: dockerd
    Umask: 0022
    State: S (sleeping)
    Pid: 1243
    PPid: 1
    VmPeak: 4270364 kB
    VmSize: 4270108 kB
    VmLck: 0 kB
    VmPin: 0 kB
    VmHWM: 1562204 kB
    VmRSS: 1492340 kB
    ...

    其中, VmRSS 为进程使用的物理内存

  • 使用 pmap 命令查看进程使用的内存信息

    pmap -x 1243
    pmap -p 1243
  • 使用 pidstat 命令查看进程使用的内存信息

    # pidstat -r -t -p 1424681 1 1
    Linux 6.8.0-1017-aws (U-3TSDMAL9IVFAQ) 11/26/2024 _x86_64_ (4 CPU)

    04:15:40 PM UID TGID TID minflt/s majflt/s VSZ RSS %MEM Command
    04:15:41 PM 408001114 1424681 - 0.00 0.00 34656400 256620 1.59 chrome
    04:15:41 PM 408001114 - 1424681 0.00 0.00 34656400 256620 1.59 |__chrome
    04:15:41 PM 408001114 - 1424696 0.00 0.00 34656400 256620 1.59 |__sandbox_ipc_thr
    04:15:41 PM 408001114 - 1424702 0.00 0.00 34656400 256620 1.59 |__chrome
    04:15:41 PM 408001114 - 1424703 0.00 0.00 34656400 256620 1.59 |__HangWatcher
    04:15:41 PM 408001114 - 1424704 0.00 0.00 34656400 256620 1.59 |__ThreadPoolServi
    04:15:41 PM 408001114 - 1424705 0.00 0.00 34656400 256620 1.59 |__ThreadPoolForeg
    04:15:41 PM 408001114 - 1424706 0.00 0.00 34656400 256620 1.59 |__ThreadPoolForeg

阅读全文 »

环境信息

  • Centos 7

sudo 可以配置适当的权限授予普通用户,使普通用户执行 root 用户才能执行的操作

配置 sudo 权限的主要配置文件为 /etc/sudoers/etc/sudoers 是一个只读文件,不能直接使用 vim 等编辑器来编辑,要修改此文件,需要以 root 用户身份使用 visudo 命令来修改。

主要配置文件内容如下

/etc/sudoers
## Allow root to run any commands anywhere
root ALL=(ALL) ALL

%wheel ALL=(ALL) NOPASSWD: ALL

各列值含义说明:

  • root 第一列为用户名,如 rootusers%wheel% 开头表示这是一个组,而不是用户
  • ALL=(ALL) 第二列等号左边的 ALL 表示允许从任何主机登录当前的用户账户;等号右边的 ALL 表示第一列的用户可以切换成系统中任何一个其它用户(如: su users );
  • ALL 第三列表示第一列的用户能下达的命令, ALL 表示可以下达任何命令。 NOPASSWD: ALL 意味着成员可以执行指定的命令而无需输入密码。

当我们以普通用户身份(以 test 为例)登录,在使用 sudo 命令时报出如下信息:

test is not in the sudoers file. This incident will be reported.

则说明该用户没有在 /etc/sudoers 文件中进行配置,因此无法使用 sudo 命令

AWS 的 Centos 镜像部署后的虚拟机默认使用 centos 用户登陆,登陆后即可执行 sudo su - 切换到 root 用户,此配置由 /etc/sudoers.d/90-cloud-init-users 配置,内容如下:

/etc/sudoers.d/90-cloud-init-users
# cat /etc/sudoers.d/90-cloud-init-users
# Created by cloud-init v. 19.4 on Mon, 31 Oct 2022 07:58:58 +0000

# User rules for centos
centos ALL=(ALL) NOPASSWD:ALL

若要禁止此行为,删除此文件即可。

使用示例

限制特定用户只能执行指定目录下的脚本

visudo 中,你可以使用 Cmnd_Alias 限制用户只能执行特定目录下的脚本。假设你想让用户 centos 只能执行 /usr/local/scripts/ 目录下的脚本,可以按照以下方式配置:

visudo
Cmnd_Alias ALLOWED_SCRIPTS = /usr/local/scripts/*

centos ALL=(ALL) NOPASSWD: ALLOWED_SCRIPTS

含义

  • Cmnd_Alias ALLOWED_SCRIPTS = /usr/local/scripts/*

    定义 ALLOWED_SCRIPTS ,表示 允许执行 /usr/local/scripts/ 目录下的所有脚本

  • qqc ALL=(ALL) NOPASSWD: ALLOWED_SCRIPTS

    允许 centos 用户以 sudo 执行 ALLOWED_SCRIPTS 目录下的所有脚本,且无需输入密码。

切换到 centos 用户,并尝试执行:

sudo /usr/local/scripts/test.sh

成功执行 ,说明规则生效。

但是,如果 centos 用户 试图运行 /bin/bash/usr/bin/python ,或者访问其他路径

$ sudo /bin/bash
Sorry, user centos is not allowed to execute '/bin/bash' as root on this host.

如果希望 centos 用户可以查看自己可以运行的命令:

visudo
Cmnd_Alias ALLOWED_SCRIPTS = /usr/local/scripts/*
qqc ALL=(ALL) NOPASSWD: ALLOWED_SCRIPTS, /usr/bin/sudo -l

这样, centos 用户可以运行:

sudo -l

来查看自己被允许的 sudo 命令。

Memory 相关的术语说明

  • Main Memory - 也经常称为 Physical Memory ,计算机上的 Fast Data Storage Area。
  • Virtual Memory - Main Memory 的一个抽象层,他几乎有无限大的空间,Virtual Memory 不是 Main Memory
  • Resident Memory - 驻留(Reside)在 Main Memory 中的内存,相当于实际使用的物理内存(Main Memory/Physical Memory),如 top 命令中的 RESps aux 命令中的 RSS 就是指 Resident Memory.
  • Anonymous Memory - 未关联文件系统位置和路径的内存,通常指 Process Address Space 中的程序运行过程中的数据(Working Data),通常被称为 Heap
  • Address Space - 内存地址空间,内存地址相关的上下文(Context),包含程序(Processes)和内核(Kernel)使用的 Virtual Address Space
  • Segment - 用于标识 Virtual Memory 中的有特殊作用的一个区域,如可执行程序(Executable)或可写(Writable)的 Page
  • Instruction Text - CPU 指令(Instructions) 在内存中的引用地址,通常位于 Segment
  • OOM - Out Of Memory,当内核检测到系统可用内存不足时采取的动作
  • Page - OS 和 CPU 使用和分配内存的单位,早期大小一般为 4 或 8 Kbytes,现代化的 CPU 和 OS 通常支持 Multi Page Sizes
  • Page Fault - 通常在需要访问的内容不存在于 Virtual Memory 中时,系统产生一个中断,导致所需内容加载入内存
  • Paging - 当内存中的内容不再使用或内存空间不足时进行的在内存和 Storage Devices 中的内容交换,主要是为了空出内存供需要内存的进程使用
  • Swapping - Linux 中将不再使用或内存空间不足时,将部分内存中的内容 Paging 到 Swap Devices
  • Swap - Linux 中 Swapping 时,将内容转移到的目标,可能是 Storage Devices 上的一个区域,被称为 Physical Swap Device,或者是一个文件系统文件,称为 Swap File。

Memory 部分概念详细说明参考

MMU

Memory Management Unit(MMU) 负责虚拟内存地址(Virtual Memory Address)到物理内存地址(Physical Memory Address)的转换

Freeing Memory

当系统上可用内存低或不足时,系统会采用一系列的手段释放内存。主要包括下图所示方式

  • Free List
    不在使用中的 Pages 列表,也称为 Idle Memory,这部分内存可以被系统立即分配给需要的程序使用
  • Page Cache
    文件系统缓存(Filesystem Cache)。有个 swappiness 的参数可以配置系统是使用 Page Cache 还是 Swapping 来释放内存
  • Swapping
    通过内核进程 kswapd 实现 Paging Out 到 Swap Device 或者 File System-Based Swap File,这只有在系统上有 Swap 时才有用。
  • Reaping
    也被称为 Shrinking ,当系统可用内存小到一个临界值后,内核就会开始释放可以回收的内存
  • OOM Killer
    Out Of Memory Killer ,系统内存不足时,系统会使用 OOM Killer 机制来 kill 掉某个进程来释放内存。

在 Linux 中,当系统可用内存低于阈值( vm.min_free_kbytes )时,Page Out Daemon( kswapd ) 会启动 Page Scanning

进程的内存分层结构

进程的内存结构一般被分成多个 segment ,包括

  • Executable Text segment - 存放程序代码(the executable CPU Instructions), 只读
  • Executable Data section - 存放程序初始化全局变量(global variables),通常 可读写 ,写权限用于程序运行期间更新变量值。
  • Heap section - 程序运行过程中动态分配的内存,属于 Anonymous Memory
  • Stack section - 调用程序功能时的临时数据存储,如函数参数、返回地址、本地变量等。

下图展示了 C 程序(Program)在内存中的分层结构(layout of a C program in memory)

  • 其中, Data section 被分成了 2 部分,包括 (a) initialized data(b) uninitialized data

使用 GNU 工具 size 可以检查 Projram 在磁盘上的 内存布局 。这些值在程序编译时确定,并不会在程序运行时变化,因此它们是固定不变的。

# size /usr/sbin/sshd
text data bss dec hex filename
817397 15460 37664 870521 d4879 /usr/sbin/sshd

输出信息中:

  • text : 代表 Text section 的大小
  • data : 初始化数据段( initialized data )的大小,包含已初始化的全局和静态变量。
  • bss : 未初始化数据段的大小,包含未初始化的全局和静态变量。
  • dec : 上述所有部分的总大小,以十进制表示。
  • hex : 上述所有部分的总大小,以十六进制表示。
阅读全文 »