AWS Athena 分析查詢 AWS 服務日誌

在做大數據分析往往會遇到許多效能性的問題,造成開發者會另外在評估快取機制或是程式端優化的步驟,當引入 AWS Athena 這項服務時讓開發者大大簡化所有複雜的需求,AWS Athena 也是無服務器可以自動擴展,即使在處理更複雜查詢和大型數據集時,也可以依靠它並行執行查詢并快速生成結果。

關於 AWS Athena

將數據作為資源存放在 Amazon S3 中,在 AWS Athena 的部分只需指向 Amazon S3 中存放的位置並定義結構描述,開發者使用標準 SQL 就能解析查詢大規模的資料集。

數據格式

查詢服務使用幾種不同的數據格式,其中包括 ORC、JSON、CSV 和 Parquet,Amazon 建議使用Apache Parquet 將數據轉換為列式存儲格式,因為交互式查詢服務的核心功能遵循計算和存儲的分離,使用壓縮和列格式可以降低查詢和存儲成本,同時進一步提高性能。

Amazon 還建議對數據進行分區,以減少查詢需要掃描的數據量,從而提高查詢性能。

這可以提高性能並降低查詢成本,還可以配對 Amazon EMR 或 Glue 來轉換數據格式,以提高文件結構和格式的效率。

實作資料分析處理

接下來使用 Application Load Balancer 和 AWS S3 的訪問日誌來了解如何使用 AWS Athena 分析存在於 Amazon S3 文件夾中的整個數據檔案。

首先開啟 Athena 服務,在查詢編輯器中執行以下命令來建立一個數據庫:

CREATE DATABASE logs_db

設定與查詢 AWS ALB 服務訪問日誌

要了解如何啟用 Application Load Balancer 訪問日誌,您可以閱讀 這篇文章

在該數據庫中創建資料表結構:

CREATE EXTERNAL TABLE IF NOT EXISTS alb_logs (
    type string,
    time string,
    elb string,
    client_ip string,
    client_port int,
    target_ip string,
    target_port int,
    request_processing_time double,
    target_processing_time double,
    response_processing_time double,
    elb_status_code string,
    target_status_code string,
    received_bytes bigint,
    sent_bytes bigint,
    request_verb string,
    request_url string,
    request_proto string,
    user_agent string,
    ssl_cipher string,
    ssl_protocol string,
    target_group_arn string,
    trace_id string,
    domain_name string,
    chosen_cert_arn string,
    matched_rule_priority string,
    request_creation_time string,
    actions_executed string,
    redirect_url string,
    lambda_error_reason string,
    new_field string
    )
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
    'serialization.format' = '1',
    'input.regex' = 
    '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) ([^ ]*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\"($| \"[^ ]*\")(.*)'LOCATION 's3://your-alb-logs-directory/AWSLogs/<ACCOUNT-ID>/elasticloadbalancing/<REGION>/';

上述的語法中需要將 LOCATION 中的值調整為要查詢的 AWS ALB 日誌位置。

示例使用的情境

查詢 ALB 的所有客戶端 IP 地址,並列出訪問次數:

SELECT distinct client_ip, count() as count 
FROM "logs_db"."alb_logs" 
GROUP BY client_ip ORDER BY count() DESC;

查詢 ALB 有關 HTTP 503 錯誤進行故障排除:

SELECT * FROM "logs_db"."alb_logs" 
WHERE elb_status_code = '503' LIMIT 10;

設定與查詢 AWS S3 訪問日誌

要了解如何啟用 S3 訪問日誌,您可以閱讀 這篇文章

在該數據庫中創建資料表結構:

CREATE EXTERNAL TABLE IF NOT EXISTS s3_logs(
  `bucketowner` STRING,
  `bucket_name` STRING,
  `requestdatetime` STRING,
  `remoteip` STRING,
  `requester` STRING,
  `requestid` STRING,
  `operation` STRING,
  `key` STRING,
  `request_uri` STRING,
  `httpstatus` STRING,
  `errorcode` STRING,
  `bytessent` BIGINT,
  `objectsize` BIGINT,
  `totaltime` STRING,
  `turnaroundtime` STRING,
  `referrer` STRING,
  `useragent` STRING,
  `versionid` STRING,
  `hostid` STRING,
  `sigv` STRING,
  `ciphersuite` STRING,
  `authtype` STRING,
  `endpoint` STRING,
  `tlsversion` STRING)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES (
  'input.regex'='([^ ]*) ([^ ]*) \\[(.*?)\\] ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) (-|[0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) (\"[^\"]*\"|-) ([^ ]*)(?: ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*))?.*$')
