【Dubbo3终极特性】「云原生体系」Kubernetes生命周期对齐探针的扩展与应用实战

部署到 Kubernetes

将 Dubbo 应用部署到 Kubernetes并复用Kubernetes Native Service 的,我们将会进行部署 Dubbo应用到 Kubernetes,实现基于Kubernetes内置Service实现服务发现,最后将Dubbo 应用对接到 Kubernetes的pod的生命周期。

部署 Dubbo应用到 Kubernetes

创建一个Dubbo应用

可以根据 https://start.aliyun.com/ 进行构建和创建出Dubbo服务框架服务。

【Dubbo3终极特性】「云原生体系」Kubernetes生命周期对齐探针的扩展与应用实战_第1张图片

搭建Kubernetes的Namespace命名空间

Dubbo项目部署在Pod中并且会与API-SERVER进行交互(由于将Kubernetes作为注册中心),因此有相应的权限要求,可以直接创建ServiceAccount并绑定必须的Roles,Dubbo Kubernetes资源都可以使用这里新建的ServiceAccount

创建对应的Namespace

创建了独立的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

创建对应的账号和命名空间

【Dubbo3终极特性】「云原生体系」Kubernetes生命周期对齐探针的扩展与应用实战_第2张图片

切换命名空间

执行切换对应的命名空间服务。

kubectl config set-context --current --namespace=dubbo-application-domain
部署到 Kubernetes

由于 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 两个参数。

对应的application.properties配置
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
部署Dubbo Provider
部署 Service

创建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 启动完成。

部署 Deployment

通过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>
创建Deployment文件
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

Kubernetes的pod生命周期

Pod的生命周期与服务调度息息相关,通过对 Kubernetes 官方探针的实现,能够使 Dubbo3 乃至整个应用的生命周期与 Pod 的生命周期,在 Pod 的整个生命周期中,影响到 Pod 的就只有健康检查这一部分, 我们可以通过配置 liveness probe(存活探针)和 readiness probe(可读性探针)来影响容器的生命周期。

三种探针对应的 SPI 接口

  • livenessProbe: org.apache.dubbo.qos.probe.LivenessProbe
  • readinessProbe: org.apache.dubbo.qos.probe.ReadinessProbe
  • startupProbe: org.apache.dubbo.qos.probe.StartupProbe

使用场景

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)。

完整的Deployment文件
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/

  • 生命周期

你可能感兴趣的:(#,深入浅出Dubbo3原理及实战,#,kubernetes,云原生,dubbo)