404频道

学习笔记

audit简介

audit为linux内核安全体系的重要组成部分,用来记录内核的系统调用,文件修改等事件,用于审计目的。

  • auditctl: 面向用户的工具,类似于iptables命令
  • auditd: 负责将审计信息写入到/var/

启动auditd服务

auditd作为单独的服务运行在系统上,Redhat系统使用systemctl start auditd启动服务,启动后通过 ps -ef | grep auditd查看进程是否启动成功。

auditctl

查看auditd的运行状态

1
2
3
4
5
6
7
8
9
$ auditctl -s
enabled 1
failure 1
pid 638
rate_limit 0
backlog_limit 8192
lost 0
backlog 0
loginuid_immutable 0 unlocked

查看当前环境规则

1
2
3
4
5
$ auditctl -l
-w /tmp/hosts -p rwxa
-w /proc/sys/net/ipv4/tcp_retries1 -p rwxa
-w /proc/sys/net/ipv4/tcp_retries2 -p rwxa
-w /proc/sys/net/ipv4/tcp_retries2 -p wa

删除所有的audit规则

1
2
$ auditctl -D
No rules

实践

监控文件变化

  1. 执行 auditctl -w $file -p wa 来监控文件,比如监控内核参数 auditctl -w /proc/sys/net/ipv4/tcp_retries2 -p wa,其中-p指定了监控文件的行为,支持rwxa。
  2. 查看文件 cat /proc/sys/net/ipv4/tcp_retries2。
  3. 使用vim打开文件 vim /proc/sys/net/ipv4/tcp_retries2。
  4. 执行 ausearch -f /proc/sys/net/ipv4/tcp_retries2 命令查看,可以看到如下的日志
1
2
3
4
5
6
7
8
$ ausearch -f /proc/sys/net/ipv4/tcp_retries1
----
time->Mon Mar 28 12:44:48 2022
type=PROCTITLE msg=audit(1648442688.159:6232591): proctitle=76696D002F70726F632F7379732F6E65742F697076342F7463705F7265747269657331
type=PATH msg=audit(1648442688.159:6232591): item=1 name="/proc/sys/net/ipv4/tcp_retries1" inode=46629229 dev=00:03 mode=0100644 ouid=0 ogid=0 rdev=00:00 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=PATH msg=audit(1648442688.159:6232591): item=0 name="/proc/sys/net/ipv4/" inode=8588 dev=00:03 mode=040555 ouid=0 ogid=0 rdev=00:00 objtype=PARENT cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0
type=CWD msg=audit(1648442688.159:6232591): cwd="/root"
type=SYSCALL msg=audit(1648442688.159:6232591): arch=c000003e syscall=2 success=yes exit=3 a0=11687a0 a1=241 a2=1a4 a3=7ffe33dc14e0 items=2 ppid=8375 pid=8629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=250225 comm="vim" exe="/usr/bin/vim" key=(null)

监控文件夹变化

监控文件夹同样采用跟上述文件相同的方式,但有个问题是如果文件夹下内容较多,会一起监控,从而导致audit的log内容过多。

监控系统定期reboot

执行如下命令:

1
2
auditctl -w /bin/systemctl -p rwxa -k systemd_call
auditctl -a always,exit -F arch=b64 -S reboot -k reboot_call

待系统重启后执行如下命令:

1
ausearch -f reboot

参考文档

RedHat auditd文档

curl

  • –local-port:指定源端口号
  • –proxy:指定本地代理,例如:http://127.0.0.1:52114
  • -d:指定body,如果body比较小,可以直接指定-d 'login=emma&password=123',也可以通过指定文件的方式 -d '@data.txt'

history

bash会将历史命令记录到文件.bash_history中,通过history命令可以查看到历史执行的命令。但history在默认情况下,仅会显示命令,不会展示出执行命令的时间。history命令可以根据环境变量HISTTIMEFORMAT来显示时间,要想显示时间可以执行如下的命令:

1
HISTTIMEFORMAT='%F %T ' history

lrzsz

CentOS rpm包地址:https://rpmfind.net/linux/centos/7.9.2009/os/x86_64/Packages/lrzsz-0.12.20-36.el7.x86_64.rpm

ps

最常用的为ps -efps aux命令,两者的输出结果差不多,其中ps -ef为System V Style风格,ps aux为BSD风格,现在ps命令两者均支持。

