ทำหน้าดู Log ของ Docker Container ผ่าน ELK อย่างง่าย

โดยปกติแล้วหากเวลาใช้งาน Docker และสั่งให้ Container นั้นทำงาน เราจะสามารถดู Log ด้วยการใช้คำสั่ง

$ docker logs <container id>

ก็จะทำให้เราได้มองเห็นสิ่งที่ Container พ่นออกมาผ่านทาง STDOUT และ STDERR อยู่ใน container แต่ปัญหามันมีอย่างหนึ่งคือ ถ้าเราไม่สามารถ Access เข้าเครื่องที่รัน Docker Engine ได้ก็จะค่อนข้างลำบากในการตรวจสอบ Container คราวนี้เราจะมาหาทางออกให้กับปัญหาพวกนี้กันด้วยการใช้ ELK (Elasticsearch + Logstash + Kibana) ในการส่ง log จาก container ออกมาให้เราดูได้ผ่านทางหน้าเว็ป

ในที่นี้ผมจะใช้ ELK ที่ทำงานด้วย Docker ทั้งหมดนะครับ

 

เริ่มต้นการทำงาน Elasticsearch

$ docker run -d --name elasticsearch elasticsearch

สร้างไฟล์ของ logstash.conf ที่ /opt/logstash/conf/logstash.conf ให้มีการรับข้อมูลขาเข้ามาจาก gelf และส่งออกไปหา elasticsearch ด้วยเนื้อไฟล์

และเริ่มต้นการทำงานของ log stash container

docker run -d --name logstash --link elasticsearch:elasticsearch -v /opt/logstash/conf/logstash.conf:/config-dir/logstash.conf logstash logstash -f /config-dir/logstash.conf

เริ่มต้นการทำงานของ kibana

docker run -d --name kibana --link elasticsearch:elasticsearch -p 5601:5601 kibana

 

การนำ STDOUT, STDERROR หรือ log ของ container เข้าสู่ ELK เผื่อใช้ในการทำเป็นตัวอย่าง index ให้กับ Elasticsearch

หลักๆ แล้วเราจะต้องระบุ log-driver และ log-option ต่างๆ ให้กับ container ตัวที่ต้องการใช้งาน ในที่นี่เราจะใช้ gelf ซึ่งจะเป็นการบอกให้ log มี format เป็นของ Graylog และ Logstash (ถ้าไม่ระบุ log จะมีลักษณะเป็น JSON format)

และจะต้องระบุ log-option ดังนี้
gelf-address คือต้องใส่ค่าของ ip address ของ container ของตัว logstash ในที่นี้คำสั่ง docker inspect --format '{{ .NetworkSettings.IPAddress }}' logstash จะทำให้เราได้เลข IP ของ container ที่มีชื่อว่า logstash ออกมาได้ ค่าที่ได้มีค่า 172.18.0.4 เป็นต้น

tag คือ ชื่อที่เราจะกำหนดให้ตัว container ตัวนี้ ถ้าเราเปิดหน้า kibana สามารถค้นหา log ด้วย tag ได้

$ docker run --rm --log-driver=gelf --log-opt gelf-address=udp://$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' logstash):12201 --log-opt tag="test" alpine /bin/sh -c "while true; do echo My message \$RANDOM; sleep 1; done;"

คำสั่งดังกล่าวจะเป็นการ start container จาก image alpine ขึ้นมา 1 ตัวและให้มัน echo ตัวเลขที่ได้จากการสุ่มตลอดเวลา หลังจากนั้นให้เราเปิดหน้าเวป kibana เช่น http://localhost:5601

จะมีให้ตั้งค่าเล็กน้อยเพื่อสร้าง index ให้กับ elasticsearch ให้เราเลือก @timestamp ไป

image-2

 

 

เพียงเท่านี้ก็สามารถดู log ที่อยู่ใน Docker ได้แล้ว 😉

image-8

ถ้าใช้ Docker-compose หล่ะ จะทำยังไง

บน Docker-compose (version 1) ก็สามารถใช้งานได้เช่นกัน (version 2 ก็ควรจะใช้งานได้ แต่เดี๋ยวทดสอบให้คราวหลัง) แต่จะต้องปรับเปลี่ยนนิดหน่อยในการ connect เข้าไปหา logstash เพราะในไฟล์ docker-compose.yml เราจะสั่งให้มันหา IP อย่างนั้นไม่ได้ จึงจำเป็นต้องไปหา IP address ของ container ของ logstash เสียก่อน จึงจะนำไปใส่ลงไปใน docker-compose.yml ได้ เช่น

$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' logstash
172.18.0.11

ดังนั้น IP ของ logstash เราคือ 172.18.0.11

web:
 image: "cpiot/web:1.0"
 links:
   - mqtt
   - influxdb
   - worker
 log_driver: gelf
 log_opt: 
   gelf-address: "udp://172.18.0.11:12201"
   tag: "iotcpfarm-web"

worker:
 image: "cpiot/worker:1.0"
 links:
   - mqtt
   - influxdb
 log_driver: gelf
 log_opt: 
   gelf-address: "udp://172.18.0.11:12201"
   tag: "iotcpfarm-woker"

 

เมื่อเราสั่ง docker-compose up ขึ้นแล้ว log ก็จะวิ่งเข้าไปหา ELK ทันที

 

ref:

https://gist.github.com/735f2871460a2b068080.git
https://docs.docker.com/compose/compose-file/#/log-driver
https://docs.docker.com/compose/compose-file/#/log-option

ball Written by:

Teerapat Khunpech Live, Tech, Beers, Bike, Cafe Racer, Docker, Devops, Eco-System