准备个容器

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: busybox
  labels: 
    app: busybox
spec: 
  replicas: 1
  selector: 
    matchLabels: 
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      containers:
        - name: busybox
          image: centos:latest
          ports:
          - name: http
            containerPort: 8080
            protocol: TCP
          command: ["/bin/sh"]
          args: ["-c","sleep 1000"]

让我们看看他默认状态下访问百度是什么样的

[root@master ~]# kubectl exec -it busybox-54b6dd484b-9pc22 -c busybox -- sh
sh-4.4# ping baidu.com
PING baidu.com (39.156.66.10) 56(84) bytes of data.
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=1 ttl=51 time=9.05 ms
64 bytes from 39.156.66.10 (39.156.66.10): icmp_seq=2 ttl=51 time=9.05 ms

好,让我们nslookup一下阿里云的ip,挑选其中一个

nslookup aliyun.com
Server:         100.100.2.136
Address:        100.100.2.136#53

Non-authoritative answer:
Name:   aliyun.com
Address: 106.11.249.99

加上一点小小的魔法

apiVersion: apps/v1
kind: Deployment
metadata: 
  name: busybox
  labels: 
    app: busybox
spec: 
  replicas: 1
  selector: 
    matchLabels: 
      app: busybox
  template:
    metadata:
      labels:
        app: busybox
    spec:
      hostAliases: 
      - ip: "106.11.249.99"
        hostnames: 
        -  "baidu.com"
      containers:
        - name: busybox
          image: centos:latest
          ports:
          - name: http
            containerPort: 8080
            protocol: TCP
          command: ["/bin/sh"]
          args: ["-c","sleep 1000"]

再进去看看,乐

[root@master ~]# kubectl exec -it busybox-7995d79d96-pnm2f -c busybox -- sh
sh-4.4# ping baidu.com
PING baidu.com (106.11.249.99) 56(84) bytes of data.
64 bytes from baidu.com (106.11.249.99): icmp_seq=1 ttl=48 time=26.7 ms
64 bytes from baidu.com (106.11.249.99): icmp_seq=2 ttl=48 time=26.7 ms

当你想要给你的应用配置某个dns,但是又不想直接修改coredns以影响整个集群的时候,你就可以使用这个

今天带两个供应商干活,以这俩人的踩坑记录把dockfile初学者可能会犯的错误罗举一下

  1. from,一定要写基础镜像(没错就是这么难绷
  2. run后面不要使用交互式的命令,如vim\不加-y的yum
  3. copy,复制的时候注意dockerfile和目标文件的层级关系,最好同级
  4. copy,如果想复制一整个文件夹,包括他自己本身,那么目的目录应该在结尾以这个文件夹的文件名为结尾,不然默认只复制文件夹里面的东西
  5. cmd,cmd是镜像启动的后执行的命令,把运行服务的命令写在run里面是没用的
  6. cmd或者run的时候要注意对应文件的权限问题,以及所使用的shell的区别
  7. 容器判断该容器是否结束退出,是通过cmd是否执行并打印0退出来判断的,不是通过后台是否有进程来决定的。如果cmd用java跑个程序那还好,如果是通过一个脚本来启动一个java程序,那么只要这个脚本被成功运行并退出了,哪怕java程序还在运行,容器也会觉得这个容器已经结束了。所以如果是通过脚本来启动服务,最好后面跟个死循环的命令,随你tail -f或者sleep睡个天荒地老都行
  8. 在cicd跑的时候注意代码文件有没有传全
  9. 最好把run一条用&&拼凑写完,run越多镜像的层数越多,构建出来的镜像越大
  10. 哪怕切了目录,也得用绝对路径

unix使用整数来追踪打开的文件,我们把这个整数叫做文件描述符(file descriptors)
image.png

运行中的进程可以查看/proc/pid/fd来看他占用的文件描述符,当然也有更简单的方法,使用lsof指令就可以查看与文件有关的信息

-a file:查看文件占用(-a加不加都行

[root@master 8432]# lsof -a /var/lib/docker/volumes/metadata.db
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
dockerd 8432 root  mem-W  REG  253,1    32768 1183817 /var/lib/docker/volumes/metadata.db
dockerd 8432 root   10uW  REG  253,1    32768 1183817 /var/lib/docker/volumes/metadata.db

-n dev:查看磁盘占用
-p pid:查看进程打开的文件
lsof -i:port 获取端口占用

describe k8s pod的时候,会看到一行QoS Class,这玩意对于k8s里的应用,就好像oom_score_adj之于linux应用,决定着当资源紧张的时候,pod被驱逐的优先顺序
k8s不想oomscore一样可以直接通过调节数值来定义,他分成固定的三类:
Guaranteed
Burstable
BestEffort
决定一个应用的QoS Class是哪一类的,是他们对资源限制的配置,当你给应用配置了cpu及内存的request和limit并且两者值相等的时候,他的种类为Guaranteed,当你至少配置了一项cpu或者内存的request的时候,他的种类为Burstable,当你什么都没有配置的时候,他的种类为BestEffort

这三种类型的容器受到的待遇天差地别,他们的cgroupsPath不同,当然还有最重要的,他们初始化的oomscoreadj也完全不同,Guaranteed可能是-998,Burstable可能是998,BestEffort就可能是1000了

还记得之前那个悄悄给自己应用取消掉了资源限制,以为这样可以为所欲为的开发的例子,java+按比例吃资源启动+容器无资源上限,得到的结果就是他的应用不停的被缺少内存资源的宿主机驱逐,属于是自作聪明了

参考:https://zhuanlan.zhihu.com/p/126532976?utm_id=0

ps -ef | grep找出应用pid
echo -1000 > /proc/$pid/oom_score_adj
oom_score_adj是内核给应用打的一个分数,区间在-1000~1000,越大越优先被杀,-1000代表禁止oom杀该进程,可以用来保护一些重要的程序,比如ssh,免得服务挂了后连登录都登不进去
当发生oom的时候,dmesg打印出的消息里面可以看到被杀的进程的oom分数

核心进程:咦,内核,你手里拿的什么
内核(举起oom):是一会要用到的神奇妙妙工具