【问题标题】:Run a script after starting tomcat at k8s pod startupk8s pod启动时启动tomcat后运行脚本
【发布时间】:2020-01-20 05:53:21
【问题描述】:

我正在尝试在 pod 中启动 tomcat 后运行一个 pod-bootstrapping 脚本(它基本上运行一个 java 程序)。我的 pod 运行一个基于 tomcat 的容器。这是我正在工作和重新工作的 sn-p:

     - image: myreg/mydir/myimg:local
       name: tomcat-adminapp
       command: ["/bin/sh"]
       args: ["-c", "$CATALINA_HOME/bin/startup.sh && /scripts/runUpg.sh"]

runUpg.sh 脚本:

#!/bin/sh
ls -l $CATALINA_HOME/webapps/app/WEB-INF/lib/
chmod 755 $CATALINA_HOME/webapps/app/WEB-INF/lib/*
java -classpath "$CATALINA_HOME/webapps/app/WEB-INF/lib/*" com.myclass.Upg <args> 
tail -f /dev/nul

它正在启动 tomcat,但我的脚本执行失败。当我执行到 pod 中时,我看到战争爆发了,CATALINA_HOME 已设置并且 tomcat 进程正在运行。但我在 kubectl 日志中看到以下脚本错误:

ls: 无法访问'/userhome/tomcat/webapps/app/WEB-INF/lib/': 没有这样的文件或目录 chmod:无法访问'/userhome/tomcat/webapps/app/WEB-INF/lib/*':没有这样的文件或目录 错误:无法找到或加载主类 com.myclass.Upg 引起:java.lang.ClassNotFoundException: com.myclass.Upg

从错误中我猜测 shell 脚本可能没有等待 tomcat 完成启动。我不知道为什么..

当我从 pod 内部手动运行脚本时,它运行良好。

这里的任何指针表示赞赏..

更新:我确认确实是时间问题。当我使用$CATALINA_HOME/bin/startup.sh &amp;&amp; sleep 60 &amp;&amp; /scripts/runUpg.sh 时,脚本似乎运行良好。但我认为这是 hack-ish 而不是在 webapp 中调用类的正确方法。

【问题讨论】:

    标签: tomcat kubernetes


    【解决方案1】:

    考虑 postStart 钩子在容器启动后执行脚本。

    示例参考

    
    apiVersion: v1
    kind: Pod
    metadata:
      name: lifecycle-demo
    spec:
      containers:
      - name: lifecycle-demo-container
        image: nginx
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
    

    【讨论】:

      【解决方案2】:

      有些事情在我看来“可疑”:

      1. /userhome/tomcate/webapps/app/WEB-INF/lib - 不应该是/user/home吗? (这只是一个旁注,我假设你已经正确定义了它)

      2. 真正的问题。我不记得tomcat脚本是如何定义的,但是没有kubernetes的事件你可以尝试运行tomcat启动脚本并立即在lib文件夹上运行ls之类的东西。该文件夹确实不存在的可能性,这就是原因(在我的理解中,再次):

      Tomcat(作为独立进程)的编写方式是“始终”运行,但有时您可以将“WARs”放入 webapps 文件夹,它会提取 WAR 并启动应用程序。然后你可以稍后再次发动另一场战争等等。换句话说,Tomcat作为一个进程的生命周期并不绑定应用的生命周期

      tomcat本身的启动过程应该是读取配置,创建HTTP连接器监听8080端口什么的,就这样,脚本完成后,tomcat启动。

      在解决方案方面:

      不要依赖 tomcat 为您创建进程的类路径,这是错误的。 相反,您可以:

      1. 将您的进程包装到 WAR 中,以便 tomcat 也可以管理它,它可以再次为多个 WAR 提供服务,而不仅仅是一个
      2. 使用您的应用程序创建一个 sidecar 容器,以便 2 个容器将在 pod 中并排运行。这是一种 Kubernetes 的做事方式,可能是最好的解决方案。在任何情况下,com.myclass.Upg 进程都应该是自包含的(意味着包含它自己的依赖项)。

      【讨论】:

      • 1.正在执行的类被包装在一个 jar 中,该 jar 位于在 tomcat 启动时存在于容器中的 war 中。只是对 main() 的调用来自外部脚本。 2. 这个 pod 的目的完全是只需要在 pod-startup 时运行一个可执行文件,并在可执行文件退出后消失。我认为我可以在主容器中执行此操作而无需侧车。
      • 是不是和应用在同一场战争中?
      • 是的,它与应用程序是同一场战争。所以我想让 tomcat 启动我的应用程序,然后我想在其中运行一个类。此外,在tomcat的startup.sh之后我用&amp;&amp;字符串的任何命令似乎都可以正常执行。只是应用程序需要时间才能出现。 (更新了我原来的帖子)
      • 认为我不能放弃战争,而是放弃爆炸战争,这样即使在 tomcat 使应用程序运行之前,磁盘上的所有 jar 文件都可用。
      • 那么还有另一种解决方案。 Web 应用程序的生命周期与 WAR 的生命周期绑定。因此,您可以创建一个侦听器,而不是运行另一个进程,当您的战争结束时,该侦听器将被自动调用为 tomcat。此侦听器是一个 java 代码,因此您可以只创建一个 Upg 对象并运行它的方法。请参阅此处有关 servlet 上下文侦听器的第 5 段(您需要实现 contextInitialized 方法)journaldev.com/1945/…
      猜你喜欢
      • 2013-10-01
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-01
      • 1970-01-01
      • 2016-01-05
      相关资源
      最近更新 更多