Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 2 — Thiết lập môi trường: tool, quyền và guardrail

Đã đọc 0/10 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Một agent chỉ mạnh bằng bộ công cụ (tools) nó được cấp và guardrail bao quanh. Bài này thiết lập nền tảng an toàn trước khi viết logic.

Nguyên tắc least privilege

Agent DevOps chạm vào production, nên phải theo nguyên tắc least privilege: cấp đúng quyền tối thiểu cần thiết, không hơn. Đừng bao giờ đưa cho agent một service account cluster-admin.

Các bước thiết lập

  • Tạo service account riêng cho agent, không dùng chung với người.
  • Cấp RBAC hẹp — ví dụ chỉ được restart pod và đọc log ở namespace production:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: agent-oncall
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "delete"]   # delete pod = restart
  - apiGroups: ["apps"]
    resources: ["deployments"]
    verbs: ["get", "list"]              # đọc, KHÔNG cấp update ở đây
  • Bọc mỗi tool bằng validation layer. Agent không gọi thẳng CLI; nó gọi hàm có kiểm tra tham số:
ALLOWED_NAMESPACES = {"production", "staging"}

def restart_pod(namespace: str, pod: str) -> dict:
    if namespace not in ALLOWED_NAMESPACES:
        raise ValueError(f"Namespace {namespace} không được phép")
    if pod.startswith("db-") or "postgres" in pod:
        raise PermissionError("Cấm restart pod database qua agent")
    return run(["kubectl", "delete", "pod", pod, "-n", namespace])
  • Thiết lập dry-run mặc định. Mọi tool có tham số dry_run=True khi test. Chỉ bật thật khi đã kiểm chứng.
  • Quản lý secret đúng cách. API token (GitHub, PagerDuty) nạp từ vault/secret manager, không hardcode, không đưa vào prompt của LLM.

Guardrail 3 lớp

  • Lớp policy (khai báo): danh sách forbidden, require_approval như Bài 1.
  • Lớp code (validation): hàm tool tự từ chối tham số nguy hiểm (như ví dụ trên).
  • Lớp hạ tầng (RBAC/IAM): dù agent có "muốn" làm bậy, quyền hệ thống cũng chặn.
Ba lớp độc lập — nếu một lớp thủng, lớp khác vẫn giữ. Đây là defense in depth.

Checklist thiết lập trước khi cho agent chạm production

  • [ ] Service account riêng, RBAC least-privilege đã tạo
  • [ ] Mỗi tool có validation layer từ chối input nguy hiểm
  • [ ] Danh sách forbidden được enforce ở cả code lẫn RBAC
  • [ ] Secret nạp từ vault, không log ra, không vào prompt
  • [ ] Chế độ dry-run hoạt động và được test
  • [ ] Rate limit: agent không gọi tool quá N lần/phút (chống loop)
  • [ ] Mọi tool-call ghi audit log (ai/cái gì/khi nào/kết quả)

Ví dụ: chống vòng lặp vô hạn

Agent có thể kẹt trong loop: restart pod → pod vẫn lỗi → restart tiếp. Đặt circuit breaker:

from collections import defaultdict
import time

_calls = defaultdict(list)

def rate_limited(tool_name, max_calls=3, window=300):
    now = time.time()
    _calls[tool_name] = [t for t in _calls[tool_name] if now - t < window]
    if len(_calls[tool_name]) >= max_calls:
        raise RuntimeError(f"{tool_name} vượt {max_calls} lần/{window}s — dừng, báo người")
    _calls[tool_name].append(now)

Sai lầm thường gặp

  • Cấp quyền rộng "cho tiện". Least privilege phải là mặc định, mở rộng theo nhu cầu thật.
  • Đưa secret vào prompt LLM. Prompt có thể bị log hoặc rò rỉ; secret phải nằm ngoài context của model.
  • Không có rate limit. Agent loop có thể restart toàn bộ cluster trong vài phút.
  • Bỏ qua dry-run. Test logic agent trực tiếp trên production là công thức gây incident.
  • Chỉ tin vào prompt để chặn hành vi. Prompt không phải cơ chế bảo mật; guardrail phải nằm ở code và hạ tầng.

Ví dụ audit log nên trông như thế nào

Mỗi hành động agent phải để lại dấu vết đầy đủ để điều tra khi có sự cố. Một bản ghi tốt gồm: ai (agent nào), làm gì (tool + tham số), khi nào, vì sao (lý do quyết định), và kết quả:

{
  "ts": "2026-07-10T02:14:33Z",
  "agent": "oncall-agent",
  "tool": "restart_pod",
  "args": {"namespace": "production", "pod": "checkout-7f9"},
  "reason": "pod CrashLoopBackOff, log cho thấy OOM",
  "result": "success",
  "triggered_by": "alert:PodCrashLoop"
}

Khi có incident do agent gây ra, audit log này là thứ đầu tiên bạn mở. Không có nó, bạn mù hoàn toàn về việc agent đã làm gì.

Tại sao guardrail phải ở code, không chỉ ở prompt

Một sai lầm nguy hiểm là tin rằng "dặn agent trong prompt đừng xóa database" là đủ. Prompt có thể bị bỏ qua khi model hiểu sai ngữ cảnh, bị prompt-injection từ nội dung log độc hại, hoặc đơn giản là model "quên" trong hội thoại dài. Guardrail thật phải là cơ chế kỹ thuật không thể vượt qua: hàm tool từ chối tham số nguy hiểm, và RBAC chặn ở tầng hạ tầng. Prompt chỉ là gợi ý; code và IAM mới là hàng rào.

Tóm tắt

Trước khi agent thông minh, nó phải an toàn. Thiết lập least-privilege RBAC, validation layer cho từng tool, guardrail 3 lớp, rate limit và audit log. Đây là móng nhà — làm chắc thì mọi bài sau mới yên tâm. Ghi nhớ: prompt không phải bảo mật, guardrail phải sống trong code và hạ tầng.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi