How to send log from AWS eks to cloudwatch.

研究如何使用 AWS 的 CloudWatch 來收集 EKS 的 log. 並使用 Grafana 做 log search.

原本的 logging architecture 是使用 Elasticsearch + Filebeat + Kibana; 現在改用 AWS CloudWatch + Fluent Bit + Grafana.

問題描述

原架構為 Elasticsearch + Filebeat + Kibana, 基於下述狀況決定改架構, 來減少維護成本.

  • 目前開發使用情境, 之需要查看 log 且可以搜尋, 不需要做資料探勘. 殺雞用牛刀了.
  • Elasticsearch 在 Basic License 下, 無法使用 LDAP, PKI3, Active Directory authentication 功能.
  • Elasticsearch 硬體需求較高, 最低的硬體需求為 t2.large (2 vCPU, 8 Mem).
  • Elasticsearch 使用門檻較高, 能維護的人員不多, 維護上困難.

日誌蒐集狀況

Index lifecycle Management 配置

取 kubernetes 的 ilm 配置, 看到熱資料配置為 20gb or 15d 做 rollover.

 1elasticsearch:/opt$ curl -XGET --user "$account:$password"  "http://$host/_ilm/policy/kubernetes?pretty"|jq
 2{
 3  "kubernetes" : {
 4    "version" : 23,
 5    "modified_date" : "2021-07-07T07:58:49.033Z",
 6    "policy" : {
 7      "phases" : {
 8        ..................
 9        "hot" : {
10          "min_age" : "0ms",
11          "actions" : {
12            "rollover" : {
13              "max_primary_shard_size" : "20gb",
14              "max_age" : "15d"
15            },
16            "forcemerge" : {
17              "max_num_segments" : 1
18            },
19            "readonly" : { },
20            "shrink" : {
21              "number_of_shards" : 1
22            },
23            "set_priority" : {
24              "priority" : 100
25            }
26          }
27        },
28      }
29    },
30    ..................
31  }
32}

資料使用量

目前資料使用量為 167G (./elasticsearch/data).

取其中一個 site 的 production 環境資料,平均 index 約 9.62 GB.

1curl -XGET --user "$account:$password"  "http://$host/_cat/indices/*prod*?v=true&pretty&s=index"
2
3health status index                                     uuid                   pri rep docs.count docs.deleted store.size pri.store.size
4green  open   kubernetes-prod-000039             co5bX1YqSOu11BaKVkUnKw   2   0   10075181            0      6.5gb          6.5gb
5green  open   shrink-arvp-kubernetes-prod-000036 tgcGQwEZSliq9H2R4QJDCQ   1   0   16602612            0       10gb           10gb
6green  open   shrink-kvlp-kubernetes-prod-000038 g0if66MHTDmyWm4vcuX9cw   1   0   15674075            0      9.7gb          9.7gb
7green  open   shrink-laqk-kubernetes-prod-000035 FxLNQzpjQRKjsz_H8Vkl5w   1   0   20661224            0     12.7gb         12.7gb
8green  open   shrink-ttkl-kubernetes-prod-000037 DpeVcQVgTg-VKfOykWkN3Q   1   0   15092948            0      9.2gb          9.2gb

執行

照著 AWS 教學文件 Set up Fluent Bit as a DaemonSet to send logs to CloudWatch Logs 實作.

Create AWS CloudWatch Logs

首先需要建立 AWS CloudWatch 的 Log groups for log stream. 其中 Cluster_Name 為 EKS cluster 名稱.

  • /aws/containerinsights/Cluster_Name/application
  • /aws/containerinsights/Cluster_Name/host
  • /aws/containerinsights/Cluster_Name/dataplane

在這邊使用 Terraform aws_cloudwatch_log_group 來實作.

Quick Start setup for Container Insights on Amazon EKS and Kubernetes

配置 IAM 權限. EKS 的 Node IAM role 需含下面權限
 1data "aws_iam_policy_document" "eks_node_group_cloudwatch_role" {
 2  statement {
 3    actions = [
 4      "logs:CreateLogStream",
 5      "logs:CreateLogGroup",
 6      "logs:DescribeLogStreams",
 7      "logs:PutLogEvents"
 8    ]
 9
10    effect = "Allow"
11
12    resources = [
13      "*",
14    ]
15  }
16}

接著按照文件 Quick Start setup for Container Insights on Amazon EKS and Kubernetes 安裝 DaemonSet of Fluent Bit.