1
2
3
4
5
6
7
8
9
10
11
$ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
www-data 1 0.0 0.0 212 8 ? Ss Apr09 0:00 /usr/bin/dumb-init -- /nginx-ingress-controller
www-data 6 0.9 0.3 813500 100456 ? Ssl Apr09 67:20 /nginx-ingress-controller --publish-service
www-data 33 0.0 0.7 458064 242252 ? S Apr09 0:53 nginx: master process /usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf
www-data 46786 0.0 0.7 459976 239996 ? S 17:57 0:00 rollback logs/eagleeye.log interval=60 adjust=600
www-data 46787 1.4 0.8 559120 283328 ? Sl 17:57 2:07 nginx: worker process
www-data 46788 1.1 0.8 558992 284772 ? Sl 17:57 1:38 nginx: worker process
www-data 46789 0.0 0.7 452012 237152 ? S 17:57 0:01 nginx: cache manager process
www-data 46790 0.0 0.8 490832 267600 ? S 17:57 0:00 nginx: x
www-data 47357 0.0 0.0 60052 1832 pts/2 R+ 20:21 0:00 ps aux

每个列的值如下:

  • %MEM:占用内存百分比
  • VSZ: 进程使用的虚拟内存量(KB)
  • RSS:进程占用的固定内存量,驻留在页中的(KB)
  • STAT:进程的状态
  • TIME:进程实际使用的cpu运行时间

pssh

该工具的定位是在多台主机上批量执行pssh命令。

  1. 将文件存放到文件中 /tmp/hosts 中,文件格式如下:
    1
    2
    192.168.1.1
    192.168.1.2
  2. 批量执行shell命令:pssh -h /tmp/hosts -A -i ‘uptime’。

具体参数说明如下:

  • -A: 手工输入密码模式,如果未打通ssh免密,可以在执行pssh命令的时候手工输入主机密码,但要求所有主机密码必须保持一致

rsync

常用命令:

  1. rsync -avz -e 'ssh -p 50023' ~/git/arkctl root@100.67.27.224:/tm

常用参数:

  • --delete: 本地文件删除时,同步删除远程文件
  • -e 'ssh -p 50023': 指定 ssh 端口号
  • --exclude=.git: 忽略同步本地的 git 目录

scp

  • -P:指定端口号

strace

跟踪进程的系统调用

  • -p:指定进程
  • -s:指定输出的字符串的最大大小
  • -f:跟踪由fork调用产生的子进程

wget

  • -P: 当下载文件时,可以指定本地的下载的目录

split

split [-bl] file [prefix]

  • -b, –bytes=SIZE:对file进行切分,每个小文件大小为SIZE。可以指定单位b,k,m。

  • -C,–bytes=SIZE:与-b选项类似,但是,切割时尽量维持每行的完整性。

  • prefix:分割后产生的文件名前缀。

拆分文件:split -b 200m ip_config.gzip ip_config.gzip

文件合并:cat ip_config.gzip* > ip_config.gzip

python

快速开启一个http server python -m SimpleHTTPServer 8080

在python3环境下该命令变更为:python3 -m http.server 8080

格式化 json: cat 1.json | python -m json.tool

awk

按照,打印出一每一列 awk -F, '{for(i=1;i<=NF;i++){print $i;}}'

docker registry

  • 列出镜像:curl http://127.0.0.1:5000/v2/_catalog?n=1000
  • 查询镜像的tag: curl http://127.0.0.1:5000/v2/nginx/tags/list,如果遇到镜像名类似aa/bb的情况,需要转移一下 curl http://127.0.0.1:5000/v2/aa\/bb/tags/list

socat

  • 向本地的 socket 文件发送数据:echo "test" | socat - unix-connect:/tmp/unix.sock
  • 通过交互的方式输入命令:socat - UNIX-CONNECT:/var/lib/kubelet/pod-resources/kubelet.sock

git

  • 删除远程分支 git push origin --delete xxx
  • 强制更新远程分支:git push --force-with-lease origin feature/statefulset
  • 删除本地分支:git branch -D local-branch
  • 拉取远程分支并切换分支:git checkout -b develop origin/remote-branch develop为本地分支,origin/remote-branch为远程分支
  • 给 Github 设置代理
    1
    2
    3
    4
    5
    # 设置代理
    git config --global http.https://github.com.proxy socks5://127.0.0.1:13659

    # 取消代理
    git config --global --unset http.https://github.com.proxy

