[Update] การจัดการ laravel.log ด้วย CloudWatch Logs ใน Elastic Beanstalk

[Update] การจัดการ laravel.log ด้วย CloudWatch Logs ใน Elastic Beanstalk

CloudWatch เป็นบริการที่สามารถช่วยให้เราสามารถดูประวัติการใช้งานผ่าน Log ได้ ต่อให้เป็นการสร้าง EC2 ในรูปแบบ Auto Scaling บน Elastic Beanstalk ก็สามารถทำการบันทึก Log ได้อย่างง่ายดาย และสำหรับคนที่กำลังใช้งาน Auto Scaling บน EC2 อยู่และมีการเปิด-ปิดการใช้งานอัตโนมัติอยู่ตลอดเวลา ผมแนะนำให้ลองใช้ CloudWatch ดูครับ ซึ่งในบทความนี้ผมจะมาสาธิตวิธีการจัดการ laravel.log ด้วย CloudWatch Logs บน Elastic Beanstalk ครับ

สวัสดีครับ POP จากบริษัท Classmethod (Thailand) ครับ

เราสามารถจัดการ laravel.log ด้วย CloudWatch Logs เพื่อดูประวัติการใช้งานผ่าน Log ที่เป็นการสร้าง EC2 ในรูปแบบ Auto Scaling บน Elastic Beanstalk ได้

สิ่งที่ต้องมี

สร้างสภาพแวดล้อมสำหรับสร้างไฟล์โปรเจกต์ ZIP

หากยังไม่มีโปรเจกต์ Laravel ให้สร้างโปรเจกต์ตามนี้ได้เลย แต่ถ้ามีโปรเจกต์อยู่แล้วข้ามไปสร้างไฟล์ ZIP โดยดูที่ลิงก์บทความถัดไปได้เลย (ครั้งนี้จะใช้ Instance ชื่อ tinnakorn-develop)

แล้วสร้างไฟล์ ZIP โดยดูตัวอย่างที่ลิงก์บทความนี้ (ยังไม่ต้องรันคำสั่งสร้างไฟล์ ZIP)

ดาวน์โหลดไฟล์โปรเจกต์ ZIP

Click to download: laravel10-sample.zip

เมื่อดาวน์โหลดไฟล์เสร็จแล้ว ให้แตกไฟล์และคัดลอกโฟลเดอร์ .ebextensions ไปเพิ่มในโปรเจกต์ที่จะ Deploy ไปยัง Elastic Beanstalk ซึ่งในโฟลเดอร์จะมีไฟล์ดังนี้

  • .ebextensions
    • 01_swap.config
    • 02_timezone.config
    • 03_laravel_folders.config
    • 04_mariadb.config

 

การเตรียมไฟล์ CloudWatch Log Config ใน Laravel

สร้างไฟล์: [.ebextensions/05_cloudwatchlog.config] และคัดลอก Code นี้วางที่ไฟล์ 05_cloudwatchlog.config

packages:
  yum:
    amazon-cloudwatch-agent: []
files:
  "/home/ec2-user/cloudwatch_log_setup.sh":
    mode: "000755"
    owner: root
    group: root
    content: |
      #!/bin/bash
      export $(cat /opt/elasticbeanstalk/deployment/env | grep -v ^# | xargs);
      export INSTANCE_ID=`cat /var/lib/cloud/data/instance-id`
      aws logs create-log-group --log-group-name "/${APP_NAME}/${APP_ENV}/laravel_log" --region ${AWS_DEFAULT_REGION}
      aws logs put-retention-policy --log-group-name "/${APP_NAME}/${APP_ENV}/laravel_log" --retention-in-days 30 --region ${AWS_DEFAULT_REGION}
      aws logs create-log-stream --log-group-name "/${APP_NAME}/${APP_ENV}/laravel_log" --log-stream-name ${INSTANCE_ID} --region ${AWS_DEFAULT_REGION}
      echo -n "" >> /etc/amazon/amazon-cloudwatch-agent/amazon-cloudwatch-agent.d/laravel_log
      printf '{
          "logs": {
              "logs_collected": {
                  "files": {
                      "collect_list": [
                          {
                              "file_path": "/var/app/current/storage/logs/laravel*.log",
                              "log_group_name": "/%s/%s/laravel_log",
                              "log_stream_name": "%s",
                              "auto_removal": true,
                              "retention_in_days": 30,
                              "timestamp_format": "%%Y-%%m-%%d %%H:%%M:%%S",
                              "timezone": "Local"
                          }
                      ]
                  }
              }
          }
      }
      ' ${APP_NAME} ${APP_ENV} ${INSTANCE_ID} > /etc/amazon/amazon-cloudwatch-agent/amazon-cloudwatch-agent.d/laravel_log

