前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >tomcat-超详细的启动流程(start)

tomcat-超详细的启动流程(start)

作者头像
虞大大
发布于 2020-08-26 09:19:25
发布于 2020-08-26 09:19:25
2.9K00
代码可运行
举报
文章被收录于专栏:码云大作战码云大作战
运行总次数:0
代码可运行

一、Bootstrap.start()

(1)tomcat启动时会先调用脚本,在脚本运行时会启动Bootstrap的main方法,mian方法中会调用load方法进行初始化操作,通过责任链模式将所有结点初始化后,会调用start方法-该方法是tomcat启动的核心方法,即启动tomcat的核心线程。

在上一篇 - tomcat-超详细的启动流程(init)中提过这里的daemon实际上为catalina,因此调用catalina的start方法。

main方法中的源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
try {
    String command = "start";
    if (args.length > 0) {
        command = args[args.length - 1];
    }

    if (command.equals("startd")) {
        args[args.length - 1] = "start";
        daemon.load(args);
        daemon.start();
    } else if (command.equals("stopd")) {
        args[args.length - 1] = "stop";
        daemon.stop();
    } else if (command.equals("start")) { //都会走进该if分支
        daemon.setAwait(true);
        daemon.load(args);
        daemon.start();
    } else if (command.equals("stop")) {
        daemon.stopServer(args);
    } else if (command.equals("configtest")) {
        daemon.load(args);
        if (null == daemon.getServer()) {
            System.exit(1);
        }

        System.exit(0);
    } else {
        log.warn("Bootstrap: command \"" + command + "\" does not exist.");
    }
} catch (Throwable var4) {
    Throwable t = var4;
    if (var4 instanceof InvocationTargetException && var4.getCause() != null) {
        t = var4.getCause();
    }

    handleThrowable(t);
    t.printStackTrace();
    System.exit(1);
}

二、Catalina.start()

本质上与init()方法没啥区别,委派给下一个standardServer结点来进行start方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void start() {

    if (getServer() == null) {
        load();
    }

    if (getServer() == null) {
        log.fatal(sm.getString("catalina.noServer"));
        return;
    }

    long t1 = System.nanoTime();
    try {        //standardServer的start方法        getServer().start();
    } catch (LifecycleException e) {
        log.fatal(sm.getString("catalina.serverStartFail"), e);
        try {
            getServer().destroy();
        } catch (LifecycleException e1) {
            log.debug("destroy() failed for failed Server ", e1);
        }
        return;
    }    //...    //在Bootstrap的main方法中 设置了为true,因此为调用await方法,保证主线程一直处于运行。
    if (await) {
        await();
        stop();
    }
}

这里的start方法也一样,由lifecycleBase来负责统一管理生命周期,并且子类会重新这个start方法,具体源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public final synchronized void start() throws LifecycleException {
    //...  上面不重要
    try {        //设置状态        setStateInternal(LifecycleState.STARTING_PREP, null, false);
        //该方法由子类重写
        startInternal();
        if (state.equals(LifecycleState.FAILED)) {
            stop();
        } else if (!state.equals(LifecycleState.STARTING)) {
            invalidTransition(Lifecycle.AFTER_START_EVENT);
        } else {
            setStateInternal(LifecycleState.STARTED, null, false);
        }
    } catch (Throwable t) {
        handleSubClassException(t, "lifecycleBase.startFail", toString());
    }
}

找到standardServer对应的startInternal方法。

三、StandardServer.startInternal()

在StandardServer.startInternal()中会继续通过责任链模式向后传递,进行StandardService的start方法调用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
protected void startInternal() throws LifecycleException {
//触发监听fireLifecycleEvent(CONFIGURE_START_EVENT, null);
    setState(LifecycleState.STARTING);
    globalNamingResources.start();
    
    //责任链继续向后传递,进行standardService的start方法    synchronized (servicesLock) {
        for (int i = 0; i < services.length; i++) {
            services[i].start();
        }
}//...
}

四、StandardService.startInternal()

从下图源码中可以看出,StandardService.startInternal(),先进行engine的start调用,再进行connector的start调用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
protected void startInternal() throws LifecycleException {

    if(log.isInfoEnabled())
        log.info(sm.getString("standardService.start.name", this.name));
    setState(LifecycleState.STARTING);
    // engine的start
    if (engine != null) {
        synchronized (engine) {
            engine.start();
        }
    }

    //server.xml中无配置executors,所以不会执行这段代码    synchronized (executors) {
        for (Executor executor: executors) {
            executor.start();
        }
    }

    mapperListener.start();
    //connector的start
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            // If it has already failed, don't try and start it
            if (connector.getState() != LifecycleState.FAILED) {
                connector.start();
            }
        }
    }
}

