如何从 Kubernetes 复制控制器的所有 pods 获取日志?

How do I get logs from all pods of a Kubernetes replication controller?

运行 kubectl logs 向我展示了一个 Kubernetes 容器的 stderr/stdout。

如何获得一组 pods 的聚合 stderr/stdout,最好是由某个复制控制器创建的那些?

一种选择是通过 Fluentd/ElasticSearch 设置集群日志记录,如 https://kubernetes.io/docs/user-guide/logging/elasticsearch/ 中所述。一旦日志在 ES 中,就可以很容易地在 Kibana 中应用过滤器来查看来自特定容器的日志。

我创建了一个名为 kubetail 的小 bash 脚本,使这成为可能。例如,要跟踪名为 "app1" 的 pods 的所有日志,您可以执行以下操作:

kubetail app1

您可以找到脚本 here

我使用这个简单的脚本从部署的 pods 中获取日志:

#!/usr/bin/env bash

DEPLOYMENT=

for p in $(kubectl get pods | grep ^${DEPLOYMENT}- | cut -f 1 -d ' '); do 
    echo --------------------------- 
    echo $p 
    echo --------------------------- 
    kubectl logs $p
done

Gist of the script

用法:log_deployment.sh "deployment-name".

脚本随后将显示以 "deployment-name".

开头的所有 pods 的日志

您可以使用标签

kubectl logs -l app=elasticsearch

您可能想要指定 --all-containers --ignore-errors 以便:

  • 包含来自 pods 的多个容器的日志
  • 出现致命错误时继续下一个 pod(例如,无法检索日志)

如果 pods 的命名有意义,可以使用简单的 Plain Old Bash:

keyword=nodejs
command="cat <("
for line in $(kubectl get pods | \
  grep $keyword | grep Running | awk '{print }'); do 
    command="$command (kubectl logs --tail=2 -f $line &) && "
  done
command="$command echo)"
eval $command

解释:循环遍历 运行ning pods,名称包含 "nodejs"。并行跟踪它们中的每一个的日志(背景中的单符号 运行s)确保如果任何 pods 失败,整个命令退出(双符号)。将来自每个尾部命令的流分类为一个唯一的流。 运行 这个动态构建的命令需要 Eval。

不确定这是否是新事物,但通过部署可以像这样进行:

kubectl logs deployment/app1

您可以按照 Adrian Ng 的建议使用标签从多个容器获取日志:

kubectl logs --selector app=yourappname

如果您有一个包含多个容器的 pod,上述命令将失败,您需要指定容器名称:

kubectl logs --selector app=yourappname --container yourcontainername

注意:如果您想查看您可以使用哪些标签,以下命令将列出所有标签:

kubectl get pod <one of your pods> -o template --template='{{.metadata.labels}}'

...输出类似于

map[app:yourappname controller-revision-hash:598302898 pod-template-generation:1]

请注意,某些标签可能不会被其他 pods 共享 - 选择 "app" 似乎是最简单的

之前提供的解决方案并不是最优的。 kubernetes团队自己前段时间也提供了一个解决方案,叫stern。

stern app1

它也匹配正则表达式,默认执行 tail 和 -f(跟随)。一个很好的好处是,它还会向您显示生成日志的 pod。

app1-12381266dad-3233c foobar log
app1-99348234asd-959cc foobar log2

为 linux 获取 go-binary 或为 OSX 通过 brew 安装。

https://kubernetes.io/blog/2016/10/tail-kubernetes-with-stern/

https://github.com/wercker/stern

如果您添加 -f 可以在之前的答案的基础上添加日志。

kubectl logs -f deployment/app

你可以从kubectl logs -h那里得到帮助,根据信息,

kubectl logs -f deployment/myapp -c myapp --tail 100

-c是容器名称,--tail会显示最新的num行,但是这样会选择一个部署的pod,而不是全部pods。这是你必须牢记的。

kubectl logs -l app=myapp -c myapp --tail 100