container_commands:
  "01_cloudwatchlog_install":
    command: |
      echo `date`." 01_cloudwatchlog_install" >> /var/log/ebextensions_test.log
      /home/ec2-user/cloudwatch_log_setup.sh
      systemctl restart amazon-cloudwatch-agent.service
      systemctl enable amazon-cloudwatch-agent.service

เมื่อเตรียมไฟล์การตั้งค่า CloudWatch Log เสร็จแล้ว ให้ทำการสร้างไฟล์ ZIP โดยรันคำสั่งนี้

รันคำสั่งล้างแคชต่างๆ เตรียมไว้

php artisan optimize:clear

รันคำสั่งด้านล่างนี้เพื่อสร้างไฟล์ zip ตามสิ่งที่เขียนไว้ข้างต้นนี้ (*เปลี่ยน "[deploy_file_name.zip]" ให้เป็นชื่อไฟล์ของคุณ เช่น laravel10-cloudwatchlog.zip เป็นต้น)

zip -r: คำสั่งสร้างไฟล์ zip
-x: คำสั่งยกเว้นโฟลเดอร์หรือไฟล์เพื่อไม่ให้รวมใน zip

zip -r [deploy_file_name.zip] * .editorconfig .styleci.yml .ebextensions .platform -x \*/.git/\* vendor/\* node_modules/\* public/build/\* public/hot/\* public/storage/\* storage/\*.key storage/framework/sessions/\* storage/framework/views/\* Homestead.json Homestead.yaml npm-debug.log yarn-error.log .idea .vscode .env \*.zip

สร้าง Resources ที่จำเป็นสำหรับ Elastic Beanstalk

สร้าง Service role และ Instance profile ที่ใช้สำหรับ Elastic Beanstalk ใน IAM

ครั้งนี้จะสร้าง Service role และ Instance profile ที่ใช้สำหรับ Elastic Beanstalk ใน IAM โดยจะเพิ่มสิทธิ์สำหรับจัดการ CloudWatch Logs ลงใน Instance profile เพื่อให้ Instance ที่สร้างใน Elastic Beanstalk สามารถจัดการ CloudWatch Logs ได้โดยแนะนำให้กำหนดชื่อและ Permissions ตาม Documentation ของ AWS และกำหนด Permissions ที่ชื่อ CloudWatchLogsFullAccess เพิ่มเติมดังนี้

IAM Role Name Permissions
tinnakorn-cloudwatchlog-ec2-role AWSElasticBeanstalkWebTier
AWSElasticBeanstalkWorkerTier
AWSElasticBeanstalkMulticontainerDocker
CloudWatchLogsFullAccess

ขั้นตอนนี้ให้สร้าง Role ดังกล่าวโดยดูตัวอย่างที่ลิงก์ด้านล่างนี้โดยเพิ่มสิทธิ์ CloudWatchLogsFullAccess เข้าไปใน Role สำหรับ Instance profile ด้วย และสำหรับชื่อ IAM Role สามารถตั้งชื่อได้ตามต้องการ

สร้าง Key Pair สำหรับ Elastic Beanstalk

ครั้งนี้จะสร้าง Key Pair ชื่อว่า tinnakorn-cloudwatchlog-eb

ดูตัวอย่างที่นี่เฉพาะหัวข้อนี้: การสร้าง Key Pair

ตัวอย่างตั้งค่าการสร้าง Key Pairs ในบทความนี้
※Create Key pairs
Name: tinnakorn-cloudwatchlog-eb
Private key file format: .ppk

สร้าง Security Group สำหรับ Elastic Beanstalk