建立 kubernetes namespace
1kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/cloudwatch-namespace.yaml
執行 fluent-bit.yaml
1ClusterName=production
2RegionName=us-east-1
3FluentBitHttpPort='2020'
4FluentBitReadFromHead='Off'
5[[ ${FluentBitReadFromHead} = 'On' ]] && FluentBitReadFromTail='Off'|| FluentBitReadFromTail='On'
6[[ -z ${FluentBitHttpPort} ]] && FluentBitHttpServer='Off' || FluentBitHttpServer='On'
7
8curl https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/quickstart/cwagent-fluent-bit-quickstart.yaml | sed 's/{{cluster_name}}/'${ClusterName}'/;s/{{region_name}}/'${RegionName}'/;s/{{http_server_toggle}}/"'${FluentBitHttpServer}'"/;s/{{http_server_port}}/"'${FluentBitHttpPort}'"/;s/{{read_from_head}}/"'${FluentBitReadFromHead}'"/;s/{{read_from_tail}}/"'${FluentBitReadFromTail}'"/' | kubectl apply -f - 
調整 application-log.conf

由於有做 healthcheck, 所以在 log 希望可以過濾掉 healthcheck 的資料.

需要再 application-log.conf 中加入下面資訊

1[FILTER]
2    Name                grep
3    Match               application.*
4    Exclude             log /.*healthcheck.*/
1kubectl edit configmap/fluent-bit-config -n amazon-cloudwatch

使用 Grafana 做 Dashborad

帳戶管理 LDAP

上面提到痛點之一就是帳戶無法統一管理, 容易遺漏. 這邊 Grafana 原生就提供 LDAP 的功能.

確認 LDAP 功能有 enable, 在 /usr/share/grafana/conf/defaults.ini. 這邊以 image: grafana/grafana:8.3.1 為例, 編輯 /usr/share/grafana/conf/ldap.toml 檔案.

 1[[servers]]
 2host = "ldap.example.com"
 3port = 389
 4use_ssl = false
 5start_tls = false
 6ssl_skip_verify = false
 7bind_dn = "uid=uid,cn=users,cn=accounts,dc=example,dc=com"
 8bind_password = 'passowrd'
 9search_filter = "(uid=%s)"
10search_base_dns = ["cn=users,cn=accounts,dc=example,dc=com"]
11[servers.attributes]
12name = "givenName"
13surname = "sn"
14username = "uid"
15member_of = "memberOf"
16email =  "email"
17
18[[servers.group_mappings]]
19group_dn = "cn=admins,cn=groups,cn=accounts,dc=example,dc=com"
20org_role = "Admin"
21
22[[servers.group_mappings]]
23group_dn = "cn=groups,ou=accounts,dc=example,dc=com"
24org_role = "Editor"
25
26[[servers.group_mappings]]
27group_dn = "*"
28org_role = "Viewer"

Create Data Source

進到 Grafana 中的 Data Source, 加入 CloudWatch 源.

完成效果

完成後會在 AWS CloudWatch 的 log groups 有接收到 log streams.

AWS CloudWatch Logs Insights

在 Grafana 中建立 Dashboard.

Grafana Dashboard

結論

上面提到的問題, 改了架構後做觀察.

目前開發使用情境, 之需要查看 log 且可以搜尋, 不需要做 log 分析. 殺雞用牛刀了.

這邊換了架構對開發並無影響. (開發沒過多反應, 平時有在使用嗎?)

Elasticsearch 在 Basic License 下, 無法使用 LDAP, PKI3, Active Directory authentication 功能.

這邊改用 Grafana 的 LDAP 功能做改善, 帳密的管理統一, 維護上變簡單.

Elasticsearch 硬體需求較高, 為 t2.large (2 vCPU, 8 Mem).

原本 t2.large, 使用 AWS 計算機算出的費用約 108.96 USD/Monthly cost 更改 CloudWatch, 收到的費用為 108.96 USD/Monthly cost (這邊為所有 groups 的費用, 包括 application, EKS, RDS 等)

這邊比較尷尬, 由於兩邊收集的 log 量不同, 不容易比較.

Elasticsearch 能維護的人員不多, 維護上困難.

在寫這篇文章的同時, 也看到一些新的 index 配置並無做優化. 相關配置也已經被動到. 很難受.
改新架構後維護應該要變簡單, 因為不用去搞 index 跟 ilm.

comments powered by Disqus