Elasticsearch7在容器中运行的时候是怎么感知到内存limit然后传递给java的xms和xmx参数:修订间差异
(创建页面,内容为“首先,看一下elasticsearch容器的启动命令,避免被<code>exec</code> 迷惑 [root@gzu1 ~]# docker inspect 1.1.1.1/library/elasticsearch:7.17.5| jq '.[].ContainerConfig | {Cmd,Entrypoint} ' { "Cmd": [ "/bin/sh", "-c", "#(nop) ", "CMD [\"eswrapper\"]" ], "Entrypoint": [ "/bin/tini", "--", "/usr/local/bin/docker-entrypoint.sh" ] } 进入到 es 容器中确认,与1号进程是预期一致的 [root@gz…”) |
小无编辑摘要 |
||
| 第25行: | 第25行: | ||
root 64430 0.0 0.0 5900 1492 pts/1 R+ 05:22 0:00 ps auxwwww | root 64430 0.0 0.0 5900 1492 pts/1 R+ 05:22 0:00 ps auxwwww | ||
'''<br />可以看到这里实际的运行 elasticsearch 的 java 命令中,居然有Xms 和Xmx,而且是 pod 内存限制的一半''' | |||
可以看到这里实际的运行 elasticsearch | |||
而在当前pod yaml中,并没有指定这些参数: | 而在当前pod yaml中,并没有指定这些参数: | ||
| 第102行: | 第101行: | ||
"env": [ | "env": [ | ||
[root@gzu1 ~]# | [root@gzu1 ~]# | ||
这时候打开 <code>/usr/local/bin/docker-entrypoint.sh</code> 脚本开始检查 该 elasticsearch 的初始化过程,能发现 | 这时候打开 <code>/usr/local/bin/docker-entrypoint.sh</code> 脚本开始检查 该 elasticsearch 的初始化过程,能发现 | ||
| 第109行: | 第106行: | ||
<code>/usr/local/bin/docker-entrypoint.sh</code> 经过一些简单的初始化以后,还会按需通过读取一些文件,转化为本文暂时不关注的环境变量,最后会调用 <code>/usr/share/elasticsearch/bin/elasticsearch</code> | <code>/usr/local/bin/docker-entrypoint.sh</code> 经过一些简单的初始化以后,还会按需通过读取一些文件,转化为本文暂时不关注的环境变量,最后会调用 <code>/usr/share/elasticsearch/bin/elasticsearch</code> | ||
而 <code>/usr/share/elasticsearch/bin/elasticsearch</code> | 而 <code>/usr/share/elasticsearch/bin/elasticsearch</code> ,众所周知,他还是一个脚本 | ||
在该脚本中,他会执行 <code>source "`dirname "$0"`"/elasticsearch-env</code> ,也就是通过 <code>/usr/share/elasticsearch/bin/elasticsearch-env</code> 做一些环境初始化, 例如定义<code>ES_JAVA_HOME</code> 环境变量,以及决定用内置<code>jdk</code>还是通过<code>env</code>指定的<code>jdk</code>。还会按需通过读取一些文件,转化为本文暂时不关注的环境变量 | 在该脚本中,他会执行 <code>source "`dirname "$0"`"/elasticsearch-env</code> ,也就是通过 <code>/usr/share/elasticsearch/bin/elasticsearch-env</code> 做一些环境初始化, 例如定义<code>ES_JAVA_HOME</code> 环境变量,以及决定用内置<code>jdk</code>还是通过<code>env</code>指定的<code>jdk</code>。还会按需通过读取一些文件,转化为本文暂时不关注的环境变量 | ||
2025年6月19日 (四) 13:49的最新版本
首先,看一下elasticsearch容器的启动命令,避免被exec 迷惑
[root@gzu1 ~]# docker inspect 1.1.1.1/library/elasticsearch:7.17.5| jq '.[].ContainerConfig | {Cmd,Entrypoint} '
{
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"eswrapper\"]"
],
"Entrypoint": [
"/bin/tini",
"--",
"/usr/local/bin/docker-entrypoint.sh"
]
}
进入到 es 容器中确认,与1号进程是预期一致的
[root@gzu1 ~]# kubectl exec -it -n es-system es-data-0 -- bash root@es-data-0:/usr/share/elasticsearch# ps auxwwww USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 2500 540 ? Ss Mar27 3:07 /bin/tini -- /usr/local/bin/docker-entrypoint.sh eswrapper elastic+ 7 103 4.7 103849888 18890788 ? Sl Mar27 124591:05 /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -XX:+ShowCodeDetailsInExceptionMessages -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dio.netty.allocator.numDirectArenas=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j2.formatMsgNoLookups=true -Djava.locale.providers=SPI,COMPAT --add-opens=java.base/java.io=ALL-UNNAMED -Djava.security.manager=allow -XX:+UseG1GC -Djava.io.tmpdir=/tmp/elasticsearch-2689440660253749261 -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError -XX:HeapDumpPath=data -XX:ErrorFile=logs/hs_err_pid%p.log -Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m -Des.cgroups.hierarchy.override=/ -Xms16384m -Xmx16384m -XX:MaxDirectMemorySize=8589934592 -XX:InitiatingHeapOccupancyPercent=30 -XX:G1ReservePercent=25 -Des.path.home=/usr/share/elasticsearch -Des.path.conf=/usr/share/elasticsearch/config -Des.distribution.flavor=default -Des.distribution.type=docker -Des.bundled_jdk=true -cp /usr/share/elasticsearch/lib/* org.elasticsearch.bootstrap.Elasticsearch elastic+ 224 0.0 0.0 108392 4636 ? Sl Mar27 0:00 /usr/share/elasticsearch/modules/x-pack-ml/platform/linux-x86_64/bin/controller root 50256 0.0 0.0 4244 2324 pts/0 Ss+ 04:05 0:00 bash root 64422 0.3 0.0 4376 2328 pts/1 Ss 05:22 0:00 bash root 64430 0.0 0.0 5900 1492 pts/1 R+ 05:22 0:00 ps auxwwww
可以看到这里实际的运行 elasticsearch 的 java 命令中,居然有Xms 和Xmx,而且是 pod 内存限制的一半
而在当前pod yaml中,并没有指定这些参数:
[root@gzu1 ~]# kubectl get pods -n es-system es-data-0 -o json | jq '.spec.containers[].resources'
{
"limits": {
"cpu": "8",
"memory": "32Gi"
},
"requests": {
"cpu": "4",
"memory": "32Gi"
}
}
[root@gzu1 ~]# kubectl get pods -n es-system es-data-0 -o json | jq '.spec.containers[].env'
[
{
"name": "POD_IP",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "status.podIP"
}
}
},
{
"name": "POD_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.name"
}
}
},
{
"name": "NODE_NAME",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "spec.nodeName"
}
}
},
{
"name": "NAMESPACE",
"valueFrom": {
"fieldRef": {
"apiVersion": "v1",
"fieldPath": "metadata.namespace"
}
}
},
{
"name": "PROBE_PASSWORD_PATH",
"value": "/mnt/elastic-internal/probe-user/elastic-internal-probe"
},
{
"name": "PROBE_USERNAME",
"value": "elastic-internal-probe"
},
{
"name": "READINESS_PROBE_PROTOCOL",
"value": "http"
},
{
"name": "HEADLESS_SERVICE_NAME",
"value": "dmp-es-data"
},
{
"name": "NSS_SDB_USE_CACHE",
"value": "no"
}
]
[root@gzu1 ~]# kubectl get pods -n es-system es-data-0 -o json | jq '.spec.containers[]'|grep -i env # 确认没有通过configmap等其他形式挂入env
"env": [
[root@gzu1 ~]#
这时候打开 /usr/local/bin/docker-entrypoint.sh 脚本开始检查 该 elasticsearch 的初始化过程,能发现
/usr/local/bin/docker-entrypoint.sh 经过一些简单的初始化以后,还会按需通过读取一些文件,转化为本文暂时不关注的环境变量,最后会调用 /usr/share/elasticsearch/bin/elasticsearch
而 /usr/share/elasticsearch/bin/elasticsearch ,众所周知,他还是一个脚本
在该脚本中,他会执行 source "`dirname "$0"`"/elasticsearch-env ,也就是通过 /usr/share/elasticsearch/bin/elasticsearch-env 做一些环境初始化, 例如定义ES_JAVA_HOME 环境变量,以及决定用内置jdk还是通过env指定的jdk。还会按需通过读取一些文件,转化为本文暂时不关注的环境变量
然后在指定完需要用哪个 java 以后,回到/usr/share/elasticsearch/bin/elasticsearch
可以看到存在一些不起眼的代码
# CONTROLLING STARTUP: # # This script relies on a few environment variables to determine startup # behavior, those variables are: # # ES_PATH_CONF -- Path to config directory # ES_JAVA_OPTS -- External Java Opts on top of the defaults set # # Optionally, exact memory values can be set using the `ES_JAVA_OPTS`. Example # values are "512m", and "10g". # # ES_JAVA_OPTS="-Xms8g -Xmx8g" ./bin/elasticsearch ........ if [ -z "$ES_TMPDIR" ]; then ES_TMPDIR=`"$JAVA" "$XSHARE" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.TempDirectory` fi ....... # The JVM options parser produces the final JVM options to start Elasticsearch. # It does this by incorporating JVM options in the following way: # - first, system JVM options are applied (these are hardcoded options in the # parser) # - second, JVM options are read from jvm.options and jvm.options.d/*.options # - third, JVM options from ES_JAVA_OPTS are applied # - fourth, ergonomic JVM options are applied ES_JAVA_OPTS=`export ES_TMPDIR; "$JAVA" "$XSHARE" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.JvmOptionsParser "$ES_PATH_CONF" "$ES_HOME/plugins"`
我们在 elasticsearch 容器中同样执行这些代码看看效果:
root@es-data-0:/usr/share/elasticsearch# /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -cp "/usr/share/elasticsearch/lib/*" org.elasticsearch.tools.launchers.TempDirectory /tmp/elasticsearch-9132815636720135492 root@es-data-0:/usr/share/elasticsearch# export ES_TMPDIR=/tmp/elasticsearch-9132815636720135492 root@es-data-0:/usr/share/elasticsearch# /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -cp "/usr/share/elasticsearch/lib/*" org.elasticsearch.tools.launchers.JvmOptionsParser /usr/share/elasticsearch/config /usr/share/elasticsearch/plugins -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -XX:+ShowCodeDetailsInExceptionMessages -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dio.netty.allocator.numDirectArenas=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j2.formatMsgNoLookups=true -Djava.locale.providers=SPI,COMPAT --add-opens=java.base/java.io=ALL-UNNAMED -Djava.security.manager=allow -XX:+UseG1GC -Djava.io.tmpdir=/tmp/elasticsearch-9132815636720135492 -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError -XX:HeapDumpPath=data -XX:ErrorFile=logs/hs_err_pid%p.log -Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m -Xms16384m -Xmx16384m -XX:MaxDirectMemorySize=8589934592 -XX:InitiatingHeapOccupancyPercent=30 -XX:G1ReservePercent=25
在这里找到了Xms 和 Xmx的定义,也就是说 /usr/share/elasticsearch/bin/elasticsearch 脚本会通过执行 org.elasticsearch.tools.launchers.TempDirectory 产生一个临时文件夹,然后继续执行 org.elasticsearch.tools.launchers.JvmOptionsParser 产生合适的 Xms 及 Xmx 参数
而如果我们在环境变量中预先定义了 ES_JAVA_OPTS ,就会有如下效果(在该脚本注释中也有提到)
root@es-data-0:/usr/share/elasticsearch# export ES_JAVA_OPTS="-Xms8g -Xmx8g" root@es-data-0:/usr/share/elasticsearch# /usr/share/elasticsearch/jdk/bin/java -Xshare:auto -cp "/usr/share/elasticsearch/lib/*" org.elasticsearch.tools.launchers.JvmOptionsParser /usr/share/elasticsearch/config /usr/share/elasticsearch/plugins -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -XX:+ShowCodeDetailsInExceptionMessages -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dio.netty.allocator.numDirectArenas=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j2.formatMsgNoLookups=true -Djava.locale.providers=SPI,COMPAT --add-opens=java.base/java.io=ALL-UNNAMED -Djava.security.manager=allow -XX:+UseG1GC -Djava.io.tmpdir=/tmp/elasticsearch-9132815636720135492 -XX:+HeapDumpOnOutOfMemoryError -XX:+ExitOnOutOfMemoryError -XX:HeapDumpPath=data -XX:ErrorFile=logs/hs_err_pid%p.log -Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m -Xms8g -Xmx8g -XX:MaxDirectMemorySize=4294967296 -XX:InitiatingHeapOccupancyPercent=30 -XX:G1ReservePercent=25