Merge master into dev-1.20 to keep in sync
This commit is contained in:
@@ -18,8 +18,8 @@ This section of the Kubernetes documentation contains references.
|
||||
|
||||
## API Reference
|
||||
|
||||
* [Kubernetes API Overview](/docs/reference/using-api/api-overview/) - Overview of the API for Kubernetes.
|
||||
* [Kubernetes API Reference {{< latest-version >}}](/docs/reference/generated/kubernetes-api/{{< latest-version >}}/)
|
||||
* [Using The Kubernetes API](/docs/reference/using-api/) - overview of the API for Kubernetes.
|
||||
|
||||
## API Client Libraries
|
||||
|
||||
@@ -36,7 +36,7 @@ client libraries:
|
||||
|
||||
* [kubectl](/docs/reference/kubectl/overview/) - Main CLI tool for running commands and managing Kubernetes clusters.
|
||||
* [JSONPath](/docs/reference/kubectl/jsonpath/) - Syntax guide for using [JSONPath expressions](https://goessner.net/articles/JsonPath/) with kubectl.
|
||||
* [kubeadm](/docs/reference/setup-tools/kubeadm/kubeadm/) - CLI tool to easily provision a secure Kubernetes cluster.
|
||||
* [kubeadm](/docs/reference/setup-tools/kubeadm/) - CLI tool to easily provision a secure Kubernetes cluster.
|
||||
|
||||
## Components Reference
|
||||
|
||||
|
||||
@@ -1,4 +1,26 @@
|
||||
---
|
||||
title: Accessing the API
|
||||
title: API Access Control
|
||||
weight: 20
|
||||
---
|
||||
no_list: true
|
||||
---
|
||||
|
||||
For an introduction to how Kubernetes implements and controls API access,
|
||||
read [Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access/).
|
||||
|
||||
Reference documentation:
|
||||
|
||||
- [Authenticating](/docs/reference/access-authn-authz/authentication/)
|
||||
- [Authenticating with Bootstrap Tokens](/docs/reference/access-authn-authz/bootstrap-tokens/)
|
||||
- [Admission Controllers](/docs/reference/access-authn-authz/admission-controllers/)
|
||||
- [Dynamic Admission Control](/docs/reference/access-authn-authz/extensible-admission-controllers/)
|
||||
- [Authorization](/docs/reference/access-authn-authz/authorization/)
|
||||
- [Role Based Access Control](/docs/reference/access-authn-authz/rbac/)
|
||||
- [Attribute Based Access Control](/docs/reference/access-authn-authz/abac/)
|
||||
- [Node Authorization](/docs/reference/access-authn-authz/node/)
|
||||
- [Webhook Authorization](/docs/reference/access-authn-authz/webhook/)
|
||||
- [Certificate Signing Requests](/docs/reference/access-authn-authz/certificate-signing-requests/)
|
||||
- including [CSR approval](/docs/reference/access-authn-authz/certificate-signing-requests/#approval-rejection)
|
||||
and [certificate signing](/docs/reference/access-authn-authz/certificate-signing-requests/#signing)
|
||||
- Service accounts
|
||||
- [Developer guide](/docs/tasks/configure-pod-container/configure-service-account/)
|
||||
- [Administration](/docs/reference/access-authn-authz/service-accounts-admin/)
|
||||
|
||||
@@ -730,7 +730,7 @@ See the [resourceQuota design doc](https://git.k8s.io/community/contributors/des
|
||||
For [RuntimeClass](/docs/concepts/containers/runtime-class/) definitions which describe an overhead associated with running a pod,
|
||||
this admission controller will set the pod.Spec.Overhead field accordingly.
|
||||
|
||||
See also [Pod Overhead](/docs/concepts/configuration/pod-overhead/)
|
||||
See also [Pod Overhead](/docs/concepts/scheduling-eviction/pod-overhead/)
|
||||
for more information.
|
||||
|
||||
### SecurityContextDeny {#securitycontextdeny}
|
||||
|
||||
@@ -29,7 +29,7 @@ It is assumed that a cluster-independent service manages normal users in the fol
|
||||
In this regard, _Kubernetes does not have objects which represent normal user
|
||||
accounts._ Normal users cannot be added to a cluster through an API call.
|
||||
|
||||
Even though normal user cannot be added via an API call, but any user that
|
||||
Even though a normal user cannot be added via an API call, any user that
|
||||
presents a valid certificate signed by the cluster's certificate authority
|
||||
(CA) is considered authenticated. In this configuration, Kubernetes determines
|
||||
the username from the common name field in the 'subject' of the cert (e.g.,
|
||||
|
||||
@@ -17,7 +17,7 @@ policies using the supported authorization modules.
|
||||
<!-- body -->
|
||||
In Kubernetes, you must be authenticated (logged in) before your request can be
|
||||
authorized (granted permission to access). For information about authentication,
|
||||
see [Controlling Access to the Kubernetes API](/docs/reference/access-authn-authz/controlling-access/).
|
||||
see [Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access/).
|
||||
|
||||
Kubernetes expects attributes that are common to REST API requests. This means
|
||||
that Kubernetes authorization works with existing organization-wide or
|
||||
@@ -52,7 +52,7 @@ Kubernetes reviews only the following API request attributes:
|
||||
* **Resource** - The ID or name of the resource that is being accessed (for resource requests only) -- For resource requests using `get`, `update`, `patch`, and `delete` verbs, you must provide the resource name.
|
||||
* **Subresource** - The subresource that is being accessed (for resource requests only).
|
||||
* **Namespace** - The namespace of the object that is being accessed (for namespaced resource requests only).
|
||||
* **API group** - The {{< glossary_tooltip text="API Group" term_id="api-group" >}} being accessed (for resource requests only). An empty string designates the [core API group](/docs/reference/using-api/api-overview/#api-groups).
|
||||
* **API group** - The {{< glossary_tooltip text="API Group" term_id="api-group" >}} being accessed (for resource requests only). An empty string designates the _core_ [API group](/docs/reference/using-api/#api-groups).
|
||||
|
||||
## Determine the Request Verb
|
||||
|
||||
@@ -202,6 +202,6 @@ action the account could take. This applies regardless of authorization mode.
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
* To learn more about Authentication, see **Authentication** in [Controlling Access to the Kubernetes API](/docs/reference/access-authn-authz/controlling-access/).
|
||||
* To learn more about Authentication, see **Authentication** in [Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access/).
|
||||
* To learn more about Admission Control, see [Using Admission Controllers](/docs/reference/access-authn-authz/admission-controllers/).
|
||||
|
||||
|
||||
@@ -12,10 +12,10 @@ weight: 20
|
||||
|
||||
Bootstrap tokens are a simple bearer token that is meant to be used when
|
||||
creating new clusters or joining new nodes to an existing cluster. It was built
|
||||
to support [kubeadm](/docs/reference/setup-tools/kubeadm/kubeadm/), but can be used in other contexts
|
||||
to support [kubeadm](/docs/reference/setup-tools/kubeadm/), but can be used in other contexts
|
||||
for users that wish to start clusters without `kubeadm`. It is also built to
|
||||
work, via RBAC policy, with the [Kubelet TLS
|
||||
Bootstrapping](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) system.
|
||||
work, via RBAC policy, with the
|
||||
[Kubelet TLS Bootstrapping](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) system.
|
||||
|
||||
|
||||
<!-- body -->
|
||||
|
||||
@@ -21,17 +21,16 @@ A CertificateSigningRequest (CSR) resource is used to request that a certificate
|
||||
by a denoted signer, after which the request may be approved or denied before
|
||||
finally being signed.
|
||||
|
||||
|
||||
|
||||
<!-- body -->
|
||||
|
||||
## Request signing process
|
||||
|
||||
The _CertificateSigningRequest_ resource type allows a client to ask for an X.509 certificate
|
||||
The CertificateSigningRequest resource type allows a client to ask for an X.509 certificate
|
||||
be issued, based on a signing request.
|
||||
The CertificateSigningRequest object includes a PEM-encoded PKCS#10 signing request in
|
||||
the `spec.request` field. The CertificateSigningRequest denotes the _signer_ (the
|
||||
the `spec.request` field. The CertificateSigningRequest denotes the signer (the
|
||||
recipient that the request is being made to) using the `spec.signerName` field.
|
||||
Note that `spec.signerName` is a required key after api version `certificates.k8s.io/v1`.
|
||||
Note that `spec.signerName` is a required key after API version `certificates.k8s.io/v1`.
|
||||
|
||||
Once created, a CertificateSigningRequest must be approved before it can be signed.
|
||||
Depending on the signer selected, a CertificateSigningRequest may be automatically approved
|
||||
@@ -68,54 +67,80 @@ This includes:
|
||||
1. **Permitted subjects**: any restrictions on and behavior when a disallowed subject is requested.
|
||||
1. **Permitted x509 extensions**: including IP subjectAltNames, DNS subjectAltNames, Email subjectAltNames, URI subjectAltNames etc, and behavior when a disallowed extension is requested.
|
||||
1. **Permitted key usages / extended key usages**: any restrictions on and behavior when usages different than the signer-determined usages are specified in the CSR.
|
||||
1. **Expiration/certificate lifetime**: whether it is fixed by the signer, configurable by the admin, determined by the CSR object etc and the behavior when an expiration is different than the signer-determined expiration that is specified in the CSR.
|
||||
1. **Expiration/certificate lifetime**: whether it is fixed by the signer, configurable by the admin, determined by the CSR object etc
|
||||
and the behavior when an expiration is different than the signer-determined expiration that is specified in the CSR.
|
||||
1. **CA bit allowed/disallowed**: and behavior if a CSR contains a request a for a CA certificate when the signer does not permit it.
|
||||
|
||||
Commonly, the `status.certificate` field contains a single PEM-encoded X.509 certificate once the CSR is approved and the certificate is issued. Some signers store multiple certificates into the `status.certificate` field. In that case, the documentation for the signer should specify the meaning of additional certificates; for example, this might be the certificate plus intermediates to be presented during TLS handshakes.
|
||||
Commonly, the `status.certificate` field contains a single PEM-encoded X.509
|
||||
certificate once the CSR is approved and the certificate is issued. Some
|
||||
signers store multiple certificates into the `status.certificate` field. In
|
||||
that case, the documentation for the signer should specify the meaning of
|
||||
additional certificates; for example, this might be the certificate plus
|
||||
intermediates to be presented during TLS handshakes.
|
||||
|
||||
The PKCS#10 signing request format doesn't allow to specify a certificate
|
||||
expiration or lifetime. The expiration or lifetime therefore has to be set
|
||||
through e.g. an annotation on the CSR object. While it's theoretically
|
||||
possible for a signer to use that expiration date, there is currently no
|
||||
known implementation that does. (The built-in signers all use the same
|
||||
`ClusterSigningDuration` configuration option, which defaults to 1 year,
|
||||
and can be changed with the `--cluster-signing-duration` command-line
|
||||
flag of the kube-controller-manager.)
|
||||
|
||||
|
||||
### Kubernetes signers
|
||||
|
||||
Kubernetes provides built-in signers that each have a well-known `signerName`:
|
||||
|
||||
1. `kubernetes.io/kube-apiserver-client`: signs certificates that will be honored as client-certs by the kube-apiserver.
|
||||
Never auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: signed certificates must be honored as client-certificates by the kube-apiserver. The CA bundle is not distributed by any other means.
|
||||
1. Permitted subjects - no subject restrictions, but approvers and signers may choose not to approve or sign. Certain subjects like cluster-admin level users or groups vary between distributions and installations, but deserve additional scrutiny before approval and signing. The `CertificateSubjectRestriction` admission plugin is available and enabled by default to restrict `system:masters`, but it is often not the only cluster-admin subject in a cluster.
|
||||
1. `kubernetes.io/kube-apiserver-client`: signs certificates that will be honored as client certificates by the API server.
|
||||
Never auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: signed certificates must be honored as client certificates by the API server. The CA bundle is not distributed by any other means.
|
||||
1. Permitted subjects - no subject restrictions, but approvers and signers may choose not to approve or sign.
|
||||
Certain subjects like cluster-admin level users or groups vary between distributions and installations,
|
||||
but deserve additional scrutiny before approval and signing.
|
||||
The `CertificateSubjectRestriction` admission plugin is enabled by default to restrict `system:masters`,
|
||||
but it is often not the only cluster-admin subject in a cluster.
|
||||
1. Permitted x509 extensions - honors subjectAltName and key usage extensions and discards other extensions.
|
||||
1. Permitted key usages - must include []string{"client auth"}. Must not include key usages beyond []string{"digital signature", "key encipherment", "client auth"}
|
||||
1. Expiration/certificate lifetime - minimum of CSR signer or request. The signer is responsible for checking that the certificate lifetime is valid and permissible.
|
||||
1. Permitted key usages - must include `["client auth"]`. Must not include key usages beyond `["digital signature", "key encipherment", "client auth"]`.
|
||||
1. Expiration/certificate lifetime - set by the `--cluster-signing-duration` option for the
|
||||
kube-controller-manager implementation of this signer.
|
||||
1. CA bit allowed/disallowed - not allowed.
|
||||
|
||||
1. `kubernetes.io/kube-apiserver-client-kubelet`: signs client certificates that will be honored as client-certs by the
|
||||
kube-apiserver.
|
||||
May be auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: signed certificates must be honored as client-certificates by the kube-apiserver. The CA bundle
|
||||
1. `kubernetes.io/kube-apiserver-client-kubelet`: signs client certificates that will be honored as client certificates by the
|
||||
API server.
|
||||
May be auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: signed certificates must be honored as client certificates by the API server. The CA bundle
|
||||
is not distributed by any other means.
|
||||
1. Permitted subjects - organizations are exactly `[]string{"system:nodes"}`, common name starts with `"system:node:"`
|
||||
1. Permitted subjects - organizations are exactly `["system:nodes"]`, common name starts with "`system:node:`".
|
||||
1. Permitted x509 extensions - honors key usage extensions, forbids subjectAltName extensions and drops other extensions.
|
||||
1. Permitted key usages - exactly `[]string{"key encipherment", "digital signature", "client auth"}`
|
||||
1. Expiration/certificate lifetime - minimum of CSR signer or request. The signer is responsible for checking that the certificate lifetime is valid and permissible.
|
||||
1. Permitted key usages - exactly `["key encipherment", "digital signature", "client auth"]`.
|
||||
1. Expiration/certificate lifetime - set by the `--cluster-signing-duration` option for the
|
||||
kube-controller-manager implementation of this signer.
|
||||
1. CA bit allowed/disallowed - not allowed.
|
||||
|
||||
1. `kubernetes.io/kubelet-serving`: signs serving certificates that are honored as a valid kubelet serving certificate
|
||||
by the kube-apiserver, but has no other guarantees.
|
||||
Never auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: signed certificates must be honored by the kube-apiserver as valid to terminate connections to a kubelet. The CA bundle is not distributed by any other means.
|
||||
1. Permitted subjects - organizations are exactly `[]string{"system:nodes"}`, common name starts with `"system:node:"`
|
||||
1. Permitted x509 extensions - honors key usage and DNSName/IPAddress subjectAltName extensions, forbids EmailAddress and URI subjectAltName extensions, drops other extensions. At least one DNS or IP subjectAltName must be present.
|
||||
1. Permitted key usages - exactly `[]string{"key encipherment", "digital signature", "server auth"}`
|
||||
1. Expiration/certificate lifetime - minimum of CSR signer or request.
|
||||
by the API server, but has no other guarantees.
|
||||
Never auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: signed certificates must be honored by the API server as valid to terminate connections to a kubelet.
|
||||
The CA bundle is not distributed by any other means.
|
||||
1. Permitted subjects - organizations are exactly `["system:nodes"]`, common name starts with "`system:node:`".
|
||||
1. Permitted x509 extensions - honors key usage and DNSName/IPAddress subjectAltName extensions, forbids EmailAddress and
|
||||
URI subjectAltName extensions, drops other extensions. At least one DNS or IP subjectAltName must be present.
|
||||
1. Permitted key usages - exactly `["key encipherment", "digital signature", "server auth"]`.
|
||||
1. Expiration/certificate lifetime - set by the `--cluster-signing-duration` option for the
|
||||
kube-controller-manager implementation of this signer.
|
||||
1. CA bit allowed/disallowed - not allowed.
|
||||
|
||||
1. `kubernetes.io/legacy-unknown`: has no guarantees for trust at all. Some third-party distributions of Kubernetes
|
||||
may honor client certificates signed by it. The stable CertificateSigningRequest API (version `certificates.k8s.io/v1` and later)
|
||||
does not allow to set the `signerName` as `kubernetes.io/legacy-unknown`.
|
||||
Never auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: None. There is no standard trust or distribution for this signer in a Kubernetes cluster.
|
||||
may honor client certificates signed by it. The stable CertificateSigningRequest API (version `certificates.k8s.io/v1` and later)
|
||||
does not allow to set the `signerName` as `kubernetes.io/legacy-unknown`.
|
||||
Never auto-approved by {{< glossary_tooltip term_id="kube-controller-manager" >}}.
|
||||
1. Trust distribution: None. There is no standard trust or distribution for this signer in a Kubernetes cluster.
|
||||
1. Permitted subjects - any
|
||||
1. Permitted x509 extensions - honors subjectAltName and key usage extensions and discards other extensions.
|
||||
1. Permitted key usages - any
|
||||
1. Expiration/certificate lifetime - minimum of CSR signer or request. The signer is responsible for checking that the certificate lifetime is valid and permissible.
|
||||
1. Expiration/certificate lifetime - set by the `--cluster-signing-duration` option for the
|
||||
kube-controller-manager implementation of this signer.
|
||||
1. CA bit allowed/disallowed - not allowed.
|
||||
|
||||
{{< note >}}
|
||||
@@ -126,7 +151,7 @@ Distribution of trust happens out of band for these signers. Any trust outside
|
||||
coincidental. For instance, some distributions may honor `kubernetes.io/legacy-unknown` as client certificates for the
|
||||
kube-apiserver, but this is not a standard.
|
||||
None of these usages are related to ServiceAccount token secrets `.data[ca.crt]` in any way. That CA bundle is only
|
||||
guaranteed to verify a connection to the kube-apiserver using the default service (`kubernetes.default.svc`).
|
||||
guaranteed to verify a connection to the API server using the default service (`kubernetes.default.svc`).
|
||||
|
||||
## Authorization
|
||||
|
||||
@@ -136,22 +161,7 @@ To allow creating a CertificateSigningRequest and retrieving any CertificateSign
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: csr-creator
|
||||
rules:
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests
|
||||
verbs:
|
||||
- create
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
```
|
||||
{{< codenew file="access/certificate-signing-request/clusterrole-create.yaml" >}}
|
||||
|
||||
To allow approving a CertificateSigningRequest:
|
||||
|
||||
@@ -161,35 +171,7 @@ To allow approving a CertificateSigningRequest:
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: csr-approver
|
||||
rules:
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests/approval
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- signers
|
||||
resourceNames:
|
||||
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
|
||||
verbs:
|
||||
- approve
|
||||
```
|
||||
{{< codenew file="access/certificate-signing-request/clusterrole-approve.yaml" >}}
|
||||
|
||||
To allow signing a CertificateSigningRequest:
|
||||
|
||||
@@ -197,54 +179,32 @@ To allow signing a CertificateSigningRequest:
|
||||
* Verbs: `update`, group: `certificates.k8s.io`, resource: `certificatesigningrequests/status`
|
||||
* Verbs: `sign`, group: `certificates.k8s.io`, resource: `signers`, resourceName: `<signerNameDomain>/<signerNamePath>` or `<signerNameDomain>/*`
|
||||
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: csr-signer
|
||||
rules:
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests/status
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- signers
|
||||
resourceName:
|
||||
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
|
||||
verbs:
|
||||
- sign
|
||||
```
|
||||
{{< codenew file="access/certificate-signing-request/clusterrole-sign.yaml" >}}
|
||||
|
||||
## Normal User
|
||||
## Normal user
|
||||
|
||||
A few steps are required in order to get normal user to be able to authenticate and invoke an API. First, this user must have certificate issued by the Kubernetes Cluster, and then present that Certificate to the API call as the Certificate Header or through the kubectl.
|
||||
A few steps are required in order to get a normal user to be able to
|
||||
authenticate and invoke an API. First, this user must have certificate issued
|
||||
by the Kubernetes cluster, and then present that Certificate to the API call
|
||||
as the Certificate Header or through the kubectl.
|
||||
|
||||
### Create Private Key
|
||||
### Create private key
|
||||
|
||||
The following scripts show how to generate PKI private key and CSR. It is important to set CN and O attribute of the CSR. CN is the name of the user and O is the group that this user will belong to. You can refer to [RBAC](/docs/reference/access-authn-authz/rbac/) for standard groups.
|
||||
The following scripts show how to generate PKI private key and CSR. It is
|
||||
important to set CN and O attribute of the CSR. CN is the name of the user and
|
||||
O is the group that this user will belong to. You can refer to
|
||||
[RBAC](/docs/reference/access-authn-authz/rbac/) for standard groups.
|
||||
|
||||
```
|
||||
```shell
|
||||
openssl genrsa -out john.key 2048
|
||||
openssl req -new -key john.key -out john.csr
|
||||
```
|
||||
|
||||
### Create Certificate Request Kubernetes Object
|
||||
### Create CertificateSigningRequest
|
||||
|
||||
Create a CertificateSigningRequest and submit it to a Kubernetes Cluster via kubectl. Below is a script to generate the CertificateSigningRequest.
|
||||
|
||||
```
|
||||
```shell
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: certificates.k8s.io/v1
|
||||
kind: CertificateSigningRequest
|
||||
@@ -262,68 +222,78 @@ EOF
|
||||
|
||||
Some points to note:
|
||||
|
||||
- usage has to be 'client auth'
|
||||
- request is the base64 encoded value of the CSR file content. You can use this command to get that ```cat john.csr | base64 | tr -d "\n"```
|
||||
- `usages` has to be '`client auth`'
|
||||
- `request` is the base64 encoded value of the CSR file content.
|
||||
You can get the content using this command: ```cat john.csr | base64 | tr -d "\n"```
|
||||
|
||||
### Approve Certificate Request
|
||||
### Approve certificate signing request
|
||||
|
||||
Use kubeadmin to create a CSR and approve it.
|
||||
Use kubectl to create a CSR and approve it.
|
||||
|
||||
Get the list of CSRs
|
||||
```
|
||||
Get the list of CSRs:
|
||||
|
||||
```shell
|
||||
kubectl get csr
|
||||
```
|
||||
|
||||
Approve the CSR
|
||||
```
|
||||
Approve the CSR:
|
||||
|
||||
```shell
|
||||
kubectl certificate approve john
|
||||
```
|
||||
|
||||
### Get the Certificate
|
||||
### Get the certificate
|
||||
|
||||
Retrieve the Certificate from the CSR.
|
||||
Retrieve the certificate from the CSR:
|
||||
|
||||
```
|
||||
```shell
|
||||
kubectl get csr/john -o yaml
|
||||
```
|
||||
|
||||
The Certificate value is in Base64-encoded format under status.certificate.
|
||||
The certificate value is in Base64-encoded format under `status.certificate`.
|
||||
|
||||
### Create Role and Role Binding
|
||||
### Create Role and RoleBinding
|
||||
|
||||
You get the Certificate already. Now it is time to define the Role and Role Binding for this user to access Kubernetes Cluster resources.
|
||||
With the certificate created. it is time to define the Role and RoleBinding for
|
||||
this user to access Kubernetes cluster resources.
|
||||
|
||||
This is a sample script to create role for this new user
|
||||
```
|
||||
This is a sample script to create a Role for this new user:
|
||||
|
||||
```shell
|
||||
kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods
|
||||
```
|
||||
|
||||
This is a sample script to create role binding for this new user
|
||||
```
|
||||
This is a sample command to create a RoleBinding for this new user:
|
||||
|
||||
```shell
|
||||
kubectl create rolebinding developer-binding-john --role=developer --user=john
|
||||
```
|
||||
|
||||
### Add to KubeConfig
|
||||
### Add to kubeconfig
|
||||
|
||||
The last step is to add this user into the KubeConfig. We assume the key and crt files are located here "/home/vagrant/work/".
|
||||
The last step is to add this user into the kubeconfig file.
|
||||
This example assumes the key and certificate files are located at "/home/vagrant/work/".
|
||||
|
||||
First, you need to add new credentials:
|
||||
|
||||
First, we need to add new credentials
|
||||
```
|
||||
kubectl config set-credentials john --client-key=/home/vagrant/work/john.key --client-certificate=/home/vagrant/work/john.crt --embed-certs=true
|
||||
|
||||
```
|
||||
|
||||
Then, we need to add the context
|
||||
Then, you need to add the context:
|
||||
|
||||
```
|
||||
kubectl config set-context john --cluster=kubernetes --user=john
|
||||
```
|
||||
|
||||
To test it, change kubecontext to john
|
||||
To test it, change the context to `john`:
|
||||
|
||||
```
|
||||
kubectl config use-context john
|
||||
```
|
||||
|
||||
## Approval & rejection
|
||||
## Approval or rejection {#approval-rejection}
|
||||
|
||||
### Control plane automated approval {#approval-rejection-control-plane}
|
||||
|
||||
@@ -333,7 +303,7 @@ permissions on CSRs for node credentials to authorization.
|
||||
The kube-controller-manager POSTs SubjectAccessReview resources to the API server
|
||||
in order to check authorization for certificate approval.
|
||||
|
||||
### Approval & rejection using `kubectl` {#approval-rejection-kubectl}
|
||||
### Approval or rejection using `kubectl` {#approval-rejection-kubectl}
|
||||
|
||||
A Kubernetes administrator (with appropriate permissions) can manually approve
|
||||
(or deny) CertificateSigningRequests by using the `kubectl certificate
|
||||
@@ -341,17 +311,17 @@ approve` and `kubectl certificate deny` commands.
|
||||
|
||||
To approve a CSR with kubectl:
|
||||
|
||||
```bash
|
||||
```shell
|
||||
kubectl certificate approve <certificate-signing-request-name>
|
||||
```
|
||||
|
||||
Likewise, to deny a CSR:
|
||||
|
||||
```bash
|
||||
```shell
|
||||
kubectl certificate deny <certificate-signing-request-name>
|
||||
```
|
||||
|
||||
### Approval & rejection using the Kubernetes API {#approval-rejection-api-client}
|
||||
### Approval or rejection using the Kubernetes API {#approval-rejection-api-client}
|
||||
|
||||
Users of the REST API can approve CSRs by submitting an UPDATE request to the `approval`
|
||||
subresource of the CSR to be approved. For example, you could write an
|
||||
@@ -400,7 +370,8 @@ you like. If you want to add a note just for human consumption, use the
|
||||
|
||||
### Control plane signer {#signer-control-plane}
|
||||
|
||||
The Kubernetes control plane implements each of the [Kubernetes signers](/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers),
|
||||
The Kubernetes control plane implements each of the
|
||||
[Kubernetes signers](/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers),
|
||||
as part of the kube-controller-manager.
|
||||
|
||||
{{< note >}}
|
||||
@@ -460,13 +431,11 @@ status:
|
||||
certificate: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JS..."
|
||||
```
|
||||
|
||||
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
* Read [Manage TLS Certificates in a Cluster](/docs/tasks/tls/managing-tls-in-a-cluster/)
|
||||
* View the source code for the kube-controller-manager built in [signer](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/signer/cfssl_signer.go)
|
||||
* View the source code for the kube-controller-manager built in [approver](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/approver/sarapprove.go)
|
||||
* For details of X.509 itself, refer to [RFC 5280](https://tools.ietf.org/html/rfc5280#section-3.1) section 3.1
|
||||
* For information on the syntax of PKCS#10 certificate signing requests, refer to [RFC 2986](https://tools.ietf.org/html/rfc2986)
|
||||
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
---
|
||||
reviewers:
|
||||
- erictune
|
||||
- lavalamp
|
||||
title: Controlling Access to the Kubernetes API
|
||||
content_type: concept
|
||||
weight: 5
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
This page provides an overview of controlling access to the Kubernetes API.
|
||||
|
||||
|
||||
<!-- body -->
|
||||
Users [access the API](/docs/tasks/access-application-cluster/access-cluster/) using `kubectl`,
|
||||
client libraries, or by making REST requests. Both human users and
|
||||
[Kubernetes service accounts](/docs/tasks/configure-pod-container/configure-service-account/) can be
|
||||
authorized for API access.
|
||||
When a request reaches the API, it goes through several stages, illustrated in the
|
||||
following diagram:
|
||||
|
||||

|
||||
|
||||
## Transport Security
|
||||
|
||||
In a typical Kubernetes cluster, the API serves on port 443.
|
||||
The API server presents a certificate. This certificate is
|
||||
often self-signed, so `$USER/.kube/config` on the user's machine typically
|
||||
contains the root certificate for the API server's certificate, which when specified
|
||||
is used in place of the system default root certificate. This certificate is typically
|
||||
automatically written into your `$USER/.kube/config` when you create a cluster yourself
|
||||
using `kube-up.sh`. If the cluster has multiple users, then the creator needs to share
|
||||
the certificate with other users.
|
||||
|
||||
## Authentication
|
||||
|
||||
Once TLS is established, the HTTP request moves to the Authentication step.
|
||||
This is shown as step **1** in the diagram.
|
||||
The cluster creation script or cluster admin configures the API server to run
|
||||
one or more Authenticator Modules.
|
||||
Authenticators are described in more detail [here](/docs/reference/access-authn-authz/authentication/).
|
||||
|
||||
The input to the authentication step is the entire HTTP request, however, it typically
|
||||
just examines the headers and/or client certificate.
|
||||
|
||||
Authentication modules include Client Certificates, Password, and Plain Tokens,
|
||||
Bootstrap Tokens, and JWT Tokens (used for service accounts).
|
||||
|
||||
Multiple authentication modules can be specified, in which case each one is tried in sequence,
|
||||
until one of them succeeds.
|
||||
|
||||
On GCE, Client Certificates, Password, Plain Tokens, and JWT Tokens are all enabled.
|
||||
|
||||
If the request cannot be authenticated, it is rejected with HTTP status code 401.
|
||||
Otherwise, the user is authenticated as a specific `username`, and the user name
|
||||
is available to subsequent steps to use in their decisions. Some authenticators
|
||||
also provide the group memberships of the user, while other authenticators
|
||||
do not.
|
||||
|
||||
While Kubernetes uses `usernames` for access control decisions and in request logging,
|
||||
it does not have a `user` object nor does it store usernames or other information about
|
||||
users in its object store.
|
||||
|
||||
## Authorization
|
||||
|
||||
After the request is authenticated as coming from a specific user, the request must be authorized. This is shown as step **2** in the diagram.
|
||||
|
||||
A request must include the username of the requester, the requested action, and the object affected by the action. The request is authorized if an existing policy declares that the user has permissions to complete the requested action.
|
||||
|
||||
For example, if Bob has the policy below, then he can read pods only in the namespace `projectCaribou`:
|
||||
|
||||
```json
|
||||
{
|
||||
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
|
||||
"kind": "Policy",
|
||||
"spec": {
|
||||
"user": "bob",
|
||||
"namespace": "projectCaribou",
|
||||
"resource": "pods",
|
||||
"readonly": true
|
||||
}
|
||||
}
|
||||
```
|
||||
If Bob makes the following request, the request is authorized because he is allowed to read objects in the `projectCaribou` namespace:
|
||||
|
||||
```json
|
||||
{
|
||||
"apiVersion": "authorization.k8s.io/v1beta1",
|
||||
"kind": "SubjectAccessReview",
|
||||
"spec": {
|
||||
"resourceAttributes": {
|
||||
"namespace": "projectCaribou",
|
||||
"verb": "get",
|
||||
"group": "unicorn.example.org",
|
||||
"resource": "pods"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
If Bob makes a request to write (`create` or `update`) to the objects in the `projectCaribou` namespace, his authorization is denied. If Bob makes a request to read (`get`) objects in a different namespace such as `projectFish`, then his authorization is denied.
|
||||
|
||||
Kubernetes authorization requires that you use common REST attributes to interact with existing organization-wide or cloud-provider-wide access control systems. It is important to use REST formatting because these control systems might interact with other APIs besides the Kubernetes API.
|
||||
|
||||
Kubernetes supports multiple authorization modules, such as ABAC mode, RBAC Mode, and Webhook mode. When an administrator creates a cluster, they configured the authorization modules that should be used in the API server. If more than one authorization modules are configured, Kubernetes checks each module, and if any module authorizes the request, then the request can proceed. If all of the modules deny the request, then the request is denied (HTTP status code 403).
|
||||
|
||||
To learn more about Kubernetes authorization, including details about creating policies using the supported authorization modules, see [Authorization Overview](/docs/reference/access-authn-authz/authorization/).
|
||||
|
||||
|
||||
## Admission Control
|
||||
|
||||
Admission Control Modules are software modules that can modify or reject requests.
|
||||
In addition to the attributes available to Authorization Modules, Admission
|
||||
Control Modules can access the contents of the object that is being created or modified.
|
||||
|
||||
Admission controllers act on requests that create, modify, delete, or connect to (proxy) an object.
|
||||
Admission controllers do not act on requests that merely read objects.
|
||||
When multiple admission controllers are configured, they are called in order.
|
||||
|
||||
This is shown as step **3** in the diagram.
|
||||
|
||||
Unlike Authentication and Authorization Modules, if any admission controller module
|
||||
rejects, then the request is immediately rejected.
|
||||
|
||||
In addition to rejecting objects, admission controllers can also set complex defaults for
|
||||
fields.
|
||||
|
||||
The available Admission Control Modules are described [here](/docs/reference/access-authn-authz/admission-controllers/).
|
||||
|
||||
Once a request passes all admission controllers, it is validated using the validation routines
|
||||
for the corresponding API object, and then written to the object store (shown as step **4**).
|
||||
|
||||
|
||||
## API Server Ports and IPs
|
||||
|
||||
The previous discussion applies to requests sent to the secure port of the API server
|
||||
(the typical case). The API server can actually serve on 2 ports:
|
||||
|
||||
By default the Kubernetes API server serves HTTP on 2 ports:
|
||||
|
||||
1. `Localhost Port`:
|
||||
|
||||
- is intended for testing and bootstrap, and for other components of the master node
|
||||
(scheduler, controller-manager) to talk to the API
|
||||
- no TLS
|
||||
- default is port 8080, change with `--insecure-port` flag.
|
||||
- default IP is localhost, change with `--insecure-bind-address` flag.
|
||||
- request **bypasses** authentication and authorization modules.
|
||||
- request handled by admission control module(s).
|
||||
- protected by need to have host access
|
||||
|
||||
2. `Secure Port`:
|
||||
|
||||
- use whenever possible
|
||||
- uses TLS. Set cert with `--tls-cert-file` and key with `--tls-private-key-file` flag.
|
||||
- default is port 6443, change with `--secure-port` flag.
|
||||
- default IP is first non-localhost network interface, change with `--bind-address` flag.
|
||||
- request handled by authentication and authorization modules.
|
||||
- request handled by admission control module(s).
|
||||
- authentication and authorization modules run.
|
||||
|
||||
When the cluster is created by `kube-up.sh`, on Google Compute Engine (GCE),
|
||||
and on several other cloud providers, the API server serves on port 443. On
|
||||
GCE, a firewall rule is configured on the project to allow external HTTPS
|
||||
access to the API. Other cluster setup methods vary.
|
||||
|
||||
@@ -433,7 +433,7 @@ Each feature gate is designed for enabling/disabling a specific feature:
|
||||
- `DevicePlugins`: Enable the [device-plugins](/docs/concepts/cluster-administration/device-plugins/)
|
||||
based resource provisioning on nodes.
|
||||
- `DefaultPodTopologySpread`: Enables the use of `PodTopologySpread` scheduling plugin to do
|
||||
[default spreading](/docs/concepts/workloads/pods/pod/pod-topology-spread-constraints/#internal-default-constraints).
|
||||
[default spreading](/docs/concepts/workloads/pods/pod-topology-spread-constraints/#internal-default-constraints).
|
||||
- `DryRun`: Enable server-side [dry run](/docs/reference/using-api/api-concepts/#dry-run) requests
|
||||
so that validation, merging, and mutation can be tested without committing.
|
||||
- `DynamicAuditing`(*deprecated*): Used to enable dynamic auditing before v1.19.
|
||||
@@ -479,8 +479,8 @@ Each feature gate is designed for enabling/disabling a specific feature:
|
||||
- `KubeletPodResources`: Enable the kubelet's pod resources grpc endpoint.
|
||||
See [Support Device Monitoring](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/compute-device-assignment.md) for more details.
|
||||
- `LegacyNodeRoleBehavior`: When disabled, legacy behavior in service load balancers and node disruption will ignore the `node-role.kubernetes.io/master` label in favor of the feature-specific labels provided by `NodeDisruptionExclusion` and `ServiceNodeExclusion`.
|
||||
- `LocalStorageCapacityIsolation`: Enable the consumption of [local ephemeral storage](/docs/concepts/configuration/manage-compute-resources-container/) and also the `sizeLimit` property of an [emptyDir volume](/docs/concepts/storage/volumes/#emptydir).
|
||||
- `LocalStorageCapacityIsolationFSQuotaMonitoring`: When `LocalStorageCapacityIsolation` is enabled for [local ephemeral storage](/docs/concepts/configuration/manage-compute-resources-container/) and the backing filesystem for [emptyDir volumes](/docs/concepts/storage/volumes/#emptydir) supports project quotas and they are enabled, use project quotas to monitor [emptyDir volume](/docs/concepts/storage/volumes/#emptydir) storage consumption rather than filesystem walk for better performance and accuracy.
|
||||
- `LocalStorageCapacityIsolation`: Enable the consumption of [local ephemeral storage](/docs/concepts/configuration/manage-resources-containers/) and also the `sizeLimit` property of an [emptyDir volume](/docs/concepts/storage/volumes/#emptydir).
|
||||
- `LocalStorageCapacityIsolationFSQuotaMonitoring`: When `LocalStorageCapacityIsolation` is enabled for [local ephemeral storage](/docs/concepts/configuration/manage-resources-containers/) and the backing filesystem for [emptyDir volumes](/docs/concepts/storage/volumes/#emptydir) supports project quotas and they are enabled, use project quotas to monitor [emptyDir volume](/docs/concepts/storage/volumes/#emptydir) storage consumption rather than filesystem walk for better performance and accuracy.
|
||||
- `MountContainers`: Enable using utility containers on host as the volume mounter.
|
||||
- `MountPropagation`: Enable sharing volume mounted by one container to other containers or pods.
|
||||
For more details, please see [mount propagation](/docs/concepts/storage/volumes/#mount-propagation).
|
||||
@@ -490,7 +490,7 @@ Each feature gate is designed for enabling/disabling a specific feature:
|
||||
- `PersistentLocalVolumes`: Enable the usage of `local` volume type in Pods.
|
||||
Pod affinity has to be specified if requesting a `local` volume.
|
||||
- `PodDisruptionBudget`: Enable the [PodDisruptionBudget](/docs/tasks/run-application/configure-pdb/) feature.
|
||||
- `PodOverhead`: Enable the [PodOverhead](/docs/concepts/configuration/pod-overhead/) feature to account for pod overheads.
|
||||
- `PodOverhead`: Enable the [PodOverhead](/docs/concepts/scheduling-eviction/pod-overhead/) feature to account for pod overheads.
|
||||
- `PodPriority`: Enable the descheduling and preemption of Pods based on their [priorities](/docs/concepts/configuration/pod-priority-preemption/).
|
||||
- `PodReadinessGates`: Enable the setting of `PodReadinessGate` field for extending
|
||||
Pod readiness evaluation. See [Pod readiness gate](/docs/concepts/workloads/pods/pod-lifecycle/#pod-readiness-gate)
|
||||
@@ -516,7 +516,7 @@ Each feature gate is designed for enabling/disabling a specific feature:
|
||||
- `RuntimeClass`: Enable the [RuntimeClass](/docs/concepts/containers/runtime-class/) feature for selecting container runtime configurations.
|
||||
- `ScheduleDaemonSetPods`: Enable DaemonSet Pods to be scheduled by the default scheduler instead of the DaemonSet controller.
|
||||
- `SCTPSupport`: Enables the _SCTP_ `protocol` value in Pod, Service, Endpoints, EndpointSlice, and NetworkPolicy definitions.
|
||||
- `ServerSideApply`: Enables the [Sever Side Apply (SSA)](/docs/reference/using-api/api-concepts/#server-side-apply) path at the API Server.
|
||||
- `ServerSideApply`: Enables the [Sever Side Apply (SSA)](/docs/reference/using-api/server-side-apply/) path at the API Server.
|
||||
- `ServiceAccountIssuerDiscovery`: Enable OIDC discovery endpoints (issuer and JWKS URLs) for the service account issuer in the API server. See [Configure Service Accounts for Pods](/docs/tasks/configure-pod-container/configure-service-account/#service-account-issuer-discovery) for more details.
|
||||
- `ServiceAppProtocol`: Enables the `AppProtocol` field on Services and Endpoints.
|
||||
- `ServiceLoadBalancerFinalizer`: Enable finalizer protection for Service load balancers.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Container
|
||||
id: container
|
||||
date: 2018-04-12
|
||||
full_link: /docs/concepts/overview/what-is-kubernetes/#why-containers
|
||||
full_link: /docs/concepts/containers/
|
||||
short_description: >
|
||||
A lightweight and portable executable image that contains software and all of its dependencies.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Kubernetes contains several built-in tools to help you work with the Kubernetes
|
||||
|
||||
## Minikube
|
||||
|
||||
[`minikube`](/docs/tasks/tools/install-minikube/) is a tool that makes it
|
||||
[`minikube`](https://minikube.sigs.k8s.io/docs/) is a tool that makes it
|
||||
easy to run a single-node Kubernetes cluster locally on your workstation for
|
||||
development and testing purposes.
|
||||
|
||||
@@ -44,7 +44,7 @@ Use Helm to:
|
||||
|
||||
## Kompose
|
||||
|
||||
[`Kompose`](https://github.com/kubernetes-incubator/kompose) is a tool to help Docker Compose users move to Kubernetes.
|
||||
[`Kompose`](https://github.com/kubernetes/kompose) is a tool to help Docker Compose users move to Kubernetes.
|
||||
|
||||
Use Kompose to:
|
||||
|
||||
|
||||
@@ -1,4 +1,132 @@
|
||||
---
|
||||
title: Using the Kubernetes API
|
||||
title: Kubernetes API Overview
|
||||
reviewers:
|
||||
- erictune
|
||||
- lavalamp
|
||||
- jbeda
|
||||
content_type: concept
|
||||
weight: 10
|
||||
---
|
||||
card:
|
||||
name: reference
|
||||
weight: 50
|
||||
title: Overview of API
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
This section provides reference information for the Kubernetes API.
|
||||
|
||||
The REST API is the fundamental fabric of Kubernetes. All operations and
|
||||
communications between components, and external user commands are REST API
|
||||
calls that the API Server handles. Consequently, everything in the Kubernetes
|
||||
platform is treated as an API object and has a corresponding entry in the
|
||||
[API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/).
|
||||
|
||||
The [Kubernetes API reference](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/)
|
||||
lists the API for Kubernetes version {{< param "version" >}}.
|
||||
|
||||
For general background information, read
|
||||
[The Kubernetes API](/docs/concepts/overview/kubernetes-api/).
|
||||
[Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access/)
|
||||
describes how clients can authenticate to the Kubernetes API server, and how their
|
||||
requests are authorized.
|
||||
|
||||
<!-- body -->
|
||||
|
||||
The REST API is the fundamental fabric of Kubernetes. All operations and
|
||||
communications between components, and external user commands are REST API
|
||||
calls that the API Server handles. Consequently, everything in the Kubernetes
|
||||
platform is treated as an API object and has a corresponding entry in the
|
||||
API.
|
||||
|
||||
## API versioning
|
||||
|
||||
The JSON and Protobuf serialization schemas follow the same guidelines for
|
||||
schema changes. The following descriptions cover both formats.
|
||||
|
||||
The API versioning and software versioning are indirectly related.
|
||||
The [API and release versioning proposal](https://git.k8s.io/community/contributors/design-proposals/release/versioning.md)
|
||||
describes the relationship between API versioning and software versioning.
|
||||
|
||||
Different API versions indicate different levels of stability and support. You
|
||||
can find more information about the criteria for each level in the
|
||||
[API Changes documentation](https://git.k8s.io/community/contributors/devel/sig-architecture/api_changes.md#alpha-beta-and-stable-versions).
|
||||
|
||||
Here's a summary of each level:
|
||||
|
||||
- Alpha:
|
||||
- The version names contain `alpha` (for example, `v1alpha1`).
|
||||
- The software may contain bugs. Enabling a feature may expose bugs. A
|
||||
feature may be disabled by default.
|
||||
- The support for a feature may be dropped at any time without notice.
|
||||
- The API may change in incompatible ways in a later software release without notice.
|
||||
- The software is recommended for use only in short-lived testing clusters,
|
||||
due to increased risk of bugs and lack of long-term support.
|
||||
|
||||
- Beta:
|
||||
- The version names contain `beta` (for example, `v2beta3`).
|
||||
- The software is well tested. Enabling a feature is considered safe.
|
||||
Features are enabled by default.
|
||||
- The support for a feature will not be dropped, though the details may change.
|
||||
|
||||
- The schema and/or semantics of objects may change in incompatible ways in
|
||||
a subsequent beta or stable release. When this happens, migration
|
||||
instructions are provided. Schema changes may require deleting, editing, and
|
||||
re-creating API objects. The editing process may not be straightforward.
|
||||
The migration may require downtime for applications that rely on the feature.
|
||||
- The software is not recommended for production uses. Subsequent releases
|
||||
may introduce incompatible changes. If you have multiple clusters which
|
||||
can be upgraded independently, you may be able to relax this restriction.
|
||||
|
||||
{{< note >}}
|
||||
Please try beta features and provide feedback. After the features exit beta, it
|
||||
may not be practical to make more changes.
|
||||
{{< /note >}}
|
||||
|
||||
- Stable:
|
||||
- The version name is `vX` where `X` is an integer.
|
||||
- The stable versions of features appear in released software for many subsequent versions.
|
||||
|
||||
## API groups
|
||||
|
||||
[API groups](https://git.k8s.io/community/contributors/design-proposals/api-machinery/api-group.md)
|
||||
make it easier to extend the Kubernetes API.
|
||||
The API group is specified in a REST path and in the `apiVersion` field of a
|
||||
serialized object.
|
||||
|
||||
There are several API groups in Kubernetes:
|
||||
|
||||
* The *core* (also called *legacy*) group is found at REST path `/api/v1`.
|
||||
The core group is not specified as part of the `apiVersion` field, for
|
||||
example, `apiVersion: v1`.
|
||||
* The named groups are at REST path `/apis/$GROUP_NAME/$VERSION` and use
|
||||
`apiVersion: $GROUP_NAME/$VERSION` (for example, `apiVersion: batch/v1`).
|
||||
You can find the full list of supported API groups in
|
||||
[Kubernetes API reference](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#-strong-api-groups-strong-).
|
||||
|
||||
## Enabling or disabling API groups {#enabling-or-disabling}
|
||||
|
||||
Certain resources and API groups are enabled by default. You can enable or
|
||||
disable them by setting `--runtime-config` on the API server. The
|
||||
`--runtime-config` flag accepts comma separated `<key>[=<value>]` pairs
|
||||
describing the runtime configuration of the API server. If the `=<value>`
|
||||
part is omitted, it is treated as if `=true` is specified. For example:
|
||||
|
||||
- to disable `batch/v1`, set `--runtime-config=batch/v1=false`
|
||||
- to enable `batch/v2alpha1`, set `--runtime-config=batch/v2alpha1`
|
||||
|
||||
{{< note >}}
|
||||
When you enable or disable groups or resources, you need to restart the API
|
||||
server and controller manager to pick up the `--runtime-config` changes.
|
||||
{{< /note >}}
|
||||
|
||||
## Persistence
|
||||
|
||||
Kubernetes stores its serialized state in terms of the API resources by writing them into
|
||||
{{< glossary_tooltip term_id="etcd" >}}.
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
- Learn more about [API conventions](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#api-conventions)
|
||||
- Read the design documentation for
|
||||
[aggregator](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/aggregated-api-servers.md)
|
||||
|
||||
@@ -431,444 +431,14 @@ Some values of an object are typically generated before the object is persisted.
|
||||
|
||||
## Server Side Apply
|
||||
|
||||
{{< feature-state for_k8s_version="v1.16" state="beta" >}}
|
||||
|
||||
Starting from Kubernetes v1.18, if you have Server Side Apply enabled then the control plane tracks managed fields for all newly created objects.
|
||||
|
||||
### Introduction
|
||||
|
||||
Server Side Apply helps users and controllers manage their resources via
|
||||
declarative configurations. It allows them to create and/or modify their
|
||||
objects declaratively, simply by sending their fully specified intent.
|
||||
|
||||
A fully specified intent is a partial object that only includes the fields and
|
||||
values for which the user has an opinion. That intent either creates a new
|
||||
object or is [combined](#merge-strategy), by the server, with the existing object.
|
||||
|
||||
The system supports multiple appliers collaborating on a single object.
|
||||
|
||||
Changes to an object's fields are tracked through a "[field management](#field-management)"
|
||||
mechanism. When a field's value changes, ownership moves from its current
|
||||
manager to the manager making the change. When trying to apply an object, fields
|
||||
that have a different value and are owned by another manager will result in a
|
||||
[conflict](#conflicts). This is done in order to signal that the operation might undo another
|
||||
collaborator's changes. Conflicts can be forced, in which case the value will be
|
||||
overridden, and the ownership will be transferred.
|
||||
|
||||
If you remove a field from a configuration and apply the configuration, server side apply checks
|
||||
if there are any other field managers that also own the field. If the field is
|
||||
not owned by any other field managers, it is either deleted from the live
|
||||
object or reset to its default value, if it has one. The same rule applies to associative list or
|
||||
map items.
|
||||
|
||||
Server side apply is meant both as a replacement for the original `kubectl
|
||||
apply` and as a simpler mechanism for controllers to enact their changes.
|
||||
|
||||
### Field Management
|
||||
|
||||
Compared to the `last-applied` annotation managed by `kubectl`, Server Side
|
||||
Apply uses a more declarative approach, which tracks a user's field management,
|
||||
rather than a user's last applied state. This means that as a side effect of
|
||||
using Server Side Apply, information about which field manager manages each
|
||||
field in an object also becomes available.
|
||||
|
||||
For a user to manage a field, in the Server Side Apply sense, means that the
|
||||
user relies on and expects the value of the field not to change. The user who
|
||||
last made an assertion about the value of a field will be recorded as the
|
||||
current field manager. This can be done either by changing the value with
|
||||
`POST`, `PUT`, or non-apply `PATCH`, or by including the field in a config sent
|
||||
to the Server Side Apply endpoint. When using Server-Side Apply, trying to
|
||||
change a field which is managed by someone else will result in a rejected
|
||||
request (if not forced, see [Conflicts](#conflicts)).
|
||||
|
||||
When two or more appliers set a field to the same value, they share ownership of
|
||||
that field. Any subsequent attempt to change the value of the shared field, by any of
|
||||
the appliers, results in a conflict. Shared field owners may give up ownership
|
||||
of a field by removing it from their configuration.
|
||||
|
||||
Field management is stored in a`managedFields` field that is part of an object's
|
||||
[`metadata`](/docs/reference/generated/kubernetes-api/{{< latest-version >}}/#objectmeta-v1-meta).
|
||||
|
||||
A simple example of an object created by Server Side Apply could look like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
namespace: default
|
||||
labels:
|
||||
test-label: test
|
||||
managedFields:
|
||||
- manager: kubectl
|
||||
operation: Apply
|
||||
apiVersion: v1
|
||||
time: "2010-10-10T0:00:00Z"
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:metadata:
|
||||
f:labels:
|
||||
f:test-label: {}
|
||||
f:data:
|
||||
f:key: {}
|
||||
data:
|
||||
key: some value
|
||||
```
|
||||
|
||||
The above object contains a single manager in `metadata.managedFields`. The
|
||||
manager consists of basic information about the managing entity itself, like
|
||||
operation type, API version, and the fields managed by it.
|
||||
|
||||
{{< note >}}
|
||||
This field is managed by the API server and should not be changed by
|
||||
the user.
|
||||
{{< /note >}}
|
||||
|
||||
Nevertheless it is possible to change `metadata.managedFields` through an
|
||||
`Update` operation. Doing so is highly discouraged, but might be a reasonable
|
||||
option to try if, for example, the `managedFields` get into an inconsistent
|
||||
state (which clearly should not happen).
|
||||
|
||||
The format of the `managedFields` is described in the [API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#fieldsv1-v1-meta).
|
||||
|
||||
### Conflicts
|
||||
|
||||
A conflict is a special status error that occurs when an `Apply` operation tries
|
||||
to change a field, which another user also claims to manage. This prevents an
|
||||
applier from unintentionally overwriting the value set by another user. When
|
||||
this occurs, the applier has 3 options to resolve the conflicts:
|
||||
|
||||
* **Overwrite value, become sole manager:** If overwriting the value was
|
||||
intentional (or if the applier is an automated process like a controller) the
|
||||
applier should set the `force` query parameter to true and make the request
|
||||
again. This forces the operation to succeed, changes the value of the field,
|
||||
and removes the field from all other managers' entries in managedFields.
|
||||
* **Don't overwrite value, give up management claim:** If the applier doesn't
|
||||
care about the value of the field anymore, they can remove it from their
|
||||
config and make the request again. This leaves the value unchanged, and causes
|
||||
the field to be removed from the applier's entry in managedFields.
|
||||
* **Don't overwrite value, become shared manager:** If the applier still cares
|
||||
about the value of the field, but doesn't want to overwrite it, they can
|
||||
change the value of the field in their config to match the value of the object
|
||||
on the server, and make the request again. This leaves the value unchanged,
|
||||
and causes the field's management to be shared by the applier and all other
|
||||
field managers that already claimed to manage it.
|
||||
|
||||
|
||||
### Managers
|
||||
|
||||
Managers identify distinct workflows that are modifying the object (especially
|
||||
useful on conflicts!), and can be specified through the `fieldManager` query
|
||||
parameter as part of a modifying request. It is required for the apply endpoint,
|
||||
though kubectl will default it to `kubectl`. For other updates, its default is
|
||||
computed from the user-agent.
|
||||
|
||||
### Apply and Update
|
||||
|
||||
The two operation types considered by this feature are `Apply` (`PATCH` with
|
||||
content type `application/apply-patch+yaml`) and `Update` (all other operations
|
||||
which modify the object). Both operations update the `managedFields`, but behave
|
||||
a little differently.
|
||||
|
||||
{{< note >}}
|
||||
Whether you are submitting JSON data or YAML data, use `application/apply-patch+yaml` as the
|
||||
`Content-Type` header value.
|
||||
|
||||
All JSON documents are valid YAML.
|
||||
{{< /note >}}
|
||||
|
||||
For instance, only the apply operation fails on conflicts while update does
|
||||
not. Also, apply operations are required to identify themselves by providing a
|
||||
`fieldManager` query parameter, while the query parameter is optional for update
|
||||
operations. Finally, when using the apply operation you cannot have `managedFields` in the object that is being applied.
|
||||
|
||||
An example object with multiple managers could look like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
namespace: default
|
||||
labels:
|
||||
test-label: test
|
||||
managedFields:
|
||||
- manager: kubectl
|
||||
operation: Apply
|
||||
apiVersion: v1
|
||||
fields:
|
||||
f:metadata:
|
||||
f:labels:
|
||||
f:test-label: {}
|
||||
- manager: kube-controller-manager
|
||||
operation: Update
|
||||
apiVersion: v1
|
||||
time: '2019-03-30T16:00:00.000Z'
|
||||
fields:
|
||||
f:data:
|
||||
f:key: {}
|
||||
data:
|
||||
key: new value
|
||||
```
|
||||
|
||||
In this example, a second operation was run as an `Update` by the manager called
|
||||
`kube-controller-manager`. The update changed a value in the data field which
|
||||
caused the field's management to change to the `kube-controller-manager`.
|
||||
|
||||
If this update would have been an `Apply` operation, the operation
|
||||
would have failed due to conflicting ownership.
|
||||
|
||||
### Merge strategy
|
||||
|
||||
The merging strategy, implemented with Server Side Apply, provides a generally
|
||||
more stable object lifecycle. Server Side Apply tries to merge fields based on
|
||||
the fact who manages them instead of overruling just based on values. This way
|
||||
it is intended to make it easier and more stable for multiple actors updating
|
||||
the same object by causing less unexpected interference.
|
||||
|
||||
When a user sends a "fully-specified intent" object to the Server Side Apply
|
||||
endpoint, the server merges it with the live object favoring the value in the
|
||||
applied config if it is specified in both places. If the set of items present in
|
||||
the applied config is not a superset of the items applied by the same user last
|
||||
time, each missing item not managed by any other appliers is removed. For
|
||||
more information about how an object's schema is used to make decisions when
|
||||
merging, see
|
||||
[sigs.k8s.io/structured-merge-diff](https://sigs.k8s.io/structured-merge-diff).
|
||||
|
||||
A number of markers were added in Kubernetes 1.16 and 1.17, to allow API
|
||||
developers to describe the merge strategy supported by lists, maps, and
|
||||
structs. These markers can be applied to objects of the respective type,
|
||||
in Go files or in the
|
||||
[OpenAPI schema definition of the CRD](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io):
|
||||
|
||||
| Golang marker | OpenAPI extension | Accepted values | Description | Introduced in |
|
||||
|---|---|---|---|---|
|
||||
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | Applicable to lists. `atomic` and `set` apply to lists with scalar elements only. `map` applies to lists of nested types only. If configured as `atomic`, the entire list is replaced during merge; a single manager manages the list as a whole at any one time. If `granular`, different managers can manage entries separately. | 1.16 |
|
||||
| `//+listMapKey` | `x-kubernetes-list-map-keys` | Slice of map keys that uniquely identify entries for example `["port", "protocol"]` | Only applicable when `+listType=map`. A slice of strings whose values in combination must uniquely identify list entries. While there can be multiple keys, `listMapKey` is singular because keys need to be specified individually in the Go type. | 1.16 |
|
||||
| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to maps. `atomic` means that the map can only be entirely replaced by a single manager. `granular` means that the map supports separate managers updating individual fields. | 1.17 |
|
||||
| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to structs; otherwise same usage and OpenAPI annotation as `//+mapType`.| 1.17 |
|
||||
|
||||
### Custom Resources
|
||||
|
||||
By default, Server Side Apply treats custom resources as unstructured data. All
|
||||
keys are treated the same as struct fields, and all lists are considered atomic.
|
||||
|
||||
If the Custom Resource Definition defines a
|
||||
[schema](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io)
|
||||
that contains annotations as defined in the previous "Merge Strategy"
|
||||
section, these annotations will be used when merging objects of this
|
||||
type.
|
||||
|
||||
### Using Server-Side Apply in a controller
|
||||
|
||||
As a developer of a controller, you can use server-side apply as a way to
|
||||
simplify the update logic of your controller. The main differences with a
|
||||
read-modify-write and/or patch are the following:
|
||||
|
||||
* the applied object must contain all the fields that the controller cares about.
|
||||
* there are no way to remove fields that haven't been applied by the controller
|
||||
before (controller can still send a PATCH/UPDATE for these use-cases).
|
||||
* the object doesn't have to be read beforehand, `resourceVersion` doesn't have
|
||||
to be specified.
|
||||
|
||||
It is strongly recommended for controllers to always "force" conflicts, since they
|
||||
might not be able to resolve or act on these conflicts.
|
||||
|
||||
### Transferring Ownership
|
||||
|
||||
In addition to the concurrency controls provided by [conflict resolution](#conflicts),
|
||||
Server Side Apply provides ways to perform coordinated
|
||||
field ownership transfers from users to controllers.
|
||||
|
||||
This is best explained by example. Let's look at how to safely transfer
|
||||
ownership of the `replicas` field from a user to a controller while enabling
|
||||
automatic horizontal scaling for a Deployment, using the HorizontalPodAutoscaler
|
||||
resource and its accompanying controller.
|
||||
|
||||
Say a user has defined deployment with `replicas` set to the desired value:
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment.yaml" >}}
|
||||
|
||||
And the user has created the deployment using server side apply like so:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment.yaml --server-side
|
||||
```
|
||||
|
||||
Then later, HPA is enabled for the deployment, e.g.:
|
||||
|
||||
```shell
|
||||
kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10
|
||||
```
|
||||
|
||||
Now, the user would like to remove `replicas` from their configuration, so they
|
||||
don't accidentally fight with the HPA controller. However, there is a race: it
|
||||
might take some time before HPA feels the need to adjust `replicas`, and if
|
||||
the user removes `replicas` before the HPA writes to the field and becomes
|
||||
its owner, then apiserver will set `replicas` to 1, its default value. This
|
||||
is not what the user wants to happen, even temporarily.
|
||||
|
||||
There are two solutions:
|
||||
|
||||
- (easy) Leave `replicas` in the configuration; when HPA eventually writes to that
|
||||
field, the system gives the user a conflict over it. At that point, it is safe
|
||||
to remove from the configuration.
|
||||
|
||||
- (more advanced) If, however, the user doesn't want to wait, for example
|
||||
because they want to keep the cluster legible to coworkers, then they can take
|
||||
the following steps to make it safe to remove `replicas` from their
|
||||
configuration:
|
||||
|
||||
First, the user defines a new configuration containing only the `replicas` field:
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment-replicas-only.yaml" >}}
|
||||
|
||||
The user applies that configuration using the field manager name `handover-to-hpa`:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment-replicas-only.yaml --server-side --field-manager=handover-to-hpa --validate=false
|
||||
```
|
||||
|
||||
If the apply results in a conflict with the HPA controller, then do nothing. The
|
||||
conflict just indicates the controller has claimed the field earlier in the
|
||||
process than it sometimes does.
|
||||
|
||||
At this point the user may remove the `replicas` field from their configuration.
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment-no-replicas.yaml" >}}
|
||||
|
||||
Note that whenever the HPA controller sets the `replicas` field to a new value,
|
||||
the temporary field manager will no longer own any fields and will be
|
||||
automatically deleted. No clean up is required.
|
||||
|
||||
### Transferring Ownership Between Users
|
||||
|
||||
Users can transfer ownership of a field between each other by setting the field
|
||||
to the same value in both of their applied configs, causing them to share
|
||||
ownership of the field. Once the users share ownership of the field, one of them
|
||||
can remove the field from their applied configuration to give up ownership and
|
||||
complete the transfer to the other user.
|
||||
|
||||
### Comparison with Client Side Apply
|
||||
|
||||
A consequence of the conflict detection and resolution implemented by Server
|
||||
Side Apply is that an applier always has up to date field values in their local
|
||||
state. If they don't, they get a conflict the next time they apply. Any of the
|
||||
three options to resolve conflicts results in the applied configuration being an
|
||||
up to date subset of the object on the server's fields.
|
||||
|
||||
This is different from Client Side Apply, where outdated values which have been
|
||||
overwritten by other users are left in an applier's local config. These values
|
||||
only become accurate when the user updates that specific field, if ever, and an
|
||||
applier has no way of knowing whether their next apply will overwrite other
|
||||
users' changes.
|
||||
|
||||
Another difference is that an applier using Client Side Apply is unable to
|
||||
change the API version they are using, but Server Side Apply supports this use
|
||||
case.
|
||||
|
||||
### Upgrading from client-side apply to server-side apply
|
||||
|
||||
Client-side apply users who manage a resource with `kubectl apply` can start
|
||||
using server-side apply with the following flag.
|
||||
|
||||
```shell
|
||||
kubectl apply --server-side [--dry-run=server]
|
||||
```
|
||||
|
||||
By default, field management of the object transfers from client-side apply
|
||||
to kubectl server-side apply without encountering conflicts.
|
||||
|
||||
{{< caution >}}
|
||||
Keep the `last-applied-configuration` annotation up to date.
|
||||
The annotation infers client-side apply's managed fields.
|
||||
Any fields not managed by client-side apply raise conflicts.
|
||||
|
||||
For example, if you used `kubectl scale` to update the replicas field after client-side apply,
|
||||
then this field is not owned by client-side apply and creates conflicts on `kubectl apply --server-side`.
|
||||
{{< /caution >}}
|
||||
|
||||
This behavior applies to server-side apply with the `kubectl` field manager. As
|
||||
an exception, you can opt-out of this behavior by specifying a different,
|
||||
non-default field manager, as seen in the following example. The default field manager for kubectl
|
||||
server-side apply is `kubectl`.
|
||||
|
||||
```shell
|
||||
kubectl apply --server-side --field-manager=my-manager [--dry-run=server]
|
||||
```
|
||||
|
||||
### Downgrading from server-side apply to client-side apply
|
||||
|
||||
If you manage a resource with `kubectl apply --server-side`,
|
||||
you can downgrade to client-side apply directly with `kubectl apply`.
|
||||
|
||||
Downgrading works because kubectl server-side apply keeps the
|
||||
`last-applied-configuration` annotation up-to-date if you use
|
||||
`kubectl apply`.
|
||||
|
||||
This behavior applies to server-side apply with the `kubectl` field manager. As
|
||||
an exception, you can opt-out of this behavior by specifying a different,
|
||||
non-default field manager, as seen in the following example. The default field manager for kubectl
|
||||
server-side apply is `kubectl`.
|
||||
|
||||
```shell
|
||||
kubectl apply --server-side --field-manager=my-manager [--dry-run=server]
|
||||
```
|
||||
|
||||
### API Endpoint
|
||||
|
||||
With the Server Side Apply feature enabled, the `PATCH` endpoint accepts the
|
||||
additional `application/apply-patch+yaml` content type. Users of Server Side
|
||||
Apply can send partially specified objects as YAML to this endpoint.
|
||||
When applying a configuration, one should always include all the fields
|
||||
that they have an opinion about.
|
||||
|
||||
### Clearing ManagedFields
|
||||
|
||||
It is possible to strip all managedFields from an object by overwriting them
|
||||
using `MergePatch`, `StrategicMergePatch`, `JSONPatch` or `Update`, so every
|
||||
non-apply operation. This can be done by overwriting the managedFields field
|
||||
with an empty entry. Two examples are:
|
||||
|
||||
```console
|
||||
PATCH /api/v1/namespaces/default/configmaps/example-cm
|
||||
Content-Type: application/merge-patch+json
|
||||
Accept: application/json
|
||||
Data: {"metadata":{"managedFields": [{}]}}
|
||||
```
|
||||
|
||||
```console
|
||||
PATCH /api/v1/namespaces/default/configmaps/example-cm
|
||||
Content-Type: application/json-patch+json
|
||||
Accept: application/json
|
||||
Data: [{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}]
|
||||
```
|
||||
|
||||
This will overwrite the managedFields with a list containing a single empty
|
||||
entry that then results in the managedFields being stripped entirely from the
|
||||
object. Note that just setting the managedFields to an empty list will not reset
|
||||
the field. This is on purpose, so managedFields never get stripped by clients
|
||||
not aware of the field.
|
||||
|
||||
In cases where the reset operation is combined with changes to other fields than
|
||||
the managedFields, this will result in the managedFields being reset first and
|
||||
the other changes being processed afterwards. As a result the applier takes
|
||||
ownership of any fields updated in the same request.
|
||||
|
||||
{{< caution >}}
|
||||
Server Side Apply does not correctly track ownership on
|
||||
sub-resources that don't receive the resource object type. If you are
|
||||
using Server Side Apply with such a sub-resource, the changed fields
|
||||
won't be tracked.
|
||||
{{< /caution >}}
|
||||
|
||||
### Disabling the feature
|
||||
|
||||
Server Side Apply is a beta feature, so it is enabled by default. To turn this
|
||||
[feature gate](/docs/reference/command-line-tools-reference/feature-gates) off,
|
||||
you need to include the `--feature-gates ServerSideApply=false` flag when
|
||||
starting `kube-apiserver`. If you have multiple `kube-apiserver` replicas, all
|
||||
should have the same flag setting.
|
||||
Starting from Kubernetes v1.18, you can enable the
|
||||
[Server Side Apply](/docs/reference/using-api/server-side-apply/)
|
||||
feature so that the control plane tracks managed fields for all newly created objects.
|
||||
Server Side Apply provides a clear pattern for managing field conflicts,
|
||||
offers server-side `Apply` and `Update` operations, and replaces the
|
||||
client-side functionality of `kubectl apply`. For more details about this
|
||||
feature, see the section on
|
||||
[Server Side Apply](/docs/reference/using-api/server-side-apply/).
|
||||
|
||||
## Resource Versions
|
||||
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
---
|
||||
title: Kubernetes API Overview
|
||||
reviewers:
|
||||
- erictune
|
||||
- lavalamp
|
||||
- jbeda
|
||||
content_type: concept
|
||||
weight: 10
|
||||
card:
|
||||
name: reference
|
||||
weight: 50
|
||||
title: Overview of API
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
This page provides an overview of the Kubernetes API.
|
||||
|
||||
<!-- body -->
|
||||
|
||||
The REST API is the fundamental fabric of Kubernetes. All operations and
|
||||
communications between components, and external user commands are REST API
|
||||
calls that the API Server handles. Consequently, everything in the Kubernetes
|
||||
platform is treated as an API object and has a corresponding entry in the
|
||||
[API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/).
|
||||
|
||||
## API versioning
|
||||
|
||||
The JSON and Protobuf serialization schemas follow the same guidelines for
|
||||
schema changes. The following descriptions cover both formats.
|
||||
|
||||
The API versioning and software versioning are indirectly related.
|
||||
The [API and release versioning proposal](https://git.k8s.io/community/contributors/design-proposals/release/versioning.md)
|
||||
describes the relationship between API versioning and software versioning.
|
||||
|
||||
Different API versions indicate different levels of stability and support. You
|
||||
can find more information about the criteria for each level in the
|
||||
[API Changes documentation](https://git.k8s.io/community/contributors/devel/sig-architecture/api_changes.md#alpha-beta-and-stable-versions).
|
||||
|
||||
Here's a summary of each level:
|
||||
|
||||
- Alpha:
|
||||
- The version names contain `alpha` (for example, `v1alpha1`).
|
||||
- The software may contain bugs. Enabling a feature may expose bugs. A
|
||||
feature may be disabled by default.
|
||||
- The support for a feature may be dropped at any time without notice.
|
||||
- The API may change in incompatible ways in a later software release without notice.
|
||||
- The software is recommended for use only in short-lived testing clusters,
|
||||
due to increased risk of bugs and lack of long-term support.
|
||||
|
||||
- Beta:
|
||||
- The version names contain `beta` (for example, `v2beta3`).
|
||||
- The software is well tested. Enabling a feature is considered safe.
|
||||
Features are enabled by default.
|
||||
- The support for a feature will not be dropped, though the details may change.
|
||||
|
||||
- The schema and/or semantics of objects may change in incompatible ways in
|
||||
a subsequent beta or stable release. When this happens, migration
|
||||
instructions are provided. Schema changes may require deleting, editing, and
|
||||
re-creating API objects. The editing process may not be straightforward.
|
||||
The migration may require downtime for applications that rely on the feature.
|
||||
- The software is not recommended for production uses. Subsequent releases
|
||||
may introduce incompatible changes. If you have multiple clusters which
|
||||
can be upgraded independently, you may be able to relax this restriction.
|
||||
|
||||
{{< note >}}
|
||||
Try the beta features and provide feedback. After the features exit beta, it
|
||||
may not be practical to make more changes.
|
||||
{{< /note >}}
|
||||
|
||||
- Stable:
|
||||
- The version name is `vX` where `X` is an integer.
|
||||
- The stable versions of features appear in released software for many subsequent versions.
|
||||
|
||||
## API groups
|
||||
|
||||
[API groups](https://git.k8s.io/community/contributors/design-proposals/api-machinery/api-group.md)
|
||||
make it easier to extend the Kubernetes API.
|
||||
The API group is specified in a REST path and in the `apiVersion` field of a
|
||||
serialized object.
|
||||
|
||||
Currently, there are several API groups in use:
|
||||
|
||||
* The *core* (also called *legacy*) group is found at REST path `/api/v1`.
|
||||
The core group is not specified as part of the `apiVersion` field, for
|
||||
example, `apiVersion: v1`.
|
||||
* The named groups are at REST path `/apis/$GROUP_NAME/$VERSION` and use
|
||||
`apiVersion: $GROUP_NAME/$VERSION` (for example, `apiVersion: batch/v1`).
|
||||
You can find the full list of supported API groups in
|
||||
[Kubernetes API reference](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/).
|
||||
|
||||
## Enabling or disabling API groups {#enabling-or-disabling}
|
||||
|
||||
Certain resources and API groups are enabled by default. You can enable or
|
||||
disable them by setting `--runtime-config` on the API server. The
|
||||
`--runtime-config` flag accepts comma separated `<key>=<value>` pairs
|
||||
describing the runtime configuration of the API server. For example:
|
||||
|
||||
- to disable `batch/v1`, set `--runtime-config=batch/v1=false`
|
||||
- to enable `batch/v2alpha1`, set `--runtime-config=batch/v2alpha1`
|
||||
|
||||
{{< note >}}
|
||||
When you enable or disable groups or resources, you need to restart the API
|
||||
server and controller manager to pick up the `--runtime-config` changes.
|
||||
{{< /note >}}
|
||||
|
||||
## Persistence
|
||||
|
||||
Kubernetes stores its serialized state in terms of the API resources by writing them into
|
||||
{{< glossary_tooltip term_id="etcd" >}}.
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
- Learn more about [API conventions](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#api-conventions)
|
||||
- Read the design documentation for
|
||||
[aggregator](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/api-machinery/aggregated-api-servers.md)
|
||||
|
||||
@@ -12,7 +12,7 @@ API from various programming languages.
|
||||
|
||||
|
||||
<!-- body -->
|
||||
To write applications using the [Kubernetes REST API](/docs/reference/using-api/api-overview/),
|
||||
To write applications using the [Kubernetes REST API](/docs/reference/using-api/),
|
||||
you do not need to implement the API calls and request/response types yourself.
|
||||
You can use a client library for the programming language you are using.
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ a deprecation policy for aspects of the system that are slated to be removed.
|
||||
Since Kubernetes is an API-driven system, the API has evolved over time to
|
||||
reflect the evolving understanding of the problem space. The Kubernetes API is
|
||||
actually a set of APIs, called "API groups", and each API group is
|
||||
independently versioned. [API versions](/docs/reference/using-api/api-overview/#api-versioning) fall
|
||||
independently versioned. [API versions](/docs/reference/using-api/#api-versioning) fall
|
||||
into 3 main tracks, each of which has different policies for deprecation:
|
||||
|
||||
| Example | Track |
|
||||
|
||||
@@ -0,0 +1,462 @@
|
||||
---
|
||||
title: Server-Side Apply
|
||||
reviewers:
|
||||
- smarterclayton
|
||||
- apelisse
|
||||
- lavalamp
|
||||
- liggitt
|
||||
content_type: concept
|
||||
weight: 25
|
||||
min-kubernetes-server-version: 1.16
|
||||
---
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.16" state="beta" >}}
|
||||
|
||||
## Introduction
|
||||
|
||||
Server Side Apply helps users and controllers manage their resources via
|
||||
declarative configurations. It allows them to create and/or modify their
|
||||
[objects](/docs/concepts/overview/working-with-objects/kubernetes-objects/)
|
||||
declaratively, simply by sending their fully specified intent.
|
||||
|
||||
A fully specified intent is a partial object that only includes the fields and
|
||||
values for which the user has an opinion. That intent either creates a new
|
||||
object or is [combined](#merge-strategy), by the server, with the existing object.
|
||||
|
||||
The system supports multiple appliers collaborating on a single object.
|
||||
|
||||
Changes to an object's fields are tracked through a "[field management](#field-management)"
|
||||
mechanism. When a field's value changes, ownership moves from its current
|
||||
manager to the manager making the change. When trying to apply an object,
|
||||
fields that have a different value and are owned by another manager will
|
||||
result in a [conflict](#conflicts). This is done in order to signal that the
|
||||
operation might undo another collaborator's changes. Conflicts can be forced,
|
||||
in which case the value will be overridden, and the ownership will be
|
||||
transferred.
|
||||
|
||||
If you remove a field from a configuration and apply the configuration, server
|
||||
side apply checks if there are any other field managers that also own the
|
||||
field. If the field is not owned by any other field managers, it is either
|
||||
deleted from the live object or reset to its default value, if it has one. The
|
||||
same rule applies to associative list or map items.
|
||||
|
||||
Server side apply is meant both as a replacement for the original `kubectl
|
||||
apply` and as a simpler mechanism for controllers to enact their changes.
|
||||
|
||||
If you have Server Side Apply enabled, the control plane tracks managed fields
|
||||
for all newlly created objects.
|
||||
|
||||
## Field Management
|
||||
|
||||
Compared to the `last-applied` annotation managed by `kubectl`, Server Side
|
||||
Apply uses a more declarative approach, which tracks a user's field management,
|
||||
rather than a user's last applied state. This means that as a side effect of
|
||||
using Server Side Apply, information about which field manager manages each
|
||||
field in an object also becomes available.
|
||||
|
||||
For a user to manage a field, in the Server Side Apply sense, means that the
|
||||
user relies on and expects the value of the field not to change. The user who
|
||||
last made an assertion about the value of a field will be recorded as the
|
||||
current field manager. This can be done either by changing the value with
|
||||
`POST`, `PUT`, or non-apply `PATCH`, or by including the field in a config sent
|
||||
to the Server Side Apply endpoint. When using Server-Side Apply, trying to
|
||||
change a field which is managed by someone else will result in a rejected
|
||||
request (if not forced, see [Conflicts](#conflicts)).
|
||||
|
||||
When two or more appliers set a field to the same value, they share ownership of
|
||||
that field. Any subsequent attempt to change the value of the shared field, by any of
|
||||
the appliers, results in a conflict. Shared field owners may give up ownership
|
||||
of a field by removing it from their configuration.
|
||||
|
||||
Field management is stored in a`managedFields` field that is part of an object's
|
||||
[`metadata`](/docs/reference/generated/kubernetes-api/{{< latest-version >}}/#objectmeta-v1-meta).
|
||||
|
||||
A simple example of an object created by Server Side Apply could look like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
namespace: default
|
||||
labels:
|
||||
test-label: test
|
||||
managedFields:
|
||||
- manager: kubectl
|
||||
operation: Apply
|
||||
apiVersion: v1
|
||||
time: "2010-10-10T0:00:00Z"
|
||||
fieldsType: FieldsV1
|
||||
fieldsV1:
|
||||
f:metadata:
|
||||
f:labels:
|
||||
f:test-label: {}
|
||||
f:data:
|
||||
f:key: {}
|
||||
data:
|
||||
key: some value
|
||||
```
|
||||
|
||||
The above object contains a single manager in `metadata.managedFields`. The
|
||||
manager consists of basic information about the managing entity itself, like
|
||||
operation type, API version, and the fields managed by it.
|
||||
|
||||
{{< note >}}
|
||||
This field is managed by the API server and should not be changed by
|
||||
the user.
|
||||
{{< /note >}}
|
||||
|
||||
Nevertheless it is possible to change `metadata.managedFields` through an
|
||||
`Update` operation. Doing so is highly discouraged, but might be a reasonable
|
||||
option to try if, for example, the `managedFields` get into an inconsistent
|
||||
state (which clearly should not happen).
|
||||
|
||||
The format of the `managedFields` is described in the
|
||||
[API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#fieldsv1-v1-meta).
|
||||
|
||||
## Conflicts
|
||||
|
||||
A conflict is a special status error that occurs when an `Apply` operation tries
|
||||
to change a field, which another user also claims to manage. This prevents an
|
||||
applier from unintentionally overwriting the value set by another user. When
|
||||
this occurs, the applier has 3 options to resolve the conflicts:
|
||||
|
||||
* **Overwrite value, become sole manager:** If overwriting the value was
|
||||
intentional (or if the applier is an automated process like a controller) the
|
||||
applier should set the `force` query parameter to true and make the request
|
||||
again. This forces the operation to succeed, changes the value of the field,
|
||||
and removes the field from all other managers' entries in managedFields.
|
||||
|
||||
* **Don't overwrite value, give up management claim:** If the applier doesn't
|
||||
care about the value of the field anymore, they can remove it from their
|
||||
config and make the request again. This leaves the value unchanged, and causes
|
||||
the field to be removed from the applier's entry in managedFields.
|
||||
|
||||
* **Don't overwrite value, become shared manager:** If the applier still cares
|
||||
about the value of the field, but doesn't want to overwrite it, they can
|
||||
change the value of the field in their config to match the value of the object
|
||||
on the server, and make the request again. This leaves the value unchanged,
|
||||
and causes the field's management to be shared by the applier and all other
|
||||
field managers that already claimed to manage it.
|
||||
|
||||
## Managers
|
||||
|
||||
Managers identify distinct workflows that are modifying the object (especially
|
||||
useful on conflicts!), and can be specified through the `fieldManager` query
|
||||
parameter as part of a modifying request. It is required for the apply endpoint,
|
||||
though kubectl will default it to `kubectl`. For other updates, its default is
|
||||
computed from the user-agent.
|
||||
|
||||
## Apply and Update
|
||||
|
||||
The two operation types considered by this feature are `Apply` (`PATCH` with
|
||||
content type `application/apply-patch+yaml`) and `Update` (all other operations
|
||||
which modify the object). Both operations update the `managedFields`, but behave
|
||||
a little differently.
|
||||
|
||||
{{< note >}}
|
||||
Whether you are submitting JSON data or YAML data, use
|
||||
`application/apply-patch+yaml` as the `Content-Type` header value.
|
||||
|
||||
All JSON documents are valid YAML.
|
||||
{{< /note >}}
|
||||
|
||||
For instance, only the apply operation fails on conflicts while update does
|
||||
not. Also, apply operations are required to identify themselves by providing a
|
||||
`fieldManager` query parameter, while the query parameter is optional for update
|
||||
operations. Finally, when using the apply operation you cannot have
|
||||
`managedFields` in the object that is being applied.
|
||||
|
||||
An example object with multiple managers could look like this:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: test-cm
|
||||
namespace: default
|
||||
labels:
|
||||
test-label: test
|
||||
managedFields:
|
||||
- manager: kubectl
|
||||
operation: Apply
|
||||
apiVersion: v1
|
||||
fields:
|
||||
f:metadata:
|
||||
f:labels:
|
||||
f:test-label: {}
|
||||
- manager: kube-controller-manager
|
||||
operation: Update
|
||||
apiVersion: v1
|
||||
time: '2019-03-30T16:00:00.000Z'
|
||||
fields:
|
||||
f:data:
|
||||
f:key: {}
|
||||
data:
|
||||
key: new value
|
||||
```
|
||||
|
||||
In this example, a second operation was run as an `Update` by the manager called
|
||||
`kube-controller-manager`. The update changed a value in the data field which
|
||||
caused the field's management to change to the `kube-controller-manager`.
|
||||
|
||||
If this update would have been an `Apply` operation, the operation
|
||||
would have failed due to conflicting ownership.
|
||||
|
||||
## Merge strategy
|
||||
|
||||
The merging strategy, implemented with Server Side Apply, provides a generally
|
||||
more stable object lifecycle. Server Side Apply tries to merge fields based on
|
||||
the fact who manages them instead of overruling just based on values. This way
|
||||
it is intended to make it easier and more stable for multiple actors updating
|
||||
the same object by causing less unexpected interference.
|
||||
|
||||
When a user sends a "fully-specified intent" object to the Server Side Apply
|
||||
endpoint, the server merges it with the live object favoring the value in the
|
||||
applied config if it is specified in both places. If the set of items present in
|
||||
the applied config is not a superset of the items applied by the same user last
|
||||
time, each missing item not managed by any other appliers is removed. For
|
||||
more information about how an object's schema is used to make decisions when
|
||||
merging, see
|
||||
[sigs.k8s.io/structured-merge-diff](https://sigs.k8s.io/structured-merge-diff).
|
||||
|
||||
A number of markers were added in Kubernetes 1.16 and 1.17, to allow API
|
||||
developers to describe the merge strategy supported by lists, maps, and
|
||||
structs. These markers can be applied to objects of the respective type,
|
||||
in Go files or in the OpenAPI schema definition of the
|
||||
[CRD](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io):
|
||||
|
||||
| Golang marker | OpenAPI extension | Accepted values | Description | Introduced in |
|
||||
|---|---|---|---|---|
|
||||
| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | Applicable to lists. `atomic` and `set` apply to lists with scalar elements only. `map` applies to lists of nested types only. If configured as `atomic`, the entire list is replaced during merge; a single manager manages the list as a whole at any one time. If `granular`, different managers can manage entries separately. | 1.16 |
|
||||
| `//+listMapKey` | `x-kubernetes-list-map-keys` | Slice of map keys that uniquely identify entries for example `["port", "protocol"]` | Only applicable when `+listType=map`. A slice of strings whose values in combination must uniquely identify list entries. While there can be multiple keys, `listMapKey` is singular because keys need to be specified individually in the Go type. | 1.16 |
|
||||
| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to maps. `atomic` means that the map can only be entirely replaced by a single manager. `granular` means that the map supports separate managers updating individual fields. | 1.17 |
|
||||
| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | Applicable to structs; otherwise same usage and OpenAPI annotation as `//+mapType`.| 1.17 |
|
||||
|
||||
### Custom Resources
|
||||
|
||||
By default, Server Side Apply treats custom resources as unstructured data. All
|
||||
keys are treated the same as struct fields, and all lists are considered atomic.
|
||||
|
||||
If the Custom Resource Definition defines a
|
||||
[schema](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io)
|
||||
that contains annotations as defined in the previous "Merge Strategy"
|
||||
section, these annotations will be used when merging objects of this
|
||||
type.
|
||||
|
||||
### Using Server-Side Apply in a controller
|
||||
|
||||
As a developer of a controller, you can use server-side apply as a way to
|
||||
simplify the update logic of your controller. The main differences with a
|
||||
read-modify-write and/or patch are the following:
|
||||
|
||||
* the applied object must contain all the fields that the controller cares about.
|
||||
* there are no way to remove fields that haven't been applied by the controller
|
||||
before (controller can still send a PATCH/UPDATE for these use-cases).
|
||||
* the object doesn't have to be read beforehand, `resourceVersion` doesn't have
|
||||
to be specified.
|
||||
|
||||
It is strongly recommended for controllers to always "force" conflicts, since they
|
||||
might not be able to resolve or act on these conflicts.
|
||||
|
||||
### Transferring Ownership
|
||||
|
||||
In addition to the concurrency controls provided by [conflict resolution](#conflicts),
|
||||
Server Side Apply provides ways to perform coordinated
|
||||
field ownership transfers from users to controllers.
|
||||
|
||||
This is best explained by example. Let's look at how to safely transfer
|
||||
ownership of the `replicas` field from a user to a controller while enabling
|
||||
automatic horizontal scaling for a Deployment, using the HorizontalPodAutoscaler
|
||||
resource and its accompanying controller.
|
||||
|
||||
Say a user has defined deployment with `replicas` set to the desired value:
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment.yaml" >}}
|
||||
|
||||
And the user has created the deployment using server side apply like so:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment.yaml --server-side
|
||||
```
|
||||
|
||||
Then later, HPA is enabled for the deployment, e.g.:
|
||||
|
||||
```shell
|
||||
kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10
|
||||
```
|
||||
|
||||
Now, the user would like to remove `replicas` from their configuration, so they
|
||||
don't accidentally fight with the HPA controller. However, there is a race: it
|
||||
might take some time before HPA feels the need to adjust `replicas`, and if
|
||||
the user removes `replicas` before the HPA writes to the field and becomes
|
||||
its owner, then apiserver will set `replicas` to 1, its default value. This
|
||||
is not what the user wants to happen, even temporarily.
|
||||
|
||||
There are two solutions:
|
||||
|
||||
- (easy) Leave `replicas` in the configuration; when HPA eventually writes to that
|
||||
field, the system gives the user a conflict over it. At that point, it is safe
|
||||
to remove from the configuration.
|
||||
|
||||
- (more advanced) If, however, the user doesn't want to wait, for example
|
||||
because they want to keep the cluster legible to coworkers, then they can take
|
||||
the following steps to make it safe to remove `replicas` from their
|
||||
configuration:
|
||||
|
||||
First, the user defines a new configuration containing only the `replicas` field:
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment-replicas-only.yaml" >}}
|
||||
|
||||
The user applies that configuration using the field manager name `handover-to-hpa`:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment-replicas-only.yaml \
|
||||
--server-side --field-manager=handover-to-hpa \
|
||||
--validate=false
|
||||
```
|
||||
|
||||
If the apply results in a conflict with the HPA controller, then do nothing. The
|
||||
conflict just indicates the controller has claimed the field earlier in the
|
||||
process than it sometimes does.
|
||||
|
||||
At this point the user may remove the `replicas` field from their configuration.
|
||||
|
||||
{{< codenew file="application/ssa/nginx-deployment-no-replicas.yaml" >}}
|
||||
|
||||
Note that whenever the HPA controller sets the `replicas` field to a new value,
|
||||
the temporary field manager will no longer own any fields and will be
|
||||
automatically deleted. No clean up is required.
|
||||
|
||||
## Transferring Ownership Between Users
|
||||
|
||||
Users can transfer ownership of a field between each other by setting the field
|
||||
to the same value in both of their applied configs, causing them to share
|
||||
ownership of the field. Once the users share ownership of the field, one of them
|
||||
can remove the field from their applied configuration to give up ownership and
|
||||
complete the transfer to the other user.
|
||||
|
||||
## Comparison with Client Side Apply
|
||||
|
||||
A consequence of the conflict detection and resolution implemented by Server
|
||||
Side Apply is that an applier always has up to date field values in their local
|
||||
state. If they don't, they get a conflict the next time they apply. Any of the
|
||||
three options to resolve conflicts results in the applied configuration being an
|
||||
up to date subset of the object on the server's fields.
|
||||
|
||||
This is different from Client Side Apply, where outdated values which have been
|
||||
overwritten by other users are left in an applier's local config. These values
|
||||
only become accurate when the user updates that specific field, if ever, and an
|
||||
applier has no way of knowing whether their next apply will overwrite other
|
||||
users' changes.
|
||||
|
||||
Another difference is that an applier using Client Side Apply is unable to
|
||||
change the API version they are using, but Server Side Apply supports this use
|
||||
case.
|
||||
|
||||
## Upgrading from client-side apply to server-side apply
|
||||
|
||||
Client-side apply users who manage a resource with `kubectl apply` can start
|
||||
using server-side apply with the following flag.
|
||||
|
||||
```shell
|
||||
kubectl apply --server-side [--dry-run=server]
|
||||
```
|
||||
|
||||
By default, field management of the object transfers from client-side apply to
|
||||
kubectl server-side apply without encountering conflicts.
|
||||
|
||||
{{< caution >}}
|
||||
Keep the `last-applied-configuration` annotation up to date.
|
||||
The annotation infers client-side apply's managed fields.
|
||||
Any fields not managed by client-side apply raise conflicts.
|
||||
|
||||
For example, if you used `kubectl scale` to update the replicas field after
|
||||
client-side apply, then this field is not owned by client-side apply and
|
||||
creates conflicts on `kubectl apply --server-side`.
|
||||
{{< /caution >}}
|
||||
|
||||
This behavior applies to server-side apply with the `kubectl` field manager.
|
||||
As an exception, you can opt-out of this behavior by specifying a different,
|
||||
non-default field manager, as seen in the following example. The default field
|
||||
manager for kubectl server-side apply is `kubectl`.
|
||||
|
||||
```shell
|
||||
kubectl apply --server-side --field-manager=my-manager [--dry-run=server]
|
||||
```
|
||||
|
||||
## Downgrading from server-side apply to client-side apply
|
||||
|
||||
If you manage a resource with `kubectl apply --server-side`,
|
||||
you can downgrade to client-side apply directly with `kubectl apply`.
|
||||
|
||||
Downgrading works because kubectl server-side apply keeps the
|
||||
`last-applied-configuration` annotation up-to-date if you use
|
||||
`kubectl apply`.
|
||||
|
||||
This behavior applies to server-side apply with the `kubectl` field manager.
|
||||
As an exception, you can opt-out of this behavior by specifying a different,
|
||||
non-default field manager, as seen in the following example. The default field
|
||||
manager for kubectl server-side apply is `kubectl`.
|
||||
|
||||
```shell
|
||||
kubectl apply --server-side --field-manager=my-manager [--dry-run=server]
|
||||
```
|
||||
|
||||
## API Endpoint
|
||||
|
||||
With the Server Side Apply feature enabled, the `PATCH` endpoint accepts the
|
||||
additional `application/apply-patch+yaml` content type. Users of Server Side
|
||||
Apply can send partially specified objects as YAML to this endpoint. When
|
||||
applying a configuration, one should always include all the fields that they
|
||||
have an opinion about.
|
||||
|
||||
## Clearing ManagedFields
|
||||
|
||||
It is possible to strip all managedFields from an object by overwriting them
|
||||
using `MergePatch`, `StrategicMergePatch`, `JSONPatch` or `Update`, so every
|
||||
non-apply operation. This can be done by overwriting the managedFields field
|
||||
with an empty entry. Two examples are:
|
||||
|
||||
```console
|
||||
PATCH /api/v1/namespaces/default/configmaps/example-cm
|
||||
Content-Type: application/merge-patch+json
|
||||
Accept: application/json
|
||||
Data: {"metadata":{"managedFields": [{}]}}
|
||||
```
|
||||
|
||||
```console
|
||||
PATCH /api/v1/namespaces/default/configmaps/example-cm
|
||||
Content-Type: application/json-patch+json
|
||||
Accept: application/json
|
||||
Data: [{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}]
|
||||
```
|
||||
|
||||
This will overwrite the managedFields with a list containing a single empty
|
||||
entry that then results in the managedFields being stripped entirely from the
|
||||
object. Note that just setting the managedFields to an empty list will not
|
||||
reset the field. This is on purpose, so managedFields never get stripped by
|
||||
clients not aware of the field.
|
||||
|
||||
In cases where the reset operation is combined with changes to other fields
|
||||
than the managedFields, this will result in the managedFields being reset
|
||||
first and the other changes being processed afterwards. As a result the
|
||||
applier takes ownership of any fields updated in the same request.
|
||||
|
||||
{{< caution >}}
|
||||
Server Side Apply does not correctly track ownership on
|
||||
sub-resources that don't receive the resource object type. If you are
|
||||
using Server Side Apply with such a sub-resource, the changed fields
|
||||
won't be tracked.
|
||||
{{< /caution >}}
|
||||
|
||||
## Disabling the feature
|
||||
|
||||
Server Side Apply is a beta feature, so it is enabled by default. To turn this
|
||||
[feature gate](/docs/reference/command-line-tools-reference/feature-gates) off,
|
||||
you need to include the `--feature-gates ServerSideApply=false` flag when
|
||||
starting `kube-apiserver`. If you have multiple `kube-apiserver` replicas, all
|
||||
should have the same flag setting.
|
||||
|
||||
Reference in New Issue
Block a user