Istio + 無代理模式
無代理模式指的是 Dubbo 直接與 Istiod 通訊,透過 xDS 協議實現服務發現和服務治理能力。在本範例中,將使用一個簡單的例子來演示如何使用無代理模式。
程式碼結構
本節主要介紹本文範例使用的程式碼結構。透過模仿此範例中的相關配置,並修改現有專案程式碼,即可讓現有專案快速以無代理 Mesh 模式運行。
1. 介面定義
為了使範例足夠簡單,這裡使用一個簡單的介面定義,僅將參數拼接後返回。
public interface GreetingService {
String sayHello(String name);
}
2. 介面實作
@DubboService(version = "1.0.0")
public class AnnotatedGreetingService implements GreetingService {
@Override
public String sayHello(String name) {
System.out.println("greeting service received: " + name);
return "hello, " + name + "! from host: " + NetUtils. getLocalHost();
}
}
3. 客戶端訂閱方法
**由於原生 xDS 協議無法支援介面到應用程式名稱的映射,因此需要配置 providedBy
參數來標記此服務來自哪個應用程式。**
未來,我們將基於 Dubbo Mesh 的控制平面實現自動服務映射關係的獲取,屆時將不再需要獨立的配置參數。Dubbo 可以在 Mesh 系統下運行,敬請期待。
@Component("annotated Consumer")
public class GreetingServiceConsumer {
@DubboReference(version = "1.0.0", providedBy = "dubbo-samples-xds-provider")
private GreetingService greetingService;
public String doSayHello(String name) {
return greetingService.sayHello(name);
}
}
4. 伺服器配置
伺服器配置的註冊中心是 istio 的地址,協議為 xds。
我們建議在 istio 系統中配置 protocol
為 tri 協議(完全相容 grpc 協議)以獲得更好的體驗。
為了讓 Kubernetes 感知到應用程式的狀態,需要配置 qosAcceptForeignIp
參數,以便 Kubernetes 能夠取得正確的應用程式狀態,[對齊生命週期](/en/docs3-v2/java-sdk/advanced-features-and-usage/others/dubbo-kubernetes-probe/)。
dubbo.application.name=dubbo-samples-xds-provider
dubbo.application.metadataServicePort=20885
dubbo.registry.address=xds://istiod.istio-system.svc:15012
dubbo.protocol.name=tri
dubbo.protocol.port=50052
dubbo.application.qosAcceptForeignIp=true
5. 客戶端配置
客戶端配置的註冊中心是 istio 的地址,協議為 xds。
dubbo.application.name=dubbo-samples-xds-consumer
dubbo.application.metadataServicePort=20885
dubbo.registry.address=xds://istiod.istio-system.svc:15012
dubbo.application.qosAcceptForeignIp=true
快速開始
步驟一:建置 Kubernetes 環境
目前 Dubbo 僅支援在 Kubernetes 環境中進行 Mesh 部署,因此在運行和啟動此範例之前,您需要先建置 Kubernetes 環境。
建置參考文件
minikube(https://kubernetes.dev.org.tw/zh-cn/docs/tutorials/hello-minikube/)
kubeadm(https://kubernetes.dev.org.tw/zh-cn/docs/setup/production-environment/tools/)
步驟二:建置 Istio 環境
建置 Istio 環境參考文件
Istio 安裝文件 (https://istio.dev.org.tw/latest/docs/setup/getting-started/)
注意:安裝 Istio 時,您需要啟用[第一方 JWT 支援](https://istio.dev.org.tw/latest/docs/ops/best-practices/security/#configure-third-party-service-account-tokens)(使用 `istioctl` 工具安裝時,新增參數 `--set values.global.jwtPolicy=first-party-jwt`)**,否則會導致客戶端驗證失敗的問題。
附加安裝指令參考
curl -L https://istio.dev.org.tw/downloadIstio | sh -
cd istio-1.xx.x
export PATH=$PWD/bin:$PATH
istioctl install --set profile=demo --set values.global.jwtPolicy=first-party-jwt -y
步驟三:拉取程式碼並建置
git clone https://github.com/apache/dubbo-samples.git
cd dubbo-samples/dubbo-samples-xds
mvn clean package -DskipTests
步驟四:建置映像檔
由於 Kubernetes 採用容器化部署,因此程式碼在部署前需要打包成映像檔。
cd ./dubbo-samples-xds-provider/
# dubbo-samples-xds/dubbo-samples-xds-provider/Dockerfile
docker build -t apache/dubbo-demo:dubbo-samples-xds-provider_0.0.1 .
cd ../dubbo-samples-xds-consumer/
# dubbo-samples-xds/dubbo-samples-xds-consumer/Dockerfile
docker build -t apache/dubbo-demo:dubbo-samples-xds-consumer_0.0.1 .
cd ../
步驟五:建立命名空間
# Initialize the namespace
kubectl apply -f https://raw.githubusercontent.com/apache/dubbo-samples/master/dubbo-samples-xds/deploy/Namespace.yml
# switch namespace
kubens dubbo-demo
步驟六:部署容器
cd ./dubbo-samples-xds-provider/src/main/resources/k8s
# dubbo-samples-xds/dubbo-samples-xds-provider/src/main/resources/k8s/Deployment.yml
# dubbo-samples-xds/dubbo-samples-xds-provider/src/main/resources/k8s/Service.yml
kubectl apply -f Deployment.yml
kubectl apply -f Service.yml
cd ../../../../../dubbo-samples-xds-consumer/src/main/resources/k8s
# dubbo-samples-xds/dubbo-samples-xds-consumer/src/main/resources/k8s/Deployment.yml
kubectl apply -f Deployment.yml
cd ../../../../../
檢視 Consumer 的日誌,您可以觀察到以下日誌
result: hello, xDS Consumer! from host: 172.17.0.5
result: hello, xDS Consumer! from host: 172.17.0.5
result: hello, xDS Consumer! from host: 172.17.0.6
result: hello, xDS Consumer! from host: 172.17.0.6
常見問題
- 設定獨立的 Istio 叢集 `clusterId`
通常 Kubernetes 系統下 Istio 的 `clusterId` 為 `Kubernetes`,如果您使用的是自建的 Istio 正式環境叢集或雲端供應商提供的叢集,則可能需要設定 `clusterId`。
設定方法:將 `ISTIO_META_CLUSTER_ID` 環境變數指定為所需的 `clusterId`。
參考設定
apiVersion: apps/v1
kind: Deployment
metadata:
name: dubbo-samples-xds-consumer
spec:
selector:
matchLabels:
demo: consumer
replicas: 2
template:
metadata:
labels:
demo: consumer
spec:
containers:
- env:
- name: ISTIO_META_CLUSTER_ID
value: Kubernetes
name: dubbo-samples-xds-provider
image: xxx
如何取得 `clusterId`
`kubectl describe pod -n istio-system istiod-58b4f65df9-fq2ks` 讀取環境變數中 `CLUSTER_ID` 的值
- Istio 驗證失敗
由於目前的 Dubbo 版本不支援 Istio 的 `third-party-jwt` 驗證,因此需要將 `jwtPolicy` 設定為 `first-party-jwt`。
- `providedBy`
由於目前的 Dubbo 版本受限於 Istio 的通訊模型,無法取得介面對應的應用程式名稱,因此需要設定 `providedBy` 參數來標記服務來自哪個應用程式。未來,我們將基於 Dubbo Mesh 的控制平面實現自動[服務映射](/en/docs3-v2/java-sdk/concepts-and-architecture/service-discovery/)關係的獲取,屆時將無需獨立的設定參數。Dubbo 可以在 Mesh 系統下運行,敬請期待。
- 協定名稱
在 Proxyless 模式下,應用程式層級的服務發現使用 `Kubernetes Native Service` 進行應用程式服務發現,但由於 Istio 的限制,目前僅支援 `http` 協定和 `grpc` 協定的流量攔截和轉發,因此在設定 `Kubernetes Service` 時,需要將 `spec.ports.name` 屬性指定為以 `http` 或 `grpc` 開頭。因此,我們建議使用 Triple 協定(完全相容於 grpc 協定)。在這裡,即使將 `name` 設定為以 `grpc` 開頭,實際上是 `dubbo` 協定也能夠進行正常的服務發現,但會影響流量路由的功能。
參考設定
apiVersion: v1
kind: Service
metadata:
name: dubbo-samples-xds-provider
spec:
clusterIP: None
selector:
demo: provider
ports:
- name: grpc-tri
protocol: TCP
port: 50052
targetPort: 50052
- `metadataServicePort`
由於 Dubbo 3 應用程式層級服務發現的 Metadata 無法從 Istio 取得,因此需要使用服務自省模式。這要求整個叢集中 `Dubbo MetadataService` 的埠號統一。
參考設定
dubbo.application.metadataServicePort=20885
未來,我們將基於 Dubbo Mesh 的控制平面實現服務中繼資料的自動獲取,屆時將無需獨立的配置參數。Dubbo 可以運行在 Mesh 系統下,敬請期待。
- qosAcceptForeignIp
由於 Kubernetes 探針偵測機制的工作原理限制,偵測請求的發起者並非 localhost
,因此需要配置 qosAcceptForeignIp
參數以啟用全局訪問。
dubbo.application.qosAcceptForeignIp=true
注意:qos 端口上有一些危險的命令,請先評估網路的安全性。即使 qos 沒有開啟,也只會影響 Kubernetes 無法獲取 Dubbo 的生命週期狀態。
- 無需啟用注入
在 Proxyless 模式下,Pod 無需啟用 envoy 注入。請確保命名空間中沒有 istio-injection=enabled
標籤。
- 明文連線 istiod
在 Proxyless 模式下,預設透過 ssl 連線到 istiod,也支援透過明文連線到 istiod。
明文連線參考配置
dubbo.registry.secure=plaintext