Skip to content

Commit

Permalink
CR conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
mbohlool committed Nov 17, 2018
1 parent 09aae56 commit c7380cb
Showing 1 changed file with 111 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,9 @@ weight: 30
{{% capture overview %}}
This page explains how to add versioning information to
[CustomResourceDefinitions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#customresourcedefinition-v1beta1-apiextensions), to indicate the stability
level of your CustomResourceDefinitions. It also describes how to upgrade an
level of your CustomResourceDefinitions or advance your API to a new version with conversion between them. It also describes how to upgrade an
object from one version to another.

{{< note >}}
**Note**: All specified versions must use the same schema. The is no schema
conversion between versions.
{{< /note >}}

{{% /capture %}}

{{% capture prerequisites %}}
Expand All @@ -37,9 +32,10 @@ conversion between versions.

The CustomResourceDefinition API supports a `versions` field that you can use to
support multiple versions of custom resources that you have developed, and
indicate the stability of a given custom resource. All versions must currently
use the same schema, so if you need to add a field, you must add it to all
versions.
indicate the stability of a given custom resource. Versions can have different
schemas and a conversion webhook can be defined to convert a version to another.
These conversion should follow API convensions (TODO link) specially They should
be round-trippable.

{{< note >}}
Earlier iterations included a `version` field instead of `versions`. The
Expand All @@ -49,8 +45,9 @@ match the first item in the `versions` field.

## Specify multiple versions

This example shows a CustomResourceDefinition with two versions. The comments in
the YAML provide more context.
This example shows a CustomResourceDefinition with two versions. For the first
example, the assumption is all versions share the same schema with no conversion
between them. The comments in the YAML provide more context.

```yaml
apiVersion: apiextensions.k8s.io/v1beta1
Expand All @@ -71,6 +68,10 @@ spec:
- name: v1
served: true
storage: false
conversion:
# a None strategy will asuume same schema for all versions and only set apiVersion
# field of the CRs to the proper value on conversion.
strategy: None
# either Namespaced or Cluster
scope: Namespaced
names:
Expand Down Expand Up @@ -144,6 +145,105 @@ version sort order is `v1`, followed by `v1beta1`. This causes the kubectl
command to use `v1` as the default version unless the provided object specifies
the version.

## Webhook conversion

The above example assumed a None converter between versions which only set apiVersion field
on conversion to the proper value and do not change the rest of the object. API server supports
webhook conversion to call an external service on CR conversions. These conversion calls happens
whenever a different version is requested from the stored version or when the provided object is
not in the sotre version.

### Write a conversion webhook server

Please refer to the implementation of the [CR conversion webhook
server](https://github.com/kubernetes/kubernetes/blob/v1.13.0-beta.1/test/images/crd-conversion-webhook/main.go)
that is validated in a Kubernetes e2e test. The webhook handles the
`conversionReview` requests sent by the apiservers, and sends back its decision
wrapped in `conversionResponse`.

The example conversion webhook server leaves the `ClientAuth` field
[empty](https://github.com/kubernetes/kubernetes/blob/v1.10.0-beta.1/test/images/crd-conversion-webhook/config.go#L48-L49),
which defaults to `NoClientCert`. This means that the webhook server does not
authenticate the identity of the clients, supposedly apiservers. If you need
mutual TLS or other ways to authenticate the clients, see
how to [authenticate apiservers](/docs/reference/access-authn-authz/extensible-admission-controllers/#authenticate-apiservers).
The example server is organized in a way to be reused for other conversions. Most of the common codes are located in the [framework file]((https://github.com/kubernetes/kubernetes/blob/v1.10.0-beta.1/test/images/crd-conversion-webhook/converter/framework.go)) leaving only [one function]((https://github.com/kubernetes/kubernetes/blob/v1.10.0-beta.1/test/images/crd-conversion-webhook/converter/example-converter.go#L29-L80)) to be implemented for different conversion.

### Deploy the admission webhook service

To deploy example conversion webhook, refer to [admission webhook example service](/docs/reference/access-authn-authz/extensible-admission-controllers/#deploy_the_admission_webhook_service).
The assumption for next sections is the conversion webhook server is deployed to a service named `exampleConversionWebhookServer` in `default` namespace.

{{< note >}}
**Note:** When the webhook server is deployed into the Kubernetes cluster as a
service, it has to expose its service on the 443 port. The communication
between the API server and the webhook service may fail if a different port
is used.
{{< /note >}}

### Configure CustomResourceDefinition to use conversion webhooks

The example above can be extended to use the conversion webhook by modifying `conversion`
section of the `spec`:

```yaml
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
- name: v1
served: true
storage: false
conversion:
# a Webhook strategy instruct API server to call an external webhook for any conversion between CRs.
strategy: None
webhookClientConfig:
service:
namespace: default
name: exampleConversionWebhookServer
caBundle: <pem encoded ca cert that signs the server cert used by the webhook>
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular name to be used as an alias on the CLI and for display
singular: crontab
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: CronTab
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- ct
```

{{< note >}}
**Note:** When using `clientConfig.service`, the server cert must be valid for
`<svc_name>.<svc_namespace>.svc`.
{{< /note >}}

You can save the CustomResourceDefinition in a YAML file, then use
`kubectl apply` to apply it.

```shell
kubectl create -f my-versioned-crontab-with-conversion.yaml
```

Make sure the conversion servie is up and running before applying new changes.
When an apiserver receives a request for a CR the needs conversion (e.g. read CRs
with different version than storage version), the apiserver sends an
`conversionReview` request to webhook as specified in the `webhookClientConfig`.

## Writing, reading, and updating versioned CustomResourceDefinition objects

When an object is written, it is persisted at the version designated as the
Expand Down

0 comments on commit c7380cb

Please sign in to comment.