zoukankan      html  css  js  c++  java
  • 深入剖析Kubernetes学习笔记:深入理解镜像(08)

    一、Python 应用案例环境

    [root@k8s-node1 Flask]# pwd
    /opt/Dockerfile/Flask
    [root@k8s-node1 Flask]# ll
    total 12
    -rw-r--r-- 1 root root 352 Feb  1 10:08 app.py
    -rw-r--r-- 1 root root 518 Feb  1 10:20 Dockerfile
    -rw-r--r-- 1 root root   6 Feb  1 10:09 requirements.txt
    [root@k8s-node1 Flask]# cat app.py
    from flask import Flask
    import socket
    import os
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        html = "<h3>Hello {name}!</h3>" 
               "<b>Hostname:</b> {hostname}<br/>"
        return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname())
    
    if __name__ == "__main__":
        app.run(host='0.0.0.0', port=80)
    [root@k8s-node1 Flask]# cat requirements.txt
    Flask
    [root@k8s-node1 Flask]# cat Dockerfile
    # 使用官方提供的 Python 开发镜像作为基础镜像
    FROM python:2.7-slim
    
    # 将工作目录切换为 /app
    WORKDIR /app
    
    # 将当前目录下的所有内容复制到 /app 下
    ADD . /app
    
    # 使用 pip 命令安装这个应用所需要的依赖
    RUN pip install --trusted-host pypi.python.org -r requirements.txt
    
    # 允许外界访问容器的 80 端口
    EXPOSE 80
    
    # 设置环境变量
    ENV NAME World
    
    # 设置容器进程为:python app.py,即:这个 Python 应用的启动命令
    CMD ["python", "app.py"]
    

    Dockerfile的设计思想,是使用一些标准的原语(即大写高亮的词语),描述我们所要构建的Docker镜像,并且这些原语,都是按顺序处理的

    需要注意的是,Dockerfile中的每个原语执行后,都会生成一个对应的镜像层

    [root@k8s-node1 Flask]# docker images|grep docker.io/python
    docker.io/python

    二、启动容器以及相关操作

    1、启动容器

    $ docker run -p 4000:80 helloworld

    2、查看进程

    $ docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED
    4ddf4638572d        helloworld       "python app.py"     10 seconds ago
    

    3、测试是否可用

    $ curl http://localhost:4000
    <h3>Hello World!</h3><b>Hostname:</b> 4ddf4638572d<br/>

    4、上传镜像到仓库

    [root@k8s-node1 ~]# docker exec -it 900e7b6e1984 /bin/sh#
    # touch test.txt#
    # exit#
    [root@k8s-node1 ~]# docker tag helloworld 10.0.128.4:500/helloworld:v1#
    [root@k8s-node1 ~]# docker push 10.0.128.4:500/helloworld:v1#
    The push refers to a repository [10.0.128.4:500/helloworld]#
    Get https://10.0.128.4:500/v1/_ping: dial tcp 10.0.128.4:500: getsockopt: connection refused                                     "/bin/sh"                2 days ago          Exited (137) 2 days ago  grave_mclean#

    三、docker exec 是怎么做到进入容器里的呢?

    1、docker exec 的实现原理

    [root@k8s-node1 Flask]# docker exec -it 43c49903582e /bin/sh
    # pwd
    /app
    # ls
    Dockerfile  app.py  requirements.txt  test.txt
    

    这里,我使用了docker exec 命令进入到了容器当中,在了解了Linux Namespace的隔离机制后,你应该会很自然地想到一个问题
    docker exec 是怎么做到进入容器里的呢?

    [root@k8s-node1 Flask]# docker inspect --format '{{ .State.Pid }}' 43c49903582e
    2400
    [root@k8s-node1 opt]# ls -l /proc/2400/ns
    total 0
    lrwxrwxrwx 1 root root 0 Feb 20 17:20 ipc -> ipc:[4026532495]
    lrwxrwxrwx 1 root root 0 Feb 20 17:19 mnt -> mnt:[4026532493]
    lrwxrwxrwx 1 root root 0 Feb 20 17:19 net -> net:[4026532498]
    lrwxrwxrwx 1 root root 0 Feb 20 17:20 pid -> pid:[4026532496]
    lrwxrwxrwx 1 root root 0 Feb 20 17:23 user -> user:[4026531837]
    lrwxrwxrwx 1 root root 0 Feb 20 17:20 uts -> uts:[4026532494]

    这也就意味着:一个进程,可以选择加入到某个进程已有的 Namespace 当中,从而达到“进入”这个进程所在容器的目的,这正是 docker exec 的实现原理

    2、docker exec 的实现原理刨析实验

    1、依赖文件

    _startmainopen@@GLIBC_2.2.5perror@@GLIBC_2.2.5_Jv_RegisterClassesexecvp@@GLIBC_2.2.5exit@@GLIBC_2.2.5__TMC_END___ITM_registerTMCloneTable_init
    [root@k8s-node1 opt]# cat set_ns.c
    #define _GNU_SOURCE
    #include <fcntl.h>
    #include <sched.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE);} while (0)
    
    int main(int argc, char *argv[]) {
        int fd;
    
        fd = open(argv[1], O_RDONLY);
        if (setns(fd, 0) == -1) {
            errExit("setns");
        }
        execvp(argv[2], &argv[2]);
        errExit("execvp");
    }
    

    2、执行

    [root@k8s-node1 opt]# gcc -o set_ns set_ns.c
    [root@k8s-node1 opt]# ./set_ns /proc/2400/ns/net /bin/bash
    [root@k8s-node1 opt]# ifconfig
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.16.6.2  netmask 255.255.255.0  broadcast 0.0.0.0
            inet6 fe80::42:acff:fe10:602  prefixlen 64  scopeid 0x20<link>
            ether 02:42:ac:10:06:02  txqueuelen 0  (Ethernet)
            RX packets 8  bytes 648 (648.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 8  bytes 648 (648.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
            inet 127.0.0.1  netmask 255.0.0.0
            inet6 ::1  prefixlen 128  scopeid 0x10<host>
            loop  txqueuelen 1  (Local Loopback)
            RX packets 0  bytes 0 (0.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 0  bytes 0 (0.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    

    3、查看进程的进程的 Namespace

    [root@k8s-node1 opt]# ps aux|grep /bin/bash
    root       2615  0.1  0.0 116204  2876 pts/0    S    17:28   0:00 /bin/bash
    root       2652  0.0  0.0 112660   972 pts/0    R+   17:28   0:00 grep --color=auto /bin/bash
    [root@k8s-node1 opt]# ls -l /proc/2615/ns/net
    lrwxrwxrwx 1 root root 0 Feb 20 17:30 /proc/2615/ns/net -> net:[4026532498]
    [root@k8s-node1 opt]# ls -l /proc/2400/ns/net
    lrwxrwxrwx 1 root root 0 Feb 20 17:19 /proc/2400/ns/net -> net:[4026532498]
    

    转了一个大圈子,我其实是为你详细解读了这个操作背后,linux namespace更具体的工作原理

    这种通过操作系统进程相关的知识,逐步刨析Docker容器的方法,是理解容器的一个关键思路,希望你一定要掌握

  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/luoahong/p/10408208.html
Copyright © 2011-2022 走看看