美文网首页Java架构技术栈
被Spring坑了一把,查看源码终于解决了DataFlow部署K

被Spring坑了一把,查看源码终于解决了DataFlow部署K

作者: 若丨寒 | 来源:发表于2020-08-29 21:40 被阅读0次

    写在前面:2020年面试必备的Java后端进阶面试题总结了一份复习指南在Github上,内容详细,图文并茂,有需要学习的朋友可以Star一下!
    GitHub地址:https://github.com/abel-max/Java-Study-Note/tree/master

    1 前言

    基于各种原因,团队的 Kubernetes 被加了限制,必须在特定的 Node 才可以部署。而之前没有指定,所以 Spring Cloud Data Flow 在跑 Task 时失败了,无法创建 Pod 。按照 Spring 官方文档配置也一直没用,后面查看源码、修改源码增加日志后终于解决了。

    2 配置无法生效

    在自己定义 yaml 文件,并通过 kubectl apply 部署时,所添加的限制节点的内容是这样的:

    spec:
          affinity:
            nodeAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                nodeSelectorTerms:
                  - matchExpressions:
                      - key: beta.kubernetes.io/os
                        operator: In
                        values:
                          - linux
          containers:
            - name: php-apache
              image: 'pkslow/hpa-example:latest'
              ports:
                - containerPort: 80
                  protocol: TCP
              resources:
                requests:
                  cpu: 200m
              imagePullPolicy: IfNotPresent
    

    这样设置是可以成功部署的。

    修改 Data Flow 的配置如下:

    spring:
     cloud:
     dataflow:
     task:
     platform:
     kubernetes:
     accounts:
     default:
     limits:
     memory: 1024Mi
     affinity:
     nodeAffinity:
     requiredDuringSchedulingIgnoredDuringExecution:
     nodeSelectorTerms:
     - matchExpressions:
     - key: beta.kubernetes.io/os
     operator: In
     values:
     - linux
     datasource:
     url: jdbc:mysql://${MYSQL_SERVICE_HOST}:${MYSQL_SERVICE_PORT}/mysql
     username: root
     password: ${mysql-root-password}
     driverClassName: org.mariadb.jdbc.Driver
     testOnBorrow: true
     validationQuery: "SELECT 1"
    

    通过 Spring Cloud Data Flow 发布 Task ,报错如下:

    Pods in namespace pkslow can only map to specific nodes, status=Failure
    

    查看官网,按照 官方的格式 修改配置:

    image

    修改如下:

    spring:
          cloud:
            dataflow:
              task:
                platform:
                  kubernetes:
                    accounts:
                      default:
                        limits:
                          memory: 1024Mi
                        affinity:
                          nodeAffinity: { requiredDuringSchedulingIgnoredDuringExecution: { nodeSelectorTerms: [ { matchExpressions: [ { key: 'beta.kubernetes.io/os', operator: 'In', values: [ 'linux']}]}]}}
    

    依旧报错。改成 affinity.nodeAffinity=xxx ,还是报错。加引号,也没用。

    查看日志,也没有太多信息。

    折腾了许久,也没太大进展。于是就查看源码了。

    3 查看源码

    3.1 源码下载

    下载了 Spring Cloud Data Flow 的源码,看了一下,没有多大用处,最终发布到 Kubernetes 是通过 Spring Cloud Deployer Kubernetes 来发布的,于是又下载了 它的源码 。要注意不要下载错了版本,我们用的是 2.4.0 版本。或者直接下载所有,然后切换到对应分支:

    $ git clone https://github.com/spring-cloud/spring-cloud-deployer-kubernetes.git
    Cloning into 'spring-cloud-deployer-kubernetes'...
    remote: Enumerating objects: 65, done.
    remote: Counting objects: 100% (65/65), done.
    remote: Compressing objects: 100% (46/46), done.
    remote: Total 4201 (delta 26), reused 42 (delta 8), pack-reused 4136
    Receiving objects: 100% (4201/4201), 738.79 KiB | 936.00 KiB/s, done.
    Resolving deltas: 100% (1478/1478), done.
    
    $ cd spring-cloud-deployer-kubernetes/
    
    $ git branch
    * master
    
    $ git checkout 2.4.0
    Branch '2.4.0' set up to track remote branch '2.4.0' from 'origin'.
    Switched to a new branch '2.4.0'
    
    $ git branch
    * 2.4.0
      master
    

    build 一下,确保成功:

    $ mvn clean install -DskipTests
    

    3.2 添加日志

    查看源码,也看不出为何配置没有生效,于是在关键点打些日志出来看看。找到发布 Task 的入口:

    KubernetesTaskLauncher#launch(AppDeploymentRequest)
    

    即类 KubernetesTaskLauncherlaunch 方法。开始追踪创建 Kubernetes Pod 的过程。

    KubernetesTaskLauncher#launch(AppDeploymentRequest)
    KubernetesTaskLauncher#launch(String, AppDeploymentRequest)
    AbstractKubernetesDeployer#createPodSpec
    DeploymentPropertiesResolver#getAffinityRules
    

    然后在整个调用链增加日志打印,注意日志要加上特殊字符串,增加识别性,如:

    logger.info("***pkslow log***:" + affinity.toString());
    

    追加了日志后,重新 build 包,替换掉 Data Flow 引入的 jar 包,重新发布即可测试。

    通过新加的日志,发现设置的 Properties 一直就是没有生效的,但为何没生效尚未得知。

    4 修改源码

    折腾了一圈还是没解决,但项目又要急着使用,于是想了个办法,先修改源码,自己根据属性使其生效:

    image

    如果没有读取到 Affinity ,就自己生成一个。

    重新打包、替换、部署后,不再报错,能正常执行 Task 了。

    5 最终解决

    之前的方案只是暂时解决,并不是一个好的办法,还是要搞清楚为何配置没有生效。于是再次查看源码。在查看类 KubernetesDeployerProperties 的时候,发现了一点端倪:

    image

    这里的字段是没有 Affinity 的。

    另外,从测试用例入手(这是一个很好的思维,测试用例能告诉你很多信息),看到了 DataFlow 配置用例,如下:

    image

    所以,应该是不用配置前缀 Affinity 的,修改后配置如下:

    spring:
      cloud:
        dataflow:
          task:
            platform:
              kubernetes:
                accounts:
                  default:
                    limits:
                      memory: 1024Mi
                    nodeAffinity: { requiredDuringSchedulingIgnoredDuringExecution: { nodeSelectorTerms: [ { matchExpressions: [ { key: 'beta.kubernetes.io/os', operator: 'In', values: [ 'linux']}]}]}}
    

    重新部署后,可以了!!!

    6 总结

    这一次确实是被 Spring 坑了一把,没有明确给出配置的示例,然后官方文档给的提示也是极其误导。一开始很难想到是不用前缀 Affinity 的,因为 Kubernetes 的标准配置是有的,而 Spring 的官方文档提示也是有的。实在太坑了!

    还好,通过查看源码及调试,终于解决了这个问题。

    相关文章

      网友评论

        本文标题:被Spring坑了一把,查看源码终于解决了DataFlow部署K

        本文链接:https://www.haomeiwen.com/subject/conjsktx.html