1

詹金斯版本: 1.643.2

Docker 插件版本: 0.16.0

在我的 Jenkins 环境中,我有一个带有 2-5 个从节点服务器(slave1、slave2、slave3)的 Jenkins 主服务器。

这些从站中的每一个都使用 Docker 插件在 Jenkins 全局配置中进行配置。

此刻一切正常。

我看到我们的监控系统对 slave3 上的高 SWAP 空间使用率发出了一些警报(对于 ex IP:11.22.33.44),所以我 ssh'ed 到那台机器并运行:sudo docker ps这给了我这个 slave3 上当前正在运行的 docker 容器的有效输出机器。

通过ps -eo pmem,pcpu,vsize,pid,cmd | sort -k 1 -nr | head -10在目标从属机器上运行(其中运行 4 个容器),我发现消耗所有 RAM 的前 5 个进程java -jar slave.jar正在每个容器内运行。所以我想为什么不重新启动狗屎并收回一些记忆。在以下输出中,我看到了该步骤sudo docker ps之前和之后的命令状态。docker restart <container_instance>向右滚动,您会注意到在容器 ID 以 结尾的第二行中,主机(slave3)机器上...0a02的虚拟端口(列在标题NAMES下)是 1053(映射到容器的虚拟 IP 的端口 22 用于 SSH)。很酷,这意味着,当来自 JenkinsManage Node部分,如果您尝试重新启动从属容器,Jenkins 将尝试连接到主机 IP 的 11.22.33.44:1053 并执行任何应该成功启动从属的操作。所以,詹金斯在某个地方持有那个端口(1053)。

CONTAINER ID        IMAGE                                                   COMMAND                  CREATED             STATUS              PORTS                  NAMES
ae3eb02a278d        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   26 hours ago        Up 26 hours         0.0.0.0:1048->22/tcp   lonely_lalande
d4745b720a02        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   9 days ago          Up About an hour    0.0.0.0:1053->22/tcp   cocky_yonath
bd9e451265a6        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   9 days ago          Up About an hour    0.0.0.0:1050->22/tcp   stoic_bell
0e905a6c3851        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   9 days ago          Up About an hour    0.0.0.0:1051->22/tcp   serene_tesla

sudo docker restart d4745b720a02; echo $?
d4745b720a02
0

CONTAINER ID        IMAGE                                                   COMMAND                  CREATED             STATUS              PORTS                  NAMES
ae3eb02a278d        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   26 hours ago        Up 26 hours         0.0.0.0:1048->22/tcp   lonely_lalande
d4745b720a02        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   9 days ago          Up 4 seconds        0.0.0.0:1054->22/tcp   cocky_yonath
bd9e451265a6        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   9 days ago          Up About an hour    0.0.0.0:1050->22/tcp   stoic_bell
0e905a6c3851        docker.someinstance.coolcompany.com:443/jenkins-slave-stable-image:1.1   "bash -c '/usr/sbin/s"   9 days ago          Up About an hour    0.0.0.0:1051->22/tcp   serene_tesla

运行后,sudo docker restart <instanceIDofContainer>我运行free -h/grep -i swap /proc/meminfo发现 RAM(之前已完全使用,仅显示剩余 230MB 可用空间)现在是 1GB 可用空间,SWAP 大小总共为 1G,使用了 1G(我尝试了 swappiness 60 或 10),现在是 450MB交换空间免费。所以警报的事情得到了解决。凉爽的。

但是,现在正如您从sudo docker ps上面的输出中注意到的那样,在重新启动步骤之后,对于该容器 ID ...0a02,我现在得到了一个新的 PORT# 1054!

