使用Kubernetes进行集群级日志记录

Kubernetes集群通常会运行许多系统和应用程序Pod。系统管理员如何收集,管理和查询系统Pod的日志?用户如何查询其应用程序日志,该应用程序日志由Kubernetes系统重启或自动生成的许多Pod组成? Kubernetes集群级别的日志记录服务解决了这些问题。

Kubernetes的集群级日志记录使我们可以收集日志,这些日志的持久性超出了容器容器镜像的生命周期,甚至超出了容器甚至集群的生命周期。在本文中,我们假设已经创建了Kubernetes集群,该集群具有集群级别的日志记录支持,可以将日志发送到 Google Cloud记录。创建一个 Google容器引擎 (GKE)集群,并且默认情况下对开源启用 Google Compute Engine (GCE)Kubernetes发行版。创建集群后,您将拥有一个系统集合 豆荚 运行支持Kubernetes服务名称的监视,日志记录和DNS解析的运行:

$ kubectl get 豆荚
NAME                                           READY     REASON    RESTARTS   AGE

fluentd-cloud-logging-kubernetes-minion-0f64   1/1       Running   0          32m

fluentd-cloud-logging-kubernetes-minion-27gf   1/1       Running   0          32m

fluentd-cloud-logging-kubernetes-minion-pk22   1/1       Running   0          31m

fluentd-cloud-logging-kubernetes-minion-20ej   1/1       Running   0          31m

kube-dns-v3-pk22                               3/3       Running   0          32m


monitoring-heapster-v1-20ej                    0/1       Running   9          32m

这是图片中的相同信息,该图片显示了吊舱如何放置在特定节点上。

这是每个节点上正在运行的内容的特写。

第一个图显示了在GCE群集上创建的四个节点,每个VM节点的名称位于紫色背景上。每个节点的内部和公共IP均显示在灰色框中,每个节点中运行的Pod均显示在绿色框中。每个Pod框都会显示Pod的名称及其运行的名称空间,Pod的IP地址以及在Pod执行过程中运行的图像。在这里,我们看到每个节点都在运行一个fluentd-cloud-logging pod,该pod收集在同一节点上运行的容器的日志输出,并将它们发送到Google Cloud Logging。提供一个 群集DNS服务 在一个节点上运行,而提供监视支持的Pod在另一个节点上运行。

为了帮助解释集群级日志记录的工作方式,让我们从合成日志生成器容器规范开始 反荚:

  apiVersion : v1  
  kind : Pod  
  metadata :  
    name : counter  
  spec :  
    containers :  
   - name : count  
      image : ubuntu:14.04  
      args : [bash, -c,   
            'for ((i = 0; ; i++)); do echo "$i: $(date)"; sleep 1; done']  

此pod规范有一个容器,该容器在诞生时运行bash脚本。该脚本仅每秒写一次计数器的值和日期,然后无限期地运行。让我们创建一个吊舱。


$ kubectl create -f 反荚


pods/counter

我们可以观察正在运行的吊舱:

$ kubectl get 豆荚
NAME                                           READY     REASON    RESTARTS   AGE

counter                                        1/1       Running   0          5m

fluentd-cloud-logging-kubernetes-minion-0f64   1/1       Running   0          55m

fluentd-cloud-logging-kubernetes-minion-27gf   1/1       Running   0          55m

fluentd-cloud-logging-kubernetes-minion-pk22   1/1       Running   0          55m

fluentd-cloud-logging-kubernetes-minion-20ej   1/1       Running   0          55m

kube-dns-v3-pk22                               3/3       Running   0          55m

monitoring-heapster-v1-20ej                    0/1       Running   9          56m

此步骤可能需要几分钟来下载ubuntu:14.04映像,在此期间,窗格状态将显示为Pending。

现在,节点之一正在运行计数器容器:

当窗格状态更改为“正在运行”时,我们可以使用kubectl logs命令查看此计数器窗格的输出。

$ kubectl logs counter

0: Tue Jun  2 21:37:31 UTC 2015

1: Tue Jun  2 21:37:32 UTC 2015

2: Tue Jun  2 21:37:33 UTC 2015

3: Tue Jun  2 21:37:34 UTC 2015

4: Tue Jun  2 21:37:35 UTC 2015

5: Tue Jun  2 21:37:36 UTC 2015

该命令从Docker日志文件中获取此容器中正在运行的映像的日志文本。我们可以连接到运行中的容器并观察运行中的计数器bash脚本。

$ kubectl exec -i counter bash

ps aux

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

root         1  0.0  0.0  17976  2888 ?        Ss   00:02   0:00 bash -c for ((i = 0; ; i++)); do echo "$i: $(date)"; sleep 1; done

root       468  0.0  0.0  17968  2904 ?        Ss   00:05   0:00 bash

root       479  0.0  0.0   4348   812 ?        S    00:05   0:00 sleep 1

root       480  0.0  0.0  15572  2212 ?        R    00:05   0:00 ps aux

如果出于某种原因,该吊舱中的映像被杀死,然后被Kubernetes重新启动,该怎么办?我们是否仍会看到容器先前调用的日志行,然后是启动容器的日志行?还是我们将从原始容器的执行中丢失日志行,而仅看到新容器的日志行?让我们找出答案。首先,让我们停止当前正在运行的计数器。

$ kubectl stop pod counter