rpm

  • rpm -ivh xx.rpm:用来安装一个 rpm 包
  • rpm -qa:查看已经安装的包
  • rpm -ql: 查看已经安装的 rpm 的文件内容
  • rpm -qpR *.rpm: 查看rpm包的依赖
  • rpm -e *:要删除的rpm包

cloc

用来统计代码行数

  • cloc .: 用来统计当前的代码行数
  • cloc . --exclude-dir vendor:忽略目录 vendor,--exclude-dir 仅能支持一级目录
  • cloc . --fullpath --not-match-d=pkg/apis/:用来忽略目录 pkg/apis 下的文件

jq

用来解析 json 格式

key 中包含特殊字符,假设文件 data.json 格式如下:

1
2
3
4
5
{
"data": {
"a.json": "abc"
}
}

可以使用 cat data.json | jq '.data."a.json"' 或者 cat data.json | jq '.data["a.json"]' 的方式来解析其中的内容。

-r 参数:
echo '"{}"' | jq . 输出结果为 "{}" 即对应的格式为字符串。echo -r '"{}"' | jq -r . 输出结果为 {},已经解析为标准的 json 格式。

题图为周末的公园露营区。一周前曾经下过一场雪,地上覆盖着厚厚的一层雪,而一星期过后,上面却扎满了帐篷。城市里的人们,在捂了一个冬季后,终于迎来了阳光明媚的春天。虽内心充满着诗和远方,疫情之下,能约上三五好友,在草地上吃上一顿野餐,亦或在帐篷里美美的睡上一觉已是一件很奢侈的事情。

资源

1. Submariner

Rancher开源的一款k8s集群之间的容器网络打通的工具。k8s社区的网络插件中以overlay的网络插件居多,因为overlay的网络对底层物理网络几乎很少有依赖,通常会采用vxlan、IPIP等协议来实现。虽然overlay的网络插件用起来比较方便,但是两个k8s集群的容器网络通常是无法直接通讯,在多k8s集群的应用场景下比较受限。Submariner提供了容器网络的互通方案。

2. k8e

k8e为Kubernetes Easy的简写。社区里有k3s和k0s项目来提供了k8s精简版,本项目在k3s的基础之上又进一步进行了裁剪,移除了一些边缘场景的特性。

3. Rancher Desktop

k8s的发行版SUSE Rancher提供的k8s的桌面客户端,目前已经发布了1.0.0版本。

4. nginx config

Nginx作为最流行的负载均衡配置软件之一,有自己的一套配置语法。DigitalOcean提供的nginx config工具可以通过UI直接进行配置,并最终可以一键生成nginx的配置文件。

5. mizu

一款部署在k8s上的流量分析工具,可以认为是k8s版的tcpdump + wireshark。底层的实现也是基于libpcap抓包的方式,可以支持解析HTTP、Redis、Kafka等协议。

6. kube-bench

互联网安全中心(Center for Internet Security)针对k8s版本提供了一套安全检查的规范,约有200多页的pdf文档,本项目为针对该规范的实现。仅需要向k8s环境中提交一个job,即可得到最终的安全结果。很多公有云厂商也有自己的实现,比如阿里云ACK的实现

7. virtual-kubelet

virtual kubelet服务通过在k8s集群上创建虚拟node,当一个pod调度到虚拟node时,virtual kubelet组件以插件的形式提供了不同的实现,可以将pod创建在k8s集群之外。比如,在阿里云的场景下,可以将pod创建到弹性容器实例ECI上面,从而达到弹性的目的。该项目除了用于公有云一些弹性的场景外,还常用于边缘计算的场景。

8. cloudevents

CloudEvents定义了一种通用的方式描述事件数据的规范,由CNCF的Serverless工作组提出。阿里云的事件总线EventBridge基于此规范提供了比较好商业化产品。

相关链接:EventBridge 事件总线及 EDA 架构解析

9. kubectl-who-can

在k8s系统中,通常会通过RBAC的机制来配置某个账号拥有某种权限,但如果反过来要查询某个权限被哪些账号所拥有,就会麻烦很多。

该工具是一个k8s的命令行小工具,可以用来解决上述需求。比如查询拥有创建namespace权限的ServiceAccount有哪些,可以直接执行 kubectl-who-can create namespace

10. kyverno

Kyverno是一款基于k8s的策略引擎工具,通过抽象CRD ClusterPolicy的方式来声明策略,在运行时通过webhook的技术来执行策略。相比于opa & gatekeeper,更加k8s化,但却没有编程语言的灵活性。目前该项目为CNCF的孵化项目。

