Merge remote-tracking branch 'upstream/main' into dev-1.24
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
---
|
||||
reviewers:
|
||||
- bryk
|
||||
- floreks
|
||||
- maciaszczykm
|
||||
- shu-mutou
|
||||
- mikedanese
|
||||
title: Deploy and Access the Kubernetes Dashboard
|
||||
description: >-
|
||||
@@ -35,7 +37,7 @@ Dashboard also provides information on the state of Kubernetes resources in your
|
||||
The Dashboard UI is not deployed by default. To deploy it, run the following command:
|
||||
|
||||
```
|
||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.4.0/aio/deploy/recommended.yaml
|
||||
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.5.0/aio/deploy/recommended.yaml
|
||||
```
|
||||
|
||||
## Accessing the Dashboard UI
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Encrypting Secret Data at Rest
|
||||
reviewers:
|
||||
- smarterclayton
|
||||
title: Encrypting Secret Data at Rest
|
||||
content_type: task
|
||||
min-kubernetes-server-version: 1.13
|
||||
---
|
||||
@@ -9,27 +9,26 @@ min-kubernetes-server-version: 1.13
|
||||
<!-- overview -->
|
||||
This page shows how to enable and configure encryption of secret data at rest.
|
||||
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
|
||||
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
* etcd v3.0 or later is required
|
||||
|
||||
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
## Configuration and determining whether encryption at rest is already enabled
|
||||
|
||||
The `kube-apiserver` process accepts an argument `--encryption-provider-config`
|
||||
that controls how API data is encrypted in etcd. An example configuration
|
||||
is provided below.
|
||||
that controls how API data is encrypted in etcd.
|
||||
The configuration is provided as an API named
|
||||
[`EncryptionConfiguration`](/docs/reference/config-api/apiserver-encryption.v1/).
|
||||
An example configuration is provided below.
|
||||
|
||||
{{< caution >}}
|
||||
**IMPORTANT:** For multi-master configurations (with two or more control plane nodes) the encryption configuration file must be the same!
|
||||
Otherwise, the kube-apiserver can't decrypt data stored inside the key-value store.
|
||||
**IMPORTANT:** For high-availability configurations (with two or more control plane nodes), the
|
||||
encryption configuration file must be the same! Otherwise, the `kube-apiserver` component cannot
|
||||
decrypt data stored in the etcd.
|
||||
{{< /caution >}}
|
||||
|
||||
## Understanding the encryption at rest configuration.
|
||||
@@ -39,39 +38,44 @@ apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: EncryptionConfiguration
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
- secrets
|
||||
providers:
|
||||
- identity: {}
|
||||
- aesgcm:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||
- name: key2
|
||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||
- name: key2
|
||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||
- secretbox:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
|
||||
- identity: {}
|
||||
- aesgcm:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||
- name: key2
|
||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: c2VjcmV0IGlzIHNlY3VyZQ==
|
||||
- name: key2
|
||||
secret: dGhpcyBpcyBwYXNzd29yZA==
|
||||
- secretbox:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
|
||||
```
|
||||
|
||||
Each `resources` array item is a separate config and contains a complete configuration. The
|
||||
`resources.resources` field is an array of Kubernetes resource names (`resource` or `resource.group`)
|
||||
that should be encrypted. The `providers` array is an ordered list of the possible encryption
|
||||
providers. Only one provider type may be specified per entry (`identity` or `aescbc` may be provided, but not both in the same item).
|
||||
providers.
|
||||
|
||||
The first provider in the list is used to encrypt resources going into storage. When reading
|
||||
resources from storage each provider that matches the stored data attempts to decrypt the data in
|
||||
order. If no provider can read the stored data due to a mismatch in format or secret key, an error
|
||||
Only one provider type may be specified per entry (`identity` or `aescbc` may be provided,
|
||||
but not both in the same item).
|
||||
The first provider in the list is used to encrypt resources written into the storage. When reading
|
||||
resources from storage, each provider that matches the stored data attempts in order to decrypt the
|
||||
data. If no provider can read the stored data due to a mismatch in format or secret key, an error
|
||||
is returned which prevents clients from accessing that resource.
|
||||
|
||||
For more detailed information about the `EncryptionConfiguration` struct, please refer to the
|
||||
[encryption configuration API](/docs/reference/config-api/apiserver-encryption.v1/).
|
||||
|
||||
{{< caution >}}
|
||||
**IMPORTANT:** If any resource is not readable via the encryption config (because keys were changed),
|
||||
If any resource is not readable via the encryption config (because keys were changed),
|
||||
the only recourse is to delete that key from the underlying etcd directly. Calls that attempt to
|
||||
read that resource will fail until it is deleted or a valid decryption key is provided.
|
||||
{{< /caution >}}
|
||||
@@ -90,15 +94,24 @@ Name | Encryption | Strength | Speed | Key Length | Other Considerations
|
||||
Each provider supports multiple keys - the keys are tried in order for decryption, and if the provider
|
||||
is the first provider, the first key is used for encryption.
|
||||
|
||||
__Storing the raw encryption key in the EncryptionConfig only moderately improves your security posture, compared to no encryption.
|
||||
Please use `kms` provider for additional security.__ By default, the `identity` provider is used to protect secrets in etcd, which
|
||||
provides no encryption. `EncryptionConfiguration` was introduced to encrypt secrets locally, with a locally managed key.
|
||||
|
||||
Encrypting secrets with a locally managed key protects against an etcd compromise, but it fails to protect against a host compromise.
|
||||
Since the encryption keys are stored on the host in the EncryptionConfig YAML file, a skilled attacker can access that file and
|
||||
extract the encryption keys.
|
||||
{{< caution >}}
|
||||
Storing the raw encryption key in the EncryptionConfig only moderately improves your security
|
||||
posture, compared to no encryption. Please use `kms` provider for additional security.
|
||||
{{< /caution >}}
|
||||
|
||||
Envelope encryption creates dependence on a separate key, not stored in Kubernetes. In this case, an attacker would need to compromise etcd, the kubeapi-server, and the third-party KMS provider to retrieve the plaintext values, providing a higher level of security than locally-stored encryption keys.
|
||||
By default, the `identity` provider is used to protect Secrets in etcd, which provides no
|
||||
encryption. `EncryptionConfiguration` was introduced to encrypt Secrets locally, with a locally
|
||||
managed key.
|
||||
|
||||
Encrypting Secrets with a locally managed key protects against an etcd compromise, but it fails to
|
||||
protect against a host compromise. Since the encryption keys are stored on the host in the
|
||||
EncryptionConfiguration YAML file, a skilled attacker can access that file and extract the encryption
|
||||
keys.
|
||||
|
||||
Envelope encryption creates dependence on a separate key, not stored in Kubernetes. In this case,
|
||||
an attacker would need to compromise etcd, the `kubeapi-server`, and the third-party KMS provider to
|
||||
retrieve the plaintext values, providing a higher level of security than locally stored encryption keys.
|
||||
|
||||
## Encrypting your data
|
||||
|
||||
@@ -109,113 +122,122 @@ apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: EncryptionConfiguration
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
- secrets
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: <BASE 64 ENCODED SECRET>
|
||||
- identity: {}
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: <BASE 64 ENCODED SECRET>
|
||||
- identity: {}
|
||||
```
|
||||
|
||||
To create a new secret perform the following steps:
|
||||
To create a new Secret, perform the following steps:
|
||||
|
||||
1. Generate a 32 byte random key and base64 encode it. If you're on Linux or macOS, run the following command:
|
||||
1. Generate a 32-byte random key and base64 encode it. If you're on Linux or macOS, run the following command:
|
||||
|
||||
```shell
|
||||
head -c 32 /dev/urandom | base64
|
||||
```
|
||||
|
||||
2. Place that value in the secret field.
|
||||
3. Set the `--encryption-provider-config` flag on the `kube-apiserver` to point to the location of the config file.
|
||||
4. Restart your API server.
|
||||
1. Place that value in the `secret` field of the `EncryptionConfiguration` struct.
|
||||
1. Set the `--encryption-provider-config` flag on the `kube-apiserver` to point to
|
||||
the location of the config file.
|
||||
1. Restart your API server.
|
||||
|
||||
{{< caution >}}
|
||||
Your config file contains keys that can decrypt content in etcd, so you must properly restrict permissions on your masters so only the user who runs the kube-apiserver can read it.
|
||||
Your config file contains keys that can decrypt the contents in etcd, so you must properly restrict
|
||||
permissions on your control-plane nodes so only the user who runs the `kube-apiserver` can read it.
|
||||
{{< /caution >}}
|
||||
|
||||
|
||||
## Verifying that data is encrypted
|
||||
|
||||
Data is encrypted when written to etcd. After restarting your `kube-apiserver`, any newly created or
|
||||
updated secret should be encrypted when stored. To check, you can use the `etcdctl` command line
|
||||
program to retrieve the contents of your secret.
|
||||
updated Secret should be encrypted when stored. To check this, you can use the `etcdctl` command line
|
||||
program to retrieve the contents of your Secret.
|
||||
|
||||
1. Create a new secret called `secret1` in the `default` namespace:
|
||||
1. Create a new Secret called `secret1` in the `default` namespace:
|
||||
|
||||
```shell
|
||||
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
|
||||
```
|
||||
|
||||
2. Using the etcdctl commandline, read that secret out of etcd:
|
||||
1. Using the `etcdctl` command line, read that Secret out of etcd:
|
||||
|
||||
`ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C`
|
||||
|
||||
where `[...]` must be the additional arguments for connecting to the etcd server.
|
||||
|
||||
3. Verify the stored secret is prefixed with `k8s:enc:aescbc:v1:` which indicates the `aescbc` provider has encrypted the resulting data.
|
||||
1. Verify the stored Secret is prefixed with `k8s:enc:aescbc:v1:` which indicates
|
||||
the `aescbc` provider has encrypted the resulting data.
|
||||
|
||||
4. Verify the secret is correctly decrypted when retrieved via the API:
|
||||
1. Verify the Secret is correctly decrypted when retrieved via the API:
|
||||
|
||||
```shell
|
||||
kubectl describe secret secret1 -n default
|
||||
```
|
||||
|
||||
should match `mykey: bXlkYXRh`, mydata is encoded, check [decoding a secret](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret) to
|
||||
completely decode the secret.
|
||||
The output should contain `mykey: bXlkYXRh`, with contents of `mydata` encoded, check
|
||||
[decoding a Secret](/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret)
|
||||
to completely decode the Secret.
|
||||
|
||||
## Ensure all Secrets are encrypted
|
||||
|
||||
## Ensure all secrets are encrypted
|
||||
|
||||
Since secrets are encrypted on write, performing an update on a secret will encrypt that content.
|
||||
Since Secrets are encrypted on write, performing an update on a Secret will encrypt that content.
|
||||
|
||||
```shell
|
||||
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
|
||||
```
|
||||
|
||||
The command above reads all secrets and then updates them to apply server side encryption.
|
||||
The command above reads all Secrets and then updates them to apply server side encryption.
|
||||
|
||||
{{< note >}}
|
||||
If an error occurs due to a conflicting write, retry the command.
|
||||
For larger clusters, you may wish to subdivide the secrets by namespace or script an update.
|
||||
{{< /note >}}
|
||||
|
||||
|
||||
## Rotating a decryption key
|
||||
|
||||
Changing the secret without incurring downtime requires a multi step operation, especially in
|
||||
the presence of a highly available deployment where multiple `kube-apiserver` processes are running.
|
||||
Changing a Secret without incurring downtime requires a multi-step operation, especially in
|
||||
the presence of a highly-available deployment where multiple `kube-apiserver` processes are running.
|
||||
|
||||
1. Generate a new key and add it as the second key entry for the current provider on all servers
|
||||
2. Restart all `kube-apiserver` processes to ensure each server can decrypt using the new key
|
||||
3. Make the new key the first entry in the `keys` array so that it is used for encryption in the config
|
||||
4. Restart all `kube-apiserver` processes to ensure each server now encrypts using the new key
|
||||
5. Run `kubectl get secrets --all-namespaces -o json | kubectl replace -f -` to encrypt all existing secrets with the new key
|
||||
6. Remove the old decryption key from the config after you back up etcd with the new key in use and update all secrets
|
||||
|
||||
With a single `kube-apiserver`, step 2 may be skipped.
|
||||
1. Restart all `kube-apiserver` processes to ensure each server can decrypt using the new key
|
||||
1. Make the new key the first entry in the `keys` array so that it is used for encryption in the config
|
||||
1. Restart all `kube-apiserver` processes to ensure each server now encrypts using the new key
|
||||
1. Run `kubectl get secrets --all-namespaces -o json | kubectl replace -f -` to encrypt all
|
||||
existing Secrets with the new key
|
||||
1. Remove the old decryption key from the config after you have backed up etcd with the new key in use
|
||||
and updated all Secrets
|
||||
|
||||
When running a single `kube-apiserver` instance, step 2 may be skipped.
|
||||
|
||||
## Decrypting all data
|
||||
|
||||
To disable encryption at rest place the `identity` provider as the first entry in the config:
|
||||
To disable encryption at rest, place the `identity` provider as the first entry in the config
|
||||
and restart all `kube-apiserver` processes.
|
||||
|
||||
```yaml
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: EncryptionConfiguration
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
- secrets
|
||||
providers:
|
||||
- identity: {}
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: <BASE 64 ENCODED SECRET>
|
||||
- identity: {}
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: <BASE 64 ENCODED SECRET>
|
||||
```
|
||||
|
||||
and restart all `kube-apiserver` processes. Then run:
|
||||
Then run the following command to force decrypt
|
||||
all Secrets:
|
||||
|
||||
```shell
|
||||
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
|
||||
```
|
||||
to force all secrets to be decrypted.
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
* Learn more about the [EncryptionConfiguration configuration API (v1)](/docs/reference/config-api/apiserver-encryption.v1/).
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@ weight: 10
|
||||
|
||||
{{< feature-state for_k8s_version="v1.15" state="stable" >}}
|
||||
|
||||
Client certificates generated by [kubeadm](/docs/reference/setup-tools/kubeadm/) expire after 1 year. This page explains how to manage certificate renewals with kubeadm.
|
||||
Client certificates generated by [kubeadm](/docs/reference/setup-tools/kubeadm/) expire after 1 year.
|
||||
This page explains how to manage certificate renewals with kubeadm. It also covers other tasks related
|
||||
to kubeadm certificate management.
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
@@ -126,13 +128,13 @@ command. In that case, you should explicitly set `--certificate-renewal=true`.
|
||||
|
||||
You can renew your certificates manually at any time with the `kubeadm certs renew` command.
|
||||
|
||||
This command performs the renewal using CA (or front-proxy-CA) certificate and key stored in `/etc/kubernetes/pki`.
|
||||
This command performs the renewal using CA (or front-proxy-CA) certificate and key stored in `/etc/kubernetes/pki`.
|
||||
|
||||
After running the command you should restart the control plane Pods. This is required since
|
||||
dynamic certificate reload is currently not supported for all components and certificates.
|
||||
[Static Pods](/docs/tasks/configure-pod-container/static-pod/) are managed by the local kubelet
|
||||
and not by the API Server, thus kubectl cannot be used to delete and restart them.
|
||||
To restart a static Pod you can temporarily remove its manifest file from `/etc/kubernetes/manifests/`
|
||||
To restart a static Pod you can temporarily remove its manifest file from `/etc/kubernetes/manifests/`
|
||||
and wait for 20 seconds (see the `fileCheckFrequency` value in [KubeletConfiguration struct](/docs/reference/config-api/kubelet-config.v1beta1/).
|
||||
The kubelet will terminate the Pod if it's no longer in the manifest directory.
|
||||
You can then move the file back and after another `fileCheckFrequency` period, the kubelet will recreate
|
||||
@@ -289,3 +291,52 @@ Such a controller is not a secure mechanism unless it not only verifies the Comm
|
||||
in the CSR but also verifies the requested IPs and domain names. This would prevent
|
||||
a malicious actor that has access to a kubelet client certificate to create
|
||||
CSRs requesting serving certificates for any IP or domain name.
|
||||
|
||||
## Generating kubeconfig files for additional users {#kubeconfig-additional-users}
|
||||
|
||||
During cluster creation, kubeadm signs the certificate in the `admin.conf` to have
|
||||
`Subject: O = system:masters, CN = kubernetes-admin`.
|
||||
[`system:masters`](/docs/reference/access-authn-authz/rbac/#user-facing-roles)
|
||||
is a break-glass, super user group that bypasses the authorization layer (e.g. RBAC).
|
||||
Sharing the `admin.conf` with additional users is **not recommended**!
|
||||
|
||||
Instead, you can use the [`kubeadm kubeconfig user`](/docs/reference/setup-tools/kubeadm/kubeadm-kubeconfig)
|
||||
command to generate kubeconfig files for additional users.
|
||||
The command accepts a mixture of command line flags and
|
||||
[kubeadm configuration](/docs/reference/config-api/kubeadm-config.v1beta3/) options.
|
||||
The generated kubeconfig will be written to stdout and can be piped to a file
|
||||
using `kubeadm kubeconfig user ... > somefile.conf`.
|
||||
|
||||
Example configuration file that can be used with `--config`:
|
||||
|
||||
```yaml
|
||||
# example.yaml
|
||||
apiVersion: kubeadm.k8s.io/v1beta3
|
||||
kind: ClusterConfiguration
|
||||
# Will be used as the target "cluster" in the kubeconfig
|
||||
clusterName: "kubernetes"
|
||||
# Will be used as the "server" (IP or DNS name) of this cluster in the kubeconfig
|
||||
controlPlaneEndpoint: "some-dns-address:6443"
|
||||
# The cluster CA key and certificate will be loaded from this local directory
|
||||
certificatesDir: "/etc/kubernetes/pki"
|
||||
```
|
||||
|
||||
Make sure that these settings match the desired target cluster settings.
|
||||
To see the settings of an existing cluster use:
|
||||
|
||||
```shell
|
||||
kubectl get cm kubeadm-config -n kube-system -o=jsonpath="{.data.ClusterConfiguration}"
|
||||
```
|
||||
|
||||
The following example will generate a kubeconfig file with credentials valid for 24 hours
|
||||
for a new user `johndoe` that is part of the `appdevs` group:
|
||||
|
||||
```shell
|
||||
kubeadm kubeconfig user --config example.yaml --org appdevs --client-name johndoe --validity-period 24h
|
||||
```
|
||||
|
||||
The following example will generate a kubeconfig file with administrator credentials valid for 1 week:
|
||||
|
||||
```shell
|
||||
kubeadm kubeconfig user --config example.yaml --client-name admin --validity-period 168h
|
||||
```
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ This page shows how to configure default memory requests and limits for a
|
||||
{{< glossary_tooltip text="namespace" term_id="namespace" >}}.
|
||||
|
||||
A Kubernetes cluster can be divided into namespaces. Once you have a namespace that
|
||||
that has a default memory
|
||||
has a default memory
|
||||
[limit](/docs/concepts/configuration/manage-resources-containers/#requests-and-limits),
|
||||
and you then try to create a Pod with a container that does not specify its own memory
|
||||
limit its own memory limit, then the
|
||||
|
||||
@@ -138,7 +138,8 @@ The sum of their values will account for the total amount of reserved memory.
|
||||
A new `--reserved-memory` flag was added to Memory Manager to allow for this total reserved memory
|
||||
to be split (by a node administrator) and accordingly reserved across many NUMA nodes.
|
||||
|
||||
The flag specifies a comma-separated list of memory reservations per NUMA node.
|
||||
The flag specifies a comma-separated list of memory reservations of different memory types per NUMA node.
|
||||
Memory reservations across multiple NUMA nodes can be specified using semicolon as separator.
|
||||
This parameter is only useful in the context of the Memory Manager feature.
|
||||
The Memory Manager will not use this reserved memory for the allocation of container workloads.
|
||||
|
||||
@@ -180,6 +181,10 @@ or
|
||||
|
||||
`--reserved-memory 0:memory=1Gi --reserved-memory 1:memory=2Gi`
|
||||
|
||||
or
|
||||
|
||||
`--reserved-memory '0:memory=1Gi;1:memory=2Gi'`
|
||||
|
||||
When you specify values for `--reserved-memory` flag, you must comply with the setting that
|
||||
you prior provided via Node Allocatable Feature flags.
|
||||
That is, the following rule must be obeyed for each memory type:
|
||||
@@ -215,7 +220,7 @@ Here is an example of a correct configuration:
|
||||
--kube-reserved=cpu=4,memory=4Gi
|
||||
--system-reserved=cpu=1,memory=1Gi
|
||||
--memory-manager-policy=Static
|
||||
--reserved-memory 0:memory=3Gi --reserved-memory 1:memory=2148Mi
|
||||
--reserved-memory '0:memory=3Gi;1:memory=2148Mi'
|
||||
```
|
||||
|
||||
Let us validate the configuration above:
|
||||
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
---
|
||||
title: "Changing the Container Runtime on a Node from Docker Engine to containerd"
|
||||
weight: 8
|
||||
content_type: task
|
||||
---
|
||||
|
||||
This task outlines the steps needed to update your container runtime to containerd from Docker. It is applicable for cluster operators running Kubernetes 1.23 or earlier. Also this covers an example scenario for migrating from dockershim to containerd and alternative container runtimes can be picked from this [page](https://kubernetes.io/docs/setup/production-environment/container-runtimes/).
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
{{% thirdparty-content %}}
|
||||
|
||||
Install containerd. For more information see, [containerd's installation documentation](https://containerd.io/docs/getting-started/) and for specific prerequisite follow [this](/docs/setup/production-environment/container-runtimes/#containerd).
|
||||
|
||||
## Drain the node
|
||||
|
||||
```
|
||||
# replace <node-to-drain> with the name of your node you are draining
|
||||
kubectl drain <node-to-drain> --ignore-daemonsets
|
||||
```
|
||||
## Stop the Docker daemon
|
||||
|
||||
```shell
|
||||
systemctl stop kubelet
|
||||
systemctl disable docker.service --now
|
||||
```
|
||||
|
||||
## Install Containerd
|
||||
|
||||
This [page](/docs/setup/production-environment/container-runtimes/#containerd) contains detailed steps to install containerd.
|
||||
|
||||
{{< tabs name="tab-cri-containerd-installation" >}}
|
||||
{{% tab name="Linux" %}}
|
||||
|
||||
1. Install the `containerd.io` package from the official Docker repositories.
|
||||
Instructions for setting up the Docker repository for your respective Linux distribution and installing the `containerd.io` package can be found at
|
||||
[Install Docker Engine](https://docs.docker.com/engine/install/#server).
|
||||
|
||||
2. Configure containerd:
|
||||
|
||||
```shell
|
||||
sudo mkdir -p /etc/containerd
|
||||
containerd config default | sudo tee /etc/containerd/config.toml
|
||||
```
|
||||
|
||||
3. Restart containerd:
|
||||
|
||||
```shell
|
||||
sudo systemctl restart containerd
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{% tab name="Windows (PowerShell)" %}}
|
||||
|
||||
Start a Powershell session, set `$Version` to the desired version (ex: `$Version="1.4.3"`), and then run the following commands:
|
||||
|
||||
1. Download containerd:
|
||||
|
||||
```powershell
|
||||
curl.exe -L https://github.com/containerd/containerd/releases/download/v$Version/containerd-$Version-windows-amd64.tar.gz -o containerd-windows-amd64.tar.gz
|
||||
tar.exe xvf .\containerd-windows-amd64.tar.gz
|
||||
```
|
||||
|
||||
2. Extract and configure:
|
||||
|
||||
```powershell
|
||||
Copy-Item -Path ".\bin\" -Destination "$Env:ProgramFiles\containerd" -Recurse -Force
|
||||
cd $Env:ProgramFiles\containerd\
|
||||
.\containerd.exe config default | Out-File config.toml -Encoding ascii
|
||||
|
||||
# Review the configuration. Depending on setup you may want to adjust:
|
||||
# - the sandbox_image (Kubernetes pause image)
|
||||
# - cni bin_dir and conf_dir locations
|
||||
Get-Content config.toml
|
||||
|
||||
# (Optional - but highly recommended) Exclude containerd from Windows Defender Scans
|
||||
Add-MpPreference -ExclusionProcess "$Env:ProgramFiles\containerd\containerd.exe"
|
||||
```
|
||||
|
||||
3. Start containerd:
|
||||
|
||||
```powershell
|
||||
.\containerd.exe --register-service
|
||||
Start-Service containerd
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{< /tabs >}}
|
||||
|
||||
## Configure the kubelet to use containerd as its container runtime
|
||||
|
||||
Edit the file `/var/lib/kubelet/kubeadm-flags.env` and add the containerd runtime to the flags. `--container-runtime=remote` and `--container-runtime-endpoint=unix:///run/containerd/containerd.sock"`
|
||||
|
||||
For users using kubeadm should consider the following:
|
||||
|
||||
The `kubeadm` tool stores the CRI socket for each host as an annotation in the Node object for that host.
|
||||
|
||||
To change it you must do the following:
|
||||
|
||||
Execute `kubectl edit no <NODE-NAME>` on a machine that has the kubeadm `/etc/kubernetes/admin.conf` file.
|
||||
|
||||
This will start a text editor where you can edit the Node object.
|
||||
|
||||
To choose a text editor you can set the `KUBE_EDITOR` environment variable.
|
||||
|
||||
- Change the value of `kubeadm.alpha.kubernetes.io/cri-socket` from `/var/run/dockershim.sock`
|
||||
to the CRI socket path of your choice (for example `unix:///run/containerd/containerd.sock`).
|
||||
|
||||
Note that new CRI socket paths must be prefixed with `unix://` ideally.
|
||||
|
||||
- Save the changes in the text editor, which will update the Node object.
|
||||
|
||||
## Restart the kubelet
|
||||
|
||||
```shell
|
||||
systemctl start kubelet
|
||||
```
|
||||
|
||||
## Verify that the node is healthy
|
||||
|
||||
Run `kubectl get nodes -o wide` and containerd appears as the runtime for the node we just changed.
|
||||
|
||||
## Remove Docker Engine
|
||||
|
||||
{{% thirdparty-content %}}
|
||||
|
||||
Finally if everything goes well remove docker
|
||||
|
||||
{{< tabs name="tab-remove-docker-enigine" >}}
|
||||
{{% tab name="CentOS" %}}
|
||||
|
||||
```shell
|
||||
sudo yum remove docker-ce docker-ce-cli
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab name="Debian" %}}
|
||||
|
||||
```shell
|
||||
sudo apt-get purge docker-ce docker-ce-cli
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab name="Fedora" %}}
|
||||
|
||||
```shell
|
||||
sudo dnf remove docker-ce docker-ce-cli
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab name="Ubuntu" %}}
|
||||
|
||||
```shell
|
||||
sudo apt-get purge docker-ce docker-ce-cli
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{< /tabs >}}
|
||||
@@ -5,7 +5,8 @@ content_type: task
|
||||
|
||||
<!--overview-->
|
||||
|
||||
This page shows you how to specify the type of [cascading deletion](/docs/concepts/workloads/controllers/garbage-collection/#cascading-deletion)
|
||||
This page shows you how to specify the type of
|
||||
[cascading deletion](/docs/concepts/architecture/garbage-collection/#cascading-deletion)
|
||||
to use in your cluster during {{<glossary_tooltip text="garbage collection" term_id="garbage-collection">}}.
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
@@ -26,7 +27,7 @@ kubectl get pods -l app=nginx --output=yaml
|
||||
|
||||
The output has an `ownerReferences` field similar to this:
|
||||
|
||||
```
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
...
|
||||
ownerReferences:
|
||||
@@ -41,7 +42,7 @@ apiVersion: v1
|
||||
|
||||
## Use foreground cascading deletion {#use-foreground-cascading-deletion}
|
||||
|
||||
By default, Kubernetes uses [background cascading deletion](/docs/concepts/workloads/controllers/garbage-collection/#background-deletion)
|
||||
By default, Kubernetes uses [background cascading deletion](/docs/concepts/architecture/garbage-collection/#background-deletion)
|
||||
to delete dependents of an object. You can switch to foreground cascading deletion
|
||||
using either `kubectl` or the Kubernetes API, depending on the Kubernetes
|
||||
version your cluster runs. {{<version-check>}}
|
||||
@@ -64,9 +65,9 @@ kubectl delete deployment nginx-deployment --cascade=foreground
|
||||
|
||||
1. Start a local proxy session:
|
||||
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
|
||||
1. Use `curl` to trigger deletion:
|
||||
|
||||
@@ -80,19 +81,19 @@ kubectl delete deployment nginx-deployment --cascade=foreground
|
||||
like this:
|
||||
|
||||
```
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"namespace": "default",
|
||||
"uid": "d1ce1b02-cae8-4288-8a53-30e84d8fa505",
|
||||
"resourceVersion": "1363097",
|
||||
"creationTimestamp": "2021-07-08T20:24:37Z",
|
||||
"deletionTimestamp": "2021-07-08T20:27:39Z",
|
||||
"finalizers": [
|
||||
"foregroundDeletion"
|
||||
]
|
||||
...
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"namespace": "default",
|
||||
"uid": "d1ce1b02-cae8-4288-8a53-30e84d8fa505",
|
||||
"resourceVersion": "1363097",
|
||||
"creationTimestamp": "2021-07-08T20:24:37Z",
|
||||
"deletionTimestamp": "2021-07-08T20:27:39Z",
|
||||
"finalizers": [
|
||||
"foregroundDeletion"
|
||||
]
|
||||
...
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
@@ -104,9 +105,9 @@ For details, read the [documentation for your Kubernetes version](/docs/home/sup
|
||||
|
||||
1. Start a local proxy session:
|
||||
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
|
||||
1. Use `curl` to trigger deletion:
|
||||
|
||||
@@ -120,19 +121,19 @@ For details, read the [documentation for your Kubernetes version](/docs/home/sup
|
||||
like this:
|
||||
|
||||
```
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"namespace": "default",
|
||||
"uid": "d1ce1b02-cae8-4288-8a53-30e84d8fa505",
|
||||
"resourceVersion": "1363097",
|
||||
"creationTimestamp": "2021-07-08T20:24:37Z",
|
||||
"deletionTimestamp": "2021-07-08T20:27:39Z",
|
||||
"finalizers": [
|
||||
"foregroundDeletion"
|
||||
]
|
||||
...
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"metadata": {
|
||||
"name": "nginx-deployment",
|
||||
"namespace": "default",
|
||||
"uid": "d1ce1b02-cae8-4288-8a53-30e84d8fa505",
|
||||
"resourceVersion": "1363097",
|
||||
"creationTimestamp": "2021-07-08T20:24:37Z",
|
||||
"deletionTimestamp": "2021-07-08T20:27:39Z",
|
||||
"finalizers": [
|
||||
"foregroundDeletion"
|
||||
]
|
||||
...
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{</tabs>}}
|
||||
@@ -165,32 +166,32 @@ kubectl delete deployment nginx-deployment --cascade=background
|
||||
|
||||
1. Start a local proxy session:
|
||||
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
|
||||
1. Use `curl` to trigger deletion:
|
||||
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
"kind": "Status",
|
||||
"apiVersion": "v1",
|
||||
...
|
||||
"status": "Success",
|
||||
"details": {
|
||||
"name": "nginx-deployment",
|
||||
"group": "apps",
|
||||
"kind": "deployments",
|
||||
"uid": "cc9eefb9-2d49-4445-b1c1-d261c9396456"
|
||||
}
|
||||
```
|
||||
```
|
||||
"kind": "Status",
|
||||
"apiVersion": "v1",
|
||||
...
|
||||
"status": "Success",
|
||||
"details": {
|
||||
"name": "nginx-deployment",
|
||||
"group": "apps",
|
||||
"kind": "deployments",
|
||||
"uid": "cc9eefb9-2d49-4445-b1c1-d261c9396456"
|
||||
}
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{% tab name="Versions prior to Kubernetes 1.20.x" %}}
|
||||
Kubernetes uses background cascading deletion by default, and does so
|
||||
@@ -211,32 +212,32 @@ kubectl delete deployment nginx-deployment --cascade=true
|
||||
|
||||
1. Start a local proxy session:
|
||||
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
|
||||
1. Use `curl` to trigger deletion:
|
||||
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Background"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
"kind": "Status",
|
||||
"apiVersion": "v1",
|
||||
...
|
||||
"status": "Success",
|
||||
"details": {
|
||||
"name": "nginx-deployment",
|
||||
"group": "apps",
|
||||
"kind": "deployments",
|
||||
"uid": "cc9eefb9-2d49-4445-b1c1-d261c9396456"
|
||||
}
|
||||
```
|
||||
```
|
||||
"kind": "Status",
|
||||
"apiVersion": "v1",
|
||||
...
|
||||
"status": "Success",
|
||||
"details": {
|
||||
"name": "nginx-deployment",
|
||||
"group": "apps",
|
||||
"kind": "deployments",
|
||||
"uid": "cc9eefb9-2d49-4445-b1c1-d261c9396456"
|
||||
}
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{</tabs>}}
|
||||
|
||||
@@ -264,33 +265,33 @@ kubectl delete deployment nginx-deployment --cascade=orphan
|
||||
|
||||
1. Start a local proxy session:
|
||||
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
|
||||
1. Use `curl` to trigger deletion:
|
||||
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
The output contains `orphan` in the `finalizers` field, similar to this:
|
||||
The output contains `orphan` in the `finalizers` field, similar to this:
|
||||
|
||||
```
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"namespace": "default",
|
||||
"uid": "6f577034-42a0-479d-be21-78018c466f1f",
|
||||
"creationTimestamp": "2021-07-09T16:46:37Z",
|
||||
"deletionTimestamp": "2021-07-09T16:47:08Z",
|
||||
"deletionGracePeriodSeconds": 0,
|
||||
"finalizers": [
|
||||
"orphan"
|
||||
],
|
||||
...
|
||||
```
|
||||
```
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"namespace": "default",
|
||||
"uid": "6f577034-42a0-479d-be21-78018c466f1f",
|
||||
"creationTimestamp": "2021-07-09T16:46:37Z",
|
||||
"deletionTimestamp": "2021-07-09T16:47:08Z",
|
||||
"deletionGracePeriodSeconds": 0,
|
||||
"finalizers": [
|
||||
"orphan"
|
||||
],
|
||||
...
|
||||
```
|
||||
|
||||
{{% /tab %}}
|
||||
{{% tab name="Versions prior to Kubernetes 1.20.x" %}}
|
||||
@@ -309,33 +310,33 @@ kubectl delete deployment nginx-deployment --cascade=orphan
|
||||
|
||||
1. Start a local proxy session:
|
||||
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
```shell
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
|
||||
1. Use `curl` to trigger deletion:
|
||||
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
```shell
|
||||
curl -X DELETE localhost:8080/apis/apps/v1/namespaces/default/deployments/nginx-deployment \
|
||||
-d '{"kind":"DeleteOptions","apiVersion":"v1","propagationPolicy":"Orphan"}' \
|
||||
-H "Content-Type: application/json"
|
||||
```
|
||||
|
||||
The output contains `orphan` in the `finalizers` field, similar to this:
|
||||
The output contains `orphan` in the `finalizers` field, similar to this:
|
||||
|
||||
```
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"namespace": "default",
|
||||
"uid": "6f577034-42a0-479d-be21-78018c466f1f",
|
||||
"creationTimestamp": "2021-07-09T16:46:37Z",
|
||||
"deletionTimestamp": "2021-07-09T16:47:08Z",
|
||||
"deletionGracePeriodSeconds": 0,
|
||||
"finalizers": [
|
||||
"orphan"
|
||||
],
|
||||
...
|
||||
```
|
||||
```
|
||||
"kind": "Deployment",
|
||||
"apiVersion": "apps/v1",
|
||||
"namespace": "default",
|
||||
"uid": "6f577034-42a0-479d-be21-78018c466f1f",
|
||||
"creationTimestamp": "2021-07-09T16:46:37Z",
|
||||
"deletionTimestamp": "2021-07-09T16:47:08Z",
|
||||
"deletionGracePeriodSeconds": 0,
|
||||
"finalizers": [
|
||||
"orphan"
|
||||
],
|
||||
...
|
||||
```
|
||||
{{% /tab %}}
|
||||
{{</tabs>}}
|
||||
|
||||
@@ -349,4 +350,4 @@ kubectl get pods -l app=nginx
|
||||
|
||||
* Learn about [owners and dependents](/docs/concepts/overview/working-with-objects/owners-dependents/) in Kubernetes.
|
||||
* Learn about Kubernetes [finalizers](/docs/concepts/overview/working-with-objects/finalizers/).
|
||||
* Learn about [garbage collection](/docs/concepts/workloads/controllers/garbage-collection/).
|
||||
* Learn about [garbage collection](/docs/concepts/architecture/garbage-collection/).
|
||||
|
||||
@@ -14,21 +14,31 @@ A security context defines privilege and access control settings for
|
||||
a Pod or Container. Security context settings include, but are not limited to:
|
||||
|
||||
* Discretionary Access Control: Permission to access an object, like a file, is based on
|
||||
[user ID (UID) and group ID (GID)](https://wiki.archlinux.org/index.php/users_and_groups).
|
||||
[user ID (UID) and group ID (GID)](https://wiki.archlinux.org/index.php/users_and_groups).
|
||||
|
||||
* [Security Enhanced Linux (SELinux)](https://en.wikipedia.org/wiki/Security-Enhanced_Linux): Objects are assigned security labels.
|
||||
* [Security Enhanced Linux (SELinux)](https://en.wikipedia.org/wiki/Security-Enhanced_Linux):
|
||||
Objects are assigned security labels.
|
||||
|
||||
* Running as privileged or unprivileged.
|
||||
|
||||
* [Linux Capabilities](https://linux-audit.com/linux-capabilities-hardening-linux-binaries-by-removing-setuid/): Give a process some privileges, but not all the privileges of the root user.
|
||||
* [Linux Capabilities](https://linux-audit.com/linux-capabilities-hardening-linux-binaries-by-removing-setuid/):
|
||||
Give a process some privileges, but not all the privileges of the root user.
|
||||
|
||||
* [AppArmor](/docs/tutorials/clusters/apparmor/): Use program profiles to restrict the capabilities of individual programs.
|
||||
* [AppArmor](/docs/tutorials/security/apparmor/):
|
||||
Use program profiles to restrict the capabilities of individual programs.
|
||||
|
||||
* [Seccomp](/docs/tutorials/clusters/seccomp/): Filter a process's system calls.
|
||||
* [Seccomp](/docs/tutorials/security/seccomp/): Filter a process's system calls.
|
||||
|
||||
* AllowPrivilegeEscalation: Controls whether a process can gain more privileges than its parent process. This bool directly controls whether the [`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt) flag gets set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged OR 2) has `CAP_SYS_ADMIN`.
|
||||
* `allowPrivilegeEscalation`: Controls whether a process can gain more privileges than
|
||||
its parent process. This bool directly controls whether the
|
||||
[`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt)
|
||||
flag gets set on the container process.
|
||||
`allowPrivilegeEscalation` is always true when the container:
|
||||
|
||||
* readOnlyRootFilesystem: Mounts the container's root filesystem as read-only.
|
||||
- is run as privileged, or
|
||||
- has `CAP_SYS_ADMIN`
|
||||
|
||||
* `readOnlyRootFilesystem`: Mounts the container's root filesystem as read-only.
|
||||
|
||||
The above bullets are not a complete set of security context settings -- please see
|
||||
[SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core)
|
||||
@@ -37,15 +47,10 @@ for a comprehensive list.
|
||||
For more information about security mechanisms in Linux, see
|
||||
[Overview of Linux Kernel Security Features](https://www.linux.com/learn/overview-linux-kernel-security-features)
|
||||
|
||||
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
|
||||
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
|
||||
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
## Set the security context for a Pod
|
||||
@@ -91,7 +96,7 @@ ps
|
||||
|
||||
The output shows that the processes are running as user 1000, which is the value of `runAsUser`:
|
||||
|
||||
```shell
|
||||
```none
|
||||
PID USER TIME COMMAND
|
||||
1 1000 0:00 sleep 1h
|
||||
6 1000 0:00 sh
|
||||
@@ -108,7 +113,7 @@ ls -l
|
||||
The output shows that the `/data/demo` directory has group ID 2000, which is
|
||||
the value of `fsGroup`.
|
||||
|
||||
```shell
|
||||
```none
|
||||
drwxrwsrwx 2 root 2000 4096 Jun 6 20:08 demo
|
||||
```
|
||||
|
||||
@@ -127,19 +132,26 @@ ls -l
|
||||
|
||||
The output shows that `testfile` has group ID 2000, which is the value of `fsGroup`.
|
||||
|
||||
```shell
|
||||
```none
|
||||
-rw-r--r-- 1 1000 2000 6 Jun 6 20:08 testfile
|
||||
```
|
||||
|
||||
Run the following command:
|
||||
|
||||
```shell
|
||||
$ id
|
||||
id
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```none
|
||||
uid=1000 gid=3000 groups=2000
|
||||
```
|
||||
You will see that gid is 3000 which is same as `runAsGroup` field. If the `runAsGroup` was omitted the gid would
|
||||
remain as 0(root) and the process will be able to interact with files that are owned by root(0) group and that have
|
||||
the required group permissions for root(0) group.
|
||||
|
||||
From the output, you can see that `gid` is 3000 which is same as the `runAsGroup` field.
|
||||
If the `runAsGroup` was omitted, the `gid` would remain as 0 (root) and the process will
|
||||
be able to interact with files that are owned by the root(0) group and groups that have
|
||||
the required group permissions for the root (0) group.
|
||||
|
||||
Exit your shell:
|
||||
|
||||
@@ -159,11 +171,14 @@ slowing Pod startup. You can use the `fsGroupChangePolicy` field inside a `secur
|
||||
to control the way that Kubernetes checks and manages ownership and permissions
|
||||
for a volume.
|
||||
|
||||
**fsGroupChangePolicy** - `fsGroupChangePolicy` defines behavior for changing ownership and permission of the volume
|
||||
before being exposed inside a Pod. This field only applies to volume types that support
|
||||
`fsGroup` controlled ownership and permissions. This field has two possible values:
|
||||
**fsGroupChangePolicy** - `fsGroupChangePolicy` defines behavior for changing ownership
|
||||
and permission of the volume before being exposed inside a Pod.
|
||||
This field only applies to volume types that support `fsGroup` controlled ownership and permissions.
|
||||
This field has two possible values:
|
||||
|
||||
* _OnRootMismatch_: Only change permissions and ownership if permission and ownership of root directory does not match with expected permissions of the volume. This could help shorten the time it takes to change ownership and permission of a volume.
|
||||
* _OnRootMismatch_: Only change permissions and ownership if permission and ownership of
|
||||
root directory does not match with expected permissions of the volume.
|
||||
This could help shorten the time it takes to change ownership and permission of a volume.
|
||||
* _Always_: Always change permission and ownership of the volume when volume is mounted.
|
||||
|
||||
For example:
|
||||
@@ -176,7 +191,6 @@ securityContext:
|
||||
fsGroupChangePolicy: "OnRootMismatch"
|
||||
```
|
||||
|
||||
|
||||
{{< note >}}
|
||||
This field has no effect on ephemeral volume types such as
|
||||
[`secret`](/docs/concepts/storage/volumes/#secret),
|
||||
@@ -238,7 +252,7 @@ kubectl exec -it security-context-demo-2 -- sh
|
||||
|
||||
In your shell, list the running processes:
|
||||
|
||||
```
|
||||
```shell
|
||||
ps aux
|
||||
```
|
||||
|
||||
@@ -297,7 +311,7 @@ ps aux
|
||||
|
||||
The output shows the process IDs (PIDs) for the Container:
|
||||
|
||||
```shell
|
||||
```
|
||||
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||
root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js
|
||||
root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js
|
||||
@@ -354,7 +368,7 @@ cat status
|
||||
|
||||
The output shows capabilities bitmap for the process:
|
||||
|
||||
```shell
|
||||
```
|
||||
...
|
||||
CapPrm: 00000000aa0435fb
|
||||
CapEff: 00000000aa0435fb
|
||||
@@ -374,7 +388,10 @@ See [capability.h](https://github.com/torvalds/linux/blob/master/include/uapi/li
|
||||
for definitions of the capability constants.
|
||||
|
||||
{{< note >}}
|
||||
Linux capability constants have the form `CAP_XXX`. But when you list capabilities in your Container manifest, you must omit the `CAP_` portion of the constant. For example, to add `CAP_SYS_TIME`, include `SYS_TIME` in your list of capabilities.
|
||||
Linux capability constants have the form `CAP_XXX`.
|
||||
But when you list capabilities in your container manifest, you must
|
||||
omit the `CAP_` portion of the constant.
|
||||
For example, to add `CAP_SYS_TIME`, include `SYS_TIME` in your list of capabilities.
|
||||
{{< /note >}}
|
||||
|
||||
## Set the Seccomp Profile for a Container
|
||||
@@ -437,18 +454,19 @@ the Pod's Volumes when applicable. Specifically `fsGroup` and `seLinuxOptions` a
|
||||
applied to Volumes as follows:
|
||||
|
||||
* `fsGroup`: Volumes that support ownership management are modified to be owned
|
||||
and writable by the GID specified in `fsGroup`. See the
|
||||
[Ownership Management design document](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)
|
||||
for more details.
|
||||
and writable by the GID specified in `fsGroup`. See the
|
||||
[Ownership Management design document](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)
|
||||
for more details.
|
||||
|
||||
* `seLinuxOptions`: Volumes that support SELinux labeling are relabeled to be accessible
|
||||
by the label specified under `seLinuxOptions`. Usually you only
|
||||
need to set the `level` section. This sets the
|
||||
[Multi-Category Security (MCS)](https://selinuxproject.org/page/NB_MLS)
|
||||
label given to all Containers in the Pod as well as the Volumes.
|
||||
by the label specified under `seLinuxOptions`. Usually you only
|
||||
need to set the `level` section. This sets the
|
||||
[Multi-Category Security (MCS)](https://selinuxproject.org/page/NB_MLS)
|
||||
label given to all Containers in the Pod as well as the Volumes.
|
||||
|
||||
{{< warning >}}
|
||||
After you specify an MCS label for a Pod, all Pods with the same label can access the Volume. If you need inter-Pod protection, you must assign a unique MCS label to each Pod.
|
||||
After you specify an MCS label for a Pod, all Pods with the same label can access the Volume.
|
||||
If you need inter-Pod protection, you must assign a unique MCS label to each Pod.
|
||||
{{< /warning >}}
|
||||
|
||||
## Clean up
|
||||
@@ -462,11 +480,8 @@ kubectl delete pod security-context-demo-3
|
||||
kubectl delete pod security-context-demo-4
|
||||
```
|
||||
|
||||
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
|
||||
* [PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core)
|
||||
* [SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core)
|
||||
* [Tuning Docker with the newest security enhancements](https://github.com/containerd/containerd/blob/main/docs/cri/config.md)
|
||||
|
||||
@@ -19,15 +19,14 @@ Kubernetes node. `crictl` and its source are hosted in the
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
|
||||
`crictl` requires a Linux operating system with a CRI runtime.
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
## Installing crictl
|
||||
|
||||
You can download a compressed archive `crictl` from the cri-tools [release
|
||||
page](https://github.com/kubernetes-sigs/cri-tools/releases), for several
|
||||
You can download a compressed archive `crictl` from the cri-tools
|
||||
[release page](https://github.com/kubernetes-sigs/cri-tools/releases), for several
|
||||
different architectures. Download the version that corresponds to your version
|
||||
of Kubernetes. Extract it and move it to a location on your system path, such as
|
||||
`/usr/local/bin/`.
|
||||
@@ -85,6 +84,7 @@ List all pods:
|
||||
```shell
|
||||
crictl pods
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -100,6 +100,7 @@ List pods by name:
|
||||
```shell
|
||||
crictl pods --name nginx-65899c769f-wv2gp
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -112,6 +113,7 @@ List pods by label:
|
||||
```shell
|
||||
crictl pods --label run=nginx
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -126,6 +128,7 @@ List all images:
|
||||
```shell
|
||||
crictl images
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -141,6 +144,7 @@ List images by repository:
|
||||
```shell
|
||||
crictl images nginx
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -153,6 +157,7 @@ Only list image IDs:
|
||||
```shell
|
||||
crictl images -q
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -169,6 +174,7 @@ List all containers:
|
||||
```shell
|
||||
crictl ps -a
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -181,9 +187,10 @@ CONTAINER ID IMAGE
|
||||
|
||||
List running containers:
|
||||
|
||||
```
|
||||
```shell
|
||||
crictl ps
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -198,6 +205,7 @@ CONTAINER ID IMAGE
|
||||
```shell
|
||||
crictl exec -i -t 1f73f2d81bf98 ls
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -211,6 +219,7 @@ Get all container logs:
|
||||
```shell
|
||||
crictl logs 87d3992f84f74
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -224,6 +233,7 @@ Get only the latest `N` lines of logs:
|
||||
```shell
|
||||
crictl logs --tail=1 87d3992f84f74
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -236,29 +246,29 @@ Using `crictl` to run a pod sandbox is useful for debugging container runtimes.
|
||||
On a running Kubernetes cluster, the sandbox will eventually be stopped and
|
||||
deleted by the Kubelet.
|
||||
|
||||
1. Create a JSON file like the following:
|
||||
1. Create a JSON file like the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"name": "nginx-sandbox",
|
||||
"namespace": "default",
|
||||
"attempt": 1,
|
||||
"uid": "hdishd83djaidwnduwk28bcsb"
|
||||
},
|
||||
"logDirectory": "/tmp",
|
||||
"linux": {
|
||||
}
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"name": "nginx-sandbox",
|
||||
"namespace": "default",
|
||||
"attempt": 1,
|
||||
"uid": "hdishd83djaidwnduwk28bcsb"
|
||||
},
|
||||
"logDirectory": "/tmp",
|
||||
"linux": {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. Use the `crictl runp` command to apply the JSON and run the sandbox.
|
||||
2. Use the `crictl runp` command to apply the JSON and run the sandbox.
|
||||
|
||||
```shell
|
||||
crictl runp pod-config.json
|
||||
```
|
||||
```shell
|
||||
crictl runp pod-config.json
|
||||
```
|
||||
|
||||
The ID of the sandbox is returned.
|
||||
The ID of the sandbox is returned.
|
||||
|
||||
### Create a container
|
||||
|
||||
@@ -266,68 +276,73 @@ Using `crictl` to create a container is useful for debugging container runtimes.
|
||||
On a running Kubernetes cluster, the sandbox will eventually be stopped and
|
||||
deleted by the Kubelet.
|
||||
|
||||
1. Pull a busybox image
|
||||
1. Pull a busybox image
|
||||
|
||||
```shell
|
||||
crictl pull busybox
|
||||
Image is up to date for busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
|
||||
```
|
||||
```shell
|
||||
crictl pull busybox
|
||||
```
|
||||
```none
|
||||
Image is up to date for busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
|
||||
```
|
||||
|
||||
2. Create configs for the pod and the container:
|
||||
2. Create configs for the pod and the container:
|
||||
|
||||
**Pod config**:
|
||||
```yaml
|
||||
{
|
||||
"metadata": {
|
||||
"name": "nginx-sandbox",
|
||||
"namespace": "default",
|
||||
"attempt": 1,
|
||||
"uid": "hdishd83djaidwnduwk28bcsb"
|
||||
},
|
||||
"log_directory": "/tmp",
|
||||
"linux": {
|
||||
}
|
||||
}
|
||||
```
|
||||
**Pod config**:
|
||||
|
||||
**Container config**:
|
||||
```yaml
|
||||
{
|
||||
"metadata": {
|
||||
"name": "busybox"
|
||||
},
|
||||
"image":{
|
||||
"image": "busybox"
|
||||
},
|
||||
"command": [
|
||||
"top"
|
||||
],
|
||||
"log_path":"busybox.log",
|
||||
"linux": {
|
||||
}
|
||||
}
|
||||
```
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"name": "nginx-sandbox",
|
||||
"namespace": "default",
|
||||
"attempt": 1,
|
||||
"uid": "hdishd83djaidwnduwk28bcsb"
|
||||
},
|
||||
"log_directory": "/tmp",
|
||||
"linux": {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Create the container, passing the ID of the previously-created pod, the
|
||||
container config file, and the pod config file. The ID of the container is
|
||||
returned.
|
||||
**Container config**:
|
||||
|
||||
```shell
|
||||
crictl create f84dd361f8dc51518ed291fbadd6db537b0496536c1d2d6c05ff943ce8c9a54f container-config.json pod-config.json
|
||||
```
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"name": "busybox"
|
||||
},
|
||||
"image":{
|
||||
"image": "busybox"
|
||||
},
|
||||
"command": [
|
||||
"top"
|
||||
],
|
||||
"log_path":"busybox.log",
|
||||
"linux": {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. List all containers and verify that the newly-created container has its
|
||||
state set to `Created`.
|
||||
3. Create the container, passing the ID of the previously-created pod, the
|
||||
container config file, and the pod config file. The ID of the container is
|
||||
returned.
|
||||
|
||||
```shell
|
||||
crictl ps -a
|
||||
```
|
||||
The output is similar to this:
|
||||
```shell
|
||||
crictl create f84dd361f8dc51518ed291fbadd6db537b0496536c1d2d6c05ff943ce8c9a54f container-config.json pod-config.json
|
||||
```
|
||||
|
||||
4. List all containers and verify that the newly-created container has its
|
||||
state set to `Created`.
|
||||
|
||||
```shell
|
||||
crictl ps -a
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT
|
||||
3e025dd50a72d busybox 32 seconds ago Created busybox 0
|
||||
```
|
||||
```
|
||||
CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT
|
||||
3e025dd50a72d busybox 32 seconds ago Created busybox 0
|
||||
```
|
||||
|
||||
### Start a container
|
||||
|
||||
@@ -336,6 +351,7 @@ To start a container, pass its ID to `crictl start`:
|
||||
```shell
|
||||
crictl start 3e025dd50a72d956c4f14881fbb5b1080c9275674e95fb67f965f6478a957d60
|
||||
```
|
||||
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
@@ -350,13 +366,12 @@ crictl ps
|
||||
The output is similar to this:
|
||||
|
||||
```
|
||||
CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT
|
||||
3e025dd50a72d busybox About a minute ago Running busybox 0
|
||||
CONTAINER ID IMAGE CREATED STATE NAME ATTEMPT
|
||||
3e025dd50a72d busybox About a minute ago Running busybox 0
|
||||
```
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
* [Learn more about `crictl`](https://github.com/kubernetes-sigs/cri-tools).
|
||||
* [Map `docker` CLI commands to `crictl`](/reference/tools/map-crictl-dockercli/).
|
||||
* [Map `docker` CLI commands to `crictl`](/docs/reference/tools/map-crictl-dockercli/).
|
||||
|
||||
<!-- discussion -->
|
||||
@@ -58,7 +58,8 @@ Again, the information from `kubectl describe ...` should be informative. The m
|
||||
|
||||
* Make sure that you have the name of the image correct.
|
||||
* Have you pushed the image to the registry?
|
||||
* Run a manual `docker pull <image>` on your machine to see if the image can be pulled.
|
||||
* Try to manually pull the image to see if the image can be pulled. For example,
|
||||
if you use Docker on your PC, run `docker pull <image>`.
|
||||
|
||||
#### My pod is crashing or otherwise unhealthy
|
||||
|
||||
|
||||
@@ -86,8 +86,8 @@ worker node, but it can't run on that machine. Again, the information from
|
||||
|
||||
* Make sure that you have the name of the image correct.
|
||||
* Have you pushed the image to the repository?
|
||||
* Run a manual `docker pull <image>` on your machine to see if the image can be
|
||||
pulled.
|
||||
* Try to manually pull the image to see if it can be pulled. For example, if you
|
||||
use Docker on your PC, run `docker pull <image>`.
|
||||
|
||||
### My pod is crashing or otherwise unhealthy
|
||||
|
||||
|
||||
@@ -45,8 +45,9 @@ and command-line interfaces (CLIs), such as [`kubectl`](/docs/reference/kubectl/
|
||||
Someone else from the community may have already asked a similar question or may
|
||||
be able to help with your problem. The Kubernetes team will also monitor
|
||||
[posts tagged Kubernetes](https://stackoverflow.com/questions/tagged/kubernetes).
|
||||
If there aren't any existing questions that help, please
|
||||
[ask a new one](https://stackoverflow.com/questions/ask?tags=kubernetes)!
|
||||
If there aren't any existing questions that help, **please [ensure that your question is on-topic on Stack Overflow](https://stackoverflow.com/help/on-topic)
|
||||
and that you read through the guidance on [how to ask a new question](https://stackoverflow.com/help/how-to-ask)**,
|
||||
before [asking a new one](https://stackoverflow.com/questions/ask?tags=kubernetes)!
|
||||
|
||||
### Slack
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ or the custom metrics API (for all other metrics).
|
||||
The common use for HorizontalPodAutoscaler is to configure it to fetch metrics from
|
||||
{{< glossary_tooltip text="aggregated APIs" term_id="aggregation-layer" >}}
|
||||
(`metrics.k8s.io`, `custom.metrics.k8s.io`, or `external.metrics.k8s.io`). The `metrics.k8s.io` API is
|
||||
usually provided by an add on named Metrics Server, which needs to be launched separately.
|
||||
usually provided by an add-on named Metrics Server, which needs to be launched separately.
|
||||
For more information about resource metrics, see
|
||||
[Metrics Server](/docs/tasks/debug-application-cluster/resource-metrics-pipeline/#metrics-server).
|
||||
|
||||
@@ -329,7 +329,7 @@ APIs, cluster administrators must ensure that:
|
||||
* The corresponding APIs are registered:
|
||||
|
||||
* For resource metrics, this is the `metrics.k8s.io` API, generally provided by [metrics-server](https://github.com/kubernetes-sigs/metrics-server).
|
||||
It can be launched as a cluster addon.
|
||||
It can be launched as a cluster add-on.
|
||||
|
||||
* For custom metrics, this is the `custom.metrics.k8s.io` API. It's provided by "adapter" API servers provided by metrics solution vendors.
|
||||
Check with your metrics pipeline to see if there is a Kubernetes metrics adapter available.
|
||||
@@ -514,7 +514,7 @@ Finally, you can delete an autoscaler using `kubectl delete hpa`.
|
||||
|
||||
In addition, there is a special `kubectl autoscale` command for creating a HorizontalPodAutoscaler object.
|
||||
For instance, executing `kubectl autoscale rs foo --min=2 --max=5 --cpu-percent=80`
|
||||
will create an autoscaler for replication set *foo*, with target CPU utilization set to `80%`
|
||||
will create an autoscaler for ReplicaSet *foo*, with target CPU utilization set to `80%`
|
||||
and the number of replicas between 2 and 5.
|
||||
|
||||
## Implicit maintenance-mode deactivation
|
||||
@@ -538,7 +538,7 @@ desired and could be troublesome when an HPA is active.
|
||||
|
||||
Keep in mind that the removal of `spec.replicas` may incur a one-time
|
||||
degradation of Pod counts as the default value of this key is 1 (reference
|
||||
[Deployment Replicas](/docs/concepts/workloads/controllers/deployment#replicas).
|
||||
[Deployment Replicas](/docs/concepts/workloads/controllers/deployment#replicas)).
|
||||
Upon the update, all Pods except 1 will begin their termination procedures. Any
|
||||
deployment application afterwards will behave as normal and respect a rolling
|
||||
update configuration as desired. You can avoid this degradation by choosing one of the following two
|
||||
|
||||
@@ -29,13 +29,18 @@ these certificates will validate against the cluster root CA.
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
|
||||
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
|
||||
{{< include "task-tutorial-prereqs.md" >}}
|
||||
|
||||
You need the `cfssl` tool. You can download `cfssl` from
|
||||
[https://github.com/cloudflare/cfssl/releases](https://github.com/cloudflare/cfssl/releases).
|
||||
|
||||
Some steps in this page use the `jq` tool. If you don't have `jq`, you can
|
||||
install it via your operating system's software sources, or fetch it from
|
||||
[https://stedolan.github.io/jq/](https://stedolan.github.io/jq/).
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
## Trusting TLS in a Cluster
|
||||
## Trusting TLS in a cluster
|
||||
|
||||
Trusting the custom CA from an application running as a pod usually requires
|
||||
some extra application configuration. You will need to add the CA certificate
|
||||
@@ -48,7 +53,7 @@ You can distribute the CA certificate as a
|
||||
[ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap) that your
|
||||
pods have access to use.
|
||||
|
||||
## Requesting a Certificate
|
||||
## Requesting a certificate
|
||||
|
||||
The following section demonstrates how to create a TLS certificate for a
|
||||
Kubernetes service accessed through DNS.
|
||||
@@ -57,12 +62,7 @@ Kubernetes service accessed through DNS.
|
||||
This tutorial uses CFSSL: Cloudflare's PKI and TLS toolkit [click here](https://blog.cloudflare.com/introducing-cfssl/) to know more.
|
||||
{{< /note >}}
|
||||
|
||||
## Download and install CFSSL
|
||||
|
||||
The cfssl tools used in this example can be downloaded at
|
||||
[https://github.com/cloudflare/cfssl/releases](https://github.com/cloudflare/cfssl/releases).
|
||||
|
||||
## Create a Certificate Signing Request
|
||||
## Create a certificate signing request
|
||||
|
||||
Generate a private key and certificate signing request (or CSR) by running
|
||||
the following command:
|
||||
@@ -98,14 +98,14 @@ is the pod's DNS name. You should see the output similar to:
|
||||
```
|
||||
|
||||
This command generates two files; it generates `server.csr` containing the PEM
|
||||
encoded [pkcs#10](https://tools.ietf.org/html/rfc2986) certification request,
|
||||
encoded [PKCS#10](https://tools.ietf.org/html/rfc2986) certification request,
|
||||
and `server-key.pem` containing the PEM encoded key to the certificate that
|
||||
is still to be created.
|
||||
|
||||
## Create a Certificate Signing Request object to send to the Kubernetes API
|
||||
## Create a CertificateSigningRequest object to send to the Kubernetes API
|
||||
|
||||
Generate a CSR yaml blob and send it to the apiserver by running the following
|
||||
command:
|
||||
Generate a CSR manifest (in YAML), and send it to the API server. You can do that by
|
||||
running the following command:
|
||||
|
||||
```shell
|
||||
cat <<EOF | kubectl apply -f -
|
||||
@@ -124,7 +124,7 @@ EOF
|
||||
```
|
||||
|
||||
Notice that the `server.csr` file created in step 1 is base64 encoded
|
||||
and stashed in the `.spec.request` field. We are also requesting a
|
||||
and stashed in the `.spec.request` field. You are also requesting a
|
||||
certificate with the "digital signature", "key encipherment", and "server
|
||||
auth" key usages, signed by an example `example.com/serving` signer.
|
||||
A specific `signerName` must be requested.
|
||||
@@ -157,7 +157,7 @@ Subject Alternative Names:
|
||||
Events: <none>
|
||||
```
|
||||
|
||||
## Get the Certificate Signing Request Approved
|
||||
## Get the CertificateSigningRequest approved {#get-the-certificate-signing-request-approved}
|
||||
|
||||
Approving the [certificate signing request](/docs/reference/access-authn-authz/certificate-signing-requests/)
|
||||
is either done by an automated approval process or on a one off basis by a cluster
|
||||
@@ -186,16 +186,18 @@ my-svc.my-namespace 10m example.com/serving yourname@example.com <none>
|
||||
This means the certificate request has been approved and is waiting for the
|
||||
requested signer to sign it.
|
||||
|
||||
## Sign the Certificate Signing Request
|
||||
## Sign the CertificateSigningRequest {#sign-the-certificate-signing-request}
|
||||
|
||||
Next, you'll play the part of a certificate signer, issue the certificate, and upload it to the API.
|
||||
|
||||
A signer would typically watch the Certificate Signing Request API for objects with its `signerName`,
|
||||
check that they have been approved, sign certificates for those requests,
|
||||
A signer would typically watch the CertificateSigningRequest API for objects with its `signerName`,
|
||||
check that they have been approved, sign certificates for those requests,
|
||||
and update the API object status with the issued certificate.
|
||||
|
||||
### Create a Certificate Authority
|
||||
|
||||
You need an authority to provide the digital signature on the new certificate.
|
||||
|
||||
First, create a signing certificate by running the following:
|
||||
|
||||
```shell
|
||||
@@ -210,7 +212,7 @@ cat <<EOF | cfssl gencert -initca - | cfssljson -bare ca
|
||||
EOF
|
||||
```
|
||||
|
||||
You should see the output similar to:
|
||||
You should see output similar to:
|
||||
|
||||
```none
|
||||
2022/02/01 11:50:39 [INFO] generating a new CA key and certificate from CSR
|
||||
@@ -223,7 +225,7 @@ You should see the output similar to:
|
||||
|
||||
This produces a certificate authority key file (`ca-key.pem`) and certificate (`ca.pem`).
|
||||
|
||||
### Issue a Certificate
|
||||
### Issue a certificate
|
||||
|
||||
{{< codenew file="tls/server-signing-config.json" >}}
|
||||
|
||||
@@ -245,7 +247,7 @@ You should see the output similar to:
|
||||
|
||||
This produces a signed serving certificate file, `ca-signed-server.pem`.
|
||||
|
||||
### Upload the Signed Certificate
|
||||
### Upload the signed certificate
|
||||
|
||||
Finally, populate the signed certificate in the API object's status:
|
||||
|
||||
@@ -256,24 +258,27 @@ kubectl get csr my-svc.my-namespace -o json | \
|
||||
```
|
||||
|
||||
{{< note >}}
|
||||
This uses the command line tool [jq](https://stedolan.github.io/jq/) to populate the base64-encoded content in the `.status.certificate` field.
|
||||
If you do not have `jq`, you can also save the JSON output to a file, populate this field manually, and upload the resulting file.
|
||||
This uses the command line tool [`jq`](https://stedolan.github.io/jq/) to populate the base64-encoded
|
||||
content in the `.status.certificate` field.
|
||||
If you do not have `jq`, you can also save the JSON output to a file, populate this field manually, and
|
||||
upload the resulting file.
|
||||
{{< /note >}}
|
||||
|
||||
Once the CSR is approved and the signed certificate is uploaded you should see the following:
|
||||
Once the CSR is approved and the signed certificate is uploaded, run:
|
||||
|
||||
```shell
|
||||
kubectl get csr
|
||||
```
|
||||
|
||||
The output is similar to:
|
||||
```none
|
||||
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
|
||||
my-svc.my-namespace 20m example.com/serving yourname@example.com <none> Approved,Issued
|
||||
```
|
||||
|
||||
## Download the Certificate and Use It
|
||||
## Download the certificate and use it
|
||||
|
||||
Now, as the requesting user, you can download the issued certificate
|
||||
Now, as the requesting user, you can download the issued certificate
|
||||
and save it to a `server.crt` file by running the following:
|
||||
|
||||
```shell
|
||||
@@ -281,37 +286,48 @@ kubectl get csr my-svc.my-namespace -o jsonpath='{.status.certificate}' \
|
||||
| base64 --decode > server.crt
|
||||
```
|
||||
|
||||
Now you can populate `server.crt` and `server-key.pem` in a secret and mount
|
||||
it into a pod to use as the keypair to start your HTTPS server:
|
||||
Now you can populate `server.crt` and `server-key.pem` in a
|
||||
{{< glossary_tooltip text="Secret" term_id="secret" >}}
|
||||
that you could later mount into a Pod (for example, to use with a webserver
|
||||
that serves HTTPS).
|
||||
|
||||
```shell
|
||||
kubectl create secret tls server --cert server.crt --key server-key.pem
|
||||
kubectl create secret tls server --cert server.crt --key server-key.pem
|
||||
```
|
||||
|
||||
```none
|
||||
secret/server created
|
||||
```
|
||||
|
||||
Finally, you can populate `ca.pem` in a configmap and use it as the trust root
|
||||
to verify the serving certificate:
|
||||
Finally, you can populate `ca.pem` into a {< glossary_tooltip text="ConfigMap" term_id="configmap" >}}
|
||||
and use it as the trust root to verify the serving certificate:
|
||||
|
||||
```shell
|
||||
kubectl create configmap example-serving-ca --from-file ca.crt=ca.pem
|
||||
kubectl create configmap example-serving-ca --from-file ca.crt=ca.pem
|
||||
```
|
||||
|
||||
```none
|
||||
configmap/example-serving-ca created
|
||||
```
|
||||
|
||||
## Approving Certificate Signing Requests
|
||||
## Approving CertificateSigningRequests {#approving-certificate-signing-requests}
|
||||
|
||||
A Kubernetes administrator (with appropriate permissions) can manually approve
|
||||
(or deny) Certificate Signing Requests by using the `kubectl certificate
|
||||
(or deny) CertificateSigningRequests by using the `kubectl certificate
|
||||
approve` and `kubectl certificate deny` commands. However if you intend
|
||||
to make heavy usage of this API, you might consider writing an automated
|
||||
certificates controller.
|
||||
|
||||
Whether a machine or a human using kubectl as above, the role of the approver is
|
||||
{{< caution >}}
|
||||
The ability to approve CSRs decides who trusts whom within your environment. The
|
||||
ability to approve CSRs should not be granted broadly or lightly.
|
||||
|
||||
You should make sure that you confidently understand both the verification requirements
|
||||
that fall on the approver **and** the repercussions of issuing a specific certificate
|
||||
before you grant the `approve` permission.
|
||||
{{< /caution >}}
|
||||
|
||||
Whether a machine or a human using kubectl as above, the role of the _approver_ is
|
||||
to verify that the CSR satisfies two requirements:
|
||||
|
||||
1. The subject of the CSR controls the private key used to sign the CSR. This
|
||||
@@ -326,20 +342,15 @@ to verify that the CSR satisfies two requirements:
|
||||
If and only if these two requirements are met, the approver should approve
|
||||
the CSR and otherwise should deny the CSR.
|
||||
|
||||
## A Word of Warning on the Approval Permission
|
||||
For more information on certificate approval and access control, read
|
||||
the [Certificate Signing Requests](/docs/reference/access-authn-authz/certificate-signing-requests/)
|
||||
reference page.
|
||||
|
||||
The ability to approve CSRs decides who trusts whom within your environment. The
|
||||
ability to approve CSRs should not be granted broadly or lightly. The
|
||||
requirements of the challenge noted in the previous section and the
|
||||
repercussions of issuing a specific certificate should be fully understood
|
||||
before granting this permission.
|
||||
## Configuring your cluster to provide signing
|
||||
|
||||
## A Note to Cluster Administrators
|
||||
|
||||
This tutorial assumes that a signer is setup to serve the certificates API. The
|
||||
This page assumes that a signer is setup to serve the certificates API. The
|
||||
Kubernetes controller manager provides a default implementation of a signer. To
|
||||
enable it, pass the `--cluster-signing-cert-file` and
|
||||
`--cluster-signing-key-file` parameters to the controller manager with paths to
|
||||
your Certificate Authority's keypair.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user