FDE PulseViệc làm FDE đang mở 314Mới đăng 7 ngày qua 10Chủ đề nổi bật: Đào tạo kỹ năng FDE tại Đông Nam Á

Tờ báo của nghề Forward Deployed Engineer

Bách khoa

Thêm xác thực và log khi không được sửa code của khách

Ứng dụng cũ của khách không ai dám sửa vẫn có thể có thêm bảo mật và log, miễn là bạn biết đặt proxy ở đâu và không giao cho nó việc của ứng dụng.

Ảnh phòng máy chủ với tủ rack và dây mạng, hoặc kỹ sư đang xem code trên màn hình trong văn phòng doanh nghiệp.
Ảnh: Raysonho @ Open Grid Scheduler / Grid Engine / CC BY 3.0
Sơ đồ đường đi của request. Bên trái, trong host của client, app cũ gọi ra ngoài qua ambassador (lo TLS, timeout, log). Ở giữa, gateway màu cam là cửa vào chung, lo xác thực, log JSON, định tuyến L7 và TLS termination. Gateway chuyển request tới app đơn hàng và dịch vụ báo cáo. Mỗi dịch vụ có một sidecar chạy cạnh, và hai sidecar nối với nhau bằng mTLS. Một đường nét đứt có dấu X cho thấy phải khóa đường đi thẳng vào backend. Bên dưới là câu chốt: proxy lo chuyện đường ống, logic nghiệp vụ phải ở lại trong ứng dụng.
Ambassador lo traffic đi ra, gateway là cửa vào chung, còn sidecar lo traffic vào và ra của từng instance. Phải khóa đường đi thẳng vào backend, và không đẩy business logic lên proxy.

Tóm tắt nhanh

  • Gateway đứng trước dịch vụ và gánh xác thực, TLS, log, throttling; sidecar chạy cạnh từng instance; ambassador chạy cạnh client để lo các cuộc gọi đi ra ngoài.
  • Gateway chỉ có tác dụng khi backend từ chối mọi request không đi qua nó, và tuyệt đối không được chứa business logic.
  • Ambassador chỉ nên retry những thao tác idempotent; còn gateway phải được thiết kế và load test để không thành điểm lỗi đơn.
Chia sẻLinkedInFacebookX

Thử hình dung sáng thứ Hai, bạn đến văn phòng khách hàng. Hệ thống quản lý đơn hàng của họ là một ứng dụng Java viết từ nhiều năm trước, người viết đã nghỉ việc, không có test và không ai dám deploy lại.

Yêu cầu bạn nhận được là tuần sau phải có xác thực cho API, có log để bộ phận an ninh đọc, và chuyển một phần traffic sang dịch vụ báo cáo mới.

Phản xạ đầu tiên của nhiều kỹ sư là mở code ra sửa. Với một FDE, đó thường là lựa chọn tệ nhất, vì code không thuộc về bạn, rủi ro hồi quy nằm hết ở phía khách, và khó có ai ký duyệt một bản build mới trong một tuần.

Kỹ năng cần có ở đây là thêm năng lực cho hệ thống từ bên ngoài, bằng một proxy đặt đúng vị trí.

Tài liệu kiến trúc của Microsoft Azure gom việc này thành mấy pattern có tên rõ ràng: gateway, sidecar, ambassador, và một biến thể chuyên về bảo mật là gatekeeper. Nắm được chúng, lần tới gặp yêu cầu “không được sửa code nhưng phải có thêm tính năng”, bạn sẽ biết ngay nên đặt proxy ở đâu.

Proxy đặt ở đâu thì gánh được việc gì?

Hãy hình dung đường đi của một request. Nó xuất phát từ client, đi qua mạng, tới dịch vụ. Ba pattern trên khác nhau ở chỗ proxy đứng tại điểm nào trên đường đi đó.

Gateway đứng trước một nhóm dịch vụ. Theo mô tả của pattern Gateway Routing, gateway định tuyến ở Layer 7 nên client chỉ cần biết một endpoint duy nhất. Bạn có thể thêm, tách hay sắp xếp lại dịch vụ phía sau mà không phải sửa client. Pattern Gateway Offloading đi thêm một bước: gateway nhận luôn các việc xuyên suốt như quản lý chứng chỉ, xác thực, TLS termination, giám sát, chuyển đổi giao thức và throttling thay cho backend.

Sidecar là một tiến trình hoặc container chạy cạnh ứng dụng. Mỗi instance có một sidecar riêng và hai bên chung vòng đời. Vì chạy riêng nên sidecar không phụ thuộc ngôn ngữ của ứng dụng. Service mesh như Istio dùng sidecar proxy để làm mTLS, retry và telemetry mà không cần sửa code ứng dụng.