文章

1. 进击的Kubernetes调度系统

该系列一共三篇文档,分别讲解了如下内容:

  • 第一篇:k8s 1.16版本引入的Scheduling Framework
  • 第二篇:阿里云ACK服务基于Scheduling Framework实现的Gang scheduling
  • 第三篇:阿里云ACK服务基于Scheduling Framework实现的支持批任务的Binpack Scheduling

2. 中国的云计算革命尚未开始

作者通过工业革命时代的电气化道路做类似,认为当前云计算的阶段仍然比较初级,并且首先要解决的是人的问题,而不是技术本身。

阿里云上有众多的云产品,本文主要分析云产品的功能以及应用场景。

容器与中间件

该部分领域与我的工作重合度较高,为重点研究领域。

事件总线EventBridge

很多服务会产生输出供下游的服务来消费,最常见的解决办法是数据生产者通过rpc调用的方式将消息发送给数据消费者。但假如消费者的数量不止一处,该模式下就需要数据生产者将数据重复发送给多个消费者,该方式对于生产者可配置的灵活性要求非常高。

为了解决上述问题,将生产者和消费者解耦,解决办法就是引入一个中间层,这也是软件架构中最常见的解决复杂问题的方法。引入的中间层即为消息队列类的服务,比如Kafka。生成者仅负责生产数据到消息队列,消费者负责从消息队列消费数据,且可以存在多个消费者。生成者和消费者根本不用关心彼此,仅需要跟消息队列进行交互就可以了。

阿里云上的某个产品新增加了一个新的操作,比如ECS主机完成了一次快照操作,都会产生事件。如果有服务要消费事件,可以使用该产品。

阿里云上的很多产品会将新产生的事件发送到事件总线,另外也支持自定义事件源,通过编程的方式将事件推送到事件源上。

数据的消费模块跟通常的消息队列有所不同,这里的数据消费需要由事件总线产品主动推送消息到对应的服务,具体要推送到哪些服务,则需要在创建总线的时候配置,该功能即消息路由。支持的消费端包括钉钉、消息队列、Serverless服务、HTTP Server等。可以看到数据的消费端除了HTTP Server外,基本不需要额外开发一个服务,也是阿里云的一些其他云产品。

消息的规范完成遵循云原生社区CNCF的CloudEvent规则。

相关链接:

弹性容器实例ECI

该产品的功能比较简单,相当于提供了管控页面来创建k8s的pod,具体pod部署在哪里用户不需要关心,提供了非常好的弹性能力,充分发挥了云的优势。

具体在实现层面,实际上会以pod的形式部署在阿里云维护的公共k8s集群中,且容器的网络在用户指定的vpc中。

除了给用户提供直接创建容器实例外,还有很大一部分功能是给Serverless Kubernetes(ASK)和容器服务(ACK)来提供弹性扩缩容的功能。

企业级分布式应用服务EDAS

提供了应用托管和微服务的治理能力。

在应用托管方面支持应用发布到虚拟机和k8s两种方式。

微服务治理方面支持了Spring Cloud、Dubbo、HSF三种微服务框架。

Serverless应用引擎SAE

提供了类似于knative的serving功能,可以支持应用的托管,用户不需要关心底层的服务器资源,可以自动将用户的应用部署在托管的k8s集群中,且具备秒级的弹性扩缩容的功能。

Serverless工作流SWF

软件工程

康威定律

任何一个组织在设计一个系统的时候,这个系统的结构与这个组织的沟通结构是一致的。
工作了这么些年对此深有感触,即“组织架构决定软件架构”。

布鲁克定律

在一个已经延期的项目中增加人手只会让项目延期更长。
我个人不是特别认可此定律,该定律肯定是项目而定的,这要看项目的协作复杂程度,如果是体力劳动居多的项目,那么堆人还是特别好使的。

帕金森定律

一项工作会占用掉所有用来完成它的时间。即如果不给一个项目设置截止日期,那么该项目就永远完成不了。安排多少时间,就会有多少工作。

冰山谬论

一款新软件的开发成本只占管理层预算的总成本的25%左右。

其他

黄金圈法则

著名的营销顾问西蒙斯.涅克提出了一个“黄金圈”理论:三个同心圆,最里面的一个是Why,中间一层是How,最外面一层是What。

大多数人的思维方式是想做什么(what)和怎么做(how),不太考虑为什么这么做(why)。

