Introduction to Istio, Part 10
Service Entries for Registry-Only Outbound Traffic Policy
Khi một dịch vụ được tạo bên trong mesh, Istio sẽ tự động tạo một mục (entry) cho dịch vụ đó trong service registry. Đây là một phần của quá trình service discovery trong Istio.
Tuy nhiên, có những tình huống mà quá trình tự động phát hiện dịch vụ (automatic service discovery) không xảy ra hoặc không thể thực hiện, nhưng dịch vụ đó vẫn cần được Istio nhận biết và thêm vào service registry. Một số ví dụ bao gồm:
Legacy workloads (khối lượng công việc cũ).
Cụm cơ sở dữ liệu (database cluster) mà các dịch vụ trong mesh cần truy cập, nhưng bản thân cụm cơ sở dữ liệu không thuộc về mesh.
Để xử lý những trường hợp này, Istio cung cấp ServiceEntry, một loại tài nguyên tùy chỉnh (custom resource), cho phép chúng ta định nghĩa các dịch vụ này một cách rõ ràng.
Phân Biệt Dịch Vụ Bên Trong và Bên Ngoài Mesh
Istio phân biệt hai loại dịch vụ:
Dịch vụ bên trong mesh (mesh-internal services):
- Ví dụ: legacy workloads.
Dịch vụ bên ngoài mesh (mesh-external services):
- Ví dụ: API của bên thứ ba.
ServiceEntry và Các Chính Sách Traffic
Khi tạo một ServiceEntry cho một API bên thứ ba, chúng ta có thể:
Định nghĩa các chính sách điều hướng và lưu lượng (routing and traffic policies) thông qua Virtual Services và Destination Rules.
Ví dụ:
Retries (thử lại).
Timeouts (giới hạn thời gian).
Mirroring (nhân bản lưu lượng).
Fault injection (tiêm lỗi).
Chiến lược cân bằng tải.
Outlier detection (phát hiện lỗi).
Nếu API của bên thứ ba không ổn định, việc định nghĩa các chính sách như timeout và retry là cần thiết. Với Istio, chúng ta có thể làm điều này một cách tập trung mà không cần sửa đổi mã nguồn của bất kỳ workload nào gửi yêu cầu đến API đó.
Ví Dụ Cấu Hình ServiceEntry
Dưới đây là một ví dụ về ServiceEntry dành cho www.googleapis.com
, định nghĩa API của bên thứ ba này là MESH_EXTERNAL:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: googleapis-svc-entry
spec:
hosts:
- www.googleapis.com
location: MESH_EXTERNAL
resolution: DNS
ports:
- number: 443
name: https
protocol: TLS
location: MESH_EXTERNAL
:- Chỉ định rằng dịch vụ nằm ngoài mesh.
resolution: DNS
:- Cho biết cách xác định endpoint thật sự của dịch vụ, trong trường hợp này là sử dụng DNS resolution.
Lợi Ích
ServiceEntry giúp tích hợp các dịch vụ bên ngoài vào mesh mà không cần sửa đổi ứng dụng.
Định nghĩa chính sách tại một nơi duy nhất giúp quản lý dễ dàng và tập trung hơn.
Bây giờ hãy tưởng tượng một tình huống khác: bạn muốn kết nối với một cụm cơ sở dữ liệu nội bộ mesh (mesh-internal database cluster) và muốn chỉ định trực tiếp các địa chỉ IP của cụm đó. Trong trường hợp này, cấu hình ServiceEntry sẽ trông như sau:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: external-svc-mongocluster
spec:
hosts:
- mymongodb.somedomain # không được sử dụng
addresses:
- 192.192.192.192/24 # Các VIPs
ports:
- number: 27018
name: mongodb
protocol: MONGO
location: MESH_INTERNAL
resolution: STATIC
endpoints:
- address: 2.2.2.2
- address: 3.3.3.3
Giải Thích Cấu Hình
location: MESH_INTERNAL
- Chỉ định rằng đây là một dịch vụ nội bộ mesh.
resolution: STATIC
- Thay vì sử dụng DNS để phân giải (resolve) địa chỉ, cấu hình này chỉ định các địa chỉ IP tĩnh trong trường
endpoints
.
- Thay vì sử dụng DNS để phân giải (resolve) địa chỉ, cấu hình này chỉ định các địa chỉ IP tĩnh trong trường
endpoints
Danh sách các địa chỉ IP tĩnh được sử dụng làm điểm kết nối (endpoints) cho dịch vụ.
Trong ví dụ này, hai địa chỉ IP
2.2.2.2
và3.3.3.3
được cung cấp làm endpoints.
hosts
- Trường này không được sử dụng trong trường hợp
resolution
là STATIC.
- Trường này không được sử dụng trong trường hợp
addresses
- Trường này khai báo một dải địa chỉ IP (VIPs - Virtual IPs) đại diện cho dịch vụ.
Lựa Chọn Thay Thế: workloadSelector
Thay vì sử dụng trường endpoints
, bạn cũng có thể chọn workloadSelector
để tự động chọn endpoints dựa trên nhãn (labels) của workload. Điều này cho phép Istio tìm kiếm và kết nối các workload cụ thể mà không cần chỉ định IP tĩnh.
Ví dụ sử dụng workloadSelector
:
workloadSelector:
labels:
app: mongodb
version: v1
Khi Nào Sử Dụng Cách Tiếp Cận Này?
Cụm cơ sở dữ liệu nội bộ hoặc dịch vụ khác không đăng ký qua DNS.
Các dịch vụ cần sử dụng IP tĩnh để kết nối (ví dụ: cơ sở dữ liệu không hỗ trợ DNS).
Các tình huống mà cần kiểm soát thủ công các endpoint hoặc VIPs.
Sử dụng ServiceEntry như trên giúp bạn tích hợp các dịch vụ nội bộ mesh một cách chính xác, đặc biệt khi các dịch vụ không hỗ trợ DNS hoặc khi cần cấu hình IP tĩnh rõ ràng.
Cấu Hình Service Entries với Chính Sách Outbound Registry-Only
Việc bảo mật egress traffic (lưu lượng thoát ra ngoài) là một phần quan trọng trong việc bảo vệ một service mesh. Istio cho phép cấu hình chính sách outbound traffic để chỉ cho phép gọi đến các dịch vụ đã được đăng ký trong service registry. Điều này giúp kiểm soát và ngăn chặn các kết nối không mong muốn ra ngoài.
Registry-Only Outbound Traffic Policy
Khi cấu hình mesh ở chế độ này, bạn phải tạo một tài nguyên ServiceEntry cho từng dịch vụ bên ngoài (mesh-external service) mà bạn muốn cho phép truy cập. Nếu không, mọi kết nối outbound đến các dịch vụ bên ngoài sẽ bị chặn.
Thực Hành: Cấu Hình Outbound Traffic Policy
Chuyển sang chế độ "registry-only" Bước đầu tiên là cấu hình mesh để sử dụng chế độ registry-only outbound traffic policy. Sau đó, kiểm tra và xác nhận rằng một dịch vụ chạy bên trong mesh không thể gọi đến bất kỳ dịch vụ bên ngoài nào, chẳng hạn như
github.com
.Yêu cầu trước:
Cụm Kubernetes đã chạy sẵn.
Istio được cài đặt và cấu hình với profile demo.
Chạy lệnh sau để kích hoạt chế độ "registry-only":
istioctl install --set profile=demo \
--set meshConfig.outboundTrafficPolicy.mode=REGISTRY_ONLY
Lưu ý: Công cụ Istio CLI đủ thông minh để nhận ra rằng Istio đã được cài đặt sẵn. Khi chạy lệnh này, cấu hình của cài đặt hiện tại sẽ được cập nhật mà không cần cài lại toàn bộ.
Kết Quả:
- Sau khi thực hiện cấu hình, bất kỳ dịch vụ nào bên trong mesh sẽ không còn khả năng gọi đến các dịch vụ bên ngoài, trừ khi bạn khai báo chúng trong một ServiceEntry.
Kiểm Tra Cấu Hình Istio
Sau khi cập nhật cấu hình outbound traffic policy sang chế độ REGISTRY_ONLY
, bạn cần xác minh giá trị cấu hình mới này.
Xem cấu hình ConfigMap của Istio: Chạy lệnh sau để hiển thị giá trị ConfigMap trong namespace
istio-system
:kubectl get cm -n istio-system istio -o yaml
Xác minh giá trị của
outboundTrafficPolicy.mode
: Kiểm tra trong đầu ra rằng trườngoutboundTrafficPolicy.mode
đã được đặt thànhREGISTRY_ONLY
.
Thực Hiện Kết Nối Từ Trong Mesh
Triển khai ứng dụng mẫu
sleep
: Ứng dụngsleep
của Istio sẽ đóng vai trò là dịch vụ chạy bên trong mesh để kiểm tra kết nối outbound.Điều hướng đến thư mục chứa bộ cài Istio:
cd <path_to_istio_distribution>
Triển khai workload
sleep
:kubectl apply -f samples/sleep/sleep.yaml
Lấy tên pod của ứng dụng
sleep
: Chạy lệnh sau để lấy tên của podsleep
đang chạy:SLEEP_POD=$(kubectl get pod -l app=sleep -ojsonpath='{.items[0].metadata.name}')
Thử thực hiện kết nối outbound tới
github.com
:Chạy lệnh sau để gửi yêu cầu HTTP từ pod
sleep
đếngithub.com
:kubectl exec $SLEEP_POD -it -- curl -v https://github.com
Xác nhận rằng yêu cầu không thành công với thông báo lỗi tương tự:
* Trying 140.82.114.4:443... * Connected to github.com (140.82.114.4) port 443 (#0) * ALPN: offers h2 * ALPN: offers http/1.1 * CAfile: /cacert.pem * CApath: none * TLSv1.3 (OUT), TLS handshake, Client hello (1): * OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443 * Closing connection 0 curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443 command terminated with exit code 35
Kết Quả:
Kết nối outbound từ dịch vụ bên trong mesh đến github.com
đã bị chặn thành công, thể hiện chính sách REGISTRY_ONLY
hoạt động đúng cách. Ở bước tiếp theo, bạn sẽ cần tạo một ServiceEntry để cấp quyền truy cập tới github.com
.
Định Nghĩa ServiceEntry
Để cấp quyền truy cập đến dịch vụ bên ngoài mesh, chúng ta sẽ định nghĩa một ServiceEntry như sau:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: github-external
spec:
hosts:
- github.com
ports:
- number: 443
name: https
protocol: HTTPS
resolution: DNS
location: MESH_EXTERNAL
location: Được đặt là
MESH_EXTERNAL
, xác định rằng đây là một dịch vụ bên ngoài mesh.hosts: Xác định hostname mà bạn muốn truy cập, ở đây là
github.com
.ports: Định nghĩa cổng và giao thức (
443
,HTTPS
) cho dịch vụ.
Triển khai ServiceEntry
Lưu tài nguyên trên vào tệp
service-entry.yaml
.Áp dụng cấu hình ServiceEntry vào cluster:
kubectl apply -f service-entry.yaml
Kiểm Tra Kết Nối
Sau khi ServiceEntry được tạo, thử lại kết nối từ pod sleep
đến github.com
:
kubectl exec $SLEEP_POD -it -- curl -v https://github.com
- Kết quả mong đợi: Lần này, yêu cầu thành công và trả về nội dung HTML từ
github.com
.
Cấu Hình Nâng Cao Với Egress Gateway
Việc định nghĩa ServiceEntry chỉ là bước đầu trong việc cấu hình dịch vụ bên ngoài. Để tăng cường kiểm soát, Istio hỗ trợ triển khai thành phần Egress Gateway:
Egress Gateway giúp định tuyến tất cả lưu lượng outbound qua gateway thay vì cho phép truy cập trực tiếp.
Kết hợp với các tài nguyên như Gateway, VirtualService, và DestinationRule, bạn có thể cấu hình chi tiết các chính sách định tuyến, retries, hay timeouts cho lưu lượng outbound.
Tích Hợp AuthorizationPolicy
Nhờ vào khả năng xác định danh tính của workload trong Istio, bạn có thể kết hợp AuthorizationPolicy để kiểm soát chi tiết:
Ai (dịch vụ nội mesh) được phép truy cập
Dịch vụ nào (dịch vụ ngoài mesh).
Ví dụ: Chỉ cho phép web-frontend
gọi đến github.com
trong khi từ chối các dịch vụ khác. Điều này giúp đảm bảo bảo mật và tuân thủ chính sách truy cập.