Ambassador cũng là proxy ngoài tiến trình, nhưng đặt cùng host với phía gọi đi. Nó lo monitoring, logging, routing, TLS và resiliency cho các cuộc gọi ra ngoài. Microsoft gợi ý dùng pattern này để mở rộng năng lực mạng cho ứng dụng legacy hoặc ứng dụng khó sửa.

Gateway Sidecar Ambassador
Vị trí Trước một nhóm dịch vụ Cạnh từng instance dịch vụ Cạnh client, trên cùng host
Hướng traffic chính Đi vào Vào và ra của một instance Đi ra
Phù hợp nhất khi Cần một cửa vào chung có xác thực và log Cần mTLS, telemetry giữa các dịch vụ App cũ gọi API bên ngoài mà không có TLS, retry, log
Cái giá Có thể thành điểm lỗi đơn và nút thắt Thêm độ trễ và tài nguyên cho mỗi instance Thêm độ trễ, retry dễ gây hậu quả

Ví dụ: dựng gateway trước ứng dụng đơn hàng

Quay lại khách hàng giả định ở trên. Giả sử ứng dụng đơn hàng nghe ở cổng 8080, dịch vụ báo cáo mới ở cổng 9000, và nhóm IT của khách đã có sẵn một dịch vụ kiểm tra token. Một cấu hình nginx tối giản làm gateway có thể như sau:

log_format json escape=json
  '{"time":"$time_iso8601","method":"$request_method",'
  '"uri":"$request_uri","status":$status,'
  '"rt":$request_time,"user":"$auth_user"}';

server {
  listen 443 ssl;
  ssl_certificate     /etc/nginx/certs/api.crt;
  ssl_certificate_key /etc/nginx/certs/api.key;
  access_log /var/log/nginx/api.json json;

  location = /_auth {
    internal;
    proxy_pass http://auth-svc/verify;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
  }

  location /api/orders/ {
    auth_request /_auth;
    auth_request_set $auth_user $upstream_http_x_user;
    proxy_pass http://legacy-orders:8080;
  }

  location /api/reports/ {
    auth_request /_auth;
    auth_request_set $auth_user $upstream_http_x_user;
    proxy_pass http://reports-v2:9000;
  }
}

Hãy đọc file này theo ba yêu cầu của khách. Xác thực nằm ở auth_request: mọi request phải qua /_auth trước, và ứng dụng Java không biết gì về chuyện đó. Log nằm ở log_format json: mỗi request ghi ra một dòng JSON có thời gian, mã trạng thái, độ trễ và người gọi, để đội an ninh đọc thẳng vào hệ thống của họ.

Định tuyến nằm ở hai khối location. Client chỉ biết một tên miền, còn /api/reports/ lặng lẽ đi sang dịch vụ mới. Nếu bản mới có lỗi, rollback chỉ là sửa một dòng proxy_pass rồi reload gateway. Đúng như pattern Gateway Offloading mô tả, kể cả khi dịch vụ phía sau chưa được instrument đúng cách, gateway vẫn cho bạn một mức giám sát và log nền.

Việc nhất định phải làm sau khi cấu hình chạy

Cấu hình trên vẫn chưa an toàn nếu ứng dụng đơn hàng còn mở cổng 8080 ra mạng nội bộ. Ai biết địa chỉ đó sẽ gọi thẳng vào, bỏ qua xác thực và không để lại dòng log nào.

Hướng dẫn của Microsoft nói rõ backend chỉ nên nhận request đi qua đúng đường gateway. Trong thực tế, bạn có thể làm việc này bằng firewall, security group hoặc network policy, chỉ cho phép IP của gateway gọi vào.

Pattern Gatekeeper còn đi xa hơn. Lớp trung gian lo kiểm tra và làm sạch request chạy với đặc quyền hạn chế, còn phần ứng dụng giữ quyền truy cập storage và dịch vụ. Áp vào ví dụ: gateway không nên giữ mật khẩu database hay khóa của backend, để nếu gateway bị chiếm thì thiệt hại được giới hạn.

Thứ tự triển khai tại chỗ khách nên như sau. Đầu tiên chạy gateway song song và chỉ ghi log, chưa bật xác thực, để xem traffic thật trông thế nào. Sau đó bật xác thực cho từng route, tiếp theo khóa đường đi thẳng vào backend, và cuối cùng mới chuyển dần traffic sang dịch vụ mới.

Sidecar và ambassador: khi gateway không với tới

Gateway chỉ quản được traffic đi qua cửa chính. Khi các dịch vụ trong cluster gọi nhau, hoặc khi ứng dụng cũ gọi ra API của đối tác, bạn cần proxy ở gần hơn.