本理论提倡的思维方式为:

  1. Why:最内层——为什么,做一件事的原因或目的,也可以说是理念和宗旨,属于战略层面;
  2. How:中间层——怎么做,针对这个目的或理念的计划,也即如何去做好这件事情,属于战术层面;
  3. What:最外层——是什么,最终得到什么,或者要做哪些具体的事,这基本是事情的表象,主要是执行层面的东西。

该法则在软件行业的述职晋升等场景下非常适用。

  1. Why:描述为什么做这个项目?
  2. How:做这个项目遇到的挑战有哪些,是怎么解决的。挑战和解决方法可以一一对应起来。
  3. What:项目的最终结果,最好有具体的可以量化的指标。

SWOT分析法

常见的战略分析方法,对研究对象进行全面、系统、准确的研究。

金字塔原理

参见《金字塔原理总结

成功的面试 = 把握正确清晰的用人标准 + 挖掘真实匹配的应聘者信息 = 以素质模型去“发问” + 用STAR方式去“追问”

STAR行为面试法

STAR是业界公认的最为有效的面试方法之一,为背景(Situation)、任务(Task)、行为(Action)、结果(Result)的缩写。该方法不仅用于面试的场合,也会用于述职、晋升答辩等场景。

任务(Task)描述在事情里的担任的角色和负责的任务。

行为(Action)是最关键部分,要了解做了什么,展现出了哪些能力。

结果(Result)部分通常需要虚实结合,且重点在实,围绕效率、效果、质量和成本四个维度量化评估。

STAR方法同样适用于述职汇报或者晋升中。

奥克姆剃刀理论

如无必要,勿增实体。

马斯洛需求层次理论

心理学中重要理论,将人类的需求分为五个层级:

  1. 生理
  2. 安全
  3. 社交
  4. 尊重
  5. 自我实现

人类的需求为逐步递进的,在满足了基本需求后,就会去实现更高的需求和目标。

在工作中,经常会用类似马斯洛需求层次理论中的金字塔结构来解释一些其他的有递进关系的场景 ,比如一个软件产品的设计目标。

SMART 原则

确定目标的五原则,通常用在绩效考核中。

  1. S(Special):目标必须是具体的
  2. M(Measurable):目标必须是可衡量的
  3. A(Attainable):目标必须是可实现的
  4. R(Relevant):与其他的目标有一定的相关性
  5. T(Time-bound):目标必须有完成的期限

常见名词

ROI:投入产出比

pod状态

1. 前置检查

在排查异常状态的pod错误之前,可以先检查一下node状态,执行kubectl get node查看是否所有的node状态都正常。

2. pod状态为CrashLoopBackOff

如果pod状态为CrashLoopBackOff状态,查看pod日志来定位原因,或者describe pod看一下。

3. pod状态为Pending

pod状态为Pending状态,说明调度失败,通常跟污点、标签、cpu、内存、磁盘等资源相关。

可以通过kubectl describe pod -n {NAMESPACE} {POD_NAME},可以在最后的Event部分找到原因。

4. pod状态为Init:0/1

有些pod会有Init Containers,这些container是在pod的containers执行之前先执行。如果Init Container出现未执行完成的情况,此时pod处于Init状态。

通过kubectl get pod -n {NAMESPACE} {POD_NAME} -o yaml 找到pod的Init Containers,并找到其中的name字段。执行kubectl logs -n {NAMESPACE} {POD_NAME} -c {INIT_CONTAINER_NAME}可以查看Init Container的日志来分析原因。

5. pod状态为Terminating

pod处于此种状态的原因大致可分为:
1、pod或其控制器被删除。
解决方法:查看pod控制器类型和控制器名称,查看其控制器是否正常。如果正常pod将会被重建,如果pod没有被重建,查看controller-manager是否正常。
2、pod所在节点状态NotReady导致。
解决方法:检查该节点的网络,cpu,内存,磁盘空间等资源是否正常。检查该节点的kubelet、docker服务是否正常。检查该节点的网络插件pod是否正常。

最常见的pod处于Terminating状态的解决办法为强制删除 kubectl delete pods -n ${namespace} ${name} --grace-period=0 --force

6. pod状态为Evicted

