-
Notifications
You must be signed in to change notification settings - Fork 39.2k
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
Proposal: Long term evolution of runtime.Scheme / conversion.Scheme #7111
Comments
@lavalamp @bgrant0607 at minimum. |
/sub |
1 similar comment
/sub |
I agree with the problem statement. One quibble, I think we want the client to by default unmarshall into a versioned type, otherwise it's difficult for non-kubernetes components to write code that stays working for more than a day. Apiserver/scheduler etc still need to work with our unversioned objects. This is already possible today--since we support DecodeInto--but we don't take advantage of it. |
Agreed - I will clarify. ----- Original Message -----
|
I agree we need to support a mix of multiple api prefixes and versions. We should consider moving generic objects like List and Status to their own api prefix and version. I agree that we should decouple encoding and schema. Currently our only conversions between versioned structs must transition through the internal representation. I don't want to support O(n^2) conversions, so that seems like a good property to keep. In general, clients should use a versioned rep and should not round-trip: #4874, #3955. I disagree that get, describe, etc. need to use the internal rep. We should assume the v1 API is stable and just use that until a new stable version is available. Cross-version conversion tools are a special case, not an every-day use case. |
|
Server capabilities -- #2953. A version-specific renderer or generator could pull the swagger and check for the presence of the field(s) needed. |
That seems overly complex for 3rd party clients (i.e., no one will do it for small ruby client, but they still have the problem that their script breaks when it's run against an older server). Is a simple schema version per object type (possibly returned with the request) or per version feasible? This could be worked into conversion (everytime we regenerate the conversions, a number has to be incremented). ----- Original Message -----
|
Some other points to argue about:
|
Also, we should consider adding the API prefix to the API version (or allowing it be optional) |
Related: #4855 |
API prefix: Or make that yet another field? I agree that we need it in some form. |
I wasn't sure - technically "api/v1beta1", "pods/v1beta1", "kubelet/v1beta1" are all unique versions (nothing says a version can't have a qualifier in it). Or we can do "kubelet-v1beta1" which is easier on the eyes - the slash just seemed somewhat nice because we could tie that to prefix and say that by convention APIs should have a version prefix that matches their path prefix so that you can guarantee you could host multiple API groups on the same server. ----- Original Message -----
|
I'm fine with slash. |
Of course, as soon as you say that, I start wondering whether it's the Kind that should be prefixed - "k8s.io/Pod". That way probably lies madness. ----- Original Message -----
|
The kind is specific to a particular version at a particular prefix -- version has a collection of kinds and prefix has a collection of versions. Really it's prefix/version/kind that is the identifier of the schema, so it either makes sense for prefix to be a separate field, like version, or as a prefix to version. We could add an even broader collection to prefix, like k8s.io/apiprefix/version/kind, but I wouldn't go there yet. |
A little more abstract: domain/apigroup/version/kind |
That makes sense to me. ----- Original Message -----
|
Related issue: Provider/domain field (e.g., kubernetes vs. openshift) for federated configuration -- https://github.com/projectatomic/atomicapp |
I'm also going to remove the use of empty string to mean "internal" and replace it with a constant "__internal", and do the same for "__unversioned" (create a special category in scheme which means - this object can be converted to any version as is) |
Design points to how codecs are retrieved: Different use points of codecs today and the reqts. of each: Rest server needs a codec for the endpoint, to handle the runtime.Object returned by the method. It needs to (per request) find one based on content type (in different directions, clients should be able to post json and get proto). It may need to return arbitrary objects (template process). It needs to handle runtime.Unknown cleanly. Kubectl generic handler needs each RestMapping to have a codec that can talk to the server (json for now). It does not need to do conversion, but does need to extract metadata. Kubectl resource builder needs the catch all decoder that can read anything the client supports (json and proto) and may have additional info about the object such as filename or content type, and the ability to get a codec to write files to output. Code internally (Kubelet) that reads files from disk needs the same thing resource builder needs (catch all decoder). Client libraries should hide details of protocol and version negotiation - some clients (templates, lists) may send/receive arbitrary objects the codec is not aware of. Client libraries need a parameter codec which is also hidden. Misc notes: Versioned client libraries may need to deal with opaque object types in memory (v1.List) - currently our versioned objects do not allow those types to be worked with. We may need a way to work with runtime.Object in an external version but still guarantee the object gets serialized prior to putting over the wire (which requires a serializer that knows the destination version). Will punt on this for now until we get closer to versioned client. We could simply have an Object in runtime.RawExtension and require the caller to do the heavy lifting of serializing it while they work on it. Serializers own the responsibility for setting type meta because serialization (how types are represented on the wire) may alter encapsulation of types: ie protobufs are most efficiently wrapped in a type envelope, while json can be efficiently extracted. Some clients may need to deeply control / wrap serializers - it should be possible for clients to override the native serialization (similar to overriding negotiation). |
I'm currently trying to get the If you could keep those types in mind as you do your work, I think we'll end up fine.
Empty string as the |
Empty string for version. Group would be required for everything except On Mon, Nov 30, 2015 at 8:27 AM, David Eads notifications@github.com
|
@kubernetes/goog-csi @krousey @caesarxuchao @nikhiljindal |
Also @wojtek-t Codec needs to additionally be able to go to/from url.Values for query parameter versioning, as discussed elsewhere. |
I split that into ParameterCodec - I think wire serialization and URL On Mon, Nov 30, 2015 at 3:54 PM, Daniel Smith notifications@github.com
|
I agree. |
After #17922 lands, the next change will be to remove conversion/scheme, and fold that function into runtime/scheme. A scheme will use a Convertor, a DeepCopier, and a set of maps for its type registry to handle anything that deals with Kind, Group, and Version and how Go structs are mapped between them. |
Much of this has been done. @smarterclayton is there anything further you want to do for 1.2 here? |
Let me write up the new list and close this. I think we did the first
cleanup, and later changes will be to enable external API groups,
performance, and extracting the core packages.
|
I had a revelation right now. We're trying to leverage native objects too much. We want runtime.Object to be a wrapper, not a native type. We want to do things like:
basically, we want runtime.Object to stop being an interface, and start being a smart wrapper
Basically all of our structs would then simply go back to being dumb structs. Codec would be responsible for setting up smart objects. This also helps us achieve our performance goals of avoiding internal types, avoiding conversions, avoiding casts, etc. |
Tim brought this up a while ago so it's not a unique idea, but I think that's what I would close this issue with - we've reached the limits of what our current approach can do, and we need to take the next step. |
I think that would allow us do more cleanly nest and handle arbitrary |
That's a very interesting idea. I'll think about that some more. |
I still want to do smart objects. But API server perf is not gating right now, so on the back burner. |
Issues go stale after 90d of inactivity. Prevent issues from auto-closing with an If this issue is safe to close now please do so with Send feedback to sig-testing, kubernetes/test-infra and/or |
/remove-lifecycle stale |
/remove-kind design
|
Continued from #2306
A runtime.Scheme combines a few concepts:
In order to better support multiple API patterns grouped together (Kubernetes user API, Kubelet API, OpenShift API, future extension API) these assumptions will start to break down.
Known problems:
A 3rd party API may have a "v1". That API may define an object "List", that they want to convert to a Kubernetes "v1" "List". In our current setup, it would be impossible for those two API objects to be compiled into the same runtime.Scheme (because they both want to reserve "v1/List" to different objects). It would also be impossible to convert from the third party API "v1" "List" to a Kubernetes "v1" "List" because they exist in different conversion schemes.
A 3rd party API may want to reuse the Kubernetes "Status" object in their own API schema for their version "v1beta1". It would be impossible for them to use the "v1" Kubernetes status object without having a separate runtime.Scheme, but their client library may want to convert both Kubernetes v1 objects to their internal type.
Finally, we may want to introduce new serialization types for objects - Gob, Protobuf, Msgpack, JSON+snappy, for various use cases (more efficient storage). The coupling of JSON to runtime.Scheme complicates those conversions or makes them less efficient.
Types of problems we want to solve:
Codec
. There may be many codecs.map[string]interface{}
(generic JSON object representation) or amap[string][]string
(url.Values) into a versioned Go struct, which is dependent on a type of marshaling (i.e. following JSON rules, or Query parameter rules).Consumers:
Still a WIP, trying to gather thoughts.
The text was updated successfully, but these errors were encountered: