zoukankan      html  css  js  c++  java
  • kubernetes 笔记 1

    参考--极客时间 深入剖析kubernetes

    容器隔离使用namespace技术,将容器进程和宿主机进程隔离。

    普通进程:pid = clone(main_function, stack_size, SIGCHLD, NULL);

    容器进程:int pid = clone(main_function, stack_size, CLONE_NEWPID | SIGCHLD, NULL);

    使用CLONE_NEWPID参数,使容器进程无法查看宿主机其他进程,并且将自己的pid设置为1。

    Linux 操作系统还提供了 Mount、UTS、IPC、Network 和 User 这些 Namespace。

    linux内核无法被namespace化的资源和对象:

    时间:使用settimeofday(2)系统调用修改时间,整个宿主机的时间也被修改

    =====

    Cgroups: Linux内核用来为进程设置资源限制的功能。

    Cgroups以文件和目录的方式组织在操作系统 /sys/fs/cgroup路径下,Ubuntu可以使用mount命令将其展示出来:

    # mount -t cgroup
    cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,name=systemd)
    cgroup on /sys/fs/cgroup/rdma type cgroup (rw,nosuid,nodev,noexec,relatime,rdma)
    cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
    cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
    cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
    cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
    cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
    cgroup on /sys/fs/cgroup/net_cls,net_prio type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls,net_prio)
    cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct)
    cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
    cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
    cgroup on /sys/fs/cgroup/pids type cgroup (rw,nosuid,nodev,noexec,relatime,pids)

    /sys/fs/cgroup/目录下有很多子目录(子系统),显示本主机可以限制的资源种类。以cpu为例:

    # ls /sys/fs/cgroup/cpu
    cgroup.clone_children  cpuacct.stat       cpuacct.usage_percpu       cpuacct.usage_sys   cpu.cfs_quota_us  docker             system.slice
    cgroup.procs           cpuacct.usage      cpuacct.usage_percpu_sys   cpuacct.usage_user  cpu.shares        notify_on_release  tasks
    cgroup.sane_behavior   cpuacct.usage_all  cpuacct.usage_percpu_user  cpu.cfs_period_us   cpu.stat          release_agent      user.slice

    cfs_period 和 cfs_quota组合使用,表示在cfs_period时间内,只能分配到cfs_quota总量的CPU使用时间。

    blkio,为块设备设定I/O 限制,一般用于磁盘等设备;
    cpuset,为进程分配单独的 CPU 核和对应的内存节点;
    memory,为进程设定内存使用的限制

    使用:

    只需要在每个子系统下面,为每一个容器创建一个控制组(即新创建一个目录),然后启动容器后,将进程pid写入到对应控制组的tasks文件中即可。

    $ echo <PID> > /sys/fs/cgroup/cpu/container/tasks
    $ docker run -it --cpu-period=100000 --cpu-quota=20000 ubuntu /bin/bash
    # 100ms(100000us)的时间内,只能使用20ms(20000us)的CPU时间,即20%的CPU带宽

    一个容器的本质就是一个进程,用户的应用进程实际上就是容器里 PID=1 的进程,也是其他后续创建的所有进程的父进程。这就意味着,在一个容器中,你没办法同时运行两个不同的应用,除非你能事先找到一个公共的 PID=1 的程序来充当两个不同应用的父进程,这也是为什么很多人都会用 systemd 或者 supervisord 这样的软件来代替应用本身作为容器的启动进程。

    =====

    mount namespace:

    mount namespace和其他namespace略有不同,它对容器视图的改变,一定伴随着挂载操作(mount)才能生效。

    Linux操作系统有chroot命令可以帮助在shell中完成根目录的挂载(change root file system),即rootfs

    chroot /path /bin/bash

    容器大概流程:

    1. 启用Linux namespace配置,

    2. 设置指定的cgroups参数,

    3. 切换进程根目录rootfs(change root)(优先pivot_root,没有使用chroot)

    ???

    docker create 没有创建系统挂载点?启动之后才会创建??

    为什么podman create 后就可以使用podman mount container返回系统挂载点??

    ???

    镜像层 ro+wh(read only + whitout)

    要删除只读镜像层的内容只需在rw层添加.wh.filename

    init 层用来存放/etc/hosts, /etc/resolv.conf 等信息,这些信息只对当前容器有效,commit时不会携带此层

    使用下面命令来查看容器pid:

    docker inspect --format '{{ .State.Pid }}' <containerId>

    查看宿主机proc文件来查看进程对应的namespace

    ls -l /proc/PID/ns
    # ls -l /proc/11520/ns
    total 0
    lrwxrwxrwx 1 root root 0 May 27 21:30 cgroup -> 'cgroup:[4026531835]'
    lrwxrwxrwx 1 root root 0 May 27 21:30 ipc -> 'ipc:[4026532432]'
    lrwxrwxrwx 1 root root 0 May 27 21:30 mnt -> 'mnt:[4026532430]'
    lrwxrwxrwx 1 root root 0 May 27 21:30 net -> 'net:[4026532435]'
    lrwxrwxrwx 1 root root 0 May 27 21:30 pid -> 'pid:[4026532433]'
    lrwxrwxrwx 1 root root 0 May 27 21:30 pid_for_children -> 'pid:[4026532433]'
    lrwxrwxrwx 1 root root 0 May 27 21:30 user -> 'user:[4026531837]'
    lrwxrwxrwx 1 root root 0 May 27 21:30 uts -> 'uts:[4026532431]'

    使用setns()系统调用来讲一个进程加入到已有的namespace中,达到docker exec的效果。

    docker提供了--net 参数允许一个容器加入到另外一个容器network namespace中,

    docker run -it --net container:<containerId> <image> <command>

    如果使用--net=host,则不会为此容器建立network namespace,直接共享主机网络栈

    Copy-on-Write:

    在容器中对rootfs做的任何修改,都会被操作系统先拷贝到可读写层,然后再修改。

    Volume:

    docker run -v /test...
    #此方式会创建一个临时目录/var/lib/docker/[volumeId]/_data,然后挂载到/test上
    docker run -v /path:/path

    挂载数据卷,在容器执行chroot/pivot_root之前,容器是可以查看到宿主机的全部文件系统,只需要在rootfs准备好后,执行chroot或pivot_root之前,将指定宿主机的目录,挂载到容器目录/test(overlay2 对应/var/lib/docker/overlay2/[可读写层ID]/merged/test上、aufs在/var/lib/docker/aufs/mnt/[可读写层ID]/test上),因为执行这个操作时,mount namespace已经创建,所以挂载事件只能在容器内可见,而宿主机不可见。

    以上操作都是docker创建的初始化进程dockerinit进行的,dockerinit负责根目录的准备,挂载设备和目录,配置hostname等一系列在容器内进行的初始化操作,随后通过调用execv()系统调用,让应用进程取代自己,成为pid 1的进程。

    使用的挂载技术就是Linux绑定挂载(mount --bind)

    mount --bind /home /test 会将/home挂载到/test上,所做的修改都是对被挂载目录的修改,一旦执行unmount命令,/test 目录原来的内容就会恢复。

    并且宿主机并不知道这个挂载的存在,所以在宿主机眼中,容器在宿主机上对应/test目录始终是空的。因为docker commit是在宿主机视角去执行的,因此不会携带/test目录里的内容,但是/test目录还是会被提交并出现在新的镜像中。

  • 相关阅读:
    Codeforces 1132D
    Codeforces 670F
    Codeforces 670E
    Codeforces 670E
    Codeforces 670E
    Codeforces 670
    Codeforces 1138
    Codeforces 1114E
    力扣21.合并两个有序链表
    力扣538.把二叉树转换为累加树
  • 原文地址:https://www.cnblogs.com/tiandz/p/12963413.html
Copyright © 2011-2022 走看看