pod处于Evicted的原因大致可分为:
1、kubelet服务启动时存在驱逐限制当节点资源可用量达到指定阈值(magefs.available<15%,memory.available<300Mi,nodefs.available<10%,nodefs.inodesFree<5%)
会优先驱逐Qos级别低的pod以保障Qos级别高的pod可用。
解决方法:增加节点资源或将被驱逐的pod迁移到其他空闲资源充足的节点上。
2、pod所在节点上被打上了NoExecute的污点,此种污点会将该节点上无法容忍此污点的pod进行驱逐。
解决方法:查看该节点上的NoExecute污点是否必要。或者pod是否可以迁移到其他节点。
3、pod所在的节点为NotReady状态

通常可以通过kubectl describe pods ${pod} -n ${namespace}的底部的Events信息来找到一些问题的原因。例如下面例子中可以看到DiskPressure信息,说明跟磁盘相关。

1
2
3
4
5
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Evicted 61s kubelet, acs.deploy The node had condition: [DiskPressure].
Normal Scheduled <invalid> default-scheduler Successfully assigned ark-system/bridge-console-bridge-console-554d57bb87-nh2vd to acs.deploy

或者根据pod的Message字段来找到原因

1
2
3
4
5
6
7
8
9
10
11
12
Name:           tiller-deploy-7f6456894f-22vgr
Namespace: kube-system
Priority: 0
Node: a36e04001.cloud.e04.amtest17/
Start Time: Mon, 08 Jun 2020 12:17:26 +0800
Labels: app=helm
name=tiller
pod-template-hash=7f6456894f
Annotations: <none>
Status: Failed
Reason: Evicted
Message: Pod The node had condition: [DiskPressure].

由于pod驱逐的原因排查跟时间点相关,需要根据pod被驱逐的时间来分析当时的状态。
4、批量删除状态Evicted的pod,此操作会删除集群里面所有状态为Evicted的pod

1
2
ns=`kubectl get ns | awk 'NR>1 {print $1}'`
for i in $ns;do kubectl get pods -n $i | grep Evicted| awk '{print $1}' | xargs kubectl delete pods -n $i ;done

7. pod状态为Unknown

通常该状态为pod对应节点的为NotReady,通过查看 kubectl get node 来查看node是否为NotReady。

8. pod为running,但是Not Ready状态

1
argo-ui-56f4d67b69-8gshr   0/1     Running     0          10h

类似上面这种状态,此时说明pod的readiness健康检查没过导致的,需要先从pod的健康检查本身来排查问题。可以通过 kubectl get pods -n ${namespace} ${name} -o yaml 找到pod的健康检查部分,关键字为readiness,然后进入pod中执行对应的健康检查命令来测试健康检查的准确性。

例如readiness的配置如下,需要进入pod中执行curl http://127.0.0.1/api/status,也可以在pod对应的node节点上执行curl [http://${pod_ip}/api/status](http://127.0.0.1/api/status)

1
2
3
4
5
6
7
8
9
10
livenessProbe:
failureThreshold: 3
httpGet:
path: /api/status
port: http
scheme: HTTP
initialDelaySeconds: 120
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1

9. pod为ContainerCreating状态

通过kubectl describe pods -n ${namespace} ${name}的Events部分来分析原因,可能的原因如下:

  • 网络分配ip地址失败

10. Init:CrashLoopBackOff

  1. 通过kubectl get pod -n {NAMESPACE} {POD_NAME} -o yaml 找到pod的Init Containers,并找到其中的name字段。
  2. 执行kubectl logs -n {NAMESPACE} {POD_NAME} -c {INIT_CONTAINER_NAME}可以查看Init Container的日志来分析原因。

11. PodInitializing

需要查看initContainer的日志

12. MatchNodeSelector

查看pod的status信息可以看到如下信息:

1
2
3
4
5
status:
message: Pod Predicate MatchNodeSelector failed
phase: Failed
reason: MatchNodeSelector
startTime: "2022-03-15T05:07:57Z"

说明该pod没有调度成功,在predicate的MatchNodeSelector阶段失败了,没有匹配上node节点。

在k8s 1.21之前的版本,存在bug,节点重启后可能遇到过问题,将pod delete后重新调度可以解决。https://github.com/kubernetes/kubernetes/issues/92067

参考

排查k8s上问题通常需要监控的配合,而k8s上的监控标准为prometheus,prometheus的dashboard最通用的为grafana。本文用来记录排查k8s问题时经常遇到的dashboard,dashboard监控的数据来源包括node-exporter、metrics-server、kube-state-metrics等最场景。

node top监控

下载链接

node上的pod监控

下载链接

