西安旅游攻略2天自由行攻略seo每日一貼
Flink on k8s部署日志詳解及與Yarn部署時(shí)的日志生成模式對(duì)比
最近需要將flink由原先部署到Y(jié)arn集群切換到kubernetes集群,在切換之后需要熟悉flink on k8s的運(yùn)行模式。在使用過(guò)程中針對(duì)日志模塊發(fā)現(xiàn),在k8s的容器中,flink的系統(tǒng)日志只有jobmanager.log/taskmanager.log 兩個(gè),而當(dāng)時(shí)在使用Yarn集群部署時(shí),flink的日志會(huì)有多個(gè),比如:jobmanager.log、jobmanager.err和jobmanager.out,TaskManager同理。
因此,有同事就提出為什么在k8s中部署時(shí),只有.log一個(gè)文件,能不能類(lèi)似Yarn部署時(shí)那樣對(duì)日志文件進(jìn)行區(qū)分。只是從容器日志來(lái)看的話(huà),在一開(kāi)始不夠了解k8s的情況下,會(huì)覺(jué)得日志收集的不夠準(zhǔn)確。
因此針對(duì)上面的這個(gè)問(wèn)題,就歸我進(jìn)行研究和解決了。網(wǎng)上的相關(guān)資料也比較少,因此,在本次對(duì)上面這個(gè)問(wèn)題整體了解分析之后,進(jìn)行一次學(xué)習(xí)記錄。有遇到相關(guān)類(lèi)似問(wèn)題的,也可以參考這個(gè)思路。
一、認(rèn)為需要修改log4j配置即可
拿到這個(gè)問(wèn)題的第一步首先想到的是,既然要對(duì)日志的類(lèi)別進(jìn)行區(qū)分,則可以修改log4j的配置,將INFO類(lèi)別和ERROR類(lèi)別分別寫(xiě)入不同的日志文件即可。于是,先對(duì)flink路徑下的conf/log4j-console.properties進(jìn)行修改(flink on k8s部署時(shí),使用的log4j配置文件是flink-console.properties文件,而不是log4j.properties)。
這里我們留下一個(gè)小疑問(wèn):為什么部署到k8s中時(shí),使用的是log4j-console.properties,而不是部署到Y(jié)arn時(shí)的log4j.properties?有什么區(qū)別?
修改后的log4j-console.properties示例如下所示:
################################################################################
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
################################################################################# Allows this configuration to be modified at runtime. The file will be checked every 30 seconds.
monitorInterval=30# This affects logging for both user code and Flink
rootLogger.level = INFO
rootLogger.appenderRef.console.ref = ConsoleAppender
rootLogger.appenderRef.rolling.ref = RollingFileAppender
rootLogger.appenderRef.errorLogFile.ref = errorLogFile# Uncomment this if you want to _only_ change Flink's logging
#logger.flink.name = org.apache.flink
#logger.flink.level = INFO# The following lines keep the log level of common libraries/connectors on
# log level INFO. The root logger does not override this. You have to manually
# change the log levels here.
logger.akka.name = akka
logger.akka.level = INFO
logger.kafka.name= org.apache.kafka
logger.kafka.level = INFO
logger.hadoop.name = org.apache.hadoop
logger.hadoop.level = INFO
logger.zookeeper.name = org.apache.zookeeper
logger.zookeeper.level = INFO# Log all infos to the console
appender.console.name = ConsoleAppender
appender.console.type = CONSOLE
appender.console.layout.type = PatternLayout
appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n# Log all infos in the given rolling file
appender.rolling.name = RollingFileAppender
appender.rolling.type = RollingFile
appender.rolling.append = true
appender.rolling.fileName = ${sys:log.file}
appender.rolling.filePattern = ${sys:log.file}.%i
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
appender.rolling.policies.type = Policies
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=100MB
appender.rolling.policies.startup.type = OnStartupTriggeringPolicy
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.max = ${env:MAX_LOG_FILE_NUMBER:-10}
appender.rolling.filter.threshold.type = LevelMatchFilter
appender.rolling.filter.threshold.level = INFO
appender.rolling.filter.threshold.onMatch = ACCEPT
appender.rolling.filter.threshold.onMisMatch = DENYappender.errorFile.name = errorLogFile
appender.errorFile.type = RollingFile
appender.errorFile.append = true
appender.errorFile.fileName = ${sys:log.file}.err
appender.errorFile.filePattern = ${sys:log.file}.err.%i
appender.errorFile.layout.type = PatternLayout
appender.errorFile.layout.pattern = %d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %-60c %x - %m%n
appender.errorFile.policies.type = Policies
appender.errorFile.policies.size.type = SizeBasedTriggeringPolicy
appender.errorFile.policies.size.size = 100MB
appender.errorFile.policies.startup.type = OnStartupTriggeringPolicy
appender.errorFile.strategy.type = DefaultRolloverStrategy
appender.errorFile.strategy.max = ${env:MAX_LOG_FILE_NUMBER:-10}
appender.errorFile.filter.threshold.type = ThresholdFilter
appender.errorFile.filter.threshold.level = ERROR
appender.errorFile.filter.threshold.onMatch = ACCEPT
appender.errorFile.filter.threshold.onMisMatch = DENY# Suppress the irrelevant (wrong) warnings from the Netty channel handler
logger.netty.name = org.apache.flink.shaded.akka.org.jboss.netty.channel.DefaultChannelPipeline
logger.netty.level = OFF
這里相比原始文件的修改,主要集中在以下兩個(gè)方面:
- 增加RollingFileAppender的threshold參數(shù)。因?yàn)槲易畛跸M?log日志就只顯示INFO日志,而不顯示其他類(lèi)型日志。但是在log4j官網(wǎng)中介紹的threshold.level參數(shù),其過(guò)濾的是低于設(shè)置類(lèi)型的日志。比如當(dāng)threshold.level=INFO時(shí),過(guò)濾的是低于INFO類(lèi)型的日志,比如DEBUG,而高于的比如ERROR類(lèi)型的日志還是會(huì)保留。在查找一番資料后,發(fā)現(xiàn)了threshold.type = LevelMatchFilter的配置,這種配置可以使得當(dāng)前appender只保留所設(shè)置的日志類(lèi)型的日志,從而實(shí)現(xiàn)了只保留INFO日志的需求。
- 增加了errorLogFile的appender。配置同上,使得當(dāng)前appender只保留ERROR類(lèi)型的日志數(shù)據(jù)。
觀察上面的log4j-console.properties配置可以發(fā)現(xiàn),在設(shè)置文件名時(shí),使用了一個(gè)系統(tǒng)變量${sys:log.file},這個(gè)系統(tǒng)變量使用過(guò)flink配置的應(yīng)該都比較熟悉,指定本地flink日志的默認(rèn)路徑,比如/opt/log/jobmanager.log。
經(jīng)過(guò)測(cè)試后,使用上面的log4j配置能夠?qū)崿F(xiàn)我最初的想法,即將INFO日志和ERROR日志區(qū)分開(kāi),寫(xiě)入不同的文件。但是經(jīng)過(guò)與Yarn部署時(shí)的文件對(duì)比發(fā)現(xiàn),實(shí)際上并不能滿(mǎn)足原始需求。
因?yàn)樵赮arn中,.log日志中也會(huì)存在ERROR日志類(lèi)型的數(shù)據(jù),似乎并不是利用log4j配置進(jìn)行分開(kāi)。而且我查看log4j.properties配置,也沒(méi)有發(fā)現(xiàn)類(lèi)似這種區(qū)分日志類(lèi)型的配置。同時(shí)在Yarn中,.err日志輸出的是任務(wù)異常信息,比如e.printStackTrace(),.out日志輸出的是類(lèi)似System.out.println中的數(shù)據(jù)。而log4j的配置實(shí)際上單純的只是針對(duì)flink執(zhí)行時(shí)的系統(tǒng)日志進(jìn)行配置處理,似乎跟上面的場(chǎng)景還不是一樣的。
因此,就要去尋找新的思路,在摸索之后,決定從根據(jù)這個(gè)log.file的系統(tǒng)變量,從flink的源碼入手
二、Flink源碼分析-Yarn
在本地git clone好flink的源碼后,切換到flink1.12版本分支,進(jìn)行全局搜索"log.file",在flink-runtime模塊下發(fā)現(xiàn)了BootstrapTools
類(lèi),在該類(lèi)下,有一個(gè)getTaskManagerShellCommand
的方法,在方法中,有一處代碼非常有用,如下所示:
startCommandValues.put("redirects","1> "+ logDirectory+ "/taskmanager.out "+ "2> "+ logDirectory+ "/taskmanager.err");
可以看到,這里不就是我們最初想要生成的.out和.err文件嗎!!。那么這里的redirects表示什么意思呢?
觀察后源碼知道,flink設(shè)置了一個(gè)啟動(dòng)命令行的template模塊,有一個(gè)redirects的占位符,因此上面實(shí)際上就是后續(xù)將重定向命令替換redirects占位符。
接下來(lái)看一下這個(gè)方法在哪里被調(diào)用了,發(fā)現(xiàn)除了在BootstrarpToolsTest
測(cè)試類(lèi)中被調(diào)用外,只在flink-yarn項(xiàng)目下src/main/java/org/apache/flink/yarn/Utils.java
類(lèi)中被使用,如下所示:
String launchCommand =BootstrapTools.getTaskManagerShellCommand(flinkConfig,tmParams,".",ApplicationConstants.LOG_DIR_EXPANSION_VAR,hasLogback,hasLog4j,hasKrb5,taskManagerMainClass,taskManagerDynamicProperties);if (log.isDebugEnabled()) {log.debug("Starting TaskManagers with command: " + launchCommand);} else {log.info("Starting TaskManagers");}
因此,當(dāng)部署到Y(jié)arn集群上上時(shí),在構(gòu)建TaskManager的啟動(dòng)命令時(shí),會(huì)使用上述的方法。同時(shí),上面的代碼發(fā)現(xiàn),當(dāng)滿(mǎn)足log.isDebugEnabled()條件時(shí),可以打印出這個(gè)啟動(dòng)命令。如何能滿(mǎn)足這個(gè)條件呢?實(shí)際上,log.isDebugEnabled()
就是表示當(dāng)前l(fā)og4j的配置是允許打印DEBUG類(lèi)型日志的,因此,我們?nèi)サ絝link的conf/log4j.properties下,修改rootLogger.level = INFO
=> rootLogger.level = DEBUG
,然后再重新運(yùn)行任務(wù),即可在日志中看到這個(gè)啟動(dòng)命令:
可以看到,在啟動(dòng)命令的最后位置,有上面代碼中的重定向命令,這個(gè)重定向命令將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤分別重定向到了.out和.err文件。
至此,我們就成功定位了在Yarn中為什么能夠生成.err和.out日志的原因了。實(shí)際上就是由于這樣的一條重定向語(yǔ)句,將flink任務(wù)執(zhí)行時(shí)的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤分別重定向到了.out和.err文件。這也解釋了為什么在Yarn部署時(shí),.err日志里顯示的是異常信息,比如e.printStackTrace(),.out文件輸出的是包括System.out的日志數(shù)據(jù)
弄明白了Yarn的日志生成機(jī)制后,我們接下來(lái)去看一下k8s是怎么實(shí)現(xiàn)的?
三、Flink源碼分析-Kubernetes
那么在k8s部署時(shí),是否也有這樣的重定向語(yǔ)句呢?為了一探究竟,仍然是分析flink 1.12版本的源碼。在flink-kubernetes項(xiàng)目下,有一個(gè)src/main/java/org/apache/flink/kubernetes/utils/KubernetesUtils.java
類(lèi),在該類(lèi)下,存在一個(gè)getCommonStartCommand
方法,該方法類(lèi)似于上面getTaskManagerShellCommand
方法,也是用來(lái)構(gòu)造啟動(dòng)命令參數(shù)的,但是在該方法下,我發(fā)現(xiàn)就不存在這樣的一條重定向語(yǔ)句:
startCommandValues.put("logging",getLogging(logDirectory + "/" + logFileName + ".log",configDirectory,hasLogback,hasLog4j));
只有這樣的一個(gè)寫(xiě)入.log文件的啟動(dòng)命令配置。同時(shí)遺憾的是,在k8s部署時(shí),也沒(méi)有類(lèi)似上面Yarn那樣可以在DEBUG日志類(lèi)型下,打印出啟動(dòng)命令的語(yǔ)句。但是,我們?nèi)匀荒茏龀鲆粋€(gè)初步的結(jié)論:
flink部署在k8s上時(shí),沒(méi)有.out和.err文件,就是由于源碼中在啟動(dòng)TaskManager/JobManager的啟動(dòng)命令參數(shù)中,沒(méi)有將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤進(jìn)行重定向到指定的.out和.err文件導(dǎo)致的。而生成的.log文件,就是在log4j-console.properties中配置的RollingFile滾動(dòng)的系統(tǒng)日志。
同時(shí)我發(fā)現(xiàn),在flink1.11版本時(shí),上面的方法中還保留著跟Yarn一樣的重定向語(yǔ)句,只是從1.12版本之后,就去掉了該重定向語(yǔ)句,是什么原因呢?
至此,我們找出了flink部署到k8s中時(shí),只有一個(gè).log文件的根源。接下來(lái),為了解決最初的原始問(wèn)題,需要向方案去解決。
四、設(shè)計(jì)解決方案
首先想到的解決方案,肯定就是將Yarn那里的重定向源碼復(fù)制一份到上面的k8s代碼中,然后重新打包Flink再進(jìn)行部署。但這種方案嘗試之后發(fā)現(xiàn),在用maven打包flink時(shí)會(huì)出現(xiàn)很多異常,比如包找不到。而且flink有180多個(gè)pom要打包,時(shí)間應(yīng)該會(huì)花費(fèi)非常長(zhǎng),在本次需求對(duì)flink源碼改動(dòng)要求不是很大的情況下,感覺(jué)這種調(diào)試會(huì)花費(fèi)太多不必要的時(shí)間。遂舍棄改方案。
另一個(gè)方案,就是想辦法在外層,能不能在將flink打包成鏡像的時(shí)候,在它原先源碼中定義的啟動(dòng)命令參數(shù)后,再手動(dòng)添加上重定向命令。為此,觀察pod的yaml可以發(fā)現(xiàn),容器啟動(dòng)的參數(shù)有args下,啟動(dòng)命令時(shí)執(zhí)行/docker-entrypoint.sh腳本
有了這些信息后,就找到docker-entrypoint.sh的啟動(dòng)腳本,打開(kāi)后進(jìn)行分析,通過(guò)日志可以知道,腳本執(zhí)行的過(guò)程中,會(huì)進(jìn)入到下面的這個(gè)分支下:
其中args參數(shù)就是上面容器中的args參數(shù),可以看到原先這個(gè)分支的最后一行是去執(zhí)行exec $(drop_privs_cmd) bash -c "${args[@]}"
。因此,我們就可以在這里,手動(dòng)添加上標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤的重定向到指定文件,也相當(dāng)于實(shí)現(xiàn)了在啟動(dòng)參數(shù)中加入重定向語(yǔ)句。
這里我們還需要借助args參數(shù)中的-Dlog.file中顯示的是jobmanager還是taskmanager來(lái)決定重定向?qū)懭氲奈募莏obmanager.err還是taskmanager.err。為此使用sed命令,先獲取到args中的-Dlog.file內(nèi)容(即上面的參數(shù)logFilePath),然后從logFilePath中,獲取到j(luò)obmanager/taskmanager的文件名(即logFileName參數(shù))。
然后,我們添加上重定向命令:
exec $(drop_privs_cmd) bash -c "${args[@]} 1> /opt/flink/log/${logFileName}.out 2> /opt/flink/log/${logFileName}.err
至此,我們就成功在外層flink打包成鏡像時(shí),手動(dòng)在啟動(dòng)命令參數(shù)后添加了重定向命令,模擬了Yarn執(zhí)行時(shí)的命令,來(lái)生成.err和.out文件。接下來(lái),就是打包成鏡像,然后在k8s中進(jìn)行測(cè)試了。經(jīng)過(guò)測(cè)試,我們發(fā)現(xiàn),在/opt/log/路徑下,真的生成了.out、.err和.log三個(gè)文件!!!
同時(shí)經(jīng)過(guò)測(cè)試可以發(fā)現(xiàn),.err、.out和.log文件分別對(duì)應(yīng)了標(biāo)準(zhǔn)錯(cuò)誤、標(biāo)準(zhǔn)輸出和系統(tǒng)文件三部分內(nèi)容。實(shí)現(xiàn)了跟部署在Yarn上時(shí)一樣的場(chǎng)景,解決了我們文章最初提出的問(wèn)題!!!
然而。。卻出現(xiàn)了問(wèn)題。
五、問(wèn)題以及對(duì)k8s日志的理解
在完成上述測(cè)試之后,當(dāng)我再次點(diǎn)擊pod,或者使用kubectl logs命令來(lái)查看日志時(shí)發(fā)現(xiàn),日志里竟然只有啟動(dòng)腳本的一些日志,而flink執(zhí)行的系統(tǒng)日志都沒(méi)有了!!
沒(méi)辦法,只能再去分析原因了。在kubernetes的官網(wǎng)中,在日志架構(gòu)章節(jié)中,赫然寫(xiě)著如下一段話(huà):
容器運(yùn)行時(shí)對(duì)寫(xiě)入到容器化應(yīng)用程序的
stdout
和stderr
流的所有輸出進(jìn)行處理和轉(zhuǎn)發(fā)。 不同的容器運(yùn)行時(shí)以不同的方式實(shí)現(xiàn)這一點(diǎn);不過(guò)它們與 kubelet 的集成都被標(biāo)準(zhǔn)化為 CRI 日志格式。默認(rèn)情況下,如果容器重新啟動(dòng),kubelet 會(huì)保留一個(gè)終止的容器及其日志。 如果一個(gè) Pod 被逐出節(jié)點(diǎn),所對(duì)應(yīng)的所有容器及其日志也會(huì)被逐出。
kubelet 通過(guò) Kubernetes API 的特殊功能將日志提供給客戶(hù)端訪(fǎng)問(wèn)。 訪(fǎng)問(wèn)這個(gè)日志的常用方法是運(yùn)行
kubectl logs
。
雖然我現(xiàn)在對(duì)k8s的理解也不夠,但看上面這段話(huà)讓我意識(shí)到,容器的日志收集或許也是通過(guò)監(jiān)聽(tīng)stdout和stderr來(lái)生成的。。。 而由于我上面使用重定向命令,將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤都重定向到了指定的文件中,導(dǎo)致stdout和stderr無(wú)法監(jiān)聽(tīng)到日志數(shù)據(jù),所以容器內(nèi)的日志就獲取不到了。
或者說(shuō),利用上面將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤重定向?qū)懭胫付ㄖ付ㄎ募姆绞?#xff0c;是相當(dāng)于將原先容器里的日志,分別根據(jù)日志類(lèi)型映射到了.err、.out和.log日志文件下來(lái)展示。
那這樣分析下來(lái),我發(fā)現(xiàn),flink之所以在1.12版本之后將重定向命令從源碼中去掉,可能為的就是利用k8s的日志聚合,將stdout和stderr都寫(xiě)入容器日志中,方便后續(xù)對(duì)容器日志的監(jiān)控和分析等操作。
嗯。。此時(shí),感覺(jué)上面最開(kāi)始的分析都白費(fèi)了,因?yàn)楸旧砣萜鞯娜罩緦?shí)際上就已經(jīng)包含了所有日志數(shù)據(jù)了,根本不用再做.out和.err的區(qū)分了
這里插一句,還記得文章在第一部分提出的問(wèn)題嗎?這里,大家再思考另一個(gè)問(wèn)題,就是講到這里,我們知道容器會(huì)對(duì)stdout和stderr流進(jìn)行處理和轉(zhuǎn)發(fā)。stderr包含flink任務(wù)執(zhí)行時(shí)的異常信息,stdout包含任務(wù)執(zhí)行時(shí)的標(biāo)準(zhǔn)輸出信息,那么flink執(zhí)行時(shí)的系統(tǒng)日志比如INFO、ERROR日志數(shù)據(jù),容器時(shí)從哪里獲取到的呢?log4j中配置的RollingFile類(lèi)型的appender可不屬于標(biāo)準(zhǔn)輸出。
那么這個(gè)問(wèn)題的答案,也就是flink提交到k8s部署時(shí),為什么使用的是log4j-console.properties配置的原因了。
因?yàn)樵趌og4j-console.properties中,會(huì)有一個(gè)ConsoleAppender的配置,將flink的系統(tǒng)日志打印到CONSOLE(System.out),所以相當(dāng)于將系統(tǒng)日志打印到了標(biāo)準(zhǔn)輸出,然后容器再通過(guò)監(jiān)聽(tīng)stdout從而獲取到系統(tǒng)日志。
而部署到Y(jié)arn時(shí),使用的log4j.properties的配置中,就可以看到并沒(méi)有ConsoleAppender的配置,所以它的系統(tǒng)日志全部打印到了.log文件中。
解決了這個(gè)問(wèn)題,再說(shuō)回之前的分析。我們上面添加的重定向操作,相當(dāng)于是模仿著Yarn上部署的方式,將原先容器里的日志,分別根據(jù)日志類(lèi)型映射到了.err、.out和.log日志文件下來(lái)展示。但是此時(shí)容器中的日志卻丟失了,可能會(huì)對(duì)后續(xù)我們最容器上的日志采集和分析有影響。
那有沒(méi)有什么解決方案呢?
雙寫(xiě)。嘗試在將標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤重定向到指定文件時(shí),同時(shí)重定向到stdout和stderr。為此,我們進(jìn)行了測(cè)試,也就是docker-entrypoint.sh中的下面這行代碼:
exec $(drop_privs_cmd) bash -c "${args[@]} 1> >(tee /opt/flink/log/${logFileName}.out >/dev/stdout) 2> >(tee /opt/flink/log/${logFileName}.err >/dev/stderr)"
命令中的1> >(tee /opt/flink/log/${logFileName}.out >/dev/stdout)
表示將標(biāo)準(zhǔn)輸出重定向到一個(gè)匿名的管道中,并將管道中的內(nèi)容通過(guò)tee
命令同時(shí)輸出到文件/opt/flink/log/${logFileName}.out
和標(biāo)準(zhǔn)輸出設(shè)備中。
經(jīng)過(guò)測(cè)試,可以實(shí)現(xiàn)上面的功能,即既有.out和.err文件,同時(shí),容器日志也恢復(fù)最初的狀態(tài)。
但是需要說(shuō)明一點(diǎn)的是,由于log4j-console.properties配置把系統(tǒng)日志也作為標(biāo)準(zhǔn)輸出的一部分,因此生成的.out文件中實(shí)際上包含了任務(wù)中System.out的輸出和系統(tǒng)文件兩部分內(nèi)容。而.err文件則只包含了標(biāo)準(zhǔn)錯(cuò)誤的日志內(nèi)容。
至此,實(shí)現(xiàn)的日志效果是:
- 容器日志:包含系統(tǒng)日志、標(biāo)準(zhǔn)輸出、標(biāo)準(zhǔn)錯(cuò)誤
- .out日志:包含系統(tǒng)日志、標(biāo)準(zhǔn)輸出
- .err日志:包含標(biāo)準(zhǔn)錯(cuò)誤
以上就是本次,針對(duì)最初提出的k8s日志問(wèn)題,進(jìn)行的一次深入探究和思考。在研究過(guò)程中,對(duì)log4j的日志配置也有了更深入的理解,由于一開(kāi)始對(duì)容器和k8s技術(shù)的不了解,導(dǎo)致最后似乎實(shí)現(xiàn)的結(jié)果不理想,但技術(shù)不就是不斷探究的過(guò)程嗎!
關(guān)于上面的問(wèn)題,如果有遇到類(lèi)似的也歡迎找我探討,感謝閱讀!