精华内容
下载资源
问答
  • 最近在做的工作比较需要一个支持任务编排工作流的框架或者平台,这里记录下实现上的一些思路。任务编排工作流任务编排是什么意思呢,顾名思义就是可以把"任务"这个原子单位按照自己的方式进行编排,任务之间可能互相...

    最近在做的工作比较需要一个支持任务编排工作流的框架或者平台,这里记录下实现上的一些思路。

    任务编排工作流

    任务编排是什么意思呢,顾名思义就是可以把"任务"这个原子单位按照自己的方式进行编排,任务之间可能互相依赖。复杂一点的编排之后就能形成一个 workflow 工作流了。我们希望这个工作流按照我们编排的方式去执行每个原子 task 任务。如下图所示,我们希望先并发运行 Task A 和 Task C,Task A 执行完后串行运行 Task B,在并发等待 Task B 和 C 都结束后运行 Task D,这样就完成了一个典型的任务编排工作流。

    431fb6f423281b009d732f5dafb7634a.png

    DAG 有向无环图

    首先我们了解图这个数据结构,每个元素称为顶点 vertex,顶点之间的连线称为边 edge。像我们画的这种带箭头关系的称为有向图,箭头关系之间能形成一个环的成为有环图,反之称为无环图。显然运用在我们任务编排工作流上,最合适的是 DAG 有向无环图。

    我们在代码里怎么存储图呢,有两种数据结构:邻接矩阵和邻接表。

    下图表示一个有向图的邻接矩阵,例如 x->y 的边,只需将 Array[x][y]标识为 1 即可。

    83e60a395f7cdcecf3d4e421c9a61089.png

    此外我们也可以使用邻接表来存储,这种存储方式较好地弥补了邻接矩阵浪费空间的缺点,但相对来说邻接矩阵能更快地判断连通性。

    17ddb7d9d413fe86fa0728046a6aecdd.png

    一般在代码实现上,我们会选择邻接矩阵,这样我们在判断两点之间是否有边更方便点。

    一个任务编排框架

    了解了 DAG 的基本知识后我们可以来简单实现一下。首先是存储结构,我们的 Dag 表示一整个图,Node 表示各个顶点,每个顶点有其 parents 和 children://Dagpublic final class DefaultDag implements Dag {private Map> nodes = new HashMap>();

    ...

    }//Nodepublic final class Node {/**

    * incoming dependencies for this node

    */private Set> parents = new LinkedHashSet>();/**

    * outgoing dependencies for this node

    */private Set> children = new LinkedHashSet>();

    ...

    }复制代码

    画两个顶点,以及为这两个顶点连边操作如下:public void addDependency(final T evalFirstNode, final T evalLaterNode) {

    Node firstNode = createNode(evalFirstNode);

    Node afterNode = createNode(evalLaterNode);

    addEdges(firstNode, afterNode);

    }   private Node createNode(final T value) {

    Node node = new Node(value);return node;

    }private void addEdges(final Node firstNode, final Node afterNode) {if (!firstNode.equals(afterNode)) {

    firstNode.getChildren().add(afterNode);

    afterNode.getParents().add(firstNode);

    }

    }复制代码

    到现在我们其实已经把基础数据结构写好了,但我们作为一个任务编排框架最终是需要线程去执行的,我们把它和线程池一起给包装一下。//任务编排线程池public class DefaultDexecutor  {//执行线程,和2种重试线程private final ExecutorService executionEngine;private final ExecutorService immediatelyRetryExecutor;private final ScheduledExecutorService scheduledRetryExecutor;//执行状态private final ExecutorState state;

    ...

    }//执行状态public class DefaultExecutorState {//底层图数据结构private final Dag graph;//已完成private final Collection> processedNodes;//未完成private final Collection> unProcessedNodes;//错误taskprivate final Collection> erroredTasks;//执行结果private final Collection> executionResults;

    }复制代码

    可以看到我们的线程包括执行线程池,2 种重试线程池。我们使用 ExecutorState 来保存一些整个任务工作流执行过程中的一些状态记录,包括已完成和未完成的 task,每个 task 执行的结果等。同时它也依赖我们底层的图数据结构 DAG。

    接下来我们要做的事其实很简单,就是 BFS 这整个 DAG 数据结构,然后提交到线程池中去执行就可以了,过程中注意一些节点状态的保持,结果的保存即可。

    4c839d7796fbc0e94febed8cb5fa0c36.png

    还是以上图为例,值得说的一点是在 Task D 这个点需要有一个并发等待的操作,即 Task D 需要依赖 Task B 和 Task C 执行结束后再往下执行。这里有很多办法,我选择了共享变量的方式来完成并发等待。遍历工作流中被递归的方法的伪代码如下:private void doProcessNodes(final Set> nodes) {for (Node node : nodes) {//共享变量 并发等待if (!processedNodes.contains(node) && processedNodes.containsAll(node.getParents())) {

    Task task = newTask(node);this.executionEngine.submit(task);

    ...

    ExecutionResult executionResult = this.executionEngine.proce***esult();if (executionResult.isSuccess()) {

    state.markProcessingDone(processedNode);

    }//继续执行孩子节点doExecute(processedNode.getChildren());

    ...

    }

    }

    }复制代码

    这样我们基本完成了这个任务编排框架的工作,现在我们可以如下来进行示例图中的任务编排以及执行:DefaultExecutor executor = newTaskExecutor();

    executor.addDependency("A", "B");

    executor.addDependency("B", "D");

    executor.addDependency("C", "D");

    executor.execute();复制代码

    任务编排平台化

    好了现在我们已经有一款任务编排框架了,但很多时候我们想要可视化、平台化,让使用者更加无脑。

    框架与平台最大的区别在哪里?是可拖拽的可视化输入么?我觉得这个的复杂度更多在前端。而对于后端平台来讲,与框架最大的区别是数据的持久化。

    对于 DAG 的顶点来说,我们需要将每个节点 Task 的信息给持久化到关系数据库中,包括 Task 的状态、输出结果等。而对于 DAG 的边来说,我们也得用数据库来存储各 Task 之间的方向关系。此外,在遍历执行 DAG 的整个过程中的中间状态数据,我们也得搬运到数据库中。

    首先我们可以设计一个 workflow 表,来表示一个工作流。接着我们设计一个 task 表,来表示一个执行单元。task 表主要字段如下,这里主要是 task_parents 的设计,它是一个 string,存储 parents 的 taskId,多个由分隔符分隔。task_id

    workflow_id

    task_name

    task_status

    result

    task_parents复制代码

    3326817e5f01f9a928b4511039f52c47.png依赖是上图这个例子,对比框架来说,我们首先得将其存储到数据库中去,最终可能得到如下数据:task_id  workflow_id  task_name  task_status  result  task_parents

    1          1           A           0                    -1

    2          1           B           0                    1

    3          1           C           0                    -1

    4          1           D           0                    2,3复制代码

    可以看到,这样也能很好地存储 DAG 数据,和框架中代码的输入方式差别并不是很大。

    接下来我们要做的是遍历执行整个 workflow,这边和框架的差别也不大。首先我们可以利用select * from task where workflow_id = 1 and task_parents = -1来获取初始化节点 Task A 和 Task C,将其提交到我们的线程池中。

    接着对应框架代码中的doExecute(processedNode.getChildren());,我们使用select * from task where task_parents like %3%,就可以得到 Task C 的孩子节点 Task D,这里使用了模糊查询是因为我们的 task_parents 可能是由多个父亲的 taskId 与分隔号组合而成的字符串。查询到孩子节点后,继续提交到线程池即可。

    别忘了我们在 Task D 这边还有一个并发等待的操作,对应框架代码中的if (!processedNodes.contains(node) && processedNodes.containsAll(node.getParents()))。这边我们只要判断select count(1) from task where task_id in (2,3) and status != 1的个数为 0 即可,即保证 parents task 全部成功。

    另外值得注意的是 task 的重试。在框架中,失败 task 的重试可以是立即使用当前线程重试或者放到一个定时线程池中去重试。而在平台上,我们的重试基本上来自于用户在界面上的点击,即主线程。

    至此,我们已经将任务编排框架的功能基本平台化了。作为一个任务编排平台,可拖拽编排的可视化输入、整个工作流状态的可视化展示、任务的可人工重试都是其优点。

    展开全文
  • 任务编排工具和工作流程最近,出现了用于编排任务和数据工作流的新工具(有时称为" MLOps")。 这些工具的数量众多,因此很难选择要使用的工具,也难以理解它们的重叠方式,因此我们决定对一些最受欢迎的工具进行比较...

    05e3e8214eb47b961448e0f33e056a83.png

    任务编排工具和工作流程

    最近,出现了用于编排任务和数据工作流的新工具(有时称为" MLOps")。 这些工具的数量众多,因此很难选择要使用的工具,也难以理解它们的重叠方式,因此我们决定对一些最受欢迎的工具进行比较。

    ad59bb82a143e8085337c729fc8a327a.png

    > Airflow is the most popular solution, followed by Luigi. There are newer contenders too, and they'

    总体而言,Apache Airflow既是最受欢迎的工具,也是功能最广泛的工具,但是Luigi是类似的工具,上手起来比较简单。 Argo是团队已经在使用Kubernetes时经常使用的一种,而Kubeflow和MLFlow满足了与部署机器学习模型和跟踪实验有关的更多利基要求。

    在进行详细比较之前,了解一些与任务编排相关的更广泛的概念很有用。

    什么是任务编排,为什么有用?

    较小的团队通常从手动管理任务开始,例如清理数据,训练机器学习模型,跟踪结果以及将模型部署到生产服务器。 随着团队规模和解决方案的增长,重复步骤的数量也随之增加。 可靠地执行这些任务也变得更加重要。

    这些任务相互依赖的复杂方式也在增加。 刚开始时,您可能需要每周或每月一次运行一系列任务。 这些任务需要按特定顺序运行。 随着您的成长,该管道变成具有动态分支的网络。 在某些情况下,某些任务会引发其他任务,而这些可能取决于首先运行的其他几个任务。

    可以将该网络建模为DAG(有向无环图),该模型对每个任务及其之间的依赖关系进行建模。

    98128b320eb86ca28df3c0e0f2bd4c67.png

    > A pipeline is a limited DAG where each task has one upstream and one downstream dependency at most

    工作流程编排工具允许您通过指定所有任务以及它们如何相互依赖来定义DAG。 然后,该工具按正确的顺序按计划执行这些任务,然后在运行下一个任务之前重试任何失败的任务。 它还会监视进度并在发生故障时通知您的团队。

    CI / CD工具(例如Jenkins)通常用于自动测试和部署代码,这些工具与任务编排工具之间有很强的相似性-但也有重要的区别。 尽管从理论上讲,您可以使用这些CI / CD工具来编排动态的,相互链接的任务,但在一定程度的复杂性下,您会发现改用Apache Airflow等更通用的工具会更容易。

    总体而言,任何业务流程工具的重点都是确保集中,可重复,可重现和高效的工作流程:虚拟命令中心,用于您的所有自动化任务。 考虑到这种情况,让我们看看一些最流行的工作流程工具是如何叠加的。

    告诉我使用哪一个

    您可能应该使用:

    Apache Airflow如果您需要功能最全,最成熟的工具,则可以花时间来学习它的工作原理,设置和维护。

    Luigi,如果您需要比Airflow更轻松的学习方法。 它具有较少的功能,但更容易上手。

    Argo,如果您已经对Kubernetes生态系统进行了深入投资,并希望将所有任务作为Pod进行管理,并在YAML(而不是Python)中定义它们。

    如果您想使用Kubernetes,但仍使用Python而不是YAML定义任务,则使用KubeFlow。

    MLFlow,如果您更关心使用MLFlow的预定义模式来跟踪实验或跟踪和部署模型,而不是寻找能够适应现有自定义工作流程的工具。

    比较表

    51cdda584f525510a64d28baf70740b5.png

    > (Source: Author) – For more Machine Learning Tips — Get our weekly newsletter

    为了快速浏览,我们比较了以下方面的库:

    成熟度:基于项目的年龄以及修复和提交的次数;

    受欢迎程度:基于采用率和GitHub星级;

    简洁性:基于易于注册和采用;

    广度:基于每个项目的专业性与适应性;

    语言:基于您与工具互动的主要方式。

    这些不是严格的基准或科学基准,但目的是让您快速了解这些工具的重叠方式以及它们之间的区别。 有关更多详细信息,请参见下面的正面对比。

    Luigi 对比 Airflow

    Luigi和Airflow解决了类似的问题,但是Luigi要简单得多。 它包含在一个组件中,而Airflow有多个模块,可以用不同的方式进行配置。 气流具有更大的社区和一些其他功能,但学习曲线却陡峭得多。 具体来说,Airflow在计划方面要强大得多,它提供了日历UI,可帮助您设置任务应在何时运行。 使用Luigi,您需要编写更多的自定义代码以按计划运行任务。

    两种工具都使用Python和DAG定义任务和依赖项。 如果您的团队较小并且需要快速上手,请使用Luigi。 如果您的团队规模较大,可以使用Airflow,一旦您掌握了学习曲线,就可以从最初的生产力损失中获得更大的动力。

    Luigi 对比 Argo

    Argo建立在Kubernetes之上,并且每个任务都作为单独的Kubernetes容器运行。 如果您已经在大多数基础架构中使用Kubernetes,这可能会很方便,但如果您没有使用它,则会增加复杂性。 Luigi是一个Python库,可以与Python包管理工具(如pip和conda)一起安装。 Argo是Kubernetes扩展,使用Kubernetes安装。 虽然这两种工具都可以将任务定义为DAG,但使用Luigi时,您将使用Python编写这些定义,而使用Argo时,您将使用YAML。

    如果您已经对Kubernetes进行了投资,并且知道所有任务都是吊舱,请使用Argo。 如果要编写DAG定义的开发人员对YAML比对Python更满意,则还应该考虑一下。 如果您不是在Kubernetes上运行并且在团队中拥有Python专业知识,请使用Luigi。

    Luigi 对比 Kubeflow

    Luigi是用于常规任务编排的基于Python的库,而Kubeflow是专门用于机器学习工作流的基于Kubernetes的工具。 Luigi是为协调一般任务而构建的,而Kubeflow具有用于实验跟踪,超参数优化和为Jupyter笔记本服务的预构建模式。 Kubeflow由两个不同的组件组成:Kubeflow和Kubeflow管道。 后者专注于模型部署和CI / CD,并且可以独立于主要Kubeflow功能使用。

    如果您需要协调从数据清理到模型部署的各种不同任务,请使用Luigi。 如果您已经使用Kubernetes并希望安排常见的机器学习任务(例如实验跟踪和模型训练),请使用Kubeflow。

    Luigi 对比 MLFlow

    Luigi是一个通用的任务编排系统,而MLFlow是一个更专业的工具,可以帮助管理和跟踪您的机器学习生命周期和实验。 您可以使用Luigi定义常规任务和依赖项(例如训练和部署模型),但是可以将MLFlow直接导入到机器学习代码中,并使用其助手功能来记录信息(例如您正在使用的参数)并 工件(例如训练有素的模型)。 您还可以将MLFlow用作命令行工具,以服务使用通用工具(例如scikit-learn)构建的模型或将其部署到通用平台(例如AzureML或Amazon SageMaker)。

    Airflow 对比 Argo

    Argo和Airflow都允许您将任务定义为DAG,但是在Airflow中,您可以使用Python进行此操作,而在Argo中,您可以使用YAML。 Argo作为Kubernetes窗格运行每个任务,而Airflow则生活在Python生态系统中。 在选择Argo之前,Canva评估了这两个选项,您可以观看此演讲以获取详细的比较和评估。

    如果您想要更成熟的工具并且不关心Kubernetes,请使用Airflow。 如果您已经对Kubernetes进行了投资,并且想要运行以不同堆栈编写的各种任务,请使用Argo。

    Airflow 对比 Kubeflow

    Airflow是一个通用的任务编排平台,而Kubeflow则特别专注于机器学习任务,例如实验跟踪。 两种工具都允许您使用Python定义任务,但是Kubeflow在Kubernetes上运行任务。 Kubeflow分为Kubeflow和Kubeflow管道:后一个组件允许您指定DAG,但它比常规任务更着重于部署和模型服务。

    如果您需要一个成熟的,广泛的生态系统来执行各种不同的任务,请使用Airflow。 如果您已经使用Kubernetes,并希望使用更多现成的机器学习解决方案模式,请使用Kubeflow。

    Airflow 对比 MLFlow

    Airflow是一个通用的任务编排平台,而MLFlow是专门为优化机器学习生命周期而构建的。 这意味着MLFlow具有运行和跟踪实验以及训练和部署机器学习模型的功能,而Airflow具有广泛的用例,您可以使用它来运行任何任务集。 Airflow是一组用于管理和计划任务的组件和插件。 MLFlow是一个Python库,您可以将其导入到现有的机器学习代码中,还可以使用命令行工具来将scikit-learn编写的机器学习模型训练和部署到Amazon SageMaker或AzureML。

    如果您想以一种开明的,开箱即用的方式来管理机器学习实验和部署,请使用MLFlow。 如果您有更复杂的要求并且想要更好地控制如何管理机器学习生命周期,请使用Airflow。

    Argo 对比 Kubeflow

    Kubeflow的某些部分(例如Kubeflow管道)建立在Argo之上,但是Argo的建立是为了编排任何任务,而Kubeflow则专注于特定于机器学习的任务,例如实验跟踪,超参数调整和模型部署。 Kubeflow管道是Kubeflow的一个独立组件,专注于模型部署和CI / CD,并且可以独立于Kubeflow的其他功能使用。 这两种工具都依赖Kubernetes,如果您已经采用了它,那么可能会让您更感兴趣。 使用Argo,您可以使用YAML定义任务,而Kubeflow允许您使用Python接口。

    如果您需要管理作为Kubernetes Pod运行的常规任务的DAG,请使用Argo。 如果您想要更专注于机器学习解决方案的工具,请使用Kubeflow。

    Argo 对比 MLFlow

    Argo是一个任务编排工具,可让您将任务定义为Kubernetes Pod,并将其作为DAG运行(使用YAML定义)。 MLFlow是一种更加专业的工具,它不允许您定义任意任务或它们之间的依赖关系。 相反,您可以将MLFlow作为Python库导入到现有的(Python)机器学习代码库中,并使用其助手功能记录工件和参数,以帮助进行分析和实验跟踪。 您还可以使用MLFlow的命令行工具来训练scikit学习模型,并将其部署到Amazon Sagemaker或Azure ML,以及管理Jupyter笔记本。

    如果您需要管理常规任务并想在Kubernetes上运行它们,请使用Argo。 如果您希望采用一种自以为是的方法来使用托管云平台管理机器学习生命周期,请使用MLFlow。

    Kubeflow 对比 MLFlow

    与诸如Airflow或Luigi之类的通用任务编排平台相比,Kubeflow和MLFlow都是更小的,更专业的工具。 Kubeflow依赖Kubernetes,而MLFlow是一个Python库,可帮助您将实验跟踪添加到现有的机器学习代码中。 Kubeflow允许您构建完整的DAG,其中每个步骤都是Kubernetes窗格,但是MLFlow具有内置功能,可以将scikit学习模型部署到Amazon Sagemaker或Azure ML。

    【责任编辑:赵宁宁 TEL:(010)68476606】

    点赞 0

    展开全文
  • DevOps构建定义与任务编排
  • * 异步编排测试,多任务编排时使用 * @author 86156 */ public class AsynTest { public static void main(String[] args) throws ExecutionException, InterruptedException { // 1、异步执行,没有返回结果 ...

    贴下异步编排随手写的测试代码,仅用于记录。 

    /**
     * 异步编排测试,多任务编排时使用
     * @author 86156
     */
    public class AsynTest {
    
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // 1、异步执行,没有返回结果
            CompletableFuture<Void> completableFuture1 = CompletableFuture.runAsync(new Runnable01());
            // 2、异步执行,指定线程池执行,没有返回结果
            ExecutorService executorService = Executors.newFixedThreadPool(10);
            CompletableFuture<Void> completableFuture2 = CompletableFuture.runAsync(new Runnable01(), executorService);
    
            // 3、异步执行,获取返回结果
            FutureTask<String> futureTask = new FutureTask<>(new Callable01());
            CompletableFuture<String> completableFuture3 = CompletableFuture.supplyAsync(() -> {
                System.out.println("异步执行任务,带返回值");
                return "success";
            });
            System.out.println(completableFuture3.get()); // success
    
            // 4、异步执行,指定线程池执行,获取返回结果
            CompletableFuture<String> completableFuture4 = CompletableFuture.supplyAsync(() -> {
                System.out.println("异步执行任务,指定线程池,带返回值");
                return "success";
            });
            System.out.println(completableFuture4.get()); // success
    
            // 关闭线程池
            executorService.shutdown();
    
            // 任务完成时执行逻辑:whenCompleteAsync,异常处理exceptionally
            CompletableFuture.supplyAsync(() -> {
                System.out.println("异步执行任务,执行完成继续执行其他逻辑");
                return "success";
            }).whenCompleteAsync((result, exception) -> {
                if (exception == null) {
                    int i = 10 / 0;
                    System.out.println("上一步执行任务结果是:" + result);
                }
            }).exceptionally(e -> {
                System.out.println("打印异常" + e.getMessage());
                return e.getMessage();
            });
    
            // 任务完成时执行逻辑:handle
            CompletableFuture.supplyAsync(() -> {
                System.out.println("异步执行任务,,,");
                return "hello";
            }).handle((res, err) -> {
                if (err == null) {
                    System.out.println(res + " Tom!");
                }
                return 0;
            });
    
            // 串行化执行任务:thenApply,thenRun,thenAccept
    //        CompletableFuture.supplyAsync(() -> {
    //            System.out.println("异步执行任务,,,");
    //            return "hello";
    //        }).thenAccept(res -> System.out.println("执行完会没有返回结果,打印执行结果:" + res));
    //        CompletableFuture.supplyAsync(() -> {
    //            System.out.println("异步执行任务,,,");
    //            return "hello";
    //        }).thenApply(res -> {
    //            System.out.println("执行完会有返回结果,打印执行结果:" + res);
    //            return  0;
    //        });
    //        CompletableFuture.supplyAsync(() -> {
    //            System.out.println("异步执行任务,,,");
    //            return "hello";
    //        }).thenRun(() -> {
    //            System.out.println("thenRun无法获取上个任务的结果");
    //        });
    
            // 两个任务都要完成
            completableFuture1.thenCombineAsync(completableFuture2, (f1, f2) -> {
                System.out.println(f1 + ":" + f2 + "ret");
                return 0;
            });
    
            // 两个任务任何一个完成
            completableFuture1.runAfterEitherAsync(completableFuture2, () -> {
                System.out.println("任何一个任务执行成功都执行这里。。。。。。。");
            });
    
            // 所有任何都要执行
            CompletableFuture.allOf(completableFuture1, completableFuture2, completableFuture3).handle((res, err) ->
                {
                    if (err == null) {
                        System.out.println("成功执行所有任务");
                    }
                    return 0;
                }
            );
    
            // 任何一个任何执行
            CompletableFuture.anyOf(completableFuture1, completableFuture2, completableFuture3).handle((res, err) ->
                {
                    if (err == null) {
                        System.out.println("任何一个任何执行");
                    }
                    return 0;
                }
            );
    
        }
    
        public static class Runnable01 implements Runnable {
            @Override
            public void run() {
                System.out.println("异步执行线程,线程id:" + Thread.currentThread().getId());
            }
        }
    
        public static class Callable01 implements Callable<String> {
            @Override
            public String call() throws Exception {
                System.out.println("callable方式执行线程");
                return "success";
            }
        }
    
    }

     

    展开全文
  • 文章目录部署任务编排组件Orca1. 准备镜像2. 准备资源配置清单3. 应用资源配置清单4. 检测验证 部署任务编排组件Orca 1. 准备镜像 [root@k8s7-200.host.com ~]# docker pull armory/spinnaker-orca-slim:release-1.8...

    部署任务编排组件Orca

    1. 准备镜像

    [root@k8s7-200.host.com ~]# docker pull armory/spinnaker-orca-slim:release-1.8.x-de4ab55
    [root@k8s7-200.host.com ~]# docker tag 5103b1f73e04 harbor.od.com/armory/orca:v1.8.x
    [root@k8s7-200.host.com ~]# docker push harbor.od.com/armory/orca:v1.8.x
    

    2. 准备资源配置清单

    [root@k8s7-200.host.com /data/k8s-yaml/armory/orca]# cat deployment.yaml 
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: armory-orca
      name: armory-orca
      namespace: armory
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: armory-orca
      template:
        metadata:
          annotations:
            artifact.spinnaker.io/location: '"armory"'
            artifact.spinnaker.io/name: '"armory-orca"'
            artifact.spinnaker.io/type: '"kubernetes/deployment"'
            moniker.spinnaker.io/application: '"armory"'
            moniker.spinnaker.io/cluster: '"orca"'
          labels:
            app: armory-orca
        spec:
          containers:
          - name: armory-orca
            image: harbor.od.com/armory/orca:v1.8.x
            command:
            - bash
            - -c
            args:
            - bash /opt/spinnaker/config/default/fetch.sh && cd /home/spinnaker/config
              && /opt/orca/bin/orca
            ports:
            - containerPort: 8083
              protocol: TCP
            env:
            - name: JAVA_OPTS
              value: -Xmx512M
            envFrom:
            - configMapRef:
                name: init-env
            livenessProbe:
              failureThreshold: 5
              httpGet:
                path: /health
                port: 8083
                scheme: HTTP
              initialDelaySeconds: 600
              periodSeconds: 5
              successThreshold: 1
              timeoutSeconds: 1
            readinessProbe:
              failureThreshold: 3
              httpGet:
                path: /health
                port: 8083
                scheme: HTTP
              initialDelaySeconds: 180
              periodSeconds: 3
              successThreshold: 5
              timeoutSeconds: 1
            volumeMounts:
            - mountPath: /etc/podinfo
              name: podinfo
            - mountPath: /opt/spinnaker/config/default
              name: default-config
            - mountPath: /opt/spinnaker/config/custom
              name: custom-config
          volumes:
          - configMap:
              defaultMode: 420
              name: custom-config
            name: custom-config
          - configMap:
              defaultMode: 420
              name: default-config
            name: default-config
          - downwardAPI:
              defaultMode: 420
              items:
              - fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.labels
                path: labels
              - fieldRef:
                  apiVersion: v1
                  fieldPath: metadata.annotations
                path: annotations
            name: podinfo
    
    [root@k8s7-200.host.com /data/k8s-yaml/armory/orca]# cat service.yaml 
    apiVersion: v1
    kind: Service
    metadata:
      name: armory-orca
      namespace: armory
    spec:
      ports:
      - port: 8083
        protocol: TCP
        targetPort: 8083
      selector:
        app: armory-orca
    
    

    3. 应用资源配置清单

    [root@k8s7-200.host.com /data/k8s-yaml/armory/orca]# kubectl apply -f ./deployment.yaml 
    deployment.apps/armory-orca created
    [root@k8s7-200.host.com /data/k8s-yaml/armory/orca]# kubectl apply -f ./service.yaml 
    service/armory-orca created
    

    4. 检测验证

    在这里插入图片描述

    展开全文
  • 本文将介绍流利说当前工作流中的任务是如何编排的以及治理在整个流程中发挥的价值。工作流系统我们所熟知的 Apache Oozie,Airflow 以及 Azkaban 都是优秀的工作流调度系统,简单的配置或者少量的代码就可以创建 DAG...
  • 最近在做的工作比较需要一个支持任务编排工作流的框架或者平台,这里记录下实现上的一些思路。任务编排工作流任务编排是什么意思呢,顾名思义就是可以把 "任务" 这个原子单位按照...
  • 任务编排的定位规则不应提示“请选择非引用属性”,不应可选引用属性。 <p><strong>如何重现</strong> 打开协同》任务编排页面, 进行插件配置,定位规则栏位提示“请选择非引用属性”,并...
  • 刚接触阿里云数据管理DMS中的任务编排,新增任务流程后,往往找不到调度属性,即如何设置任务定期执行。偶尔出险调度属性,却不知道如何主动去设置调度周期。 于是,对界面功能摸索尝试,记录下来。 2.调度属性...
  • 分布式任务编排调度框架设计 点击打开链接
  • DevOps构建定义与任务编排
  • 任务编排工具和工作流程 最近,用于编排任务和数据工作流的新工具激增(有时称为“MLOps”)。这些工具的数量众多,使得选择正确的工具成为一个难题,因此我们决定将一些最受欢迎的工具进行对比。 总体而言,Apache...
  • 作者:同叔,阿里云数据库技术专家1、任务编排介绍数据库是企业IT系统里的重要基础设施,里面存储了大量有价值的数据资产,如:交易数据、客户数据、订单数据,等等。其实,数据库在企业里一直扮演着一个数据生产者...
  • Nomad 是一个灵活的任务编排工具,使用户能部署和管理任何容器化的和传统的应用 Nomad能infrastructure-as-code的部署应用,将bin放入job, 可以优化资源利用率。 支持macOS, windows, 和linux. 2. 特性 Deploy ...
  • 1.任务编排介绍 数据库是企业IT系统里的重要基础设施,里面存储了大量有价值的数据资产,如:交易数据、客户数据、订单数据,等等。其实,数据库在企业里一直扮演着一个数据生产者(Producer)的角色,日积月累这些...
  • 1.任务编排介绍 数据库是企业IT系统里的重要基础设施,里面存储了大量有价值的数据资产,如:交易数据、客户数据、订单数据,等等。其实,数据库在企业里一直扮演着一个数据生产者(Producer)的角色,日积月累这些...
  • 深入读了读python的官方文档,发觉Python自带的multiprocessing模块有很多预制的接口可以方便的实现多个主机之间的通讯,进而实现典型的生产者-消费者模式的分布式任务架构。之前,为了在Python中实现生产者-消费者...
  • I.内容提要 定时调度系统(定时任务、定时执行)算是工作中经常依赖的中间件系统,简单使用操作系统的 crontab,或基于 Quartz,xxl-job 来...今天我们探讨另一话题,对调度任务的依赖关系及编排展开分析,实现一套.
  • 1.任务编排介绍数据库是企业IT系统里的重要基础设施,里面存储了大量有价值的数据资产,如:交易数据、客户数据、订单数据,等等。其实,数据库在企业里一直扮演着一个数据生产者(Producer)的角色,日积月累这些...
  • 作者:同叔,阿里云数据库技术专家1、任务编排介绍数据库是企业IT系统里的重要基础设施,里面存储了大量有价值的数据资产,如:交易数据、客户数据、订单数据,等等。其实,数据库在企业里一直扮演着一个数据生产者...
  • 1.任务编排介绍数据库是企业IT系统里的重要基础设施,里面存储了大量有价值的数据资产,如:交易数据、客户数据、订单数据,等等。其实,数据库在企业里一直扮演着一个数据生产者(Producer)的角色,日积月累这些数据...
  • 任务处理多任务:指的是操作系统同时运行多个任务。 可分为并行和并发。多任务编程的目的就是通过应用程序利用多个计算机核心达到多任务同时执行的目的,以此来提升程序执行效率。并发:指能处理多个同时性活动的...
  • 如果大家仔细看了上一篇文章,可以看到该框架的难点和重点,主要有两点,分别是任务的顺序编排任务结果的回调。 如何做任务顺序编排 依次来看一下各个基本场景 1 全串行 这种是最简单的,依次串行即可。 ...
  • 分布式任务编排调度框架设计

    千次阅读 2018-09-18 16:53:18
    原本一个人可以轻松维护十几台甚至几十台服务器:写几个常用的监控和配置下发脚本、或者利用cronTab制作几个定时任务就可以搞定。当服务器的数量由几十上升到几百,几千时,量变就引起了质变;而且随着应用数量的...
  • 并发编程中我们经常创建异步线程来执行任务。但是,当异步任务之间存在依赖关系时,使得我们开发过程变得更加复杂。比如: 1、线程2依赖于线程1的执行结果 2、线程3依赖于线程1和线程2执行结果的合并 要实现以上...
  • cmdb/堡垒机/webssh/主机管理/云主机/Devops/任务编排/自动化运维 本次向大家介绍是的 chinatime,瓷器时代智能运维工具aiops 功能说明 统一身份验证 资源统一管理,防止身份冒用 职权管控 账号管控 运维账号唯一性,...
  • 任务编排的应用场景 任务类型 任务编排并不局限于HSF任务,由于框架仅要求传入的是一个函数,通过函数进行抽象,可以支持任意类型的任务编排,例如:HSF、MetaQ、Tair、DB等。 任务编排形式 下单页的例子是串行&...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,211
精华内容 484
关键字:

任务编排