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
Prevent functions from stealing cycles #848
Comments
/kind spec This is a good discussion; I'm going to pull out the CPU freeze discussion from the runtime contract and reference this issue. |
Another motivating problem: someone manages to get cryptocoin mining logic into my function or base image. I want that code to only be able to run while a request is being served or event processed. It won't prevent the mining logic from executing, but it limits the scope and increases the odds of detection via latency/throughput metrics. |
If someone can modify your image or function, then there is nothing to stop them from just delaying an HTTP request/response to the max time limit. |
@jhanley-com you're right, but I think the key is that delaying the HTTP response will quickly show up in response time metrics. @markusthoemmes was pointing out that in the execution model, the request could be processed normally and unobserved background work could continue without being connected to any request, until scale down occurs. |
thx @markusthoemmes -- this is a great topic. In my mental model, the issue you're raising has some sub-aspects:
Long story short -- as long as the definitions for when metering starts/ends are clearly defined, avoiding stealing of cycles becomes a much easier topic. Because then the problem is reduced in my mind to whether i as a provider go with a suspend/remove or container-provisioning-time-optimization strategy (or both combined) . The former one is pretty proven and can be done today (with a few technology options, as you laid out above), the latter would require some more technical groundwork and therefore doesn't seem like a super short-term solution (i would love it to be wrong here -- if there is a competitive technology out there, pls bring it up). WDYT? |
Issues go stale after 90 days of inactivity. Send feedback to Knative Productivity Slack channel or file an issue in knative/test-infra. /lifecycle stale |
Stale issues rot after 30 days of inactivity. Send feedback to Knative Productivity Slack channel or file an issue in knative/test-infra. /lifecycle rotten |
Rotten issues close after 30 days of inactivity. Send feedback to Knative Productivity Slack channel or file an issue in knative/test-infra. /close |
@knative-housekeeping-robot: Closing this issue. In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Problem
FaaS platforms in general are heavily request driven. Resources are handled on a per-request basis and metering/billing is usually also done per-request. But what happens if a user breaks out of the request's context?
An example:
The "request" will be immediatly closed in the above case, but if the container is still running, the function will steal cycles by running
crunchNumbers()
asynchronously. This is valid for any language with support for asynchronous tasks.This problem is especially apparent in a multi-tenant platform, because one tenant can cause heavy noisy-neighbor effects due to the "untracked" nature of her system usage then.
Possible solutions
(This is of course an incomplete list and up for discussion)
1. Alternative metering
@grantr rightfully mentioned in a Slack discussion, that the platform could choose to meter based on the runtime of the container itself and not per-request. That would indeed solve this issue but I'm not sure if that'd be accepted in the FaaS world of only "paying for what you use on a millisecond basis". The scale-to-zero timeout would then determine the overhead of what I'm always paying, which may or may not make a dent in my bill.
2. Process freezing
A unix process can be frozen and thus prevented from consuming any cpu resources. There are several alternatives on how to do this, including the cgroup freezer and CRIU. A
pause
/resume
command is built-in intodocker
,containerd
/runc
andkata
.gvisor
doesn't seem to support this OOTB.pause
/resume
is not part of the OCI spec. Kubernetes (today) does not expose a command to pause a container via its CRI.Using any of the above solutions (some are much more involved than others) a container could be frozen in a very short timeframe after the last request finished "officially".
One more wrinkle is, that process freezing only prevents consumption of cpu resources, but leaves the process' pages in memory. A solution could be to use a more sophisticated checkpoint tool rather than just freezing the process. @jchesterpivotal mentioned previous work around that in riff.
As an example implementation, OpenWhisk on Kubernetes goes rogue on its executor nodes and talks directly to the underlying container daemon (implemented for
docker
andcontainerd
) to invokepause
/unpause
respectively. As a rough estimate, both operations take 15ms to complete.It'd be desirable to have that operation baked into the K8s CRI.
3. Make container creation/removal so fast it doesn't matter
@julz mentioned that we could also make container creation/removal so fast, that cycle stealing becomes a non-issue. That would translate to a very low scale-to-zero timeout. That's certainly true, a cold start might involve more than just creating the container though (setting up connections in the function etc. etc.), so I'm wondering how far we can push the boundary on that end.
Certainly, having a container creation/removal lifecycle so fast makes the whole container lifecycle easier (less states to be in) and would possibly reduce overall complexity, so that'd be the nicest of them all.
The text was updated successfully, but these errors were encountered: