在不终止任务的情况下缩减 Concourse 工作人员

Scale-in Concourse workers without killing tasks

每个工人运行多个任务。如果我们有很多任务,我们将需要多个工人。为了节省资源,我们希望根据供应(备用容量)和需求(待处理的任务)弹性地调入和调出工作人员。

横向扩展很容易:添加更多节点,它们向 TSA 注册并开始工作。

缩小规模比较棘手:需要等待其任务完成才能杀死工作人员的实例。否则他们将不得不重新启动另一个工人。这对于小任务来说很好,但对于可能无法接受的较长任务。

AWS 上的一种可能解决方案是使用 Autoscaling Lifecycle Hooks to synchronously tell the worker to not accept any more tasks and return when all are finished, then kill it. The Concourse Worker API 但是没有任何此类操作。

有没有办法安全地缩减 Concourse 工作人员?

如果答案是 "don't worry, Bosh will take care of it" 我想知道这些机制是什么,因为我可能不会使用它。

您必须在运行 ATC 的主机(即大厅调度程序和 Web 界面)上从命令行使用 concourse 二进制文件:

concourse --help
Usage:
  concourse [OPTIONS] <command>

Application Options:
  -v, --version  Print the version of Concourse and exit [$CONCOURSE_VERSION]

Help Options:
  -h, --help     Show this help message

Available commands:
  land-worker    Safely drain a worker's assignments for temporary downtime.
  retire-worker  Safely remove a worker from the cluster permanently.
  web            Run the web UI and build scheduler.
  worker         Run and register a worker.

所以看起来你可以挂钩到自动缩放生命周期服务调用 land-worker 然后 retire-worker 的东西(不确定 retire-worker 是否足够),一旦你弄清楚您想停用哪个工人...

当你旋转同一个worker时,你可能需要小心worker的名字,我好像记得有时候ATC会混淆,你将不得不试验一下(是否可以保持相同的名字或更改它)。

您可以在您的 Concourse worker ASG 上创建一个生命周期挂钩:

    Type: AWS::AutoScaling::LifecycleHook
    Properties:
      AutoScalingGroupName: !Ref ConcourseWorkerASG
      DefaultResult: CONTINUE / ABANDON
      HeartbeatTimeout: 900 # 15 minutes for example
      LifecycleHookName: lchname
      LifecycleTransition: "autoscaling:EC2_INSTANCE_TERMINATING"

使用脚本让工人退休,类似于

lch.sh

#!/bin/bash

TYPE=$(cat /opt/concourse/type)
tsa_host=zz
instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id/)
lifecycleState=$(aws autoscaling describe-auto-scaling-instances --instance-ids $instance_id --query 'AutoScalingInstances[0].LifecycleState' --output text --region eu-west-1)

if [ "$TYPE" == "worker" ]; then
  if [ "$lifecycleState" == "Terminating:Wait" ]; then
    asg=$(aws autoscaling describe-auto-scaling-instances --instance-ids $instance_id --query 'AutoScalingInstances[0].AutoScalingGroupName' --output text --region eu-west-1)

    /opt/concourse/concourse/bin/concourse retire-worker \
        --name $HOSTNAME \  
        --tsa-host ${tsa_host}:2222 \
        --tsa-public-key some_tsa_host_key.pub \
        --tsa-worker-private-key some_worker_key

    sleep 5m

    systemctl stop your_concourse_service

    aws autoscaling complete-lifecycle-action \
      --instance-id $instance_id \
      --auto-scaling-group-name $asg \
      --lifecycle-hook-name "lchname" \
      --lifecycle-action-result "CONTINUE" \
      --region eu-west-1
  fi
fi

然后安排一个 cronjob,例如通过 Ansible:

- name: List lch.sh as cronjob
  cron:
    name: "check asg lch for retiring the worker"
    minute: "*/5" # run every 5 minutes
    job: "/opt/concourse/lch.sh"