ตอนเปิด Cost Explorer แล้วเห็นกราฟ EC2 กับ RDS โตเป็นแท่งใหญ่ ใครๆ ก็รู้ว่าต้องไปดูตรงนั้นก่อน ปัญหาคือเงินที่รั่วจริงๆ มักไม่ได้อยู่ในแท่งใหญ่ มันซ่อนอยู่ในบรรทัดเล็กๆ ที่ชื่อฟังดูไม่น่ากลัว เช่น "Data Transfer" หรือ "EC2-Other" ซึ่งเป็นถังรวมที่ยัดสารพัดอย่างไว้ข้างใน
บทความนี้เล่าวิธีที่ใช้จริงเวลาไล่บิล: เลิกดูระดับ Service แล้วเจาะลงไปที่ Usage Type ทีละบรรทัด พร้อม 6 จุดที่เจอบ่อยที่สุด ตัวเลขราคาทั้งหมดเป็น list price ของ us-east-1 ณ ตอนเขียน (ราคาเปลี่ยนได้ และแต่ละ region ไม่เท่ากัน เช็คหน้า pricing ของ AWS อีกทีก่อนเอาไปคำนวณ) ส่วนตัวเลขบิลจริงของที่ไหนไม่เอามาใส่ทั้งนั้น
ทำไมระดับ Service ถึงไม่พอ
"EC2-Other" ใน Cost Explorer ไม่ใช่ instance นะ มันคือทุกอย่างที่เกี่ยวกับ EC2 แต่ไม่ใช่ค่า instance: EBS volume, snapshot, NAT Gateway, Elastic IP, data transfer ข้าม AZ ทั้งหมดรวมอยู่ในก้อนเดียว ถ้าก้อนนี้โต คุณไม่มีทางรู้เลยว่าเป็นเพราะอะไร จนกว่าจะแตกมันออกเป็น Usage Type
วิธีแตกที่เร็วที่สุดคือใน Cost Explorer เลือก Group by เป็น Usage Type แล้ว filter Service เป็น "EC2-Other" ถ้าชอบ CLI:
aws ce get-cost-and-usage \
--time-period Start=2026-09-01,End=2026-10-01 \
--granularity MONTHLY \
--metrics UnblendedCost \
--filter '{"Dimensions":{"Key":"SERVICE","Values":["EC2 - Other"]}}' \
--group-by Type=DIMENSION,Key=USAGE_TYPE \
--query 'ResultsByTime[0].Groups[].[Keys[0],Metrics.UnblendedCost.Amount]' \
--output text | sort -k2 -nr | head -15
หมายเหตุเล็กๆ: Cost Explorer API คิดเงินต่อ request (ราว $0.01 ต่อครั้ง) ไม่ต้องยิงรัวใน loop แต่ถ้าครั้งสองครั้งต่อเดือน ไม่ถึงกับเจ็บ
พอได้ลิสต์ Usage Type แล้ว ลองไล่ดูหกตัวนี้ก่อน
1. NatGateway-Bytes: ค่าประมวลผลต่อ GB ที่ไม่มีใครมอง
NAT Gateway คิดสองก้อน คือค่าชั่วโมง (NatGateway-Hours) กับค่าประมวลผลข้อมูลต่อ GB (NatGateway-Bytes, ราว $0.045 ต่อ GB) ก้อนหลังคือตัวที่โตเงียบๆ เพราะทุก byte ที่ผ่าน NAT โดนนับหมด ไม่ว่าจะไปไหน
ตัวการที่เจอบ่อยคือ traffic ไป S3 และ DynamoDB ที่ไหลผ่าน NAT ทั้งที่ไม่จำเป็น เพราะ Gateway endpoint ของ S3 กับ DynamoDB ไม่มีค่าใช้จ่าย และ pod ที่ pull image จาก ECR ก็เหมือนกัน layer จริงๆ อยู่ใน S3 ใส่ S3 gateway endpoint ใน route table ของ private subnet ก้อนใหญ่หายไปได้เลย
ส่วน interface endpoint (เช่นของ ECR API, STS) ไม่ฟรี คิดต่อ AZ ต่อชั่วโมงบวกค่า data ต้องคำนวณก่อนว่าคุ้มกว่า NAT หรือเปล่า ไม่ใช่ใส่ทุกตัวตามกระแส
2. PublicIPv4:InUseAddress และ IdleAddress: IP ที่เคยฟรีกลายเป็นบิล
ตั้งแต่ AWS เริ่มคิดค่า public IPv4 ทุกตัว (ตัวละ $0.005 ต่อชั่วโมง ราว $3.65 ต่อเดือน) ไม่ว่าจะใช้งานอยู่หรือไม่ก็ตาม บรรทัดนี้โผล่ในบิลของแทบทุกคน Usage Type จะแยกเป็น PublicIPv4:InUseAddress กับ PublicIPv4:IdleAddress
ที่ควรเช็คตามลำดับ:
- Elastic IP ที่ไม่ได้ผูกกับอะไร (Idle) ลบได้เลย
- ENI ที่ค้างอยู่หลังลบ resource ที่เคยใช้มัน
- EC2 ใน public subnet ที่จริงๆ ไม่ต้องมี IP ตัวเอง ย้ายไปหลัง load balancer ได้
- ALB เองก็ใช้ public IP ต่อ AZ นะ อย่าลืมนับด้วย
ข้อควรระวัง: ถ้าย้ายของไปหลัง NAT เพื่อประหยัด IP ให้กลับไปดูข้อ 1 ด้วย เดี๋ยวประหยัดค่า IP แล้วไปเสียค่า NAT แทน
3. DataTransfer-Regional-Bytes: ค่า traffic ข้าม AZ
ข้อนี้ทำให้คนงงบ่อยที่สุด traffic ระหว่าง AZ ใน region เดียวกันคิดเงินทั้งสองฝั่ง (ราว $0.01 ต่อ GB ขาออกและ $0.01 ต่อ GB ขาเข้า รวมเป็น $0.02 ต่อ GB ต่อการส่งหนึ่งครั้ง) ฟังดูเล็ก แต่ cluster ที่ service คุยกันถี่ๆ กระจายอยู่หลาย AZ จะสะสมเร็วมาก
จุดที่ต้องดู: service ที่คุยกันเยอะแต่ถูก schedule คนละ AZ, ระบบ messaging หรือ database replication ข้าม AZ, และ log shipper ที่ส่งข้ามไปรวมศูนย์ ใน Kubernetes ลองใช้ topology aware routing (ให้ Service ส่ง traffic ไปที่ endpoint ใน AZ เดียวกันก่อน) หรือ topologySpreadConstraints ที่คิดมาแล้วว่า service คู่ไหนควรอยู่ใกล้กัน แลกกับความ resilient ที่ลดลงนิดหน่อย ซึ่งต้องตัดสินใจเป็นรายระบบ ไม่ใช่เปิดทุกที่
4. DataProcessing-Bytes ของ CloudWatch Logs: ค่า ingest
CloudWatch Logs คิดค่า ingest ราว $0.50 ต่อ GB (ราคาที่แพงกว่าที่คนส่วนใหญ่นึก) และ retention ค่าเริ่มต้นคือ Never expire บรรทัดนี้โตเงียบๆ จากสาเหตุเดิมซ้ำๆ: service ยิง DEBUG ใน production ค้างไว้, log ของ health check ทุก 10 วินาที, หรือ log แบบ JSON ก้อนใหญ่ที่ไม่มีใครอ่าน
ไล่แก้ตามนี้: ตั้ง retention ทุก log group (หลักวันถึงหลักเดือนตามที่ต้องใช้จริง), ปรับ log level, กรอง health check ออกที่ต้นทาง และสำหรับ log ที่ต้องเก็บยาวแต่ไม่ค่อยอ่าน พิจารณา Infrequent Access log class ที่ราคา ingest ถูกลง (แลกกับฟีเจอร์ที่ลดลง เช็คข้อจำกัดก่อนใช้)
5. VolumeUsage.gp2 และ snapshot ที่ไม่มีเจ้าของ
EBS gp3 ถูกกว่า gp2 ราว 20% ต่อ GB ($0.08 เทียบกับ $0.10) และได้ baseline 3,000 IOPS ทุกขนาด แถมเปลี่ยนจาก gp2 เป็น gp3 ได้แบบ online ด้วย modify-volume ไม่ต้อง detach ที่เจอบ่อยคือ module Terraform เก่าที่ก๊อปต่อกันมายังตั้ง default เป็น gp2 อยู่ แก้ที่ default ใน IaC ด้วย ไม่งั้นของใหม่ก็ยังเป็น gp2 ต่อไป
อีกก้อนคือ snapshot ที่ค้างอยู่หลัง AMI ถูก deregister ซึ่ง AWS ไม่ลบให้ ลองไล่ดู snapshot ที่ไม่มี AMI หรือ volume ต้นทางอ้างถึงแล้ว ตั้ง lifecycle policy (Data Lifecycle Manager) ให้ลบเองตามอายุ
6. ELB ที่ไม่มี traffic
Load balancer คิดค่าชั่วโมงตลอดเวลาที่มันอยู่ ต่อให้ไม่มี request สักตัว ของที่เจอบ่อยคือ ALB/NLB ที่เหลือจาก environment ที่เคยทดลองแล้วไม่ได้ลบ เช็คจาก metric RequestCount หรือ ActiveFlowCount ใน CloudWatch ย้อนหลัง 30 วัน ถ้าเป็นศูนย์ตลอด ถามเจ้าของก่อน แล้วค่อยลบ
จัดลำดับก่อนลงมือ
ไล่ครบหกข้อแล้วอย่าเพิ่งแก้ทุกอย่างพร้อมกัน เรียงตามเงินที่ได้คืนต่อแรงที่เสีย แล้วเริ่มจากของที่ไม่เสี่ยงก่อน:
- ตั้ง retention ให้ log group และลบ Elastic IP / snapshot / ELB ที่ไม่มีใครใช้ (เสี่ยงต่ำ ได้เงินคืนเร็ว)
- ใส่ S3 gateway endpoint และเปลี่ยน default เป็น gp3 ใน IaC
- ค่อยพิจารณา cross-AZ กับ interface endpoint ที่ต้องคำนวณและมี trade-off เรื่อง resilience
ก่อนลบอะไรที่ไม่ใช่ของตัวเอง ให้ดูก่อนว่ามี tag เจ้าของไหม ถ้าไม่มี ถามในช่องทีมก่อน และเปิด cost allocation tag ไว้ตั้งแต่วันนี้ เพราะเดือนหน้าคุณจะอยากรู้ว่าบรรทัดไหนเป็นของทีมไหน
สรุป
Cost Explorer ระดับ Service บอกว่า "เงินไปไหน" ได้แค่ครึ่งเดียว ครึ่งที่เหลืออยู่ใน Usage Type ซึ่งใช้เวลาอ่านไม่ถึงครึ่งชั่วโมงต่อเดือน ลองตั้งเป็นกิจวัตรสิ้นเดือน เปิดกราฟ group by Usage Type เรียงจากมากไปน้อย แล้วถามตัวเองว่า "บรรทัดนี้ ใครเป็นเจ้าของ แล้วเรารู้หรือเปล่าว่ามันควรอยู่เท่านี้" แค่นี้ก็จับของรั่วได้ก่อนมันกลายเป็นบิลก้อนโต 555
ตัวเลขราคาในบทความเป็น list price โดยประมาณของ us-east-1 ราคาจริงของคุณอาจต่างตาม region, ส่วนลด หรือสัญญา ตรวจกับหน้า pricing และ pricing calculator ของ AWS ก่อนตัดสินใจทุกครั้ง
Top comments (0)