pods/counter


Now let’s restart the counter.


$ kubectl create -f 反荚

pods/counter

让我们等待容器重新启动,然后再次获取日志行。

$ kubectl logs counter

0: Tue Jun  2 21:51:40 UTC 2015

1: Tue Jun  2 21:51:41 UTC 2015

2: Tue Jun  2 21:51:42 UTC 2015

3: Tue Jun  2 21:51:43 UTC 2015

4: Tue Jun  2 21:51:44 UTC 2015

5: Tue Jun  2 21:51:45 UTC 2015

6: Tue Jun  2 21:51:46 UTC 2015

7: Tue Jun  2 21:51:47 UTC 2015

8: Tue Jun  2 21:51:48 UTC 2015

不好了!我们在此容器中首次调用容器时丢失了日志行!理想情况下,我们希望保留pod中每个容器的每次调用的所有日志行。此外,即使重新启动了容器,我们仍然希望保留容器中容器发出的所有日志行。但是不要担心,这是Kubernetes中群集级别的日志记录提供的功能。创建集群后,可以使用以下命令提取每个容器的标准输出和标准错误输出: 流利的 在每个节点上运行的代理 Google Cloud记录 或进入Elasticsearch并与Kibana一起查看。这篇博客文章重点介绍Google Cloud Logging。

创建启用日志记录到Google Cloud Logging的Kubernetes集群后,系统会在集群的每个节点上创建一个名为fluentd-cloud-logging的pod,以收集Docker容器日志。在本博客文章的开头显示了对第一个get 豆荚命令的响应中显示的这些Pod。

此日志收集窗格具有一个类似于以下内容的规范 fluentd-gcp.yaml:

apiVersion: v1

kind: Pod

metadata:

  name: fluentd-cloud-logging

spec:

  containers:

  - name: fluentd-cloud-logging

    image: gcr.io/google\_containers/fluentd-gcp:1.6

    env:

    - name: FLUENTD\_ARGS

      value: -qq

    volumeMounts:

    - name: containers

      mountPath: /var/lib/docker/containers

  volumes:

  - name: containers

    hostPath:

      path: /var/lib/docker/containers

此pod规范将包含Docker日志文件的主机上的目录/ var / lib / docker / containers映射到容器内具有相同路径的目录。该广告连播运行一个图像gcr.io/google_containers/fluentd-gcp:1.6,该图像被配置为从logs目录中收集Docker日志文件,并将其提取到Google Cloud Logging中。该Pod的一个实例在群集的每个节点上运行。 Kubernetes将注意到该Pod是否失败并自动重启。

我们可以单击Google Developer Console的Monitoring部分下的Logs项,然后选择计数器容器的日志,该日志容器称为kubernetes.counter_default_count。这标识发生日志收集的容器的名称(计数器),名称空间(默认)和容器的名称(计数)。使用此名称,我们可以从下拉菜单中仅选择计数器容器的日志:

(image-counter-new-logs.png)

在开发人员控制台中查看日志时,我们会观察到容器的两次调用的日志。

(image-screenshot-2015-06-02)

请注意第一个容器计数为108,然后终止。当下一个容器映像重新启动时,计数过程从0开始恢复。类似地,如果我们删除了容器并重新启动它,我们将在容器运行时捕获容器中容器的所有实例的日志。

提取到Google Cloud Logging中的日志可能会导出到其他各种目标,包括 谷歌云存储 水桶和 大查询。使用Cloud Logging控制台中的Exports选项卡指定日志应流到的位置(或单击此链接以 设置标签)。

我们可以使用SQL查询来查询BigQuery提取的日志,该SQL报告首先显示最新行的计数器日志行。

从[mylogs.kubernetes_counter_default_count_20150611]中选择元数据.timestamp,structPayload.log

这是一些示例输出:

(image-bigquery-log-new.png)

我们还可以将日志从Google Cloud Storage存储桶中提取到我们的台式机或笔记本电脑中,然后在本地进行搜索。以下命令获取在群集中运行的计数器容器的日志,该群集本身在GCE项目myproject中。仅获取日期为2015-06-11的日志。

$ gsutil -m cp -r gs://myproject/kubernetes.counter\_default\_count/2015/06/11 .

现在,我们可以对提取的日志运行查询。下面的示例使用q 程序仅提取日志行。

$ cat 21\:00\:00\_21\:59\:59\_S0.json | q  '.structPayload.log'

"0: Thu Jun 11 21:39:38 UTC 2015\n"

"1: Thu Jun 11 21:39:39 UTC 2015\n"

"2: Thu Jun 11 21:39:40 UTC 2015\n"

"3: Thu Jun 11 21:39:41 UTC 2015\n"

"4: Thu Jun 11 21:39:42 UTC 2015\n"

"5: Thu Jun 11 21:39:43 UTC 2015\n"

"6: Thu Jun 11 21:39:44 UTC 2015\n"

"7: Thu Jun 11 21:39:45 UTC 2015\n"

本文简要介绍了支持在Kubernetes部署上收集群集级别日志的基本机制。这里的方法仅适用于收集在容器容器中运行的进程的标准输出和标准错误输出。要收集存储在文件中的其他日志,可以使用sidecar容器来收集所需的文件,如页面中所述 使用Fluentd在容器内收集日志文件,并将其发送到Google Cloud Logging服务.