如果要显示所有pods的日志,可以使用-l并指定一个标签,但同时-f不会被使用。

在这个例子中,当一个Pod中定义了多个容器时,您可以替换<namespace><app-name>来获取日志。

kubectl -n <namespace> logs -f deployment/<app-name> \
    --all-containers=true --since=10m

您也可以通过服务名称执行此操作。

首先尝试找到对应多个pods同一个服务的各个pod的服务名。 kubectl get svc.

接下来,运行以下命令显示每个容器的日志。

kubectl logs -f service/<service-name>

我用这个命令。

kubectl -n <namespace> logs -f deployment/<app-name> --all-containers=true --since=10m

我会考虑的另一个解决方案是使用 K9S,这是一个很棒的 kube 管理工具。

安装后,使用非常简单:

 k9s -n my-namespace --context the_context_name_in_kubeconfig

(如果 kubeconfig 不在默认位置添加 KUBECONFIG=path/to/kubeconfig 前缀)。

默认视图将所有pods列为列表:

我们可以通过输入冒号 : 并开始输入所需的控制器——正如我们所见,K9S 为我们提供了自动完成功能:

并且我们可以看到当前命名空间中的所有副本集:

我们可以通过单击 enter 选择所需的副本集,然后我们将看到与该副本集相关的所有 pods 的列表 - 然后我们可以 按 'l' 查看每个 pod 的日志

因此,与 stern 的情况不同,我们仍然需要继续查看每个 pod 并查看其日志,但我认为使用 K9S 非常方便 - 我们首先查看所有 pods一个相关的控制器,然后通过简单地导航 enterlescape.

来调查每个 pod 的日志

为我工作:

kubectl logs -n namespace -l app=label -c container

@johan 的回答给了我一个单线的想法:

for i in $(kubectl get pods -n default |cut -d" " -f1); do kubectl logs $i -n default; done

您可以根据自己的要求执行以下任一操作:

  1. kubectl -n my_namespace logs deployment/my_deployment --all-containers=true --since 10m
  2. for i in $(kubectl get pods -n "my_namespace" | sed 1d | cut -d" " -f1); do kubectl logs $i -n "my_namespace" "app_name" | grep -i "filter_string you want to" ; done

这个答案试图提供一个简明的例子和解释。为了获得一组 pods 中所有容器的所有输出,您必须使用标签(选择器),除非您计划执行一些额外的脚本。

kubectl logs \
--namespace my-namespace \
-l app=my-app-label \
--tail=-1 \
--timestamps=true \
--prefix=true \
--all-containers=true

此示例 returns 来自 pods 中由标签 app=my-app-label 定义的所有容器的完整快照日志。

可选选项

添加 --timestamps=true--prefix=true 标志可能会有所帮助,以便时间戳和日志源在输出中可见,但这不是必需的。

资源日志

如果指定了诸如部署之类的资源并且该部署具有 多个 pods 例如 ReplicaSet,那么只有一个 pods 日志将被 returned。这就是为什么使用选择器来标识 pods.

尽管指定了 --all-containers,但未成功 return 使用 kubectl v1 的所有 pods 中所有容器的日志 return 以服务或部署等资源为目标.22.5 撰写此回复时。这就是必须使用选择器的原因。

容器名称

根据 kubectl logs --help

的输出

Print the logs for a container in a pod or specified resource. If the pod has only one container, the container name is optional.

这意味着如果有多个容器,则必须执行以下操作之一:

  • 让命令为您选择一个容器
  • 使用 --all-containers=true 选项

跟随和尾随

如果您像上面的示例那样指定标签,那么 tail 将设置为 10,return 仅为每个容器的最后 10 个日志。要获取所有日志,请将 tail 设置为 -1

在示例中添加 -f--follow 以跟踪日志。如果不需要所有日志,请更改 --tail 选项的值。拖尾日志时,您可能希望确保默认选项 --max-log-requests=5 足够。如果有 20 个容器,则需要 --max-log-requests=20