博客 / 詳情

返回

使用 Lambda 函數將 CloudWatch Log 中的日誌歸檔到 S3 桶中


作者:SRE運維博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/221205544069/
相關話題:https://www.cnsre.cn/tags/aws/

躺了好久,詐屍了。因為換了工作,所以比較忙一直沒有時間去更新博客的內容(主要還是因為懶🤔)

話不多説 直接上乾貨。

需求背景

最近在看費用的時候發現有很大一部分費用都是 cloudwatch log中存儲了大量的數據,是因為ec2 將日誌傳輸到了存儲到了cloudwatch中。這個存儲的多的查詢日誌的時候收費特別的高。另外一個是因為數據分析用途,大數據分析的同事如果想那到數據的話,還是存儲在 S3 中是比較划算和方便的,一個是拿取數據比較方便,另外一個是S3 可以最歸檔存儲,後面的大量數據可以分層儲存,以此來降低費用。
如果你也想將你的cloudwatch 中日誌組中的日誌存儲到S3中的話可以參考下這篇文章。

前置條件

  • 創建 一個 S3 桶,並修改權限
  • 創建 lambda 函數
  • 有一個Cloudwatch 日誌組並且有一天以上的日誌
  • 給 lambda分配所需的權限

創建 S3 桶並修改權限

sre運維|Linux運維|關鍵詞

{{< tabs 國內S3桶權限配置 國外S3桶權限配置 >}}
{{< tab >}}

國內S3桶權限配置

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.cn-north-1.amazonaws.com.cn"
            },
            "Action": "s3:GetBucketAcl",
            "Resource": "arn:aws-cn:s3:::<bucket name>"
        },
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "logs.cn-north-1.amazonaws.com.cn"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws-cn:s3:::<bucket name>/*",
            "Condition": {
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }
        }
    ]
}

{{< /tab >}}
{{< tab >}}

國外S3桶權限配置

{
    "Version": "2012-10-17",
    "Statement": [
      {
          "Action": "s3:GetBucketAcl",
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::<bucket name>",
          "Principal": { "Service": "logs.us-west-2.amazonaws.com" }
      },
      {
          "Action": "s3:PutObject" ,
          "Effect": "Allow",
          "Resource": "arn:aws:s3:::<bucket name>*",
          "Condition": { "StringEquals": { "s3:x-amz-acl": "bucket-owner-full-control" } },
          "Principal": { "Service": "logs.us-west-2.amazonaws.com" }
      }
    ]
}

{{< /tab >}}
{{< /tabs >}}

S3 桶權限文檔鏈接

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4855142804875926"

 crossorigin="anonymous"></script>

<ins class="adsbygoogle"

 style="display:block; text-align:center;"
 data-ad-layout="in-article"
 data-ad-format="fluid"
 data-ad-client="ca-pub-4855142804875926"
 data-ad-slot="5670838583"></ins>

<script>

 (adsbygoogle = window.adsbygoogle || []).push({});

</script>

創建 lambda 函數

創建 lambda

import boto3
import logging
import time
import datetime
import json

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def export_s3_logs(bucket_name, log_group_name, log_stream_name, days_of_logs=1, timeout=1000):
    '''
    today = datetime.datetime.combine(datetime.datetime.utcnow(), datetime.datetime.min.time())
    day_end = today
    day_start = today - datetime.timedelta(days=days_of_logs)
    '''
    today = datetime.datetime.combine(datetime.datetime.utcnow() + datetime.timedelta(hours=8),
                                      datetime.datetime.min.time()) # UTC+8 

    day_end = today - datetime.timedelta(hours=8) # UTC
    day_start = today - datetime.timedelta(days=days_of_logs, hours=8) # UTC    
   
    #print(day_start)
    ts_start = '{0:.0f}'.format(((day_start - datetime.datetime(1970, 1, 1)).total_seconds())*1000)
    ts_end = '{0:.0f}'.format(((day_end - datetime.datetime(1970, 1, 1)).total_seconds())*1000)
    the_date = '/'.join([str(today.year), '0'+str(today.month)[-2:], '0'+str(today.day)[-2:]]) 
    #folder_name = '/'.join([log_group_name, log_stream_name, the_date])
    folder_name = '/'.join([log_group_name,the_date])
    client = boto3.client('logs')
    
    #print (ts_start, ts_end)#, day_start, day_end,the_date
    
    task_id = client.create_export_task(
        logGroupName=log_group_name,
        #logStreamNamePrefix=log_stream_name,
        fromTime=int(ts_start),
        to=int(ts_end),
        destination=bucket_name,
        destinationPrefix=folder_name
    )['taskId']

    i = 1
    while i<timeout:
        response = client.describe_export_tasks(
            taskId=task_id
        )

        status = response['exportTasks'][0]['status']
        if status == 'COMPLETED':
            result = True
            break
        elif status != 'RUNNING':
            result = False
            break
        i += 1
        time.sleep(interval)
    
    return result

def lambda_handler(event, context):
    region = 'cn-northwest-1' # 日誌組所在區域
    bucket_name = '<bucket name>' #同區域內的S3桶名稱
    log_group_name = '<log group name>' #日誌組名稱
    log_stream_name = '1' #默認即可
    log_export_days = 1   #默認即可
    export_s3_logs(bucket_name, log_group_name, log_stream_name, log_export_days)

給 lambda 分配權限

  • AmazonS3的讀寫權限
  • CloudWatchLogsFullAccess

驗證桶內的文件

最後會以日期的目錄將日誌歸檔起來,以方便日後對歸檔文件進行梳理。
sre運維|Linux運維|關鍵詞


作者:SRE運維博客
博客地址:https://www.cnsre.cn/
文章地址:https://www.cnsre.cn/posts/221205544069/
相關話題:https://www.cnsre.cn/tags/aws/

user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.