Giả sử khách chạy trên Kubernetes và muốn mã hóa traffic giữa các dịch vụ. Một sidecar proxy trong mỗi pod, chẳng hạn qua Istio, làm được mTLS và thu telemetry mà ứng dụng không cần biết.

Tài liệu của Istio mô tả service mesh mang lại bảo mật zero-trust, khả năng quan sát và quản lý traffic nâng cao, với hai chế độ là ambient hoặc sidecar truyền thống.

Còn nếu ứng dụng đơn hàng gọi API thanh toán qua HTTP trần, không có timeout và không log, hãy đặt một ambassador trên cùng host. Ứng dụng gọi localhost, ambassador lo TLS, ghi log từng cuộc gọi đi và áp timeout. Code cũ vẫn giữ nguyên.

Bốn cái bẫy thường gặp

Bẫy đầu tiên là để backend mở như đã nói ở trên. Bẫy thứ hai nguy hiểm hơn vì nó đến từ thiện chí: khách nhờ “tiện thì kiểm tra hạn mức tín dụng ở gateway luôn”. Hướng dẫn của Microsoft nói thẳng là không bao giờ được đẩy business logic lên gateway.

Cám dỗ tương tự xuất hiện với Gateway Aggregation, tức gateway gọi nhiều backend rồi gộp kết quả để client đỡ phải gọi nhiều lần. Nếu logic gộp bắt đầu phức tạp, hãy tách nó thành một dịch vụ aggregation riêng đặt sau gateway.

Bẫy thứ ba là bật retry trong ambassador cho mọi thứ. Microsoft lưu ý retry trong ambassador có thể không an toàn nếu các thao tác không idempotent.

Thử hình dung lệnh tạo thanh toán bị timeout ở phía trả lời nhưng thực ra đã thành công: proxy gửi lại, và khách hàng của khách bị trừ tiền hai lần.

Chỉ retry những thao tác như GET, hoặc các lệnh ghi có idempotency key.

Bẫy thứ tư là quên rằng mọi request giờ đều đi qua gateway. Gateway có thể thành điểm lỗi đơn và nút thắt cổ chai, nên phải load test trước khi đưa vào production và thiết kế theo yêu cầu sẵn sàng của khách, chẳng hạn chạy nhiều bản.

Sidecar cũng có cái giá riêng: thêm độ trễ, phí tài nguyên với ứng dụng nhỏ, và có thể không cần nếu mesh của khách đã có data plane không dùng sidecar.

Bạn chọn được proxy nào cho ba tình huống này?

Hãy tự trả lời trước khi đọc đáp án. Tình huống A: một ứng dụng báo cáo cũ gọi API của nhà cung cấp qua HTTP trần, khách muốn có TLS và log cho từng cuộc gọi đi. Tình huống B: đối tác bên ngoài cần một endpoint duy nhất, có xác thực, để gọi vào ba dịch vụ nội bộ.

Tình huống C: các dịch vụ trên Kubernetes gọi nhau, đội an ninh yêu cầu mã hóa và thu telemetry cho traffic giữa chúng mà không sửa code.

Đáp án: A là ambassador, vì vấn đề nằm ở traffic đi ra từ phía client. B là gateway, vì cần một cửa vào chung lo xác thực và định tuyến.

C là sidecar proxy trong service mesh, hoặc chế độ ambient nếu mesh của khách hỗ trợ và đáp ứng yêu cầu. Nếu bạn trả lời đúng cả ba, bạn đã nắm được câu hỏi cốt lõi: request đi theo hướng nào, và proxy đứng ở đâu trên đường đi đó.

Thể hiện kỹ năng này trong hồ sơ thế nào?

Khi đọc JD vị trí FDE hoặc solutions engineer, hãy để ý các cụm như “integrate with legacy systems”, “API gateway”, “service mesh”, “observability”.

Trong CV, đừng chỉ ghi “biết nginx, Istio”. Hãy viết theo kết quả, chẳng hạn: thêm xác thực và log có cấu trúc cho hệ thống legacy thông qua gateway, không sửa dòng code nào, khóa đường truy cập trực tiếp vào backend. Câu đó cho người phỏng vấn thấy bạn hiểu cả kỹ thuật lẫn ràng buộc của khách.

Lần tới khi ai đó bảo “hệ thống này không ai dám sửa”, bạn đừng coi đó là ngõ cụt. Thường đó là lúc nên hỏi xem request đi qua những đâu, và nên đặt proxy ở điểm nào.

7 nguồn
Đọc tiếp trên lộ trình · Chặng 5: Triển khaiAnti-corruption layer và strangler fig: cách gắn AI vào hệ thống cũ của khách hàng mà không làm hỏng nóHệ thống cũ của khách không cần được viết lại từ đầu. Lớp AI mới cũng không nên học theo những quy ước lộn xộn của nó.