k8s(一)走进docker

k8s(一)走进docker

Build,Ship and Run Any App,Anywhere

作者:lomtom

个人网站:lomtom.cn

个人公众号:博思奥园

你的支持就是我最大的动力。

k8s系列:

  1. k8s(一)走进docker
  2. k8s(二)Docker的HelloWorld
  3. k8s(三)走进k8s
  4. k8s(四)安装k8s集群
  5. k8s(五)k8s的HelloWorld
  6. k8s(六)走进Pod

docker
Build,Ship and Run Any App,Anywhere

容器

容器是一个标准化的单元,是一个轻量级、可移植的软件打包技术。它将软件代码及其相关依赖打包,使应用程序可以在任何计算介质中运行。简单来讲,容器就像一个标准化的盒子,能够装很多不同类型的东西,并且装完后能够塞进很多不同类型的柜子里。

  • 容器的特性:
    • 封装性:将软件打包成标准化单元以进行开发、迁移和部署
    • 隔离性:计算、存储、网络等资源彼此隔离(运行环境的隔离)
    • 高效性:轻量、快速启停、快速部署与迁移
    • 职责分工明确:开发专心写代码,运维专注基础环境配置
    • 镜像增量分发
  • 容器使用难题
    • 统一平台:在k8s之前,并没有一个统一的平台去操作容器,基本上所有操作都由开发人员/运维人员完成
    • 易用性

虚拟机 VS 容器

img

  • 容器没有虚拟化层,所以容器通常称为轻量级虚拟化技术,然而他真正的实现是通过namespace来进行进程隔离,进入到容器内该Namespace下挂载的目录、文件或者网络。究其根源,容器只是宿主机器上的一个特殊的进程
  • 虚拟化虚拟的是硬件,容器虚拟的是操作系统,所以更高效

image-20220309103834583

docker使用

  1. 通常在项目工程里使用Makefile文件,指定一系列的操作步骤;
  2. 通过docker build构建成一个可运行镜像;
  3. 使用docker push推送到指定的镜像仓库;
  4. 在任何可以连接镜像仓库的地方,拉取镜像并且运行:docker pull docker run

docker原理

docker的运行时是runc,runc采用的技术:基于Linux内核的Cgroup(资源限制),Namespace(隔离),以及UnionFS(文件系统)等技术,对进程进行封装隔离

  1. Namespace:对进程进行隔离,解决了进程之间的可见性问题。

    • 系统可以为进程分配不同的 Namespace,使进程能够拥有独立的运行环境,并且能够拥有网络与宿主机器进行通信。而container本质上是宿主机器上的一个进程;
    • 一个进程的Namespace信息以一个文件的形式存在于宿主机器上。

    image-20220419082127765

  2. Cgroup:对进程组资源进行限制及监控。(全称为control Group)

    • 保证不同的进程组资源独立分配、进程组彼此隔离,即不同的进程组下的进程互不干扰 。这些资源包括:主机名、用户权限、文件系统、网络、进程号、进程间通信。

    • 对进程的资源控制通常存在于/sys/fs/cgroup,每一个进程都会在这里存在一个单独的文件夹,文件夹下会存在各种资源的使用限制,可以修改里面的值进行相应的资源控制。

      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
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      [root@master cpu]# cd /sys/fs/cgroup
      # 创建文件夹
      [root@master cpu]# mkdir lomtom
      # 进入文件夹
      [root@master cpu]# cd lomtom
      [root@master lomtom]# ls
      cgroup.clone_children cgroup.procs cpuacct.usage cpu.cfs_period_us cpu.rt_period_us cpu.shares notify_on_release
      cgroup.event_control cpuacct.stat cpuacct.usage_percpu cpu.cfs_quota_us cpu.rt_runtime_us cpu.stat tasks
      ...

      # 另起一个窗口,运行一个消耗cpu的程序(用写几个for循环即可)
      [root@master root]# cat > main.go << EOF
      package main

      func main() {
      go func() {
      for {

      }
      }()
      go func() {
      for {

      }
      }()
      for {

      }
      }
      EOF
      [root@master root]# go build ./main.go
      [root@master root]#./main


      # 查询该进程的进程号
      [root@master lomtom]# ps -ef|grep main|grep -v grep|awk '{print $2}'
      # 将进程号写入该文件夹下的cgroup.procs
      [root@master lomtom]# echo 26630 > cgroup.procs
      [root@master lomtom]# cat cgroup.procs
      26630

      # 限制cpu使用率上限(10%)
      [root@master lomtom]# echo 10000 > cpu.cfs_quota_us
      [root@master lomtom]# cat cpu.cfs_quota_us
      10000

      限制前cpu占有率

      image-20220419100021909

      限制后cpu占有率

      image-20220419100236239

  3. 除此之外,还会对进程(也就是容器)切换根目录。并且docker镜像是以一层一层的结构构成,rootfs在原有的基础镜像(例如centos)增加自己所要执行的操作即在可读写层添加相应的层。

    img

    并且,下一步操作如果与之前的操作冲突,将会覆盖之前的。例如我先创建一个文件config,然后我又重新写入config文件,那么最终保存的就是最后一次执行的config文件。

    1
    2
    echo 你好 > config
    echo 你快乐吗 > config

    最终在config中只有“你快乐吗”,这在日常的使用中也是这样的,所以这很好理解。

    对于docker镜像来说,Dockerfile的每一步操作都会生成一层可读写层,并且后来的操作也就是上层会覆盖下层,可以通过docker history [images ID],来查看镜像的层级结构。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    [root@master ~]# docker images
    REPOSITORY TAG IMAGE ID CREATED SIZE
    rancher/mirrored-flannelcni-flannel v0.17.0 9247abf08677 7 weeks ago 59.8MB

    [root@master ~]# docker history 9247abf08677
    IMAGE CREATED CREATED BY SIZE COMMENT
    9247abf08677 7 weeks ago ENTRYPOINT ["/opt/bin/flanneld"] 0B buildkit.dockerfile.v0
    <missing> 7 weeks ago RUN /bin/sh -c /iptables-wrapper-installer.s… 1.93kB buildkit.dockerfile.v0
    <missing> 7 weeks ago COPY dist/iptables-wrapper-installer.sh / # … 7.66kB buildkit.dockerfile.v0
    <missing> 7 weeks ago COPY dist/mk-docker-opts.sh /opt/bin/ # buil… 2.14kB buildkit.dockerfile.v0
    <missing> 7 weeks ago COPY dist/flanneld-amd64 /opt/bin/flanneld #… 39.8MB buildkit.dockerfile.v0
    <missing> 7 weeks ago RUN /bin/sh -c apk add wireguard-tools --no-… 2.63MB buildkit.dockerfile.v0
    <missing> 7 weeks ago RUN /bin/sh -c apk add --no-cache iproute2 n… 11.8MB buildkit.dockerfile.v0
    <missing> 7 weeks ago ENV FLANNEL_ARCH=amd64 0B buildkit.dockerfile.v0
    <missing> 5 months ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B
    <missing> 5 months ago /bin/sh -c #(nop) ADD file:5a707b9d6cb5fff53… 5.62MB

    这样的一个好处是,当我在进行容器的分发时,发现底层层级没有发生改变时,那么每次发布只会发布改变的部分。

容器与k8s

CRI接口是kubelet调用容器运行时的grpc接口,也就是k8s定义的容器运行时接口。

而dockershim、cri-containerd都是CRI接口的实现。

而以下都是当下比较流行的运行时的实现。

  1. runc

容器公用主机资源,采用Ns,Cgroup等技术,本质上是一个进程,更轻量。

  1. kata

容器有独立的内核,裁剪了一些不必要的设备、总线、驱动、文件系统等,本质上是一个轻量化的虚拟机,更安全。

k8s(一)走进docker

https://lomtom.cn/24bc125b.html

作者

lomtom

发布于

2022-04-24

更新于

2022-08-16

许可协议