APM Field LabECV Operation · Technical Enablement RHEL · Apache · PHP-FPM
ทดสอบจริงแล้ว · Manual lab

Deploy. Trace.
Verify.

ติดตั้ง Datadog APM บน EC2 RHEL แบบทีละขั้น ตั้งแต่ Apache และ PHP-FPM ไปจนถึง trace แรกที่มองเห็นได้จริง

เริ่มจาก Pre-check RHEL 8/9 · Agent 7 · PHP 8.x
7 manual steps Learn at your pace
↗
Trace goalยืนยัน Traces received > 0
DATADOG APM · HANDS-ON

ทำตามทีละขั้นตอน

รันทีละ code block และเทียบ output ก่อนขยับไป Step ถัดไป ทุกตัวอย่างมาจากการทดสอบจริงบน RHEL 9.8

Terraform scope

lab/ สร้างเฉพาะ EC2 + encrypted volume + IAM/SSM ส่วน Apache, PHP-FPM, sample app และ Datadog ให้ทำตาม 7 ขั้นตอนด้านล่างด้วยตนเอง

เส้นทางที่ทดสอบผ่านแก้ 4 จุดก่อนเริ่ม เพื่อไม่ต้องย้อนแก้กลางแลป
01

Apache bindใช้คำสั่ง sed ที่ให้ไว้ตรง ๆ แล้วตรวจ Listen 127.0.0.1:80

02

SELinux ก่อนลง SSIติดตั้ง policy ใน Step 02 ขณะเครื่องยัง clean แล้วคง Enforcing ตั้งแต่ต้น

03

Trace ผ่าน TCPกำหนด DD_TRACE_AGENT_URL ทั้ง pool และ systemd เพื่อเลี่ยง UDS denial

04

รอ minute windowAgent status สรุป “previous minute” ถ้าดูเร็วเกินไปอาจยังเป็นศูนย์

01
STEP 01

สำรวจเครื่องก่อนติดตั้ง

3 min

บันทึก OS, เวอร์ชัน runtime, สถานะ service และ endpoint ของ PHP-FPM ก่อนแก้ configuration

bash · EC2
cat /etc/redhat-release
uname -m
systemctl is-active amazon-ssm-agent
php -v || true
php-fpm -v || true
httpd -v || true

sudo systemctl status httpd --no-pager || true
sudo systemctl status php-fpm --no-pager || true
sudo grep -E '^[; ]*listen[ .=]' /etc/php-fpm.d/www.conf || true

# ตรวจ outbound ที่ Agent ต้องใช้
curl -I --max-time 10 https://app.datadoghq.com
✓

ผ่านเมื่อ ยืนยันได้ว่าเป็น RHEL 8/9 และออก HTTPS ไป Datadog ได้

Observed output · clean host
Red Hat Enterprise Linux release 9.8 (Plow)
x86_64
amazon-ssm-agent: active
package httpd is not installed
package php-fpm is not installed
package datadog-agent is not installed
02
STEP 02

ติดตั้ง Stack และเตรียม SELinux

12 min

ติดตั้ง package มาตรฐานของ RHEL แล้วเตรียม policy ให้เรียบร้อยก่อนลง Datadog SSI

bash · EC2
sudo dnf install -y httpd php php-fpm php-cli curl

# แลปนี้ใช้ Security Group ที่มี inbound กว้าง จึง bind เฉพาะ localhost
sudo sed -i -E 's/^Listen[[:space:]]+80$/Listen 127.0.0.1:80/' \
  /etc/httpd/conf/httpd.conf
grep '^Listen' /etc/httpd/conf/httpd.conf

sudo systemctl enable --now php-fpm httpd

