-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement specialized executor for fault injection #2742
Comments
Not having a When you know how long the disruption will be, why is having a Or, to put it another way, why isn't this problem solvable with JS code and needs changes in k6 fundamentals? For example, a small JS helper can generate both the |
Maybe I did not explain myself correctly. The problem is not having
Given that every scenario that runs a chaos will have this same issues described above, delegating it to a helper function that must be imported from a js library along with the xk6-disruptor doesn't seem the best developer experience, in my opinion. Not all what is possible is convenient. However, if I could inject this scenario from the extension itself, that could be a good option, but I'm not sure if that is possible. That is, if I could call the inject disruption method in the
This executor will basically be a restricted version of the shared iterations executor that does not allow unsafe parameter combinations by removing those parameters. I don't see it as a "change in k6 fundamentals!. |
I updated the proposal to clarify that the requirement is not to remove the |
I updated the proposal for providing more context on the use case that raised this requirement. |
I understand that the primary goal the proposal for adding the A question about the assumptions:
I'm not a fan of helper functions for creating scenarios because they feel a little hacky, but to illustrate it, this is how it could be implemented today without making core changes. import { chaosScenario } from 'https://jslib.k6.io/chaosUtils/1.0.0/index.js';
export function disrupt() {
// delay traffic from one random replica of the deployment
const fault = {
average_delay: 50,
error_code: 500,
error_rate: 0.1
}
podDisruptor.injectHttpFaults(fault, 60) // second argument is the duration of the disruption in seconds
}
export const options = {
// This scenario executes the tests
scenarios: {
load: {
executor: 'constant-arrival-rate',
rate: 100,
preAllocatedVUs: 10,
maxVUs: 100,
exec: "default",
startTime: '0s',
duration: "60s",
},
disrupt: chaosScenario({exec: "disrupt"}) // all other params are default but can be overriden
}
} The downside of implementing a Another approach is implementing the |
Totally agree. I though of using that name, but to be honest, the only use case I'm aware now that would require this only-once execution is chaos.
This is possible, indeed. I can think about some failures like killing pods that may follow this pattern. But I think this can be easily implemented using a loop and a sleep instead of using the fixed rate executor, for example. What worries me more is the possibility of running more than one fault injection concurrently from multiple VUs. Maybe, the goal should be to find a mechanism that prevents multiple concurrent executions of the disruptor to happen, but I don't see any, considering a distributed execution environment except using some form of Kubernetes resource or using annotations in the targets, but both are complex to implement reliably.
I was also of this impression, but seeing your proposal, it looks interesting. I'm wondering if this function could be exported from the extension, instead of a JS library. Is there any technical restriction on this regard, like not been able to call functions from extensions from the |
Yes, of course, xk6 JS extensions (and built-in modules) primarily export JS functions that you can Lines 52 to 63 in 8a74171
Line 71 in 8a74171
You can do something like that to export a k6/lib/executor/shared_iterations.go Lines 19 to 30 in 8a74171
It's the same API that is used to register built-in executor types 😅 To be clear, we make no promises that this API won't change. In fact, it's quite likely to change (#1302), but even after we fix the module structure, there would be no obstacles to providing an official API for executor extensions (#2254). All of that said, I still think a custom executor type would be an overkill here, and the problem should be better solved some other way. For example, if the current way to specify scenarios and executor options seems to error-prone and unwieldy, we should probably design a better way to specify them instead of having a bunch of semi-duplicate executor types? The goal of the different executors is to express different ways of scheduling work (iterations) among a set of workers (VUs). Where there is some precedent for overlapping executors (e.g. Besides, this (and other similar things) seem like a completely plausible use cases that someone might want to test for:
Implementing it with a for-loop would potentially introduce inaccuracies and delays from the time the operation takes to complete, unless you carefully account for that. And accounting for it would be certainly more complicated than configuring an executor even with the current
I don't understand the issues here, sorry. If you have a scenario with a single VU and a single iteration (or 1 iteration every 30s or whatever), with execution segments k6 will never schedule more than 1 VU, regardless of how many instances you have. |
Hi @na-- Thanks your your extensive explanation. Really useful. Just a few comments/clarifications
My question was more in the line of any restriction about using the functions exported by an extension in the
That is right. If there is only one VU multiple iterations should be ok. My comment was regarding to the risk of opening the use of any scenario configuration because there is this strict restriction of only one VU at a time.
There was also another requirement regarding the
I don't think there's an issue with the executors from the perspective of generating load. As I mentioned before, I think the "problem" I was facing comes from the fact that faults are discrete events that occur at specific times during the execution of a test (generally, only once) and this seemed to me different from generating a workload. But after this discussion I think the solution is more in the side of providing a different UX in the disruptor than changing the way k6 schedules work. |
Yes, there is no restriction. We have to impose that restriction artificially, when we want some function to be used only in the init context. For example: Lines 66 to 71 in 8a74171
Or only in the VU context: Lines 142 to 146 in 8a74171
As you can see, the current way to ensure either is to check whether the VU |
At that stage, we don't have any plans to implement this in k6, so I'm closing this for now. |
Edit: More context added to the proposal
The xk6-disruptor extension provides functions that allow the injection of faults during the execution of tests. Injecting faults in running tests follows a pattern that is different from the common use case for k6, which consists in generating multiple requests to simulate a workload from one or more users. Injecting faults, on the contrary, require the execution of single events. Each of these events (a fault injection) should have a defined duration.
This is accomplished by using two scenarios: one for running the test and another for injecting the faults as in the example below. The scenario that injects the fault must invoke the fault injection logic only once, therefore a shared iterations executor is used specifying one UV and one iteration.
However, this approach has some issues:
duration
attribute. Therefore the duration is defined in the invocation to the function that injects the faults (injectHttpFaults
in the example below). To make things more confusing, if this duration is longer than10m
, themaxDuration
attribute of the scenario must be specified or it will be cancelled while the load scenario (the one injecting load) continues its execution, but without the fault injection, creating misleading results.To overcome this limitations, instead of reusing existing executor for this particular use case, it would be convenient to have a specialized executor that allows only one iteration in one VU and have
no defaultamaxDuration
,duration
attribute so it must be explicitly definedif required (most of the time, it should not be required).In this way, following the Poka-yoke philosophy introducing errors will be hard by design.Following this ideas, the example above would be implemented as shown in the code below (some code omitted for brevity):
Additionally, a
duration
attribute could be defined in the scenario and made accessible by means of the k6-execution api so that it could used as a default value for the duration of the disruption function. In this way the duration would be more explicit in the definition of the scenario.The text was updated successfully, but these errors were encountered: