-
Notifications
You must be signed in to change notification settings - Fork 670
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
RFC into RFC #5653
RFC into RFC #5653
Changes from 1 commit
37255a1
bcdbf5f
f1c2231
f8d4992
e8a44b4
452538a
24a6e4e
14eaa16
44c701e
5f9abb1
2eede89
c8be3e4
934f5c1
6d58c73
8380f84
6568582
2528de7
6a39af7
674367f
1ac8bbe
8ef5ea9
dd67ff0
6be49e8
ab95f7e
b03e86d
9955256
734d6f3
b36556e
c7d1463
6159c27
80ccda3
4a90440
7287470
2ba277f
30b1675
ed23620
3004af4
d0ed6c4
1757750
c899586
0095165
35797ec
2ca3111
e8588f3
7e99ba4
6f0c274
a521dd0
de61bd0
c64b5e3
6b74673
8f0cd02
575a2a1
e3e614a
fb52e31
4ff2707
0ffab4a
8c5aac6
8eb7b0d
6b03731
f0d645b
5c77765
876999c
b79cd51
c77e2c3
8a8bbc0
9853abe
95e9ac8
f32132b
6ebcb86
1f0a4f2
ce0fd45
5470f3f
40dccab
ec3f38b
defacc1
8cad4ed
79a1992
00cad51
a6b32f9
88a2f50
5350c42
b55026e
f59e5ae
8cc9617
8dd8b05
0a1c82c
ccf9473
b3c746f
dd022b5
f5c228f
bd3ed0d
41ee314
5cfd004
de9a5c8
8db9901
f05acc7
46db95b
b36a1f3
cb57beb
43c0f1a
41b1b84
aa1f211
c0f5b10
ee6037b
2f38d65
7b82397
4dd5f3c
11fbeca
add971e
e506d19
9e41df2
16d54de
31802c7
519080b
96acc5c
2f1f813
1384b32
16d2b14
458da5c
7d2f0d0
cfaedce
2f7bedf
317ad30
c1eddad
8a61252
2143948
95196af
0583f77
470621e
5f9abaf
ba3647f
d04cf66
1078e09
75b33f8
22d81c6
715496a
1e61f4e
f08eb47
9ffc54f
5a81e76
fceb78f
25c3596
38883c7
cd37d1b
15e321b
bd2f9a8
266beda
3f4c2c8
9484e36
653ca85
9b78125
bba8c11
7d788cb
02bf85f
59e18d1
1abdd94
791471c
de415af
8c8e4f8
ba88e82
297cdf8
16e7780
f87a049
c10346d
4cb1473
f54b74e
87db0a3
2334d3f
ef6d491
ed40a94
8b71469
8805613
242303b
f1e511d
d5744da
e1d9c5c
3ee7120
f715341
5ab247f
37fe0a3
12bd353
dc6060d
5c70453
5cc7f58
83daf56
ce5eb03
b592177
c97a0e9
4643e2a
5b0d787
9b2a04b
c512571
2407e90
fc1c92c
2b0e8ef
f075b34
5c33464
e13bfe3
b63ce0e
b7e6959
b171b51
81afb76
c1563d7
220d594
94af58f
0cddc15
03a1c9e
9638db0
0b39839
fe879f2
337088e
02a0d2e
71779b3
3082cd3
63f8307
a07753e
4514860
1f26055
1e54d21
07d3cfc
6292dec
ef27b29
30d3314
9d0d67a
d6da838
025296a
01ecd0a
92dca29
45e287a
b18449e
17719e2
89fd084
89a70fb
7e16ff4
b6bc902
1124ea9
0a441a9
4014bbd
8156b1c
43c9d94
91d14b7
1de1b50
52322d0
96bbf7e
5be4545
a13a63d
736e338
9cfb4e3
37b4e13
e89f434
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,32 +4,77 @@ | |
|
||
- @wild-endeavor | ||
- @EngHabu | ||
- @katrogan | ||
|
||
## 1 Executive Summary | ||
|
||
Flyte depends on a series of `inputs.pb` and `outputs.pb` files to do communication between nodes. This has typically served us well, except for the occasional map task that produces a large Literal output. We sometimes also run into this issue for large dataclasses. This RFC proposes a mechanism that allows the offloading of any Literal, which would be done only of course for now for size reasons. | ||
Flyte depends on a series of `inputs.pb` and `outputs.pb` files to do communication between nodes. This has typically served us well, except for the occasional map task that produces a large Literal collection output. This large collection typically exceeds default gRPC and configured storage limits. We sometimes also run into this issue for large dataclasses. This RFC proposes a mechanism that allows the offloading of any Literal, to get around size limitations for passing large Literal protobuf messages in the system. | ||
|
||
## 2 Motivation | ||
A [cursory search](https://discuss.flyte.org/?threads%5Bquery%5D=LIMIT_EXCEEDED) of Slack history shows a few times that this has come up before (and I remember some other instances, I think that search term just wasn't included). This is something that we've historically addressed by just increasing the size of the grpc message that's allowed, but this is an unsustainable solution. | ||
A [cursory search](https://discuss.flyte.org/?threads%5Bquery%5D=LIMIT_EXCEEDED) of Slack history shows a few times that this has come up before (and I remember some other instances, I think that search term just wasn't included). This is something that we've historically addressed by just increasing the size of the grpc message that's allowed, but this is an unsustainable solution and severely reduces the utility of large-fan-out map tasks. | ||
|
||
## 3 Proposed Implementation | ||
We propose configuring propeller to offload large literal collections, using the following config | ||
|
||
### 3.1 Offloaded Literal IDL | ||
To the `Literal` [message](https://github.com/flyteorg/flyte/blob/cb6384ac6ea60f8b9421a71cfda4279f3579d3cb/flyteidl/protos/flyteidl/core/literals.proto#L95), add a new field called `starp` that will point to a location in the "metadata" bucket of the Flyte backend. The offloaded bytes should be deserialzable into a `Literal` object. | ||
```yaml | ||
type LiteralOffloadingConfig struct { | ||
Enabled bool | ||
// Maps flytekit SDK to minimum supported version that can handle reading offloaded literals. | ||
SupportedSDKVersions map[string]string | ||
// Default, 10Mbs. Determines the size of a literal at which to trigger offloading | ||
MinSizeInMBForOffloading uint64 | ||
// Fail fast threshold | ||
MaxSizeInMBForOffloading uint64 | ||
} | ||
|
||
``` | ||
|
||
Questions: How will things like metadata be handled? Should they be merged? What should be in the `value` field of the main parent Literal? | ||
### 3.1 Offloaded Literal IDL | ||
Update the `Literal` [message](https://github.com/flyteorg/flyte/blob/4a7c3c0040b1995a43939407b99ca3e87b1eb752/flyteidl/protos/flyteidl/core/literals.proto#L94-L114) | ||
like so | ||
|
||
```protobuf | ||
message Literal { | ||
oneof value { | ||
// A simple value. | ||
Scalar scalar = 1; | ||
// A collection of literals to allow nesting. | ||
LiteralCollection collection = 2; | ||
// A map of strings to literals. | ||
LiteralMap map = 3; | ||
} | ||
... | ||
// ** new below this line ** | ||
// If this literal is offloaded, this field will contain metadata including the offload location. | ||
string uri = 6; | ||
// Includes information about the size of the literal. | ||
uint64 size_bytes = 7; | ||
} | ||
|
||
``` | ||
|
||
### 3.2 Flyte Propeller | ||
* When writing map task outputs, depending on the size, Propeller will need to offload the LiteralCollection after constructing it, and create a new Literal for downstream tasks to use, with the | ||
* Also Propeller will need to check the flytekit version of the map task. If it's an older version (i.e. before the change proposed in this RFC), and it's large enough to need to be offloaded, it should fail the task. The assumption here is that if the map task is of the older version then downstream tasks will probably also be of those older versions which won't know how to resolved these offloaded literals. | ||
Once offloading is enabled in the deployment config, flytepropeller can read from the [RuntimeMetadata](https://github.com/flyteorg/flyte/blob/f448a0358d8706a09b65b96543134f629327d755/flyteidl/protos/flyteidl/core/tasks.proto#L71-L87) in the task config to determine the SDK version. | ||
|
||
When writing outputs in the [remote_file_output_writer](https://github.com/flyteorg/flyte/blob/2ca31119d6b9258661a71f38e450f93b6692402c/flyteplugins/go/tasks/pluginmachinery/ioutils/remote_file_output_writer.go#L56-L84) the source code should detect whether the literal size exceeds the configured minimum and | ||
- if the task is using a newer SDK version that supports reading offloaded literals, offload the literal to the configured storage backend and update the literal with the offload URI and size. | ||
- if the task is using an older SDK version that doesn't support offloaded literals, fail the task with an error message indicating that the task output is too large and the user should update their SDK version. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's add a line to say downstream tasks also have to upgraded? that is, if you have a reference/remote task downstream that consumes the map task output, but it hasn't been updated, then it'll fail. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done, thanks |
||
|
||
### 3.3 Flytekit & Copilot | ||
Flytekit and Copilot will both need to detect that a Literal has been offloaded and know to download it. | ||
- in Flytekit this can be done by checking the `uri` field in the Literal message when converting a literal [to_python_value](https://github.com/flyteorg/flytekit/blob/e394af0be9f904fbf8be675eaa8b8cdc24311ced/flytekit/core/type_engine.py#L1134) | ||
- in Copilot, the data downloader [literal handling](https://github.com/flyteorg/flyte/blob/5f4199899922ca63f7690c82dfca42a783db64c3/flytecopilot/data/download.go#L219-L248) should fetch the value | ||
|
||
For large outputs (like large maps of large dataclasses), Flytekit should also know how to offload the data. This should be done transparently to the user. How will propeller know to fail though if propeller hasn't been updated? | ||
As a follow-up, we can also implement literal offloading in the SDK for conventional python tasks. Flytekit should also know how to offload the data. This should be done transparently to the user. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we cover that here? or is this only for map tasks for now? for the general case, we were going to go with the solution of propeller setting an environment variable that turns on offloading on the flytekit side? for erroring if things get too big, i don't know that there's a solution. We should just add a size limit asap in flytekit right @eapolinario? Some env var based setting with a 10MB default. If a literal is more than 10MBs then error. considering we don't know when we'll get to the general case, by the time we do, most users might've already upgraded. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we're leaning towards not tackling the implementation bits for this proposal but I think it's okay to cover future work here? Updated to include the bits about failing fast here for too-large literals, thank you! |
||
|
||
**Open Question:** How will flytekit know to fail though if propeller hasn't been updated? | ||
|
||
### 3.4 Other Implications | ||
Does console need to change at all? | ||
#### Flytekit Remote | ||
Flytekit Remote will need to be updated to handle offloaded literals. In order to fetch offloaded literals by URI, users must now authenticate with their cloud provider on their machines using a role which has read access to the _metadata bucket_. | ||
|
||
#### Console | ||
Console code should show the offloaded literal URI and gracefully handle nil Literal [values](https://github.com/flyteorg/flyte/blob/4a7c3c0040b1995a43939407b99ca3e87b1eb752/flyteidl/protos/flyteidl/core/literals.proto#L96-L105). | ||
|
||
## 4 Metrics & Dashboards | ||
|
||
|
@@ -45,15 +90,17 @@ Alternate suggestions that were proposed include | |
|
||
* For map tasks, change the type of the output to a Union of the current user defined List and a new Offloaded type. We felt this would be a bit awkward since it changes the user-facing type itself (like if you were to pull up the map task definition in the API endpoint). It's also not extensible to other types of literals (maps of large dataclasses for example). | ||
|
||
* Build off of the input wrapper construct that's still in PR. The idea was to have the wrapper contain in large cases, a reference to the data, and in small cases, the data itself. We didn't fully like this idea because the entire input set or output set needs to be offloaded. | ||
* Build off of the input wrapper construct that's still in [PR](https://github.com/flyteorg/flyte/pull/4298). The idea was to have the wrapper contain in large cases, a reference to the data, and in small cases, the data itself. We didn't fully like this idea because the entire input set or output set needs to be offloaded. | ||
* If the task downstream of a map task takes both the output list, along with some other input, after creating and upload the large pb file for the map task's output, Propeller would need to re-upload the entire large list or map (one time for each downstream task). If the offloading is done per literal, Propeller can just upload once and use. | ||
* Modify the workflow CRD to include the offloading bits so that they're respected at execution time, and serialized at registration time. This is a bit heavier handed than just respecting the SDK version | ||
|
||
## 7 Potential Impact and Dependencies | ||
|
||
There's a couple edge cases that will just not work. | ||
|
||
* If the map task is of an older flytekit version but for some reason the downstream task is of a newer version, Propeller will fail unnecessarily. | ||
* If the map task is a newer version, but the downstream task is an older version, the downstream task will fail correctly. | ||
* If workflow is using an older SDK version and launches a child workflow with a newer SDK version, the parent workflow will fail to resolve the child workflow outputs | ||
|
||
Are there concerns about the fact that if we're offloading data once, and then sharing the pointer, we're no longer copying-by-value? Does this break any of the guarantees of Flyte and will we need to be more careful in the future around other changes to avoid issues? | ||
|
||
|
@@ -65,5 +112,7 @@ Is there anything around sampled data, or automatically computed actual metadata | |
|
||
## 9 Conclusion | ||
|
||
*Here, we briefly outline why this is the right decision to make at this time and move forward!* | ||
Moving to literal offloading fixes a common and frustrating pain point around map tasks. It's a relatively simple change that should have a big impact on the usability of Flyte. | ||
|
||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is size important again? I mean there's other metadata as well (etag information). The assumption here is that size is super important so we want to be able to show that without making a head call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
general consensus seemed to be this is useful, I guess it's nice for clients who want to decide whether to pull massive datasets?