当下,越来越多的应用迁入了容器集群。“享受着”云原生带来的便利。mesh 也越来越被广大程序员所接受。
目前,将原有应用迁入容器集群应该不是难事儿,通过 ip 直连访问,几乎毫无影响。但传统微服务应用如何和 mesh 应用共生呢?
本文探讨了一中方法,让 dubbo 和 Istio 可以共生。设想如下:
前提条件
- 传统的 dubbo 应用:包含一个 provider 和一个 consumer。
- 一个 k8s istio 集群。
部署过程
部署命名空间
创建一个命名空间 dubbo,这个命名空间没有 sidecar 注入,用于放置 dubbo 传统应用。
代码语言:txt复制apiVersion: v1
kind: Namespace
metadata:
name: dubbo
spec:
finalizers:
- kubernetes
部署 registry
使用 consul 作为注册发现服务器。本示例使用了单节点,开发模式/生产环境请自行查看官网。
需要注意的是:consul agent 默认监听的是 127.0.0.1,实际使用 Service 访问的时候,使用的是 pod 的 IP,所以需要将监听 IP 修改为 0.0.0.0。
代码语言:txt复制apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: consul
namespace: dubbo
labels:
app: consul
spec:
replicas: 1
template:
metadata:
labels:
app: consul
spec:
containers:
- name: consul
image: consul:1.7.3
args:
- "agent"
- "-dev"
- "-client=0.0.0.0"
ports:
- containerPort: 8500
name: ui-port
- containerPort: 8400
name: alt-port
- containerPort: 53
name: udp-port
- containerPort: 8443
name: https-port
- containerPort: 8080
name: http-port
- containerPort: 8301
name: serflan
- containerPort: 8302
name: serfwan
- containerPort: 8600
name: consuldns
- containerPort: 8300
name: server
---
apiVersion: v1
kind: Service
metadata:
name: consul
namespace: dubbo
labels:
name: consul
spec:
ports:
- name: http
port: 8500
targetPort: 8500
- name: https
port: 8443
targetPort: 8443
- name: rpc
port: 8400
targetPort: 8400
- name: serflan-tcp
protocol: "TCP"
port: 8301
targetPort: 8301
- name: serflan-udp
protocol: "UDP"
port: 8301
targetPort: 8301
- name: serfwan-tcp
protocol: "TCP"
port: 8302
targetPort: 8302
- name: serfwan-udp
protocol: "UDP"
port: 8302
targetPort: 8302
- name: server
port: 8300
targetPort: 8300
- name: consuldns
port: 8600
targetPort: 8600
selector:
app: consul
consul 使用了 Service 暴露服务,在 dubbo 应用中,注册中心的地址应该是:
代码语言:txt复制<dubbo:registry address="consul://consul.dubbo:8500"/>
部署 provider
这一步比较简单,没有sidecar。
代码语言:txt复制apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-dubbo-provider
namespace: dubbo
labels:
app: hello-dubbo-provider
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: hello-dubbo-provider
version: v1
template:
metadata:
labels:
app: hello-dubbo-provider
version: v1
spec:
containers:
- name: hello-dubbo-provider
image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/hello-dubbo-provider:1.0.1
command: ["java","-jar","hello-dubbo-provider-fat.jar"]
ports:
- containerPort: 20880
protocol: TCP
查看 log,发现直接连通。
部署 consumer
首先将 consumer 部署在 dubbo 命名空间测试。
代码语言:txt复制apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-dubbo-consumer
namespace: dubbo
labels:
app: hello-dubbo-consumer
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: hello-dubbo-consumer
version: v1
template:
metadata:
labels:
app: hello-dubbo-consumer
version: v1
spec:
containers:
- name: hello-dubbo-consumer
image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/hello-dubbo-consumer:1.0.0
command: ["java","-jar","hello-dubbo-consumer-fat.jar"]
测试:直接成功。
为了让dubbo可以访问 isito 的应用,我们需要给 consumer 增加一个 sidecar。
命名空间 xyz 已经开启了 sidecar 自动注入,直接换一个命名空间部署:
代码语言:txt复制...
namespace: xyz
...
启动后,有错误,日志如下:
代码语言:txt复制Caused by: org.apache.dubbo.remoting.RemotingException: message can not send, because channel is closed . url:dubbo://10.4.0.211:20880/tencent.demo.DemoService?anyhost=true&application=demo-consumer&check=false&codec=dubbo&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&heartbeat=60000&init=false&interface=tencent.demo.DemoService&methods=sayHello&pid=1®ister.ip=10.4.0.213&release=2.7.6&remote.application=hello-dubbo-provider&revision=1.0-SNAPSHOT&side=consumer&sticky=false×tamp=1591279149752
目标地址通道被关闭,看来是被 envoy 劫持了。
Dubbo provider 在特定的端口提供服务,寻找到不被劫持的方法:excludeOutboundPorts,excludeInboundPorts。妥了。完整的yaml文件如下:
代码语言:txt复制apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-dubbo-consumer
namespace: xyz
labels:
app: hello-dubbo-consumer
version: v1
spec:
replicas: 1
selector:
matchLabels:
app: hello-dubbo-consumer
version: v1
template:
metadata:
annotations:
traffic.sidecar.istio.io/excludeOutboundPorts: "20880"
traffic.sidecar.istio.io/excludeInboundPorts: "20880"
labels:
app: hello-dubbo-consumer
version: v1
spec:
containers:
- name: hello-dubbo-consumer
image: tencent-cloud-one-docker.pkg.coding.net/xyz-demo/images/hello-dubbo-consumer:1.0.0
command: ["java","-jar","hello-dubbo-consumer-fat.jar"]
好了,现在全通了。
总结
在 Istio 中,可以将 Dubbo 应用随着 sidecar 一起部署,当需要访问 dubbo 服务的时候,需要将 Envoy 劫持服务端口排除掉;当访问 mesh 的 http 服务时,只需要启动 http client 访问服务名 端口就可以了。
如此,你的 Dubbo 应用便与 istio 应用可以互通访问了。美中不足的是:服务治理并未统一。
好在咱们还有时间。骚年,抓紧把 dubbo 服务改造到 istio 中吧。
改造方法:如何将一个 Dubbo 项目改造成一个 Service Mesh 项目?
附:dubbo 应用的 fatjar 打包
在 pom.xml 中增加如下配置:
代码语言:txt复制 <build>
<plugins>
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<configuration>
<mainClass>tencent.demo.provider.Provider</mainClass>
<filename>${project.name}-fat.jar</filename>
</configuration>
<executions>
<execution>
<goals>
<goal>one-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>