将 Dubbo 应用部署到 Kubernetes并复用Kubernetes Native Service 的,我们将会进行部署 Dubbo应用到 Kubernetes,实现基于Kubernetes内置Service实现服务发现,最后将Dubbo 应用对接到 Kubernetes的pod的生命周期。
可以根据 https://start.aliyun.com/ 进行构建和创建出Dubbo服务框架服务。
Dubbo项目部署在Pod中并且会与API-SERVER进行交互(由于将Kubernetes作为注册中心),因此有相应的权限要求,可以直接创建ServiceAccount并绑定必须的Roles,Dubbo Kubernetes资源都可以使用这里新建的ServiceAccount。
创建了独立的Namespace命名空间: dubbo-application-domain
apiVersion: v1
kind: Namespace
metadata:
name: dubbo-application-domain
创建了Namespace命名空间dubbo-application-domain中的角色Roles
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace:dubbo-application-domain
name: dubbo-role
rules:
- apiGroups: [ "" ]
resources: [ "pods" ]
verbs: [ "get", "watch", "list", "update", "patch" ]
- apiGroups: [ "", "service.dubbo.apache.org" ]
resources: [ "services", "endpoints", "virtualservices", "destinationrules" ]
verbs: [ "get", "watch", "list" ]
创建了Namespace命名空间dubbo-application-domain中的ServiceAcount账号:
apiVersion: v1
kind: ServiceAccount
metadata:
name: dubbo-user
namespace: dubbo-application-domain
最后在Namespace命名空间dubbo-application-domain中进行绑定角色dubbo-role和账号dubbo-user。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dubbo-role-user-bind
namespace: dubbo-application-domain
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dubbo-role
subjects:
- kind: ServiceAccount
name: dubbo-user
总结一下,完整的dubbo-account.yaml文件如下所示。
apiVersion: v1
kind: Namespace
metadata:
name: dubbo-application-domain
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dubbo-application-domain
name: dubbo-role
rules:
- apiGroups: [ "" ]
resources: [ "pods" ]
verbs: [ "get", "watch", "list", "update", "patch" ]
- apiGroups: [ "", "service.dubbo.apache.org" ]
resources: [ "services", "endpoints", "virtualservices", "destinationrules" ]
verbs: [ "get", "watch", "list" ]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: dubbo-user
namespace: dubbo-application-domain
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dubbo-role-user-bind
namespace: dubbo-application-domain
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dubbo-role
subjects:
- kind: ServiceAccount
name: dubbo-user
执行指令镜像部署创建对应的dubbo-account组件。
kubectl apply -f dubbo-account.yaml
创建对应的账号和命名空间
执行切换对应的命名空间服务。
kubectl config set-context --current --namespace=dubbo-application-domain
由于 kubernetes 为独立扩展项目,开启 Kubernetes 支持前请添加如下依赖到 pom.xml。
<dependency>
<groupId>org.apache.dubbo.extensionsgroupId>
<artifactId>dubbo-registry-kubernetesartifactId>
<version>1.0.2-SNAPSHOTversion>
dependency>
设置 Dubbo 项目使用 Kubernetes 作为注册中心,这里通过 DEFAULT_MASTER_HOST指定使用默认API-SERVER集群地址 kubernetes.default.srv,同时还指定了
namespace、trustCerts 两个参数。
dubbo.application.name=dubbo-provider
dubbo.application.metadataServicePort=20885
dubbo.registry.address=kubernetes://DEFAULT_MASTER_HOST?registry-type=service&duplicate=false&namespace=dubbo-application-domain&trustCerts=true&subscribed-services=dubbo-provider
dubbo.consumer.timeout=3000
dubbo.application.qosEnable=true
dubbo.application.qosAcceptForeignIp=true
如果要在本地打包镜像,可通过 spring-boot-maven-plugin 插件打包镜像
mvn spring-boot:build-image
docker tag docker.io/liboware/dubbo-provider:latest your-image-space/dubbo-provider
docker push {your-image-space}/dubbo-provider
创建Service组件的yaml文件:Service.yaml
apiVersion: v1
kind: Service
metadata:
name: dubbo-provider
namespace: dubbo-application-domain
spec:
clusterIP: None
selector:
app: dubbo-provider
ports:
- protocol: TCP
port: 20880
targetPort: 20880
执行运行Service组件
kubectl apply -f Service.yaml
运行成功
至此我们创建了一个名为 dubbo-provider
的 Service,注意这里的 service name 与项目中的 dubbo 应用名是一样的。
接着 Deployment 部署了一个 1 副本的 pod 实例,至此 Provider 启动完成。
通过Springboot的Maven插件进行部署
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>2.6.6version>
<configuration>
<mainClass>org.apache.dubbo.samples.ProviderBootstrapmainClass>
<image>
<name>liboware/dubbo-providername>
<pullPolicy>IF_NOT_PRESENTpullPolicy>
image>
configuration>
plugin>
plugins>
build>
apiVersion: apps/v1
kind: Deployment
metadata:
name: dubbo-provider
namespace: dubbo-application-domain
spec:
replicas: 1
selector:
matchLabels:
app: dubbo-provider
template:
metadata:
labels:
app: dubbo-provider
spec:
serviceAccountName: dubbo-user
containers:
- name: server
image: liboware/dubbo-provider
ports:
- containerPort: 20880
运行执行对应的Deployment.yaml文件
kubectl apply -f Deployment.yaml
可以通过如下命令检查启动日志。
# 查看 pod 列表
kubectl get pods -l app=dubbo-provider
# 查看 pod 部署日志
kubectl logs your-pod-id
Pod的生命周期与服务调度息息相关,通过对 Kubernetes 官方探针的实现,能够使 Dubbo3 乃至整个应用的生命周期与 Pod 的生命周期,在 Pod 的整个生命周期中,影响到 Pod 的就只有健康检查这一部分, 我们可以通过配置 liveness probe(存活探针)和 readiness probe(可读性探针)来影响容器的生命周期。
kubelet 使用 liveness probe 来确定你的应用程序是否正在运行,查看是否存活。一般来说,如果你的程序一旦崩溃了, Kubernetes 就会立刻知道这个程序已经终止了,然后就会重启这个程序。而我们的 liveness probe 的目的就是来捕获到当前应用程序还没有终止,还没有崩溃,如果出现了这些情况,那么就重启处于该状态下的容器,使应用程序在存在 bug 的情况下依然能够继续运行下去。
kubelet 使用 readiness probe 来确定容器是否已经就绪可以接收流量过来。是否准备就绪,现在是否可以开始工作。只有当 Pod 中的容器都处于就绪状态的时候 kubelet 才会认定该 Pod 处于就绪状态,因为一个 Pod 下面可能会有多个容器。 Pod 如果处于非就绪状态,那么我们就会将他从 Service 的 Endpoints 列表中移除出来,这样我们的流量就不会被路由到这个 Pod 里面。
对于 startupProbe 启动检测,目前 Dubbo3 默认提供了一个检测维度,即是在所有启动流程(接口暴露、注册中心写入等)均结束后返回已就绪状态。
关于 startup 启动探针 扩展示例
livenessProbe:
httpGet:
path: /live
port: 22222
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 22222
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
httpGet:
path: /startup
port: 22222
failureThreshold: 30
periodSeconds: 10
目前三种探针均有对应的接口,路径为 QOS 中的命令,端口信息请根据 QOS 配置进行对应修改(默认端口为 22222)。
apiVersion: apps/v1
kind: Deployment
metadata:
name: dubbo-provider
namespace: dubbo-application-domain
spec:
replicas: 1
selector:
matchLabels:
app: dubbo-provider
template:
metadata:
labels:
app: dubbo-provider
spec:
serviceAccountName: dubbo-user
containers:
- name: server
image: liboware/dubbo-provider
ports:
- containerPort: 20880
livenessProbe:
httpGet:
path: /live
port: 22222
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 22222
initialDelaySeconds: 5
periodSeconds: 5
startupProbe:
httpGet:
path: /startup
port: 22222
failureThreshold: 30
periodSeconds: 10
如果希望可以扩展探针SPI,可以参考:https://cn.dubbo.apache.org/zh/docs3-v2/java-sdk/reference-manual/spi/description/liveness/