当我转到管理节点 > 尝试使该节点脱机、停止并重新启动它时,Jenkins 没有选择新端口 (1054)。它仍然以某种方式选择旧端口 1053(同时尝试在端口 1053 上建立与 11.22.33.44(主机 IP)的 SSH 连接,该端口映射到容器的虚拟 IP 端口#22(ssh))。

如何在 Jenkins 中为此从容器更改此端口或配置,以便 Jenkins 可以看到新端口并成功重新启动?

PS:单击节点上的“配置”以查看它的配置除了名称字段之外没有显示任何内容。通常在常规从属设备中有很多字段(您可以在其中定义标签、根目录、启动方法、属性 env 变量、从属环境的工具,但我猜对于这些 Docker 容器,除了名称字段)。单击Jenkins Global 配置中的测试连接(在Docker插件部分下)显示它已成功找到 Docker 版本 1.8.3

现在,由于 1053 端口 (telnet) 无法正常工作,因为该容器的 instanceID 现在是 1054(在重新启动步骤之后),Jenkins 重新启动步骤在 SSH 连接步骤期间失败(它首先通过 SSH 方法连接)。

在此处输入图像描述

[07/27/17 17:17:19] [SSH] Opening SSH connection to 11.22.33.44:1053.
Connection timed out
ERROR: Unexpected error in launching a slave. This is probably a bug in Jenkins.
java.lang.IllegalStateException: Connection is not established!
    at com.trilead.ssh2.Connection.getRemainingAuthMethods(Connection.java:1030)
    at com.cloudbees.jenkins.plugins.sshcredentials.impl.TrileadSSHPasswordAuthenticator.canAuthenticate(TrileadSSHPasswordAuthenticator.java:82)
    at com.cloudbees.jenkins.plugins.sshcredentials.SSHAuthenticator.newInstance(SSHAuthenticator.java:207)
    at com.cloudbees.jenkins.plugins.sshcredentials.SSHAuthenticator.newInstance(SSHAuthenticator.java:169)
    at hudson.plugins.sshslaves.SSHLauncher.openConnection(SSHLauncher.java:1212)
    at hudson.plugins.sshslaves.SSHLauncher$2.call(SSHLauncher.java:711)
    at hudson.plugins.sshslaves.SSHLauncher$2.call(SSHLauncher.java:706)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
[07/27/17 17:19:26] Launch failed - cleaning up connection
[07/27/17 17:19:26] [SSH] Connection closed.
4

1 回答 1

0

好的。宙斯!

在 JENKINS_HOME(主服务器的)中,我搜索了哪个配置文件保存了该/那些容器节点的旧端口#信息,这些节点现在显示为离线。

将目录更改为:$JENKINS_HOME 内的节点文件夹,发现每个节点都有 config.xml 文件。

例如: $JENKINS_HOME/nodes / <slave3_node_IP>-d4745b720a02/config.xml

解决步骤

  1. Vim 编辑文件以将 OLD 更改为 NEW 端口。
  2. 管理 Jenkins > 从磁盘重新加载配置。
  3. 管理节点 > 选择离线的特定节点。
  4. 重新启动从站,这一次 Jenkins 选择了新的 PORT 并按预期启动了容器从站(配置更改后与新端口的 SSH 连接可见)。

我认为这个页面:https<slave3_IP> ://my.company.jenkins.instance.com/projectInstance/docker-plugin/server//网页,它显示了所有容器信息(以表格形式在给定的从机上运行) ,此页面有一个按钮(最后一列)用于停止给定从属容器的容器,但不用于启动或重新启动。

有一个STARTRESTART按钮应该以某种方式完成我刚刚在上面所做的事情。

更好的解决方案:

发生的事情是,在 slave3 上运行的所有 4 个长期存在的容器节点都在竞争获得所有可用的 RAM(11-12GB),并且随着时间的推移,JVM 进程(java -jar slave.jar 重新启动步骤在目标容器的单个容器的 slave3 从服务器上运行的虚拟机 (IP) 试图尽可能多地占用内存 (RAM)。这导致了低可用内存,因此 SWAP 被使用并且也被使用到监控工具将开始通过发送通知等向我们尖叫的地步。

要解决这种情况,首先应该做的是:

1)在 Jenkins 全局配置下(管理 Jenkins > 配置系统 > Docker 插件部分,对于该从服务器的Image / Docker 模板,在高级设置部分下,我们可以放置 JVM 选项来告诉容器不要竞争所有 RAM。把以下 JVM 选项有所帮助。这些 JVM 设置将尝试将每个容器的堆空间保持在一个较小的盒子中,以免耗尽系统的其余部分。

您可以从 3-4GB 开始,具体取决于您的从机/机器上将运行基于容器的从机节点的总 RAM。

在此处输入图像描述

2) 查找任何最新版本的 slave.jar(可能有一些性能/维护增强功能,这将有所帮助。

3) 集成监控解决方案(Incinga/etc 你有)来自动启动 Jenkins 作业(Jenkins 作业将运行一些动作 - BASH 一个班轮,Python 狗屎或 Groovy 善良,Ansible 剧本等)以解决相关问题任何此类警报。

4) 自动重新启动容器从节点(即重新启动步骤) - 使从节点离线、在线、重新启动步骤,因为这将使从节点恢复到恢复活力的新鲜状态。我们所要做的就是,寻找一个空闲的奴隶(如果它没有运行任何工作)然后,让它离线>然后在线>然后使用 Jenkins REST API 通过一个小的 Groovy 脚本重新启动奴隶,并将这一切都放在一个 Jenkins 工作中如果这些从节点寿命很长,让它执行上述操作。

5)或者可以在运行中旋转基于容器的从站 -每次 Jenkins 排队运行作业时使用并抛出模型。

于 2017-07-28T01:59:29.540 回答