Merge remote-tracking branch 'upstream/main' into dev-1.30

pull/45559/head
Vyom-Yadav 2024-03-15 16:42:11 +05:30
commit 1eb315a43a
No known key found for this signature in database
116 changed files with 5999 additions and 498 deletions

View File

@ -49,14 +49,15 @@ aliases:
- windsonsea
sig-docs-es-owners: # Admins for Spanish content
- 92nqb
- krol3
- electrocucaracha
- krol3
- raelga
- ramrodo
sig-docs-es-reviews: # PR reviews for Spanish content
- 92nqb
- krol3
- electrocucaracha
- jossemarGT
- krol3
- raelga
- ramrodo
sig-docs-fr-owners: # Admins for French content

View File

@ -732,6 +732,8 @@ body.td-documentation {
}
}
/* Announcements */
#announcement {
> * {
color: inherit;
@ -753,10 +755,21 @@ body.td-documentation {
padding-top: 40px;
}
// Don't show announcements when javascript is not available
html.no-js body div#announcement {
display: none;
}
#announcement.display-announcement{
display: block; // apply this class to display the announcement
}
#announcement {
// default background is blue; overrides are possible
color: #fff;
display: none; // When javascript is available, Let javascript handle the state of the announcement
.announcement-main {
margin-left: auto;
margin-right: auto;

View File

@ -64,7 +64,7 @@ time to review the [dockershim migration documentation](/docs/tasks/administer-c
and consult your Kubernetes hosting vendor (if you have one) what container runtime options are available for you.
Read up [container runtime documentation with instructions on how to use containerd and CRI-O](/docs/setup/production-environment/container-runtimes/#container-runtimes)
to help prepare you when you're ready to upgrade to 1.24. CRI-O, containerd, and
Docker with [Mirantis cri-dockerd](https://github.com/Mirantis/cri-dockerd) are
Docker with [Mirantis cri-dockerd](https://mirantis.github.io/cri-dockerd/) are
not the only container runtime options, we encourage you to explore the [CNCF landscape on container runtimes](https://landscape.cncf.io/?group=projects-and-products&view-mode=card#runtime--container-runtime)
in case another suits you better.

View File

@ -109,7 +109,7 @@ Kubernetes clusters. Containers make this kind of interoperability possible.
Mirantis and Docker have [committed][mirantis] to maintaining a replacement adapter for
Docker Engine, and to maintain that adapter even after the in-tree dockershim is removed
from Kubernetes. The replacement adapter is named [`cri-dockerd`](https://github.com/Mirantis/cri-dockerd).
from Kubernetes. The replacement adapter is named [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/).
You can install `cri-dockerd` and use it to connect the kubelet to Docker Engine. Read [Migrate Docker Engine nodes from dockershim to cri-dockerd](/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd/) to learn more.

View File

@ -173,6 +173,8 @@ publishing packages to the Google-hosted repository in the future.
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
```
_Update: In releases older than Debian 12 and Ubuntu 22.04, the folder `/etc/apt/keyrings` does not exist by default, and it should be created before the curl command._
3. Update the `apt` package index:
```shell

View File

@ -0,0 +1,476 @@
---
layout: blog
title: "CRI-O: Applying seccomp profiles from OCI registries"
date: 2024-03-07
slug: cri-o-seccomp-oci-artifacts
---
**Author:** Sascha Grunert
Seccomp stands for secure computing mode and has been a feature of the Linux
kernel since version 2.6.12. It can be used to sandbox the privileges of a
process, restricting the calls it is able to make from userspace into the
kernel. Kubernetes lets you automatically apply seccomp profiles loaded onto a
node to your Pods and containers.
But distributing those seccomp profiles is a major challenge in Kubernetes,
because the JSON files have to be available on all nodes where a workload can
possibly run. Projects like the [Security Profiles
Operator](https://sigs.k8s.io/security-profiles-operator) solve that problem by
running as a daemon within the cluster, which makes me wonder which part of that
distribution could be done by the [container
runtime](/docs/setup/production-environment/container-runtimes).
Runtimes usually apply the profiles from a local path, for example:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- name: container
image: nginx:1.25.3
securityContext:
seccompProfile:
type: Localhost
localhostProfile: nginx-1.25.3.json
```
The profile `nginx-1.25.3.json` has to be available in the root directory of the
kubelet, appended by the `seccomp` directory. This means the default location
for the profile on-disk would be `/var/lib/kubelet/seccomp/nginx-1.25.3.json`.
If the profile is not available, then runtimes will fail on container creation
like this:
```shell
kubectl get pods
```
```console
NAME READY STATUS RESTARTS AGE
pod 0/1 CreateContainerError 0 38s
```
```shell
kubectl describe pod/pod | tail
```
```console
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 117s default-scheduler Successfully assigned default/pod to 127.0.0.1
Normal Pulling 117s kubelet Pulling image "nginx:1.25.3"
Normal Pulled 111s kubelet Successfully pulled image "nginx:1.25.3" in 5.948s (5.948s including waiting)
Warning Failed 7s (x10 over 111s) kubelet Error: setup seccomp: unable to load local profile "/var/lib/kubelet/seccomp/nginx-1.25.3.json": open /var/lib/kubelet/seccomp/nginx-1.25.3.json: no such file or directory
Normal Pulled 7s (x9 over 111s) kubelet Container image "nginx:1.25.3" already present on machine
```
The major obstacle of having to manually distribute the `Localhost` profiles
will lead many end-users to fall back to `RuntimeDefault` or even running their
workloads as `Unconfined` (with disabled seccomp).
## CRI-O to the rescue
The Kubernetes container runtime [CRI-O](https://github.com/cri-o/cri-o)
provides various features using custom annotations. The v1.30 release
[adds](https://github.com/cri-o/cri-o/pull/7719) support for a new set of
annotations called `seccomp-profile.kubernetes.cri-o.io/POD` and
`seccomp-profile.kubernetes.cri-o.io/<CONTAINER>`. Those annotations allow you
to specify:
- a seccomp profile for a specific container, when used as:
`seccomp-profile.kubernetes.cri-o.io/<CONTAINER>` (example:
`seccomp-profile.kubernetes.cri-o.io/webserver:
'registry.example/example/webserver:v1'`)
- a seccomp profile for every container within a pod, when used without the
container name suffix but the reserved name `POD`:
`seccomp-profile.kubernetes.cri-o.io/POD`
- a seccomp profile for a whole container image, if the image itself contains
the annotation `seccomp-profile.kubernetes.cri-o.io/POD` or
`seccomp-profile.kubernetes.cri-o.io/<CONTAINER>`.
CRI-O will only respect the annotation if the runtime is configured to allow it,
as well as for workloads running as `Unconfined`. All other workloads will still
use the value from the `securityContext` with a higher priority.
The annotations alone will not help much with the distribution of the profiles,
but the way they can be referenced will! For example, you can now specify
seccomp profiles like regular container images by using OCI artifacts:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod
annotations:
seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2
spec: …
```
The image `quay.io/crio/seccomp:v2` contains a `seccomp.json` file, which
contains the actual profile content. Tools like [ORAS](https://oras.land) or
[Skopeo](https://github.com/containers/skopeo) can be used to inspect the
contents of the image:
```shell
oras pull quay.io/crio/seccomp:v2
```
```console
Downloading 92d8ebfa89aa seccomp.json
Downloaded 92d8ebfa89aa seccomp.json
Pulled [registry] quay.io/crio/seccomp:v2
Digest: sha256:f0205dac8a24394d9ddf4e48c7ac201ca7dcfea4c554f7ca27777a7f8c43ec1b
```
```shell
jq . seccomp.json | head
```
```yaml
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"defaultErrno": "ENOSYS",
"archMap": [
{
"architecture": "SCMP_ARCH_X86_64",
"subArchitectures": [
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
```
```shell
# Inspect the plain manifest of the image
skopeo inspect --raw docker://quay.io/crio/seccomp:v2 | jq .
```
```yaml
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config":
{
"mediaType": "application/vnd.cncf.seccomp-profile.config.v1+json",
"digest": "sha256:ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356",
"size": 3,
},
"layers":
[
{
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"digest": "sha256:92d8ebfa89aa6dd752c6443c27e412df1b568d62b4af129494d7364802b2d476",
"size": 18853,
"annotations": { "org.opencontainers.image.title": "seccomp.json" },
},
],
"annotations": { "org.opencontainers.image.created": "2024-02-26T09:03:30Z" },
}
```
The image manifest contains a reference to a specific required config media type
(`application/vnd.cncf.seccomp-profile.config.v1+json`) and a single layer
(`application/vnd.oci.image.layer.v1.tar`) pointing to the `seccomp.json` file.
But now, let's give that new feature a try!
### Using the annotation for a specific container or whole pod
CRI-O needs to be configured adequately before it can utilize the annotation. To
do this, add the annotation to the `allowed_annotations` array for the runtime.
This can be done by using a drop-in configuration
`/etc/crio/crio.conf.d/10-crun.conf` like this:
```toml
[crio.runtime]
default_runtime = "crun"
[crio.runtime.runtimes.crun]
allowed_annotations = [
"seccomp-profile.kubernetes.cri-o.io",
]
```
Now, let's run CRI-O from the latest `main` commit. This can be done by either
building it from source, using the [static binary bundles](https://github.com/cri-o/packaging?tab=readme-ov-file#using-the-static-binary-bundles-directly)
or [the prerelease packages](https://github.com/cri-o/packaging?tab=readme-ov-file#usage).
To demonstrate this, I ran the `crio` binary from my command line using a single
node Kubernetes cluster via [`local-up-cluster.sh`](https://github.com/cri-o/cri-o?tab=readme-ov-file#running-kubernetes-with-cri-o).
Now that the cluster is up and running, let's try a pod without the annotation
running as seccomp `Unconfined`:
```shell
cat pod.yaml
```
```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- name: container
image: nginx:1.25.3
securityContext:
seccompProfile:
type: Unconfined
```
```shell
kubectl apply -f pod.yaml
```
The workload is up and running:
```shell
kubectl get pods
```
```console
NAME READY STATUS RESTARTS AGE
pod 1/1 Running 0 15s
```
And no seccomp profile got applied if I inspect the container using
[`crictl`](https://sigs.k8s.io/cri-tools):
```shell
export CONTAINER_ID=$(sudo crictl ps --name container -q)
sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp
```
```console
null
```
Now, let's modify the pod to apply the profile `quay.io/crio/seccomp:v2` to the
container:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod
annotations:
seccomp-profile.kubernetes.cri-o.io/container: quay.io/crio/seccomp:v2
spec:
containers:
- name: container
image: nginx:1.25.3
```
I have to delete and recreate the Pod, because only recreation will apply a new
seccomp profile:
```shell
kubectl delete pod/pod
```
```console
pod "pod" deleted
```
```shell
kubectl apply -f pod.yaml
```
```console
pod/pod created
```
The CRI-O logs will now indicate that the runtime pulled the artifact:
```console
WARN[…] Allowed annotations are specified for workload [seccomp-profile.kubernetes.cri-o.io]
INFO[…] Found container specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io/container=quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer
```
And the container is finally using the profile:
```shell
export CONTAINER_ID=$(sudo crictl ps --name container -q)
sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head
```
```yaml
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
```
The same would work for every container in the pod, if users replace the
`/container` suffix with the reserved name `/POD`, for example:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod
annotations:
seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2
spec:
containers:
- name: container
image: nginx:1.25.3
```
### Using the annotation for a container image
While specifying seccomp profiles as OCI artifacts on certain workloads is a
cool feature, the majority of end users would like to link seccomp profiles to
published container images. This can be done by using a container image
annotation; instead of being applied to a Kubernetes Pod, the annotation is some
metadata applied at the container image itself. For example,
[Podman](https://podman.io) can be used to add the image annotation directly
during image build:
```shell
podman build \
--annotation seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 \
-t quay.io/crio/nginx-seccomp:v2 .
```
The pushed image then contains the annotation:
```shell
skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2 |
jq '.annotations."seccomp-profile.kubernetes.cri-o.io"'
```
```console
"quay.io/crio/seccomp:v2"
```
If I now use that image in an CRI-O test pod definition:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod
# no Pod annotations set
spec:
containers:
- name: container
image: quay.io/crio/nginx-seccomp:v2
```
Then the CRI-O logs will indicate that the image annotation got evaluated and
the profile got applied:
```shell
kubectl delete pod/pod
```
```console
pod "pod" deleted
```
```shell
kubectl apply -f pod.yaml
```
```console
pod/pod created
```
```console
INFO[…] Found image specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Created container 116a316cd9a11fe861dd04c43b94f45046d1ff37e2ed05a4e4194fcaab29ee63: default/pod/container id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
```
```shell
export CONTAINER_ID=$(sudo crictl ps --name container -q)
sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head
```
```yaml
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
```
For container images, the annotation `seccomp-profile.kubernetes.cri-o.io` will
be treated in the same way as `seccomp-profile.kubernetes.cri-o.io/POD` and
applies to the whole pod. In addition to that, the whole feature also works when
using the container specific annotation on an image, for example if a container
is named `container1`:
```shell
skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2-container |
jq '.annotations."seccomp-profile.kubernetes.cri-o.io/container1"'
```
```console
"quay.io/crio/seccomp:v2"
```
The cool thing about this whole feature is that users can now create seccomp
profiles for specific container images and store them side by side in the same
registry. Linking the images to the profiles provides a great flexibility to
maintain them over the whole application's life cycle.
### Pushing profiles using ORAS
The actual creation of the OCI object that contains a seccomp profile requires a
bit more work when using ORAS. I have the hope that tools like Podman will
simplify the overall process in the future. Right now, the container registry
needs to be [OCI compatible](https://oras.land/docs/compatible_oci_registries/#registries-supporting-oci-artifacts),
which is also the case for [Quay.io](https://quay.io). CRI-O expects the seccomp
profile object to have a container image media type
(`application/vnd.cncf.seccomp-profile.config.v1+json`), while ORAS uses
`application/vnd.oci.empty.v1+json` per default. To achieve all of that, the
following commands can be executed:
```shell
echo "{}" > config.json
oras push \
--config config.json:application/vnd.cncf.seccomp-profile.config.v1+json \
quay.io/crio/seccomp:v2 seccomp.json
```
The resulting image contains the `mediaType` that CRI-O expects. ORAS pushes a
single layer `seccomp.json` to the registry. The name of the profile does not
matter much. CRI-O will pick the first layer and check if that can act as a
seccomp profile.
## Future work
CRI-O internally manages the OCI artifacts like regular files. This provides the
benefit of moving them around, removing them if not used any more or having any
other data available than seccomp profiles. This enables future enhancements in
CRI-O on top of OCI artifacts, but also allows thinking about stacking seccomp
profiles as part of having multiple layers in an OCI artifact. The limitation
that it only works for `Unconfined` workloads for v1.30.x releases is something
different CRI-O would like to address in the future. Simplifying the overall
user experience by not compromising security seems to be the key for a
successful future of seccomp in container workloads.
The CRI-O maintainers will be happy to listen to any feedback or suggestions on
the new feature! Thank you for reading this blog post, feel free to reach out
to the maintainers via the Kubernetes [Slack channel #crio](https://kubernetes.slack.com/messages/CAZH62UR1)
or create an issue in the [GitHub repository](https://github.com/cri-o/cri-o).

View File

@ -0,0 +1,126 @@
---
layout: blog
title: 'A Peek at Kubernetes v1.30'
date: 2024-03-12
slug: kubernetes-1-30-upcoming-changes
---
**Authors:** Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko
## A quick look: exciting changes in Kubernetes v1.30
It's a new year and a new Kubernetes release. We're halfway through the release cycle and
have quite a few interesting and exciting enhancements coming in v1.30. From brand new features
in alpha, to established features graduating to stable, to long-awaited improvements, this release
has something for everyone to pay attention to!
To tide you over until the official release, here's a sneak peek of the enhancements we're most
excited about in this cycle!
## Major changes for Kubernetes v1.30
### Structured parameters for dynamic resource allocation ([KEP-4381](https://kep.k8s.io/4381))
[Dynamic resource allocation](/docs/concepts/scheduling-eviction/dynamic-resource-allocation/) was
added to Kubernetes as an alpha feature in v1.26. It defines an alternative to the traditional
device-plugin API for requesting access to third-party resources. By design, dynamic resource
allocation uses parameters for resources that are completely opaque to core Kubernetes. This
approach poses a problem for the Cluster Autoscaler (CA) or any higher-level controller that
needs to make decisions for a group of pods (e.g. a job scheduler). It cannot simulate the effect of
allocating or deallocating claims over time. Only the third-party DRA drivers have the information
available to do this.
Structured Parameters for dynamic resource allocation is an extension to the original
implementation that addresses this problem by building a framework to support making these claim
parameters less opaque. Instead of handling the semantics of all claim parameters themselves,
drivers could manage resources and describe them using a specific "structured model" pre-defined by
Kubernetes. This would allow components aware of this "structured model" to make decisions about
these resources without outsourcing them to some third-party controller. For example, the scheduler
could allocate claims rapidly without back-and-forth communication with dynamic resource
allocation drivers. Work done for this release centers on defining the framework necessary to enable
different "structured models" and to implement the "named resources" model. This model allows
listing individual resource instances and, compared to the traditional device plugin API, adds the
ability to select those instances individually via attributes.
### Node memory swap support ([KEP-2400](https://kep.k8s.io/2400))
In Kubernetes v1.30, memory swap support on Linux nodes gets a big change to how it works - with a
strong emphasis on improving system stability. In previous Kubernetes versions, the `NodeSwap`
feature gate was disabled by default, and when enabled, it used `UnlimitedSwap` behavior as the
default behavior. To achieve better stability, `UnlimitedSwap` behavior (which might compromise node
stability) will be removed in v1.30.
The updated, still-beta support for swap on Linux nodes will be available by default. However, the
default behavior will be to run the node set to `NoSwap` (not `UnlimitedSwap`) mode. In `NoSwap`
mode, the kubelet supports running on a node where swap space is active, but Pods don't use any of
the page file. You'll still need to set `--fail-swap-on=false` for the kubelet to run on that node.
However, the big change is the other mode: `LimitedSwap`. In this mode, the kubelet actually uses
the page file on that node and allows Pods to have some of their virtual memory paged out.
Containers (and their parent pods) do not have access to swap beyond their memory limit, but the
system can still use the swap space if available.
Kubernetes' Node special interest group (SIG Node) will also update the documentation to help you
understand how to use the revised implementation, based on feedback from end users, contributors,
and the wider Kubernetes community.
Read the previous [blog post](/blog/2023/08/24/swap-linux-beta/) or the [node swap
documentation](/docs/concepts/architecture/nodes/#swap-memory) for more details on
Linux node swap support in Kubernetes.
### Support user namespaces in pods ([KEP-127](https://kep.k8s.io/127))
[User namespaces](/docs/concepts/workloads/pods/user-namespaces) is a Linux-only feature that better
isolates pods to prevent or mitigate several CVEs rated high/critical, including
[CVE-2024-21626](https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv),
published in January 2024. In Kubernetes 1.30, support for user namespaces is migrating to beta and
now supports pods with and without volumes, custom UID/GID ranges, and more!
### Structured authorization configuration ([KEP-3221](https://kep.k8s.io/3221))
Support for [structured authorization
configuration](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file)
is moving to beta and will be enabled by default. This feature enables the creation of
authorization chains with multiple webhooks with well-defined parameters that validate requests in a
particular order and allows fine-grained control such as explicit Deny on failures. The
configuration file approach even allows you to specify [CEL](/docs/reference/using-api/cel/) rules
to pre-filter requests before they are dispatched to webhooks, helping you to prevent unnecessary
invocations. The API server also automatically reloads the authorizer chain when the configuration
file is modified.
You must specify the path to that authorization configuration using the `--authorization-config`
command line argument. If you want to keep using command line flags instead of a
configuration file, those will continue to work as-is. To gain access to new authorization webhook
capabilities like multiple webhooks, failure policy, and pre-filter rules, switch to putting options
in an `--authorization-config` file. From Kubernetes 1.30, the configuration file format is
beta-level, and only requires specifying `--authorization-config` since the feature gate is enabled by
default. An example configuration with all possible values is provided in the [Authorization
docs](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file).
For more details, read the [Authorization
docs](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file).
### Container resource based pod autoscaling ([KEP-1610](https://kep.k8s.io/1610))
Horizontal pod autoscaling based on `ContainerResource` metrics will graduate to stable in v1.30.
This new behavior for HorizontalPodAutoscaler allows you to configure automatic scaling based on the
resource usage for individual containers, rather than the aggregate resource use over a Pod. See our
[previous article](/blog/2023/05/02/hpa-container-resource-metric/) for further details, or read
[container resource metrics](/docs/tasks/run-application/horizontal-pod-autoscale/#container-resource-metrics).
### CEL for admission control ([KEP-3488](https://kep.k8s.io/3488))
Integrating Common Expression Language (CEL) for admission control in Kubernetes introduces a more
dynamic and expressive way of evaluating admission requests. This feature allows complex,
fine-grained policies to be defined and enforced directly through the Kubernetes API, enhancing
security and governance capabilities without compromising performance or flexibility.
CEL's addition to Kubernetes admission control empowers cluster administrators to craft intricate
rules that can evaluate the content of API requests against the desired state and policies of the
cluster without resorting to Webhook-based access controllers. This level of control is crucial for
maintaining the integrity, security, and efficiency of cluster operations, making Kubernetes
environments more robust and adaptable to various use cases and requirements. For more information
on using CEL for admission control, see the [API
documentation](/docs/reference/access-authn-authz/validating-admission-policy/) for
ValidatingAdmissionPolicy.
We hope you're as excited for this release as we are. Keep an eye out for the official release
blog in a few weeks for more highlights!

View File

@ -115,9 +115,9 @@ are enabled, kubelets are only authorized to create/modify their own Node resour
{{< note >}}
As mentioned in the [Node name uniqueness](#node-name-uniqueness) section,
when Node configuration needs to be updated, it is a good practice to re-register
the node with the API server. For example, if the kubelet being restarted with
the new set of `--node-labels`, but the same Node name is used, the change will
not take an effect, as labels are being set on the Node registration.
the node with the API server. For example, if the kubelet is being restarted with
a new set of `--node-labels`, but the same Node name is used, the change will
not take effect, as labels are only set (or modified) upon Node registration with the API server.
Pods already scheduled on the Node may misbehave or cause issues if the Node
configuration will be changed on kubelet restart. For example, already running

View File

@ -82,7 +82,7 @@ installation instructions. The list does not try to be exhaustive.
* [Spiderpool](https://github.com/spidernet-io/spiderpool) is an underlay and RDMA
networking solution for Kubernetes. Spiderpool is supported on bare metal, virtual machines,
and public cloud environments.
* [Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/)
* [Weave Net](https://github.com/rajch/weave#using-weave-on-kubernetes)
provides networking and network policy, will carry on working on both sides
of a network partition, and does not require an external database.

View File

@ -97,15 +97,13 @@ The usual way to access this is by running `kubectl logs`.
{{< feature-state for_k8s_version="v1.21" state="stable" >}}
You can configure the kubelet to rotate logs automatically.
If you configure rotation, the kubelet is responsible for rotating container logs and managing the
The kubelet is responsible for rotating container logs and managing the
logging directory structure.
The kubelet sends this information to the container runtime (using CRI),
and the runtime writes the container logs to the given location.
You can configure two kubelet [configuration settings](/docs/reference/config-api/kubelet-config.v1beta1/),
`containerLogMaxSize` and `containerLogMaxFiles`,
`containerLogMaxSize` (default 10Mi) and `containerLogMaxFiles` (default 5),
using the [kubelet configuration file](/docs/tasks/administer-cluster/kubelet-config-file/).
These settings let you configure the maximum size for each log file and the maximum number of
files allowed for each container respectively.

View File

@ -11,11 +11,11 @@ using a client of the {{<glossary_tooltip term_id="kube-apiserver" text="API ser
creates an `Eviction` object, which causes the API server to terminate the Pod.
API-initiated evictions respect your configured [`PodDisruptionBudgets`](/docs/tasks/run-application/configure-pdb/)
and [`terminationGracePeriodSeconds`](/docs/concepts/workloads/pods/pod-lifecycle#pod-termination).
and [`terminationGracePeriodSeconds`](/docs/concepts/workloads/pods/pod-lifecycle#pod-termination).
Using the API to create an Eviction object for a Pod is like performing a
policy-controlled [`DELETE` operation](/docs/reference/kubernetes-api/workload-resources/pod-v1/#delete-delete-a-pod)
on the Pod.
on the Pod.
## Calling the Eviction API
@ -75,13 +75,13 @@ checks and responds in one of the following ways:
* `429 Too Many Requests`: the eviction is not currently allowed because of the
configured {{<glossary_tooltip term_id="pod-disruption-budget" text="PodDisruptionBudget">}}.
You may be able to attempt the eviction again later. You might also see this
response because of API rate limiting.
response because of API rate limiting.
* `500 Internal Server Error`: the eviction is not allowed because there is a
misconfiguration, like if multiple PodDisruptionBudgets reference the same Pod.
If the Pod you want to evict isn't part of a workload that has a
PodDisruptionBudget, the API server always returns `200 OK` and allows the
eviction.
eviction.
If the API server allows the eviction, the Pod is deleted as follows:
@ -103,12 +103,12 @@ If the API server allows the eviction, the Pod is deleted as follows:
## Troubleshooting stuck evictions
In some cases, your applications may enter a broken state, where the Eviction
API will only return `429` or `500` responses until you intervene. This can
happen if, for example, a ReplicaSet creates pods for your application but new
API will only return `429` or `500` responses until you intervene. This can
happen if, for example, a ReplicaSet creates pods for your application but new
pods do not enter a `Ready` state. You may also notice this behavior in cases
where the last evicted Pod had a long termination grace period.
If you notice stuck evictions, try one of the following solutions:
If you notice stuck evictions, try one of the following solutions:
* Abort or pause the automated operation causing the issue. Investigate the stuck
application before you restart the operation.

View File

@ -96,7 +96,7 @@ define. Some of the benefits of affinity and anti-affinity include:
The affinity feature consists of two types of affinity:
- *Node affinity* functions like the `nodeSelector` field but is more expressive and
allows you to specify soft rules.
allows you to specify soft rules.
- *Inter-pod affinity/anti-affinity* allows you to constrain Pods against labels
on other Pods.
@ -254,13 +254,13 @@ the node label that the system uses to denote the domain. For examples, see
[Well-Known Labels, Annotations and Taints](/docs/reference/labels-annotations-taints/).
{{< note >}}
Inter-pod affinity and anti-affinity require substantial amount of
Inter-pod affinity and anti-affinity require substantial amounts of
processing which can slow down scheduling in large clusters significantly. We do
not recommend using them in clusters larger than several hundred nodes.
{{< /note >}}
{{< note >}}
Pod anti-affinity requires nodes to be consistently labelled, in other words,
Pod anti-affinity requires nodes to be consistently labeled, in other words,
every node in the cluster must have an appropriate label matching `topologyKey`.
If some or all nodes are missing the specified `topologyKey` label, it can lead
to unintended behavior.
@ -305,22 +305,22 @@ Pod affinity rule uses the "hard"
`requiredDuringSchedulingIgnoredDuringExecution`, while the anti-affinity rule
uses the "soft" `preferredDuringSchedulingIgnoredDuringExecution`.
The affinity rule specifies that the scheduler is allowed to place the example Pod
The affinity rule specifies that the scheduler is allowed to place the example Pod
on a node only if that node belongs to a specific [zone](/docs/concepts/scheduling-eviction/topology-spread-constraints/)
where other Pods have been labeled with `security=S1`.
For instance, if we have a cluster with a designated zone, let's call it "Zone V,"
consisting of nodes labeled with `topology.kubernetes.io/zone=V`, the scheduler can
assign the Pod to any node within Zone V, as long as there is at least one Pod within
Zone V already labeled with `security=S1`. Conversely, if there are no Pods with `security=S1`
where other Pods have been labeled with `security=S1`.
For instance, if we have a cluster with a designated zone, let's call it "Zone V,"
consisting of nodes labeled with `topology.kubernetes.io/zone=V`, the scheduler can
assign the Pod to any node within Zone V, as long as there is at least one Pod within
Zone V already labeled with `security=S1`. Conversely, if there are no Pods with `security=S1`
labels in Zone V, the scheduler will not assign the example Pod to any node in that zone.
The anti-affinity rule specifies that the scheduler should try to avoid scheduling the Pod
The anti-affinity rule specifies that the scheduler should try to avoid scheduling the Pod
on a node if that node belongs to a specific [zone](/docs/concepts/scheduling-eviction/topology-spread-constraints/)
where other Pods have been labeled with `security=S2`.
For instance, if we have a cluster with a designated zone, let's call it "Zone R,"
consisting of nodes labeled with `topology.kubernetes.io/zone=R`, the scheduler should avoid
assigning the Pod to any node within Zone R, as long as there is at least one Pod within
Zone R already labeled with `security=S2`. Conversely, the anti-affinity rule does not impact
where other Pods have been labeled with `security=S2`.
For instance, if we have a cluster with a designated zone, let's call it "Zone R,"
consisting of nodes labeled with `topology.kubernetes.io/zone=R`, the scheduler should avoid
assigning the Pod to any node within Zone R, as long as there is at least one Pod within
Zone R already labeled with `security=S2`. Conversely, the anti-affinity rule does not impact
scheduling into Zone R if there are no Pods with `security=S2` labels.
To get yourself more familiar with the examples of Pod affinity and anti-affinity,
@ -364,19 +364,19 @@ null `namespaceSelector` matches the namespace of the Pod where the rule is defi
{{< note >}}
<!-- UPDATE THIS WHEN PROMOTING TO BETA -->
The `matchLabelKeys` field is a alpha-level field and is disabled by default in
The `matchLabelKeys` field is an alpha-level field and is disabled by default in
Kubernetes {{< skew currentVersion >}}.
When you want to use it, you have to enable it via the
`MatchLabelKeysInPodAffinity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/).
{{< /note >}}
Kubernetes includes an optional `matchLabelKeys` field for Pod affinity
or anti-affinity. The field specifies keys for the labels that should match with the incoming Pod's labels,
or anti-affinity. The field specifies keys for the labels that should match with the incoming Pod's labels,
when satisfying the Pod (anti)affinity.
The keys are used to look up values from the pod labels; those key-value labels are combined
(using `AND`) with the match restrictions defined using the `labelSelector` field. The combined
filtering selects the set of existing pods that will be taken into Pod (anti)affinity calculation.
filtering selects the set of existing pods that will be taken into Pod (anti)affinity calculation.
A common use case is to use `matchLabelKeys` with `pod-template-hash` (set on Pods
managed as part of a Deployment, where the value is unique for each revision).
@ -405,7 +405,7 @@ spec:
# Only Pods from a given rollout are taken into consideration when calculating pod affinity.
# If you update the Deployment, the replacement Pods follow their own affinity rules
# (if there are any defined in the new Pod template)
matchLabelKeys:
matchLabelKeys:
- pod-template-hash
```
@ -415,14 +415,14 @@ spec:
{{< note >}}
<!-- UPDATE THIS WHEN PROMOTING TO BETA -->
The `mismatchLabelKeys` field is a alpha-level field and is disabled by default in
The `mismatchLabelKeys` field is an alpha-level field and is disabled by default in
Kubernetes {{< skew currentVersion >}}.
When you want to use it, you have to enable it via the
`MatchLabelKeysInPodAffinity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/).
{{< /note >}}
Kubernetes includes an optional `mismatchLabelKeys` field for Pod affinity
or anti-affinity. The field specifies keys for the labels that should **not** match with the incoming Pod's labels,
or anti-affinity. The field specifies keys for the labels that should **not** match with the incoming Pod's labels,
when satisfying the Pod (anti)affinity.
One example use case is to ensure Pods go to the topology domain (node, zone, etc) where only Pods from the same tenant or team are scheduled in.
@ -438,22 +438,22 @@ metadata:
...
spec:
affinity:
podAffinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# ensure that pods associated with this tenant land on the correct node pool
- matchLabelKeys:
- tenant
topologyKey: node-pool
podAntiAffinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# ensure that pods associated with this tenant can't schedule to nodes used for another tenant
- mismatchLabelKeys:
- tenant # whatever the value of the "tenant" label for this Pod, prevent
- tenant # whatever the value of the "tenant" label for this Pod, prevent
# scheduling to nodes in any pool where any Pod from a different
# tenant is running.
labelSelector:
# We have to have the labelSelector which selects only Pods with the tenant label,
# otherwise this Pod would hate Pods from daemonsets as well, for example,
# otherwise this Pod would hate Pods from daemonsets as well, for example,
# which aren't supposed to have the tenant label.
matchExpressions:
- key: tenant
@ -561,7 +561,7 @@ where each web server is co-located with a cache, on three separate nodes.
| *webserver-1* | *webserver-2* | *webserver-3* |
| *cache-1* | *cache-2* | *cache-3* |
The overall effect is that each cache instance is likely to be accessed by a single client, that
The overall effect is that each cache instance is likely to be accessed by a single client that
is running on the same node. This approach aims to minimize both skew (imbalanced load) and latency.
You might have other reasons to use Pod anti-affinity.
@ -589,7 +589,7 @@ Some of the limitations of using `nodeName` to select nodes are:
{{< note >}}
`nodeName` is intended for use by custom schedulers or advanced use cases where
you need to bypass any configured schedulers. Bypassing the schedulers might lead to
failed Pods if the assigned Nodes get oversubscribed. You can use [node affinity](#node-affinity) or a the [`nodeselector` field](#nodeselector) to assign a Pod to a specific Node without bypassing the schedulers.
failed Pods if the assigned Nodes get oversubscribed. You can use the [node affinity](#node-affinity) or the [`nodeselector` field](#nodeselector) to assign a Pod to a specific Node without bypassing the schedulers.
{{</ note >}}
Here is an example of a Pod spec using the `nodeName` field:
@ -633,13 +633,13 @@ The following operators can only be used with `nodeAffinity`.
| Operator | Behaviour |
| :------------: | :-------------: |
| `Gt` | The supplied value will be parsed as an integer, and that integer is less than the integer that results from parsing the value of a label named by this selector |
| `Lt` | The supplied value will be parsed as an integer, and that integer is greater than the integer that results from parsing the value of a label named by this selector |
| `Gt` | The supplied value will be parsed as an integer, and that integer is less than the integer that results from parsing the value of a label named by this selector |
| `Lt` | The supplied value will be parsed as an integer, and that integer is greater than the integer that results from parsing the value of a label named by this selector |
{{<note>}}
`Gt` and `Lt` operators will not work with non-integer values. If the given value
doesn't parse as an integer, the pod will fail to get scheduled. Also, `Gt` and `Lt`
`Gt` and `Lt` operators will not work with non-integer values. If the given value
doesn't parse as an integer, the pod will fail to get scheduled. Also, `Gt` and `Lt`
are not available for `podAffinity`.
{{</note>}}

View File

@ -41,14 +41,14 @@ ResourceClass
driver.
ResourceClaim
: Defines a particular resource instances that is required by a
: Defines a particular resource instance that is required by a
workload. Created by a user (lifecycle managed manually, can be shared
between different Pods) or for individual Pods by the control plane based on
a ResourceClaimTemplate (automatic lifecycle, typically used by just one
Pod).
ResourceClaimTemplate
: Defines the spec and some meta data for creating
: Defines the spec and some metadata for creating
ResourceClaims. Created by a user when deploying a workload.
PodSchedulingContext

View File

@ -62,7 +62,7 @@ kube-scheduler selects a node for the pod in a 2-step operation:
The _filtering_ step finds the set of Nodes where it's feasible to
schedule the Pod. For example, the PodFitsResources filter checks whether a
candidate Node has enough available resource to meet a Pod's specific
candidate Node has enough available resources to meet a Pod's specific
resource requests. After this step, the node list contains any suitable
Nodes; often, there will be more than one. If the list is empty, that
Pod isn't (yet) schedulable.

View File

@ -171,7 +171,7 @@ The kubelet has the following default hard eviction thresholds:
- `nodefs.inodesFree<5%` (Linux nodes)
These default values of hard eviction thresholds will only be set if none
of the parameters is changed. If you changed the value of any parameter,
of the parameters is changed. If you change the value of any parameter,
then the values of other parameters will not be inherited as the default
values and will be set to zero. In order to provide custom values, you
should provide all the thresholds respectively.

View File

@ -64,7 +64,7 @@ and it cannot be prefixed with `system-`.
A PriorityClass object can have any 32-bit integer value smaller than or equal
to 1 billion. This means that the range of values for a PriorityClass object is
from -2147483648 to 1000000000 inclusive. Larger numbers are reserved for
from -2147483648 to 1000000000 inclusive. Larger numbers are reserved for
built-in PriorityClasses that represent critical system Pods. A cluster
admin should create one PriorityClass object for each such mapping that they want.
@ -182,8 +182,8 @@ When Pod priority is enabled, the scheduler orders pending Pods by
their priority and a pending Pod is placed ahead of other pending Pods
with lower priority in the scheduling queue. As a result, the higher
priority Pod may be scheduled sooner than Pods with lower priority if
its scheduling requirements are met. If such Pod cannot be scheduled,
scheduler will continue and tries to schedule other lower priority Pods.
its scheduling requirements are met. If such Pod cannot be scheduled, the
scheduler will continue and try to schedule other lower priority Pods.
## Preemption
@ -199,7 +199,7 @@ the Pods are gone, P can be scheduled on the Node.
### User exposed information
When Pod P preempts one or more Pods on Node N, `nominatedNodeName` field of Pod
P's status is set to the name of Node N. This field helps scheduler track
P's status is set to the name of Node N. This field helps the scheduler track
resources reserved for Pod P and also gives users information about preemptions
in their clusters.
@ -209,8 +209,8 @@ After victim Pods are preempted, they get their graceful termination period. If
another node becomes available while scheduler is waiting for the victim Pods to
terminate, scheduler may use the other node to schedule Pod P. As a result
`nominatedNodeName` and `nodeName` of Pod spec are not always the same. Also, if
scheduler preempts Pods on Node N, but then a higher priority Pod than Pod P
arrives, scheduler may give Node N to the new higher priority Pod. In such a
the scheduler preempts Pods on Node N, but then a higher priority Pod than Pod P
arrives, the scheduler may give Node N to the new higher priority Pod. In such a
case, scheduler clears `nominatedNodeName` of Pod P. By doing this, scheduler
makes Pod P eligible to preempt Pods on another Node.
@ -256,9 +256,9 @@ the Node is not considered for preemption.
If a pending Pod has inter-pod {{< glossary_tooltip text="affinity" term_id="affinity" >}}
to one or more of the lower-priority Pods on the Node, the inter-Pod affinity
rule cannot be satisfied in the absence of those lower-priority Pods. In this case,
rule cannot be satisfied in the absence of those lower-priority Pods. In this case,
the scheduler does not preempt any Pods on the Node. Instead, it looks for another
Node. The scheduler might find a suitable Node or it might not. There is no
Node. The scheduler might find a suitable Node or it might not. There is no
guarantee that the pending Pod can be scheduled.
Our recommended solution for this problem is to create inter-Pod affinity only
@ -288,7 +288,7 @@ enough demand and if we find an algorithm with reasonable performance.
## Troubleshooting
Pod priority and pre-emption can have unwanted side effects. Here are some
Pod priority and preemption can have unwanted side effects. Here are some
examples of potential problems and ways to deal with them.
### Pods are preempted unnecessarily
@ -361,7 +361,7 @@ to get evicted. The kubelet ranks pods for eviction based on the following facto
1. Whether the starved resource usage exceeds requests
1. Pod Priority
1. Amount of resource usage relative to requests
1. Amount of resource usage relative to requests
See [Pod selection for kubelet eviction](/docs/concepts/scheduling-eviction/node-pressure-eviction/#pod-selection-for-kubelet-eviction)
for more details.

View File

@ -9,7 +9,7 @@ weight: 40
{{< feature-state for_k8s_version="v1.30" state="stable" >}}
Pods were considered ready for scheduling once created. Kubernetes scheduler
does its due diligence to find nodes to place all pending Pods. However, in a
does its due diligence to find nodes to place all pending Pods. However, in a
real-world case, some Pods may stay in a "miss-essential-resources" state for a long period.
These Pods actually churn the scheduler (and downstream integrators like Cluster AutoScaler)
in an unnecessary manner.
@ -59,7 +59,7 @@ The output is:
```
To inform scheduler this Pod is ready for scheduling, you can remove its `schedulingGates` entirely
by re-applying a modified manifest:
by reapplying a modified manifest:
{{% code_sample file="pods/pod-without-scheduling-gates.yaml" %}}
@ -79,7 +79,7 @@ Given the test-pod doesn't request any CPU/memory resources, it's expected that
transited from previous `SchedulingGated` to `Running`:
```none
NAME READY STATUS RESTARTS AGE IP NODE
NAME READY STATUS RESTARTS AGE IP NODE
test-pod 1/1 Running 0 15s 10.0.0.4 node-2
```
@ -92,8 +92,8 @@ scheduling. You can use `scheduler_pending_pods{queue="gated"}` to check the met
## Mutable Pod scheduling directives
You can mutate scheduling directives of Pods while they have scheduling gates, with certain constraints.
At a high level, you can only tighten the scheduling directives of a Pod. In other words, the updated
directives would cause the Pods to only be able to be scheduled on a subset of the nodes that it would
At a high level, you can only tighten the scheduling directives of a Pod. In other words, the updated
directives would cause the Pods to only be able to be scheduled on a subset of the nodes that it would
previously match. More concretely, the rules for updating a Pod's scheduling directives are as follows:
1. For `.spec.nodeSelector`, only additions are allowed. If absent, it will be allowed to be set.
@ -105,8 +105,8 @@ previously match. More concretely, the rules for updating a Pod's scheduling dir
or `fieldExpressions` are allowed, and no changes to existing `matchExpressions`
and `fieldExpressions` will be allowed. This is because the terms in
`.requiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms`, are ORed
while the expressions in `nodeSelectorTerms[].matchExpressions` and
`nodeSelectorTerms[].fieldExpressions` are ANDed.
while the expressions in `nodeSelectorTerms[].matchExpressions` and
`nodeSelectorTerms[].fieldExpressions` are ANDed.
4. For `.preferredDuringSchedulingIgnoredDuringExecution`, all updates are allowed.
This is because preferred terms are not authoritative, and so policy controllers

View File

@ -58,8 +58,8 @@ Within the `scoringStrategy` field, you can configure two parameters: `requested
`resources`. The `shape` in the `requestedToCapacityRatio`
parameter allows the user to tune the function as least requested or most
requested based on `utilization` and `score` values. The `resources` parameter
consists of `name` of the resource to be considered during scoring and `weight`
specify the weight of each resource.
comprises both the `name` of the resource to be considered during scoring and
its corresponding `weight`, which specifies the weight of each resource.
Below is an example configuration that sets
the bin packing behavior for extended resources `intel.com/foo` and `intel.com/bar`

View File

@ -77,7 +77,7 @@ If you don't specify a threshold, Kubernetes calculates a figure using a
linear formula that yields 50% for a 100-node cluster and yields 10%
for a 5000-node cluster. The lower bound for the automatic value is 5%.
This means that, the kube-scheduler always scores at least 5% of your cluster no
This means that the kube-scheduler always scores at least 5% of your cluster no
matter how large the cluster is, unless you have explicitly set
`percentageOfNodesToScore` to be smaller than 5.

View File

@ -83,7 +83,7 @@ the Pod is put into the active queue or the backoff queue
so that the scheduler will retry the scheduling of the Pod.
{{< note >}}
QueueingHint evaluation during scheduling is a beta-level feature.
QueueingHint evaluation during scheduling is a beta-level feature.
The v1.28 release series initially enabled the associated feature gate; however, after the
discovery of an excessive memory footprint, the Kubernetes project set that feature gate
to be disabled by default. In Kubernetes {{< skew currentVersion >}}, this feature gate is
@ -113,7 +113,7 @@ called for that node. Nodes may be evaluated concurrently.
### PostFilter {#post-filter}
These plugins are called after Filter phase, but only when no feasible nodes
These plugins are called after the Filter phase, but only when no feasible nodes
were found for the pod. Plugins are called in their configured order. If
any postFilter plugin marks the node as `Schedulable`, the remaining plugins
will not be called. A typical PostFilter implementation is preemption, which

View File

@ -84,7 +84,7 @@ An empty `effect` matches all effects with key `key1`.
{{< /note >}}
The above example used `effect` of `NoSchedule`. Alternatively, you can use `effect` of `PreferNoSchedule`.
The above example used the `effect` of `NoSchedule`. Alternatively, you can use the `effect` of `PreferNoSchedule`.
The allowed values for the `effect` field are:
@ -227,7 +227,7 @@ are true. The following taints are built in:
* `node.kubernetes.io/network-unavailable`: Node's network is unavailable.
* `node.kubernetes.io/unschedulable`: Node is unschedulable.
* `node.cloudprovider.kubernetes.io/uninitialized`: When the kubelet is started
with "external" cloud provider, this taint is set on a node to mark it
with an "external" cloud provider, this taint is set on a node to mark it
as unusable. After a controller from the cloud-controller-manager initializes
this node, the kubelet removes this taint.

View File

@ -71,7 +71,7 @@ spec:
```
You can read more about this field by running `kubectl explain Pod.spec.topologySpreadConstraints` or
refer to [scheduling](/docs/reference/kubernetes-api/workload-resources/pod-v1/#scheduling) section of the API reference for Pod.
refer to the [scheduling](/docs/reference/kubernetes-api/workload-resources/pod-v1/#scheduling) section of the API reference for Pod.
### Spread constraint definition
@ -254,7 +254,7 @@ follows the API definition of the field; however, the behavior is more likely to
confusing and troubleshooting is less straightforward.
You need a mechanism to ensure that all the nodes in a topology domain (such as a
cloud provider region) are labelled consistently.
cloud provider region) are labeled consistently.
To avoid you needing to manually label nodes, most clusters automatically
populate well-known labels such as `kubernetes.io/hostname`. Check whether
your cluster supports this.
@ -263,7 +263,7 @@ your cluster supports this.
### Example: one topology spread constraint {#example-one-topologyspreadconstraint}
Suppose you have a 4-node cluster where 3 Pods labelled `foo: bar` are located in
Suppose you have a 4-node cluster where 3 Pods labeled `foo: bar` are located in
node1, node2 and node3 respectively:
{{<mermaid>}}
@ -290,7 +290,7 @@ can use a manifest similar to:
{{% code_sample file="pods/topology-spread-constraints/one-constraint.yaml" %}}
From that manifest, `topologyKey: zone` implies the even distribution will only be applied
to nodes that are labelled `zone: <any value>` (nodes that don't have a `zone` label
to nodes that are labeled `zone: <any value>` (nodes that don't have a `zone` label
are skipped). The field `whenUnsatisfiable: DoNotSchedule` tells the scheduler to let the
incoming Pod stay pending if the scheduler can't find a way to satisfy the constraint.
@ -494,7 +494,7 @@ There are some implicit conventions worth noting here:
above example, if you remove the incoming Pod's labels, it can still be placed onto
nodes in zone `B`, since the constraints are still satisfied. However, after that
placement, the degree of imbalance of the cluster remains unchanged - it's still zone `A`
having 2 Pods labelled as `foo: bar`, and zone `B` having 1 Pod labelled as
having 2 Pods labeled as `foo: bar`, and zone `B` having 1 Pod labeled as
`foo: bar`. If this is not what you expect, update the workload's
`topologySpreadConstraints[*].labelSelector` to match the labels in the pod template.
@ -618,7 +618,7 @@ section of the enhancement proposal about Pod topology spread constraints.
because, in this case, those topology domains won't be considered until there is
at least one node in them.
You can work around this by using an cluster autoscaling tool that is aware of
You can work around this by using a cluster autoscaling tool that is aware of
Pod topology spread constraints and is also aware of the overall set of topology
domains.

View File

@ -291,7 +291,7 @@ sandboxing implementations are available:
* [gVisor](https://gvisor.dev/) intercepts syscalls from containers and runs them through a
userspace kernel, written in Go, with limited access to the underlying host.
* [Kata Containers](https://katacontainers.io/) is an OCI compliant runtime that allows you to run
* [Kata Containers](https://katacontainers.io/) provide a secure container runtime that allows you to run
containers in a VM. The hardware virtualization available in Kata offers an added layer of
security for containers running untrusted code.

View File

@ -38,7 +38,7 @@ Kubernetes also supports _automatic scaling_ of workloads, which is the focus of
The concept of _Autoscaling_ in Kubernetes refers to the ability to automatically update an
object that manages a set of Pods (for example a
{{< glossary_tooltip text="Deployment" term_id="deployment" >}}.
{{< glossary_tooltip text="Deployment" term_id="deployment" >}}).
### Scaling workloads horizontally
@ -55,7 +55,7 @@ There is a [walkthrough tutorial](/docs/tasks/run-application/horizontal-pod-aut
{{< feature-state for_k8s_version="v1.25" state="stable" >}}
You can automatically scale a workload vertically using a _VerticalPodAutoscaler_ (VPA).
Different to the HPA, the VPA doesn't come with Kubernetes by default, but is a separate project
Unlike the HPA, the VPA doesn't come with Kubernetes by default, but is a separate project
that can be found [on GitHub](https://github.com/kubernetes/autoscaler/tree/9f87b78df0f1d6e142234bb32e8acbd71295585a/vertical-pod-autoscaler).
Once installed, it allows you to create {{< glossary_tooltip text="CustomResourceDefinitions" term_id="customresourcedefinition" >}}
@ -71,7 +71,7 @@ At the moment, the VPA can operate in four different modes:
{{< table caption="Different modes of the VPA" >}}
Mode | Description
:----|:-----------
`Auto` | Currently `Recreate`, might change to in-place updates in the future
`Auto` | Currently, `Recreate` might change to in-place updates in the future
`Recreate` | The VPA assigns resource requests on pod creation as well as updates them on existing pods by evicting them when the requested resources differ significantly from the new recommendation
`Initial` | The VPA only assigns resource requests on pod creation and never changes them later.
`Off` | The VPA does not automatically change the resource requirements of the pods. The recommendations are calculated and can be inspected in the VPA object.
@ -82,7 +82,7 @@ Mode | Description
{{< feature-state for_k8s_version="v1.27" state="alpha" >}}
Resizing a workload in-place **without** restarting the {{< glossary_tooltip text="Pods" term_id="pod" >}}
or its {{< glossary_tooltip text="Containers" term_id="container" >}} requires Kubernetes version 1.27 or later.<br />
or its {{< glossary_tooltip text="Containers" term_id="container" >}} requires Kubernetes version 1.27 or later.
Additionally, the `InPlaceVerticalScaling` feature gate needs to be enabled.
{{< feature-gate-description name="InPlacePodVerticalScaling" >}}
@ -91,7 +91,7 @@ Additionally, the `InPlaceVerticalScaling` feature gate needs to be enabled.
For workloads that need to be scaled based on the size of the cluster (for example
`cluster-dns` or other system components), you can use the
[_Cluster Proportional Autoscaler_](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler).<br />
[_Cluster Proportional Autoscaler_](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler).
Just like the VPA, it is not part of the Kubernetes core, but hosted as its
own project on GitHub.

View File

@ -92,15 +92,14 @@ Namespace: default
Selector: tier=frontend
Labels: app=guestbook
tier=frontend
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1","kind":"ReplicaSet","metadata":{"annotations":{},"labels":{"app":"guestbook","tier":"frontend"},"name":"frontend",...
Annotations: <none>
Replicas: 3 current / 3 desired
Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed
Pod Template:
Labels: tier=frontend
Containers:
php-redis:
Image: gcr.io/google_samples/gb-frontend:v3
Image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
Port: <none>
Host Port: <none>
Environment: <none>
@ -109,9 +108,9 @@ Pod Template:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 117s replicaset-controller Created pod: frontend-wtsmm
Normal SuccessfulCreate 116s replicaset-controller Created pod: frontend-b2zdv
Normal SuccessfulCreate 116s replicaset-controller Created pod: frontend-vcmts
Normal SuccessfulCreate 13s replicaset-controller Created pod: frontend-gbgfx
Normal SuccessfulCreate 13s replicaset-controller Created pod: frontend-rwz57
Normal SuccessfulCreate 13s replicaset-controller Created pod: frontend-wkl7w
```
And lastly you can check for the Pods brought up:
@ -124,16 +123,16 @@ You should see Pod information similar to:
```
NAME READY STATUS RESTARTS AGE
frontend-b2zdv 1/1 Running 0 6m36s
frontend-vcmts 1/1 Running 0 6m36s
frontend-wtsmm 1/1 Running 0 6m36s
frontend-gbgfx 1/1 Running 0 10m
frontend-rwz57 1/1 Running 0 10m
frontend-wkl7w 1/1 Running 0 10m
```
You can also verify that the owner reference of these pods is set to the frontend ReplicaSet.
To do this, get the yaml of one of the Pods running:
```shell
kubectl get pods frontend-b2zdv -o yaml
kubectl get pods frontend-gbgfx -o yaml
```
The output will look similar to this, with the frontend ReplicaSet's info set in the metadata's ownerReferences field:
@ -142,11 +141,11 @@ The output will look similar to this, with the frontend ReplicaSet's info set in
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2020-02-12T07:06:16Z"
creationTimestamp: "2024-02-28T22:30:44Z"
generateName: frontend-
labels:
tier: frontend
name: frontend-b2zdv
name: frontend-gbgfx
namespace: default
ownerReferences:
- apiVersion: apps/v1
@ -154,7 +153,7 @@ metadata:
controller: true
kind: ReplicaSet
name: frontend
uid: f391f6db-bb9b-4c09-ae74-6a1f77f3d5cf
uid: e129deca-f864-481b-bb16-b27abfd92292
...
```

View File

@ -1,5 +1,5 @@
---
title: Managing Resources
title: Managing Workloads
content_type: concept
reviewers:
- janetkuo
@ -8,14 +8,14 @@ weight: 40
<!-- overview -->
You've deployed your application and exposed it via a service. Now what? Kubernetes provides a
You've deployed your application and exposed it via a Service. Now what? Kubernetes provides a
number of tools to help you manage your application deployment, including scaling and updating.
<!-- body -->
## Organizing resource configurations
Many applications require multiple resources to be created, such as a Deployment and a Service.
Many applications require multiple resources to be created, such as a Deployment along with a Service.
Management of multiple resources can be simplified by grouping them together in the same file
(separated by `---` in YAML). For example:
@ -32,9 +32,9 @@ service/my-nginx-svc created
deployment.apps/my-nginx created
```
The resources will be created in the order they appear in the file. Therefore, it's best to
specify the service first, since that will ensure the scheduler can spread the pods associated
with the service as they are created by the controller(s), such as Deployment.
The resources will be created in the order they appear in the manifest. Therefore, it's best to
specify the Service first, since that will ensure the scheduler can spread the pods associated
with the Service as they are created by the controller(s), such as Deployment.
`kubectl apply` also accepts multiple `-f` arguments:
@ -50,7 +50,7 @@ directory. If the tiers of your application bind to each other using DNS, you ca
the components of your stack together.
A URL can also be specified as a configuration source, which is handy for deploying directly from
configuration files checked into GitHub:
manifests in your source control system:
```shell
kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
@ -60,6 +60,27 @@ kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx created
```
If you need to define more manifests, such as adding a ConfigMap, you can do that too.
### External tools
This section lists only the most common tools used for managing workloads on Kubernetes. To see a larger list, view
[Application definition and image build](https://landscape.cncf.io/guide#app-definition-and-development--application-definition-image-build)
in the {{< glossary_tooltip text="CNCF" term_id="cncf" >}} Landscape.
#### Helm {#external-tool-helm}
{{% thirdparty-content single="true" %}}
[Helm](https://helm.sh/) is a tool for managing packages of pre-configured
Kubernetes resources. These packages are known as _Helm charts_.
#### Kustomize {#external-tool-kustomize}
[Kustomize](https://kustomize.io/) traverses a Kubernetes manifest to add, remove or update configuration options.
It is available both as a standalone binary and as a [native feature](/docs/tasks/manage-kubernetes-objects/kustomization/)
of kubectl.
## Bulk operations in kubectl
Resource creation isn't the only operation that `kubectl` can perform in bulk. It can also extract
@ -94,26 +115,32 @@ deployment.apps "my-nginx" deleted
service "my-nginx-svc" deleted
```
### Chaining and filtering
Because `kubectl` outputs resource names in the same syntax it accepts, you can chain operations
using `$()` or `xargs`:
```shell
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service)
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service | xargs -i kubectl get {}
kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/ )
kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/ | xargs -i kubectl get '{}'
```
The output might be similar to:
```none
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
my-nginx-svc LoadBalancer 10.0.0.208 <pending> 80/TCP 0s
```
With the above commands, we first create resources under `examples/application/nginx/` and print
With the above commands, first you create resources under `examples/application/nginx/` and print
the resources created with `-o name` output format (print each resource as resource/name).
Then we `grep` only the "service", and then print it with `kubectl get`.
Then you `grep` only the Service, and then print it with [`kubectl get`](/docs/reference/kubectl/generated/kubectl_get/).
### Recursive operations on local files
If you happen to organize your resources across several subdirectories within a particular
directory, you can recursively perform the operations on the subdirectories also, by specifying
`--recursive` or `-R` alongside the `--filename,-f` flag.
`--recursive` or `-R` alongside the `--filename`/`-f` argument.
For instance, assume there is a directory `project/k8s/development` that holds all of the
{{< glossary_tooltip text="manifests" term_id="manifest" >}} needed for the development environment,
@ -130,7 +157,7 @@ project/k8s/development
```
By default, performing a bulk operation on `project/k8s/development` will stop at the first level
of the directory, not processing any subdirectories. If we had tried to create the resources in
of the directory, not processing any subdirectories. If you had tried to create the resources in
this directory using the following command, we would have encountered an error:
```shell
@ -141,7 +168,7 @@ kubectl apply -f project/k8s/development
error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin)
```
Instead, specify the `--recursive` or `-R` flag with the `--filename,-f` flag as such:
Instead, specify the `--recursive` or `-R` command line argument along with the `--filename`/`-f` argument:
```shell
kubectl apply -f project/k8s/development --recursive
@ -153,10 +180,10 @@ deployment.apps/my-deployment created
persistentvolumeclaim/my-pvc created
```
The `--recursive` flag works with any operation that accepts the `--filename,-f` flag such as:
`kubectl {create,get,delete,describe,rollout}` etc.
The `--recursive` argument works with any operation that accepts the `--filename`/`-f` argument such as:
`kubectl create`, `kubectl get`, `kubectl delete`, `kubectl describe`, or even `kubectl rollout`.
The `--recursive` flag also works when multiple `-f` arguments are provided:
The `--recursive` argument also works when multiple `-f` arguments are provided:
```shell
kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive
@ -173,6 +200,90 @@ persistentvolumeclaim/my-pvc created
If you're interested in learning more about `kubectl`, go ahead and read
[Command line tool (kubectl)](/docs/reference/kubectl/).
## Updating your application without an outage
At some point, you'll eventually need to update your deployed application, typically by specifying
a new image or image tag. `kubectl` supports several update operations, each of which is applicable
to different scenarios.
You can run multiple copies of your app, and use a _rollout_ to gradually shift the traffic to
new healthy Pods. Eventually, all the running Pods would have the new software.
This section of the page guides you through how to create and update applications with Deployments.
Let's say you were running version 1.14.2 of nginx:
```shell
kubectl create deployment my-nginx --image=nginx:1.14.2
```
```none
deployment.apps/my-nginx created
```
Ensure that there is 1 replica:
```shell
kubectl scale --replicas 1 deployments/my-nginx --subresource='scale' --type='merge' -p '{"spec":{"replicas": 1}}'
```
```none
deployment.apps/my-nginx scaled
```
and allow Kubernetes to add more temporary replicas during a rollout, by setting a _surge maximum_ of
100%:
```shell
kubectl patch --type='merge' -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge": "100%" }}}}'
```
```none
deployment.apps/my-nginx patched
```
To update to version 1.16.1, change `.spec.template.spec.containers[0].image` from `nginx:1.14.2`
to `nginx:1.16.1` using `kubectl edit`:
```shell
kubectl edit deployment/my-nginx
# Change the manifest to use the newer container image, then save your changes
```
That's it! The Deployment will declaratively update the deployed nginx application progressively
behind the scene. It ensures that only a certain number of old replicas may be down while they are
being updated, and only a certain number of new replicas may be created above the desired number
of pods. To learn more details about how this happens,
visit [Deployment](/docs/concepts/workloads/controllers/deployment/).
You can use rollouts with DaemonSets, Deployments, or StatefulSets.
### Managing rollouts
You can use [`kubectl rollout`](/docs/reference/kubectl/generated/kubectl_rollout/) to manage a
progressive update of an existing application.
For example:
```shell
kubectl apply -f my-deployment.yaml
# wait for rollout to finish
kubectl rollout status deployment/my-deployment --timeout 10m # 10 minute timeout
```
or
```shell
kubectl apply -f backing-stateful-component.yaml
# don't wait for rollout to finish, just check the status
kubectl rollout status statefulsets/backing-stateful-component --watch=false
```
You can also pause, resume or cancel a rollout.
Visit [`kubectl rollout`](/docs/reference/kubectl/generated/kubectl_rollout/) to learn more.
## Canary deployments
<!--TODO: make a task out of this for canary deployment, ref #42786-->
@ -229,13 +340,10 @@ each release that will receive live production traffic (in this case, 3:1).
Once you're confident, you can update the stable track to the new application release and remove
the canary one.
For a more concrete example, check the
[tutorial of deploying Ghost](https://github.com/kelseyhightower/talks/tree/master/kubecon-eu-2016/demo#deploy-a-canary).
## Updating annotations
Sometimes you would want to attach annotations to resources. Annotations are arbitrary
non-identifying metadata for retrieval by API clients such as tools, libraries, etc.
non-identifying metadata for retrieval by API clients such as tools or libraries.
This can be done with `kubectl annotate`. For example:
```shell
@ -253,7 +361,7 @@ metadata:
```
For more information, see [annotations](/docs/concepts/overview/working-with-objects/annotations/)
and [kubectl annotate](/docs/reference/generated/kubectl/kubectl-commands/#annotate) document.
and [kubectl annotate](/docs/reference/kubectl/generated/kubectl_annotate/).
## Scaling your application
@ -283,6 +391,7 @@ To have the system automatically choose the number of nginx replicas as needed,
ranging from 1 to 3, do:
```shell
# This requires an existing source of container and Pod metrics
kubectl autoscale deployment/my-nginx --min=1 --max=3
```
@ -292,8 +401,8 @@ horizontalpodautoscaler.autoscaling/my-nginx autoscaled
Now your nginx replicas will be scaled up and down as needed, automatically.
For more information, please see [kubectl scale](/docs/reference/generated/kubectl/kubectl-commands/#scale),
[kubectl autoscale](/docs/reference/generated/kubectl/kubectl-commands/#autoscale) and
For more information, please see [kubectl scale](/docs/reference/kubectl/generated/kubectl_scale/),
[kubectl autoscale](/docs/reference/kubectl/generated/kubectl_autoscale/) and
[horizontal pod autoscaler](/docs/tasks/run-application/horizontal-pod-autoscale/) document.
## In-place updates of resources
@ -305,7 +414,7 @@ Sometimes it's necessary to make narrow, non-disruptive updates to resources you
It is suggested to maintain a set of configuration files in source control
(see [configuration as code](https://martinfowler.com/bliki/InfrastructureAsCode.html)),
so that they can be maintained and versioned along with the code for the resources they configure.
Then, you can use [`kubectl apply`](/docs/reference/generated/kubectl/kubectl-commands/#apply)
Then, you can use [`kubectl apply`](/docs/reference/kubectl/generated/kubectl_apply/)
to push your configuration changes to the cluster.
This command will compare the version of the configuration that you're pushing with the previous
@ -320,23 +429,11 @@ kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml
deployment.apps/my-nginx configured
```
Note that `kubectl apply` attaches an annotation to the resource in order to determine the changes
to the configuration since the previous invocation. When it's invoked, `kubectl apply` does a
three-way diff between the previous configuration, the provided input and the current
configuration of the resource, in order to determine how to modify the resource.
Currently, resources are created without this annotation, so the first invocation of `kubectl
apply` will fall back to a two-way diff between the provided input and the current configuration
of the resource. During this first invocation, it cannot detect the deletion of properties set
when the resource was created. For this reason, it will not remove them.
All subsequent calls to `kubectl apply`, and other commands that modify the configuration, such as
`kubectl replace` and `kubectl edit`, will update the annotation, allowing subsequent calls to
`kubectl apply` to detect and perform deletions using a three-way diff.
To learn more about the underlying mechanism, read [server-side apply](/docs/reference/using-api/server-side-apply/).
### kubectl edit
Alternatively, you may also update resources with `kubectl edit`:
Alternatively, you may also update resources with [`kubectl edit`](/docs/reference/kubectl/generated/kubectl_edit/):
```shell
kubectl edit deployment/my-nginx
@ -359,15 +456,17 @@ rm /tmp/nginx.yaml
This allows you to do more significant changes more easily. Note that you can specify the editor
with your `EDITOR` or `KUBE_EDITOR` environment variables.
For more information, please see [kubectl edit](/docs/reference/generated/kubectl/kubectl-commands/#edit) document.
For more information, please see [kubectl edit](/docs/reference/kubectl/generated/kubectl_edit/).
### kubectl patch
You can use `kubectl patch` to update API objects in place. This command supports JSON patch,
JSON merge patch, and strategic merge patch. See
You can use [`kubectl patch`](/docs/reference/kubectl/generated/kubectl_patch/) to update API objects in place.
This subcommand supports JSON patch,
JSON merge patch, and strategic merge patch.
See
[Update API Objects in Place Using kubectl patch](/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/)
and
[kubectl patch](/docs/reference/generated/kubectl/kubectl-commands/#patch).
for more details.
## Disruptive updates
@ -385,48 +484,7 @@ deployment.apps/my-nginx deleted
deployment.apps/my-nginx replaced
```
## Updating your application without a service outage
At some point, you'll eventually need to update your deployed application, typically by specifying
a new image or image tag, as in the canary deployment scenario above. `kubectl` supports several
update operations, each of which is applicable to different scenarios.
We'll guide you through how to create and update applications with Deployments.
Let's say you were running version 1.14.2 of nginx:
```shell
kubectl create deployment my-nginx --image=nginx:1.14.2
```
```none
deployment.apps/my-nginx created
```
with 3 replicas (so the old and new revisions can coexist):
```shell
kubectl scale deployment my-nginx --current-replicas=1 --replicas=3
```
```none
deployment.apps/my-nginx scaled
```
To update to version 1.16.1, change `.spec.template.spec.containers[0].image` from `nginx:1.14.2`
to `nginx:1.16.1` using the previous kubectl commands.
```shell
kubectl edit deployment/my-nginx
```
That's it! The Deployment will declaratively update the deployed nginx application progressively
behind the scene. It ensures that only a certain number of old replicas may be down while they are
being updated, and only a certain number of new replicas may be created above the desired number
of pods. To learn more details about it, visit [Deployment page](/docs/concepts/workloads/controllers/deployment/).
## {{% heading "whatsnext" %}}
- Learn about [how to use `kubectl` for application introspection and debugging](/docs/tasks/debug/debug-application/debug-running-pod/).
- See [Configuration Best Practices and Tips](/docs/concepts/configuration/overview/).

View File

@ -45,6 +45,14 @@ Each day in a week-long shift as PR Wrangler:
- Using style fixups as good first issues is a good way to ensure a supply of easier tasks
to help onboard new contributors.
{{< note >}}
PR wrangler duties do not apply to localization PRs (non-English PRs).
Localization teams have their own processes and teams for reviewing their language PRs.
However, it's often helpful to ensure language PRs are labeled correctly,
review small non-language dependent PRs (like a link update),
or tag reviewers or contributors in long-running PRs (ones opened more than 6 months ago and have not been updated in a month or more).
{{< /note >}}
### Helpful GitHub queries for wranglers

View File

@ -10,5 +10,5 @@ stages:
defaultValue: false
fromVersion: "1.29"
---
Enables images to be pulled based on the [runtime class]
(/docs/concepts/containers/runtime-class/) of the pods that reference them.
Enables images to be pulled based on the [runtime class](/docs/concepts/containers/runtime-class/)
of the pods that reference them.

View File

@ -71,12 +71,19 @@ KUBECONFIG=~/.kube/config:~/.kube/kubconfig2
kubectl config view
# Show merged kubeconfig settings and raw certificate data and exposed secrets
kubectl config view --raw
# get the password for the e2e user
kubectl config view -o jsonpath='{.users[?(@.name == "e2e")].user.password}'
# get the certificate for the e2e user
kubectl config view --raw -o jsonpath='{.users[?(.name == 'e2e')].user.client-certificate-data}' | base64 -d
kubectl config view -o jsonpath='{.users[].name}' # display the first user
kubectl config view -o jsonpath='{.users[*].name}' # get a list of users
kubectl config get-contexts # display list of contexts
kubectl config get-contexts -o name # get all context names
kubectl config current-context # display the current-context
kubectl config use-context my-cluster-name # set the default context to my-cluster-name

View File

@ -60,7 +60,7 @@ When present, indicates that modifications should not be persisted. An invalid o
## fieldManager {#fieldManager}
fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint.
fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://pkg.go.dev/unicode#IsPrint.
<hr>

View File

@ -48,6 +48,6 @@ You can provide feedback via the GitHub issue [**Dockershim removal feedback & i
* Mirantis blog: [The Future of Dockershim is cri-dockerd](https://www.mirantis.com/blog/the-future-of-dockershim-is-cri-dockerd/) (published 2021/04/21)
* Mirantis: [Mirantis/cri-dockerd](https://github.com/Mirantis/cri-dockerd) Git repository (on GitHub)
* Mirantis: [Mirantis/cri-dockerd](https://mirantis.github.io/cri-dockerd/) Official Documentation
* Tripwire: [How Dockershims Forthcoming Deprecation Affects Your Kubernetes](https://www.tripwire.com/state-of-security/security-data-protection/cloud/how-dockershim-forthcoming-deprecation-affects-your-kubernetes/) (published 2021/07/01)

View File

@ -308,15 +308,14 @@ This config option supports live configuration reload to apply this change: `sys
{{< note >}}
These instructions assume that you are using the
[`cri-dockerd`](https://github.com/Mirantis/cri-dockerd) adapter to integrate
[`cri-dockerd`](https://mirantis.github.io/cri-dockerd/) adapter to integrate
Docker Engine with Kubernetes.
{{< /note >}}
1. On each of your nodes, install Docker for your Linux distribution as per
[Install Docker Engine](https://docs.docker.com/engine/install/#server).
2. Install [`cri-dockerd`](https://github.com/Mirantis/cri-dockerd), following
the instructions in that source code repository.
2. Install [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/usage/install), following the directions in the install section of the documentation.
For `cri-dockerd`, the CRI socket is `/run/cri-dockerd.sock` by default.
@ -326,7 +325,7 @@ For `cri-dockerd`, the CRI socket is `/run/cri-dockerd.sock` by default.
available container runtime that was formerly known as Docker Enterprise Edition.
You can use Mirantis Container Runtime with Kubernetes using the open source
[`cri-dockerd`](https://github.com/Mirantis/cri-dockerd) component, included with MCR.
[`cri-dockerd`](https://mirantis.github.io/cri-dockerd/) component, included with MCR.
To learn more about how to install Mirantis Container Runtime,
visit [MCR Deployment Guide](https://docs.mirantis.com/mcr/20.10/install.html).

View File

@ -62,10 +62,10 @@ route, we recommend you add IP route(s) so Kubernetes cluster addresses go via t
These [required ports](/docs/reference/networking/ports-and-protocols/)
need to be open in order for Kubernetes components to communicate with each other.
You can use tools like netcat to check if a port is open. For example:
You can use tools like [netcat](https://netcat.sourceforge.net) to check if a port is open. For example:
```shell
nc 127.0.0.1 6443
nc 127.0.0.1 6443 -v
```
The pod network plugin you use may also require certain ports to be
@ -93,7 +93,7 @@ for more information.
{{< note >}}
Docker Engine does not implement the [CRI](/docs/concepts/architecture/cri/)
which is a requirement for a container runtime to work with Kubernetes.
For that reason, an additional service [cri-dockerd](https://github.com/Mirantis/cri-dockerd)
For that reason, an additional service [cri-dockerd](https://mirantis.github.io/cri-dockerd/)
has to be installed. cri-dockerd is a project based on the legacy built-in
Docker Engine support that was [removed](/dockershim) from the kubelet in version 1.24.
{{< /note >}}
@ -161,14 +161,14 @@ For more information on version skews, see:
{{< note >}}
There's a dedicated package repository for each Kubernetes minor version. If you want to install
a minor version other than {{< skew currentVersion >}}, please see the installation guide for
a minor version other than v{{< skew currentVersion >}}, please see the installation guide for
your desired minor version.
{{< /note >}}
{{< tabs name="k8s_install" >}}
{{% tab name="Debian-based distributions" %}}
These instructions are for Kubernetes {{< skew currentVersion >}}.
These instructions are for Kubernetes v{{< skew currentVersion >}}.
1. Update the `apt` package index and install packages needed to use the Kubernetes `apt` repository:
@ -182,13 +182,13 @@ These instructions are for Kubernetes {{< skew currentVersion >}}.
The same signing key is used for all repositories so you can disregard the version in the URL:
```shell
# If the folder `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
# If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below.
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
```
{{< note >}}
In releases older than Debian 12 and Ubuntu 22.04, folder `/etc/apt/keyrings` does not exist by default, and it should be created before the curl command.
In releases older than Debian 12 and Ubuntu 22.04, directory `/etc/apt/keyrings` does not exist by default, and it should be created before the curl command.
{{< /note >}}
3. Add the appropriate Kubernetes `apt` repository. Please note that this repository have packages
@ -210,6 +210,12 @@ In releases older than Debian 12 and Ubuntu 22.04, folder `/etc/apt/keyrings` do
sudo apt-mark hold kubelet kubeadm kubectl
```
5. (Optional) Enable the kubelet service before running kubeadm:
```shell
sudo systemctl enable --now kubelet
```
{{% /tab %}}
{{% tab name="Red Hat-based distributions" %}}
@ -255,10 +261,15 @@ settings that are not supported by kubeadm.
EOF
```
3. Install kubelet, kubeadm and kubectl, and enable kubelet to ensure it's automatically started on startup:
3. Install kubelet, kubeadm and kubectl:
```shell
sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
```
4. (Optional) Enable the kubelet service before running kubeadm:
```shell
sudo systemctl enable --now kubelet
```
@ -294,7 +305,7 @@ ARCH="amd64"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz
```
Install `kubeadm`, `kubelet`, `kubectl` and add a `kubelet` systemd service:
Install `kubeadm`, `kubelet` and add a `kubelet` systemd service:
```bash
RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
@ -304,9 +315,9 @@ sudo curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${
sudo chmod +x {kubeadm,kubelet}
RELEASE_VERSION="v0.16.2"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service
sudo mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service
sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
```
{{< note >}}
@ -316,10 +327,10 @@ that do not include `glibc` by default.
Install `kubectl` by following the instructions on [Install Tools page](/docs/tasks/tools/#kubectl).
Enable and start `kubelet`:
Optionally, enable the kubelet service before running kubeadm:
```bash
systemctl enable --now kubelet
sudo systemctl enable --now kubelet
```
{{< note >}}

View File

@ -163,9 +163,16 @@ Note that the kubeadm CLI command never touches this drop-in file.
This configuration file installed by the `kubeadm`
[package](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf) is written to
`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` and is used by systemd.
`/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf` and is used by systemd.
It augments the basic
[`kubelet.service`](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubelet/kubelet.service):
[`kubelet.service`](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubelet/kubelet.service).
If you want to override that further, you can make a directory `/etc/systemd/system/kubelet.service.d/`
(not `/usr/lib/systemd/system/kubelet.service.d/`) and put your own customizations into a file there.
For example, you might add a new local file `/etc/systemd/system/kubelet.service.d/local-overrides.conf`
to override the unit settings configured by `kubeadm`.
Here is what you are likely to find in `/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf`:
{{< note >}}
The contents below are just an example. If you don't want to use a package manager

View File

@ -47,7 +47,7 @@ to `cri-dockerd`.
## {{% heading "prerequisites" %}}
* [`cri-dockerd`](https://github.com/mirantis/cri-dockerd#build-and-install)
* [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/usage/install)
installed and started on each node.
* A [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/).

View File

@ -205,7 +205,8 @@ Below are the procedures to set up autocompletion for PowerShell.
1. After installing the plugin, clean up the installation files:
```powershell
del kubectl-convert.exe kubectl-convert.exe.sha256
del kubectl-convert.exe
del kubectl-convert.exe.sha256
```
## {{% heading "whatsnext" %}}

View File

@ -11,7 +11,7 @@ weight: 30
{{< feature-state for_k8s_version="v1.4" state="beta" >}}
AppArmor is a Linux kernel security module that supplements the standard Linux user and group based
[AppArmor](https://apparmor.net/) is a Linux kernel security module that supplements the standard Linux user and group based
permissions to confine programs to a limited set of resources. AppArmor can be configured for any
application to reduce its potential attack surface and provide greater in-depth defense. It is
configured through profiles tuned to allow the access needed by a specific program or container,
@ -19,7 +19,7 @@ such as Linux capabilities, network access, file permissions, etc. Each profile
*enforcing* mode, which blocks access to disallowed resources, or *complain* mode, which only reports
violations.
AppArmor can help you to run a more secure deployment by restricting what containers are allowed to
On Kubernetes, AppArmor can help you to run a more secure deployment by restricting what containers are allowed to
do, and/or provide better auditing through system logs. However, it is important to keep in mind
that AppArmor is not a silver bullet and can only do so much to protect against exploits in your
application code. It is important to provide good, restrictive profiles, and harden your
@ -30,7 +30,7 @@ applications and cluster from other angles as well.
## {{% heading "objectives" %}}
* See an example of how to load a profile on a node
* See an example of how to load a profile on a Node
* Learn how to enforce the profile on a Pod
* Learn how to check that the profile is loaded
* See what happens when a profile is violated
@ -41,23 +41,10 @@ applications and cluster from other angles as well.
## {{% heading "prerequisites" %}}
Make sure:
AppArmor is an optional kernel module and Kubernetes feature, so verify it is supported on your
Nodes before proceeding:
1. Kubernetes version is at least v1.4 -- Kubernetes support for AppArmor was added in
v1.4. Kubernetes components older than v1.4 are not aware of the new AppArmor annotations, and
will **silently ignore** any AppArmor settings that are provided. To ensure that your Pods are
receiving the expected protections, it is important to verify the Kubelet version of your nodes:
```shell
kubectl get nodes -o=jsonpath=$'{range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}'
```
```
gke-test-default-pool-239f5d02-gyn2: v1.4.0
gke-test-default-pool-239f5d02-x1kf: v1.4.0
gke-test-default-pool-239f5d02-xwux: v1.4.0
```
2. AppArmor kernel module is enabled -- For the Linux kernel to enforce an AppArmor profile, the
1. AppArmor kernel module is enabled -- For the Linux kernel to enforce an AppArmor profile, the
AppArmor kernel module must be installed and enabled. Several distributions enable the module by
default, such as Ubuntu and SUSE, and many others provide optional support. To check whether the
module is enabled, check the `/sys/module/apparmor/parameters/enabled` file:
@ -67,24 +54,17 @@ Make sure:
Y
```
If the Kubelet contains AppArmor support (>= v1.4), it will refuse to run a Pod with AppArmor
options if the kernel module is not enabled.
The Kubelet verifies that AppArmor is enabled on the host before admitting a pod with AppArmor
explicitly configured.
{{< note >}}
Ubuntu carries many AppArmor patches that have not been merged into the upstream Linux
kernel, including patches that add additional hooks and features. Kubernetes has only been
tested with the upstream version, and does not promise support for other features.
{{< /note >}}
3. Container runtime supports AppArmor -- Currently all common Kubernetes-supported container
runtimes should support AppArmor, like {{< glossary_tooltip term_id="docker">}},
{{< glossary_tooltip term_id="cri-o" >}} or {{< glossary_tooltip term_id="containerd" >}}.
Please refer to the corresponding runtime documentation and verify that the cluster fulfills
the requirements to use AppArmor.
3. Container runtime supports AppArmor -- All common Kubernetes-supported container
runtimes should support AppArmor, including {{< glossary_tooltip term_id="containerd" >}} and
{{< glossary_tooltip term_id="cri-o" >}}. Please refer to the corresponding runtime
documentation and verify that the cluster fulfills the requirements to use AppArmor.
4. Profile is loaded -- AppArmor is applied to a Pod by specifying an AppArmor profile that each
container should be run with. If any of the specified profiles is not already loaded in the
kernel, the Kubelet (>= v1.4) will reject the Pod. You can view which profiles are loaded on a
container should be run with. If any of the specified profiles are not loaded in the
kernel, the Kubelet will reject the Pod. You can view which profiles are loaded on a
node by checking the `/sys/kernel/security/apparmor/profiles` file. For example:
```shell
@ -100,22 +80,6 @@ Make sure:
For more details on loading profiles on nodes, see
[Setting up nodes with profiles](#setting-up-nodes-with-profiles).
As long as the Kubelet version includes AppArmor support (>= v1.4), the Kubelet will reject a Pod
with AppArmor options if any of the prerequisites are not met. You can also verify AppArmor support
on nodes by checking the node ready condition message (though this is likely to be removed in a
later release):
```shell
kubectl get nodes -o=jsonpath='{range .items[*]}{@.metadata.name}: {.status.conditions[?(@.reason=="KubeletReady")].message}{"\n"}{end}'
```
```
gke-test-default-pool-239f5d02-gyn2: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-x1kf: kubelet is posting ready status. AppArmor enabled
gke-test-default-pool-239f5d02-xwux: kubelet is posting ready status. AppArmor enabled
```
<!-- lessoncontent -->
## Securing a Pod
@ -133,7 +97,7 @@ container.apparmor.security.beta.kubernetes.io/<container_name>: <profile_ref>
```
Where `<container_name>` is the name of the container to apply the profile to, and `<profile_ref>`
specifies the profile to apply. The `profile_ref` can be one of:
specifies the profile to apply. The `<profile_ref>` can be one of:
* `runtime/default` to apply the runtime's default profile
* `localhost/<profile_name>` to apply the profile loaded on the host with the name `<profile_name>`
@ -141,24 +105,15 @@ specifies the profile to apply. The `profile_ref` can be one of:
See the [API Reference](#api-reference) for the full details on the annotation and profile name formats.
Kubernetes AppArmor enforcement works by first checking that all the prerequisites have been
met, and then forwarding the profile selection to the container runtime for enforcement. If the
prerequisites have not been met, the Pod will be rejected, and will not run.
To verify that the profile was applied, you can look for the AppArmor security option listed in the container created event:
```shell
kubectl get events | grep Created
```
```
22s 22s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet e2e-test-stclair-node-pool-31nt} Created container with docker id 269a53b202d3; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
```
You can also verify directly that the container's root process is running with the correct profile by checking its proc attr:
To verify that the profile was applied, you can check that the container's root process is
running with the correct profile by examining its proc attr:
```shell
kubectl exec <pod_name> -- cat /proc/1/attr/current
```
The output should look something like this:
```
k8s-apparmor-example-deny-write (enforce)
```
@ -167,9 +122,9 @@ k8s-apparmor-example-deny-write (enforce)
*This example assumes you have already set up a cluster with AppArmor support.*
First, we need to load the profile we want to use onto our nodes. This profile denies all file writes:
First, load the profile you want to use onto your Nodes. This profile denies all file writes:
```shell
```
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
@ -182,16 +137,14 @@ profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
}
```
Since we don't know where the Pod will be scheduled, we'll need to load the profile on all our
nodes. For this example we'll use SSH to install the profiles, but other approaches are
The profile needs to loaded onto all nodes, since you don't know where the pod will be scheduled.
For this example you can use SSH to install the profiles, but other approaches are
discussed in [Setting up nodes with profiles](#setting-up-nodes-with-profiles).
```shell
NODES=(
# The SSH-accessible domain names of your nodes
gke-test-default-pool-239f5d02-gyn2.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-x1kf.us-central1-a.my-k8s
gke-test-default-pool-239f5d02-xwux.us-central1-a.my-k8s)
# This example assumes that node names match host names, and are reachable via SSH.
NODES=($(kubectl get nodes -o name))
for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q <<EOF
#include <tunables/global>
@ -207,38 +160,26 @@ EOF'
done
```
Next, we'll run a simple "Hello AppArmor" pod with the deny-write profile:
Next, run a simple "Hello AppArmor" Pod with the deny-write profile:
{{% code_sample file="pods/security/hello-apparmor.yaml" %}}
```shell
kubectl create -f ./hello-apparmor.yaml
kubectl create -f hello-apparmor.yaml
```
If we look at the pod events, we can see that the Pod container was created with the AppArmor
profile "k8s-apparmor-example-deny-write":
```shell
kubectl get events | grep hello-apparmor
```
```
14s 14s 1 hello-apparmor Pod Normal Scheduled {default-scheduler } Successfully assigned hello-apparmor to gke-test-default-pool-239f5d02-gyn2
14s 14s 1 hello-apparmor Pod spec.containers{hello} Normal Pulling {kubelet gke-test-default-pool-239f5d02-gyn2} pulling image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Pulled {kubelet gke-test-default-pool-239f5d02-gyn2} Successfully pulled image "busybox"
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet gke-test-default-pool-239f5d02-gyn2} Created container with docker id 06b6cd1c0989; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Started {kubelet gke-test-default-pool-239f5d02-gyn2} Started container with docker id 06b6cd1c0989
```
We can verify that the container is actually running with that profile by checking its proc attr:
You can verify that the container is actually running with that profile by checking `/proc/1/attr/current`:
```shell
kubectl exec hello-apparmor -- cat /proc/1/attr/current
```
The output should be:
```
k8s-apparmor-example-deny-write (enforce)
```
Finally, we can see what happens if we try to violate the profile by writing to a file:
Finally, you can see what happens if you violate the profile by writing to a file:
```shell
kubectl exec hello-apparmor -- touch /tmp/test
@ -248,12 +189,10 @@ touch: /tmp/test: Permission denied
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1
```
To wrap up, let's look at what happens if we try to specify a profile that hasn't been loaded:
To wrap up, see what happens if you try to specify a profile that hasn't been loaded:
```shell
kubectl create -f /dev/stdin <<EOF
```
```yaml
apiVersion: v1
kind: Pod
metadata:
@ -266,101 +205,53 @@ spec:
image: busybox:1.28
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
EOF
```
```
pod/hello-apparmor-2 created
```
Although the Pod was created successfully, further examination will show that it is stuck in pending:
```shell
kubectl describe pod hello-apparmor-2
```
```
Name: hello-apparmor-2
Namespace: default
Node: gke-test-default-pool-239f5d02-x1kf/
Node: gke-test-default-pool-239f5d02-x1kf/10.128.0.27
Start Time: Tue, 30 Aug 2016 17:58:56 -0700
Labels: <none>
Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write
Status: Pending
Reason: AppArmor
Message: Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
IP:
Controllers: <none>
Containers:
hello:
Container ID:
Image: busybox
Image ID:
Port:
Command:
sh
-c
echo 'Hello AppArmor!' && sleep 1h
State: Waiting
Reason: Blocked
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-dnz7v (ro)
Conditions:
Type Status
Initialized True
Ready False
PodScheduled True
Volumes:
default-token-dnz7v:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-dnz7v
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: <none>
...
Events:
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
23s 23s 1 {default-scheduler } Normal Scheduled Successfully assigned hello-apparmor-2 to e2e-test-stclair-node-pool-t1f5
23s 23s 1 {kubelet e2e-test-stclair-node-pool-t1f5} Warning AppArmor Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 10s default-scheduler Successfully assigned default/hello-apparmor to gke-test-default-pool-239f5d02-x1kf
Normal Pulled 8s kubelet Successfully pulled image "busybox:1.28" in 370.157088ms (370.172701ms including waiting)
Normal Pulling 7s (x2 over 9s) kubelet Pulling image "busybox:1.28"
Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found k8s-apparmor-example-allow-write
Normal Pulled 7s kubelet Successfully pulled image "busybox:1.28" in 90.980331ms (91.005869ms including waiting)
```
Note the pod status is Pending, with a helpful error message: `Pod Cannot enforce AppArmor: profile
"k8s-apparmor-example-allow-write" is not loaded`. An event was also recorded with the same message.
An Event provides the error message with the reason, the specific wording is runtime-dependent:
```
Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found
```
## Administration
### Setting up nodes with profiles
### Setting up Nodes with profiles
Kubernetes does not currently provide any native mechanisms for loading AppArmor profiles onto
nodes. There are lots of ways to set up the profiles though, such as:
Kubernetes does not currently provide any built-in mechanisms for loading AppArmor profiles onto
Nodes. Profiles can be loaded through custom infrastructure or tools like the
[Kubernetes Security Profiles Operator](https://github.com/kubernetes-sigs/security-profiles-operator).
* Through a [DaemonSet](/docs/concepts/workloads/controllers/daemonset/) that runs a Pod on each node to
ensure the correct profiles are loaded. An example implementation can be found
[here](https://git.k8s.io/kubernetes/test/images/apparmor-loader).
* At node initialization time, using your node initialization scripts (e.g. Salt, Ansible, etc.) or
image.
* By copying the profiles to each node and loading them through SSH, as demonstrated in the
[Example](#example).
The scheduler is not aware of which profiles are loaded onto which node, so the full set of profiles
must be loaded onto every node. An alternative approach is to add a node label for each profile (or
class of profiles) on the node, and use a
The scheduler is not aware of which profiles are loaded onto which Node, so the full set of profiles
must be loaded onto every Node. An alternative approach is to add a Node label for each profile (or
class of profiles) on the Node, and use a
[node selector](/docs/concepts/scheduling-eviction/assign-pod-node/) to ensure the Pod is run on a
node with the required profile.
### Disabling AppArmor
If you do not want AppArmor to be available on your cluster, it can be disabled by a command-line flag:
```
--feature-gates=AppArmor=false
```
When disabled, any Pod that includes an AppArmor profile will fail validation with a "Forbidden"
error.
{{<note>}}
Even if the Kubernetes feature is disabled, runtimes may still enforce the default profile. The
option to disable the AppArmor feature will be removed when AppArmor graduates to general
availability (GA).
{{</note>}}
Node with the required profile.
## Authoring Profiles
@ -393,8 +284,7 @@ Specifying the profile a container will run with:
### Profile Reference
- `runtime/default`: Refers to the default runtime profile.
- Equivalent to not specifying a profile, except it still
requires AppArmor to be enabled.
- Equivalent to not specifying a profile, except it still requires AppArmor to be enabled.
- In practice, many container runtimes use the same OCI default profile, defined here:
https://github.com/containers/common/blob/main/pkg/apparmor/apparmor_linux_template.go
- `localhost/<profile_name>`: Refers to a profile loaded on the node (localhost) by name.

View File

@ -18,4 +18,4 @@ spec:
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5

View File

@ -21,7 +21,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
@ -365,7 +364,7 @@ func walkConfigFiles(inDir string, t *testing.T, fn func(name, path string, data
file := filepath.Base(path)
if ext := filepath.Ext(file); ext == ".json" || ext == ".yaml" {
data, err := ioutil.ReadFile(path)
data, err := os.ReadFile(path)
if err != nil {
return err
}

View File

@ -4,7 +4,6 @@ metadata:
name: hello-apparmor
annotations:
# Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write".
# Note that this is ignored if the Kubernetes node is not running version 1.4 or greater.
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write
spec:
containers:

View File

@ -57,7 +57,11 @@
"sendto",
"set_tid_address",
"setitimer",
"writev"
"writev",
"fstatfs",
"getdents64",
"pipe2",
"getrlimit"
],
"action": "SCMP_ACT_ALLOW"
}

View File

@ -0,0 +1,748 @@
---
reviewers:
- raelga
title: Ingress
content_type: concept
description: >-
Permite que sean accesibles los servicios de red HTTP (o HTTPS) usando un mecanismo de configuración consciente del protocolo, que entiende conceptos como URIs, nombres de host, rutas y más.
El concepto de Ingress te permite mapear el tráfico a diferentes backend basado en las reglas que defines a través de la API de Kubernetes.
weight: 30
---
<!-- overview -->
{{< feature-state for_k8s_version="v1.19" state="stable" >}}
{{< glossary_definition term_id="ingress" length="all" >}}
{{< note >}}
El recurso Ingress está congelado.
Las nuevas características se añaden
al [API del Gateway](/docs/concepts/services-networking/gateway/)
{{< /note >}}
<!-- body -->
## Terminología
Para mayor claridad, esta guía define los siguientes términos:
* Nodo: Una máquina worker en Kubernetes, parte de un clúster.
* Clúster: Un conjunto de Nodos que ejecutan aplicaciones en contenedores,
administrados por Kubernetes.
Para este ejemplo, y para los despliegues más comunes de Kubernetes, los nodos
en el clúster no son parte del internet público.
* Enrutador Edge: un enrutador que refuerza la política de seguridad del
cortafuegos para tu clúster.
Esto podría ser una puerta de entrada administrada por un proveedor de la nube
o una pieza física de hardware.
* Red del clúster: un conjunto de enlaces, lógicos o físicos,
que facilitan la comunicación dentro de un clúster de acuerdo con
el [modelo de redes](/docs/concepts/cluster-administration/networking/) de
Kubernetes.
* Service: Un {{< glossary_tooltip term_id="service" >}} que identifica
un conjunto de Pods que utilizan selectores de {{< glossary_tooltip text="label" term_id="label" >}}.
A menos que se indique de otra manera, los Services se asumen que tienen IPs
virtuales que solo se pueden enrutar dentro de la red del clúster.
## ¿Qué es un Ingress?
Un [Ingress](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#ingress-v1-networking-k8s-io)
expone rutas HTTP y HTTPS desde el exterior del clúster a los
{{< link text="servicios" url="es/docs/concepts/services-networking/service/" >}} dentro del clúster.
El control del tráfico es controlado por las reglas definidas en el recurso Ingress.
Aquí tienes un ejemplo simple de un Ingress que envía todo su tráfico a un
Service:
{{< figure src="/docs/images/ingress.svg" alt="ingress-diagram" class="diagram-large" caption="Figure. Ingress" link="https://mermaid.live/edit#pako:eNqNkstuwyAQRX8F4U0r2VHqPlSRKqt0UamLqlnaWWAYJygYLB59KMm_Fxcix-qmGwbuXA7DwAEzzQETXKutof0Ovb4vaoUQkwKUu6pi3FwXM_QSHGBt0VFFt8DRU2OWSGrKUUMlVQwMmhVLEV1Vcm9-aUksiuXRaO_CEhkv4WjBfAgG1TrGaLa-iaUw6a0DcwGI-WgOsF7zm-pN881fvRx1UDzeiFq7ghb1kgqFWiElyTjnuXVG74FkbdumefEpuNuRu_4rZ1pqQ7L5fL6YQPaPNiFuywcG9_-ihNyUkm6YSONWkjVNM8WUIyaeOJLO3clTB_KhL8NQDmVe-OJjxgZM5FhFiiFTK5zjDkxHBQ9_4zB4a-x20EGNSZhyaKmXrg7f5hSsvufUwTMXThtMWiot5Jh6p9ffimHijIezaSVoeN0uiqcfMJvf7w" >}}
Un Ingress se puede configurar para otorgar URLs a los Services que son
accesibles desde el exterior,
para hacer balance de cargas del tráfico, finalizar SSL/TLS y ofrecer
alojamiento virtual basado en nombres.
Un [controlador de Ingress](/docs/concepts/services-networking/ingress-controllers)
es responsable de complementar el Ingress,
comúnmente con un balanceador de cargas,
aunque también puedes configurar tu enrutador edge con frontends adicionales para
ayudar a manejar el tráfico.
Un Ingress no expone puertos o protocolos arbitrariamente. Exponer servicios
distintos de HTTP o HTTPS al internet usa un servicio de
tipo [Service.Type=NodePort](/es/docs/concepts/services-networking/service/#tipo-nodeport)
o [Service.Type=LoadBalancer](/es/docs/concepts/services-networking/service/#loadbalancer).
## Prerrequisitos
Debes tener
un [controlador de Ingress](/docs/concepts/services-networking/ingress-controllers)
para satisfacer a un Ingress.
Crear únicamente un recurso Ingress no tiene ningún efecto.
Puede que necesites desplegar un controlador Ingress controller tal como
el [ingress-nginx](https://kubernetes.github.io/ingress-nginx/deploy/).
Puedes elegir de un número
de [controladores de Ingress](/docs/concepts/services-networking/ingress-controllers).
Idealmente,
todos los controladores de Ingress deberían encajar con la especificación de
referencia.
En realidad, los distintos controladores de Ingress operan ligeramente
diferente.
{{< note >}}
Asegúrate de revisar la documentación del controlador de Ingress para entender
las precauciones de usarlo.
{{< /note >}}
## El recurso Ingress
Un ejemplo mínimo de un recurso Ingress:
{{% code_sample file="service/networking/minimal-ingress.yaml" %}}
Un Ingress necesita los campos `apiVersion`, `kind`, `metadata` y `spec`.
El nombre del objeto Ingress debe ser un
[nombre de subdominio DNS](es/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)
válido.
Para información general sobre cómo trabajar con archivos de configuración,
mira [desplegando aplicaciones](/es/docs/tasks/run-application/run-stateless-application-deployment/),
[configurando contenedores](/docs/tasks/configure-pod-container/configure-pod-configmap/),
[administrando recursos](/docs/concepts/cluster-administration/manage-deployment/).
Los Ingress usan anotaciones frecuentemente para configurar algunas opciones
dependiendo del controlador de Ingress,
un ejemplo de ello es
la [anotación rewrite-target](https://github.com/kubernetes/ingress-nginx/blob/main/docs/examples/rewrite/README.md).
Distintos [controladores de Ingress](/docs/concepts/services-networking/ingress-controllers)
soportan anotaciones diferentes.
Revisa la documentación para tu elección del controlador de Ingress para saber
qué anotaciones son soportadas.
La [especificación Ingress](/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec)
tiene toda la información que necesitas para configurar un balanceador de cargas
o un servidor proxy.
Mucho más importante, contiene un listado de reglas que emparejan contra todas
las peticiones entrantes.
El recurso Ingress solo soporta reglas para dirigir el tráfico HTTP(S).
Si se omite la `ingressClassName`, se define
una [clase Ingress por defecto](#default-ingress-class).
Existen algunos controladores de Ingress,
que trabajan sin la definición de una `IngressClass` por defecto.
Por ejemplo, el controlador Ingress-NGINX se puede configurar con
una [opción](https://kubernetes.github.io/ingress-nginx/user-guide/k8s-122-migration/#what-is-the-flag-watch-ingress-without-class)
`--watch-ingress-without-class`.
Sin embargo,
se [recomienda](https://kubernetes.github.io/ingress-nginx/user-guide/k8s-122-migration/#i-have-only-one-ingress-controller-in-my-cluster-what-should-i-do)
especificar el `IngressClass` por defecto como se
muestra [abajo](#default-ingress-class).
### Reglas del Ingress
Cada regla HTTP contiene la siguiente información:
* Un host opcional.
En este ejemplo,
no se define un host así que la regla se aplica a todo el tráfico de
entrada HTTP a través de la dirección IP especificada.
Cuando se proporciona un host (por ejemplo, foo.bar.com), las reglas se
aplican a ese host.
* Un listado de rutas (por ejemplo, `/testpath`), cada una de las cuales tiene
un backend asociado con un `service.name` y un `service.port.name` o
un `service.port.number`. Tanto el host como la ruta deben coincidir con el
contenido de una petición de entrada antes que el balanceador de cargas dirija
el tráfico al Service referenciado.
* Un backend es una combinación de un Service y un puerto como se describe en la
[documentación del Service](/es/docs/concepts/services-networking/service/) o
un [recurso personalizado backend](#resource-backend)
a través de un {{< glossary_tooltip term_id="CustomResourceDefinition" text=" CRD" >}}.
Las peticiones HTTP (y HTTPS) al Ingress que coinciden con el host y la
ruta de la regla se envían al backend del listado.
Un `defaultBackend` se configura frecuentemente en un controlador de Ingress
para dar servicio a cualquier petición que no coincide con una ruta en la
especificación.
### DefaultBackend {#default-backend}
Un Ingress sin reglas envía todo el tráfico a un único backend
y `.spec.defaultBackend` está en el backend que debería manejar las peticiones
en ese caso.
El `defaultBackend` es una opción de configuración convencional
del [controlador Ingress ](/docs/concepts/services-networking/ingress-controllers)
y no se especifica en tus recursos del Ingress.
Si no se especifican reglas `.spec.rules`, se debe
especificar `.spec.defaultBackend`.
Si no se establece un `defaultBackend`, las peticiones que no coincidan con
ninguna de las reglas las decidirá el controlador ingress (consulta la
documentación de tu controlador de ingress para saber cómo maneja este caso).
Si ninguno de los hosts o rutas coincide con la petición HTTP en los objetos Ingress,
el tráfico será enrutado a tu backend predeterminado.
### Resource backends {#resource-backend}
Un `Resource` backend es una referencia de objeto
(ObjectRef en inglés)
a otro recurso de Kubernetes dentro del mismo espacio de nombres que el objeto
Ingress.
Este `Resource` es mutuamente exclusivo con el Service,
y la validación fallará si ambos se especifican.
Un uso común para un `Resource` backend es para ingresar datos a un backend de almacenamiento de datos con activos estáticos.
{{% code_sample file="service/networking/ingress-resource-backend.yaml" %}}
Luego de crear el Ingress mencionado arriba,
puedes verlo con el siguiente comando:
```bash
kubectl describe ingress ingress-resource-backend
```
```
Name: ingress-resource-backend
Namespace: default
Address:
Default backend: APIGroup: k8s.example.com, Kind: StorageBucket, Name: static-assets
Rules:
Host Path Backends
---- ---- --------
*
/icons APIGroup: k8s.example.com, Kind: StorageBucket, Name: icon-assets
Annotations: <none>
Events: <none>
```
### Tipos de ruta
Se requiere que cada ruta de un Ingress tenga un tipo de ruta correspondiente.
Las Rutas que no incluyen un `pathType` explícito fallarán la validación.
Hay 3 tipos de rutas soportadas:
* `ImplementationSpecific`: Con este tipo de ruta, la coincidencia depende de la
IngressClass.
Las implementaciones pueden tratar esto como un `pathType` separado o
tratarlas de forma idéntica a los tipos de ruta `Prefix` o `Exact`.
* `Exact`: Coincide la ruta de la URL exactamente con sensibilidad a mayúsculas
y minúsculas.
* `Prefix`: Coincide basado en el prefijo de una ruta URL dividida por `/`.
La coincidencia es sensible a mayúsculas y minúsculas, y hecha en un elemento
de la ruta por elemento.
Un elemento de la ruta refiere a la lista de etiquetas en la ruta dividida por
el separador `/`.
Una petición es una coincidencia para la ruta _p_ si cada _p_ es un elemento
prefijo de _p_ de la ruta requerida.
{{< note >}}
Si el último elemento de una ruta es una subcadena de caracteres del último
elemento de la solicitud de ruta, no es una coincidencia
(por ejemplo: `/foo/bar`
coincide con `/foo/bar/baz`, pero no coincide con `/foo/barbaz`).
{{< /note >}}
### Ejemplos
| Tipo | Ruta(s) | Ruta de la(s) peticion(es) | ¿Coincide? |
|----------|-----------------------------------|----------------------------|----------------------------------------|
| Prefijo | `/` | (todas las rutas) | Sí |
| Exacto | `/foo` | `/foo` | Si |
| Exacto | `/foo` | `/bar` | No |
| Exacto | `/foo` | `/foo/` | No |
| Exacto | `/foo/` | `/foo` | No |
| Prefijo | `/foo` | `/foo`, `/foo/` | Si |
| Prefijo | `/foo/` | `/foo`, `/foo/` | Si |
| Prefijo | `/aaa/bb` | `/aaa/bbb` | No |
| Prefijo | `/aaa/bbb` | `/aaa/bbb` | Si |
| Prefijo | `/aaa/bbb/` | `/aaa/bbb` | Si, ignora la barra diagonal |
| Prefijo | `/aaa/bbb` | `/aaa/bbb/` | Si, coincide con barra diagonal |
| Prefijo | `/aaa/bbb` | `/aaa/bbb/ccc` | Si, coincide con la subruta |
| Prefijo | `/aaa/bbb` | `/aaa/bbbxyz` | No, no coincide con el prefijo de cadena |
| Prefijo | `/`, `/aaa` | `/aaa/ccc` | Si, coincide con el prefijo `/aaa` |
| Prefijo | `/`, `/aaa`, `/aaa/bbb` | `/aaa/bbb` | Si, coincide con el prefijo `/aaa/bbb` |
| Prefijo | `/`, `/aaa`, `/aaa/bbb` | `/ccc` | Si, coincide con el prefijo`/` |
| Prefijo | `/aaa` | `/ccc` | No, usa el backend predeterminado |
| Mezclado | `/foo` (Prefijo), `/foo` (Exacto) | `/foo` | Si, prefiere la coincidencia exacta |
#### Múltiples coincidencias
En algunos casos,
muchas rutas dentro de un Ingress coincidirán con una petición.
En esos casos,
la precedencia se le dará al primero con la ruta más larga que coincide.
Si dos rutas todavía coinciden por igual, se le dará precedencia a las rutas con
una coincidencia de ruta exacta sobre las rutas que contienen prefijos.
## Comodines Hostname
Los hosts pueden ser coincidencias exactas
(por ejemplo “`foo.bar.com`”) o un comodín (por ejemplo “`*.foo.com`”).
Las coincidencias precisas requieren que el encabezado `host` coincida con el
campo `host`.
Las coincidencias de comodín requieren que el encabezado `host` sea igual al
sufijo de la regla del comodín.
| Host | Encabezado Host | ¿Coincidencia? |
|-------------|-------------------|-----------------------------------------------------|
| `*.foo.com` | `bar.foo.com` | Coincide basado en el sufijo común |
| `*.foo.com` | `baz.bar.foo.com` | No coincide, el comodín solo cubre una etiqueta DNS |
| `*.foo.com` | `foo.com` | No coincide, el comodín solo cubre una etiqueta DNS |
{{% code_sample file="service/networking/ingress-wildcard-host.yaml" %}}
## La Clase Ingress
Los Ingress pueden ser implementados por distintos controladores,
comúnmente con una configuración distinta.
Cada Ingress debería especificar una clase,
una referencia a un recurso IngressClass que contiene información adicional
incluyendo el nombre del controlador que debería implementar la clase.
{{% code_sample file="service/networking/external-lb.yaml" %}}
El campo `.spec.parameters` de un IngressClass te permite hacer referencia a
otro recurso que proporciona la configuración relacionada con esa IngressClass.
El tipo específico de parámetros a usar depende del controlador de Ingress que
especificas en el campo `spec.controller` de la IngressClass.
### Alcance de IngressClass
Dependiendo de tu controlador de ingress, podrías ser capaz de usar parámetros
que se establecen en todo el clúster, o solamente para un namespace.
{{< tabs name="tabs_ingressclass_parameter_scope" >}}
{{% tab name="Clúster" %}}
El alcance por defecto de los parámetros IngressClass es para todo el clúster.
Si estableces el campo `spec.parameters` y no estableces el
campo `spec.parameters.scope`,
entonces el IngressClass se refiere al recurso cuyo alcance es todo el clúster.
El atributo `kind` (en combinación con el `apiGroup`)
de los parámetros se refiere a la API con alcance a todo el clúster
(posiblemente un recurso personalizado), y el `name` de los parámetros
identifica al recurso del clúster específico para esa API.
Por ejemplo:
```yaml
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-1
spec:
controller: example.com/ingress-controller
parameters:
# Los parámetros para este IngressClass se especifican en un
# ClusterIngressParameter (API group k8s.example.net) llamado
# "external-config-1". Esta definición le indica a Kubernetes
# de buscar por un parámetro de recurso con alcance a todo el clúster.
scope: Cluster
apiGroup: k8s.example.net
kind: ClusterIngressParameter
name: external-config-1
```
{{% /tab %}}
{{% tab name="Namespaced" %}}
{{< feature-state for_k8s_version="v1.23" state="stable" >}}
Si estableces el campo `spec.parameters` y el `spec.parameters.scope`
al `Namespace`,
entonces el IngressClass se refiere al recurso cuyo alcance es el namespace.
También debes establecer el campo `namespace` dentro de `spec.parameters` con el
Namespace que contiene los parámetros que quieres usar.
El atributo `kind` (en combinación con `apiGroup`)
de los parámetros se refiere a la API restringida por un Namespace (por ejemplo:
ConfigMap), y el `name` de los parámetros identifica al recurso específico en el
namespace que has especificado en `namespace`.
Los parámetros con alcance al Namespace ayudan al operador del clúster a delegar
el control sobre la configuración
(por ejemplo, ajustes del balanceador de cargas, definición de una API gateway)
que se usa para una carga de trabajo.
Si utilizas un parámetro con alcance al Namespace entonces:
- El equipo operador del clúster necesita aprobar los cambios de un equipo
distinto cada vez que se aplica un nuevo cambio a la configuración.
- O el equipo operador del clúster debe definir específicamente estos controles
de acceso, tales como asociaciones de
roles [RBAC](/docs/reference/access-authn-authz/rbac/) y mapeos, que permitan
a la aplicación hacer cambios al recurso de parámetros con alcance al clúster.
La API de la IngressClass por sí misma siempre tiene alcance al clúster.
Aquí hay un ejemplo de una IngressClass que hace referencia a parámetros que
están restringidos por un Namespace:
```yaml
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb-2
spec:
controller: example.com/ingress-controller
parameters:
# Los parámetros para esta IngressClass se especifican en un
# IngressParameter (API group k8s.example.com) llamado "external-config",
# que está en el namespace "external-configuration".
scope: Namespace
apiGroup: k8s.example.com
kind: IngressParameter
namespace: external-configuration
name: external-config
```
{{% /tab %}}
{{< /tabs >}}
### Anotación deprecada
Antes que el recurso IngressClass y el campo `ingressClassName` se añadieran a
Kubernetes
1.18,
las clases Ingress se especificaban con una
anotación `kubernetes.io/ingress.class` en el Ingress.
Esta anotación nunca se definió formalmente,
pero era ampliamente soportada por los controladores de Ingress.
El nuevo campo `ingressClassName` en los recursos Ingress es un reemplazo para
esa anotación, pero no es un equivalente directo.
Mientras que la anotación se utilizaba generalmente para hacer referencia al
nombre del controlador de Ingress que debería implementar el Ingress, el campo
es una referencia a un recurso IngressClass que contiene configuración adicional
del Ingress, incluyendo el nombre del controlador Ingress.
### IngressClass por defecto {#default-ingress-class}
Puedes marcar un ingressClass en particular por defecto para tu clúster.
Establecer la anotación `ingressclass.kubernetes.io/is-default-class` a `true`
en un recurso IngressClass
asegurará que los nuevos Ingress sin un campo `ingressClassName` especificado
sean asignados a esta IngressClass por defecto.
{{< caution >}}
Si tienes más de una IngressClass marcada por defecto en tu clúster,
el controlador de admisión impide crear objetos que no tienen
un `ingressClassName` especificado.
Puedes resolver esto asegurándote que como máximo 1 IngressClass está marcado
como el predeterminado en tu clúster.
{{< /caution >}}
Existen algunos controladores de ingress,
que funcionan sin una definición de una `ingressClass`.
Por ejemplo, el controlador Ingress-NGINX se puede configurar con
una [opción](https://kubernetes.github.io/ingress-nginx/#what-is-the-flag-watch-ingress-without-class)
`--watch-ingress-without-class`.
Sin embargo,
se [recomienda](https://kubernetes.github.io/ingress-nginx/#i-have-only-one-instance-of-the-ingresss-nginx-controller-in-my-cluster-what-should-i-do)
especificar el `IngressClass` predeterminado:
{{% code_sample file="service/networking/default-ingressclass.yaml" %}}
## Tipos de Ingress
### Ingress respaldado por un único servicio {#single-service-ingress}
Hay conceptos existentes de Kubernetes que te permiten exponer un Service
único
(mirar [alternativas](#alternativas)).
También puedes hacerlo con un Ingress especificando un *backend predeterminado*
sin reglas.
{{% code_sample file="service/networking/test-ingress.yaml" %}}
Si lo creas usando `kubectl apply -f` podrías mirar el estado del Ingress que
has creado:
```bash
kubectl get ingress test-ingress
```
```
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
```
Donde `203.0.113.123` es la IP asignada por el controlador Ingress para
satisfacer este Ingress.
{{< note >}}
Los controladores de Ingress y los balanceadores de carga pueden tardar un
minuto o dos en asignar una dirección IP.
Hasta entonces, se podrá ver la dirección marcada como `<pending>`.
{{< /note >}}
### Abanico Simple
Una configuración de abanico enruta el tráfico de una única dirección IP a más
de un Service,
basado en la URI HTTP solicitada.
Un Ingress te permite tener el número de balanceadores de carga al mínimo.
Por ejemplo, una configuración como:
{{< figure src="/docs/images/ingressFanOut.svg" alt="ingress-fanout-diagram" class="diagram-large" caption="Figure. Ingress Fan Out" link="https://mermaid.live/edit#pako:eNqNUslOwzAQ_RXLvYCUhMQpUFzUUzkgcUBwbHpw4klr4diR7bCo8O8k2FFbFomLPZq3jP00O1xpDpjijWHtFt09zAuFUCUFKHey8vf6NE7QrdoYsDZumGIb4Oi6NAskNeOoZJKpCgxK4oXwrFVgRyi7nCVXWZKRPMlysv5yD6Q4Xryf1Vq_WzDPooJs9egLNDbolKTpT03JzKgh3zWEztJZ0Niu9L-qZGcdmAMfj4cxvWmreba613z9C0B-AMQD-V_AdA-A4j5QZu0SatRKJhSqhZR0wjmPrDP6CeikrutQxy-Cuy2dtq9RpaU2dJKm6fzI5Glmg0VOLio4_5dLjx27hFSC015KJ2VZHtuQvY2fuHcaE43G0MaCREOow_FV5cMxHZ5-oPX75UM5avuXhXuOI9yAaZjg_aLuBl6B3RYaKDDtSw4166QrcKE-emrXcubghgunDaY1kxYizDqnH99UhakzHYykpWD9hjS--fEJoIELqQ" >}}
Requeriría un Ingress como este:
{{% code_sample file="service/networking/simple-fanout-example.yaml" %}}
Cuando creas el Ingress con `kubectl apply -f`:
```shell
kubectl describe ingress simple-fanout-example
```
```
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
```
El controlador de Ingress aprovisiona un balanceador de cargas específico para
la implementación que satisface al Ingress,
mientras los Services (`service1`, `service2`) existan.
Cuando sea así,
podrás ver la dirección del balanceador de cargas en el campo de dirección.
{{< note >}}
Dependiendo
del [controlador de Ingress](/docs/concepts/services-networking/ingress-controllers/)
que uses, puede que necesites crear
un [Service](/es/docs/concepts/services-networking/service/) default-http-backend.
{{< /note >}}
### Hosting virtual basado en nombre
Los hostings virtuales basados en el nombre soportan enrutado de tráfico HTTP
a nombres hosts múltiples con la misma dirección IP.
{{< figure src="/docs/images/ingressNameBased.svg" alt="ingress-namebase-diagram" class="diagram-large" caption="Figure. Ingress Name Based Virtual hosting" link="https://mermaid.live/edit#pako:eNqNkl9PwyAUxb8KYS-atM1Kp05m9qSJJj4Y97jugcLtRqTQAPVPdN_dVlq3qUt8gZt7zvkBN7xjbgRgiteW1Rt0_zjLNUJcSdD-ZBn21WmcoDu9tuBcXDHN1iDQVWHnSBkmUMEU0xwsSuK5DK5l745QejFNLtMkJVmSZmT1Re9NcTz_uDXOU1QakxTMJtxUHw7ss-SQLhehQEODTsdH4l20Q-zFyc84-Y67pghv5apxHuweMuj9eS2_NiJdPhix-kMgvwQShOyYMNkJoEUYM3PuGkpUKyY1KqVSdCSEiJy35gnoqCzLvo5fpPAbOqlfI26UsXQ0Ho9nB5CnqesRGTnncPYvSqsdUvqp9KRdlI6KojjEkB0mnLgjDRONhqENBYm6oXbLV5V1y6S7-l42_LowlIN2uFm_twqOcAW2YlK0H_i9c-bYb6CCHNO2FFCyRvkc53rbWptaMA83QnpjMS2ZchBh1nizeNMcU28bGEzXkrV_pArN7Sc0rBTu" >}}
El siguiente Ingress le dice al balanceador de cargas de respaldo de enrutar las
peticiones basadas en
el [encabezado del Host ](https://tools.ietf.org/html/rfc7230#section-5.4).
{{% code_sample file="service/networking/name-virtual-host-ingress.yaml" %}}
Si creas un recurso Ingress sin ningún host definido en las reglas,
luego cualquier tráfico web a la dirección IP de tu controlador Ingress puede
coincidir sin requerir un host virtual basado en el nombre.
Por ejemplo, el siguiente Ingress enruta el tráfico solicitado
para `first.bar.com` a `service1`, `second.bar.com` a `service2`,
y cualquier tráfico cuyo encabezado de petición del host no coincida
con `first.bar.com` y `second.bar.com` a `service3`.
{{% code_sample file="service/networking/name-virtual-host-ingress-no-third-host.yaml" %}}
### TLS
Puedes segurizar un Ingress especificando un {{< glossary_tooltip term_id="secret" >}} que contiene una clave privada TLS y un certificado.
El recurso Ingress solo soporta un puerto TLS,
el 443,
y asume la terminación TLS en el punto del ingress
(El tráfico al Service y sus Pods es en texto plano).
Si la sección de configuración TLS especifica hosts diferentes,
se multiplexan en el mismo puerto de acuerdo con el hostname especificado a
través de la extensión TLS SNI (teniendo el cuenta que el controlador de Ingress
soporte SNI).
El secreto TLS debe contener claves llamadas `tls.crt` y `tls.key` que contiene
el certificado y llave privad para usar TLS.
Por ejemplo:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
```
Al hacer referencia a este secreto en un Ingress le indica al controlador
Ingress de segurizar el canal desde el cliente al balanceador de cargas usando
TLS.
Necesitas asegurarte que el secreto TLS que has creado viene de un certificado que
contiene un nombre común (CN), también conocido como Nombre de dominio
calificado (FQDN en inglés)
para `https-example.foo.com`.
{{< note >}}
Ten en cuenta que TLS no funcionará en la regla predeterminada porque los
certificados estarían emitidos para todos los sub-dominios posibles.
Por lo tanto, los `hosts` en la sección `tls` tienen que coincidir
explícitamente con el `host` en la sección `rules`.
{{< /note >}}
{{% code_sample file="service/networking/tls-example-ingress.yaml" %}}
{{< note >}}
Hay una diferencia entre las características TLS soportadas por varios
controladores Ingress.
Mira la documentación
en [nginx](https://kubernetes.github.io/ingress-nginx/user-guide/tls/), [GCE](https://git.k8s.io/ingress-gce/README.md#frontend-https),
o cualquier otro controlador Ingress específico de plataforma para entender cómo
funciona el TLS en tu entorno.
{{< /note >}}
### Balanceo de cargas {#load-balancing}
Un controlador de Ingress está configurado por defecto con algunos ajustes de
política de balanceo de cargas que aplica a todos los Ingress, como los
algoritmos de balanceo de cargas, esquema de pesos del backend y otros.
Otros conceptos más avanzados de balanceo de cargas (ej., sesiones persistentes,
pesos dinámicos) no están expuestos todavía a través del Ingress.
En su lugar, obtienes estas características a través del balanceador de cargas
usado por un Service.
Vale la pena apuntar que aunque las revisiones de salud no se exponen
directamente a través del Ingress, existen conceptos paralelos en Kubernetes
tales
como [readiness probes](/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)
que permiten lograr el mismo resultado final.
Revisa la documentación específica del controlador para conocer cómo manejar estas
revisiones de salud (por ejemplo:
[nginx](https://git.k8s.io/ingress-nginx/README.md),
o [GCE](https://git.k8s.io/ingress-gce/README.md#health-checks)).
## Actualizando un Ingress
Para actualizar un Ingress existente a un nuevo Host,
puedes actualizarlo editando el recurso:
```shell
kubectl describe ingress test
```
```
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 35s loadbalancer-controller default/test
```
```shell
kubectl edit ingress test
```
Esto muestra un editor con la configuración existente en formato YAML.
Modifícalo para incluir el nuevo Host:
```yaml
spec:
rules:
- host: foo.bar.com
http:
paths:
- backend:
service:
name: service1
port:
number: 80
path: /foo
pathType: Prefix
- host: bar.baz.com
http:
paths:
- backend:
service:
name: service2
port:
number: 80
path: /foo
pathType: Prefix
#..
```
Luego de guardar tus cambios,
kubectl actualiza el recurso en el servidor API, que le indica al controlador
Ingress de reconfigurar el balanceador de cargas.
Verifica esto:
```shell
kubectl describe ingress test
```
```
Name: test
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:80 (10.8.0.90:80)
bar.baz.com
/foo service2:80 (10.8.0.91:80)
Annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 45s loadbalancer-controller default/test
```
Puedes lograr el mismo resultado invocando `kubectl replace -f` en un fichero
YAML de Ingress.
## Fallos a través de zonas de disponibilidad
Las técnicas para distribuir el tráfico entre dominios de falla difieren entre
los proveedores de la nube.
Revisa la documentación
del [Ingress controller](/docs/concepts/services-networking/ingress-controllers)
relevante para detalles.
## Alternativas
Puedes exponer un Service de muchas maneras que no involucran directamente el
recurso Ingress:
* Usa
un [Service.Type=LoadBalancer](es/docs/concepts/services-networking/service/#loadbalancer)
* Usa
un [Service.Type=NodePort](es/docs/concepts/services-networking/service/#nodeport)
## {{% heading "whatsnext" %}}
* Aprende sobre la API
del [Ingress](/docs/reference/kubernetes-api/service-resources/ingress-v1/)
* Aprende
sobre [Ingress controllers](/docs/concepts/services-networking/ingress-controllers/)
* [Configurar un Ingress en Minikube con el controlador NGINX](/docs/tasks/access-application-cluster/ingress-minikube/)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
---
title: Ingress
id: ingress
date: 2018-04-12
full_link: /docs/concepts/services-networking/ingress/
short_description: >
Un objeto de la API que administra el acceso externo a los servicios en un clúster, típicamente HTTP.
aka:
tags:
- networking
- architecture
- extension
---
Un objeto de la API que administra el acceso externo a los servicios en un clúster, típicamente HTTP.
<!--more-->
Un Ingress podría proveer balanceo de cargas, terminación SSL y hosting virtual basado en nombres.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
labels:
app.kubernetes.io/component: controller
name: nginx-example
annotations:
ingressclass.kubernetes.io/is-default-class: "true"
spec:
controller: k8s.io/ingress-nginx

View File

@ -0,0 +1,18 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
spec:
rules:
- host: hello-world.info
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: web
port:
number: 8080

View File

@ -0,0 +1,10 @@
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb

View File

@ -0,0 +1,20 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
spec:
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets

View File

@ -0,0 +1,26 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-wildcard-host
spec:
rules:
- host: "foo.bar.com"
http:
paths:
- pathType: Prefix
path: "/bar"
backend:
service:
name: service1
port:
number: 80
- host: "*.foo.com"
http:
paths:
- pathType: Prefix
path: "/foo"
backend:
service:
name: service2
port:
number: 80

View File

@ -0,0 +1,18 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx-example
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80

View File

@ -0,0 +1,35 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: first.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
- http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service3
port:
number: 80

View File

@ -0,0 +1,26 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80

View File

@ -0,0 +1,23 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080

View File

@ -0,0 +1,10 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80

View File

@ -0,0 +1,20 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80

View File

@ -972,7 +972,7 @@ Plus d'exemples sont disponibles [ici](https://github.com/kubernetes/examples/tr
## Utilisation de subPath
Parfois, il est utile de partager un volume pour plusieurs utilisations dans un même Pod.
La propriété `volumeMounts.subPath` peut être utilisée pour spécifier un sous-chemin à l'intérieur du volume référencé au lieu de sa racine.
La propriété `volumeMounts[*].subPath` peut être utilisée pour spécifier un sous-chemin à l'intérieur du volume référencé au lieu de sa racine.
Voici un exemple d'un Pod avec une stack LAMP (Linux Apache Mysql PHP) utilisant un unique volume partagé.
Le contenu HTML est mappé à son dossier `html` et les bases de données seront stockées dans son dossier `mysql` :

View File

@ -180,7 +180,6 @@ Vous pouvez utiliser un [ContainerPort](/docs/reference/generated/kubernetes-api
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
@ -200,7 +199,6 @@ Ainsi, l'exemple précédent deviendrait :
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:

View File

@ -9,7 +9,7 @@ weight: 10
<body>
<link href="/docs/tutorials/kubernetes-basics/public/css/styles.css" rel="stylesheet">
<link href="/docs/tutorials/kubernetes-basics/public/css/styles.css" rel="stylesheet">
<div class="layout" id="top">
@ -65,13 +65,12 @@ weight: 10
<br>
<div class="row">
<p class="col-md-8">
<div class="col-md-8">
<p>आप कुबेरनेट्स कमांड लाइन इंटरफेस, <b>kubectl</b> का उपयोग करके डिप्लॉयमेंट बना और प्रबंधित कर सकते हैं। kubectl क्लस्टर के साथ बातचीत करने के लिए कुबेरनेट्स एपीआई का उपयोग करता है। इस मॉड्यूल में, आप कुबेरनेट्स क्लस्टर पर आपके एप्लिकेशन चलाने वाले डिप्लॉयमेंट बनाने के लिए आवश्यक सबसे सामान्य kubectl कमांड सीखेंगे।</p>
<p>जब आप कोई डिप्लॉयमेंट बनाते हैं, तो आपको अपने एप्लिकेशन के लिए कंटेनर इमेज और चलाने के लिए इच्छित प्रतिकृतियों की संख्या निर्दिष्ट करने की आवश्यकता होगी। आप अपने कामकाज को अपडेट करके बाद में उस जानकारी को बदल सकते हैं; बूटकैंप के मॉड्यूल <a href="/hi//docs/tutorials/kubernetes-basics/scale/scale-intro/">5</a> और <a href="/hi/docs/tutorials/kubernetes-basics/update/update-intro/" >6</a> चर्चा करते हैं कि आप अपने डिप्लॉयमेंट को कैसे स्केल और अपडेट कर सकते हैं।</p>
</div>
<div class="col-md-4">
<div class="content__box content__box_fill">

View File

@ -899,7 +899,7 @@ Lebih banyak contoh dapat ditemukan [di sini](https://github.com/kubernetes/exam
## Menggunakan subPath
Terkadang, diperlukan untuk membagi sebuah Volume untuk banyak kegunaan berbeda pada sebuah Pod. Kolom `volumeMounts.subPath` dapat digunakan untuk merinci sebuah _sub-path_ di dalam Volume yang dimaksud, menggantikan _root path_-nya.
Terkadang, diperlukan untuk membagi sebuah Volume untuk banyak kegunaan berbeda pada sebuah Pod. Kolom `volumeMounts[*].subPath` dapat digunakan untuk merinci sebuah _sub-path_ di dalam Volume yang dimaksud, menggantikan _root path_-nya.
Berikut contoh sebuah Pod dengan _stack_ LAMP (Linux Apache Mysql PHP) menggunakan sebuah Volume yang dibagi-bagi.
Isi HTML-nya dipetakan ke dalam direktori `html`-nya, dan _database_-nya akan disimpan di dalam direktori `mysql`-nya.
@ -1099,7 +1099,7 @@ Untuk lebih lanjut, dapat ditemukan [di sini](https://github.com/kubernetes/comm
_Mount propagation_ memungkinkan berbagi volume-volume yang ditambatkan oleh sebuah Container kepada Container-container lain di dalam Pod yang sama, atau bahkan pada Pod lainnya di dalam Node yang sama.
_Mount propagation_ dari sebuah volume diatur oleh kolom `mountPropagation` di dalam `Container.volumeMounts`.
_Mount propagation_ dari sebuah volume diatur oleh kolom `mountPropagation` di dalam `containers[*].volumeMounts`.
Nilai-nilainya adalah sebagai berikut:
* `None` - Tambatan volume ini tidak akan menerima apapun tambatan selanjutnya yang ditambatkan pada volume ini atau apapun sub-direktori yang dimilikinya oleh _host_.

View File

@ -0,0 +1,503 @@
---
title: Распределение подов по узлам
content_type: concept
weight: 20
---
<!-- overview -->
Можно настроить {{< glossary_tooltip text="под" term_id="pod" >}} так, чтобы тот мог запускаться олько_ на определенном(-ых) {{< glossary_tooltip text="узле(-ах)" term_id="node" >}} или _предпочитал_ определенную группу узлов.
Сделать это можно несколькими способами, при этом все рекомендуемые подходы используют [селекторы лейблов](/ru/docs/concepts/overview/working-with-objects/labels/) для выбора.
Зачастую нужды в подобных ограничениях нет; {{< glossary_tooltip text="планировщик" term_id="kube-scheduler" >}} автоматически размещает поды оптимальным образом (например, распределяет их по узлам, чтобы они не оказались все на одном узле с дефицитом ресурсов).
Однако в некоторых обстоятельствах возможность контролировать, куда именно попадет под, может пригодиться. Например, она поможет запланировать под на узел с быстрым SSD-хранилищем или разместить два активно взаимодействующих друг с другом пода в одной зоне доступности.
<!-- body -->
Для планирования подов на определенные узлы можно использовать любой из методов:
* Поле [nodeSelector](#nodeselector) и [лейблы узлов](#built-in-node-labels);
* Правила [совместного/раздельного существования (affinity и anti-affinity)](#affinity-and-anti-affinity);
* Поле [nodeName](#nodename);
* [Ограничения на топологию распределения подов](#pod-topology-spread-constraints).
## Лейблы узлов {#built-in-node-labels}
Как и у многих других объектов Kubernetes, у узлов есть [лейблы](/ru/docs/concepts/overview/working-with-objects/labels/). Их можно [навешивать вручную](/docs/tasks/configure-pod-container/assign-pods-nodes/#add-a-label-to-a-node).
Kubernetes также навешивает [стандартный набор лейблов](/docs/reference/node/node-labels/) на все узлы кластера.
{{<note>}}
Значения этих лейблов зависят от облачного провайдера, поэтому на них нельзя полагаться.
Например, в одних окружениях значение `kubernetes.io/hostname` может совпадать с именем узла, в других — отличаться.
{{</note>}}
### Изоляция узла/ограничение его использования
Лейблы узлов позволяют размещать поды на определенные узлы или группы узлов. С их помощью можно планировать поды на узлы с определенными требованиями к изоляции, безопасности или соответствию нормативным положениям.
При использовании лейблов для изоляции узлов следует выбирать ключи лейблов, которые {{<glossary_tooltip text="kubelet" term_id="kubelet">}} не может изменить. В этом случае взломанный узел не сможет навесить на себя эти лейблы в надежде, что планировщик разместит на него рабочие нагрузки.
[Admission-плагин NodeRestriction](/docs/reference/access-authn-authz/admission-controllers/#noderestriction) не позволяет kubelet'у устанавливать или изменять лейблы с префиксом `node-restriction.kubernetes.io/`.
Чтобы использовать этот префикс для изоляции узла:
1. Убедитесь, что используется [авторизатор узлов](/docs/reference/access-authn-authz/node/) и _включен_ admission-плагин `NodeRestriction`.
2. Добавьте лейблы с префиксом `node-restriction.kubernetes.io/` к узлам и используйте их в [селекторах узлов](#nodeselector). Например, `example.com.node-restriction.kubernetes.io/fips=true` или `example.com.node-restriction.kubernetes.io/pci-dss=true`.
## nodeSelector
`nodeSelector` — простейшая рекомендуемая форма настроек выбора узлов.
Можно добавить поле `nodeSelector` в спецификацию пода и перечислить в нем [лейблы узлов](#built-in-node-labels), которые подходят для развертывания пода. В этом случае Kubernetes будет планировать под только на узлы со всеми указанными лейблами.
Дополнительную информацию см. в разделе [Размещение подов на узлах](/docs/tasks/configure-pod-container/assign-pods-nodes).
## Правила совместного/раздельного существования (affinity и anti-affinity) {#affinity-and-anti-affinity}
`nodeSelector` — самый простой способ развернуть поды на узлах с определенными лейблами. Правила совместного/раздельного существования расширяют типы ограничений, которые можно накладывать. Вот некоторые из их преимуществ:
* Язык правил affinity/anti-affinity более выразителен. `nodeSelector` выбирает узлы только со всеми указанными лейблами. Правила affinity/anti-affinity расширяют логику выбора и делают ее более гибкой.
* Правило может быть *мягким* (soft) или *предпочтительным* (preferred). В этом случае планировщик все равно запланирует под, даже если подходящего узла для него не найдется.
* При планировании пода планировщик может учитывать лейблы других подов, запущенных на узле (или в иной топологической области), а не только лейблы самого узла. Это позволяет формулировать правила, определяющие сосуществование подов на узле.
Правила совместного существования (affinity) бывают двух типов:
* *Правила для узлов* (node affinity) работают подобно полю `nodeSelector`, но более выразительны. Кроме того, можно задавать мягкие правила.
* *Правила для подов* (inter-pod affinity и anti-affinity) позволяют при планировании учитывать лейблы других подов.
### Правила совместного существования для узлов (node affinity) {#node-affinity}
Правила совместного существования для узлов концептуально похожи на `nodeSelector`. С помощью лейблов они позволяют ограничивать список узлов, на которые может быть запланирован под. Существует два типа таких правил:
* `requiredDuringSchedulingIgnoredDuringExecution`: Планировщик не может запланировать под, если правило не выполнено. Работает как `nodeSelector`, но с более выразительным синтаксисом.
* `preferredDuringSchedulingIgnoredDuringExecution`: Планировщик пытается найти узел, который соответствует правилу. Если подходящий узел не удается найти, планировщик все равно планирует под.
{{<note>}}
В типах выше `IgnoredDuringExecution` означает, что под продолжит свою работу, если лейблы узлов изменятся после того, как Kubernetes запланировал его.
{{</note>}}
Задавать правила совместного существования для узлов можно с помощью поля `.spec.affinity.nodeAffinity` в спецификации пода.
В качестве примера рассмотрим следующую спецификацию пода:
{{< codenew file="pods/pod-with-node-affinity.yaml" >}}
В этом примере применяются следующие правила:
* У узла *должен* быть лейбл с ключом `topology.kubernetes.io/zone`, и значение этого лейбла *должно* быть либо `antarctica-east1`, либо `antarctica-west1`.
* *Предпочтительно*, чтобы у узла был лейбл с ключом `another-node-label-key` и значением `another-node-label-value`.
Можно использовать поле `operator` для указания логического оператора, который Kubernetes будет применять при интерпретации правил. Доступны `In`, `NotIn`, `Exists`, `DoesNotExist`, `Gt` и `Lt`.
Узнать больше о том, как они работают, можно в подразделе [Операторы](/#operators).
`NotIn` и `DoesNotExist` позволяют задавать правила раздельного существования (anti-affinity) для узла.
Кроме того, можно использовать [taint'ы узлов](/docs/concepts/scheduling-eviction/taint-and-toleration/), чтобы "отвадить" поды от определенных узлов.
{{<note>}}
Когда указаны и `nodeSelector`, и `nodeAffinity`, под будет запланирован на узел только в том случае, если *оба* этих условия удовлетворены.
Если указать несколько условий `nodeSelectorTerms`, привязанных к типам `nodeAffinity`, то под может быть запланирован на узел, если удовлетворяется одно из указанных условий `nodeSelectorTerms`. К условиям применяется логическое ИЛИ.
Если задать несколько выражений в поле `matchExpressions` для одного условия `nodeSelectorTerms`, под будет запланирован на узел только если удовлетворены все выражения `matchExpressions`. К условиям применяется логическое И.
{{</note>}}
Дополнительную информацию см. в разделе [Размещаем поды на узлы с помощью Node Affinity](/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/).
#### Вес правил совместного существования
Для каждого правила типа `preferredDuringSchedulingIgnoredDuringExecution` можно указать вес `weight` в диапазоне от 1 до 100. Найдя несколько узлов, удовлетворяющих всем остальным требованиям для планирования пода, планировщик перебирает предпочтительные правила, которым удовлетворяет узел, и суммирует их веса.
Итоговая сумма добавляется к оценке, полученной при анализе других параметров, влияющих на приоритет узла. Принимая решение о размещении пода, планировщик отдает предпочтение узлам с наибольшей суммарной оценкой.
В качестве примера рассмотрим следующую спецификацию пода:
{{< codenew file="pods/pod-with-affinity-anti-affinity.yaml" >}}
Если правилу `preferredDuringSchedulingIgnoredDuringExecution` соответствуют два узла (один — с лейблом `label-1:key-1`, другой — с `label-2:key-2`), планировщик считает вес `weight` каждого узла и добавляет его к другим оценкам для этого узла. Под планируется на узел с наивысшей итоговой оценкой.
{{<note>}}
Чтобы Kubernetes смог запланировать поды в этом примере, необходимо, чтобы существовали узлы с лейблом `kubernetes.io/os=linux`.
{{</note>}}
#### Правила совместного существования и профили планирования
{{< feature-state for_k8s_version="v1.20" state="beta" >}}
При настройке нескольких [профилей планирования](/docs/reference/scheduling/config/#multiple-profiles) можно связать профиль с правилами совместного существования для узлов (это удобно, когда профиль применяется к определенному набору узлов). Для этого необходимо добавить `addedAffinity` в поле `args` [плагина `NodeAffinity`](/docs/reference/scheduling/config/#scheduling-plugins) в [конфигурации планировщика](/docs/reference/scheduling/config/). Например:
```yaml
apiVersion: kubescheduler.config.k8s.io/v1beta3
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
- schedulerName: foo-scheduler
pluginConfig:
- name: NodeAffinity
args:
addedAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: scheduler-profile
operator: In
values:
- foo
```
Правило `addedAffinity` применяется ко всем подам с полем `.spec.schedulerName`, имеющим значение `foo-scheduler`, в дополнение к NodeAffinity, заданному в PodSpec. Таким образом, подходящие для пода узлы должны удовлетворять параметрам `addedAffinity` и правилам `.spec.NodeAffinity` пода.
Поскольку конечные пользователи не видят `addedAffinity`, результат применения этих правил может быть для них неожиданным. Используйте лейблы узлов, которые однозначно соотносятся с именем профиля планировщика.
{{< note >}}
Контроллер DaemonSet, [создающий поды для DaemonSet'ов](/docs/concepts/workloads/controllers/daemonset/#scheduled-by-default-scheduler), не поддерживает профили планирования. Контроллер DaemonSet создает поды, а штатный планировщик Kubernetes, размещая их, следит за соблюдением правил `nodeAffinity`.
{{< /note >}}
### Правила совместного/раздельного существования подов
Правила совместного/раздельного существования подов позволяют выбирать узлы для планирования в зависимости от лейблов **подов**, которые уже на этих узлах работают (вместо лейблов самих узлов).
Алгоритм работы правил совместного/раздельного существования подов можно описать так: "данный под олжен_ (или е должен_ в случае раздельного (anti-affinity) существования) размещаться на X, если на нем уже работает один или несколько подов, удовлетворяющих правилу Y", где X — топологический домен, например, узел, стойка, зона/регион облачного провайдера и т. п., а Y — правило, которое Kubernetes пытается удовлетворить.
Для задания правил Y используются [селекторы лейблов](/ru/docs/concepts/overview/working-with-objects/labels/#селекторы-меток) с необязательным связанным списком пространств имен. Для подов в Kubernetes указываются пространства имен, соответственно, их лейблы также оказываются неявно связаны с этими же пространствами имен. Любые селекторы лейблов для лейблов подов должны содержать пространства имен, в которых Kubernetes должен искать эти лейблы.
Топологический домен X задается с помощью `topologyKey` — ключа для лейбла узла, который система использует для обозначения домена. Примеры см. в разделе [Типичные лейблы, аннотации и taint'ы](/docs/reference/labels-annotations-taints/).
{{< note >}}
Обработка правил совместного/раздельного существования подов требует значительных ресурсов и может значительно замедлить планирование в больших кластерах. Их не рекомендуется использовать в кластерах, число узлов в которых превышает несколько сотен.
{{< /note >}}
{{< note >}}
Правила раздельного существования для подов требуют согласованности лейблов узлов. Другими словами, у каждого узла в кластере должен быть лейбл, относящий его к определенному ключу `topologyKey`. Отсутствие лейблов `topologyKey` у некоторых или всех узлов в кластере может привести к непредсказуемому поведению.
{{< /note >}}
#### Типы правил совместного/раздельного существования подов
По аналогии [c правилами для узлов](#node-affinity) существует два типа правил для подов:
* `requiredDuringSchedulingIgnoredDuringExecution`
* `preferredDuringSchedulingIgnoredDuringExecution`
Например, с помощью правила совместного существования `requiredDuringSchedulingIgnoredDuringExecution` можно заставить планировщик размещать поды, относящиеся к разным сервисам, в одной зоне облачного провайдера, поскольку они активно обмениваются данными друг с другом.
Аналогичным образом можно использовать правило раздельного существования `preferredDuringSchedulingIgnoredDuringExecution` для распределения подов по нескольким зонам облачного провайдера.
Для задания правил совместного существования предназначено поле `affinity.podAffinity` в спецификации пода.
Для задания правил раздельного существования предназначено поле `affinity.podAntiAffinity` в спецификации пода.
#### Планирование группы подов, связанных правилами совместного существования
Если планируемый под — первый в серии подов, связанных правилами совместного существования,
он может быть запланирован, если удовлетворит всем остальным правилам совместного существования. Чтобы подтвердить, что этот под — действительно первый,
проводится проверка, которая должна показать, что пространство имен и селектор этого пода уникальны в кластере (то есть нет других таких подов). Кроме того,
под должен соответствовать своим собственным правилам, а выбранный узел — всем запрошенным топологиям.
Это предотвращает тупиковую ситуацию, когда поды не могут запланироваться из-за того, что все они связаны правилами совместного существования.
#### Пример правил совместного/раздельного существования для пода {#an-example-of-a-pod-that-uses-pod-affinity}
Рассмотрим следующую спецификацию пода:
{{< codenew file="pods/pod-with-pod-affinity.yaml" >}}
В примере задается одно правило совместного существования подов, и одно — раздельного. Для совместного правила используется жесткий тип `requiredDuringSchedulingIgnoredDuringExecution`, для раздельного — мягкий `preferredDuringSchedulingIgnoredDuringExecution`.
Правило совместного существования гласит, что планировщик может разместить под на узел, только если тот находится в зоне с одним или более подами с лейблом `security=S1`.
Например, если есть кластер с выделенной зоной, назовем ее "V",
состоящей из узлов с лейблом `topology.kubernetes.io/zone=V`, планировщик может
назначить под на любой узел зоны V только если в этой зоне уже есть хотя бы один под
с лейблом `security=S1`. И наоборот, если в зоне V нет подов с лейблом `security=S1`,
планировщик не сможет назначить под на какой-либо из узлов в этой зоне.
Правило раздельного существования гласит, что планировщик при возможности не должен размещать под на узел, если тот находится в зоне с одним или более подами с лейблом `security=S2`.
Например, если есть кластер с выделенной зоной, назовем ее "R",
состоящей из узлов с лейблами `topology.kubernetes.io/zone=R`. Планировщик должен избегать
назначать поды на узлы из зоны R, если в ней уже есть по крайней мере один под
с лейблом `security=S2`. Соответственно, если в зоне R нет подов с лейблами `security=S2`,
правило раздельного существования не будет влиять на планирование подов в эту зону.
Больше примеров правил совместного/раздельного существования для подов можно найти в [рабочей документации](https://git.k8s.io/design-proposals-archive/scheduling/podaffinity.md).
Поле `operator` пода поддерживает значения `In`, `NotIn`, `Exists` и `DoesNotExist` при задании правил совместного/раздельного существования.
Узнать больше о том, как они работают, можно в подразделе [Операторы](/#operators).
В принципе, `topologyKey` может быть любым разрешенным лейблом-ключом со следующими исключениями по соображениям производительности и безопасности:
* При задании правил совместного/раздельного существования для подов пустое поле `topologyKey` не допускается как для `requiredDuringSchedulingIgnoredDuringExecution`, так и для `preferredDuringSchedulingIgnoredDuringExecution`.
* Для правил раздельного существования типа `requiredDuringSchedulingIgnoredDuringExecution` admission-контроллер разрешает использовать только `kubernetes.io/hostname` в качестве `topologyKey`. Для работы с кастомными топологиями admission-контроллер можно дополнить или совсем отключить его.
В дополнение к `labelSelector` и `topologyKey` можно опционально указать список пространств имен, которые должен выбирать `labelSelector`, с помощью поля `namespaces` на том же уровне, что `labelSelector` и `topologyKey`. Если поле `namespaces` опущено или пусто, по умолчанию выбирается пространство имен пода, в котором задаются правила совместного/раздельного существования.
#### Селектор пространств имен
{{< feature-state for_k8s_version="v1.24" state="stable" >}}
Подходящие пространства имен также можно выбрать с помощью `namespaceSelector`, который попытается найти лейбл в наборе пространств имен.
Условия совместного существования применяются к пространствам имен, выбранным как селектором `namespaceSelector`, так и полем `namespaces`.
Обратите внимание, что пустой селектор `namespaceSelector` ({}) выбирает все пространства имен, в то время как пустой или null-список `namespaces` и null-селектор `namespaceSelector` выбирает пространство имен пода, в котором правило задано.
#### matchLabelKeys
{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}}
{{< note >}}
<!-- UPDATE THIS WHEN PROMOTING TO BETA -->
Поле `matchLabelKeys` является полем альфа-уровня и по умолчанию отключено в
Kubernetes {{< skew currentVersion >}}.
Включить его можно с помощью [переключателя функциональности](/docs/reference/command-line-tools-reference/feature-gates/)
(feature gate) `MatchLabelKeysInPodAffinity`.
{{< /note >}}
Kubernetes включает необязательное поле `matchLabelKeys` для правил совместного (раздельного) существования подов.
В нем указываются ключи для лейблов, которые должны совпадать с лейблами входящего пода,
чтобы правила совместного (раздельного) существования выполнялись.
Ключи используются для поиска значений в лейблах подов; эти ключи-лейблы объединяются (с помощью `AND`)
с ограничениями, задаваемыми с помощью поля `labelSelector`. Такая комбинированная фильтрация позволяет отобрать
набор существующих подов, которые приниматься в расчет при обработке правил совместного (раздельного) существования.
Обычно `matchLabelKeys` используется вместе с `pod-template-hash` (задается для подов,
которые управляются как часть деплоймента, где значение уникально для каждой ревизии).
Использование `pod-template-hash` в `matchLabelKeys` позволяет нацеливаться на поды, принадлежащие
к той же ревизии, что и входящий под. Таким образом, что скользящее обновление не нарушит правила совместного существования.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: application-server
...
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- database
topologyKey: topology.kubernetes.io/zone
# При расчете affinity подов учитываются только поды из определенного выката.
# При обновлении Deployment'а новые поды будут следовать своим собственным правилам совместного существования
# (если они заданы в новом шаблоне подов)
matchLabelKeys:
- pod-template-hash
```
#### mismatchLabelKeys
{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}}
{{< note >}}
<!-- UPDATE THIS WHEN PROMOTING TO BETA -->
Поле `mismatchLabelKeys` является полем альфа-уровня и по умолчанию отключено в
Kubernetes {{< skew currentVersion >}}.
Включить его можно с помощью [переключателя функциональности](/docs/reference/command-line-tools-reference/feature-gates/)
(feature gate) `MatchLabelKeysInPodAffinity`.
{{< /note >}}
Kubernetes включает необязательное поле `mismatchLabelKeys` для определения правил совместного (раздельного) существования подов.
В поле указываются ключи для лейблов, которые **не** должны совпадать с лейблами входящего пода,
чтобы правила совместного (раздельного) существования подов удовлетворялись.
Один из примеров использования — размещение подов определенной группы пользователей (tenant'ов) или команды в конкретном топологическом домене (узле, зоне и т. д.).
То есть идея в том, чтобы избежать одновременного запуска подов от разных групп пользователей в одном топологическом домене.
```yaml
apiVersion: v1
kind: Pod
metadata:
labels:
# Assume that all relevant Pods have a "tenant" label set
tenant: tenant-a
...
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# следим за тем, чтобы поды, связанные с этим тенантом, попадали на нужный пул узлов
- matchLabelKeys:
- tenant
topologyKey: node-pool
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
# следим за тем, чтобы поды, связанные с этим тенантом, не смогли планироваться на узлы для другого тенанта
- mismatchLabelKeys:
- tenant # значение лейбла "tenant" этого пода будет предотвращать
# планирование на узлы в пулах, на которых работают поды
# другого тенанта
labelSelector:
# Должен быть labelSelector, который выбирает поды с лейблом tenant,
# иначе этот под также будет "ненавидеть" поды из daemonset'ов, например,
# те, у которых нет лейбла tenant.
matchExpressions:
- key: tenant
operator: Exists
topologyKey: node-pool
```
#### Другие примеры использования
Правила совместного/раздельного существования для подов особенно удобны, когда используются совместно с абстракциями более высокого уровня, такими как ReplicaSet, StatefulSet, Deployment и т. д. Эти правила позволяют настроить размещение рабочих нагрузок с учетом имеющейся топологии; например, пара связанных подов будет планироваться на один и тот же узел.
Представьте кластер, состоящий из трех узлов. Он используется для запуска веб-приложения и как in-memory-кэш (например, Redis). Предположим, что задержка между веб-приложением и кэшем должна быть минимальной. Правила совместного/раздельного существования для подов позволяют настроить планировщик так, чтобы тот размещал веб-серверы как можно ближе к кэшу.
В приведенном ниже примере конфигурации деплоймента с Redis его реплики получают лейбл `app=store`. Правило `podAntiAffinity` запрещает планировщику размещать несколько реплик с лейблом `app=store` на одном узле. В результате каждый узел получает по отдельной кэш-реплике.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-cache
spec:
selector:
matchLabels:
app: store
replicas: 3
template:
metadata:
labels:
app: store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: redis-server
image: redis:3.2-alpine
```
Конфигурация деплоймента, приведенная ниже, создает три реплики веб-сервера с лейблом `app=web-store`.
Правило совместного существования предписывает планировщику размещать каждую реплику на узле, на котором уже имеется под с лейблом `app=store`. В то же время правило раздельного существования запрещает планировщику размещать несколько серверов с лейблом `app=web-store` на одном узле.
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-server
spec:
selector:
matchLabels:
app: web-store
replicas: 3
template:
metadata:
labels:
app: web-store
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- store
topologyKey: "kubernetes.io/hostname"
containers:
- name: web-app
image: nginx:1.16-alpine
```
Развертывание ресурсов в соответствии с приведенными выше конфигурациями приведет к созданию кластера, в котором на каждом узле будет по одному веб-серверу и одной реплике Redis (всего три отдельных узла):
| узел 1 | узел 2 | узел 3 |
|:--------------------:|:-------------------:|:------------------:|
| *webserver-1* | *webserver-2* | *webserver-3* |
| *cache-1* | *cache-2* | *cache-3* |
В итоге к каждому инстансу Redis'а, скорее всего, будет обращаться клиент, который работает с ним на том же узле. Подобный подход позволит минимизировать как перекос (дисбаланс нагрузки), так и задержки.
Правила совместного/раздельного существования для подов можно использовать и в других случаях.
См., например, [руководство по ZooKeeper](/docs/tutorials/stateful-application/zookeeper/#tolerating-node-failure). В нем с помощью правил раздельного существования StatefulSet настраивается так, чтобы обеспечить высокую доступность (используется подход, аналогичный тому, что применен выше).
## nodeName
Поле `nodeName` в спецификации пода — более непосредственный способ выбора узлов по сравнению с правилами совместного существования или селектором `nodeSelector`. Если поле `nodeName` не пустое, планировщик игнорирует под, а kubelet на узле с соответствующим именем пытается разместить под на этом узле. Приоритет поля `nodeName` выше, чем селектора `nodeSelector` или правил совместного/раздельного существования.
Однако у `nodeName` имеются и некоторые недостатки:
- Если узел с заданным именем не существует, под не будет запущен. Кроме того, в некоторых случаях он может быть автоматически удален.
- Если на узле с заданным именем недостаточно ресурсов для работы пода, последний будет остановлен; соответствующая причина (например, OutOfmemory или OutOfcpu) будет указана.
- В облачных окружениях имена узлов не всегда предсказуемы или стабильны.
{{< note >}}
Поле `nodeName` предназначено для использования в кастомных планировщиках или в продвинутых случаях,
когда необходимо обойти настроенные планировщики. Обход планировщиков может привести к тому, что поды не будут запущены,
если целевые узлы окажутся перегруженными. С помощью правила [совместного существования (affinity) узла](#node-affinity) или поля [`nodeselector`](#nodeselector) под можно назначить на определенный узел, не обходя планировщики с помощью `nodeName`.
{{</ note >}}
Ниже приведен пример спецификации пода с полем `nodeName`:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeName: kube-01
```
Такой под будет работать только на узле с именем `kube-01`.
## Ограничения на топологию распределения подов
С помощью _ограничений на топологию распределения_ (_topology spread constraints_) можно настроить размещение {{< glossary_tooltip text="подов" term_id="Pod" >}} в кластере по failure-доменам, таким как регионы, зоны, узлы, или любым другим заданным топологическим конфигурациям. Это позволяет повысить производительность, ожидаемую доступность или эффективность использования ресурсов.
Дополнительные сведения о принципах их работы читайте в разделе [Ограничения на топологию распределения подов](/docs/concepts/scheduling-eviction/topology-spread-constraints/).
## Операторы {#operators}
Ниже приведены все логические операторы, которые можно использовать в поле `operator` для `nodeAffinity` и `podAffinity`.
| Оператор | Действие |
| :------------: | :-------------: |
| `In` | Значение лейбла присутствует в предоставленном наборе строк |
| `NotIn` | Значение лейбла отсутствует в предоставленном наборе строк |
| `Exists` | Лейбл с таким ключом существует для объекта |
| `DoesNotExist` | У объекта не существует лейбла с таким ключом |
Следующие операторы могут использоваться только с `nodeAffinity`.
| Оператор | Действие |
| :------------: | :-------------: |
| `Gt` | Введенное значение будет обработано как целое число, и это целое число меньше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором |
| `Lt` | Введенное значение будет обработано как целое число, и это целое число больше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором |
{{<note>}}
Операторы `Gt` и `Lt` не работают с нецелыми значениями. Если заданное значение
не является целым числом, под не будет запланирован. Кроме того, `Gt` и `Lt`
недоступны для `podAffinity`.
{{</note>}}
## {{% heading "whatsnext" %}}
* Дополнительная информация о [taint'ах и toleration'ах](/docs/concepts/scheduling-eviction/taint-and-toleration/).
* Рабочая документация по правилам [совместного существования для узлов](https://git.k8s.io/design-proposals-archive/scheduling/nodeaffinity.md) и по правилам [совместного/раздельного существования для подов](https://git.k8s.io/design-proposals-archive/scheduling/podaffinity.md).
* [Информация о том](/docs/tasks/administer-cluster/topology-manager/), как менеджер топологии участвует в принятии решений о распределении ресурсов на уровне узлов.
* Подробнее об использовании [селектора nodeSelector](/docs/tasks/configure-pod-container/assign-pods-nodes/).
* Подробнее об использовании правил [совместного/раздельного существования](/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/).

View File

@ -0,0 +1,4 @@
---
title: Проблемы и безопасность Kubernetes
weight: 70
---

View File

@ -0,0 +1,15 @@
---
title: Трекер задач (Issues) Kubernetes
weight: 10
aliases: [/cve/,/cves/]
---
Чтобы сообщить о проблеме в области безопасности, воспользуйтесь процедурой [раскрытия информации о безопасности Kubernetes](/ru/docs/reference/issues-security/security/#report-a-vulnerability).
Механизм [GitHub Issues](https://github.com/kubernetes/kubernetes/issues/) позволяет работать с кодом Kubernetes и отслеживать активные задачи.
* Официальный [список известных CVE](/ru/docs/reference/issues-security/official-cve-feed/)
(уязвимостей в области безопасности), которые были обнародованы [Комитетом по реагированию на угрозы в области безопасности Kubernetes](https://github.com/kubernetes/committee-security-response).
* [Issues на GitHub, связанные с CVE](https://github.com/kubernetes/kubernetes/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3Aarea%2Fsecurity+in%3Atitle+CVE)
Связанные с безопасностью анонсы публикуются в рассылке [kubernetes-security-announce@googlegroups.com](https://groups.google.com/forum/#!forum/kubernetes-security-announce).

View File

@ -0,0 +1,47 @@
---
title: Официальный CVE-фид
linkTitle: CVE-фид
weight: 25
outputs:
- json
- html
- rss
layout: cve-feed
---
{{< feature-state for_k8s_version="v1.27" state="beta" >}}
Поддерживаемый сообществом список официальных CVE, анонсированных
Комитетом по реагированию на проблемы безопасности Kubernetes. Подробности см. на странице
[Общие сведения о безопасности Kubernetes и раскрытии информации](/ru/docs/reference/issues-security/security/).
Проект Kubernetes публикует фиды с анонсами проблем в области безопасности в формате [JSON](/docs/reference/issues-security/official-cve-feed/index.json) и [RSS](/docs/reference/issues-security/official-cve-feed/feed.xml), доступные для автоматического считывания. Доступ к ним можно получить, выполнив следующие команды:
{{< tabs name="CVE-фиды" >}}
{{% tab name="JSON-фид" %}}
[Ссылка на JSON-формат](/docs/reference/issues-security/official-cve-feed/index.json)
```shell
curl -Lv https://k8s.io/docs/reference/issues-security/official-cve-feed/index.json
```
{{% /tab %}}
{{% tab name="RSS-фид" %}}
[Ссылка на RSS-формат](/docs/reference/issues-security/official-cve-feed/feed.xml)
```shell
curl -Lv https://k8s.io/docs/reference/issues-security/official-cve-feed/feed.xml
```
{{% /tab %}}
{{< /tabs >}}
{{< cve-feed >}}
<!-- | CVE ID | Краткое описание проблемы | Ссылка на Issue на GitHub'е |
| ----------- | ----------- | --------- |
| [CVE-2021-25741](https://www.cve.org/CVERecord?id=CVE-2021-25741) | Symlink Exchange Can Allow Host Filesystem Access | [#104980](https://github.com/kubernetes/kubernetes/issues/104980) |
| [CVE-2020-8565](https://www.cve.org/CVERecord?id=CVE-2020-8565) | Incomplete fix for CVE-2019-11250 allows for token leak in logs when logLevel >= 9 | [#95623](https://github.com/kubernetes/kubernetes/issues/95623) | -->
Список автоматически обновляется с заметной, но небольшой задержкой (от нескольких минут до нескольких часов)
с момента анонса CVE до момента его появления в этом фиде.
В качестве источника используется набор GitHub Issues, отфильтрованный по контролируемому и
ограниченному лейблу `official-cve-feed`. Исходные данные хранятся в бакете Google Cloud,
право на запись в который есть только у небольшого числа доверенных представителей сообщества.

View File

@ -0,0 +1,55 @@
---
title: Общие сведения о безопасности Kubernetes и раскрытии информации
aliases: [/security/]
reviewers:
- eparis
- erictune
- philips
- jessfraz
content_type: concept
weight: 20
---
<!-- overview -->
На этой странице приводятся общие сведения о безопасности Kubernetes и раскрытии информации, имеющей к ней отношение.
<!-- body -->
## Анонсы в области безопасности
Информация о проблемах в области безопасности и ключевых изменениях API доступна в рассылке [kubernetes-security-announce](https://groups.google.com/forum/#!forum/kubernetes-security-announce).
## Сообщить об уязвимости
Мы искренне признательны исследователям в области безопасности и пользователям, которые передают информацию об уязвимостях в Open Source-сообщество Kubernetes. Все отчеты тщательно изучаются группой добровольцев сообщества.
Чтобы создать отчет, отправьте свою уязвимость в [Bug Bounty-программу Kubernetes](https://hackerone.com/kubernetes). Это позволит отследить и обработать уязвимость в стандартные сроки.
Также можно оправить [стандартное письмо об ошибках Kubernetes](https://github.com/kubernetes/kubernetes/blob/master/.github/ISSUE_TEMPLATE/bug-report.yaml) с описанием проблемы с безопасностью и ее подробностями в закрытый список [security@kubernetes.io](mailto:security@kubernetes.io).
Письмо можно зашифровать, используя GPG-ключи [членов Комитета по безопасности](https://git.k8s.io/security/README.md#product-security-committee-psc). Шифрование с использованием GPG НЕ является обязательным.
### Когда следует сообщать об уязвимости
- Вы думаете, что обнаружили уязвимость в безопасности Kubernetes.
- Вы не уверены, как именно уязвимость повлияет на Kubernetes.
- Вы думаете, что обнаружили уязвимость в другом проекте, от которого зависит работа Kubernetes.
- Если у проекта имеется собственный регламент регистрации и раскрытия информации об уязвимостях, пожалуйста, следуйте ему и пишите сразу в проект.
### Когда НЕ следует сообщать об уязвимости
- Вам нужна помощь в настройке компонентов Kubernetes для обеспечения безопасности.
- Вам нужна помощь в применении обновлений, связанных с безопасностью.
- Проблема не связана с безопасностью.
## Реагирование на уязвимости в области безопасности
Каждый отчет об уязвимости подтверждается и анализируется членами Комитета по реагированию на угрозы безопасности в течение 3 рабочих дней. После этого [запускается соответствующая процедура](https://git.k8s.io/security/security-release-process.md#disclosures).
Любая информация об уязвимостях, переданная Комитету по реагированию на угрозы безопасности, остается внутри проекта Kubernetes и не передается в другие проекты, если только этого не требуется для устранения проблемы.
Автору отчета будет сообщено о результатах триажа и дальнейших шагах по подготовке исправления и планированию релиза.
## Сроки раскрытия информации
Дата публичного раскрытия согласовывается Комитетом по реагированию на угрозы безопасности Kubernetes и автором отчета об уязвимости. Мы предпочитаем полностью раскрывать информацию об обнаруженной проблеме сразу после того, как станет понятно, какие шаги необходимо предпринять для устранения ее последствий. Разумно отложить раскрытие информации, если проблема или порядок дальнейших шагов не до конца понятны, решение плохо протестировано или необходима координация действий вендоров. Срок раскрытия информации варьируется от незамедлительного (особенно если она уже широко известна) до нескольких недель. Для "простых" уязвимостей с момента подачи отчета до даты раскрытия обычно проходит около 7 дней. Комитет по реагированию на угрозы безопасности сохраняет последнее слово при определении даты раскрытия информации.

View File

@ -213,7 +213,6 @@ kubectl describe pod goproxy
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
@ -234,8 +233,7 @@ livenessProbe:
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: command-demo
labels:
purpose: demonstrate-command
spec:
containers:
- name: command-demo-container
image: debian
command: ["printenv"]
args: ["HOSTNAME", "KUBERNETES_PORT"]
restartPolicy: OnFailure

View File

@ -0,0 +1,30 @@
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# Эти контейнеры запускаются во время инициализации пода
initContainers:
- name: install
image: busybox:1.28
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://info.cern.ch
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}

View File

@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"]

View File

@ -0,0 +1,21 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never

View File

@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: SPECIAL_LEVEL
path: keys
restartPolicy: Never

View File

@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# Укажите имя ConfigMap с файлами, которые вы хотите
# добавить в контейнер
name: special-config
restartPolicy: Never

View File

@ -0,0 +1,21 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: Never

View File

@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent

View File

@ -0,0 +1,18 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: foo-node # запланировать под на конкретный узел
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent

View File

@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd

View File

@ -0,0 +1,20 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: vault-token
serviceAccountName: build-robot
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
path: vault-token
expirationSeconds: 7200
audience: vault

View File

@ -0,0 +1,23 @@
apiVersion: v1
kind: Pod
metadata:
name: pod1
labels:
tier: frontend
spec:
containers:
- name: hello1
image: gcr.io/google-samples/hello-app:2.0
---
apiVersion: v1
kind: Pod
metadata:
name: pod2
labels:
tier: frontend
spec:
containers:
- name: hello2
image: gcr.io/google-samples/hello-app:1.0

View File

@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
# Задать переменную окружения
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# ConfigMap со значением, которое вы хотите присвоить SPECIAL_LEVEL_KEY
name: special-config
# Укажите ключ, привязанный к значению
key: special.how
restartPolicy: Never

View File

@ -0,0 +1,32 @@
apiVersion: v1
kind: Pod
metadata:
name: with-affinity-anti-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: label-1
operator: In
values:
- key-1
- weight: 50
preference:
matchExpressions:
- key: label-2
operator: In
values:
- key-2
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0

View File

@ -0,0 +1,26 @@
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: registry.k8s.io/pause:2.0

View File

@ -0,0 +1,29 @@
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: registry.k8s.io/pause:2.0

View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
schedulingGates:
- name: example.com/foo
- name: example.com/bar
containers:
- name: pause
image: registry.k8s.io/pause:3.6

View File

@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"

View File

@ -0,0 +1,8 @@
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: pause
image: registry.k8s.io/pause:3.6

View File

@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regcred

View File

@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
shareProcessNamespace: true
containers:
- name: nginx
image: nginx
- name: shell
image: busybox:1.28
securityContext:
capabilities:
add:
- SYS_PTRACE
stdin: true
tty: true

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80

View File

@ -0,0 +1,27 @@
apiVersion: v1
kind: Pod
metadata:
name: two-containers
spec:
restartPolicy: Never
volumes:
- name: shared-data
emptyDir: {}
containers:
- name: nginx-container
image: nginx
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
- name: debian-container
image: debian
volumeMounts:
- name: shared-data
mountPath: /pod-data
command: ["/bin/sh"]
args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]

View File

@ -0,0 +1,10 @@
apiVersion: v1
kind: Pod
metadata:
name: userns
spec:
hostUsers: false
containers:
- name: shell
command: ["sleep", "infinity"]
image: debian

View File

@ -0,0 +1,417 @@
---
layout: blog
title: '镜像文件系统:配置 Kubernetes 将容器存储在独立的文件系统上'
date: 2024-01-23
slug: kubernetes-separate-image-filesystem
---
<!--
layout: blog
title: 'Image Filesystem: Configuring Kubernetes to store containers on a separate filesystem'
date: 2024-01-23
slug: kubernetes-separate-image-filesystem
-->
<!--
**Author:** Kevin Hannon (Red Hat)
-->
**作者:** Kevin Hannon (Red Hat)
**译者:** [Michael Yao](https://github.com/windsonsea)
<!--
A common issue in running/operating Kubernetes clusters is running out of disk space.
When the node is provisioned, you should aim to have a good amount of storage space for your container images and running containers.
The [container runtime](/docs/setup/production-environment/container-runtimes/) usually writes to `/var`.
This can be located as a separate partition or on the root filesystem.
CRI-O, by default, writes its containers and images to `/var/lib/containers`, while containerd writes its containers and images to `/var/lib/containerd`.
-->
磁盘空间不足是运行或操作 Kubernetes 集群时的一个常见问题。
在制备节点时,你应该为容器镜像和正在运行的容器留足够的存储空间。
[容器运行时](/zh-cn/docs/setup/production-environment/container-runtimes/)通常会向 `/var` 目录写入数据。
此目录可以位于单独的分区或根文件系统上。CRI-O 默认将其容器和镜像写入 `/var/lib/containers`
而 containerd 将其容器和镜像写入 `/var/lib/containerd`
<!--
In this blog post, we want to bring attention to ways that you can configure your container runtime to store its content separately from the default partition.
This allows for more flexibility in configuring Kubernetes and provides support for adding a larger disk for the container storage while keeping the default filesystem untouched.
One area that needs more explaining is where/what Kubernetes is writing to disk.
-->
在这篇博文中,我们想要关注的是几种不同方式,用来配置容器运行时将其内容存储到别的位置而非默认分区。
这些配置允许我们更灵活地配置 Kubernetes支持在保持默认文件系统不受影响的情况下为容器存储添加更大的磁盘。
需要额外讲述的是 Kubernetes 向磁盘在写入数据的具体位置及内容。
<!--
## Understanding Kubernetes disk usage
Kubernetes has persistent data and ephemeral data. The base path for the kubelet and local
Kubernetes-specific storage is configurable, but it is usually assumed to be `/var/lib/kubelet`.
In the Kubernetes docs, this is sometimes referred to as the root or node filesystem. The bulk of this data can be categorized into:
-->
## 了解 Kubernetes 磁盘使用情况 {#understanding-kubernetes-disk-usage}
Kubernetes 有持久数据和临时数据。kubelet 和特定于 Kubernetes 的本地存储的基础路径是可配置的,
但通常假定为 `/var/lib/kubelet`。在 Kubernetes 文档中,
这一位置有时被称为根文件系统或节点文件系统。写入的数据可以大致分类为:
<!--
- ephemeral storage
- logs
- and container runtime
This is different from most POSIX systems as the root/node filesystem is not `/` but the disk that `/var/lib/kubelet` is on.
-->
- 临时存储
- 日志
- 容器运行时
与大多数 POSIX 系统不同,这里的根/节点文件系统不是 `/`,而是 `/var/lib/kubelet` 所在的磁盘。
<!--
### Ephemeral storage
Pods and containers can require temporary or transient local storage for their operation.
The lifetime of the ephemeral storage does not extend beyond the life of the individual pod, and the ephemeral storage cannot be shared across pods.
-->
### 临时存储 {#ephemeral-storage}
Pod 和容器的某些操作可能需要临时或瞬态的本地存储。
临时存储的生命周期短于 Pod 的生命周期,且临时存储不能被多个 Pod 共享。
<!--
### Logs
By default, Kubernetes stores the logs of each running container, as files within `/var/log`.
These logs are ephemeral and are monitored by the kubelet to make sure that they do not grow too large while the pods are running.
You can customize the [log rotation](/docs/concepts/cluster-administration/logging/#log-rotation) settings
for each node to manage the size of these logs, and configure log shipping (using a 3rd party solution)
to avoid relying on the node-local storage.
-->
### 日志 {#logs}
默认情况下Kubernetes 将每个运行容器的日志存储为 `/var/log` 中的文件。
这些日志是临时性质的,并由 kubelet 负责监控以确保不会在 Pod 运行时变得过大。
你可以为每个节点自定义[日志轮换](/zh-cn/docs/concepts/cluster-administration/logging/#log-rotation)设置,
以管控这些日志的大小,并(使用第三方解决方案)配置日志转储以避免对节点本地存储形成依赖。
<!--
### Container runtime
The container runtime has two different areas of storage for containers and images.
- read-only layer: Images are usually denoted as the read-only layer, as they are not modified when containers are running.
The read-only layer can consist of multiple layers that are combined into a single read-only layer.
There is a thin layer on top of containers that provides ephemeral storage for containers if the container is writing to the filesystem.
-->
### 容器运行时 {#container-runtime}
容器运行时针对容器和镜像使用两个不同的存储区域。
- 只读层:镜像通常被表示为只读层,因为镜像在容器处于运行状态期间不会被修改。
只读层可以由多个层组成,这些层组合到一起形成最终的只读层。
如果容器要向文件系统中写入数据,则在容器层之上会存在一个薄层为容器提供临时存储。
<!--
- writeable layer: Depending on your container runtime, local writes might be
implemented as a layered write mechanism (for example, `overlayfs` on Linux or CimFS on Windows).
This is referred to as the writable layer.
Local writes could also use a writeable filesystem that is initialized with a full clone of the container
image; this is used for some runtimes based on hypervisor virtualisation.
The container runtime filesystem contains both the read-only layer and the writeable layer.
This is considered the `imagefs` in Kubernetes documentation.
-->
- 可写层:取决于容器运行时的不同实现,本地写入可能会用分层写入机制来实现
(例如 Linux 上的 `overlayfs` 或 Windows 上的 CimFS。这一机制被称为可写层。
本地写入也可以使用一个可写文件系统来实现,该文件系统使用容器镜像的完整克隆来初始化;
这种方式适用于某些基于 Hypervisor 虚拟化的运行时。
容器运行时文件系统包含只读层和可写层。在 Kubernetes 文档中,这一文件系统被称为 `imagefs`
<!--
## Container runtime configurations
### CRI-O
CRI-O uses a storage configuration file in TOML format that lets you control how the container runtime stores persistent and temporary data.
CRI-O utilizes the [storage library](https://github.com/containers/storage).
Some Linux distributions have a manual entry for storage (`man 5 containers-storage.conf`).
The main configuration for storage is located in `/etc/containers/storage.conf` and one can control the location for temporary data and the root directory.
The root directory is where CRI-O stores the persistent data.
-->
## 容器运行时配置 {#container-runtime-configurations}
### CRI-O
CRI-O 使用 TOML 格式的存储配置文件,让你控制容器运行时如何存储持久数据和临时数据。
CRI-O 使用了 [containers-storage 库](https://github.com/containers/storage)。
某些 Linux 发行版为 containers-storage 提供了帮助手册条目(`man 5 containers-storage.conf`)。
存储的主要配置位于 `/etc/containers/storage.conf` 中,你可以控制临时数据和根目录的位置。
根目录是 CRI-O 存储持久数据的位置。
<!--
```toml
[storage]
# Default storage driver
driver = "overlay"
# Temporary storage location
runroot = "/var/run/containers/storage"
# Primary read/write location of container storage
graphroot = "/var/lib/containers/storage"
```
-->
```toml
[storage]
# 默认存储驱动
driver = "overlay"
# 临时存储位置
runroot = "/var/run/containers/storage"
# 容器存储的主要读/写位置
graphroot = "/var/lib/containers/storage"
```
<!--
- `graphroot`
- Persistent data stored from the container runtime
- If SELinux is enabled, this must match the `/var/lib/containers/storage`
- `runroot`
- Temporary read/write access for container
- Recommended to have this on a temporary filesystem
-->
- `graphroot`
- 存储来自容器运行时的持久数据
- 如果 SELinux 被启用,则此项必须是 `/var/lib/containers/storage`
- `runroot`
- 容器的临时读/写访问
- 建议将其放在某个临时文件系统上
<!--
Here is a quick way to relabel your graphroot directory to match `/var/lib/containers/storage`:
```bash
semanage fcontext -a -e /var/lib/containers/storage <YOUR-STORAGE-PATH>
restorecon -R -v <YOUR-STORAGE-PATH>
```
-->
以下是为你的 graphroot 目录快速重新打标签以匹配 `/var/lib/containers/storage` 的方法:
```bash
semanage fcontext -a -e /var/lib/containers/storage <你的存储路径>
restorecon -R -v <你的存储路径>
```
<!--
### containerd
The containerd runtime uses a TOML configuration file to control where persistent and ephemeral data is stored.
The default path for the config file is located at `/etc/containerd/config.toml`.
The relevant fields for containerd storage are `root` and `state`.
-->
### containerd
containerd 运行时使用 TOML 配置文件来控制存储持久数据和临时数据的位置。
配置文件的默认路径位于 `/etc/containerd/config.toml`
与 containerd 存储的相关字段是 `root``state`
<!--
- `root`
- The root directory for containerd metadata
- Default is `/var/lib/containerd`
- Root also requires SELinux labels if your OS requires it
- `state`
- Temporary data for containerd
- Default is `/run/containerd`
-->
- `root`
- containerd 元数据的根目录
- 默认为 `/var/lib/containerd`
- 如果你的操作系统要求,需要为根目录设置 SELinux 标签
- `state`
- containerd 的临时数据
- 默认为 `/run/containerd`
<!--
## Kubernetes node pressure eviction
Kubernetes will automatically detect if the container filesystem is split from the node filesystem.
When one separates the filesystem, Kubernetes is responsible for monitoring both the node filesystem and the container runtime filesystem.
Kubernetes documentation refers to the node filesystem and the container runtime filesystem as nodefs and imagefs.
If either nodefs or the imagefs are running out of disk space, then the overall node is considered to have disk pressure.
Kubernetes will first reclaim space by deleting unusued containers and images, and then it will resort to evicting pods.
On a node that has a nodefs and an imagefs, the kubelet will
[garbage collect](/docs/concepts/architecture/garbage-collection/#containers-images) unused container images
on imagefs and will remove dead pods and their containers from the nodefs.
If there is only a nodefs, then Kubernetes garbage collection includes dead containers, dead pods and unused images.
-->
## Kubernetes 节点压力驱逐 {#kubernetes-node-pressure-eviction}
Kubernetes 将自动检测容器文件系统是否与节点文件系统分离。
当你分离文件系统时Kubernetes 负责同时监视节点文件系统和容器运行时文件系统。
Kubernetes 文档将节点文件系统称为 nodefs将容器运行时文件系统称为 imagefs。
如果 nodefs 或 imagefs 中有一个磁盘空间不足,则整个节点被视为有磁盘压力。
这种情况下Kubernetes 先通过删除未使用的容器和镜像来回收空间,之后会尝试驱逐 Pod。
在同时具有 nodefs 和 imagefs 的节点上kubelet 将在 imagefs
上对未使用的容器镜像执行[垃圾回收](/zh-cn/docs/concepts/architecture/garbage-collection/#containers-images)
并从 nodefs 中移除死掉的 Pod 及其容器。
如果只有 nodefs则 Kubernetes 垃圾回收将包括死掉的容器、死掉的 Pod 和未使用的镜像。
<!--
Kubernetes allows more configurations for determining if your disk is full.
The eviction manager within the kubelet has some configuration settings that let you control
the relevant thresholds.
For filesystems, the relevant measurements are `nodefs.available`, `nodefs.inodesfree`, `imagefs.available`, and `imagefs.inodesfree`.
If there is not a dedicated disk for the container runtime then imagefs is ignored.
Users can use the existing defaults:
-->
Kubernetes 提供额外的配置方法来确定磁盘是否已满。kubelet 中的驱逐管理器有一些让你可以控制相关阈值的配置项。
对于文件系统,相关测量值有 `nodefs.available`、`nodefs.inodesfree`、`imagefs.available` 和
`imagefs.inodesfree`。如果容器运行时没有专用磁盘,则 imagefs 被忽略。
用户可以使用现有的默认值:
<!--
- `memory.available` < 100MiB
- `nodefs.available` < 10%
- `imagefs.available` < 15%
- `nodefs.inodesFree` < 5% (Linux nodes)
Kubernetes allows you to set user defined values in `EvictionHard` and `EvictionSoft` in the kubelet configuration file.
-->
- `memory.available` < 100MiB
- `nodefs.available` < 10%
- `imagefs.available` < 15%
- `nodefs.inodesFree` < 5%Linux 节点)
Kubernetes 允许你在 kubelet 配置文件中将 `EvictionHard``EvictionSoft` 设置为用户定义的值。
<!--
`EvictionHard`
: defines limits; once these limits are exceeded, pods will be evicted without any grace period.
`EvictionSoft`
: defines limits; once these limits are exceeded, pods will be evicted with a grace period that can be set per signal.
-->
`EvictionHard`
: 定义限制一旦超出这些限制Pod 将被立即驱逐,没有任何宽限期。
`EvictionSoft`
: 定义限制一旦超出这些限制Pod 将在按各信号所设置的宽限期后被驱逐。
<!--
If you specify a value for `EvictionHard`, it will replace the defaults.
This means it is important to set all signals in your configuration.
For example, the following kubelet configuration could be used to configure [eviction signals](/docs/concepts/scheduling-eviction/node-pressure-eviction/#eviction-signals-and-thresholds) and grace period options.
-->
如果你为 `EvictionHard` 指定了值,所设置的值将取代默认值。
这意味着在你的配置中设置所有信号非常重要。
例如,以下 kubelet
配置可用于配置[驱逐信号](/zh-cn/docs/concepts/scheduling-eviction/node-pressure-eviction/#eviction-signals-and-thresholds)和宽限期选项。
```yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: "192.168.0.8"
port: 20250
serializeImagePulls: false
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
imagefs.inodesFree: "5%"
evictionSoft:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
imagefs.inodesFree: "5%"
evictionSoftGracePeriod:
memory.available: "1m30s"
nodefs.available: "2m"
nodefs.inodesFree: "2m"
imagefs.available: "2m"
imagefs.inodesFree: "2m"
evictionMaxPodGracePeriod: 60s
```
<!--
### Problems
The Kubernetes project recommends that you either use the default settings for eviction or you set all the fields for eviction.
You can use the default settings or specify your own `evictionHard` settings. If you miss a signal, then Kubernetes will not monitor that resource.
One common misconfiguration administrators or users can hit is mounting a new filesystem to `/var/lib/containers/storage` or `/var/lib/containerd`.
Kubernetes will detect a separate filesystem, so you want to make sure to check that `imagefs.inodesfree` and `imagefs.available` match your needs if you've done this.
-->
### 问题 {#problems}
Kubernetes 项目建议你针对 Pod 驱逐要么使用其默认设置,要么设置与之相关的所有字段。
你可以使用默认设置或指定你自己的 `evictionHard` 设置。 如果你漏掉一个信号,那么 Kubernetes 将不会监视该资源。
管理员或用户可能会遇到的一个常见误配是将新的文件系统挂载到 `/var/lib/containers/storage``/var/lib/containerd`
Kubernetes 将检测到一个单独的文件系统,因此你要确保 `imagefs.inodesfree``imagefs.available` 符合你的需要。
<!--
Another area of confusion is that ephemeral storage reporting does not change if you define an image
filesystem for your node. The image filesystem (`imagefs`) is used to store container image layers; if a
container writes to its own root filesystem, that local write doesn't count towards the size of the container image. The place where the container runtime stores those local modifications is runtime-defined, but is often
the image filesystem.
If a container in a pod is writing to a filesystem-backed `emptyDir` volume, then this uses space from the
`nodefs` filesystem.
The kubelet always reports ephemeral storage capacity and allocations based on the filesystem represented
by `nodefs`; this can be confusing when ephemeral writes are actually going to the image filesystem.
-->
另一个令人困惑的地方是,如果你为节点定义了镜像文件系统,则临时存储报告不会发生变化。
镜像文件系统(`imagefs`)用于存储容器镜像层;如果容器向自己的根文件系统写入,
那么这种本地写入不会计入容器镜像的大小。容器运行时存储这些本地修改的位置是由运行时定义的,但通常是镜像文件系统。
如果 Pod 中的容器正在向基于文件系统的 `emptyDir` 卷写入,所写入的数据将使用 `nodefs` 文件系统的空间。
kubelet 始终根据 `nodefs` 所表示的文件系统来报告临时存储容量和分配情况;
当临时写入操作实际上是写到镜像文件系统时,这种差别可能会让人困惑。
<!--
### Future work
To fix the ephemeral storage reporting limitations and provide more configuration options to the container runtime, SIG Node are working on [KEP-4191](http://kep.k8s.io/4191).
In KEP-4191, Kubernetes will detect if the writeable layer is separated from the read-only layer (images).
This would allow us to have all ephemeral storage, including the writeable layer, on the same disk as well as allowing for a separate disk for images.
-->
### 后续工作 {#future-work}
为了解决临时存储报告相关的限制并为容器运行时提供更多配置选项SIG Node
正在处理 [KEP-4191](http://kep.k8s.io/4191)。在 KEP-4191 中,
Kubernetes 将检测可写层是否与只读层(镜像)分离。
这种检测使我们可以将包括可写层在内的所有临时存储放在同一磁盘上,同时也可以为镜像使用单独的磁盘。
<!--
### Getting involved
If you would like to get involved, you can
join [Kubernetes Node Special-Interest-Group](https://github.com/kubernetes/community/tree/master/sig-node) (SIG).
If you would like to share feedback, you can do so on our
[#sig-node](https://kubernetes.slack.com/archives/C0BP8PW9G) Slack channel.
If you're not already part of that Slack workspace, you can visit https://slack.k8s.io/ for an invitation.
-->
### 参与其中 {#getting-involved}
如果你想参与其中,可以加入
[Kubernetes Node 特别兴趣小组](https://github.com/kubernetes/community/tree/master/sig-node)SIG
如果你想分享反馈,可以分享到我们的
[#sig-node](https://kubernetes.slack.com/archives/C0BP8PW9G) Slack 频道。
如果你还没有加入该 Slack 工作区,可以访问 https://slack.k8s.io/ 获取邀请。
<!--
Special thanks to all the contributors who provided great reviews, shared valuable insights or suggested the topic idea.
-->
特别感谢所有提供出色评审、分享宝贵见解或建议主题想法的贡献者。
- Peter Hunt
- Mrunal Patel
- Ryan Phillips
- Gaurav Singh

View File

@ -65,7 +65,7 @@ Kubernetes 也使用 Lease 确保在任何给定时间某个组件只有一个
-->
## API 服务器身份 {#api-server-identity}
{{< feature-state for_k8s_version="v1.26" state="beta" >}}
{{< feature-state feature_gate_name="APIServerIdentity" >}}
<!--
Starting in Kubernetes v1.26, each `kube-apiserver` uses the Lease API to publish its identity to the

View File

@ -399,7 +399,7 @@ The `logrotate` tool rotates logs daily, or once the log size is greater than 10
-->
## 日志查询 {#log-query}
{{< feature-state for_k8s_version="v1.27" state="alpha" >}}
{{< feature-state feature_gate_name="NodeLogQuery" >}}
<!--
To help with debugging issues on nodes, Kubernetes v1.27 introduced a feature that allows viewing logs of services

View File

@ -305,7 +305,7 @@ Kubernetes 会增加每次尝试之间的延迟,直到达到编译限制,即
-->
### 基于运行时类的镜像拉取 {#image-pull-per-runtime-class}
{{< feature-state for_k8s_version="v1.29" state="alpha" >}}
{{< feature-state feature_gate_name="RuntimeClassInImageCriApi" >}}
<!--
Kubernetes includes alpha support for performing image pulls based on the RuntimeClass of a Pod.

View File

@ -61,7 +61,7 @@ as well as detecting and responding to cluster events (for example, starting up
<!--
Control plane components can be run on any machine in the cluster. However,
for simplicity, set up scripts typically start all control plane components on
for simplicity, setup scripts typically start all control plane components on
the same machine, and do not run user containers on this machine. See
[Creating Highly Available clusters with kubeadm](/docs/setup/production-environment/tools/kubeadm/high-availability/)
for an example control plane setup that runs across multiple machines.

View File

@ -43,39 +43,222 @@ Kubernetes API 使你可以在 Kubernetes 中查询和操纵 API 对象
(例如 Pod、Namespace、ConfigMap 和 Event的状态。
<!--
Most operations can be performed through the
[kubectl](/docs/reference/kubectl/) command-line interface or other
command-line tools, such as
[kubeadm](/docs/reference/setup-tools/kubeadm/), which in turn use the
API. However, you can also access the API directly using REST calls.
Consider using one of the [client libraries](/docs/reference/using-api/client-libraries/)
if you are writing an application using the Kubernetes API.
Most operations can be performed through the [kubectl](/docs/reference/kubectl/)
command-line interface or other command-line tools, such as
[kubeadm](/docs/reference/setup-tools/kubeadm/), which in turn use the API.
However, you can also access the API directly using REST calls. Kubernetes
provides a set of [client libraries](/docs/reference/using-api/client-libraries/)
for those looking to
write applications using the Kubernetes API.
-->
大部分操作都可以通过 [kubectl](/zh-cn/docs/reference/kubectl/) 命令行接口或类似
[kubeadm](/zh-cn/docs/reference/setup-tools/kubeadm/) 这类命令行工具来执行,
这些工具在背后也是调用 API。不过你也可以使用 REST 调用来访问这些 API。
Kubernetes 为那些希望使用 Kubernetes API
编写应用的开发者提供一组[客户端库](/zh-cn/docs/reference/using-api/client-libraries/)。
如果你正在编写程序来访问 Kubernetes API
可以考虑使用[客户端库](/zh-cn/docs/reference/using-api/client-libraries/)之一。
<!--
Each Kubernetes cluster publishes the specification of the APIs that the cluster serves.
There are two mechanisms that Kubernetes uses to publish these API specifications; both are useful
to enable automatic interoperability. For example, the `kubectl` tool fetches and caches the API
specification for enabling command-line completion and other features.
The two supported mechanisms are as follows:
-->
每个 Kubernetes 集群都会发布集群所使用的 API 规范。
Kubernetes 使用两种机制来发布这些 API 规范;这两种机制都有助于实现自动互操作。
例如,`kubectl` 工具获取并缓存 API 规范,以实现命令行补全和其他特性。所支持的两种机制如下:
<!--
- [The Discovery API](#discovery-api) provides information about the Kubernetes APIs:
API names, resources, versions, and supported operations. This is a Kubernetes
specific term as it is a separate API from the Kubernetes OpenAPI.
It is intended to be a brief summary of the available resources and it does not
detail specific schema for the resources. For reference about resource schemas,
please refer to the OpenAPI document.
-->
- [发现 API](#discovery-api) 提供有关 Kubernetes API 的信息API 名称、资源、版本和支持的操作。
此 API 是特定于 Kubernetes 的一个术语,因为它是一个独立于 Kubernetes OpenAPI 的 API。
其目的是为可用的资源提供简要总结,不详细说明资源的具体模式。有关资源模式的参考,请参阅 OpenAPI 文档。
<!--
- The [Kubernetes OpenAPI Document](#openapi-specification) provides (full)
[OpenAPI v2.0 and 3.0 schemas](https://www.openapis.org/) for all Kubernetes API
endpoints.
The OpenAPI v3 is the preferred method for accessing OpenAPI as it
provides
a more comprehensive and accurate view of the API. It includes all the available
API paths, as well as all resources consumed and produced for every operations
on every endpoints. It also includes any extensibility components that a cluster supports.
The data is a complete specification and is significantly larger than that from the
Discovery API.
-->
- [Kubernetes OpenAPI 文档](#openapi-specification)为所有 Kubernetes API 端点提供(完整的)
[OpenAPI v2.0 和 v3.0 模式](https://www.openapis.org/)。OpenAPI v3 是访问 OpenAPI 的首选方法,
因为它提供了更全面和准确的 API 视图。其中包括所有可用的 API 路径,以及每个端点上每个操作所接收和生成的所有资源。
它还包括集群支持的所有可扩展组件。这些数据是完整的规范,比 Discovery API 提供的规范要大得多。
<!--
## Discovery API
Kubernetes publishes a list of all group versions and resources supported via
the Discovery API. This includes the following for each resource:
-->
## Discovery API
Kubernetes 通过 Discovery API 发布集群所支持的所有组版本和资源列表。对于每个资源,包括以下内容:
<!--
- Name
- Cluster or namespaced scope
- Endpoint URL and supported verbs
- Alternative names
- Group, version, kind
-->
- 名称
- 集群作用域还是名字空间作用域
- 端点 URL 和所支持的动词
- 别名
- 组、版本、类别
<!--
The API is available both aggregated and unaggregated form. The aggregated
discovery serves two endpoints while the unaggregated discovery serves a
separate endpoint for each group version.
-->
API 以聚合和非聚合形式提供。聚合的发现提供两个端点,而非聚合的发现为每个组版本提供单独的端点。
<!--
### Aggregated discovery
-->
### 聚合的发现 {#aggregated-discovery}
{{< feature-state state="beta" for_k8s_version="v1.27" >}}
<!--
Kubernetes offers beta support for aggregated discovery, publishing
all resources supported by a cluster through two endpoints (`/api` and
`/apis`). Requesting this
endpoint drastically reduces the number of requests sent to fetch the
discovery data from the cluster. You can access the data by
requesting the respective endpoints with an `Accept` header indicating
the aggregated discovery resource:
`Accept: application/json;v=v2beta1;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList`.
-->
Kubernetes 为聚合的发现提供了 Beta 支持,通过两个端点(`/api` 和 `/apis`)发布集群所支持的所有资源。
请求这个端点会大大减少从集群获取发现数据时发送的请求数量。你可以通过带有
`Accept` 头(`Accept: application/json;v=v2beta1;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList`
的请求发送到不同端点,来指明聚合发现的资源。
<!--
Without indicating the resource type using the `Accept` header, the default
response for the `/api` and `/apis` endpoint is an unaggregated discovery
document.
-->
如果没有使用 `Accept` 头指示资源类型,对于 `/api``/apis` 端点的默认响应将是一个非聚合的发现文档。
<!--
The [discovery document](https://github.com/kubernetes/kubernetes/blob/release-v{{< skew currentVersion >}}/api/discovery/aggregated_v2beta1.json)
for the built-in resources can be found in the Kubernetes GitHub repository.
This Github document can be used as a reference of the base set of the available resources
if a Kubernetes cluster is not available to query.
The endpoint also supports ETag and protobuf encoding.
-->
内置资源的[发现文档](https://github.com/kubernetes/kubernetes/blob/release-v{{< skew currentVersion >}}/api/discovery/aggregated_v2beta1.json)可以在
Kubernetes GitHub 代码仓库中找到。如果手头没有 Kubernetes 集群可供查询,
此 Github 文档可用作可用资源的基础集合的参考。端点还支持 ETag 和 protobuf 编码。
<!--
### Unaggregated discovery
Without discovery aggregation, discovery is published in levels, with the root
endpoints publishing discovery information for downstream documents.
A list of all group versions supported by a cluster is published at
the `/api` and `/apis` endpoints. Example:
-->
### 非聚合的发现 {#unaggregated-discovery}
在不使用聚合发现的情况下,发现 API 以不同级别发布,同时根端点为下游文档发布发现信息。
集群支持的所有组版本列表发布在 `/api``/apis` 端点。例如:
```
{
"kind": "APIGroupList",
"apiVersion": "v1",
"groups": [
{
"name": "apiregistration.k8s.io",
"versions": [
{
"groupVersion": "apiregistration.k8s.io/v1",
"version": "v1"
}
],
"preferredVersion": {
"groupVersion": "apiregistration.k8s.io/v1",
"version": "v1"
}
},
{
"name": "apps",
"versions": [
{
"groupVersion": "apps/v1",
"version": "v1"
}
],
"preferredVersion": {
"groupVersion": "apps/v1",
"version": "v1"
}
},
...
}
```
<!--
Additional requests are needed to obtain the discovery document for each group version at
`/apis/<group>/<version>` (for example:
`/apis/rbac.authorization.k8s.io/v1alpha1`), which advertises the list of
resources served under a particular group version. These endpoints are used by
kubectl to fetch the list of resources supported by a cluster.
-->
用户需要发出额外的请求才能在 `/apis/<group>/<version>`(例如 `/apis/rbac.authorization.k8s.io/v1alpha1`
获取每个组版本的发现文档。这些发现文档会公布在特定组版本下所提供的资源列表。
kubectl 使用这些端点来获取某集群所支持的资源列表。
<!-- body -->
<a id="#api-specification" />
<!--
## OpenAPI specification {#api-specification}
## OpenAPI interface definition
Complete API details are documented using [OpenAPI](https://www.openapis.org/).
For details about the OpenAPI specifications, see the [OpenAPI documentation](https://www.openapis.org/).
Kubernetes serves both OpenAPI v2.0 and OpenAPI v3.0. OpenAPI v3 is the
preferred method of accessing the OpenAPI because it offers a more comprehensive
(lossless) representation of Kubernetes resources. Due to limitations of OpenAPI
version 2, certain fields are dropped from the published OpenAPI including but not
limited to `default`, `nullable`, `oneOf`.
-->
## OpenAPI 接口定义 {#openapi-interface-definition}
有关 OpenAPI 规范的细节,参阅 [OpenAPI 文档](https://www.openapis.org/)。
Kubernetes 同时提供 OpenAPI v2.0 和 OpenAPI v3.0。OpenAPI v3 是访问 OpenAPI 的首选方法,
因为它提供了对 Kubernetes 资源更全面(无损)的表示。由于 OpenAPI v2 的限制,
所公布的 OpenAPI 中会丢弃掉一些字段,包括但不限于 `default`、`nullable`、`oneOf`。
<!--
### OpenAPI V2
The Kubernetes API server serves an aggregated OpenAPI v2 spec via the
`/openapi/v2` endpoint. You can request the response format using
request headers as follows:
-->
## OpenAPI 规范 {#api-specification}
完整的 API 细节是用 [OpenAPI](https://www.openapis.org/) 来表述的。
### OpenAPI v2
Kubernetes API 服务器通过 `/openapi/v2` 端点提供聚合的 OpenAPI v2 规范。
@ -144,21 +327,9 @@ Kubernetes API 服务器通过 `/openapi/v2` 端点提供聚合的 OpenAPI v2
</tbody>
</table>
<!--
Kubernetes implements an alternative Protobuf based serialization format that
is primarily intended for intra-cluster communication. For more information
about this format, see the [Kubernetes Protobuf serialization](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md) design proposal and the
Interface Definition Language (IDL) files for each schema located in the Go
packages that define the API objects.
-->
Kubernetes 为 API 实现了一种基于 Protobuf 的序列化格式,主要用于集群内部通信。
关于此格式的详细信息,可参考
[Kubernetes Protobuf 序列化](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md)设计提案。
每种模式对应的接口描述语言IDL位于定义 API 对象的 Go 包中。
### OpenAPI v3
{{< feature-state state="stable" for_k8s_version="v1.27" >}}
{{< feature-state feature_gate_name="OpenAPIV3" >}}
<!--
Kubernetes supports publishing a description of its APIs as OpenAPI v3.
@ -245,9 +416,34 @@ Kubernetes API 服务器会在端点 `/openapi/v3/apis/<group>/<version>?hash=<h
</table>
<!--
A Golang implementation to fetch the OpenAPI V3 is provided in the package `k8s.io/client-go/openapi3`.
A Golang implementation to fetch the OpenAPI V3 is provided in the package
[`k8s.io/client-go/openapi3`](https://pkg.go.dev/k8s.io/client-go/openapi3).
Kubernetes {{< skew currentVersion >}} publishes
OpenAPI v2.0 and v3.0; there are no plans to support 3.1 in the near future.
-->
`k8s.io/client-go/openapi3` 包中提供了获取 OpenAPI v3 的 Golang 实现。
[`k8s.io/client-go/openapi3`](https://pkg.go.dev/k8s.io/client-go/openapi3)
包中提供了获取 OpenAPI v3 的 Golang 实现。
Kubernetes {{< skew currentVersion >}} 发布了 OpenAPI v2.0 和 v3.0
近期没有支持 v3.1 的计划。
<!--
### Protobuf serialization
Kubernetes implements an alternative Protobuf based serialization format that
is primarily intended for intra-cluster communication. For more information
about this format, see the [Kubernetes Protobuf serialization](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md)
design proposal and the
Interface Definition Language (IDL) files for each schema located in the Go
packages that define the API objects.
-->
### Protobuf 序列化 {#protobuf-serialization}
Kubernetes 为 API 实现了一种基于 Protobuf 的序列化格式,主要用于集群内部通信。
关于此格式的详细信息,可参考
[Kubernetes Protobuf 序列化](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md)设计提案。
每种模式对应的接口描述语言IDL位于定义 API 对象的 Go 包中。
<!--
## Persistence

View File

@ -334,7 +334,7 @@ kubelet 具有以下默认硬驱逐条件:
<!--
These default values of hard eviction thresholds will only be set if none
of the parameters is changed. If you changed the value of any parameter,
of the parameters is changed. If you change the value of any parameter,
then the values of other parameters will not be inherited as the default
values and will be set to zero. In order to provide custom values, you
should provide all the thresholds respectively.

View File

@ -222,7 +222,7 @@ called for that node. Nodes may be evaluated concurrently.
### PostFilter {#post-filter}
<!--
These plugins are called after Filter phase, but only when no feasible nodes
These plugins are called after the Filter phase, but only when no feasible nodes
were found for the pod. Plugins are called in their configured order. If
any postFilter plugin marks the node as `Schedulable`, the remaining plugins
will not be called. A typical PostFilter implementation is preemption, which

Some files were not shown because too many files have changed in this diff Show More