ลองเล่น Stackdriver Trace บน Django

หลังจาก implement AWS X-Ray ให้ที่บริษัทไป ผมก็เลยว่าอยากจะ implement ระบบคล้ายๆ กันให้ TipMe บ้าง แต่ TipMe อยู่บน Google Cloud ก็เลยจะต้องใช้บริการของเค้าคือ Stackdriver Trace

(Note: ถ้ายังไม่ได้อ่านตอนของ X-Ray แนะนำให้อ่านก่อนเพื่อเข้าใจ concept ของ Tracing ครับ)

Zipkin

สำหรับการใช้งาน Stackdriver Trace นั้นจะแตกต่างกับของ X-Ray ตรงที่ Trace มี API ให้เราเลือกใช้ถึง 3 แบบ คือ

  1. REST API ซึ่งจะเป็น API เฉพาะของ Trace เอง เช่นเดียวกับของ X-Ray
  2. gRPC API เป็น custom API เช่นกัน แต่ตอนนี้ยังไม่มี client library ให้ใช้
  3. Zipkin API ซึ่ง Zipkin เป็นโปรแกรมสำหรับทำ tracing แบบ open source แล้ว Google Cloud นำมาแก้ให้ใช้ gRPC API ของเค้าเป็น backend อีกทีหนึ่ง (จะเรียกว่าเป็น adapter ก็ได้)

เพื่อไม่ให้ vendor lock in เราก็จะเลือกใช้ Zipkin API ฉะนั้นอย่างแรกที่จะต้องทำคือติดตั้ง Zipkin Collector ของเค้าก่อน สำหรับบน Kubernetes ก็ใช้ Deployment ประมาณนี้

apiVersion: v1
kind: ReplicationController
metadata:
  name: zipkin
spec:
  replicas: 1
  selector:
    app: zipkin
  template:
    metadata:
      labels:
        app: zipkin
    spec:
      containers:
      - name: zipkin
        image: gcr.io/stackdriver-trace-docker/zipkin-collector
        ports:
        - containerPort: 9411
        env:
        - name: GOOGLE_APPLICATION_CREDENTIALS
          value: /secrets/service-account
        livenessProbe:
          httpGet:
            path: /health
            port: 9411
          initialDelaySeconds: 120
        readinessProbe:
          httpGet:
            path: /health
            port: 9411
        resources:
          requests:
            memory: "0Mi"
            cpu: "3m"
          limits:
            memory: "256Mi"
        volumeMounts:
        - name: secret
          mountPath: /secrets
          readOnly: true
      volumes:
      - name: secret
        secret:
          secretName: zipkin
---
apiVersion: v1
kind: Service
metadata:
  name: zipkin
  labels:
    app: zipkin
spec:
  selector:
    app: zipkin
  ports:
    - port: 9411
---
apiVersion: v1
kind: Secret
metadata:
  name: zipkin
type: Opaque
data:
  service-account: แปะ service account เป็น base64

เนื่องจากบน Kubernetes เราจะใช้ instance role ไม่ได้ (เพราะไม่ได้เซตสิทธิ์ไว้ตอนเปิด cluster) ก็เลยจะต้องใช้ Service account แทน วิธีการสร้าง Service account ก็คือ

  1. เข้าไปที่ Service Accounts
  2. กด Create service account ด้านบน
  3. กรอก Service account name ตามชอบ และเลือก Role เป็น Cloud Trace > Cloud Trace Agent
  4. ติ๊ก Furnish a new private key และเลือก JSON
  5. กด Create
  6. เมื่อได้ JSON มา ให้เอาไปเข้ารหัส Base64 แล้วแปะใน Secret ด้านบน (cat file.json | base64 -w0)

พอเสร็จแล้วก็ kubectl apply -f zipkin.yaml เป็นอันเรียบร้อย

Integrate กับ Django

ถัดมาเราจะต้องติดตั้ง Tracer ลงในโปรแกรมของเรา ซึ่งถ้าเป็น Node.js แบบที่วงในก็คงจะง่าย แต่พอเป็น Python แล้วก็พบว่าเราคงจะต้องทำเอง -_-!! ซึ่งของที่ผมออกแรงนั่งทำมาก็ปล่อยเป็น open source แล้วครับ ฟีเจอร์หลักๆ ก็คือ

  • Trace request ได้
  • Trace request ออกไปทาง urllib3 (request module) ได้ รวมทั้งจะแปะ X-B3-TraceId ส่งไปให้ด้วย
  • Trace template render time ได้
  • Trace database query ได้ (แต่จะไม่ log parameter ของ query เพื่อความปลอดภัย)

วิธีการติดตั้งก็คือ

  1. เพิ่ม django-zipkin-trace==1.0.0 ลงใน requirements.txt
  2. pip install -r requirements.txt
  3. แก้ไข settings.py ของเราในส่วนของ MIDDLEWARES เติม zipkin_trace.ZipkinMiddleware ไปเป็นอันบนสุด
  4. เพิ่ม ZIPKIN_SERVER='http://zipkin:9411' ลงใน settings.py

ถ้าอยากลองเทส ก็สามารถเทสบนเครื่องได้โดยใช้ Zipkin ของแท้ ดังนี้

  1. Start Zipkin ด้วยคำสั่ง sudo docker run -d -p 9411:9411 openzipkin/zipkin
  2. เช็คว่าสามารถเข้า Zipkin ได้ที่ http://localhost:9411 (ใครใช้ Docker for Mac/Windows อาจจะต้องเข้า IP ของ VM แทน)
  3. แก้ไข ZIPKIN_SERVERS ใน settings.py ให้ชี้ไปที่ http://localhost:9411 แทน
  4. ลองเข้าเว็บ Django ของเราแล้วรีเฟรชสองสามที
  5. ใน Zipkin กด Find Traces น่าจะปรากฏ Trace ขึ้นมา

(Note: py-zipkin จะสะสม trace ให้ครบ 100 อันก่อนส่ง ต้องเปิด DEBUG=true ถึงจะส่ง trace ทันที)

Trace ที่ได้จะหน้าตาประมาณนี้

สำหรับถ้าจะใช้บน Google Cloud Trace จะหน้าตาแบบนี้

เปรียบเทียบกับ X-Ray

จากที่ใช้งานมาทั้ง 2 platform แล้ว ผมพบว่าสิ่งที่ X-Ray จะนำเสนอคือความสัมพันธ์ระหว่าง service และ error ระหว่างทำงานมากกว่า เพราะมุมมองการดู Trace นั้นสามารถใช้งานได้สะดวกมาก และมีแผนภาพระหว่าง service ด้วย

สำหรับทางฝั่ง Stackdriver Trace นั้น จุดขายคือ Auto analysis ครับ

พอเราใช้ไปสักสัปดาห์นึงแล้ว URL ไหนที่ hit บ่อยที่สุด top 3 จะถูกนำมาเทียบกับสัปดาห์ที่แล้วโดยอัตโนมัติ เพื่อให้เราเห็นว่าที่เราทำไปในสัปดาห์นี้นั้นทำให้เว็บเร็วขึ้นหรือช้าลงหรือเปล่า และสามารถกดดูตัวอย่าง Trace ใน percentile ต่างๆ ได้ด้วย (ถ้าใช้ X-Ray จะต้องไปลากในกราฟเอาเอง)

โดยส่วนตัวผมชอบแบบ X-Ray มากกว่า เพราะอยากรู้เรื่อง error เป็นหลักมากกว่าซึ่งใน Trace มันดูไม่ได้ (เข้าใจว่าน่าจะให้ไปใช้ Stackdriver Error Reporting แทน แต่ผมใช้ Sentry อยู่แล้ว)

สุดท้าย Stackdriver Trace ฟรี 100% ครับ ไม่มีข้อจำกัดใดๆ ทั้งสิ้น ฉะนั้นที่ TipMe ตอนนี้ก็จะยิงทุก request เข้าหมดทุกอันได้เลย