jenkinsci / ec2-fleet-plugin

The EC2 Fleet plugin launches EC2 instances as worker nodes for Jenkins CI server, automatically scaling the capacity with the load.
https://plugins.jenkins.io/ec2-fleet/
Apache License 2.0
111 stars 81 forks source link

NoDelayProvisionStrategy won't provision after scaling down to 0 instances in auto scaling group #425

Open cccCody opened 10 months ago

cccCody commented 10 months ago

I think this is the same issue as https://github.com/jenkinsci/ec2-fleet-plugin/issues/180

Describe the bug I'm currently trying to move from ec2-plugin to this plugin, but I'm seeing that the final stage of my build doesn't ever get an executor. My build looks roughly like this:

  1. build step on a single node
  2. test in parallel on several nodes (150 of them!)
  3. collect coverage reports on a single node

Everything works nicely until the last step, where it gets stuck on:

All nodes of label ec2-fleet are offline

When I check the system logs, I see this on repeat:

Nov 21, 2023 3:08:12 PM FINE com.amazon.jenkins.ec2fleet.NoDelayProvisionStrategy apply
label [ec2-fleet]: queueLength 1 availableCapacity 1 (availableExecutors 0 plannedCapacitySnapshot 1 additionalPlannedCapacity 0)
Nov 21, 2023 3:08:12 PM INFO com.amazon.jenkins.ec2fleet.NoDelayProvisionStrategy apply
label [ec2-fleet]: No excess workload, provisioning not needed.

I'm especially suspicious of plannedCapacitySnapshot 1, which, if I'm reading the source code right, seems to mean that it thinks it's already started scaling up another node (and is waiting for it to come online?) but it never does.

Other misc info, may or may not be relevant:

Environment Details

Plugin Version? 3.1.0 (latest as of opening this)

Jenkins Version? 2.426.1 (latest LTS version as of opening this issue)

Spot Fleet or ASG? ASG

Label based fleet? no

Linux or Windows? linux

cccCody commented 10 months ago

I was able to get it to work for a single run by setting "Minimum Spare Size" to 1, but then when I started another build after that, it hit the issue when provisioning the first node that time. It seems like, more generally, this is an issue with scaling out shortly after scaling in.

icep87 commented 10 months ago

We are also seeing this issue. When there are no agents available, meaning they are all scale down. The plugin won t spin up agents at all.

In the logs it says:

Nov 22, 2023 7:02:32 PM FINE com.amazon.jenkins.ec2fleet.NoDelayProvisionStrategy
label [linux]: queueLength 1 availableCapacity 1 (availableExecutors 0 plannedCapacitySnapshot 1 additionalPlannedCapacity 0)
Nov 22, 2023 7:02:32 PM INFO com.amazon.jenkins.ec2fleet.NoDelayProvisionStrategy apply
label [linux]: No excess workload, provisioning not needed.
Nov 22, 2023 7:02:32 PM FINE com.amazon.jenkins.ec2fleet.NoDelayProvisionStrategy
label [powerful]: queueLength 1 availableCapacity 1 (availableExecutors 0 plannedCapacitySnapshot 1 additionalPlannedCapacity 0)
Nov 22, 2023 7:02:32 PM INFO com.amazon.jenkins.ec2fleet.NoDelayProvisionStrategy apply
label [powerful]: No excess workload, provisioning not needed.

I'm wondering why it actually says that there is availableCapacity when clearly there is none and no scale up is triggered.

icep87 commented 10 months ago

@cccCody Did you manage to find the cause of this?

taka-papa commented 9 months ago

I encountered a similar problem I tried the jenkins script console

Jenkins jenkins = Jenkins.getInstance()

jenkins.getLabels().each { Label label ->
    def nodeProvisioner = label.nodeProvisioner
    def pendingLaunches = nodeProvisioner.getPendingLaunches()

     if (pendingLaunches.size() == 0) {
        return
     }

    println("Label: ${label.name}")
    pendingLaunches.each {
        println("  Planned Node: ${it.displayName}, Executors: ${it.numExecutors}")
    }
}

Output

Label: xxx
  Planned Node: NodeName-xx, Executors: 1
  Planned Node: NodeName-xx, Executors: 1

There were no jobs running Restarting jenkins solved it

opajonk commented 8 months ago

I think we are running into the same issue here, with the NoDelayProvisioningStrategy. Digging around in the issues I found https://github.com/jenkinsci/ec2-fleet-plugin/issues/149 - this one reads like a regression. Could that be?

Restarting Jenkins "fixed" the issue, but I suspect it will come back. Then I will run the script console snippet of @snowman-papa to see if we also have "stuck planned" machines.

pawel-t commented 7 months ago

I have faced the same issue on 3.2.0.

Once we have switched to ASG from SpotFleet. My SpotFleet was setup with Min = 0 and Spare = 0 and after it scaled down to 0 instance. For 1.5h it didn't scale up while jobs were waiting in queue.

I needed to increase min and spare in order it to work.

ldmonkey commented 5 months ago

We downgraded the plugin from 3.2.0 to 3.0.1. Waiting for a fix for this issue.

icep87 commented 2 months ago

The issue is actually occurring in the NodeProvisioner. We could not find any errors of failed launch in the EC2-Fleet plugins. Instead, the NodeProvisioner has stale nodes planned. This could be fixed by the plugin by monitoring which nodes are planned by the NodeProvisioner and removing them if they haven’t come up after a defined time. Currently, NodeProvisioner does not provide any kind of timestamp indicating when the planned node was requested. Making it quite hard to find without a function that can monitor it.

As mentioned by @taka-papa, you can run the script to see if there are any planned launches of nodes. If you have staled nodes and want to solve the issue and avoid restarting Jenkins, here is a script that will help you remove the planned launches.

import jenkins.model.Jenkins
import hudson.model.Label
import hudson.slaves.NodeProvisioner

Jenkins jenkins = Jenkins.getInstance()

def labelToReset = "LABEL OF THE CLOUDNODES"

jenkins.getLabels().each { Label label ->
    if (label.name == labelToReset) {
        def nodeProvisioner = label.nodeProvisioner
        def pendingLaunches = nodeProvisioner.getPendingLaunches()

        if (pendingLaunches.size() > 0) {
            println("Cancelling pending launches for label: ${label.name}")
            pendingLaunches.each { launch ->
                launch.future.cancel(true)
                println("Cancelled launch: ${launch.displayName}")
            }
        } else {
            println("No pending launches to cancel for label: ${label.name}")
        }
    }
}

return "Cancellation process completed."
wosiu commented 2 months ago

@icep87 What do you mean by "(...) has stale nodes planned"? Any chances you dig into why they don't "come up after a defined time"?

icep87 commented 2 months ago

@wosiu What I mean is that the nodes get stuck in PendingLaunch. They never leave that state. I could not find any errors in the logs, and as this issue is hard to reproduce it makes it difficult to debug. But as soon as I have the chance I will try to debug it.

For example we haven't had this issue for more than 2 weeks now.

PW999 commented 3 weeks ago

I'm constantly having issues with the NoDelayProvisionStrategy.

Right now it says the target is 3 image

Yet in AWS the desired size is 1 image

and there is a single instance running, but it doesn't show up in Jenkins at all. So if you need any specific debug logs, just let me know ;)