(1)StandardEngine.startInternal()

本质上调用了父类ContainerBase.startInternal()。核心源码如下,在代码中主要作用为将tomcat容器以线程池的方式来启动,这个startStopExecutor是在tomcat的init中被构造出来的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
protected synchronized void startInternal() throws LifecycleException {
    // 前面代码我跳过了,不重要
    Container children[] = findChildren();
    List<Future<Void>> results = new ArrayList<>();
    for (int i = 0; i < children.length; i++) {
        results.add(startStopExecutor.submit(new StartChild(children[i])));
    }
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    //...
}

tomcat容器的关系为:Engine——>Host——>Context——>Wrapper——>Servlet。

进入StartChild线程中可以看到线程实现方式为Callable,并且在child中又使用了start()。即Engine——>Host。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static class StartChild implements Callable<Void> {

    private Container child;
    public StartChild(Container child) {
        this.child = child;
    }

    @Override
    public Void call() throws LifecycleException {
        child.start();
        return null;
    }
}

(2)StandardHost.startInternal()

StandardHost.startInternal()中又递归调用了父类ContainerBase.startInternal方法。即下一个线程池需要启动的子类为StandardContext。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
protected synchronized void startInternal() throws LifecycleException {    // 前面代码...    super.startInternal();
}

(3)StandardContext.startInternal()

