服务器和应用程序日志记录是开发人员、运维人员和安全团队了解应用程序在其生产环境中运行状态的重要工具。
日志记录允许运维人员确定应用程序和所需的组件是否运行顺畅,并检测是否发生了异常情况,以便他们能够对情况作出反应。
对于开发人员来说,日志记录提供了在开发期间和之后对代码进行故障排除的可见性。 在生产环境中,开发人员通常依赖于日志记录工具,而不是调试工具。 结合来自系统的日志记录,开发人员可以与运维人员携手合作,有效地解决问题。
日志记录功能最重要的受益者是安全团队,尤其是在云原生环境中。 能够从应用程序和系统日志中收集信息,使安全团队能够分析来自身份验证、应用程序访问和恶意软件活动的数据,并在需要时对其做出响应。
Kubernetes 是领先的容器平台,越来越多的应用程序部署在生产环境中。 我相信,理解 Kubernetes 的日志记录架构对于每个开发、运维和安全团队来说都是一项非常重要的工作。
在本文中,我将讨论 Kubernetes 中不同的容器日志记录模式是如何工作的。
系统日志记录和应用程序日志记录
在我深入研究 Kubernetes 日志记录架构之前,我想先探讨不同的日志记录方法,以及这两种功能如何成为 Kubernetes 日志记录的关键特性。
有两种类型的系统组件:一种是在容器中运行的,另一种是不在容器中运行的。 例如
- Kubernetes 调度器和
kube-proxy
在容器中运行。 kubelet
和容器运行时不在容器中运行。
与容器日志类似,系统容器日志存储在 /var/log
目录中,你应该定期轮换它们。
在这里我考虑容器日志记录。 首先,我来看一下集群级别的日志记录以及为什么它对集群运维人员很重要。 集群日志提供有关集群性能的信息。 诸如 Pod 为何被驱逐或节点死亡之类的信息。 集群日志记录还可以捕获诸如集群和应用程序访问以及应用程序如何利用计算资源之类的信息。 总的来说,集群日志记录工具为集群运维人员提供了对集群运行和安全有用的信息。
捕获容器日志的另一种方法是通过应用程序的本机日志记录工具。 现代应用程序设计很可能具有一种日志记录机制,该机制通过标准输出 (stdout
) 和错误流 (stderr
) 帮助开发人员解决应用程序性能问题。
为了拥有有效的日志记录工具,Kubernetes 实现需要应用程序和系统日志记录组件。
Kubernetes 容器日志记录的 3 种类型
在大多数 Kubernetes 实现中,你可以看到三种突出的集群级别日志记录方法。
- 节点级别日志记录代理
- 用于日志记录的 Sidecar 容器应用程序
- 将应用程序日志直接公开给日志记录后端
节点级别日志记录代理
我想考虑一下节点级别的日志记录代理。 你通常使用 DaemonSet 作为部署策略来实现这些,以在所有 Kubernetes 节点中部署 Pod(充当日志记录代理)。 然后配置此日志记录代理以从所有 Kubernetes 节点读取日志。 你通常配置代理以读取节点 /var/logs
目录,捕获 stdout
/stderr
流并将其发送到日志记录后端存储。
下图显示了作为代理在所有节点中运行的节点级别日志记录。