sudo apachectl configtest
systemctl is-active httpd php-fpm
httpd -v | head -1
php-fpm -v | head -1
curl -I http://127.0.0.1/
ปัญหาที่เจอจริง: คำสั่ง sed ที่ escape space ผิดจะขึ้น unterminated `s' command ให้ใช้คำสั่งด้านบนทั้งบรรทัดและตรวจค่า Listen ก่อน restart
✓

ผ่านเมื่อ configtest แสดง Syntax OK และ service ทั้งสองเป็น active

Observed output
Listen 127.0.0.1:80
Syntax OK
active
active
Server version: Apache/2.4.62 (Red Hat Enterprise Linux)
PHP 8.0.30 (fpm-fcgi)

2.1 ติดตั้ง SELinux policy ก่อนลง Datadog SSI

ทำตอนนี้ก่อน Step 04

คง SELinux เป็น Enforcing ตลอดแลป Policy นี้จำกัดเฉพาะสิทธิ์ที่ AppSec sidecar ต้องใช้และการเชื่อมต่อ TCP 8126 จึงไม่ต้องใช้ setenforce 0

เหตุผลที่ต้องเตรียมก่อนลง SSI
ถ้า restart PHP-FPM หลังลง SSI แต่ยังไม่มี policy อาจพบ:
AH01075: Error dispatching request to PHP-FPM (polling timeout)
PHP-FPM child exited on signal 6 (SIGABRT)
avc: denied { execute_no_trans } ... scontext=httpd_t ... tcontext=ld_so_t

เปิด sudo vi /tmp/datadog_php_sidecar.te แล้ววาง policy ต่อไปนี้:

selinux · /tmp/datadog_php_sidecar.te
module datadog_php_sidecar 1.2;

require {
    type httpd_t;
    type httpd_tmpfs_t;
    type ld_so_t;
    attribute port_type;
    class file { execute execute_no_trans };
    class tcp_socket name_connect;
}

type datadog_apm_port_t;
typeattribute datadog_apm_port_t port_type;

allow httpd_t httpd_tmpfs_t:file { execute execute_no_trans };
allow httpd_t ld_so_t:file execute_no_trans;
allow httpd_t datadog_apm_port_t:tcp_socket name_connect;
bash · compile, install & label ก่อน SSI
sudo dnf install -y policycoreutils-python-utils checkpolicy policycoreutils-devel

sudo checkmodule -M -m -o /tmp/datadog_php_sidecar.mod /tmp/datadog_php_sidecar.te
sudo semodule_package -o /tmp/datadog_php_sidecar.pp \
  -m /tmp/datadog_php_sidecar.mod
sudo semodule -i /tmp/datadog_php_sidecar.pp
sudo semanage port -a -t datadog_apm_port_t -p tcp 8126 2>/dev/null || \
  sudo semanage port -m -t datadog_apm_port_t -p tcp 8126

getenforce
sudo semodule -l | grep datadog_php_sidecar
sudo semanage port -l | grep datadog_apm_port_t
✓

ผ่านเมื่อ ได้ Enforcing, พบ module datadog_php_sidecar และ port type ของ TCP 8126 ก่อนขยับไป Step 03

Observed output · policy ready before SSI
Enforcing
datadog_php_sidecar
datadog_apm_port_t    tcp    8126
03
STEP 03

สร้าง PHP endpoint สำหรับยิง traffic

5 min

ตัวอย่างมี latency หลายช่วงเพื่อให้ trace flame graph อ่านง่าย โดยไม่ต้องมีฐานข้อมูลภายนอก

bash · EC2
sudo tee /var/www/html/index.php >/dev/null <<'PHP'
<?php
header('Content-Type: application/json');

function loadCatalog(): array {
    usleep(random_int(15000, 45000));
    return ['agent', 'apm', 'integration'];
}

$started = microtime(true);
$items = loadCatalog();
usleep(random_int(5000, 20000));

echo json_encode([
    'service' => 'customer-demo-php',
    'status' => 'ok',
    'items' => $items,
    'duration_ms' => round((microtime(true) - $started) * 1000, 2)
], JSON_PRETTY_PRINT);
PHP

sudo restorecon -Rv /var/www/html
php -l /var/www/html/index.php
curl -s http://127.0.0.1/index.php
✓

ผ่านเมื่อ ได้ JSON ที่มี "status": "ok"

Observed output
No syntax errors detected in /var/www/html/index.php
{
    "service": "customer-demo-php",
    "status": "ok",
    "items": ["agent", "apm", "integration"]
}
05
STEP 05

ตั้งค่า PHP APM แล้ว restart อย่างปลอดภัย

8 min

เมื่อ SELinux policy พร้อมจาก Step 02 แล้ว ให้ตั้ง Unified Service Tags → TCP endpoint → ตรวจ policy → syntax test → restart

เปิด sudo vi /etc/php-fpm.d/www.conf แล้วเพิ่มท้ายไฟล์:

ini · /etc/php-fpm.d/www.conf
env[DD_SERVICE] = customer-demo-php
env[DD_ENV] = dev
env[DD_VERSION] = 1.0.0
env[DD_TRACE_ENABLED] = true
env[DD_LOGS_INJECTION] = true
env[DD_TRACE_AGENT_URL] = http://127.0.0.1:8126

ให้ SSI เห็น endpoint ตั้งแต่เริ่ม service ด้วย systemd drop-in:

bash · systemd drop-in
sudo install -d -m 755 /etc/systemd/system/php-fpm.service.d
sudo tee /etc/systemd/system/php-fpm.service.d/datadog-apm.conf >/dev/null <<'EOF'
[Service]
Environment="DD_TRACE_AGENT_URL=http://127.0.0.1:8126"
EOF
อย่าปิด SELinux

Policy ถูกติดตั้งไว้ก่อนลง SSI ตั้งแต่ Step 02 แล้ว Step นี้เพียงตรวจซ้ำก่อน restart ไม่ใช้ setenforce 0 และไม่สร้าง policy กว้างด้วย audit2allow

bash · pre-restart guard
test "$(getenforce)" = "Enforcing"
sudo semodule -l | grep -q '^datadog_php_sidecar' && echo 'SELinux module: ready'
sudo semanage port -l | grep 'datadog_apm_port_t.*8126'
bash · apply & inspect
sudo systemctl daemon-reload
sudo php-fpm -t
sudo systemctl restart php-fpm httpd

systemctl is-active php-fpm httpd datadog-agent
curl -fsS --max-time 10 http://127.0.0.1/index.php
php-fpm -i | grep -iE 'ddtrace|datadog|dd_library_loader' | head
✓

ผ่านเมื่อ SELinux ยังเป็น Enforcing, services เป็น active และ PHP-FPM พบ Datadog library loader

Observed output
Enforcing
datadog_php_sidecar
datadog_apm_port_t    tcp    8126
configuration file /etc/php-fpm.conf test is successful
active
active
active
{ "service": "customer-demo-php", "status": "ok" }
dd_library_loader v1.25.1
ถ้า request ค้าง: ตรวจ journalctl -u php-fpm และ ausearch -m AVC -ts recent ก่อน อย่าใช้ setenforce 0 สำหรับแก้ลัด ส่วน AVC แบบ getattr ของ UDS/cgroup อาจยังปรากฏจาก SSI probe แต่ไม่ขวาง trace ที่วิ่งผ่าน TCP
06
STEP 06

เปิด Apache และ PHP-FPM integrations

12 min

6.1 Apache mod_status

เปิด sudo vi /etc/httpd/conf.d/datadog-status.conf แล้วใส่:

apache · /etc/httpd/conf.d/datadog-status.conf
<Location "/server-status">
    SetHandler server-status
    Require local
</Location>

ExtendedStatus On

เตรียม directory แล้วเปิด sudo vi /etc/datadog-agent/conf.d/apache.d/conf.yaml:

bash · prepare integration directories
sudo install -d -o dd-agent -g dd-agent \
  /etc/datadog-agent/conf.d/apache.d \
  /etc/datadog-agent/conf.d/php_fpm.d
yaml · /etc/datadog-agent/conf.d/apache.d/conf.yaml
init_config:

instances:
  - apache_status_url: http://127.0.0.1/server-status?auto
    tags:
      - env:dev
      - service:customer-demo-php

6.2 PHP-FPM status และ ping

เพิ่มสามบรรทัดนี้ท้าย /etc/php-fpm.d/www.conf:

ini · เพิ่มใน /etc/php-fpm.d/www.conf
pm.status_path = /status
ping.path = /ping
ping.response = pong
apache · เพิ่มใน datadog-status.conf
<LocationMatch "^/(status|ping)$">
    SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost/"
    Require local
</LocationMatch>

เปิด sudo vi /etc/datadog-agent/conf.d/php_fpm.d/conf.yaml แล้วใส่:

yaml · /etc/datadog-agent/conf.d/php_fpm.d/conf.yaml
init_config:

instances:
  - status_url: http://127.0.0.1/status
    ping_url: http://127.0.0.1/ping
    ping_reply: pong
    tags:
      - env:dev
      - service:customer-demo-php
bash · permissions, restart & verify
sudo chown dd-agent:dd-agent \
  /etc/datadog-agent/conf.d/apache.d/conf.yaml \
  /etc/datadog-agent/conf.d/php_fpm.d/conf.yaml
sudo chmod 640 \
  /etc/datadog-agent/conf.d/apache.d/conf.yaml \
  /etc/datadog-agent/conf.d/php_fpm.d/conf.yaml

sudo apachectl configtest
sudo php-fpm -t
sudo systemctl restart php-fpm httpd

curl -fsS 'http://127.0.0.1/server-status?auto' | head
curl -fsS http://127.0.0.1/status | head
curl -fsS http://127.0.0.1/ping; echo

sudo datadog-agent check apache
sudo datadog-agent check php_fpm
✓

ผ่านเมื่อ Apache และ PHP-FPM checks แสดง [OK] และ ping ตอบ pong

Observed output
Syntax OK
pool:                 www
process manager:      dynamic
listen queue:         0
pong

apache (7.5.0)
  Instance ID: ... [OK]
  Metric Samples: 25
  apache.can_connect: status 0

php_fpm (6.4.1)
  Instance ID: ... [OK]
  Metric Samples: 9
  php_fpm.can_ping: status 0
07
STEP 07

สร้าง traffic และยืนยัน trace

7 min
bash · generate 20 real requests
ok=0; fail=0
for i in $(seq 1 20); do
  if curl -fsS --max-time 10 http://127.0.0.1/index.php >/dev/null; then
    ok=$((ok+1))
  else
    fail=$((fail+1))
  fi
done
echo "Requests_OK=$ok Requests_Failed=$fail"
date -u '+Traffic completed at %H:%M:%S UTC'
อย่ารีบสรุปว่า trace หาย: ส่วน Receiver ใน datadog-agent status แสดง “previous minute” ให้รอจนเลขนาที UTC เปลี่ยนจากเวลาที่ traffic จบ แล้วค่อยรันคำสั่งตรวจด้านล่าง
bash · after UTC minute changes
date -u '+Checking at %H:%M:%S UTC'
sudo datadog-agent status | sed -n '/APM Agent/,/DogStatsD/p'
sudo datadog-agent health

จากนั้นไปที่ APM → Service หรือ APM → Traces ใน Datadog แล้ว filter ด้วย:

service:customer-demo-php AND env:dev
✓

ผ่านเมื่อ เห็น request traces, runtime fpm-fcgi และ Agent รายงาน traces/spans มากกว่า 0

Observed output · debug disabled
Requests_OK=20 Requests_Failed=0
APM Agent
  Status: Running
  Receiver: localhost:8126
  From php 8.0.30 (fpm-fcgi), client 1.25.1 via tcp
    Traces received: 20
    Spans received: 20
  Priority sampling rate for
    service:customer-demo-php,env:dev: 100.0%

Agent health: PASS
Datadog APM service: customer-demo-php
Operation: web.request
HEALTH: OK
05 · RECOVERY

Troubleshooting map

เริ่มจาก symptom แล้วไล่ตรวจจุดที่ใกล้ที่สุดก่อน

01Agent ทำงาน แต่ไม่มี trace+

ตรวจ endpoint ที่ tracer เห็น, restart PHP-FPM หลังติดตั้ง SSI และยิง request เข้า PHP จริง จากนั้นรอให้ Agent เปลี่ยน previous-minute window

sudo systemctl show -p Environment php-fpm
php-fpm -i | grep -iE 'ddtrace|datadog|dd_library_loader'
curl -fsS http://127.0.0.1/index.php
sudo datadog-agent status
02Apache check เชื่อมต่อไม่ได้+

ทดสอบ URL เดียวกับใน config และยืนยันว่า Require local อนุญาต localhost

curl -v 'http://127.0.0.1/server-status?auto'
sudo apachectl -M | grep status
sudo journalctl -u httpd -n 50 --no-pager
03PHP-FPM status ได้ 404 / 503+

ตรวจ socket จาก directive listen, module proxy_fcgi และ syntax ของทั้งสอง service

sudo grep -E '^listen|^pm.status_path|^ping.path' /etc/php-fpm.d/www.conf
sudo apachectl -M | grep proxy_fcgi
sudo ls -l /run/php-fpm/www.sock
04PHP-FPM timeout / AppSec sidecar crash บน SELinux+

อาการที่พบจริงคือ Apache AH01075, PHP-FPM worker SIGABRT และ AVC execute_no_trans บน dynamic linker ให้ย้อนตรวจ policy ที่ติดตั้งไว้ใน Step 02 โดยคง SELinux เป็น Enforcing และส่ง trace ผ่าน port type เฉพาะ 8126

getenforce
sudo ausearch -m AVC -ts recent | tail -30
sudo semodule -l | grep datadog_php_sidecar
sudo semanage port -l | grep datadog_apm_port_t
sudo systemctl restart php-fpm
curl -fsS http://127.0.0.1/index.php

SSI อาจยัง log AVC แบบ getattr ตอน probe Unix socket หรือ cgroup แม้ TCP trace ใช้งานได้ ให้พิจารณาผล request และ APM counters ร่วมกัน และอย่าอนุญาตทุก AVC ด้วย policy กว้างโดยไม่ review

05ต้องเก็บ log เพิ่มเพื่อส่ง Support+

สร้าง flare หลัง reproduce ปัญหา โดยตรวจข้อมูลลับก่อน upload ทุกครั้ง

sudo datadog-agent flare
sudo journalctl -u datadog-agent -n 100 --no-pager
sudo tail -100 /var/log/php-fpm/error.log
คัดลอกแล้ว