正向代理通常用在远程访问某个环境中的。常见的正向代理工具包括squid、nginx、3proxy。

squid

老牌的正向代理工具。

安装:yum install squid && systemctl start squid

squid默认会监听在3128端口号。

缺点:如果修改了本地的/etc/hosts文件,则需要重启squid后才可以更新。

3proxy

官方并没有提供yum的安装方式,比较简单的运行方式是以docker的形式。

执行如下的命令,即可开启3128端口作为http代理,3129端口作为sock5代理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mkdir /etc/3proxy
cat > /etc/3proxy/3proxy.cfg <<EOF
log /var/log/3proxy.log D
logformat "- +_L%t.%. %N.%p %E %U %C:%c %R:%r %O %I %h %T"
rotate 7
auth none
flush
allow somepu
maxconn 200

# starting HTTP proxy with disabled NTLM auth ( -n )
proxy -p3128 -n

# starting SOCKS proxy
socks -p3129 -n
EOF
docker run -d --restart=always -p 3128:3128 -p 3129:3129 --net=host -v /var/log:/var/log -v /etc/3proxy/3proxy.cfg:/etc/3proxy/3proxy.cfg --name 3proxy 3proxy/3proxy

设置代理

终端设置代理

shell支持如下的代理环境变量:

1
2
export http_proxy=http://localhost:1080
export https_proxy=http://localhost:1080

如果是 socks5 代理同样可以使用上述两个环境变量:

1
2
export http_proxy=socks5://localhost:1080
export https_proxy=socks5://localhost:1080

相关链接

ssh命令常用参数

指定私钥连接:ssh -i ~/.ssh/id_rsa ido@192.168.1.111 -p 7744

免密登录

用来两台主机之间的ssh免密操作,步骤比较简单,主要实现如下两个操作:

  1. 生成公钥和私钥
  2. 将公钥copy到要免密登录的服务器

生成公钥和私钥

执行 ssh-keygen -b 4096 -t rsa 即可在 ~/.ssh/目录下生成两个文件id_rsa和id_rsa.pub,其中id_rsa为私钥文件,id_rsa.pub为公钥文件。

将公钥copy到要免密登录的服务器

执行 ssh-copy-id $user@$ip 即可将本地的公钥文件放到放到要免密登录服务器的 $HOME/.ssh/authorized_keys 文件中。至此,免密登录的配置就完成了。

也可以不使用 ssh-copy-id 命令,而是手工操作完成。

  1. 在客户端机器上执行 cat .ssh/id_rsa.pub 获取到公钥信息。
  2. 在服务端机器上执行 vim ~/.ssh/authorized_keys,将上面的公钥信息追加到文件的尾部。如果目录 .ssh 不存在,需要先创建。
  3. 执行 chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys 给文件和目录设置合理的权限。

ssh隧道

动态端口转发:执行 ssh root@xxxx -ND 127.0.0.1:1080 即可在本机的1080端口开启一个ssh隧道。

rsync

rsync的常用命令:

1
rsync -avzP --delete $local_idr  $user@$remote:$remote_dir

OpenKruise是阿里云开源的一系列基于k8s的扩展组件的集合,其中包含了像增强版的workload、sidecar容器管理、高可用性防护等特性,包含了很多的“黑科技”。

如果k8s的kube-controller-manager组件可以提供非常强的扩展能力,可以实现自定义的Deployment、StatefulSet的controller,而不是使用原生的kube-controller-manager的功能,类似于实现自定义的调度器扩展功能。那么很有可能OpenKruise的实现方案就不再会采用CRD扩展的方式,而是直接在原生的Deployment、StatefulSet等对象上通过annotation的方式来实现。

安装

可以直接使用helm的方式安装

1
2
helm repo add openkruise https://openkruise.github.io/charts/
helm install kruise openkruise/kruise --version 1.0.1

安装完成后,可以看到在kruise-system下创建了一个DeamonSet和一个Deployment。并且安装了很多的CRD和webhook组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ kubectl  get pod -n kruise-system
NAME READY STATUS RESTARTS AGE
kruise-controller-manager-67878b65d-cv6f4 1/1 Running 0 92s
kruise-controller-manager-67878b65d-jrmnd 1/1 Running 0 92s
kruise-daemon-ktwvv 1/1 Running 0 92s
kruise-daemon-nf84r 1/1 Running 0 92s
kruise-daemon-rjs26 1/1 Running 0 92s
kruise-daemon-vghw4 1/1 Running 0 92s