StandardContext.startInternal()这里的触发监听,比较核心,在内部会解析web.xml。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected synchronized void startInternal() throws LifecycleException {
    // 前面代码...    try {             // 前面代码...            // 触发监听 - 解析web.xml
            fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
            // 这里child为Context的子类 Wrapper的start的调用
            for (Container child : findChildren()) {
                if (!child.getState().isAvailable()) {
                    child.start();
                }
}//后面代码...}

触发监听,核心代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public void lifecycleEvent(LifecycleEvent event) {
    // 前面代码...
    if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {        //触发监听的type为这一行        configureStart();
    } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
        beforeStart();
    } else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
        if (originalDocBase != null) {
            context.setDocBase(originalDocBase);
        }
    } else if (event.getType().equals(Lifecycle.CONFIGURE_STOP_EVENT)) {
        configureStop();
    } else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) {
        init();
    } else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) {
        destroy();
    }

}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected synchronized void configureStart() {
    //前面代码...
    webConfig();
    // 后面代码...
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
**
 * Scan the web.xml files that apply to the web application and merge them
 * using the rules defined in the spec. For the global web.xml files,
 * where there is duplicate configuration, the most specific level wins. ie
 * an application's web.xml takes precedence over the host level or global
 * web.xml file.
 *///看英文注释可以知道,这个方法是用来解析tomcat的web.xmlprotected void webConfig() {

在webConfig中也可以找到我们经常会配置的一些解析方法,比如servlet、filter等。

下图为filter的解析。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for (FilterDef filter : webxml.getFilters().values()) {
    if (filter.getAsyncSupported() == null) {
        filter.setAsyncSupported("false");
    }
    context.addFilterDef(filter);
}
for (FilterMap filterMap : webxml.getFilterMappings()) {
    context.addFilterMap(filterMap);
}

下图为servlet的解析。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for (ServletDef servlet : webxml.getServlets().values()) {
    Wrapper wrapper = context.createWrapper();
    if (servlet.getLoadOnStartup() != null) {
        wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
    }
    if (servlet.getEnabled() != null) {
        wrapper.setEnabled(servlet.getEnabled().booleanValue());
    }
wrapper.setName(servlet.getServletName());    // ...}

下图为listener的解析。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for (String listener : webxml.getListeners()) {
    context.addApplicationListener(listener);
}

(4)StandardWrapper.startInternal()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected synchronized void startInternal() throws LifecycleException {

    //本质上也一样 调用父类的startInternal() 线程池启动
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    super.startInternal();
    
}

这一步为止,tomcat容器(Engine—>Host—>Context—>Wrapper)启动完毕。

五、mapperListern.startInternal()

回到StandardService,会进行mapperListern的启动。找到子类重写的startInernal(),源码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public void startInternal() throws LifecycleException {

setState(LifecycleState.STARTING);
    // 获取engine    Engine engine = service.getContainer();
    if (engine == null) {
        return;
    }

findDefaultHost();
    // 添加engine中的listerner    addListeners(engine);
    Container[] conHosts = engine.findChildren();
    for (Container conHost : conHosts) {
        Host host = (Host) conHost;
        if (!LifecycleState.NEW.equals(host.getState())) {
            //遍历host-注册host
            registerHost(host);
        }
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void registerHost(Host host) {

    String[] aliases = host.findAliases();
    mapper.addHost(host.getName(), aliases, host);
    for (Container container : host.findChildren()) {
if (container.getState().isAvailable()) {//注册host下的contextregisterContext((Context) container);
        }
    }
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private void registerContext(Context context) {

    String contextPath = context.getPath();
    if ("/".equals(contextPath)) {
        contextPath = "";
    }
    Host host = (Host)context.getParent();
    WebResourceRoot resources = context.getResources();
    String[] welcomeFiles = context.findWelcomeFiles();
    List<WrapperMappingInfo> wrappers = new ArrayList<>();
    for (Container container : context.findChildren()) {        //遍历contxt-注册wrapper        prepareWrapperMappingInfo(context, (Wrapper) container, wrappers);
        if(log.isDebugEnabled()) {
            log.debug(sm.getString("mapperListener.registerWrapper",
                    container.getName(), contextPath, service));
        }
    }
    //最后将host名+host端口+context+wrapper即servlet 添加到mapper中。
    mapper.addContextVersion(host.getName(), host, contextPath,
            context.getWebappVersion(), context, welcomeFiles, resources,
            wrappers);
    if(log.isDebugEnabled()) {
        log.debug(sm.getString("mapperListener.registerContext",
                contextPath, service));
    }
}

在mapper中会注册engine、host、context、wrapper,组成host名+host端口+context路径+context应用名+servlet添加到mapper中,因此当接受到http请求时,如果tomcat有多个工程,多个host情况下,可以根据url拆分然后然后根据mapper来进行匹配。

六、Connector.startInternal()

责任链模式委托protocolHandler.start(),实际上未NioEndpoint.startInternal()

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected void startInternal() throws LifecycleException {
    if (getPortWithOffset() < 0) {
        throw new LifecycleException(sm.getString(
                "coyoteConnector.invalidPort", Integer.valueOf(getPortWithOffset())));
    }

    setState(LifecycleState.STARTING);
    try {        //protocolHandler的启动        protocolHandler.start();
    } catch (Exception e) {
        throw new LifecycleException(
                sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
    }
}

七、NioEndpoint.startInternal()

(1)在NioEndpoint.startInternal()中会创建工作线程池、clientPoller线程池、acceptor线程池。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void startInternal() throws Exception {

    if (!running) {
        //...
        if ( getExecutor() == null ) {            //启动工作线程,            createExecutor();
        }

        initializeConnectionLatch();
        
        pollers = new Poller[getPollerThreadCount()];
        for (int i=0; i<pollers.length; i++) {
            pollers[i] = new Poller();
            Thread pollerThread       //启动clientPoller线程
       = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
            pollerThread.setPriority(threadPriority);
            pollerThread.setDaemon(true);
            pollerThread.start();
        }
        //创建acceptor线程
        startAcceptorThreads();
    }
}

最小线程数量默认为10,最大线程数量默认为200,也可读取server.xml中配置的线程数量。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void createExecutor() {
    internalExecutor = true;
    TaskQueue taskqueue = new TaskQueue();
    TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
    executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
    taskqueue.setParent( (ThreadPoolExecutor) executor);
}

(2)acceptor线程

在下面方法中会启动,acceptor线程,并创建acceptor对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected void startAcceptorThreads() {
    int count = getAcceptorThreadCount();
    acceptors = new ArrayList<>(count);
    for (int i = 0; i < count; i++) {
        Acceptor<U> acceptor = new Acceptor<>(this);
        String threadName = getName() + "-Acceptor-" + i;
        acceptor.setThreadName(threadName);
        acceptors.add(acceptor);
        Thread t = new Thread(acceptor, threadName);
        t.setPriority(getAcceptorThreadPriority());
        t.setDaemon(getDaemon());
        t.start();
    }
}

启动线程后,查询acceptor线程的run方法,发现acceptor中会建立socket连接,可以接收http请求。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
public void run() {
    while (endpoint.isRunning()) {

        try {
            U socket = null;
            try {
                //接收socket
                socket = endpoint.serverSocketAccept();
            } catch (Exception ioe) {
               //...
            }
           
        } catch (Throwable t) {
           //...//...//...
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
        }
    }
}

到这一步tomcat完全启动成功,并且开启了对应的线程,可以接受http请求,处理http请求。

八、总结

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码云大作战 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
Kubernetes 1.28:Sidecar 容器、Job和Proxy的新功能
Kubernetes 1.28 现已发布,具有 44 项新的或改进的增强功能! 此版本包含许多主要功能,例如对 sidecar 容器的内置支持、作业优化和更好的代理。 这些新功能可以帮助您提高 Kubernetes 集群的性能、效率和安全性。
从大数据到人工智能
2023/10/18
1K0
Kubernetes 1.28:Sidecar 容器、Job和Proxy的新功能
Kubernetes 1.25:对使用用户名字空间运行 Pod 提供 Alpha 支持
作者: Rodrigo Campos(Microsoft)、Giuseppe Scrivano(Red Hat)
CNCF
2022/11/28
5350
Kubernetes v1.30 新特性一览
各位 Kubernetes 用户们,请注意!1.30版本即将发布,这将对运维和开发者带来强大的功能。以下是关键特性的详细介绍:
用户1107783
2024/03/25
6120
Kubernetes v1.30 新特性一览
不讲武德,Kubernetes 弃用 Docker刷爆了网络,我们公司也慌了!
目前,kubelet 中的 Docker 支持功能现已弃用,并将在之后的版本中被删除。Kubelet 之前使用的是一个名为 dockershim 的模块,用以实现对 Docker 的 CRI 支持。但 Kubernetes 社区发现了与之相关的维护问题,因此建议大家考虑使用包含 CRI 完整实现(兼容 v1alpha1 或 v1)的可用容器运行时。
芋道源码
2020/12/09
5320
不讲武德,Kubernetes 弃用 Docker刷爆了网络,我们公司也慌了!
容器安全与安全运行环境的重要性
了解容器运行环境的工作机制,缘何若攻击者突破容器的限制,过度耦合的运行环境可能造成主机被接管,以及gVisor和Kata Containers等安全容器运行环境的好处。
云云众生s
2024/03/28
2180
K8s宣布弃用Docker,千万别慌!
近日,Kubernetes 官方发布公告,宣布自 v1.20 起放弃对 Docker 的支持,届时用户将收到 Docker 弃用警告,并需要改用其他容器运行时。
SDNLAB
2020/12/09
15K0
K8s宣布弃用Docker,千万别慌!
Runc 容器初始化和容器逃逸
在每一个 Kubernetes 节点中,运行着 kubelet,负责为 Pod 创建销毁容器,kubelet 预定义了 API 接口,通过 GRPC 从指定的位置调用特定的 API 进行相关操作。而这些 CRI 的实现者,如 cri-o, containerd 等,通过调用 runc 创建出容器。runc 功能相对单一,即针对特定的配置,构建出容器运行指定进程,它不能直接用来构建镜像,kubernetes 依赖的如 cri-o 这类 CRI,在 runc 基础上增加了通过 API 管理镜像,容器等功能。
米开朗基杨
2021/02/25
9390
Runc 容器初始化和容器逃逸
Docker,containerd,CRI,CRI-O,OCI,runc 分不清?看这一篇就够了
自 Docker 开启了使用容器的爆发式增长,有越来越多的工具和标准来帮助管理和使用这项容器化技术,与此同时也造成了有很多术语让人感到困惑。
Peter Shen
2022/04/26
5.2K0
Docker,containerd,CRI,CRI-O,OCI,runc 分不清?看这一篇就够了
2022 年 Kubernetes 高危漏洞盘点
2022 年,Kubernetes继续巩固自己作为关键基础设施领域的地位。从小型到大型组织,它已成为广受欢迎的选择。出于显而易见的原因,这种转变使 Kubernetes 更容易受到攻击。但这还没有结束,开发人员通常将Kubernetes 部署与其他云原生组件一起使用来构建一个完善的工作系统。不幸的是,这种组合会导致具有更多组件的更复杂的基础架构。这最终会增加易受攻击的表面积和范围。
用户5166556
2023/03/18
1.9K0
2022 年 Kubernetes 高危漏洞盘点
1.Containerd容器运行时初识与尝试
本章主要讲解,目前K8S使用率最多的容器运行时讲解, 由于k8s在2020年宣布1.20版本之后将弃用dockershim(其中也有kubernetes与Docker爱恨情仇)时才把containerd拉回大众的视野之中,本章主要讲解containerd基础入门。
全栈工程师修炼指南
2021/07/25
2.8K0
1.Containerd容器运行时初识与尝试
Inspektor Gadget:云原生时代下的 eBPF 工具链框架
Hello folks,我是 Luga,今天我们来聊一下云原生生态领域的 eBPF 工具链管理框架 - Inspektor Gadget 。
Luga Lee
2023/11/17
4970
Inspektor Gadget:云原生时代下的 eBPF 工具链框架
【容器安全系列Ⅱ】- 容器隔离与命名空间深度解析
在本系列的第一部分中,我们了解到容器实际上只是 Linux 进程。现在,我们需要了解容器如何与主机的其余部分隔离。换句话说,我们如何确保在一个容器中运行的进程不会轻易干扰另一个容器或底层主机的操作?
星尘安全
2024/08/17
2020
【容器安全系列Ⅱ】- 容器隔离与命名空间深度解析
经验分享:Docker安全的26项检查清单(checklist)
容器以及编排工具(例如Kubernetes)开创了应用开发的新时代,让微服务架构以及CI/CD的实现成为了可能。Docker是迄今为止最主要的容器运行时引擎。然而,使用Docker容器构建应用也引入了新的安全挑战和风险。
Jintao Zhang
2022/12/07
8570
经验分享:Docker安全的26项检查清单(checklist)
【K8s】Kubernetes 网络之 Pod 网络调试
在实际工作中,我们经常会遇到一些疑似网络方面的故障问题,从而需要对 Kubernetes 集群中的 Pod 进行网络调试。
行者Sun
2024/12/27
1260
【K8s】Kubernetes 网络之 Pod 网络调试
带你搞懂Kubernetes Pod 如何获取 IP 地址
Kubernetes 网络模型的核心要求之一是每个 Pod 都应该有自己的 IP 地址,并且集群中的每个 Pod 都应该能够使用这个 IP 地址与其进行通信。有多个网络提供商(flannel、calico、canal 等)实现了这种网络模型。
用户1107783
2024/04/18
4590
带你搞懂Kubernetes Pod 如何获取 IP 地址
容器运行时
要把进程运行在容器中,还需要有便捷的SDK或命令来调用Linux的系统功能,从而创建出容器。容器的运行时(runtime)就是运行和管理容器进程、镜像的工具。
CNCF
2022/11/28
1.6K0
容器运行时
Kubernetes 弃用 Docker刷爆网络,有什么替代品?
通过以上架构图,可以看到每个 Kubernetes 节点都与控制平面彼此通信。各个节点上的 kubelet 获取元数据,并执行 CRI 以在该节点上创建 / 删除容器。 1、但 Docker 为什么会被弃用?
java进阶架构师
2020/12/17
1.4K0
Kubernetes 弃用 Docker刷爆网络,有什么替代品?
OCI容器与Wasm初体验
WebAssembly(Wasm)有一套完整的语义,在web中被设计成无版本、特性可测试、向后兼容的,当然,WebAssembly 不仅可以运行在浏览器上,也可以运行在非web环境下。实际上wasm是体积小且加载快的二进制格式,其目标就是充分发挥硬件能力以达到原生执行效率,在本文中,将介绍以容器镜像方式运行Wasm工作负载的场景,关于运行时的介绍可以参看Containerd深度剖析-runtime篇
zouyee
2023/02/06
1.1K0
细说Containerd CVE-2020–15257
周日有空,zouyee带各位看看11月末CVE-2020–15257的安全漏洞。Containerd是基于OCI规范实现的一款工业级标准的容器运行时。Containerd在宿主机中管理容器生命周期,如容器镜像的传输和存储、容器的执行和管理、存储和网络等。containerd-shim是用作容器运行的载体,实现容器生命周期管理, 其API以抽象命名空间Unix域套接字方式暴露,该套接字可通过根网络名称空间访问。因此,一旦普通用户获得主机网络访问权限(通过启动主机网络模式的容器),则可以访问任一容器的API,并以此提权。例如生命周期管理,高级网络,资源绑定,状态抽象以及这些抽象概念多年来的变化。
zouyee
2021/02/01
1.4K0
细说Containerd CVE-2020–15257
一文搞懂Kubernetes容器运行原理
Hello folks,我是 Luga,今天我们来分享一下与云原生体系有关的话题- 云原生技术-Container。 作为一个“核心”要素之一,容器技术在云原生生态中发挥着重要的意义。
Luga Lee
2023/04/28
1.9K1
一文搞懂Kubernetes容器运行原理
推荐阅读
相关推荐
Kubernetes 1.28:Sidecar 容器、Job和Proxy的新功能
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文