之前理解错了k8s给容器配置的一些配置项。阅读一下kubernetes官方文档

https://kubernetes.io/zh-cn/docs/concepts/configuration/manage-resources-containers/

容器资源设置

当定义pod时,可以设定每个容器所需要的资源数量,如CPU和内存大小

其中resources有两项配置:requests和limits

resources:
  limits:
    cpu: '1'
    memory: 8Gi
  requests:
    cpu: 50m
    memory: 500Mi

request配置决定了kube-scheduler将pod调度到哪个节点上

当你为container指定了limit后,kubelet将会确保运行的容器不会使用超过所涉限制的资源

即:requests决定去哪个节点,limits决定了docker的占用资源

pod可以使用超出requests的资源,但无法超过limits设置的资源

例:配置memory的limit为4G,容器运行时的最大内存占用就是4G,一旦docker的进程尝试使用更多的内存就会OOM

本地临时性存储设置

临时性本地数据:emptyDir卷、可写入容器层、容器镜像、日志

可以为本地临时性存储设置请求和限制

spec.containers[].resources.limits.ephemeral-storage
spec.containers[].resources.requests.ephemeral-storage

举例:

apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
    volumeMounts:
    - name: ephemeral
      mountPath: "/tmp"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        ephemeral-storage: "2Gi"
      limits:
        ephemeral-storage: "4Gi"
    volumeMounts:
    - name: ephemeral
      mountPath: "/tmp"
  volumes:
    - name: ephemeral
      emptyDir:
        sizeLimit: 500Mi

该pod包含两个容器,每个容器请求2G大小的本地临时性存储,每个容器都设置了4G作为本地临时性存储的限制,因此整个pod的本地临时性存储请求是4G,限制为8G,其中emptyDir可以使用500M

什么叫可写入镜像层?我们了解一下docker的镜像分层原理

docker镜像分层原理

使用docker pull的时候我们可以看到镜像是分层下载的

在这里插入图片描述
当我们运行一个新的容器的时候,是在镜像分层的基础上新增了一层:container layer
针对这一层的修改,再容器重启后都会全部丢失

所以在使用docker的过程中,如果需要修改运行时的容器文件,尽量去重新构建镜像而不是直接修改容器内的文件

如果重新构建解决不了问题,就通过挂载数据卷的方式解决在这里插入图片描述
容器层如果想做修改,实际上时进行了写时复制操作

容器的层是怎么来的?实际上在构建镜像的时候,每执行一个操作就会多一层

在这里插入图片描述
分层的好处是什么?在pull镜像的时候可能会注意到,如果本地已经存在了部分层,是不会重复拉取的!

因此 分层主要解决的就是镜像版本变化的拉取问题,可以节省时间,并且节省存储空间

并且,当多个基于相同镜像运行的容器,是共享相同的镜像层的,每个容器有区别的地方在于可写入镜像层,也就是说所主机上只需要保存一份base镜像,内存中也只需要加载一份base镜像,使用这个镜像的容器就都可以运行了

Docker镜像层都是只读的,容器层是可写的。 当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器层中

接下来理解一下docker的几个概念:rootfs、Union mount、image、layer

rootfs

代表一个docker container在启动时其内部进程可见的文件系统视角,或者是docker container的根目录

docker的运行和linux操作系统内核启动类似,当docker daemon为docker container挂载rootfs的时候,将其设定为只读模式。在rootfs挂载完毕之后,docker daemonl利用union mount方式,在只读的rootfs上再挂载一个读写的文件系统

也就是说 容器中的进程堆rootfs的内容只有只读权限

Union mount

一种文件系统挂载的方式,允许同一时刻多种文件系统挂载在一起,并以一种文件系统的形式呈现多种文件系统内容合并后的目录

一般情况下,通过某种文件系统挂载内容至挂载点,那么挂载点目录中原先的内容将会被隐藏,而union mount不会。

实现union mount的文件系统称为union FileSystem,常见的有unionFS、AUFS、OverlayFS

对用户而言,整个文件系统并没有关注那部分是只读的,那部分是读写的,即便用户试图改写/etc/hosts中的内容,也是修改的读写系统中复制的/etc/hosts,然后保证用户看到读写系统中的/etc/hosts

image

docker中的image是一种轻量级的、可独立执行的软件包

layer

image由layer组成

除了只读的image之外,docker daemon在创建容器时会在容器的rootfs上,再mount一层read-write filesystem,而这一层文件系统,也称为容器的一层layer,常被称为top layer

容器的top layer可以转化为image吗?当然时可以的,这就是docker中的commit操作,无论在什么周期节点,对容器进行commit都可以将top layer所有内容打包为一个image,变成一个新的镜像

dockerFile中 ENV CMD LABEL不会增加层 而 RUN ADD COPY都会增加一层

COW策略

写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略。其核心思想是,如果有多个调用者(callers)同时请求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的。此作法主要的优点是如果调用者没有修改该资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源。

在docker中,如果某一层需要读取低层的文件,直接读即可。如果要修改一个文件,且这个文件是在低层,那就需要先拷贝到当前层,然后修改当前层这个文件

简单理解就是 镜像的层包含这一层文件相对于之前层的diff

docker下载

1、docker client发送镜像的tag到registry
2、registry根据镜像tag,得到manifest文件,返回给docker client
3、docker client根据manifest文件后,根据imageID检查镜像在本地是否存在
4、如果不存在则下载config文件,根据diff_ids得到镜像每一层解压后的digest
5、根据每层解压后的digest文件,检查本地是否存在,如果不存在则通过layer的digest下载该层并解压

docker本地存储

本地存储目录为/var/lib/docker/image/overlay2

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