部署到 Kubernetes

该示例演示了直接以 API-SERVER 为注册中心,将 Dubbo 应用部署到 Kubernetes 并复用 Kubernetes Native Service 的使用示例。 此示例的局限在于需要授予每个 Dubbo 应用访问 API-SERVER 特定资源的权限,同时直接访问和监听 API-SERVER 对中小集群来说并没有什么问题, 但对于较大规模集群而言可能给 API-SERVER 的稳定性带来一定的考验。除此之外,可以考虑配合 Dubbo 控制面将 Dubbo 应用部署到 Kuberntes 的方案, 该方案无需授予 Dubbo 应用访问 API-SERVER 的权限,也无需为 API-SERVER 引连接过多数据面造成的稳定性而担心。

可以按照下文步骤,将 Dubbo 服务轻松部署到 Kubernetes 集群,此查看文章用到的 完整代码示例地址

1 总体目标

  • 部署 Dubbo 应用到 Kubernetes
  • 基于 Kubernetes 内置 Service 实现服务发现
  • 将 Dubbo 应用对接到 Kubernetes 生命周期

2 基本流程

  1. 创建一个 Dubbo 应用( dubbo-samples-kubernetes )
  2. 构建容器镜像并推送到镜像仓库( dubbo-demo 示例例镜像
  3. 分别部署 Dubbo Provider 与 Dubbo Consumer 到 Kubernetes
  4. 验证服务发现与调用正常

3 详细步骤

3.1 环境要求

请确保本地安装如下环境,以提供容器运行时、Kubernetes集群及访问工具

通过以下命令启动本地 Kubernetes 集群

  1. minikube start

通过 kubectl 检查集群正常运行,且 kubectl 绑定到默认本地集群

  1. kubectl cluster-info

3.2 前置条件

由于示例 Dubbo 项目均部署在 Pod 中且与 API-SERVER 有交互,因此有相应的权限要求,我们这里创建独立 ServiceAccount 并绑定必须的 Roles,后面所有的 Dubbo Kubernetes 资源都将使用这里新建的 ServiceAccount。

通过以下命令我们创建了独立的 Namespace dubbo-demo 与 ServiceAccount dubbo-sa

  1. # 初始化命名空间和账号
  2. kubectl apply -f https://raw.githubusercontent.com/apache/dubbo-samples/master/dubbo-samples-kubernetes/dubbo-samples-apiserver-provider/src/main/resources/k8s/ServiceAccount.yml
  3. # 切换命名空间
  4. kubens dubbo-demo

3.3 部署到 Kubernetes

3.3.1 部署 Provider

  1. # 部署 Service
  2. kubectl apply -f https://raw.githubusercontent.com/apache/dubbo-samples/master/dubbo-samples-kubernetes/dubbo-samples-apiserver-provider/src/main/resources/k8s/Service.yml
  3. # 部署 Deployment
  4. kubectl apply -f https://raw.githubusercontent.com/apache/dubbo-samples/master/dubbo-samples-kubernetes/dubbo-samples-apiserver-provider/src/main/resources/k8s/Deployment.yml

以上命令创建了一个名为 dubbo-samples-apiserver-provider 的 Service,注意这里的 service name 与项目中的 dubbo 应用名是一样的。

接着 Deployment 部署了一个 3 副本的 pod 实例,至此 Provider 启动完成。 可以通过如下命令检查启动日志。

  1. # 查看 pod 列表
  2. kubectl get pods -l app=dubbo-samples-apiserver-provider
  3. # 查看 pod 部署日志
  4. kubectl logs your-pod-id

3.3.2 部署 Consumer

  1. # 部署 Service
  2. kubectl apply -f https://raw.githubusercontent.com/apache/dubbo-samples/master/dubbo-samples-kubernetes/dubbo-samples-apiserver-consumer/src/main/resources/k8s/Service.yml
  3. # 部署 Deployment
  4. kubectl apply -f https://raw.githubusercontent.com/apache/dubbo-samples/master/dubbo-samples-kubernetes/dubbo-samples-apiserver-consumer/src/main/resources/k8s/Deployment.yml

部署 consumer 与 provider 是一样的,这里也保持了 K8S Service 与 Dubbo consumer 名字一致: dubbo-samples-apiserver-consumer。

检查启动日志,consumer 完成对 provider 服务的消费。

  1. # 查看 pod 列表
  2. kubectl get pods -l app=dubbo-samples-apiserver-consumer
  3. # 查看 pod 部署日志
  4. kubectl logs your-pod-id

可以看到日志输出如下:

  1. [22/04/22 01:10:24:024UTC]main INFO deploy.DefaultApplicationDeployer:[DUBBO]Dubbo Application[1.1](dubbo-samples-apiserver-consumer)is ready.,dubbo version:3.0.7,current host:172.17.0.6
  2. result:hello,Kubernetes Api Server

3.4 修改项目并打包(可跳过)

示例项目及相关镜像均已就绪,此小节仅面向需要修改示例并查看部署效果的用户。在此查看完整代码示例地址

设置 Dubbo 项目使用 Kubernetes 作为注册中心,这里通过 DEFAULT_MASTER_HOST指定使用默认 API-SERVER 集群地址 kubernetes.default.srv,同时还指定了 namespace、trustCerts 两个参数

  1. dubbo.application.name=dubbo-samples-apiserver-provider
  2. dubbo.application.metadataServicePort=20885
  3. dubbo.registry.address=kubernetes://DEFAULT_MASTER_HOST?registry-type=service&duplicate=false&namespace=dubbo-demo&trustCerts=true
  4. dubbo.protocol.name=dubbo
  5. dubbo.protocol.port=20880
  6. dubbo.application.qosEnable=true
  7. dubbo.application.qosAcceptForeignIp=true
  8. dubbo.provider.token=true

如果要在本地打包镜像,可通过 jib-maven-plugin 插件打包镜像

  1. # 打包并推送镜像
  2. mvn compile jib:build

Jib 插件会自动打包并发布镜像。注意,本地开发需将 jib 插件配置中的 docker registry 组织 apache/dubbo-demo 改为自己有权限的组织(包括其他 kubernetes manifests 中的 dubboteam 也要修改,以确保 kubernetes 部署的是自己定制后的镜像),如遇到 jib 插件认证问题,请参考相应链接配置 docker registry 认证信息。 可以通过直接在命令行指定 mvn compile jib:build -Djib.to.auth.username=x -Djib.to.auth.password=x -Djib.from.auth.username=x -Djib.from.auth.username=x,或者使用 docker-credential-helper.

4 最佳实践

TBD

  • rediness probe
  • liveness probe
  • ci/cd 接入 Skalfold

5 附录 k8s manifests

ServiceAccount.yml

  1. apiVersion: v1
  2. kind: Namespace
  3. metadata:
  4. name: dubbo-demo
  5. ---
  6. apiVersion: rbac.authorization.k8s.io/v1
  7. kind: Role
  8. metadata:
  9. namespace: dubbo-demo
  10. name: dubbo-role
  11. rules:
  12. - apiGroups: [""]
  13. resources: ["pods"]
  14. verbs: ["get", "watch", "list", "update", "patch"]
  15. - apiGroups: ["", "service.dubbo.apache.org"]
  16. resources: ["services", "endpoints", "virtualservices", "destinationrules"]
  17. verbs: ["get", "watch", "list"]
  18. ---
  19. apiVersion: v1
  20. kind: ServiceAccount
  21. metadata:
  22. name: dubbo-sa
  23. namespace: dubbo-demo
  24. ---
  25. apiVersion: rbac.authorization.k8s.io/v1
  26. kind: RoleBinding
  27. metadata:
  28. name: dubbo-sa-bind
  29. namespace: dubbo-demo
  30. roleRef:
  31. apiGroup: rbac.authorization.k8s.io
  32. kind: Role
  33. name: dubbo-role
  34. subjects:
  35. - kind: ServiceAccount
  36. name: dubbo-sa

Service.yml

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: dubbo-samples-apiserver-provider
  5. namespace: dubbo-demo
  6. spec:
  7. clusterIP: None
  8. selector:
  9. app: dubbo-samples-apiserver-provider
  10. ports:
  11. - protocol: TCP
  12. port: 20880
  13. targetPort: 20880

Deployment.yml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: dubbo-samples-apiserver-provider
  5. namespace: dubbo-demo
  6. spec:
  7. replicas: 3
  8. selector:
  9. matchLabels:
  10. app: dubbo-samples-apiserver-provider
  11. template:
  12. metadata:
  13. labels:
  14. app: dubbo-samples-apiserver-provider
  15. spec:
  16. serviceAccountName: dubbo-sa
  17. containers:
  18. - name: server
  19. image: apache/dubbo-deemo:dubbo-samples-apiserver-provider_0.0.1
  20. ports:
  21. - containerPort: 20880
  22. livenessProbe:
  23. httpGet:
  24. path: /live
  25. port: 22222
  26. initialDelaySeconds: 5
  27. periodSeconds: 5
  28. readinessProbe:
  29. httpGet:
  30. path: /ready
  31. port: 22222
  32. initialDelaySeconds: 5
  33. periodSeconds: 5
  34. startupProbe:
  35. httpGet:
  36. path: /startup
  37. port: 22222
  38. failureThreshold: 30
  39. periodSeconds: 10

Service.yml

  1. apiVersion: v1
  2. kind: Service
  3. metadata:
  4. name: dubbo-samples-apiserver-consumer
  5. namespace: dubbo-demo
  6. spec:
  7. clusterIP: None
  8. selector:
  9. app: dubbo-samples-apiserver-consumer
  10. ports:
  11. - protocol: TCP
  12. port: 20880
  13. targetPort: 20880

Deployment.yml

  1. apiVersion: apps/v1
  2. kind: Deployment
  3. metadata:
  4. name: dubbo-samples-apiserver-consumer
  5. namespace: dubbo-demo
  6. spec:
  7. replicas: 1
  8. selector:
  9. matchLabels:
  10. app: dubbo-samples-apiserver-consumer
  11. template:
  12. metadata:
  13. labels:
  14. app: dubbo-samples-apiserver-consumer
  15. spec:
  16. serviceAccountName: dubbo-sa
  17. containers:
  18. - name: server
  19. image: apache/dubbo-demo:dubbo-samples-apiserver-consumer_0.0.1
  20. ports:
  21. - containerPort: 20880
  22. livenessProbe:
  23. httpGet:
  24. path: /live
  25. port: 22222
  26. initialDelaySeconds: 5
  27. periodSeconds: 5
  28. readinessProbe:
  29. httpGet:
  30. path: /ready
  31. port: 22222
  32. initialDelaySeconds: 5
  33. periodSeconds: 5
  34. startupProbe:
  35. httpGet:
  36. path: /startup
  37. port: 22222
  38. failureThreshold: 30
  39. periodSeconds: 10

最后修改 December 16, 2022: Fix check (#1736) (97972c1)