$ kubectl get crd | grep kruise.io
advancedcronjobs.apps.kruise.io 2022-03-05T13:21:39Z
broadcastjobs.apps.kruise.io 2022-03-05T13:21:39Z
clonesets.apps.kruise.io 2022-03-05T13:21:39Z
containerrecreaterequests.apps.kruise.io 2022-03-05T13:21:39Z
daemonsets.apps.kruise.io 2022-03-05T13:21:39Z
imagepulljobs.apps.kruise.io 2022-03-05T13:21:39Z
nodeimages.apps.kruise.io 2022-03-05T13:21:39Z
podunavailablebudgets.policy.kruise.io 2022-03-05T13:21:39Z
resourcedistributions.apps.kruise.io 2022-03-05T13:21:39Z
sidecarsets.apps.kruise.io 2022-03-05T13:21:39Z
statefulsets.apps.kruise.io 2022-03-05T13:21:39Z
uniteddeployments.apps.kruise.io 2022-03-05T13:21:39Z
workloadspreads.apps.kruise.io 2022-03-05T13:21:39Z

$ kubectl get validatingwebhookconfigurations kruise-validating-webhook-configuration
NAME WEBHOOKS AGE
kruise-validating-webhook-configuration 17 17m
$ kubectl get mutatingwebhookconfigurations kruise-mutating-webhook-configuration
NAME WEBHOOKS AGE
kruise-mutating-webhook-configuration 11 17m

功能

大类 子类 描述
通用工作负载 CloneSet 定位是用来代替k8s的Deployment,但做了很多能力的增强。增强的功能点:
1. 支持声明pvc,给pod来申请pv。当pod销毁后,pvc会同步销毁。
2. 指定pod来进行缩容。
3. 流式扩容,可以指定扩容的步长等更高级的库容特性。
4. 分批灰度。
5. 通过partition回滚。
6. 控制pod的升级顺序。
7. 发布暂停。
8. 原地升级自动镜像预热。
9. 生命周期钩子。pod的多个声明周期之间可以读取finalizer,如果finalizer中有指定的值,则controller会停止。该行为作为k8s的一种hook方式,用户可以自定义controller来控制finalizer的行为。
通用工作负载 Advanced StatefulSet 用来取代k8s原生的StatefulSet,很多增强特性跟CloneSet比较类似。
1. 原地升级。
2. 升级顺序增强。
3. 发布暂停。
4. 原地升级自动预热。
5. 序号跳过。StatefulSet创建的pod的后缀会从0开始依次累加,可以指定某个特定的序号跳过。
6. 流式扩容。
通用工作负载 Advanced DaemonSet 用来取代k8s原生的DaemonSet。1. 热升级
2. 暂停升级
任务工作负载 BroadcastJob agent类型的job,每个节点上都会执行
任务工作负载 AdvancedCronJob 原生的CronJob的扩展版本,可以周期性创建BroadcastJob。
Sidecar容器管理 SidecarSet 用来管理Sidecar容器,其最核心的功能是支持在pod不重启的情况下Sidecar容器的热升级
多区域管理 WorkloadSpread 将workload按照不同的策略来打散,随着k8s功能不断完善,部分功能k8s已经具备。支持Deployment、ReplicaSet、CloneSet。
多区域管理 UnitedDeployment k8s集群内可能存在不同种类型的node,该特性通过UnitedDeployment对象来管理将一个workload的不同pod分发到不同类型的节点上,并且可以指定不同类型节点的pod副本数。
增强运维 重启一个pod中的某个容器 该特性依赖于kurise-daemon组件实现,通过将容器进程停掉,kubelet检测到容器停掉后会自动将容器拉起。停掉容器的方式跟kubelet实现一致。
增强运维 镜像预热 通过ImagePullJob CR提供操作入口,底层的实现通过调用CRI的pod image接口实现
增强运维 控制pod中容器的启动顺序 kruise创建一个ConfigMap,并在pod中注入来挂载该ConfigMap,每个容器使用ConfigMap中的不同key。kruise依次往CM中增加key来实现控制容器启动顺序的目的。
增强运维 资源分发ResourceDestribution 可以跨namespace来分发CM、Secret,保证每个namespace下均有
应用安全防护 资源删除防护 通过webhook技术实现
应用安全防护 PodUnavailableBudget 通过webhook实现的k8s原生的pdb能力的增强,覆盖pdb不具备的场景

资料

0%