STORED AS INPUTFORMAT
  'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://your-s3-logs-directory/prefix/'

上述的語法中需要將 LOCATION 中的值調整為要查詢的 AWS S3 日誌位置。

示例使用的情境

查詢在特定時間段內已刪除對象的日誌:

SELECT requestdatetime, remoteip, requester, key 
FROM "logs_db"."s3_logs" 
WHERE operation like '%DELETE%' 
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN 
parse_datetime('2021-10-18:07:00:00','yyyy-MM-dd:HH:mm:ss')
AND
parse_datetime('2021-12-06:08:00:00','yyyy-MM-dd:HH:mm:ss');

要顯示特定 IP 地址在特定時間段內傳輸的數據量:

SELECT 
SUM(bytessent) as uploadtotal,
SUM(objectsize) as downloadtotal, 
SUM(bytessent + objectsize) AS total 
FROM "apeiro"."s3_access_logs" 
WHERE remoteIP = '3.1.86.30' 
AND parse_datetime(requestdatetime,'dd/MMM/yyyy:HH:mm:ss Z')
BETWEEN 
parse_datetime('2021-10-18:07:00:00','yyyy-MM-dd:HH:mm:ss')
AND 
parse_datetime('2021-12-06:08:00:00','yyyy-MM-dd:HH:mm:ss');

優化 AWS Athena 成本

用戶只需為運行的查詢掃描的數據量付費,此外存儲在 S3 中的結果可能會產生存儲費用。

  • 每 TB 掃描數據的定價為 5 美元。這意味著您只需為您運行的查詢付費,無需額外費用。
  • 查詢四捨五入到最接近的 MB,最小為 10 MB。
  • 用戶按常規 S3 費率為存儲的數據付費。

建議用戶使用壓縮數據文件,以列格式保存數據,並定期刪除舊的結果集以保持較低的費用。在 Apache Parquet 中格式化數據可以加快查詢速度並減少查詢費用。

結論

Athena 可協助分析在 Amazon S3 中存放的非結構化、半結構化和結構化資料,當需要管理很多複雜的 AWS 環境時,這種方法就可以簡化很多排查步驟。

或是有相關開發上的功能需求也可以透過程式端連接 AWS Athena 做資料搜集應用,並可以再開發的產品系統上顯示當前伺服器的狀態,對於以往開發要抓取伺服器狀態的工作也簡化了許多。

AWS S3 Bucket 設定 Logging & Lifecycle

當建立完成 S3 Bucket 默認情況下日誌記錄是處於禁用狀態,必須再進行設定啟用日誌記錄來增強安全性,通過日誌記錄我們可以有助於安全審核找出可疑活動,並且可以從用戶訪問對象的位置以及訪問最多的對象了解更多信息。

了解與啟用日誌記錄

有兩種方法可以記錄對 S3 存儲資源的訪問資訊:

伺服器存取記錄

類似於 HTTP Server 日誌記錄,它包含有關請求者、資源響應以及有關請求者的其他詳細信息。

設定啟用存取記錄

  • 開啟 AWS S3 管理介面
  • 點擊 Bucket 名稱並選擇屬性
  • 在伺服器存取記錄部分選擇編輯
  • 在編輯界面中選擇啟用並選擇儲存的目標位置

日誌格式

存取記錄文件命名方式以以下格式寫入目標儲存貯體:

s3://bucket/prefix/YYYY-mm-DD-HH-MM-SS-UniqueString

內容使用以下以空格分隔的格式寫入,它看起來像這樣:

79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be awsexamplebucket1 [06/Feb/2019:00:00:38 +0000] 192.0.2.3 79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be 3E57427F3EXAMPLE REST.GET.VERSIONING - "GET /awsexamplebucket1?versioning HTTP/1.1" 200 - 113 - 7 - "-" "S3Console/0.4" - s9lzHYrFp76ZVxRcpX9+5cjAnEH2ROuNkd2BHfIa6UkFVdtjf5mKR3/eTPFvsiP/XV/VLi31234= SigV2 ECDHE-RSA-AES128-GCM-SHA256 AuthHeader awsexamplebucket1.s3.us-west-1.amazonaws.com TLSV1.1

內容包含 HTTP / REST 的操作(例如 GET、PUT、POST、OPTIONS.. ),每個紀錄有 24 個字串段,您可以 在此處 閱讀有關更多詳細的數據字段。

AWS CloudTrail 資料事件