ครั้งนี้จะสร้าง Security Group ชื่อว่า: tinnakorn-cloudwatchlog-eb เข้ามาที่ Service Amazon EC2 แล้วคลิก Security Groups จากเมนูด้านซ้ายในหัวข้อ "▼ Network & Security"

คลิก Create security group

เมื่อเข้ามาหน้า Create security group แล้วให้ตั้งค่า Basic details:
・Security group name: tinnakorn-cloudwatchlog-eb (ชื่ออะไรก็ได้)
・Description: tinnakorn-cloudwatchlog-eb (ป้อนอะไรก็ได้)

จากนั้นเลื่อนลงมาด้านล่างสุด คลิก Create security group

การสร้าง Security Groups ใช้สำหรับ Elastic Beanstalk เสร็จเรียบร้อยแล้ว ทำขั้นตอนถัดไปได้เลย

สร้าง Environment สำหรับ CloudWatch Log

หากเรามี Environment ที่ Deploy สำหรับ Laravel อยู่แล้ว สามารถ Copy การตั้งค่าและสร้าง Environment จาก Saved configuration ใน Application ของเราได้โดยดูตัวอย่างได้ที่ลิงก์ด้านล่างนี้

หากไม่มี Environment ดังกล่าวให้ทำตามขั้นตอนด้านล่างนี้

ดูวิธีการสร้าง Environment สำหรับ CloudWatch Log ด้วย Auto Scaling ตามลิงก์ด้านล่างนี้ เนื่องจากเป็นการตั้งค่าที่เหมือนกัน

ดูตัวอย่างที่นี่: สร้าง Environment สำหรับ Auto Scaling (ดูตัวอย่างการตั้งค่าด้านล่างนี้ประกอบด้วย เนื่องจากมีบางส่วนที่ตั้งค่าไม่เหมือนกัน)

ตัวอย่างครั้งนี้จะสร้าง Environment โดยใช้ชื่อดังนี้
Environment name: tinnakorn-cloudwatchlog-eb
EC2 key pair: tinnakorn-cloudwatchlog-eb
EC2 security groups: tinnakorn-cloudwatchlog-eb

สำหรับ Step 2 - Configure service access เปลี่ยน EC2 instance profile ให้เป็นสำหรับ CloudWatch Log ดังนี้
・เลือก EC2 instance profile ที่สร้างเมื่อสักครู่ ครั้งนี้คือ tinnakorn-cloudwatchlog-ec2-role

สำหรับ Step 4 - optional: Configure instance traffic and scaling
・ไม่ต้องตั้งค่าเปิดใช้งาน Stickiness ในหัวข้อ Processes เนื่องจากต้องการทดสอบ Error Log ที่ถูกส่งจาก Instance ไปยัง CloudWatch Log

สำหรับ Step 5 - optional: Configure updates, monitoring, and logging ให้เปลี่ยนการตั้งค่าในส่วนของ Environment properties ให้เป็นสำหรับ CloudWatch Log ดังนี้
・APP_ENV = cloudwatchlog
・APP_NAME = tinnakorn
・คลิก Next ไปยัง Step 6: Review

แล้วดำเนินการ Step 6: Review
・ตรวจสอบการตั้งค่าตั้งแต่ "Step 1 - Step 5"
・คลิก Submit ด้านล่างสุด แล้วรอสักครู่

ถ้าเสร็จแล้วให้คลิกลิงก์เปิดหน้าเว็บไซต์โปรเจกต์ของเราจากหน้า Environment (ลิงก์นี้เป็นแค่ตัวอย่าง)

http://tinnakorn-cloudwatchlog-eb.ap-southeast-1.elasticbeanstalk.com/

ตรวจสอบ CloudWatch Log

ไปที่ Service [CloudWatch > Log groups]

ทำการตรวจสอบ Log ดังนี้:
ค้นหาชื่อของเรา เช่น /tinnakorn/cloudwatchlog แล้วคลิกเข้าไป (นี่คือตัวแปรสภาพแวดล้อมที่ถูกใช้งาน ซึ่งเป็น /APP_NAME/APP_ENV นั่นเอง)

เมื่อเข้ามาแล้วดูที่ Log streams จะเห็นว่ามี Instance ID แสดงขึ้นมา 2 ตัวตามที่กำหนดไว้ใน Elastic Beanstalk
ซึ่งเราสามารถ Copy Instance ID จากที่นี่ไปค้นหาในหน้า Instance ได้
ทีนี้ให้คลิกเข้าไปดูในแต่ละ Instance ได้เลย

Instance ID ของบทความนี้: i-00ab2472f62135222, i-0e84af5b8940bab63

จะเห็นว่าไม่มีข้อมูลแสดงใน Log events เพราะว่ายังไม่มี Error

ทดสอบ Error Log ใน CloudWatch Log


กลับมาที่หน้าเว็บไซต์โปรเจกต์ของเรา แล้วเปิดหน้าเว็บอะไรก็ได้ที่ทำให้เกิด Error เพื่อให้บันทึก Log ไปยัง laravel.log เช่น

http://tinnakorn-cloudwatchlog-eb.ap-southeast-1.elasticbeanstalk.com/customer/3

ไปที่หน้า Service [CloudWatch > Log groups > /your_app_name/cloudwatchlog/laravel_log > i-your_instance_id]
จะเห็นว่ามีข้อมูล Error Log แสดงขึ้นมาแล้ว

Terminate Instance และตรวจสอบ CloudWatch Log

มาที่ Service [EC2 > Instance] แล้วทำการ Terminate instance ตัวไหนก็ได้สัก 1 ตัว
เช่น i-00ab2472f62135222 แล้วรอจนกว่า Instance state เป็น Terminate

เมื่อ Instance state เป็น Terminate แล้วให้กดปุ่ม Reload
จะเห็นว่ามี Instance ใหม่เพิ่มขึ้นมา 1 ตัว นั่นก็คือ i-00f477fcd99cf242e

ทีนี้ให้มาที่หน้า Service [CloudWatch > Log groups > /your_app_name/cloudwatchlog/laravel_log]
จะเห็นว่า Log stream ของ Instance ID: i-00f477fcd99cf242e เพิ่มขึ้นมา ซึ่งยังไม่มีข้อมูล Error Log (กรณีที่ต้องการดู Log ของ Instance ID ที่ Terminate ไปแล้ว สามารถคลิกเข้าไปที่ Instance ID นั้นได้เลย)

ไปที่หน้าเว็บไซต์โปรเจกต์ที่ Error ของเรา แล้วทำการ Reload ประมาณ 2-3 ครั้ง

จากนั้นกลับมาที่หน้า Service [CloudWatch > Log groups > /your_app_name/cloudwatchlog/laravel_log] อีกครั้งแล้วทำการ Reload
ถ้า Last event time ในแถวของ Instance ID ตัวใหม่แสดงวันที่และเวลาขึ้นมาแล้ว ให้คลิกเข้าไปได้เลย

จะเห็นว่ามีข้อมูล Error Log แสดงขึ้นมาแล้ว เพียงเท่านี้เราก็สามารถดูข้อมูล Log ใน Instance ของเราได้โดยไม่ต้องเข้าไปใน Linux และรันคำสั่งให้ยุ่งยากอีกต่อไป

สรุป

ผมได้มีโอกาสใช้ CloudWatch Log แล้วทำให้ผมรู้สึกว่าเวลาจะดูข้อมูล Error, ข้อมูลการเชื่อมต่อ หรือประวัติการใช้งานต่างๆ ก็ไม่ต้องไปรันคำสั่งใน Server EC2 ทุกครั้งให้ยุ่งยาก และตั้งแต่ได้รู้จักกับ Service CloudWatch แล้วทำให้ผมได้เห็นถึงความสะดวกในการตรวจสอบข้อมูลที่เรียกว่า Log คือเราสามารถเข้าไปดูใน Service CloudWatch ได้เลยนั่นเอง

นอกจากนี้ต่อให้เราทำการ Terminate Instance ไปแล้วเราก็ยังสามารถดูประวัติการใช้งานย้อนหลังของ Instance นั้นใน CloudWatch Log ได้อีกด้วย

บทความที่เกี่ยวข้อง

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.