summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrendan Burns <bburns@google.com>2015-07-27 12:49:06 -0700
committerBrendan Burns <bburns@google.com>2015-08-13 09:25:02 -0700
commit4fa0f3a7b2c2d43815967c6f4671713a0c2ffa40 (patch)
tree7b0153aa72772c1fd9d485bfc3d554ad39684b8d
parentc89196ac7341fdfbfbed5d27bb568bb66d4eafec (diff)
Add initial storage types to the Kubernetes API
-rw-r--r--extending-api.md222
1 files changed, 222 insertions, 0 deletions
diff --git a/extending-api.md b/extending-api.md
new file mode 100644
index 00000000..cca257bd
--- /dev/null
+++ b/extending-api.md
@@ -0,0 +1,222 @@
+<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
+
+<!-- BEGIN STRIP_FOR_RELEASE -->
+
+<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
+ width="25" height="25">
+<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
+ width="25" height="25">
+<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
+ width="25" height="25">
+<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
+ width="25" height="25">
+<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
+ width="25" height="25">
+
+<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
+
+If you are using a released version of Kubernetes, you should
+refer to the docs that go with that version.
+
+<strong>
+The latest 1.0.x release of this document can be found
+[here](http://releases.k8s.io/release-1.0/docs/design/extending-api.md).
+
+Documentation for other releases can be found at
+[releases.k8s.io](http://releases.k8s.io).
+</strong>
+--
+
+<!-- END STRIP_FOR_RELEASE -->
+
+<!-- END MUNGE: UNVERSIONED_WARNING -->
+
+# Adding custom resources to the Kubernetes API server
+
+This document describes the design for implementing the storage of custom API types in the Kubernetes API Server.
+
+
+## Resource Model
+
+### The ThirdPartyResource
+
+The `ThirdPartyResource` resource describes the multiple versions of a custom resource that the user wants to add
+to the Kubernetes API. `ThirdPartyResource` is a non-namespaced resource, attempting to place it in a resource
+will return an error.
+
+Each `ThirdPartyResource` resource has the following:
+ * Standard Kubernetes object metadata.
+ * ResourceKind - The kind of the resources described by this third party resource.
+ * Description - A free text description of the resource.
+ * APIGroup - An API group that this resource should be placed into.
+ * Versions - One or more `Version` objects.
+
+### The `Version` Object
+
+The `Version` object describes a single concrete version of a custom resource. The `Version` object currently
+only specifies:
+ * The `Name` of the version.
+ * The `APIGroup` this version should belong to.
+
+## Expectations about third party objects
+
+Every object that is added to a third-party Kubernetes object store is expected to contain Kubernetes
+compatible [object metadata](../devel/api-conventions.md#metadata). This requirement enables the
+Kubernetes API server to provide the following features:
+ * Filtering lists of objects via LabelQueries
+ * `resourceVersion`-based optimistic concurrency via compare-and-swap
+ * Versioned storage
+ * Event recording
+ * Integration with basic `kubectl` command line tooling.
+ * Watch for resource changes.
+
+The `Kind` for an instance of a third-party object (e.g. CronTab) below is expected to be
+programnatically convertible to the name of the resource using
+the following conversion. Kinds are expected to be of the form `<CamelCaseKind>`, the
+`APIVersion` for the object is expected to be `<domain-name>/<api-group>/<api-version>`.
+
+For example `example.com/stable/v1`
+
+`domain-name` is expected to be a fully qualified domain name.
+
+'CamelCaseKind' is the specific type name.
+
+To convert this into the `metadata.name` for the `ThirdPartyResource` resource instance,
+the `<domain-name>` is copied verbatim, the `CamelCaseKind` is
+then converted
+using '-' instead of capitalization ('camel-case'), with the first character being assumed to be
+capitalized. In pseudo code:
+
+```go
+var result string
+for ix := range kindName {
+ if isCapital(kindName[ix]) {
+ result = append(result, '-')
+ }
+ result = append(result, toLowerCase(kindName[ix])
+}
+```
+
+As a concrete example, the resource named `camel-case-kind.example.com` defines resources of Kind `CamelCaseKind`, in
+the APIGroup with the prefix `example.com/...`.
+
+The reason for this is to enable rapid lookup of a `ThirdPartyResource` object given the kind information.
+This is also the reason why `ThirdPartyResource` is not namespaced.
+
+## Usage
+
+When a user creates a new `ThirdPartyResource`, the Kubernetes API Server reacts by creating a new, namespaced
+RESTful resource path. For now, non-namespaced objects are not supported. As with existing built-in objects
+deleting a namespace, deletes all third party resources in that namespace.
+
+For example, if a user creates:
+
+```yaml
+metadata:
+ name: cron-tab.example.com
+apiVersion: experimental/v1
+kind: ThirdPartyResource
+description: "A specification of a Pod to run on a cron style schedule"
+versions:
+ - name: stable/v1
+ - name: experimental/v2
+```
+
+Then the API server will program in two new RESTful resource paths:
+ * `/thirdparty/example.com/stable/v1/namespaces/<namespace>/crontabs/...`
+ * `/thirdparty/example.com/experimental/v2/namespaces/<namespace>/crontabs/...`
+
+
+Now that this schema has been created, a user can `POST`:
+
+```json
+{
+ "metadata": {
+ "name": "my-new-cron-object"
+ },
+ "apiVersion": "example.com/stable/v1",
+ "kind": "CronTab",
+ "cronSpec": "* * * * /5",
+ "image": "my-awesome-chron-image"
+}
+```
+
+to: `/third-party/example.com/stable/v1/namespaces/default/crontabs/my-new-cron-object`
+
+and the corresponding data will be stored into etcd by the APIServer, so that when the user issues:
+
+```
+GET /third-party/example.com/stable/v1/namespaces/default/crontabs/my-new-cron-object`
+```
+
+And when they do that, they will get back the same data, but with additional Kubernetes metadata
+(e.g. `resourceVersion`, `createdTimestamp`) filled in.
+
+Likewise, to list all resources, a user can issue:
+
+```
+GET /third-party/example.com/stable/v1/namespaces/default/crontabs
+```
+
+and get back:
+
+```json
+{
+ "apiVersion": "example.com/stable/v1",
+ "kind": "CronTabList",
+ "items": [
+ {
+ "metadata": {
+ "name": "my-new-cron-object"
+ },
+ "apiVersion": "example.com/stable/v1",
+ "kind": "CronTab",
+ "cronSpec": "* * * * /5",
+ "image": "my-awesome-chron-image"
+ }
+ ]
+}
+```
+
+Because all objects are expected to contain standard Kubernetes metdata fileds, these
+list operations can also use `Label` queries to filter requests down to specific subsets.
+
+Likewise, clients can use watch endpoints to watch for changes to stored objects.
+
+
+## Storage
+
+In order to store custom user data in a versioned fashion inside of etcd, we need to also introduce a
+`Codec`-compatible object for persistent storage in etcd. This object is `ThirdPartyResourceData` and it contains:
+ * Standard API Metadata
+ * `Data`: The raw JSON data for this custom object.
+
+### Storage key specification
+
+Each custom object stored by the API server needs a custom key in storage, this is described below:
+
+#### Definitions
+
+ * `resource-namespace` : the namespace of the particular resource that is being stored
+ * `resource-name`: the name of the particular resource being stored
+ * `third-party-resource-namespace`: the namespace of the `ThirdPartyResource` resource that represents the type for the specific instance being stored.
+ * `third-party-resource-name`: the name of the `ThirdPartyResource` resource that represents the type for the specific instance being stored.
+
+#### Key
+
+Given the definitions above, the key for a specific third-party object is:
+
+```
+${standard-k8s-prefix}/third-party-resources/${third-party-resource-namespace}/${third-party-resource-name}/${resource-namespace}/${resource-name}
+```
+
+Thus, listing a third-party resource can be achieved by listing the directory:
+
+```
+${standard-k8s-prefix}/third-party-resources/${third-party-resource-namespace}/${third-party-resource-name}/${resource-namespace}/
+```
+
+
+<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
+[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/design/extending-api.md?pixel)]()
+<!-- END MUNGE: GENERATED_ANALYTICS -->