--- title: 使用 Fluentd 记录日志 description: 此任务将展示如何配置 Istio 将日志记录到 Fluentd 守护进程。 weight: 60 keywords: [telemetry,logging] --- 此任务将展示如何配置 Istio 创建自定义日志条目并且发送给 [Fluentd](https://www.fluentd.org/) 守护进程。 Fluentd 是一个开源的日志收集器,支持多种[数据输出](https://www.fluentd.org/dataoutputs)并且有一个可插拔架构。 [Elasticsearch](https://www.elastic.co/products/elasticsearch)是一个流行的后端日志记录程序, [Kibana](https://www.elastic.co/products/kibana) 用于查看。在任务结束后,一个新的日志流将被加载发送日志到示例 Fluentd/Elasticsearch/Kibana 软件栈。 在任务中,将使用 [Bookinfo](/docs/examples/bookinfo/) 示例应用程序作为示例应用程序。 ## 在开始之前 * [安装 Istio](/docs/setup/) 到您的集群并且部署一个应用程序。这个任务假定 Mixer 是以默认配置设置的(`--configDefaultNamespace=istio-system`)。如果您使用不同的值,则更新此任务中的配置和命令以匹配对应的值。 ## 安装 Fluentd 在您的集群中,您可能已经有一个 Fluentd daemon set 运行,就像 add-on 中[这里](https://kubernetes.io/docs/tasks/debug-application-cluster/logging-elasticsearch-kibana/) 和[这里](https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsearch) 的描述,或者特定于您的集群提供方的东西。这可能配置为将日志发送到 Elasticsearch 系统或其它日志记录提供程序。 您可以使用这些 Fluentd 守护进程或您已经设置的任何其他 Fluentd 守护进程,只要 Fluentd 守护进程正在监听转发的日志,并且 Istio 的 Mixer 可以连接 Fluentd 守护进程。为了让 Mixer 连接到正在运行的 Fluentd 守护进程, 您可能需要为 Fluentd 添加 [service](https://kubernetes.io/docs/concepts/services-networking/service/)。监听转发日志的 Fluentd 配置是: {{< text xml >}} type forward {{< /text >}} 将 Mixer 连接到所有可能 Fluentd 配置的完整细节超出了此任务的范围。 ### Fluentd/Elasticsearch/Kibana 软件栈 为了这个任务的准备,您可以部署提供的示例软件栈。 该栈包括 Fluentd,Elasticsearch 和 Kibana 在一个非生产集合 [Services](https://kubernetes.io/docs/concepts/services-networking/service/) 和 [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) 在一个新的叫做`logging`的 [Namespace](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) 中。 将下面的内容保存为 `logging-stack.yaml`. {{< text yaml >}} # Logging 命名空间。下面的资源都是这个命名空间的一部分。 apiVersion: v1 kind: Namespace metadata: name: logging --- # Elasticsearch Service apiVersion: v1 kind: Service metadata: name: elasticsearch namespace: logging labels: app: elasticsearch spec: ports: - port: 9200 protocol: TCP targetPort: db selector: app: elasticsearch --- # Elasticsearch Deployment apiVersion: extensions/v1beta1 kind: Deployment metadata: name: elasticsearch namespace: logging labels: app: elasticsearch annotations: sidecar.istio.io/inject: "false" spec: template: metadata: labels: app: elasticsearch spec: containers: - image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.1.1 name: elasticsearch resources: # need more cpu upon initialization, therefore burstable class limits: cpu: 1000m requests: cpu: 100m env: - name: discovery.type value: single-node ports: - containerPort: 9200 name: db protocol: TCP - containerPort: 9300 name: transport protocol: TCP volumeMounts: - name: elasticsearch mountPath: /data volumes: - name: elasticsearch emptyDir: {} --- # Fluentd Service apiVersion: v1 kind: Service metadata: name: fluentd-es namespace: logging labels: app: fluentd-es spec: ports: - name: fluentd-tcp port: 24224 protocol: TCP targetPort: 24224 - name: fluentd-udp port: 24224 protocol: UDP targetPort: 24224 selector: app: fluentd-es --- # Fluentd Deployment apiVersion: extensions/v1beta1 kind: Deployment metadata: name: fluentd-es namespace: logging labels: app: fluentd-es annotations: sidecar.istio.io/inject: "false" spec: template: metadata: labels: app: fluentd-es spec: containers: - name: fluentd-es image: gcr.io/google-containers/fluentd-elasticsearch:v2.0.1 env: - name: FLUENTD_ARGS value: --no-supervisor -q resources: limits: memory: 500Mi requests: cpu: 100m memory: 200Mi volumeMounts: - name: config-volume mountPath: /etc/fluent/config.d terminationGracePeriodSeconds: 30 volumes: - name: config-volume configMap: name: fluentd-es-config --- # Fluentd ConfigMap, 包含了配置文件。 kind: ConfigMap apiVersion: v1 data: forward.input.conf: |- # Takes the messages sent over TCP type forward output.conf: |- type elasticsearch log_level info include_tag_key true host elasticsearch port 9200 logstash_format true # Set the chunk limits. buffer_chunk_limit 2M buffer_queue_limit 8 flush_interval 5s # Never wait longer than 5 minutes between retries. max_retry_wait 30 # Disable the limit on the number of retries (retry forever). disable_retry_limit # Use multiple threads for processing. num_threads 2 metadata: name: fluentd-es-config namespace: logging --- # Kibana Service apiVersion: v1 kind: Service metadata: name: kibana namespace: logging labels: app: kibana spec: ports: - port: 5601 protocol: TCP targetPort: ui selector: app: kibana --- # Kibana Deployment apiVersion: extensions/v1beta1 kind: Deployment metadata: name: kibana namespace: logging labels: app: kibana annotations: sidecar.istio.io/inject: "false" spec: template: metadata: labels: app: kibana spec: containers: - name: kibana image: docker.elastic.co/kibana/kibana-oss:6.1.1 resources: # need more cpu upon initialization, therefore burstable class limits: cpu: 1000m requests: cpu: 100m env: - name: ELASTICSEARCH_URL value: http://elasticsearch:9200 ports: - containerPort: 5601 name: ui protocol: TCP --- {{< /text >}} 创建资源:
{{< text bash >}} $ kubectl apply -f logging-stack.yaml namespace "logging" created service "elasticsearch" created deployment "elasticsearch" created service "fluentd-es" created deployment "fluentd-es" created configmap "fluentd-es-config" created service "kibana" created deployment "kibana" created {{< /text >}}
## 配置 Istio 现在有一个正在运行的 Fluentd 守护进程,请使用新的日志类型配置 Istio,并将这些日志发送到监听守护进程。 创建一个新的 YAML 文件来保存日志流的配置,Istio 将自动生成并收集。 将下面的内容保存为 `fluentd-istio.yaml`: {{< text yaml >}} # logentry 实例的配置 apiVersion: "config.istio.io/v1alpha2" kind: logentry metadata: name: newlog namespace: istio-system spec: severity: '"info"' timestamp: request.time variables: source: source.labels["app"] | source.service | "unknown" user: source.user | "unknown" destination: destination.labels["app"] | destination.service | "unknown" responseCode: response.code | 0 responseSize: response.size | 0 latency: response.duration | "0ms" monitored_resource_type: '"UNSPECIFIED"' --- # fluentd handler 的配置 apiVersion: "config.istio.io/v1alpha2" kind: fluentd metadata: name: handler namespace: istio-system spec: address: "fluentd-es.logging:24224" --- # 发送 logentry 实例到 fluentd handler 的规则 apiVersion: "config.istio.io/v1alpha2" kind: rule metadata: name: newlogtofluentd namespace: istio-system spec: match: "true" # match for all requests actions: - handler: handler.fluentd instances: - newlog.logentry --- {{< /text >}} 创建资源: {{< text bash >}} $ istioctl create -f fluentd-istio.yaml Created config logentry/istio-system/newlog at revision 22374 Created config fluentd/istio-system/handler at revision 22375 Created config rule/istio-system/newlogtofluentd at revision 22376 {{< /text >}} 请注意在处理程序配置中 `address: "fluentd-es.logging:24224"` 行指向我们设置的 Fluentd 守护进程示例软件栈。 ## 查看新的日志 1. 将流量发送到示例应用程序。 对于 [Bookinfo](/docs/examples/bookinfo/#determining-the-ingress-ip-and-port) 示例, 在浏览器中访问 `http://$GATEWAY_URL/productpage` 或发送以下命令: {{< text bash >}} $ curl http://$GATEWAY_URL/productpage {{< /text >}} 1. 在 Kubernetes 环境中, 通过以下命令为 Kibana 建立端口转发: {{< text bash >}} $ kubectl -n logging port-forward $(kubectl -n logging get pod -l app=kibana -o jsonpath='{.items[0].metadata.name}') 5601:5601 {{< /text >}} 让命令继续运行。完成访问 Kibana UI 时按下 Ctrl-C 退出。 1. 导航到 [Kibana UI](http://localhost:5601/) 并点击 右上角的 "Set up index patterns"。 1. 使用 `*` 作为索引模式, 并单击 "Next step."。 1. 选择 `@timestamp` 作为时间筛选字段名称,然后单击 "Create index pattern"。 1. 现在在左侧的菜单上点击 "Discover",并开始检索生成的日志。 ## 清理 * 删除新的遥测配置: {{< text bash >}} $ istioctl delete -f fluentd-istio.yaml {{< /text >}} * 删除 Fluentd, Elasticsearch, Kibana 示例软件栈: {{< text bash >}} $ kubectl delete -f logging-stack.yaml {{< /text >}} * 如果您不打算探索任何后续任务,可以参考 [Bookinfo 清理](/docs/examples/bookinfo/#cleanup) 步骤去关闭程序。