AWS CloudTrail 是一項可以審查您的 AWS 內所有活動的服務。Object-level logging 與 AWS CloudTrail 集成可以在 CloudTrail 中查看和分析日誌,這些日誌事件以 JSON 格式保存在 CloudTrail 中,進入 CloudTrail 後詳細事件將存儲在 S3 Bucket 中,並可輕鬆與其他服務集成,例如 CloudWatch(監控/警報)、SNS(通知)、SQS(用於其他處理的隊列)和 lambda 函數(無服務器處理)。

設定啟用存取記錄

  • 開啟 AWS CloudTrail 管理介面
  • 點擊 Create trail 進入 Step 1
  • 選擇 Use existing S3 bucket 以及設定依需求要開啟的服務,進入 Step 2
  • Events 的步驟只點選開啟 Data events 收集 S3的數據

日誌格式

所有的活動紀錄都會紀錄在 CloudTrail Event history 裡面記載了有關操作的完整詳細信息,另外這些訪問紀錄也會以 JSON 數據結構保留在 S3 bucket。

了解兩者紀錄資料之間的差異

伺服器存取記錄

類似於 Web 服務器訪問日誌,以簡單的格式記錄信息,並存儲在 S3 bucket 中,它不包括訪問操作的對象完整的詳細資料,在事件發生時比較難有詳細的指標進行問題追蹤。

但在使用 3rd-party 日誌搜尋工具或者開發自己的解析/通知系統,伺服器存取記錄相關的信息如對象/請求的大小和響應時間,這對容量和性能規劃以及熱門文件... 分析就已經很有用。

在成本上此功能是免費提供的,唯一的成本是日誌的存儲成本。

AWS CloudTrail 資料事件

可靠的 API 調用日誌記錄,例如操作中的 ACL 定義... 等提供了數據的完整度,在安全性和 IT 操作都有較多的詳細資訊可以追蹤。

在與 AWS 其他服務 CloudWatch, SNS , SQS 也可以很輕鬆地進行串接,來達到全面的監控策略保護 S3 bucket 。

自動刪除舊文件

在完成啟用存取記錄後我們收集了大量的數據在一段時間後就不是那麼必要,佔用的空間越來越大在成本上會耗費很多,所以必須定期刪除不必要的數據,在 AWS 平台上我們可以應用生命週期規則,從 S3 bucket 中自動刪除數據。

設定生命週期規則

  • 開啟 AWS S3 管理介面
  • 點擊 Bucket 名稱並選擇管理在點擊建立生命週期規則
  • 替生命週期規則設定一項名稱

  • 設定篩選條件前綴,這個目錄及子目錄下的所有檔案都會被涵括在內

  • 最後設定執行的規則希望文件在 30 天後被刪除,選擇"讓目前版本的物件過期"並輸入天數

在 S3 Bucket上我們使用的是未啟用版本控制針對生命週期所有的物件都是目前的版本,可以透過上述的規則進行檔案在30天後將被標將被標記成過期物件,而被標記過期的物件我們需要再重複剛剛的動作另外建立一組新的規則在標記1天後永久刪除。

當每組文件需要有不同的保留時間,規則也可以設定很多組來自動執行,這樣就可以幫助避免不必要的費用自動刪除舊日誌。

結論

雲服務本身並不能完全的提供安全保護,隨著攻擊者不斷發現配置中的漏洞,當管理者本身也必須實時監控日誌當存在影響網站的基礎服務或安全相關問題時,我們就可以輕鬆識別這些變化的紀錄並深入解決問題,確保開發出來的應用程式具有更高的穩定性和可用性。

AWS Elastic Load Balancing 建立訪問日誌


Amazon ELB (Elastic Load Balancing) 提供訪問日誌,捕獲有關發送到負載平衡器的詳細信息,每個紀錄會包含如接收請求的時間、客戶端的 IP 地址、延遲、請求路徑和服務器響應等信息,這些訪問日誌可用於分析流量或是解決安全和操作問題。

一開始建立完成 Amazon ELB 默認情況下是禁用的,必須要再手動啟用訪問日誌記錄以及指定到 Amazon S3 保留下訪問數據。

設定 Amazon S3

