• 使用 Fluentd 记录日志
    • 开始之前
    • 安装 Fluentd
      • 示例 Fluentd、Elasticsearch、Kibana 工具栈
    • 配置 Istio
    • 查看新的日志
    • 清理

    使用 Fluentd 记录日志

    此任务说明了如何配置 Istio 以创建自定义日志条目并将它们输出到一个 Fluentd 守护程序。Fluentd 是一个开源日志收集器,支持许多数据输出方式,而且是可插拔架构。一种流行的日志后端是 Elasticsearch,以及作为展示的 Kibana。在此任务结束时,将会实现一个新的日志流,把日志发送到一个示例 Fluentd / Elasticsearch / Kibana 工具栈。

    Bookinfo 示例应用程序被用作贯穿全文的例子。

    开始之前

    • 在您的集群中安装 Istio 并部署一个应用程序。此任务假设 Mixer 使用默认配置(—configDefaultNamespace=istio-system)进行设置。如果你使用不同的配置值,请更新此任务中的配置和命令以匹配该值。

    安装 Fluentd

    在您的集群中可能已经运行了一个 Fluentd 守护程序,例如通过这里和这里描述的 add-on 进行安装,或者由您的集群提供商安装。这很可能会将日志配置为发送到 Elasticsearch 系统或日志提供者。

    您可以使用这些 Fluentd 守护程序,或者您配置的其他 Fluentd。只要他们能够监听转发日志,Istio 的 Mixer 就可以连接他们。要使 Istio 的 Mixer 连接到一个运行的 Fluentd 守护程序,您需要为 Fluentd 添加一个 service。监听转发日志的 Fluentd 配置为:

    1. <source>
    2. type forward
    3. </source>

    将 Mixer 连接到所有可能的 Fluentd 的全部配置细节超出了此任务的范围。

    示例 Fluentd、Elasticsearch、Kibana 工具栈

    为了此任务的目标,您可以部署提供的示例工具栈。此栈在一个非生产就绪的 Services 和 Deployments 集合中包含了 Fluentd、Elasticsearch 和 Kibana,它们都位于一个名为 logging 的新 Namespace 中。

    将下面的内容保存为 logging-stack.yaml

    1. # Logging Namespace。下列内容都在此 namespace 中.
    2. apiVersion: v1
    3. kind: Namespace
    4. metadata:
    5. name: logging
    6. ---
    7. # Elasticsearch Service
    8. apiVersion: v1
    9. kind: Service
    10. metadata:
    11. name: elasticsearch
    12. namespace: logging
    13. labels:
    14. app: elasticsearch
    15. spec:
    16. ports:
    17. - port: 9200
    18. protocol: TCP
    19. targetPort: db
    20. selector:
    21. app: elasticsearch
    22. ---
    23. # Elasticsearch Deployment
    24. apiVersion: extensions/v1beta1
    25. kind: Deployment
    26. metadata:
    27. name: elasticsearch
    28. namespace: logging
    29. labels:
    30. app: elasticsearch
    31. annotations:
    32. sidecar.istio.io/inject: "false"
    33. spec:
    34. template:
    35. metadata:
    36. labels:
    37. app: elasticsearch
    38. spec:
    39. containers:
    40. - image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.1.1
    41. name: elasticsearch
    42. resources:
    43. # 在初始化时需要更多的 cpu,因此使用 burstable 级别。
    44. limits:
    45. cpu: 1000m
    46. requests:
    47. cpu: 100m
    48. env:
    49. - name: discovery.type
    50. value: single-node
    51. ports:
    52. - containerPort: 9200
    53. name: db
    54. protocol: TCP
    55. - containerPort: 9300
    56. name: transport
    57. protocol: TCP
    58. volumeMounts:
    59. - name: elasticsearch
    60. mountPath: /data
    61. volumes:
    62. - name: elasticsearch
    63. emptyDir: {}
    64. ---
    65. # Fluentd Service
    66. apiVersion: v1
    67. kind: Service
    68. metadata:
    69. name: fluentd-es
    70. namespace: logging
    71. labels:
    72. app: fluentd-es
    73. spec:
    74. ports:
    75. - name: fluentd-tcp
    76. port: 24224
    77. protocol: TCP
    78. targetPort: 24224
    79. - name: fluentd-udp
    80. port: 24224
    81. protocol: UDP
    82. targetPort: 24224
    83. selector:
    84. app: fluentd-es
    85. ---
    86. # Fluentd Deployment
    87. apiVersion: extensions/v1beta1
    88. kind: Deployment
    89. metadata:
    90. name: fluentd-es
    91. namespace: logging
    92. labels:
    93. app: fluentd-es
    94. annotations:
    95. sidecar.istio.io/inject: "false"
    96. spec:
    97. template:
    98. metadata:
    99. labels:
    100. app: fluentd-es
    101. spec:
    102. containers:
    103. - name: fluentd-es
    104. image: gcr.io/google-containers/fluentd-elasticsearch:v2.0.1
    105. env:
    106. - name: FLUENTD_ARGS
    107. value: --no-supervisor -q
    108. resources:
    109. limits:
    110. memory: 500Mi
    111. requests:
    112. cpu: 100m
    113. memory: 200Mi
    114. volumeMounts:
    115. - name: config-volume
    116. mountPath: /etc/fluent/config.d
    117. terminationGracePeriodSeconds: 30
    118. volumes:
    119. - name: config-volume
    120. configMap:
    121. name: fluentd-es-config
    122. ---
    123. # Fluentd ConfigMap,包含配置文件。
    124. kind: ConfigMap
    125. apiVersion: v1
    126. data:
    127. forward.input.conf: |-
    128. # 采用 TCP 发送的消息
    129. <source>
    130. type forward
    131. </source>
    132. output.conf: |-
    133. <match **>
    134. type elasticsearch
    135. log_level info
    136. include_tag_key true
    137. host elasticsearch
    138. port 9200
    139. logstash_format true
    140. # 设置 chunk limits.
    141. buffer_chunk_limit 2M
    142. buffer_queue_limit 8
    143. flush_interval 5s
    144. # 重试间隔绝对不要超过 5 分钟。
    145. max_retry_wait 30
    146. # 禁用重试次数限制(永远重试)。
    147. disable_retry_limit
    148. # 使用多线程。
    149. num_threads 2
    150. </match>
    151. metadata:
    152. name: fluentd-es-config
    153. namespace: logging
    154. ---
    155. # Kibana Service
    156. apiVersion: v1
    157. kind: Service
    158. metadata:
    159. name: kibana
    160. namespace: logging
    161. labels:
    162. app: kibana
    163. spec:
    164. ports:
    165. - port: 5601
    166. protocol: TCP
    167. targetPort: ui
    168. selector:
    169. app: kibana
    170. ---
    171. # Kibana Deployment
    172. apiVersion: extensions/v1beta1
    173. kind: Deployment
    174. metadata:
    175. name: kibana
    176. namespace: logging
    177. labels:
    178. app: kibana
    179. annotations:
    180. sidecar.istio.io/inject: "false"
    181. spec:
    182. template:
    183. metadata:
    184. labels:
    185. app: kibana
    186. spec:
    187. containers:
    188. - name: kibana
    189. image: docker.elastic.co/kibana/kibana-oss:6.1.1
    190. resources:
    191. # need more cpu upon initialization, therefore burstable class
    192. limits:
    193. cpu: 1000m
    194. requests:
    195. cpu: 100m
    196. env:
    197. - name: ELASTICSEARCH_URL
    198. value: http://elasticsearch:9200
    199. ports:
    200. - containerPort: 5601
    201. name: ui
    202. protocol: TCP
    203. ---

    创建资源:

    1. $ kubectl apply -f logging-stack.yaml
    2. namespace "logging" created
    3. service "elasticsearch" created
    4. deployment "elasticsearch" created
    5. service "fluentd-es" created
    6. deployment "fluentd-es" created
    7. configmap "fluentd-es-config" created
    8. service "kibana" created
    9. deployment "kibana" created

    配置 Istio

    现在已经有了一个运行的 Fluentd 守护程序,接下来使用新的日志类型配置 Istio,并将日志发送到监听的守护程序。创建一个新的用于保存日志流配置 YAML 文件,Istio 将自动生成和收集这些日志流。

    将下列内容保存为 fluentd-istio.yaml

    1. # logentry 实例配置
    2. apiVersion: "config.istio.io/v1alpha2"
    3. kind: logentry
    4. metadata:
    5. name: newlog
    6. namespace: istio-system
    7. spec:
    8. severity: '"info"'
    9. timestamp: request.time
    10. variables:
    11. source: source.labels["app"] | source.workload.name | "unknown"
    12. user: source.user | "unknown"
    13. destination: destination.labels["app"] | destination.workload.name | "unknown"
    14. responseCode: response.code | 0
    15. responseSize: response.size | 0
    16. latency: response.duration | "0ms"
    17. monitored_resource_type: '"UNSPECIFIED"'
    18. ---
    19. # Fluentd handler 配置
    20. apiVersion: "config.istio.io/v1alpha2"
    21. kind: fluentd
    22. metadata:
    23. name: handler
    24. namespace: istio-system
    25. spec:
    26. address: "fluentd-es.logging:24224"
    27. ---
    28. # 将 logentry 示例发送到 Fluentd handler 的 rule
    29. apiVersion: "config.istio.io/v1alpha2"
    30. kind: rule
    31. metadata:
    32. name: newlogtofluentd
    33. namespace: istio-system
    34. spec:
    35. match: "true" # 匹配所有请求
    36. actions:
    37. - handler: handler.fluentd
    38. instances:
    39. - newlog.logentry
    40. ---

    创建资源:

    1. $ kubectl apply -f fluentd-istio.yaml
    2. Created config logentry/istio-system/newlog at revision 22374
    3. Created config fluentd/istio-system/handler at revision 22375
    4. Created config rule/istio-system/newlogtofluentd at revision 22376

    请注意,handler 配置中的 address: "fluentd-es.logging:24224" 一行指向我们在示例工具栈中配置的 Fluentd 守护程序。

    查看新的日志

    • 发送流量到示例应用程序。

    对于 Bookinfo 示例,请在您的浏览器中访问 http://$GATEWAY_URL/productpage,或执行以下命令:

    1. $ curl http://$GATEWAY_URL/productpage
    • 在 Kubernetes 环境中,通过以下命令为 Kibana 设置端口转发:
    1. $ kubectl -n logging port-forward $(kubectl -n logging get pod -l app=kibana -o jsonpath='{.items[0].metadata.name}') 5601:5601 &

    保持命令运行。在结束对 Kibana UI 的访问时,使用 Ctrl-C 退出。

    • 导航到 Kibana UI 并点击右上角的 “Set up index patterns”。

    • 使用 * 作为索引模式,并点击 “Next step”。

    • 选择 @timestamp 作为 Time Filter 字段名称,并点击 “Create index pattern”。

    • 现在点击左侧目录中的 “Discover”,开始探索生成的日志。

    清理

    • 删除新的遥测配置:
    1. $ kubectl delete -f fluentd-istio.yaml
    • 删除示例 Fluentd、Elasticsearch、Kibana 工具栈:
    1. $ kubectl delete -f logging-stack.yaml
    • 删除任何可能还在运行的 kubectl port-forward 进程:
    1. $ killall kubectl
    • 如果您不打算探索任何后续任务,请参考 Bookinfo 清理中的指示停止应用程序。