(Mike Calizo, CC BY-SA 4.0)
要使用 fluentd
方法设置节点级别日志记录,你需要执行以下操作:
- 首先,你需要创建一个名为
fluentdd
的 ServiceAccount。 Fluentd Pod 使用此服务帐户来访问 Kubernetes API,你需要使用标签app: fluentd
在日志记录命名空间中创建它们。
#fluentd-SA.yaml apiVersion: v1 kind: ServiceAccount metadata: name: fluentd namespace: logging labels: app: fluentd
你可以在此 repo 中查看完整的示例。
- 然后,你需要创建一个 ConfigMap
fluentd-configmap
。 这为fluentd daemonset
提供了一个包含所有必需属性的配置文件。
#fluentd-daemonset.yaml apiVersion: extensions/v1beta1 kind: DaemonSet metadata: name: fluentd namespace: logging labels: app: fluentd kubernetes.io/cluster-service: "true" spec: selector: matchLabels: app: fluentd kubernetes.io/cluster-service: "true" template: metadata: labels: app: fluentd kubernetes.io/cluster-service: "true" spec: serviceAccount: fluentd containers: - name: fluentd image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-elasticsearch7-1.0 env: - name: FLUENT_ELASTICSEARCH_HOST value: "elasticsearch.logging.svc.cluster.local" - name: FLUENT_ELASTICSEARCH_PORT value: "9200" - name: FLUENT_ELASTICSEARCH_SCHEME value: "http" - name: FLUENT_ELASTICSEARCH_USER value: "elastic" - name: FLUENT_ELASTICSEARCH_PASSWORD valueFrom: secretKeyRef: name: efk-pw-elastic key: password - name: FLUENT_ELASTICSEARCH_SED_DISABLE value: "true" resources: limits: memory: 512Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: varlog mountPath: /var/log - name: varlibdockercontainers mountPath: /var/lib/docker/containers readOnly: true - name: fluentconfig mountPath: /fluentd/etc/fluent.conf subPath: fluent.conf terminationGracePeriodSeconds: 30 volumes: - name: varlog hostPath: path: /var/log - name: varlibdockercontainers hostPath: path: /var/lib/docker/containers - name: fluentconfig configMap: name: fluentdconf
你可以在此 repo 中查看完整的示例。
现在,我来看看如何将 fluentd daemonset
部署为日志代理的代码。
#fluentd-daemonset.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fluentd
namespace: logging
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
selector:
matchLabels:
app: fluentd
kubernetes.io/cluster-service: "true"
template:
metadata:
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
serviceAccount: fluentd
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-elasticsearch7-1.0
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.logging.svc.cluster.local"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http"
- name: FLUENT_ELASTICSEARCH_USER
value: "elastic"
- name: FLUENT_ELASTICSEARCH_PASSWORD
valueFrom:
secretKeyRef:
name: efk-pw-elastic
key: password
- name: FLUENT_ELASTICSEARCH_SED_DISABLE
value: "true"
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: fluentconfig
mountPath: /fluentd/etc/fluent.conf
subPath: fluent.conf
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: fluentconfig
configMap:
name: fluentdconf
总而言之:
kubectl apply -f fluentd-SA.yaml \
-f fluentd-configmap.yaml \
-f fluentd-daemonset.yaml
用于日志记录的 Sidecar 容器应用程序
另一种方法是使用带有日志记录代理的专用 Sidecar 容器。 Sidecar 容器最常见的实现是使用 Fluentd 作为日志收集器。 在企业部署中(你不用担心少量的计算资源开销),使用 fluentd
(或 类似)实现的 Sidecar 容器比集群级别日志记录提供了更大的灵活性。 这是因为你可以根据日志的类型、频率以及需要捕获的其他可能的调整来调整和配置收集器代理。
下图显示了作为日志记录代理的 Sidecar 容器。

(Mike Calizo, CC BY-SA 4.0)
例如,一个 Pod 运行一个容器,该容器使用两种不同的格式写入两个不同的日志文件。 这是 Pod 的配置文件
#log-sidecar.yaml
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
containers:
- name: count
image: busybox
args:
- /bin/sh
- -c
- >
i=0;
while true;
do
echo "$i: $(date)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
总而言之,你可以运行这个 Pod
$ kubectl apply -f log-sidecar.yaml
要验证 Sidecar 容器是否作为日志记录代理工作,你可以执行
$ kubectl logs counter count-log
预期的输出应如下所示
$ kubectl logs counter count-log-1
Thu 04 Nov 2021 09:23:21 NZDT
Thu 04 Nov 2021 09:23:22 NZDT
Thu 04 Nov 2021 09:23:23 NZDT
Thu 04 Nov 2021 09:23:24 NZDT
将应用程序日志直接公开给日志记录后端
第三种方法(我个人认为)是 Kubernetes 容器和应用程序日志最灵活的日志记录解决方案,它将日志直接推送到日志记录后端解决方案。 虽然此模式不依赖于 Kubernetes 的本机功能,但它提供了大多数企业需要的灵活性,例如
- 扩展对更广泛的网络协议和输出格式的支持。
- 允许负载均衡功能并提高性能。
- 可配置为通过上游聚合接受复杂的日志记录要求
由于第三种方法通过直接从每个应用程序推送日志来依赖于非 Kubernetes 功能,因此它超出了 Kubernetes 的范围。
结论
Kubernetes 日志记录工具是 Kubernetes 集群企业部署的一个非常重要的组件。 我讨论了三种可能的模式可供使用。 你需要找到适合你需求的模式。
如所示,使用 daemonset
的节点级别日志记录是最容易使用的部署模式,但它也有一些可能不符合你组织需求的限制。 另一方面,Sidecar 模式提供了灵活性和定制,允许你定制要捕获的日志类型,从而为你提供计算资源开销。 最后,将应用程序日志直接公开给后端日志工具是另一种有吸引力的方法,可以进一步定制。
选择权在你。 你只需要找到适合你组织需求的方法。
评论已关闭。