準備在 Amazon S3 建立 Buckets 儲存 ELB 訪問日誌記錄,在管理多個環境時,將日誌存儲在單獨的 S3 存儲桶中,以便輕鬆查找特定環境的日誌。

  • 打開 Amazon S3 控制台建立 Buckets,必須與 ELB 在相同區域

  • 修改 bucket policy 授予 ELB 寫入訪問日誌的權限,以下使用策略:

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "AWS": "arn:aws:iam::elb-account-id:root"
          },
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::bucket-name/AWSLogs/your-aws-account-id/*"
        },
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "delivery.logs.amazonaws.com"
          },
          "Action": "s3:PutObject",
          "Resource": "arn:aws:s3:::bucket-name/AWSLogs/your-aws-account-id/*",
          "Condition": {
            "StringEquals": {
              "s3:x-amz-acl": "bucket-owner-full-control"
            }
          }
        },
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "delivery.logs.amazonaws.com"
          },
          "Action": "s3:GetBucketAcl",
          "Resource": "arn:aws:s3:::bucket-name"
        }
      ]
    }

    使用策略中所需要調整的屬性描述:

  • bucket-name:填入建立的 bucket 名稱

  • your-aws-account-id:填入 AWS 帳戶 ID,可以在帳戶設定中找到

  • elb-account-id:填入 ELB 所在區域的 ID

Region Region name Elastic Load Balancing account ID
us-east-1 US East (N. Virginia) 127311923021
us-east-2 US East (Ohio) 033677994240
us-west-1 US West (N. California) 027434742980
us-west-2 US West (Oregon) 797873946194
af-south-1 Africa (Cape Town) 098369216593
ca-central-1 Canada (Central) 985666609251
eu-central-1 Europe (Frankfurt) 054676820928
eu-west-1 Europe (Ireland) 156460612806
eu-west-2 Europe (London) 652711504416
eu-south-1 Europe (Milan) 635631232127
eu-west-3 Europe (Paris) 009996457667
eu-north-1 Europe (Stockholm) 897822967062
ap-east-1 Asia Pacific (Hong Kong) 754344448648
ap-northeast-1 Asia Pacific (Tokyo) 582318560864
ap-northeast-2 Asia Pacific (Seoul) 600734575887
ap-northeast-3 Asia Pacific (Osaka) 383597477331
ap-southeast-1 Asia Pacific (Singapore) 114774131450
ap-southeast-2 Asia Pacific (Sydney) 783225319266
ap-south-1 Asia Pacific (Mumbai) 718504428378
me-south-1 Middle East (Bahrain) 076674570225
sa-east-1 South America (São Paulo) 507241528517
us-gov-west-1* AWS GovCloud (US-West) 048591011584
us-gov-east-1* AWS GovCloud (US-East) 190560391635
cn-north-1* China (Beijing) 638102146993
cn-northwest-1* China (Ningxia) 037604701340

啟用 Amazon ELB 訪問日誌記錄

  • 打開 Amazon ELB 控制台選擇已經建立的 ELB 在 description 裡點選 Edit attributes

  • 點選啟用並填入 S3 Bucket 名稱

這樣就可以完成日誌的相關設定,在我們 Amazon ELB 運行了一段時間之後,所設定的 S3 Bucket 路徑中就可以找到收集的日誌資訊。

深入了解 ELB 日誌

Amazon ELB 會依照設定時間在每個時間段內生成一次日誌文件,以下是輸出檔案的文件格式:

bucket[/prefix]/AWSLogs/aws-account-id/elasticloadbalancing/region/yyyy/mm/dd/aws-account-idelasticloadbalancingregion_load-balancer-id_end-time_ip-address_random-string.log.gz

我們可以從日誌中收集所有使用者連線的資訊、主機檔案存取的紀錄,以下是日誌的內容:

h2 2018-07-02T22:23:00.186641Z app/my-loadbalancer/50dc6c495c0c9188 
10.0.1.252:48160 10.0.0.66:9000 0.000 0.002 0.000 200 200 5 257 
"GET https://10.0.2.105:773/ HTTP/2.0" "curl/7.46.0" ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2
arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/my-targets/73e2d6bc24d8a067
"Root=1-58337327-72bd00b0343d75b906739c42" "-" "-"
1 2018-07-02T22:22:48.364000Z "redirect" "https://example.com:80/" "-" 10.0.0.66:9000 200 "-" "-"

Amazon ELB 日誌包含非結構化數據,我們可以使用正則表達式將這些數據轉換 JSON 格式或者其他格式以便開發或是串接第三方平台,有關日誌每個字段的完整描述請參考 AWS 文檔

充分利用 ELB 日誌

了解日誌的格式後我們就可以專注於這些服務生成的日誌及其結構,並處理使用這些日誌的價值。

以下是些常用的案例:

  • 結合第三方工具如 PrometheusCoralogix 這些強大的軟體做數據視覺化分析
  • 使用 Amazon CloudWatch 分析數據中異常的警報
  • SaaS 服務商統計業務流量