-
-
Notifications
You must be signed in to change notification settings - Fork 320
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
protobuf encoding exploration #371
Comments
Now that our So, if we had an something like an alternative |
This is really three separate questions:
IMO, 2 is the big question that we need to start with. If Protobuf aligns better with K8s semantics (and IIRC it does), then switching to it might enable us to get rid of a bunch of the hacks in Regardless, we should probably at least try to keep @Arnavion in the loop before committing to anything. While an ecosystem split might end up inevitable due to backwards compatibility concerns, that would be a sad outcome and should probably be a strategy of last resort rather than a starting assumption. |
I'd looked into supporting protobufs instead of JSON before, and had found that upstream didn't want anything except golang code to use protobufs. I see https://github.com/kubernetes/api#recommended-use still seems to imply that.
That said, I assume whatever clients you found that do use protobufs are doing the double-(de)serialization themselves anyway? |
While that is a bit annoying, presumably that "just" means that we need to wrap Prost's serializer ourselves rather than relying on it directly. It doesn't seem to affect the actual object serialization, and still has to be stable(ish) since they can't just break old Go clients whenever either. |
So does using the |
FWIW: The official way to get the protos for a client seems to be through kubernetes-client/gen/proto, and kubernetes is definitely keen on us using that repo. I still have no idea how good the output is (it doesn't seem to like an up to date libprotobuf?), but might try to spend some time on it. |
Default output from Pod
/// Pod is a collection of containers that can run on a host. This resource is created
/// by clients and scheduled onto hosts.
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Pod {
/// Standard object's metadata.
/// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
/// +optional
#[prost(message, optional, tag="1")]
pub metadata: ::core::option::Option<super::super::super::apimachinery::pkg::apis::meta::v1::ObjectMeta>,
/// Specification of the desired behavior of the pod.
/// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
/// +optional
#[prost(message, optional, tag="2")]
pub spec: ::core::option::Option<PodSpec>,
/// Most recently observed status of the pod.
/// This data may not be up to date.
/// Populated by the system.
/// Read-only.
/// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
/// +optional
#[prost(message, optional, tag="3")]
pub status: ::core::option::Option<PodStatus>,
}
/// Pod is a collection of containers that can run on a host. This resource is created by clients and scheduled onto hosts.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Pod {
/// Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
pub metadata: crate::apimachinery::pkg::apis::meta::v1::ObjectMeta,
/// Specification of the desired behavior of the pod. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
pub spec: Option<crate::api::core::v1::PodSpec>,
/// Most recently observed status of the pod. This data may not be up to date. Populated by the system. Read-only. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
pub status: Option<crate::api::core::v1::PodStatus>,
}
|
I think that's promising. The output looks good. We don't need the |
I had misunderstood
I've never used |
https://github.com/kazk/k8s-pb Not very useful, but shows the following:
The generated code looks nice and readable, but I don't think we can do much to it. How Kubernetes wraps them for responses ( |
|
Wow. That repo looks great, just tried it all myself and it loads it all in with the given instructions. Also great to see that we're not losing anything by going with The problem here is that we need to inject the generic properties out-of-band. I.e. maybe we also have to grab the swagger schema to get the data for the Anyway, feel free to move that into |
RE: Generating
|
Yeah, we'll need to use By the way, there are some irregular camel case to snake case conversion failing (e.g., I'm also thinking of avoiding
I'd like to play around with it some more, but suggestions on what to experiment with, or sharing what you tried is welcomed there. Once we have a better idea, I'll transfer to the org, or create a new repo based on it. What should be the goal? Are we still trying to fit in Some things to explore:
|
I think this should work. However, I'd propose to use API discovery instead. I think it also provides all needed information (resource name, scope, GVK, and so on), and is easier to consume. I don't have much free time these days, but I will try to make a POC of integrating a prost-generated client with API discovery. |
Sounds good. I'll direct PRs in that direction at some point (probably after Tuesday). I might try my hands at something like:
I think it sounds like a nice separation of concerns to have as much generic information about api resources as output for the main library. We could even analyse the various subpaths of the api/{resource}/* urls to figure out exactly what
I'd assume so. The way we hide the
Well, unless you have any objections, I am probably going to propose to the kubernetes/org repo that we start kube-rs as a CNCF sandbox project. Based on the options they presented us with. So with that in mind. I think if we can make something we would use and can build upon, and then got that setup in What do you think? |
@MikailBag I imagine the desired interface would sit somewhere in the realm between the current dynamic But on the other hand, the core types do not change except between kubernetes releases, so I can't think of a reason to encourage running unnecessary discovery of unchanging core objects like |
Sorry if I expressed my point in an unclear way. I don't mean that kube should do some discovery at runtime (unless user manually uses Discovery). I mean that a code generator tool somehow used by kube should infer k8s-specific metadata not from an openapi schema, but from the apiserver. i.e:
|
@MikailBag : That's an interesting idea. I was thinking a bit about it last week. I fear that would increase the ops complexity of such a repo quite a bit compared to a straight parser with fix-ups. We'd need to stand up a full k8s server as part of CI - one with inclusive feature gates, and even then I'm not sure we would get all the api resources that's available in the spec. It might be easier from a software point of view, than a complex parser, but otoh the parser is kind of already done in k8s-openapi. |
One way would be to basically do it like
|
I haven't had much time since I commented, but I wrote some Pod looks like this: {
"name": "pods",
"namespaced": true,
"subresource": false,
"apiGroupVersion": "v1",
"group": "",
"version": "v1",
"kind": "Pod",
"rust": "api::core::v1::Pod",
"verbs": ["create", "delete", "deletecollection", "get", "list", "patch", "update"],
"scopedVerbs": {
"all": ["list"],
"namespaced": ["create", "delete", "deletecollection", "get", "list", "patch", "update"]
},
"paths": [
"/api/v1/pods",
"/api/v1/namespaces/{namespace}/pods",
"/api/v1/namespaces/{namespace}/pods/{name}"
]
} |
hahaha, that is beautiful. i didn't think you'd be able to get that good information from just i was envisioning some several hundred lines of rust to do more or less the same thing, but now i'm thinking maybe we just write something on top of the json output there. |
What are the limitations of this method can you see?
|
I love Rust, but I can't think of a good reason to use it to transform JSON like this. It's not much, and should be pretty obvious when something goes wrong (e.g., script will fail, generated code based on these won't compile, etc.). Regardless of if we end up using it or not, I'm thinking of creating a repo that keeps tracks of these JSON derived from
I don't see anything new at the moment.
I don't think so, that part is building a translation map from definition name to Rust path for Resource. If it doesn't have GVK defined, we shouldn't need them. We can also change the script to fail if the map doesn't contain the path. To see definition names without GVK field: [
.definitions | to_entries[]
| select(.value | has("x-kubernetes-group-version-kind") | not)
| .key
] It's also excluding definitions with multiple GVKs. To see that: [
.definitions | to_entries[]
| .value["x-kubernetes-group-version-kind"]? as $gvks
| select($gvks != null and ($gvks | length > 1))
| .key
] which is just these two [
"io.k8s.apimachinery.pkg.apis.meta.v1.DeleteOptions",
"io.k8s.apimachinery.pkg.apis.meta.v1.WatchEvent"
] |
Closing this in favour of #725 to keep things more reasonably scoped. With the creation and buildability of the k8s-pb library, i'd say this is good enough for this chaotic exploration issue. |
Is it reasonable/possible for us to get protobuf encoding with generated material?
This is just a bit of a ramble on potential ideas. There's no concrete plans as of writing this. Any help on this is appreciated.
This is for the last Gold Requirement
Official documentation on kubernetes.io/api-concepts#protobuf
Continuing/summarising the discussion from #127, we see conflicting uses of
client-gold
in other clients that do not support it, but let us assume good faith and try our best here.We see that the go api has protobuf codegen hints (api/types.go) like:
whereas the (huge) swagger codegen has the equivalent json for that part of the PodSpec:
Here, the ordering
34
is missing so this is probably difficult to solve for k8s-openapi as it stands.However kubernetes/api does have
generated.proto
files (see core/v1/genreated.proto) and it has the following to say about the entry:We could maybe load those files with prost, but AFAIKT that will create structs that conflict with the generated structs from
k8s-openapi
, and we rely onk8s-openapi
for trait implementations. Unless there's a way to associate these structs with the ones fromk8s-openapi
structs of the same name, this would be hard. Sounds like another codegen project if it is possible.On the other hand, if the swagger schemas had these tags, then
k8s-openapi
could optionally enable prost-tagging, but based on the existance of kubernetes/api repo maybe they don't want to evolve the swagger schemas anymore? Maybe it's worth requesting upstream?The text was updated successfully, but these errors were encountered: