Merge branch 'main' into dev-1.26

This commit is contained in:
Tim Bannister 2022-12-03 21:36:34 +00:00
commit 8f9446f87d
No known key found for this signature in database
GPG Key ID: 468B7071483F639F
241 changed files with 6660 additions and 5147 deletions

View File

@ -1,17 +1,16 @@
aliases:
sig-docs-blog-owners: # Approvers for blog content
- onlydole
- mrbobbytables
- sftim
- nate-double-u
- onlydole
- sftim
sig-docs-blog-reviewers: # Reviewers for blog content
- mrbobbytables
- nate-double-u
- onlydole
- sftim
- nate-double-u
sig-docs-localization-owners: # Admins for localization content
- a-mccarthy
- bradtopol
- divya-mohan0209
- jimangel
- kbhawkey
@ -33,7 +32,6 @@ aliases:
- bradtopol
- divya-mohan0209
- jimangel
- jlbutler
- kbhawkey
- krol3
- natalisucks
@ -44,7 +42,6 @@ aliases:
- tengqm
sig-docs-en-reviews: # PR reviews for English content
- bradtopol
- daminisatya
- divya-mohan0209
- jimangel
- kbhawkey
@ -52,7 +49,6 @@ aliases:
- natalisucks
- nate-double-u
- onlydole
- rajeshdeshpande02
- reylejano
- sftim
- shannonxtreme
@ -255,17 +251,19 @@ aliases:
# authoritative source: https://git.k8s.io/sig-release/OWNERS_ALIASES
sig-release-leads:
- cpanato # SIG Technical Lead
- jeremyrickard # SIG Technical Lead
- jeremyrickard # SIG Chair
- justaugustus # SIG Chair
- puerco # SIG Technical Lead
- saschagrunert # SIG Chair
- Verolop # SIG Technical Lead
release-engineering-approvers:
- cpanato # Release Manager
- palnabarun # Release Manager
- puerco # Release Manager
- saschagrunert # subproject owner / Release Manager
- cpanato # subproject owner / Release Manager
- jeremyrickard # subproject owner / Release Manager
- justaugustus # subproject owner / Release Manager
- Verolop # Release Manager
- palnabarun # Release Manager
- puerco # subproject owner / Release Manager
- saschagrunert # subproject owner / Release Manager
- Verolop # subproject owner / Release Manager
- xmudrii # Release Manager
release-engineering-reviewers:
- ameukam # Release Manager Associate

View File

@ -11,5 +11,9 @@
# INSTRUCTIONS AT https://kubernetes.io/security/
divya-mohan0209
jimangel
reylejano
sftim
tengqm
onlydole
kbhawkey
natalisucks

View File

@ -4,9 +4,12 @@ title: "PodSecurityPolicy Deprecation: Past, Present, and Future"
date: 2021-04-06
slug: podsecuritypolicy-deprecation-past-present-and-future
---
**Author:** Tabitha Sable (Kubernetes SIG Security)
{{% pageinfo color="primary" %}}
**Update:** *With the release of Kubernetes v1.25, PodSecurityPolicy has been removed.* *You can read more information about the removal of PodSecurityPolicy in the [Kubernetes 1.25 release notes](/blog/2022/08/23/kubernetes-v1-25-release/#pod-security-changes).*
{{% /pageinfo %}}
PodSecurityPolicy (PSP) is being deprecated in Kubernetes 1.21, to be released later this week. This starts the countdown to its removal, but doesnt change anything else. PodSecurityPolicy will continue to be fully functional for several more releases before being removed completely. In the meantime, we are developing a replacement for PSP that covers key use cases more easily and sustainably.
What are Pod Security Policies? Why did we need them? Why are they going away, and whats next? How does this affect you? These key questions come to mind as we prepare to say goodbye to PSP, so lets walk through them together. Well start with an overview of how features get removed from Kubernetes.

View File

@ -11,7 +11,7 @@ Change is an integral part of the Kubernetes life-cycle: as Kubernetes grows and
## The Kubernetes API Removal and Deprecation process {#k8s-api-deprecation-process}
The Kubernetes project has a [well-documented deprecation policy](https://kubernetes.io/docs/reference/using-api/deprecation-policy/) for features. This policy states that stable APIs may only be deprecated when a newer, stable version of that same API is available and that APIs have a minimum lifetime for each stability level. A deprecated API is one that has been marked for removal in a future Kubernetes release; it will continue to function until removal (at least one year from the deprecation), but usage will result in a warning being displayed. Removed APIs are no longer available in the current version, at which point you must migrate to using the replacement.
The Kubernetes project has a [well-documented deprecation policy](/docs/reference/using-api/deprecation-policy/) for features. This policy states that stable APIs may only be deprecated when a newer, stable version of that same API is available and that APIs have a minimum lifetime for each stability level. A deprecated API is one that has been marked for removal in a future Kubernetes release; it will continue to function until removal (at least one year from the deprecation), but usage will result in a warning being displayed. Removed APIs are no longer available in the current version, at which point you must migrate to using the replacement.
* Generally available (GA) or stable API versions may be marked as deprecated but must not be removed within a major version of Kubernetes.
* Beta or pre-release API versions must be supported for 3 releases after deprecation.
@ -21,7 +21,7 @@ Whether an API is removed as a result of a feature graduating from beta to stabl
## A note about the removal of the CRI `v1alpha2` API and containerd 1.5 support {#cri-api-removal}
Following the adoption of the [Container Runtime Interface](https://kubernetes.io/docs/concepts/architecture/cri/) (CRI) and the [removal of dockershim] in v1.24 , the CRI is the supported and documented way through which Kubernetes interacts withdifferent container runtimes. Each kubelet negotiates which version of CRI to use with the container runtime on that node.
Following the adoption of the [Container Runtime Interface](/docs/concepts/architecture/cri/) (CRI) and the [removal of dockershim] in v1.24 , the CRI is the supported and documented way through which Kubernetes interacts with different container runtimes. Each kubelet negotiates which version of CRI to use with the container runtime on that node.
The Kubernetes project recommends using CRI version `v1`; in Kubernetes v1.25 the kubelet can also negotiate the use of CRI `v1alpha2` (which was deprecated along at the same time as adding support for the stable `v1` interface).
@ -37,11 +37,11 @@ In addition to the above, Kubernetes v1.26 is targeted to include several additi
### Removal of the `v1beta1` flow control API group
The `flowcontrol.apiserver.k8s.io/v1beta1` API version of FlowSchema and PriorityLevelConfiguration [will no longer be served in v1.26](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#flowcontrol-resources-v126). Users should migrate manifests and API clients to use the `flowcontrol.apiserver.k8s.io/v1beta2` API version, available since v1.23.
The `flowcontrol.apiserver.k8s.io/v1beta1` API version of FlowSchema and PriorityLevelConfiguration [will no longer be served in v1.26](/docs/reference/using-api/deprecation-guide/#flowcontrol-resources-v126). Users should migrate manifests and API clients to use the `flowcontrol.apiserver.k8s.io/v1beta2` API version, available since v1.23.
### Removal of the `v2beta2` HorizontalPodAutoscaler API
The `autoscaling/v2beta2` API version of HorizontalPodAutoscaler [will no longer be served in v1.26](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#horizontalpodautoscaler-v126). Users should migrate manifests and API clients to use the `autoscaling/v2` API version, available since v1.23.
The `autoscaling/v2beta2` API version of HorizontalPodAutoscaler [will no longer be served in v1.26](/docs/reference/using-api/deprecation-guide/#horizontalpodautoscaler-v126). Users should migrate manifests and API clients to use the `autoscaling/v2` API version, available since v1.23.
### Removal of in-tree credential management code
@ -64,14 +64,14 @@ The `userspace` proxy mode, deprecated for over a year, is [no longer supported
### Removal of in-tree OpenStack cloud provider
Kubernetes is switching from in-tree code for storage integrations, in favor of the Container Storage Interface (CSI).
As part of this, Kubernetes v1.26 will remove the the deprecated in-tree storage integration for OpenStack
As part of this, Kubernetes v1.26 will remove the deprecated in-tree storage integration for OpenStack
(the `cinder` volume type). You should migrate to external cloud provider and CSI driver from
https://github.com/kubernetes/cloud-provider-openstack instead.
For more information, visit [Cinder in-tree to CSI driver migration](https://github.com/kubernetes/enhancements/issues/1489).
### Removal of the GlusterFS in-tree driver
The in-tree GlusterFS driver was [deprecated in v1.25](https://kubernetes.io/blog/2022/08/23/kubernetes-v1-25-release/#deprecations-and-removals), and will be removed from Kubernetes v1.26.
The in-tree GlusterFS driver was [deprecated in v1.25](/blog/2022/08/23/kubernetes-v1-25-release/#deprecations-and-removals), and will be removed from Kubernetes v1.26.
### Deprecation of non-inclusive `kubectl` flag
@ -91,7 +91,7 @@ Dynamic kubelet configuration was removed from the kubelet in v1.24, and will be
The `--master-service-namespace` command line argument to the kube-apiserver doesn't have
any effect, and was already informally [deprecated](https://github.com/kubernetes/kubernetes/pull/38186).
That command line argument wil be formally marked as deprecated in v1.26, preparing for its
That command line argument will be formally marked as deprecated in v1.26, preparing for its
removal in a future release.
The Kubernetes project does not expect any impact from this deprecation and removal.
@ -108,7 +108,7 @@ Several unused option arguments for the `kubectl run` subcommand will be [marked
* `--timeout`
* `--wait`
These arguments are already ignored so no impact is expected: the explicit deprecation sets a warning message and prepares the removal of the argumentsin a future release.
These arguments are already ignored so no impact is expected: the explicit deprecation sets a warning message and prepares the removal of the arguments in a future release.
### Removal of legacy command line arguments relating to logging
@ -119,7 +119,7 @@ For more information, see [Deprecate klog specific flags in Kubernetes Component
## Looking ahead {#looking-ahead}
The official list of [API removals](https://kubernetes.io/docs/reference/using-api/deprecation-guide/#v1-27) planned for Kubernetes 1.27 includes:
The official list of [API removals](/docs/reference/using-api/deprecation-guide/#v1-27) planned for Kubernetes 1.27 includes:
* All beta versions of the CSIStorageCapacity API; specifically: `storage.k8s.io/v1beta1`

View File

@ -0,0 +1,75 @@
---
layout: blog
title: "registry.k8s.io: faster, cheaper and Generally Available (GA)"
date: 2022-11-28
slug: registry-k8s-io-faster-cheaper-ga
---
**Authors**: Adolfo García Veytia (Chainguard), Bob Killen (Google)
Starting with Kubernetes 1.25, our container image registry has changed from k8s.gcr.io to [registry.k8s.io](https://registry.k8s.io). This new registry spreads the load across multiple Cloud Providers & Regions, functioning as a sort of content delivery network (CDN) for Kubernetes container images. This change reduces the projects reliance on a single entity and provides a faster download experience for a large number of users.
## TL;DR: What you need to know about this change
* Container images for Kubernetes releases from 1.25 onward are no longer published to k8s.gcr.io, only to registry.k8s.io.
* In the upcoming December patch releases, the new registry domain default will be backported to all branches still in support (1.22, 1.23, 1.24).
* If you run in a restricted environment and apply strict domain/IP address access policies limited to k8s.gcr.io, the __image pulls will not function__ after the migration to this new registry. For these users, the recommended method is to mirror the release images to a private registry.
If youd like to know more about why we made this change, or some potential issues you might run into, keep reading.
## Why has Kubernetes changed to a different image registry?
k8s.gcr.io is hosted on a custom [Google Container Registry](https://cloud.google.com/container-registry) (GCR) domain that was setup solely for the Kubernetes project. This has worked well since the inception of the project, and we thank Google for providing these resources, but today there are other cloud providers and vendors that would like to host images to provide a better experience for the people on their platforms. In addition to Googles [renewed commitment to donate $3 million](https://www.cncf.io/google-cloud-recommits-3m-to-kubernetes/) to support the project's infrastructure, Amazon announced a matching donation during their Kubecon NA 2022 keynote in Detroit. This will provide a better experience for users (closer servers = faster downloads) and will reduce the egress bandwidth and costs from GCR at the same time. registry.k8s.io will spread the load between Google and Amazon, with other providers to follow in the future.
## Why isnt there a stable list of domains/IPs? Why cant I restrict image pulls?
registry.k8s.io is a [secure blob redirector](https://github.com/kubernetes/registry.k8s.io/blob/main/cmd/archeio/docs/request-handling.md) that connects clients to the closest cloud provider. The nature of this change means that a client pulling an image could be redirected to any one of a large number of backends. We expect the set of backends to keep changing and will only increase as more and more cloud providers and vendors come on board to help mirror the release images.
Restrictive control mechanisms like man-in-the-middle proxies or network policies that restrict access to a specific list of IPs/domains will break with this change. For these scenarios, we encourage you to mirror the release images to a local registry that you have strict control over.
For more information on this policy, please see the [stability section of the registry.k8s.io documentation](https://github.com/kubernetes/registry.k8s.io#stability).
## What kind of errors will I see? How will I know if Im still using the old address?
Errors may depend on what kind of container runtime you are using, and what endpoint you are routed to, but it should present as a container failing to be created with the warning `FailedCreatePodSandBox`.
Below is an example error message showing a proxied deployment failing to pull due to an unknown certificate:
```
FailedCreatePodSandBox: Failed to create pod sandbox: rpc error: code = Unknown desc = Error response from daemon: Head “https://us-west1-docker.pkg.dev/v2/k8s-artifacts-prod/images/pause/manifests/3.8”: x509: certificate signed by unknown authority
```
## Im impacted by this change, how do I revert to the old registry address?
If using the new registry domain name is not an option, you can revert to the old domain name for cluster versions less than 1.25. Keep in mind that, eventually, you will have to switch to the new registry, as new image tags will no longer be pushed to GCR.
### Reverting the registry name in kubeadm
The registry used by kubeadm to pull its images can be controlled by two methods:
Setting the `--image-repository` flag.
```
kubeadm init --image-repository=k8s.gcr.io
```
Or in [kubeadm config](https://kubernetes.io/docs/reference/config-api/kubeadm-config.v1beta3/) `ClusterConfiguration`:
```yaml
apiVersion: kubeadm.k8s.io/v1beta3
kind: ClusterConfiguration
imageRepository: "k8s.gcr.io"
```
### Reverting the Registry Name in kubelet
The image used by kubelet for the pod sandbox (`pause`) can be overridden by setting the `--pod-infra-container-image` flag. For example:
```
kubelet --pod-infra-container-image=k8s.gcr.io/pause:3.5
```
## Acknowledgments
__Change is hard__, and evolving our image-serving platform is needed to ensure a sustainable future for the project. We strive to make things better for everyone using Kubernetes. Many contributors from all corners of our community have been working long and hard to ensure we are making the best decisions possible, executing plans, and doing our best to communicate those plans.
Thanks to Aaron Crickenberger, Arnaud Meukam, Benjamin Elder, Caleb Woodbine, Davanum Srinivas, Mahamed Ali, and Tim Hockin from SIG K8s Infra, Brian McQueen, and Sergey Kanzhelev from SIG Node, Lubomir Ivanov from SIG Cluster Lifecycle, Adolfo García Veytia, Jeremy Rickard, Sascha Grunert, and Stephen Augustus from SIG Release, Bob Killen and Kaslin Fields from SIG Contribex, Tim Allclair from the Security Response Committee. Also a big thank you to our friends acting as liaisons with our cloud provider partners: Jay Pipes from Amazon and Jon Johnson Jr. from Google.

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 KiB

View File

@ -0,0 +1,279 @@
---
layout: blog
title: "Boosting Kubernetes container runtime observability with OpenTelemetry"
date: 2022-12-01
slug: runtime-observability-opentelemetry
---
**Authors:** Sascha Grunert
When speaking about observability in the cloud native space, then probably
everyone will mention [OpenTelemetry (OTEL)][otel] at some point in the
conversation. That's great, because the community needs standards to rely on
for developing all cluster components into the same direction. OpenTelemetry
enables us to combine logs, metrics, traces and other contextual information
(called baggage) into a single resource. Cluster administrators or software
engineers can use this resource to get a viewport about what is going on in the
cluster over a defined period of time. But how can Kubernetes itself make use of
this technology stack?
[otel]: https://opentelemetry.io
Kubernetes consists of multiple components where some are independent and others
are stacked together. Looking at the architecture from a container runtime
perspective, then there are from the top to the bottom:
- **kube-apiserver**: Validates and configures data for the API objects
- **kubelet**: Agent running on each node
- **CRI runtime**: Container Runtime Interface (CRI) compatible container runtime
like [CRI-O][crio] or [containerd][containerd]
- **OCI runtime**: Lower level [Open Container Initiative (OCI)][oci] runtime
like [runc][runc] or [crun][crun]
- **Linux kernel** or **Microsoft Windows**: Underlying operating system
[crio]: https://cri-o.io
[containerd]: https://containerd.io
[oci]: https://opencontainers.org
[runc]: https://github.com/opencontainers/runc
[crun]: https://github.com/containers/crun
That means if we encounter a problem with running containers in Kubernetes, then
we start looking at one of those components. Finding the root cause for problems
is one of the most time consuming actions we face with the increased
architectural complexity from today's cluster setups. Even if we know the
component which seems to cause the issue, we still have to take the others into
account to maintain a mental timeline of events which are going on. How do we
achieve that? Well, most folks will probably stick to scraping logs, filtering
them and assembling them together over the components borders. We also have
metrics, right? Correct, but bringing metrics values in correlation with plain
logs makes it even harder to track what is going on. Some metrics are also not
made for debugging purposes. They have been defined based on the end user
perspective of the cluster for linking usable alerts and not for developers
debugging a cluster setup.
OpenTelemetry to the rescue: the project aims to combine signals such as
[traces][traces], [metrics][metrics] and [logs][logs] together to maintain the
right viewport on the cluster state.
[traces]: https://opentelemetry.io/docs/concepts/signals/traces
[metrics]: https://opentelemetry.io/docs/concepts/signals/metrics
[logs]: https://opentelemetry.io/docs/concepts/signals/logs
What is the current state of OpenTelemetry tracing in Kubernetes? From an API
server perspective, we have alpha support for tracing since Kubernetes v1.22,
which will graduate to beta in one of the upcoming releases. Unfortunately the
beta graduation has missed the v1.26 Kubernetes release. The design proposal can
be found in the [_API Server Tracing_ Kubernetes Enhancement Proposal
(KEP)][kep-647] which provides more information about it.
[kep-647]: https://github.com/kubernetes/enhancements/issues/647
The kubelet tracing part is tracked [in another KEP][kep-2831], which was
implemented in an alpha state in Kubernetes v1.25. A beta graduation is not
planned as time of writing, but more may come in the v1.27 release cycle.
There are other side-efforts going on beside both KEPs, for example [klog is
considering OTEL support][klog-otel], which would boost the observability by
linking log messages to existing traces. Within SIG Instrumentation and SIG Node,
we're also discussing [how to link the
kubelet traces together][issue-113414], because right now they're focused on the
[gRPC][grpc] calls between the kubelet and the CRI container runtime.
[kep-647]: https://github.com/kubernetes/enhancements/issues/647
[kep-2831]: https://github.com/kubernetes/enhancements/issues/2831
[klog-otel]: https://github.com/kubernetes/klog/issues/356
[issue-113414]: https://github.com/kubernetes/kubernetes/issues/113414
[grpc]: https://grpc.io
CRI-O features OpenTelemetry tracing support [since v1.23.0][pr-4883] and is
working on continuously improving them, for example by [attaching the logs to the
traces][pr-6294] or extending the [spans to logical parts of the
application][pr-6343]. This helps users of the traces to gain the same
information like parsing the logs, but with enhanced capabilities of scoping and
filtering to other OTEL signals. The CRI-O maintainers are also working on a
container monitoring replacement for [conmon][conmon], which is called
[conmon-rs][conmon-rs] and is purely written in [Rust][rust]. One benefit of
having a Rust implementation is to be able to add features like OpenTelemetry
support, because the crates (libraries) for those already exist. This allows a
tight integration with CRI-O and lets consumers see the most low level tracing
data from their containers.
[pr-4883]: https://github.com/cri-o/cri-o/pull/4883
[pr-6294]: https://github.com/cri-o/cri-o/pull/6294
[pr-6343]: https://github.com/cri-o/cri-o/pull/6343
[conmon]: https://github.com/containers/conmon
[conmon-rs]: https://github.com/containers/conmon-rs
[rust]: https://www.rust-lang.org
The [containerd][containerd] folks added tracing support since v1.6.0, which is
available [by using a plugin][containerd-docs]. Lower level OCI runtimes like
[runc][runc] or [crun][crun] feature no support for OTEL at all and it does not
seem to exist a plan for that. We always have to consider that there is a
performance overhead when collecting the traces as well as exporting them to a
data sink. I still think it would be worth an evaluation on how extended
telemetry collection could look like in OCI runtimes. Let's see if the Rust OCI
runtime [youki][youki-1348] is considering something like that in the future.
[containerd-docs]: https://github.com/containerd/containerd/blob/7def13d/docs/tracing.md
[youki-1348]: https://github.com/containers/youki/issues/1348
I'll show you how to give it a try. For my demo I'll stick to a stack with a single local node
that has runc, conmon-rs, CRI-O, and a kubelet. To enable tracing in the kubelet, I need to
apply the following `KubeletConfiguration`:
```yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
KubeletTracing: true
tracing:
samplingRatePerMillion: 1000000
```
A `samplingRatePerMillion` equally to one million will internally translate to
sampling everything. A similar configuration has to be applied to CRI-O; I can
either start the `crio` binary with `--enable-tracing` and
`--tracing-sampling-rate-per-million 1000000` or we use a drop-in configuration
like this:
```shell
cat /etc/crio/crio.conf.d/99-tracing.conf
```
```toml
[crio.tracing]
enable_tracing = true
tracing_sampling_rate_per_million = 1000000
```
To configure CRI-O to use conmon-rs, you require at least the latest CRI-O
v1.25.x and conmon-rs v0.4.0. Then a configuration drop-in like this can be used
to make CRI-O use conmon-rs:
```shell
cat /etc/crio/crio.conf.d/99-runtimes.conf
```
```toml
[crio.runtime]
default_runtime = "runc"
[crio.runtime.runtimes.runc]
runtime_type = "pod"
monitor_path = "/path/to/conmonrs" # or will be looked up in $PATH
```
That's it, the default configuration will point to an [OpenTelemetry
collector][collector] [gRPC][grpc] endpoint of `localhost:4317`, which has to be up and
running as well. There are multiple ways to run OTLP as [described in the
docs][collector], but it's also possible to `kubectl proxy` into an existing
instance running within Kubernetes.
[collector]: https://opentelemetry.io/docs/collector/getting-started
If everything is set up, then the collector should log that there are incoming
traces:
```
ScopeSpans #0
ScopeSpans SchemaURL:
InstrumentationScope go.opentelemetry.io/otel/sdk/tracer
Span #0
Trace ID : 71896e69f7d337730dfedb6356e74f01
Parent ID : a2a7714534c017e6
ID : 1d27dbaf38b9da8b
Name : github.com/cri-o/cri-o/server.(*Server).filterSandboxList
Kind : SPAN_KIND_INTERNAL
Start time : 2022-11-15 09:50:20.060325562 +0000 UTC
End time : 2022-11-15 09:50:20.060326291 +0000 UTC
Status code : STATUS_CODE_UNSET
Status message :
Span #1
Trace ID : 71896e69f7d337730dfedb6356e74f01
Parent ID : a837a005d4389579
ID : a2a7714534c017e6
Name : github.com/cri-o/cri-o/server.(*Server).ListPodSandbox
Kind : SPAN_KIND_INTERNAL
Start time : 2022-11-15 09:50:20.060321973 +0000 UTC
End time : 2022-11-15 09:50:20.060330602 +0000 UTC
Status code : STATUS_CODE_UNSET
Status message :
Span #2
Trace ID : fae6742709d51a9b6606b6cb9f381b96
Parent ID : 3755d12b32610516
ID : 0492afd26519b4b0
Name : github.com/cri-o/cri-o/server.(*Server).filterContainerList
Kind : SPAN_KIND_INTERNAL
Start time : 2022-11-15 09:50:20.0607746 +0000 UTC
End time : 2022-11-15 09:50:20.060795505 +0000 UTC
Status code : STATUS_CODE_UNSET
Status message :
Events:
SpanEvent #0
-> Name: log
-> Timestamp: 2022-11-15 09:50:20.060778668 +0000 UTC
-> DroppedAttributesCount: 0
-> Attributes::
-> id: Str(adf791e5-2eb8-4425-b092-f217923fef93)
-> log.message: Str(No filters were applied, returning full container list)
-> log.severity: Str(DEBUG)
-> name: Str(/runtime.v1.RuntimeService/ListContainers)
```
I can see that the spans have a trace ID and typically have a parent attached.
Events such as logs are part of the output as well. In the above case, the kubelet is
periodically triggering a `ListPodSandbox` RPC to CRI-O caused by the Pod
Lifecycle Event Generator (PLEG). Displaying those traces can be done via,
for example, [Jaeger][jaeger]. When running the tracing stack locally, then a Jaeger
instance should be exposed on `http://localhost:16686` per default.
[jaeger]: https://www.jaegertracing.io/
The `ListPodSandbox` requests are directly visible within the Jaeger UI:
![ListPodSandbox RPC in the Jaeger UI](list_pod_sandbox.png)
That's not too exciting, so I'll run a workload directly via `kubectl`:
```shell
kubectl run -it --rm --restart=Never --image=alpine alpine -- echo hi
```
```
hi
pod "alpine" deleted
```
Looking now at Jaeger, we can see that we have traces for `conmonrs`, `crio` as
well as the `kubelet` for the `RunPodSandbox` and `CreateContainer` CRI RPCs:
![Container creation in the Jaeger UI](create_container.png)
The kubelet and CRI-O spans are connected to each other to make investigation
easier. If we now take a closer look at the spans, then we can see that CRI-O's
logs are correctly accosted with the corresponding functionality. For example we
can extract the container user from the traces like this:
![CRI-O in the Jaeger UI](crio_spans.png)
The lower level spans of conmon-rs are also part of this trace. For example
conmon-rs maintains an internal `read_loop` for handling IO between the
container and the end user. The logs for reading and writing bytes are part of
the span. The same applies to the `wait_for_exit_code` span, which tells us that
the container exited successfully with code `0`:
![conmon-rs in the Jaeger UI](conmonrs_spans.png)
Having all that information at hand side by side to the filtering capabilities
of Jaeger makes the whole stack a great solution for debugging container issues!
Mentioning the "whole stack" also shows the biggest downside of the overall
approach: Compared to parsing logs it adds a noticeable overhead on top of the
cluster setup. Users have to maintain a sink like [Elasticsearch][elastic] to
persist the data, expose the Jaeger UI and possibly take the performance
drawback into account. Anyways, it's still one of the best ways to increase the
observability aspect of Kubernetes.
[elastic]: https://www.elastic.co
Thank you for reading this blog post, I'm pretty sure we're looking into a
bright future for OpenTelemetry support in Kubernetes to make troubleshooting
simpler.

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,346 @@
---
layout: blog
title: "Finding suspicious syscalls with the seccomp notifier"
date: 2022-12-02
slug: seccomp-notifier
---
**Authors:** Sascha Grunert
Debugging software in production is one of the biggest challenges we have to
face in our containerized environments. Being able to understand the impact of
the available security options, especially when it comes to configuring our
deployments, is one of the key aspects to make the default security in
Kubernetes stronger. We have all those logging, tracing and metrics data already
at hand, but how do we assemble the information they provide into something
human readable and actionable?
[Seccomp][seccomp] is one of the standard mechanisms to protect a Linux based
Kubernetes application from malicious actions by interfering with its [system
calls][syscalls]. This allows us to restrict the application to a defined set of
actionable items, like modifying files or responding to HTTP requests. Linking
the knowledge of which set of syscalls is required to, for example, modify a
local file, to the actual source code is in the same way non-trivial. Seccomp
profiles for Kubernetes have to be written in [JSON][json] and can be understood
as an architecture specific allow-list with superpowers, for example:
[seccomp]: https://en.wikipedia.org/wiki/Seccomp
[syscalls]: https://en.wikipedia.org/wiki/Syscall
[json]: https://www.json.org
```json
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"defaultErrno": "ENOSYS",
"syscalls": [
{
"names": ["chmod", "chown", "open", "write"],
"action": "SCMP_ACT_ALLOW"
}
]
}
```
The above profile errors by default specifying the `defaultAction` of
`SCMP_ACT_ERRNO`. This means we have to allow a set of syscalls via
`SCMP_ACT_ALLOW`, otherwise the application would not be able to do anything at
all. Okay cool, for being able to allow file operations, all we have to do is
adding a bunch of file specific syscalls like `open` or `write`, and probably
also being able to change the permissions via `chmod` and `chown`, right?
Basically yes, but there are issues with the simplicity of that approach:
Seccomp profiles need to include the minimum set of syscalls required to start
the application. This also includes some syscalls from the lower level
[Open Container Initiative (OCI)][oci] container runtime, for example
[runc][runc] or [crun][crun]. Beside that, we can only guarantee the required
syscalls for a very specific version of the runtimes and our application,
because the code parts can change between releases. The same applies to the
termination of the application as well as the target architecture we're
deploying on. Features like executing commands within containers also require
another subset of syscalls. Not to mention that there are multiple versions for
syscalls doing slightly different things and the seccomp profiles are able to
modify their arguments. It's also not always clearly visible to the developers
which syscalls are used by their own written code parts, because they rely on
programming language abstractions or frameworks.
[oci]: https://opencontainers.org
[runc]: https://github.com/opencontainers/runc
[crun]: https://github.com/containers/crun
_How can we know which syscalls are even required then? Who should create and
maintain those profiles during its development life-cycle?_
Well, recording and distributing seccomp profiles is one of the problem domains
of the [Security Profiles Operator][spo], which is already solving that. The
operator is able to record [seccomp][seccomp], [SELinux][selinux] and even
[AppArmor][apparmor] profiles into a [Custom Resource Definition (CRD)][crd],
reconciles them to each node and makes them available for usage.
[spo]: https://github.com/kubernetes-sigs/security-profiles-operator
[selinux]: https://en.wikipedia.org/wiki/Security-Enhanced_Linux
[apparmor]: https://en.wikipedia.org/wiki/AppArmor
[crd]: https://k8s.io/docs/concepts/extend-kubernetes/api-extension/custom-resources
The biggest challenge about creating security profiles is to catch all code
paths which execute syscalls. We could achieve that by having **100%** logical
coverage of the application when running an end-to-end test suite. You get the
problem with the previous statement: It's too idealistic to be ever fulfilled,
even without taking all the moving parts during application development and
deployment into account.
Missing a syscall in the seccomp profiles' allow list can have tremendously
negative impact on the application. It's not only that we can encounter crashes,
which are trivially detectable. It can also happen that they slightly change
logical paths, change the business logic, make parts of the application
unusable, slow down performance or even expose security vulnerabilities. We're
simply not able to see the whole impact of that, especially because blocked
syscalls via `SCMP_ACT_ERRNO` do not provide any additional [audit][audit]
logging on the system.
[audit]: https://linux.die.net/man/8/auditd
Does that mean we're lost? Is it just not realistic to dream about a Kubernetes
where [everyone uses the default seccomp profile][seccomp-default]? Should we
stop striving towards maximum security in Kubernetes and accept that it's not
meant to be secure by default?
[seccomp-default]: https://github.com/kubernetes/enhancements/issues/2413
**Definitely not.** Technology evolves over time and there are many folks
working behind the scenes of Kubernetes to indirectly deliver features to
address such problems. One of the mentioned features is the _seccomp notifier_,
which can be used to find suspicious syscalls in Kubernetes.
The seccomp notify feature consists of a set of changes introduced in Linux 5.9.
It makes the kernel capable of communicating seccomp related events to the user
space. That allows applications to act based on the syscalls and opens for a
wide range of possible use cases. We not only need the right kernel version,
but also at least runc v1.1.0 (or crun v0.19) to be able to make the notifier
work at all. The Kubernetes container runtime [CRI-O][cri-o] gets [support for
the seccomp notifier in v1.26.0][cri-o-notifier]. The new feature allows us to
identify possibly malicious syscalls in our application, and therefore makes it
possible to verify profiles for consistency and completeness. Let's give that a
try.
[cri-o]: https://cri-o.io
[cri-o-notifier]: https://github.com/cri-o/cri-o/pull/6120
First of all we need to run the latest `main` version of CRI-O, because v1.26.0
has not been released yet at time of writing. You can do that by either
compiling it from the [source code][sources] or by using the pre-built binary
bundle via [the get-script][script]. The seccomp notifier feature of CRI-O is
guarded by an annotation, which has to be explicitly allowed, for example by
using a configuration drop-in like this:
```console
> cat /etc/crio/crio.conf.d/02-runtimes.conf
```
```toml
[crio.runtime]
default_runtime = "runc"
[crio.runtime.runtimes.runc]
allowed_annotations = [ "io.kubernetes.cri-o.seccompNotifierAction" ]
```
[sources]: https://github.com/cri-o/cri-o/blob/main/install.md#build-and-install-cri-o-from-source
[script]: https://github.com/cri-o/cri-o#installing-cri-o
If CRI-O is up and running, then it should indicate that the seccomp notifier is
available as well:
```console
> sudo ./bin/crio --enable-metrics
INFO[…] Starting seccomp notifier watcher
INFO[…] Serving metrics on :9090 via HTTP
```
We also enable the metrics, because they provide additional telemetry data about
the notifier. Now we need a running Kubernetes cluster for demonstration
purposes. For this demo, we mainly stick to the
[`hack/local-up-cluster.sh`][local-up] approach to locally spawn a single node
Kubernetes cluster.
[local-up]: https://github.com/cri-o/cri-o#running-kubernetes-with-cri-o
If everything is up and running, then we would have to define a seccomp profile
for testing purposes. But we do not have to create our own, we can just use the
`RuntimeDefault` profile which gets shipped with each container runtime. For
example the `RuntimeDefault` profile for CRI-O can be found in the
[containers/common][runtime-default] library.
[runtime-default]: https://github.com/containers/common/blob/afff1d6/pkg/seccomp/seccomp.json
Now we need a test container, which can be a simple [nginx][nginx] pod like
this:
[nginx]: https://www.nginx.com
```yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
annotations:
io.kubernetes.cri-o.seccompNotifierAction: "stop"
spec:
restartPolicy: Never
containers:
- name: nginx
image: nginx:1.23.2
securityContext:
seccompProfile:
type: RuntimeDefault
```
Please note the annotation `io.kubernetes.cri-o.seccompNotifierAction`, which
enables the seccomp notifier for this workload. The value of the annotation can
be either `stop` for stopping the workload or anything else for doing nothing
else than logging and throwing metrics. Because of the termination we also use
the `restartPolicy: Never` to not automatically recreate the container on
failure.
Let's run the pod and check if it works:
```console
> kubectl apply -f nginx.yaml
```
```console
> kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx 1/1 Running 0 3m39s 10.85.0.3 127.0.0.1 <none> <none>
```
We can also test if the web server itself works as intended:
```console
> curl 10.85.0.3
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
```
While everything is now up and running, CRI-O also indicates that it has started
the seccomp notifier:
```
INFO[…] Injecting seccomp notifier into seccomp profile of container 662a3bb0fdc7dd1bf5a88a8aa8ef9eba6296b593146d988b4a9b85822422febb
```
If we would now run a forbidden syscall inside of the container, then we can
expect that the workload gets terminated. Let's give that a try by running
`chroot` in the containers namespaces:
```console
> kubectl exec -it nginx -- bash
```
```console
root@nginx:/# chroot /tmp
chroot: cannot change root directory to '/tmp': Function not implemented
root@nginx:/# command terminated with exit code 137
```
The exec session got terminated, so it looks like the container is not running
any more:
```console
> kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 seccomp killed 0 96s
```
Alright, the container got killed by seccomp, do we get any more information
about what was going on?
```console
> kubectl describe pod nginx
Name: nginx
Containers:
nginx:
State: Terminated
Reason: seccomp killed
Message: Used forbidden syscalls: chroot (1x)
Exit Code: 137
Started: Mon, 14 Nov 2022 12:19:46 +0100
Finished: Mon, 14 Nov 2022 12:20:26 +0100
```
The seccomp notifier feature of CRI-O correctly set the termination reason and
message, including which forbidden syscall has been used how often (`1x`). How
often? Yes, the notifier gives the application up to 5 seconds after the last
seen syscall until it starts the termination. This means that it's possible to
catch multiple forbidden syscalls within one test by avoiding time-consuming
trial and errors.
```console
> kubectl exec -it nginx -- chroot /tmp
chroot: cannot change root directory to '/tmp': Function not implemented
command terminated with exit code 125
> kubectl exec -it nginx -- chroot /tmp
chroot: cannot change root directory to '/tmp': Function not implemented
command terminated with exit code 125
> kubectl exec -it nginx -- swapoff -a
command terminated with exit code 32
> kubectl exec -it nginx -- swapoff -a
command terminated with exit code 32
```
```console
> kubectl describe pod nginx | grep Message
Message: Used forbidden syscalls: chroot (2x), swapoff (2x)
```
The CRI-O metrics will also reflect that:
```console
> curl -sf localhost:9090/metrics | grep seccomp_notifier
# HELP container_runtime_crio_containers_seccomp_notifier_count_total Amount of containers stopped because they used a forbidden syscalls by their name
# TYPE container_runtime_crio_containers_seccomp_notifier_count_total counter
container_runtime_crio_containers_seccomp_notifier_count_total{name="…",syscalls="chroot (1x)"} 1
container_runtime_crio_containers_seccomp_notifier_count_total{name="…",syscalls="chroot (2x), swapoff (2x)"} 1
```
How does it work in detail? CRI-O uses the chosen seccomp profile and injects
the action `SCMP_ACT_NOTIFY` instead of `SCMP_ACT_ERRNO`, `SCMP_ACT_KILL`,
`SCMP_ACT_KILL_PROCESS` or `SCMP_ACT_KILL_THREAD`. It also sets a local listener
path which will be used by the lower level OCI runtime (runc or crun) to create
the seccomp notifier socket. If the connection between the socket and CRI-O has
been established, then CRI-O will receive notifications for each syscall being
interfered by seccomp. CRI-O stores the syscalls, allows a bit of timeout for
them to arrive and then terminates the container if the chosen
`seccompNotifierAction=stop`. Unfortunately, the seccomp notifier is not able to
notify on the `defaultAction`, which means that it's required to have
a list of syscalls to test for custom profiles. CRI-O does also state that
limitation in the logs:
```log
INFO[…] The seccomp profile default action SCMP_ACT_ERRNO cannot be overridden to SCMP_ACT_NOTIFY,
which means that syscalls using that default action can't be traced by the notifier
```
As a conclusion, the seccomp notifier implementation in CRI-O can be used to
verify if your applications behave correctly when using `RuntimeDefault` or any
other custom profile. Alerts can be created based on the metrics to create long
running test scenarios around that feature. Making seccomp understandable and
easier to use will increase adoption as well as help us to move towards a more
secure Kubernetes by default!
Thank you for reading this blog post. If you'd like to read more about the
seccomp notifier, checkout the following resources:
- The Seccomp Notifier - New Frontiers in Unprivileged Container Development: https://brauner.io/2020/07/23/seccomp-notify.html
- Bringing Seccomp Notify to Runc and Kubernetes: https://kinvolk.io/blog/2022/03/bringing-seccomp-notify-to-runc-and-kubernetes
- Seccomp Agent reference implementation: https://github.com/opencontainers/runc/tree/6b16d00/contrib/cmd/seccompagent

View File

@ -0,0 +1,209 @@
---
layout: blog
title: "Forensic container checkpointing in Kubernetes"
date: 2022-12-05
slug: forensic-container-checkpointing-alpha
---
**Authors:** Adrian Reber (Red Hat)
Forensic container checkpointing is based on [Checkpoint/Restore In
Userspace](https://criu.org/) (CRIU) and allows the creation of stateful copies
of a running container without the container knowing that it is being
checkpointed. The copy of the container can be analyzed and restored in a
sandbox environment multiple times without the original container being aware
of it. Forensic container checkpointing was introduced as an alpha feature in
Kubernetes v1.25.
## How does it work?
With the help of CRIU it is possible to checkpoint and restore containers.
CRIU is integrated in runc, crun, CRI-O and containerd and forensic container
checkpointing as implemented in Kubernetes uses these existing CRIU
integrations.
## Why is it important?
With the help of CRIU and the corresponding integrations it is possible to get
all information and state about a running container on disk for later forensic
analysis. Forensic analysis might be important to inspect a suspicious
container without stopping or influencing it. If the container is really under
attack, the attacker might detect attempts to inspect the container. Taking a
checkpoint and analysing the container in a sandboxed environment offers the
possibility to inspect the container without the original container and maybe
attacker being aware of the inspection.
In addition to the forensic container checkpointing use case, it is also
possible to migrate a container from one node to another node without loosing
the internal state. Especially for stateful containers with long initialization
times restoring from a checkpoint might save time after a reboot or enable much
faster startup times.
## How do I use container checkpointing?
The feature is behind a [feature gate][container-checkpoint-feature-gate], so
make sure to enable the `ContainerCheckpoint` gate before you can use the new
feature.
The runtime must also support container checkpointing:
* containerd: support is currently under discussion. See containerd
pull request [#6965][containerd-checkpoint-restore-pr] for more details.
* CRI-O: v1.25 has support for forensic container checkpointing.
[containerd-checkpoint-restore-pr]: https://github.com/containerd/containerd/pull/6965
[container-checkpoint-feature-gate]: https://kubernetes.io/docs/reference/command-line-tools-reference/feature-gates/
### Usage example with CRI-O
To use forensic container checkpointing in combination with CRI-O, the runtime
needs to be started with the command-line option `--enable-criu-support=true`.
For Kubernetes, you need to run your cluster with the `ContainerCheckpoint`
feature gate enabled. As the checkpointing functionality is provided by CRIU it
is also necessary to install CRIU. Usually runc or crun depend on CRIU and
therefore it is installed automatically.
It is also important to mention that at the time of writing the checkpointing functionality is
to be considered as an alpha level feature in CRI-O and Kubernetes and the
security implications are still under consideration.
Once containers and pods are running it is possible to create a checkpoint.
[Checkpointing](https://kubernetes.io/docs/reference/node/kubelet-checkpoint-api/)
is currently only exposed on the **kubelet** level. To checkpoint a container,
you can run `curl` on the node where that container is running, and trigger a
checkpoint:
```shell
curl -X POST "https://localhost:10250/checkpoint/namespace/podId/container"
```
For a container named *counter* in a pod named *counters* in a namespace named
*default* the **kubelet** API endpoint is reachable at:
```shell
curl -X POST "https://localhost:10250/checkpoint/default/counters/counter"
```
For completeness the following `curl` command-line options are necessary to
have `curl` accept the *kubelet*'s self signed certificate and authorize the
use of the *kubelet* `checkpoint` API:
```shell
--insecure --cert /var/run/kubernetes/client-admin.crt --key /var/run/kubernetes/client-admin.key
```
Triggering this **kubelet** API will request the creation of a checkpoint from
CRI-O. CRI-O requests a checkpoint from your low-level runtime (for example,
`runc`). Seeing that request, `runc` invokes the `criu` tool
to do the actual checkpointing.
Once the checkpointing has finished the checkpoint should be available at
`/var/lib/kubelet/checkpoints/checkpoint-<pod-name>_<namespace-name>-<container-name>-<timestamp>.tar`
You could then use that tar archive to restore the container somewhere else.
### Restore a checkpointed container outside of Kubernetes (with CRI-O) {#restore-checkpointed-container-standalone}
With the checkpoint tar archive it is possible to restore the container outside
of Kubernetes in a sandboxed instance of CRI-O. For better user experience
during restore, I recommend that you use the latest version of CRI-O from the
*main* CRI-O GitHub branch. If you're using CRI-O v1.25, you'll need to
manually create certain directories Kubernetes would create before starting the
container.
The first step to restore a container outside of Kubernetes is to create a pod sandbox
using *crictl*:
```shell
crictl runp pod-config.json
```
Then you can restore the previously checkpointed container into the newly created pod sandbox:
```shell
crictl create <POD_ID> container-config.json pod-config.json
```
Instead of specifying a container image in a registry in `container-config.json`
you need to specify the path to the checkpoint archive that you created earlier:
```json
{
"metadata": {
"name": "counter"
},
"image":{
"image": "/var/lib/kubelet/checkpoints/<checkpoint-archive>.tar"
}
}
```
Next, run `crictl start <CONTAINER_ID>` to start that container, and then a
copy of the previously checkpointed container should be running.
### Restore a checkpointed container within of Kubernetes {#restore-checkpointed-container-k8s}
To restore the previously checkpointed container directly in Kubernetes it is
necessary to convert the checkpoint archive into an image that can be pushed to
a registry.
One possible way to convert the local checkpoint archive consists of the
following steps with the help of [buildah](https://buildah.io/):
```shell
newcontainer=$(buildah from scratch)
buildah add $newcontainer /var/lib/kubelet/checkpoints/checkpoint-<pod-name>_<namespace-name>-<container-name>-<timestamp>.tar /
buildah config --annotation=io.kubernetes.cri-o.annotations.checkpoint.name=<container-name> $newcontainer
buildah commit $newcontainer checkpoint-image:latest
buildah rm $newcontainer
```
The resulting image is not standardized and only works in combination with
CRI-O. Please consider this image format as pre-alpha. There are ongoing
[discussions][image-spec-discussion] to standardize the format of checkpoint
images like this. Important to remember is that this not yet standardized image
format only works if CRI-O has been started with `--enable-criu-support=true`.
The security implications of starting CRI-O with CRIU support are not yet clear
and therefore the functionality as well as the image format should be used with
care.
Now, you'll need to push that image to a container image registry. For example:
```shell
buildah push localhost/checkpoint-image:latest container-image-registry.example/user/checkpoint-image:latest
```
To restore this checkpoint image (`container-image-registry.example/user/checkpoint-image:latest`), the
image needs to be listed in the specification for a Pod. Here's an example
manifest:
```yaml
apiVersion: v1
kind: Pod
metadata:
namePrefix: example-
spec:
containers:
- name: <container-name>
image: container-image-registry.example/user/checkpoint-image:latest
nodeName: <destination-node>
```
Kubernetes schedules the new Pod onto a node. The kubelet on that node
instructs the container runtime (CRI-O in this example) to create and start a
container based on an image specified as `registry/user/checkpoint-image:latest`.
CRI-O detects that `registry/user/checkpoint-image:latest`
is a reference to checkpoint data rather than a container image. Then,
instead of the usual steps to create and start a container,
CRI-O fetches the checkpoint data and restores the container from that
specified checkpoint.
The application in that Pod would continue running as if the checkpoint had not been taken;
within the container, the application looks and behaves like any other container that had been
started normally and not restored from a checkpoint.
With these steps, it is possible to replace a Pod running on one node
with a new equivalent Pod that is running on a different node,
and without losing the state of the containers in that Pod.
[image-spec-discussion]: https://github.com/opencontainers/image-spec/issues/962
## How do I get involved?
You can reach SIG Node by several means:
- Slack: [#sig-node](https://kubernetes.slack.com/messages/sig-node)
- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-node)

View File

@ -52,20 +52,20 @@ for a general explanation of feature gates and how to enable and
disable them. The name of the feature gate for APF is
"APIPriorityAndFairness". This feature also involves an {{<
glossary_tooltip term_id="api-group" text="API Group" >}} with: (a) a
`v1alpha1` version, disabled by default, and (b) `v1beta1` and
`v1beta2` versions, enabled by default. You can disable the feature
gate and API group beta versions by adding the following
command-line flags to your `kube-apiserver` invocation:
`v1alpha1` version and a `v1beta1` version, disabled by default, and
(b) `v1beta2` and `v1beta3` versions, enabled by default. You can
disable the feature gate and API group beta versions by adding the
following command-line flags to your `kube-apiserver` invocation:
```shell
kube-apiserver \
--feature-gates=APIPriorityAndFairness=false \
--runtime-config=flowcontrol.apiserver.k8s.io/v1beta1=false,flowcontrol.apiserver.k8s.io/v1beta2=false \
--runtime-config=flowcontrol.apiserver.k8s.io/v1beta2=false,flowcontrol.apiserver.k8s.io/v1beta3=false \
# …and other flags as usual
```
Alternatively, you can enable the v1alpha1 version of the API group
with `--runtime-config=flowcontrol.apiserver.k8s.io/v1alpha1=true`.
Alternatively, you can enable the v1alpha1 and v1beta1 versions of the API group
with `--runtime-config=flowcontrol.apiserver.k8s.io/v1alpha1=true,flowcontrol.apiserver.k8s.io/v1beta1=true`.
The command-line flag `--enable-priority-and-fairness=false` will disable the
API Priority and Fairness feature, even if other flags have enabled it.
@ -89,7 +89,7 @@ Without APF enabled, overall concurrency in the API server is limited by the
defined by these flags are summed and then the sum is divided up among a
configurable set of _priority levels_. Each incoming request is assigned to a
single priority level, and each priority level will only dispatch as many
concurrent requests as its configuration allows.
concurrent requests as its particular limit allows.
The default configuration, for example, includes separate priority levels for
leader-election requests, requests from built-in controllers, and requests from
@ -97,6 +97,13 @@ Pods. This means that an ill-behaved Pod that floods the API server with
requests cannot prevent leader election or actions by the built-in controllers
from succeeding.
The concurrency limits of the priority levels are periodically
adjusted, allowing under-utilized priority levels to temporarily lend
concurrency to heavily-utilized levels. These limits are based on
nominal limits and bounds on how much concurrency a priority level may
lend and how much it may borrow, all derived from the configuration
objects mentioned below.
### Seats Occupied by a Request
The above description of concurrency management is the baseline story.
@ -187,15 +194,38 @@ A PriorityLevelConfiguration represents a single priority level. Each
PriorityLevelConfiguration has an independent limit on the number of outstanding
requests, and limitations on the number of queued requests.
Concurrency limits for PriorityLevelConfigurations are not specified in absolute
number of requests, but rather in "concurrency shares." The total concurrency
limit for the API Server is distributed among the existing
PriorityLevelConfigurations in proportion with these shares. This allows a
cluster administrator to scale up or down the total amount of traffic to a
server by restarting `kube-apiserver` with a different value for
`--max-requests-inflight` (or `--max-mutating-requests-inflight`), and all
PriorityLevelConfigurations will see their maximum allowed concurrency go up (or
down) by the same fraction.
The nominal oncurrency limit for a PriorityLevelConfiguration is not
specified in an absolute number of seats, but rather in "nominal
concurrency shares." The total concurrency limit for the API Server is
distributed among the existing PriorityLevelConfigurations in
proportion to these shares, to give each level its nominal limit in
terms of seats. This allows a cluster administrator to scale up or
down the total amount of traffic to a server by restarting
`kube-apiserver` with a different value for `--max-requests-inflight`
(or `--max-mutating-requests-inflight`), and all
PriorityLevelConfigurations will see their maximum allowed concurrency
go up (or down) by the same fraction.
{{< caution >}}
In the versions before `v1beta3` the relevant
PriorityLevelConfiguration field is named "assured concurrency shares"
rather than "nominal concurrency shares". Also, in Kubernetes release
1.25 and earlier there were no periodic adjustments: the
nominal/assured limits were always applied without adjustment.
{{< /caution >}}
The bounds on how much concurrency a priority level may lend and how
much it may borrow are expressed in the PriorityLevelConfiguration as
percentages of the level's nominal limit. These are resolved to
absolute numbers of seats by multiplying with the nominal limit /
100.0 and rounding. The dynamically adjusted concurrency limit of a
priority level is constrained to lie between (a) a lower bound of its
nominal limit minus its lendable seats and (b) an upper bound of its
nominal limit plus the seats it may borrow. At each adjustment the
dynamic limits are derived by each priority level reclaiming any lent
seats for which demand recently appeared and then jointly fairly
responding to the recent seat demand on the priority levels, within
the bounds just described.
{{< caution >}}
With the Priority and Fairness feature enabled, the total concurrency limit for
@ -606,10 +636,55 @@ poorly-behaved workloads that may be harming system health.
to increase that PriorityLevelConfiguration's concurrency shares.
{{< /note >}}
* `apiserver_flowcontrol_request_concurrency_limit` is a gauge vector
holding the computed concurrency limit (based on the API server's
total concurrency limit and PriorityLevelConfigurations' concurrency
shares), broken down by the label `priority_level`.
* `apiserver_flowcontrol_request_concurrency_limit` is the same as
`apiserver_flowcontrol_nominal_limit_seats`. Before the
introduction of concurrency borrowing between priority levels, this
was always equal to `apiserver_flowcontrol_current_limit_seats`
(which did not exist as a distinct metric).
* `apiserver_flowcontrol_nominal_limit_seats` is a gauge vector
holding each priority level's nominal concurrency limit, computed
from the API server's total concurrency limit and the priority
level's configured nominal concurrency shares.
* `apiserver_flowcontrol_lower_limit_seats` is a gauge vector holding
the lower bound on each priority level's dynamic concurrency limit.
* `apiserver_flowcontrol_upper_limit_seats` is a gauge vector holding
the upper bound on each priority level's dynamic concurrency limit.
* `apiserver_flowcontrol_demand_seats` is a histogram vector counting
observations, at the end of every nanosecond, of each priority
level's ratio of (seat demand) / (nominal concurrency limit). A
priority level's seat demand is the sum, over both queued requests
and those in the initial phase of execution, of the maximum of the
number of seats occupied in the request's initial and final
execution phases.
* `apiserver_flowcontrol_demand_seats_high_watermark` is a gauge vector
holding, for each priority level, the maximum seat demand seen
during the last concurrency borrowing adjustment period.
* `apiserver_flowcontrol_demand_seats_average` is a gauge vector
holding, for each priority level, the time-weighted average seat
demand seen during the last concurrency borrowing adjustment period.
* `apiserver_flowcontrol_demand_seats_stdev` is a gauge vector
holding, for each priority level, the time-weighted population
standard deviation of seat demand seen during the last concurrency
borrowing adjustment period.
* `apiserver_flowcontrol_target_seats` is a gauge vector holding, for
each priority level, the concurrency target going into the borrowing
allocation problem.
* `apiserver_flowcontrol_seat_fair_frac` is a gauge holding the fair
allocation fraction determined in the last borrowing adjustment.
* `apiserver_flowcontrol_current_limit_seats` is a gauge vector
holding, for each priority level, the dynamic concurrency limit
derived in the last adjustment.
* `apiserver_flowcontrol_request_wait_duration_seconds` is a histogram
vector of how long requests spent queued, broken down by the labels

View File

@ -39,6 +39,18 @@ Resource quotas work like this:
See the [walkthrough](/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/)
for an example of how to avoid this problem.
{{< note >}}
- For `cpu` and `memory` resources, ResourceQuotas enforce that **every**
(new) pod in that namespace sets a limit for that resource.
If you enforce a resource quota in a namespace for either `cpu` or `memory`,
you, and other clients, **must** specify either `requests` or `limits` for that resource,
for every new Pod you submit. If you don't, the control plane may reject admission
for that Pod.
- For other resources: ResourceQuota works and will ignore pods in the namespace without setting a limit or request for that resource. It means that you can create a new pod without limit/request ephemeral storage if the resource quota limits the ephemeral storage of this namespace.
You can use a [LimitRange](/docs/concepts/policy/limit-range/) to automatically set
a default request for these resources.
{{< /note >}}
The name of a ResourceQuota object must be a valid
[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).

View File

@ -2,7 +2,7 @@
reviewers:
- davidopp
- kevin-wangzefeng
- bsalamat
- alculquicondor
title: Assigning Pods to Nodes
content_type: concept
weight: 20
@ -144,13 +144,13 @@ to repel Pods from specific nodes.
If you specify both `nodeSelector` and `nodeAffinity`, *both* must be satisfied
for the Pod to be scheduled onto a node.
If you specify multiple `nodeSelectorTerms` associated with `nodeAffinity`
types, then the Pod can be scheduled onto a node if one of the specified `nodeSelectorTerms` can be
satisfied.
If you specify multiple terms in `nodeSelectorTerms` associated with `nodeAffinity`
types, then the Pod can be scheduled onto a node if one of the specified terms
can be satisfied (terms are ORed).
If you specify multiple `matchExpressions` associated with a single `nodeSelectorTerms`,
then the Pod can be scheduled onto a node only if all the `matchExpressions` are
satisfied.
If you specify multiple expressions in a single `matchExpressions` field associated with a
term in `nodeSelectorTerms`, then the Pod can be scheduled onto a node only
if all the expressions are satisfied (expressions are ANDed).
{{</note>}}
See [Assign Pods to Nodes using Node Affinity](/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/)

View File

@ -233,11 +233,12 @@ different EndpointSlice objects can arrive at the Kubernetes client watch / cach
at different times.
{{< note >}}
Clients of the EndpointSlice API must be able to handle the situation where
a particular endpoint address appears in more than one slice.
Clients of the EndpointSlice API must iterate through all the existing EndpointSlices
associated to a Service and build a complete list of unique network endpoints. It is
important to mention that endpoints may be duplicated in different EndointSlices.
You can find a reference implementation for how to perform this endpoint deduplication
as part of the `EndpointSliceCache` code within `kube-proxy`.
You can find a reference implementation for how to perform this endpoint aggregation
and deduplication as part of the `EndpointSliceCache` code within `kube-proxy`.
{{< /note >}}
## Comparison with Endpoints {#motivation}

View File

@ -101,7 +101,7 @@ Each HTTP rule contains the following information:
Service.
* A backend is a combination of Service and port names as described in the
[Service doc](/docs/concepts/services-networking/service/) or a [custom resource backend](#resource-backend) by way of a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CRD" >}}. HTTP (and HTTPS) requests to the
Ingress that matches the host and path of the rule are sent to the listed backend.
Ingress that match the host and path of the rule are sent to the listed backend.
A `defaultBackend` is often configured in an Ingress controller to service any requests that do not
match a path in the spec.

View File

@ -18,7 +18,6 @@ This feature, specifically the alpha `topologyKeys` API, is deprecated since
Kubernetes v1.21.
[Topology Aware Hints](/docs/concepts/services-networking/topology-aware-hints/),
introduced in Kubernetes v1.21, provide similar functionality.
{{</ note >}}
_Service Topology_ enables a service to route traffic based upon the Node
@ -194,12 +193,7 @@ spec:
- "*"
```
## {{% heading "whatsnext" %}}
* Read about [enabling Service Topology](/docs/tasks/administer-cluster/enabling-service-topology)
* Read about [Topology Aware Hints](/docs/concepts/services-networking/topology-aware-hints/)
* Read [Connecting Applications with Services](/docs/tutorials/services/connect-applications-service/)

View File

@ -145,14 +145,16 @@ spec:
targetPort: http-web-svc
```
This works even if there is a mixture of Pods in the Service using a single
configured name, with the same network protocol available via different
port numbers. This offers a lot of flexibility for deploying and evolving
your Services. For example, you can change the port numbers that Pods expose
in the next version of your backend software, without breaking clients.
The default protocol for Services is TCP; you can also use any other
[supported protocol](#protocol-support).
The default protocol for Services is
[TCP](/docs/reference/networking/service-protocols/#protocol-tcp); you can also
use any other [supported protocol](/docs/reference/networking/service-protocols/).
As many Services need to expose more than one port, Kubernetes supports multiple
port definitions on a Service object.
@ -316,150 +318,6 @@ This field follows standard Kubernetes label syntax. Values should either be
[IANA standard service names](https://www.iana.org/assignments/service-names) or
domain prefixed names such as `mycompany.com/my-custom-protocol`.
## Virtual IPs and service proxies
Every node in a Kubernetes cluster runs a `kube-proxy`. `kube-proxy` is
responsible for implementing a form of virtual IP for `Services` of type other
than [`ExternalName`](#externalname).
### Why not use round-robin DNS?
A question that pops up every now and then is why Kubernetes relies on
proxying to forward inbound traffic to backends. What about other
approaches? For example, would it be possible to configure DNS records that
have multiple A values (or AAAA for IPv6), and rely on round-robin name
resolution?
There are a few reasons for using proxying for Services:
* There is a long history of DNS implementations not respecting record TTLs,
and caching the results of name lookups after they should have expired.
* Some apps do DNS lookups only once and cache the results indefinitely.
* Even if apps and libraries did proper re-resolution, the low or zero TTLs
on the DNS records could impose a high load on DNS that then becomes
difficult to manage.
Later in this page you can read about how various kube-proxy implementations work. Overall,
you should note that, when running `kube-proxy`, kernel level rules may be
modified (for example, iptables rules might get created), which won't get cleaned up,
in some cases until you reboot. Thus, running kube-proxy is something that should
only be done by an administrator which understands the consequences of having a
low level, privileged network proxying service on a computer. Although the `kube-proxy`
executable supports a `cleanup` function, this function is not an official feature and
thus is only available to use as-is.
### Configuration
Note that the kube-proxy starts up in different modes, which are determined by its configuration.
- The kube-proxy's configuration is done via a ConfigMap, and the ConfigMap for kube-proxy
effectively deprecates the behavior for almost all of the flags for the kube-proxy.
- The ConfigMap for the kube-proxy does not support live reloading of configuration.
- The ConfigMap parameters for the kube-proxy cannot all be validated and verified on startup.
For example, if your operating system doesn't allow you to run iptables commands,
the standard kernel kube-proxy implementation will not work.
Likewise, if you have an operating system which doesn't support `netsh`,
it will not run in Windows userspace mode.
### User space proxy mode {#proxy-mode-userspace}
In this (legacy) mode, kube-proxy watches the Kubernetes control plane for the addition and
removal of Service and Endpoint objects. For each Service it opens a
port (randomly chosen) on the local node. Any connections to this "proxy port"
are proxied to one of the Service's backend Pods (as reported via
Endpoints). kube-proxy takes the `SessionAffinity` setting of the Service into
account when deciding which backend Pod to use.
Lastly, the user-space proxy installs iptables rules which capture traffic to
the Service's `clusterIP` (which is virtual) and `port`. The rules
redirect that traffic to the proxy port which proxies the backend Pod.
By default, kube-proxy in userspace mode chooses a backend via a round-robin algorithm.
![Services overview diagram for userspace proxy](/images/docs/services-userspace-overview.svg)
### `iptables` proxy mode {#proxy-mode-iptables}
In this mode, kube-proxy watches the Kubernetes control plane for the addition and
removal of Service and Endpoint objects. For each Service, it installs
iptables rules, which capture traffic to the Service's `clusterIP` and `port`,
and redirect that traffic to one of the Service's
backend sets. For each Endpoint object, it installs iptables rules which
select a backend Pod.
By default, kube-proxy in iptables mode chooses a backend at random.
Using iptables to handle traffic has a lower system overhead, because traffic
is handled by Linux netfilter without the need to switch between userspace and the
kernel space. This approach is also likely to be more reliable.
If kube-proxy is running in iptables mode and the first Pod that's selected
does not respond, the connection fails. This is different from userspace
mode: in that scenario, kube-proxy would detect that the connection to the first
Pod had failed and would automatically retry with a different backend Pod.
You can use Pod [readiness probes](/docs/concepts/workloads/pods/pod-lifecycle/#container-probes)
to verify that backend Pods are working OK, so that kube-proxy in iptables mode
only sees backends that test out as healthy. Doing this means you avoid
having traffic sent via kube-proxy to a Pod that's known to have failed.
![Services overview diagram for iptables proxy](/images/docs/services-iptables-overview.svg)
### IPVS proxy mode {#proxy-mode-ipvs}
{{< feature-state for_k8s_version="v1.11" state="stable" >}}
In `ipvs` mode, kube-proxy watches Kubernetes Services and Endpoints,
calls `netlink` interface to create IPVS rules accordingly and synchronizes
IPVS rules with Kubernetes Services and Endpoints periodically.
This control loop ensures that IPVS status matches the desired
state.
When accessing a Service, IPVS directs traffic to one of the backend Pods.
The IPVS proxy mode is based on netfilter hook function that is similar to
iptables mode, but uses a hash table as the underlying data structure and works
in the kernel space.
That means kube-proxy in IPVS mode redirects traffic with lower latency than
kube-proxy in iptables mode, with much better performance when synchronizing
proxy rules. Compared to the other proxy modes, IPVS mode also supports a
higher throughput of network traffic.
IPVS provides more options for balancing traffic to backend Pods;
these are:
* `rr`: round-robin
* `lc`: least connection (smallest number of open connections)
* `dh`: destination hashing
* `sh`: source hashing
* `sed`: shortest expected delay
* `nq`: never queue
{{< note >}}
To run kube-proxy in IPVS mode, you must make IPVS available on
the node before starting kube-proxy.
When kube-proxy starts in IPVS proxy mode, it verifies whether IPVS
kernel modules are available. If the IPVS kernel modules are not detected, then kube-proxy
falls back to running in iptables proxy mode.
{{< /note >}}
![Services overview diagram for IPVS proxy](/images/docs/services-ipvs-overview.svg)
In these proxy models, the traffic bound for the Service's IP:Port is
proxied to an appropriate backend without the clients knowing anything
about Kubernetes or Services or Pods.
If you want to make sure that connections from a particular client
are passed to the same Pod each time, you can select the session affinity based
on the client's IP addresses by setting `service.spec.sessionAffinity` to "ClientIP"
(the default is "None").
You can also set the maximum session sticky time by setting
`service.spec.sessionAffinityConfig.clientIP.timeoutSeconds` appropriately.
(the default value is 10800, which works out to be 3 hours).
{{< note >}}
On Windows, setting the maximum session sticky time for Services is not supported.
{{< /note >}}
## Multi-Port Services
For some Services, you need to expose more than one port.
@ -507,46 +365,6 @@ The IP address that you choose must be a valid IPv4 or IPv6 address from within
If you try to create a Service with an invalid clusterIP address value, the API
server will return a 422 HTTP status code to indicate that there's a problem.
## Traffic policies
### External traffic policy
You can set the `spec.externalTrafficPolicy` field to control how traffic from external sources is routed.
Valid values are `Cluster` and `Local`. Set the field to `Cluster` to route external traffic to all ready endpoints
and `Local` to only route to ready node-local endpoints. If the traffic policy is `Local` and there are no node-local
endpoints, the kube-proxy does not forward any traffic for the relevant Service.
### Internal traffic policy
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
You can set the `spec.internalTrafficPolicy` field to control how traffic from internal sources is routed.
Valid values are `Cluster` and `Local`. Set the field to `Cluster` to route internal traffic to all ready endpoints
and `Local` to only route to ready node-local endpoints. If the traffic policy is `Local` and there are no node-local
endpoints, traffic is dropped by kube-proxy.
### Traffic to Terminating Endpoints
{{< feature-state for_k8s_version="v1.26" state="beta" >}}
If the `ProxyTerminatingEndpoints`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
is enabled in kube-proxy and the traffic policy is `Local`, that node's
kube-proxy uses a more complicated algorithm to select endpoints for a Service.
With the feature enabled, kube-proxy checks if the node
has local endpoints and whether or not all the local endpoints are marked as terminating.
If there are local endpoints and **all** of them are terminating, then kube-proxy
will forward traffic to those terminating endpoints. Otherwise, kube-proxy will always
prefer forwarding traffic to endpoints that are not terminating.
This forwarding behavior for terminating endpoints exist to allow `NodePort` and `LoadBalancer` Services to
gracefully drain connections when using `externalTrafficPolicy=Local`. As a deployment goes through
a rolling update, nodes backing a loadbalancer may transition from N to 0 replicas of that deployment.
In some cases, external load balancers can send traffic to a node with 0 replicas in between health check probes.
Routing traffic to terminating endpoints ensures that Node's that are scaling down Pods can gracefully receive
and drain traffic to those terminating Pods. By the time the Pod completes termination, the external load balancer
should have seen the node's health check failing and fully removed the node from the backend pool.
## Discovering services
Kubernetes supports 2 primary modes of finding a Service - environment
@ -672,6 +490,12 @@ Kubernetes `ServiceTypes` allow you to specify what kind of Service you want.
to use the `ExternalName` type.
{{< /note >}}
The `type` field was designed as nested functionality - each level adds to the
previous. This is not strictly required on all cloud providers (for example: Google
Compute Engine does not need to allocate a node port to make `type: LoadBalancer` work,
but another cloud provider integration might do). Although strict nesting is not required,
but the Kubernetes API design for Service requires it anyway.
You can also use [Ingress](/docs/concepts/services-networking/ingress/) to expose your Service.
Ingress is not a Service type, but it acts as the entry point for your cluster.
It lets you consolidate your routing rules into a single resource as it can expose multiple
@ -799,6 +623,7 @@ _As an alpha feature_, you can configure a load balanced Service to
[omit](#load-balancer-nodeport-allocation) assigning a node port, provided that the
cloud provider implementation supports this.
{{< note >}}
On **Azure**, if you want to use a user-specified public type `loadBalancerIP`, you first need
@ -816,9 +641,14 @@ or [CreatingLoadBalancerFailed on AKS cluster with advanced networking](https://
#### Load balancers with mixed protocol types
{{< feature-state for_k8s_version="v1.26" state="stable" >}}
{{< feature-state for_k8s_version="v1.24" state="beta" >}}
You can use different protocols for LoadBalancer type of Services, when there is more than one port defined.
By default, for LoadBalancer type of Services, when there is more than one port defined, all
ports must have the same protocol, and the protocol must be one which is supported
by the cloud provider.
The feature gate `MixedProtocolLBService` (enabled by default for the kube-apiserver as of v1.24) allows the use of
different protocols for LoadBalancer type of Services, when there is more than one port defined.
{{< note >}}
@ -1353,201 +1183,34 @@ spec:
- 80.11.12.10
```
## Shortcomings
## Session stickiness
Using the userspace proxy for VIPs works at small to medium scale, but will
not scale to very large clusters with thousands of Services. The
[original design proposal for portals](https://github.com/kubernetes/kubernetes/issues/1107)
has more details on this.
Using the userspace proxy obscures the source IP address of a packet accessing
a Service.
This makes some kinds of network filtering (firewalling) impossible. The iptables
proxy mode does not
obscure in-cluster source IPs, but it does still impact clients coming through
a load balancer or node-port.
The `Type` field is designed as nested functionality - each level adds to the
previous. This is not strictly required on all cloud providers (e.g. Google Compute Engine does
not need to allocate a `NodePort` to make `LoadBalancer` work, but AWS does)
but the Kubernetes API design for Service requires it anyway.
## Virtual IP implementation {#the-gory-details-of-virtual-ips}
The previous information should be sufficient for many people who want to
use Services. However, there is a lot going on behind the scenes that may be
worth understanding.
### Avoiding collisions
One of the primary philosophies of Kubernetes is that you should not be
exposed to situations that could cause your actions to fail through no fault
of your own. For the design of the Service resource, this means not making
you choose your own port number if that choice might collide with
someone else's choice. That is an isolation failure.
In order to allow you to choose a port number for your Services, we must
ensure that no two Services can collide. Kubernetes does that by allocating each
Service its own IP address from within the `service-cluster-ip-range`
CIDR range that is configured for the API server.
To ensure each Service receives a unique IP, an internal allocator atomically
updates a global allocation map in {{< glossary_tooltip term_id="etcd" >}}
prior to creating each Service. The map object must exist in the registry for
Services to get IP address assignments, otherwise creations will
fail with a message indicating an IP address could not be allocated.
In the control plane, a background controller is responsible for creating that
map (needed to support migrating from older versions of Kubernetes that used
in-memory locking). Kubernetes also uses controllers to check for invalid
assignments (e.g. due to administrator intervention) and for cleaning up allocated
IP addresses that are no longer used by any Services.
Services are using an [allocation strategy](/docs/concepts/services-networking/cluster-ip-allocation/) that divides the `ClusterIP` range into two bands, based on
the size of the configured `service-cluster-ip-range` by using the following formula
`min(max(16, cidrSize / 16), 256)`, described as _never less than 16 or more than 256,
with a graduated step function between them_. Dynamic IP allocations will be preferentially
chosen from the upper band, reducing risks of conflicts with the IPs
assigned from the lower band.
This allows users to use the lower band of the `service-cluster-ip-range` for their
Services with static IPs assigned with a very low risk of running into conflicts.
### Service IP addresses {#ips-and-vips}
Unlike Pod IP addresses, which actually route to a fixed destination,
Service IPs are not actually answered by a single host. Instead, kube-proxy
uses iptables (packet processing logic in Linux) to define _virtual_ IP addresses
which are transparently redirected as needed. When clients connect to the
VIP, their traffic is automatically transported to an appropriate endpoint.
The environment variables and DNS for Services are actually populated in
terms of the Service's virtual IP address (and port).
kube-proxy supports three proxy modes&mdash;userspace, iptables and IPVS&mdash;which
each operate slightly differently.
#### Userspace
As an example, consider the image processing application described above.
When the backend Service is created, the Kubernetes master assigns a virtual
IP address, for example 10.0.0.1. Assuming the Service port is 1234, the
Service is observed by all of the kube-proxy instances in the cluster.
When a proxy sees a new Service, it opens a new random port, establishes an
iptables redirect from the virtual IP address to this new port, and starts accepting
connections on it.
When a client connects to the Service's virtual IP address, the iptables
rule kicks in, and redirects the packets to the proxy's own port.
The "Service proxy" chooses a backend, and starts proxying traffic from the client to the backend.
This means that Service owners can choose any port they want without risk of
collision. Clients can connect to an IP and port, without being aware
of which Pods they are actually accessing.
#### iptables
Again, consider the image processing application described above.
When the backend Service is created, the Kubernetes control plane assigns a virtual
IP address, for example 10.0.0.1. Assuming the Service port is 1234, the
Service is observed by all of the kube-proxy instances in the cluster.
When a proxy sees a new Service, it installs a series of iptables rules which
redirect from the virtual IP address to per-Service rules. The per-Service
rules link to per-Endpoint rules which redirect traffic (using destination NAT)
to the backends.
When a client connects to the Service's virtual IP address the iptables rule kicks in.
A backend is chosen (either based on session affinity or randomly) and packets are
redirected to the backend. Unlike the userspace proxy, packets are never
copied to userspace, the kube-proxy does not have to be running for the virtual
IP address to work, and Nodes see traffic arriving from the unaltered client IP
address.
This same basic flow executes when traffic comes in through a node-port or
through a load-balancer, though in those cases the client IP does get altered.
#### IPVS
iptables operations slow down dramatically in large scale cluster e.g. 10,000 Services.
IPVS is designed for load balancing and based on in-kernel hash tables.
So you can achieve performance consistency in large number of Services from IPVS-based kube-proxy.
Meanwhile, IPVS-based kube-proxy has more sophisticated load balancing algorithms
(least conns, locality, weighted, persistence).
If you want to make sure that connections from a particular client are passed to
the same Pod each time, you can configure session affinity based on the client's
IP address. Read [session affinity](/docs/reference/networking/virtual-ips/#session-affinity)
to learn more.
## API Object
Service is a top-level resource in the Kubernetes REST API. You can find more details
about the [Service API object](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#service-v1-core).
## Supported protocols {#protocol-support}
<!-- preserve existing hyperlinks -->
<a id="shortcomings" /><a id="#the-gory-details-of-virtual-ips" />
### TCP
## Virtual IP addressing mechanism
You can use TCP for any kind of Service, and it's the default network protocol.
### UDP
You can use UDP for most Services. For type=LoadBalancer Services, UDP support
depends on the cloud provider offering this facility.
### SCTP
{{< feature-state for_k8s_version="v1.20" state="stable" >}}
When using a network plugin that supports SCTP traffic, you can use SCTP for
most Services. For type=LoadBalancer Services, SCTP support depends on the cloud
provider offering this facility. (Most do not).
#### Warnings {#caveat-sctp-overview}
##### Support for multihomed SCTP associations {#caveat-sctp-multihomed}
{{< warning >}}
The support of multihomed SCTP associations requires that the CNI plugin can support the
assignment of multiple interfaces and IP addresses to a Pod.
NAT for multihomed SCTP associations requires special logic in the corresponding kernel modules.
{{< /warning >}}
##### Windows {#caveat-sctp-windows-os}
{{< note >}}
SCTP is not supported on Windows based nodes.
{{< /note >}}
##### Userspace kube-proxy {#caveat-sctp-kube-proxy-userspace}
{{< warning >}}
The kube-proxy does not support the management of SCTP associations when it is in userspace mode.
{{< /warning >}}
### HTTP
If your cloud provider supports it, you can use a Service in LoadBalancer mode
to set up external HTTP / HTTPS reverse proxying, forwarded to the Endpoints
of the Service.
{{< note >}}
You can also use {{< glossary_tooltip term_id="ingress" >}} in place of Service
to expose HTTP/HTTPS Services.
{{< /note >}}
### PROXY protocol
If your cloud provider supports it,
you can use a Service in LoadBalancer mode to configure a load balancer outside
of Kubernetes itself, that will forward connections prefixed with
[PROXY protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt).
The load balancer will send an initial series of octets describing the
incoming connection, similar to this example
```
PROXY TCP4 192.0.2.202 10.0.42.7 12345 7\r\n
```
followed by the data from the client.
Read [Virtual IPs and Service Proxies](/docs/reference/networking/virtual-ips/) to learn about the
mechanism Kubernetes provides to expose a Service with a virtual IP address.
## {{% heading "whatsnext" %}}
* Follow the [Connecting Applications with Services](/docs/tutorials/services/connect-applications-service/) tutorial
* Read about [Ingress](/docs/concepts/services-networking/ingress/)
* Read about [EndpointSlices](/docs/concepts/services-networking/endpoint-slices/)
For more context:
* Read [Virtual IPs and Service Proxies](/docs/reference/networking/virtual-ips/)
* Read the [API reference](/docs/reference/kubernetes-api/service-resources/service-v1/) for the Service API
* Read the [API reference](/docs/reference/kubernetes-api/service-resources/endpoints-v1/) for the Endpoints API
* Read the [API reference](/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/) for the EndpointSlice API

View File

@ -45,8 +45,8 @@ The following is an example of a Deployment. It creates a ReplicaSet to bring up
In this example:
* A Deployment named `nginx-deployment` is created, indicated by the `.metadata.name` field.
* The Deployment creates three replicated Pods, indicated by the `.spec.replicas` field.
* The `.spec.selector` field defines how the Deployment finds which Pods to manage.
* The Deployment creates a ReplicaSet that creates three replicated Pods, indicated by the `.spec.replicas` field.
* The `.spec.selector` field defines how the created ReplicaSet finds which Pods to manage.
In this case, you select a label that is defined in the Pod template (`app: nginx`).
However, more sophisticated selection rules are possible,
as long as the Pod template itself satisfies the rule.

View File

@ -264,7 +264,8 @@ Jobs with _fixed completion count_ - that is, jobs that have non null
- As part of the Pod hostname, following the pattern `$(job-name)-$(index)`.
When you use an Indexed Job in combination with a
{{< glossary_tooltip term_id="Service" >}}, Pods within the Job can use
the deterministic hostnames to address each other via DNS.
the deterministic hostnames to address each other via DNS. For more information about
how to configure this, see [Job with Pod-to-Pod Communication](/docs/tasks/job/job-with-pod-to-pod-communication/).
- From the containerized task, in the environment variable `JOB_COMPLETION_INDEX`.
The Job is considered complete when there is one successfully completed Pod
@ -475,12 +476,13 @@ The tradeoffs are:
The tradeoffs are summarized here, with columns 2 to 4 corresponding to the above tradeoffs.
The pattern names are also links to examples and more detailed description.
| Pattern | Single Job object | Fewer pods than work items? | Use app unmodified? |
| ----------------------------------------- |:-----------------:|:---------------------------:|:-------------------:|
| [Queue with Pod Per Work Item] | ✓ | | sometimes |
| [Queue with Variable Pod Count] | ✓ | ✓ | |
| [Indexed Job with Static Work Assignment] | ✓ | | ✓ |
| [Job Template Expansion] | | | ✓ |
| Pattern | Single Job object | Fewer pods than work items? | Use app unmodified? |
| ----------------------------------------------- |:-----------------:|:---------------------------:|:-------------------:|
| [Queue with Pod Per Work Item] | ✓ | | sometimes |
| [Queue with Variable Pod Count] | ✓ | ✓ | |
| [Indexed Job with Static Work Assignment] | ✓ | | ✓ |
| [Job Template Expansion] | | | ✓ |
| [Job with Pod-to-Pod Communication] | ✓ | sometimes | sometimes |
When you specify completions with `.spec.completions`, each Pod created by the Job controller
has an identical [`spec`](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status). This means that
@ -491,17 +493,19 @@ are different ways to arrange for pods to work on different things.
This table shows the required settings for `.spec.parallelism` and `.spec.completions` for each of the patterns.
Here, `W` is the number of work items.
| Pattern | `.spec.completions` | `.spec.parallelism` |
| ----------------------------------------- |:-------------------:|:--------------------:|
| [Queue with Pod Per Work Item] | W | any |
| [Queue with Variable Pod Count] | null | any |
| [Indexed Job with Static Work Assignment] | W | any |
| [Job Template Expansion] | 1 | should be 1 |
| Pattern | `.spec.completions` | `.spec.parallelism` |
| ----------------------------------------------- |:-------------------:|:--------------------:|
| [Queue with Pod Per Work Item] | W | any |
| [Queue with Variable Pod Count] | null | any |
| [Indexed Job with Static Work Assignment] | W | any |
| [Job Template Expansion] | 1 | should be 1 |
| [Job with Pod-to-Pod Communication] | W | W |
[Queue with Pod Per Work Item]: /docs/tasks/job/coarse-parallel-processing-work-queue/
[Queue with Variable Pod Count]: /docs/tasks/job/fine-parallel-processing-work-queue/
[Indexed Job with Static Work Assignment]: /docs/tasks/job/indexed-parallel-processing-static/
[Job Template Expansion]: /docs/tasks/job/parallel-processing-expansion/
[Job with Pod-to-Pod Communication]: /docs/tasks/job/job-with-pod-to-pod-communication/
## Advanced usage

View File

@ -268,7 +268,7 @@ The certificate value is in Base64-encoded format under `status.certificate`.
Export the issued certificate from the CertificateSigningRequest.
```
```shell
kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt
```
@ -295,20 +295,20 @@ The last step is to add this user into the kubeconfig file.
First, you need to add new credentials:
```
```shell
kubectl config set-credentials myuser --client-key=myuser.key --client-certificate=myuser.crt --embed-certs=true
```
Then, you need to add the context:
```
```shell
kubectl config set-context myuser --cluster=kubernetes --user=myuser
```
To test it, change the context to `myuser`:
```
```shell
kubectl config use-context myuser
```

View File

@ -317,6 +317,12 @@ objects with an `aggregationRule` set. The `aggregationRule` defines a label
uses to match other ClusterRole objects that should be combined into the `rules`
field of this one.
{{< caution >}}
The control plane overwrites any values that you manually specify in the `rules` field of an
aggregate ClusterRole. If you want to change or add rules, do so in the `ClusterRole` objects
that are selected by the `aggregationRule`.
{{< /caution >}}
Here is an example aggregated ClusterRole:
```yaml

View File

@ -204,7 +204,7 @@ In the following table:
| `ResourceQuotaScopeSelectors` | `true` | GA | 1.17 | 1.18 |
| `RootCAConfigMap` | `false` | Alpha | 1.13 | 1.19 |
| `RootCAConfigMap` | `true` | Beta | 1.20 | 1.20 |
| `RootCAConfigMap` | `true` | GA | 1.21 | 1.12 |
| `RootCAConfigMap` | `true` | GA | 1.21 | 1.22 |
| `RotateKubeletClientCertificate` | `true` | Beta | 1.8 | 1.18 |
| `RotateKubeletClientCertificate` | `true` | GA | 1.19 | 1.21 |
| `RunAsGroup` | `true` | Beta | 1.14 | 1.20 |

View File

@ -74,12 +74,12 @@ For a reference to old feature gates that are removed, please refer to
| `CPUManagerPolicyBetaOptions` | `true` | Beta | 1.23 | |
| `CPUManagerPolicyOptions` | `false` | Alpha | 1.22 | 1.22 |
| `CPUManagerPolicyOptions` | `true` | Beta | 1.23 | |
| `CrossNamespaceVolumeDataSource` | `false` | Alpha| 1.26 | |
| `CSIMigrationPortworx` | `false` | Alpha | 1.23 | 1.24 |
| `CSIMigrationPortworx` | `false` | Beta | 1.25 | |
| `CSIMigrationRBD` | `false` | Alpha | 1.23 | |
| `CSINodeExpandSecret` | `false` | Alpha | 1.25 | |
| `CSIVolumeHealth` | `false` | Alpha | 1.21 | |
| `CrossNamespaceVolumeDataSource` | `false` | Alpha| 1.26 | |
| `ContainerCheckpoint` | `false` | Alpha | 1.25 | |
| `ContextualLogging` | `false` | Alpha | 1.24 | |
| `CustomCPUCFSQuotaPeriod` | `false` | Alpha | 1.12 | |
@ -118,6 +118,10 @@ For a reference to old feature gates that are removed, please refer to
| `JobPodFailurePolicy` | `true` | Beta | 1.26 | |
| `JobReadyPods` | `false` | Alpha | 1.23 | 1.23 |
| `JobReadyPods` | `true` | Beta | 1.24 | |
| `JobTrackingWithFinalizers` | `false` | Alpha | 1.22 | 1.22 |
| `JobTrackingWithFinalizers` | `false` | Beta | 1.23 | 1.24 |
| `JobTrackingWithFinalizers` | `true` | Beta | 1.25 | |
| `KMSv2` | `false` | Alpha | 1.25 | |
| `KubeletCredentialProviders` | `false` | Alpha | 1.20 | 1.23 |
| `KubeletCredentialProviders` | `true` | Beta | 1.24 | |
| `KubeletInUserNamespace` | `false` | Alpha | 1.22 | |
@ -615,6 +619,7 @@ Each feature gate is designed for enabling/disabling a specific feature:
completions without relying on Pods remaining in the cluster indefinitely.
The Job controller uses Pod finalizers and a field in the Job status to keep
track of the finished Pods to count towards completion.
- `KMSv2`: Enables KMS v2 API for encryption at rest. See [Using a KMS Provider for data encryption](/docs/tasks/administer-cluster/kms-provider) for more details.
- `KubeletCredentialProviders`: Enable kubelet exec credential providers for
image pull credentials.
- `KubeletInUserNamespace`: Enables support for running kubelet in a

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,55 @@
---
title: Node metrics data
content_type: reference
weight: 50
description: >-
Mechanisms for accessing metrics at node, volume, pod and container level,
as seen by the kubelet.
---
The [kubelet](/docs/reference/command-line-tools-reference/kubelet/)
gathers metric statistics at the node, volume, pod and container level,
and emits this information in the
[Summary API](https://github.com/kubernetes/kubernetes/blob/7d309e0104fedb57280b261e5677d919cb2a0e2d/staging/src/k8s.io/kubelet/pkg/apis/stats/v1alpha1/types.go).
You can send a proxied request to the stats summary API via the
Kubernetes API server.
Here is an example of a Summary API request for a node named `minikube`:
```shell
kubectl get --raw "/api/v1/nodes/minikube/proxy/stats/summary"
```
Here is the same API call using `curl`:
```shell
# You need to run "kubectl proxy" first
# Change 8080 to the port that "kubectl proxy" assigns
curl http://localhost:8080/api/v1/nodes/minikube/proxy/stats/summary
```
{{< note >}}
Beginning with `metrics-server` 0.6.x, `metrics-server` queries the `/metrics/resource`
kubelet endpoint, and not `/stats/summary`.
{{< /note >}}
## Summary metrics API source {#summary-api-source}
By default, Kubernetes fetches node summary metrics data using an embedded
[cAdvisor](https://github.com/google/cadvisor) that runs within the kubelet.
## Summary API data via CRI {#pod-and-container-stats-from-cri}
{{< feature-state for_k8s_version="v1.23" state="alpha" >}}
If you enable the `PodAndContainerStatsFromCRI`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) in your
cluster, and you use a container runtime that supports statistics access via
{{< glossary_tooltip term_id="cri" text="Container Runtime Interface">}} (CRI), then
the kubelet fetches Pod- and container-level metric data using CRI, and not via cAdvisor.
## {{% heading "whatsnext" %}}
The task pages for [Troubleshooting Clusters](/docs/tasks/debug/debug-cluster/) discuss
how to use a metrics pipeline that rely on these data.

View File

@ -22,7 +22,7 @@ This page contains a list of commonly used `kubectl` commands and flags.
### BASH
```bash
source <(kubectl completion bash) # setup autocomplete in bash into the current shell, bash-completion package should be installed first.
source <(kubectl completion bash) # set up autocomplete in bash into the current shell, bash-completion package should be installed first.
echo "source <(kubectl completion bash)" >> ~/.bashrc # add autocomplete permanently to your bash shell.
```
@ -36,12 +36,12 @@ complete -o default -F __start_kubectl k
### ZSH
```bash
source <(kubectl completion zsh) # setup autocomplete in zsh into the current shell
source <(kubectl completion zsh) # set up autocomplete in zsh into the current shell
echo '[[ $commands[kubectl] ]] && source <(kubectl completion zsh)' >> ~/.zshrc # add autocomplete permanently to your zsh shell
```
### A Note on --all-namespaces
### A note on `--all-namespaces`
Appending `--all-namespaces` happens frequently enough where you should be aware of the shorthand for `--all-namespaces`:
Appending `--all-namespaces` happens frequently enough where you should be aware of the shorthand for `--all-namespaces`:
```kubectl -A```
@ -155,7 +155,7 @@ EOF
```
## Viewing, finding resources
## Viewing and finding resources
```bash
# Get commands with basic output
@ -269,6 +269,7 @@ kubectl expose rc nginx --port=80 --target-port=8000
kubectl get pod mypod -o yaml | sed 's/\(image: myimage\):.*$/\1:v4/' | kubectl replace -f -
kubectl label pods my-pod new-label=awesome # Add a Label
kubectl label pods my-pod new-label- # Remove a label
kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq # Add an annotation
kubectl autoscale deployment foo --min=2 --max=10 # Auto scale a deployment "foo"
```
@ -349,7 +350,7 @@ kubectl exec my-pod -c my-container -- ls / # Run command in existing po
kubectl top pod POD_NAME --containers # Show metrics for a given pod and its containers
kubectl top pod POD_NAME --sort-by=cpu # Show metrics for a given pod and sort it by 'cpu' or 'memory'
```
## Copy files and directories to and from containers
## Copying files and directories to and from containers
```bash
kubectl cp /tmp/foo_dir my-pod:/tmp/bar_dir # Copy /tmp/foo_dir local directory to /tmp/bar_dir in a remote pod in the current namespace
@ -358,7 +359,7 @@ kubectl cp /tmp/foo my-namespace/my-pod:/tmp/bar # Copy /tmp/foo local fil
kubectl cp my-namespace/my-pod:/tmp/foo /tmp/bar # Copy /tmp/foo from a remote pod to /tmp/bar locally
```
{{< note >}}
`kubectl cp` requires that the 'tar' binary is present in your container image. If 'tar' is not present,`kubectl cp` will fail.
`kubectl cp` requires that the 'tar' binary is present in your container image. If 'tar' is not present, `kubectl cp` will fail.
For advanced use cases, such as symlinks, wildcard expansion or file mode preservation consider using `kubectl exec`.
{{< /note >}}

View File

@ -0,0 +1,11 @@
---
title: Networking Reference
content_type: reference
weight: 85
---
<!-- overview -->
This section of the Kubernetes documentation provides reference details
of Kubernetes networking.
<!-- body -->

View File

@ -1,7 +1,7 @@
---
title: Ports and Protocols
content_type: reference
weight: 90
weight: 40
---
When running Kubernetes in an environment with strict network boundaries, such

View File

@ -0,0 +1,127 @@
---
title: Protocols for Services
content_type: reference
weight: 10
---
<!-- overview -->
If you configure a {{< glossary_tooltip text="Service" term_id="service" >}},
you can select from any network protocol that Kubernetes supports.
Kubernetes supports the following protocols with Services:
- [`SCTP`](#protocol-sctp)
- [`TCP`](#protocol-tcp) _(the default)_
- [`UDP`](#protocol-udp)
When you define a Service, you can also specify the
[application protocol](/docs/concepts/services-networking/service/#application-protocol)
that it uses.
This document details some special cases, all of them typically using TCP
as a transport protocol:
- [HTTP](#protocol-http-special) and [HTTPS](#protocol-http-special)
- [PROXY protocol](#protocol-proxy-special)
- [TLS](#protocol-tls-special) termination at the load balancer
<!-- body -->
## Supported protocols {#protocol-support}
There are 3 valid values for the `protocol` of a port for a Service:
### `SCTP` {#protocol-sctp}
{{< feature-state for_k8s_version="v1.20" state="stable" >}}
When using a network plugin that supports SCTP traffic, you can use SCTP for
most Services. For `type: LoadBalancer` Services, SCTP support depends on the cloud
provider offering this facility. (Most do not).
SCTP is not supported on nodes that run Windows.
#### Support for multihomed SCTP associations {#caveat-sctp-multihomed}
The support of multihomed SCTP associations requires that the CNI plugin can support the assignment of multiple interfaces and IP addresses to a Pod.
NAT for multihomed SCTP associations requires special logic in the corresponding kernel modules.
{{< note >}}
The kube-proxy does not support the management of SCTP associations when it is in userspace mode.
{{< /note >}}
### `TCP` {#protocol-tcp}
You can use TCP for any kind of Service, and it's the default network protocol.
### `UDP` {#protocol-udp}
You can use UDP for most Services. For `type: LoadBalancer` Services,
UDP support depends on the cloud provider offering this facility.
## Special cases
### HTTP {#protocol-http-special}
If your cloud provider supports it, you can use a Service in LoadBalancer mode to
configure a load balancer outside of your Kubernetes cluster, in a special mode
where your cloud provider's load balancer implements HTTP / HTTPS reverse proxying,
with traffic forwarded to the backend endpoints for that Service.
Typically, you set the protocol for the Service to `TCP` and add an
{{< glossary_tooltip text="annotation" term_id="annotation" >}}
(usually specific to your cloud provider) that configures the load balancer
to handle traffic at the HTTP level.
This configuration might also include serving HTTPS (HTTP over TLS) and
reverse-proxying plain HTTP to your workload.
{{< note >}}
You can also use an {{< glossary_tooltip term_id="ingress" >}} to expose
HTTP/HTTPS Services.
{{< /note >}}
You might additionally want to specify that the
[application protocol](/docs/concepts/services-networking/service/#application-protocol)
of the connection is `http` or `https`. Use `http` if the session from the
load balancer to your workload is HTTP without TLS, and use `https` if the
session from the load balancer to your workload uses TLS encryption.
### PROXY protocol {#protocol-proxy-special}
If your cloud provider supports it, you can use a Service set to `type: LoadBalancer`
to configure a load balancer outside of Kubernetes itself, that will forward connections
wrapped with the
[PROXY protocol](https://www.haproxy.org/download/2.5/doc/proxy-protocol.txt).
The load balancer then sends an initial series of octets describing the
incoming connection, similar to this example (PROXY protocol v1):
```
PROXY TCP4 192.0.2.202 10.0.42.7 12345 7\r\n
```
The data after the proxy protocol preamble are the original
data from the client. When either side closes the connection,
the load balancer also triggers a connection close and sends
any remaining data where feasible.
Typically, you define a Service with the protocol to `TCP`.
You also set an annotation, specific to your
cloud provider, that configures the load balancer to wrap each incoming connection in the PROXY protocol.
### TLS {#protocol-tls-special}
If your cloud provider supports it, you can use a Service set to `type: LoadBalancer` as
a way to set up external reverse proxying, where the connection from client to load
balancer is TLS encrypted and the load balancer is the TLS server peer.
The connection from the load balancer to your workload can also be TLS,
or might be plain text. The exact options available to you depend on your
cloud provider or custom Service implementation.
Typically, you set the protocol to `TCP` and set an annotation
(usually specific to your cloud provider) that configures the load balancer
to act as a TLS server. You would configure the TLS identity (as server,
and possibly also as a client that connects to your workload) using
mechanisms that are specific to your cloud provider.

View File

@ -0,0 +1,343 @@
---
title: Virtual IPs and Service Proxies
content_type: reference
weight: 50
---
<!-- overview -->
Every {{< glossary_tooltip term_id="node" text="node" >}} in a Kubernetes
cluster runs a [kube-proxy](/docs/reference/command-line-tools-reference/kube-proxy/)
(unless you have deployed your own alternative component in place of `kube-proxy`).
The `kube-proxy` component is responsible for implementing a _virtual IP_
mechanism for {{< glossary_tooltip term_id="service" text="Services">}}
of `type` other than
[`ExternalName`](/docs/concepts/services-networking/service/#externalname).
A question that pops up every now and then is why Kubernetes relies on
proxying to forward inbound traffic to backends. What about other
approaches? For example, would it be possible to configure DNS records that
have multiple A values (or AAAA for IPv6), and rely on round-robin name
resolution?
There are a few reasons for using proxying for Services:
* There is a long history of DNS implementations not respecting record TTLs,
and caching the results of name lookups after they should have expired.
* Some apps do DNS lookups only once and cache the results indefinitely.
* Even if apps and libraries did proper re-resolution, the low or zero TTLs
on the DNS records could impose a high load on DNS that then becomes
difficult to manage.
Later in this page you can read about how various kube-proxy implementations work.
Overall, you should note that, when running `kube-proxy`, kernel level rules may be modified
(for example, iptables rules might get created), which won't get cleaned up, in some
cases until you reboot. Thus, running kube-proxy is something that should only be done
by an administrator which understands the consequences of having a low level, privileged
network proxying service on a computer. Although the `kube-proxy` executable supports a
`cleanup` function, this function is not an official feature and thus is only available
to use as-is.
<a id="example"></a>
Some of the details in this reference refer to an example: the back end Pods for a stateless
image-processing workload, running with three replicas. Those replicas are
fungible&mdash;frontends do not care which backend they use. While the actual Pods that
compose the backend set may change, the frontend clients should not need to be aware of that,
nor should they need to keep track of the set of backends themselves.
<!-- body -->
## Proxy modes
Note that the kube-proxy starts up in different modes, which are determined by its configuration.
- The kube-proxy's configuration is done via a ConfigMap, and the ConfigMap for
kube-proxy effectively deprecates the behavior for almost all of the flags for
the kube-proxy.
- The ConfigMap for the kube-proxy does not support live reloading of configuration.
- The ConfigMap parameters for the kube-proxy cannot all be validated and verified on startup.
For example, if your operating system doesn't allow you to run iptables commands,
the standard kernel kube-proxy implementation will not work.
Likewise, if you have an operating system which doesn't support `netsh`,
it will not run in Windows userspace mode.
### User space proxy mode {#proxy-mode-userspace}
{{< feature-state for_k8s_version="v1.23" state="deprecated" >}}
This (legacy) mode uses iptables to install interception rules, and then performs
traffic forwarding with the assistance of the kube-proxy tool.
The kube-procy watches the Kubernetes control plane for the addition, modification
and removal of Service and EndpointSlice objects. For each Service, the kube-proxy
opens a port (randomly chosen) on the local node. Any connections to this _proxy port_
are proxied to one of the Service's backend Pods (as reported via
EndpointSlices). The kube-proxy takes the `sessionAffinity` setting of the Service into
account when deciding which backend Pod to use.
The user-space proxy installs iptables rules which capture traffic to the
Service's `clusterIP` (which is virtual) and `port`. Those rules redirect that traffic
to the proxy port which proxies the backend Pod.
By default, kube-proxy in userspace mode chooses a backend via a round-robin algorithm.
{{< figure src="/images/docs/services-userspace-overview.svg" title="Services overview diagram for userspace proxy" class="diagram-medium" >}}
#### Example {#packet-processing-userspace}
As an example, consider the image processing application described [earlier](#example)
in the page.
When the backend Service is created, the Kubernetes control plane assigns a virtual
IP address, for example 10.0.0.1. Assuming the Service port is 1234, the
Service is observed by all of the kube-proxy instances in the cluster.
When a proxy sees a new Service, it opens a new random port, establishes an
iptables redirect from the virtual IP address to this new port, and starts accepting
connections on it.
When a client connects to the Service's virtual IP address, the iptables
rule kicks in, and redirects the packets to the proxy's own port.
The "Service proxy" chooses a backend, and starts proxying traffic from the client to the backend.
This means that Service owners can choose any port they want without risk of
collision. Clients can connect to an IP and port, without being aware
of which Pods they are actually accessing.
#### Scaling challenges {#scaling-challenges-userspace}
Using the userspace proxy for VIPs works at small to medium scale, but will
not scale to very large clusters with thousands of Services. The
[original design proposal for portals](https://github.com/kubernetes/kubernetes/issues/1107)
has more details on this.
Using the userspace proxy obscures the source IP address of a packet accessing
a Service.
This makes some kinds of network filtering (firewalling) impossible. The iptables
proxy mode does not
obscure in-cluster source IPs, but it does still impact clients coming through
a load balancer or node-port.
### `iptables` proxy mode {#proxy-mode-iptables}
In this mode, kube-proxy watches the Kubernetes control plane for the addition and
removal of Service and EndpointSlice objects. For each Service, it installs
iptables rules, which capture traffic to the Service's `clusterIP` and `port`,
and redirect that traffic to one of the Service's
backend sets. For each endpoint, it installs iptables rules which
select a backend Pod.
By default, kube-proxy in iptables mode chooses a backend at random.
Using iptables to handle traffic has a lower system overhead, because traffic
is handled by Linux netfilter without the need to switch between userspace and the
kernel space. This approach is also likely to be more reliable.
If kube-proxy is running in iptables mode and the first Pod that's selected
does not respond, the connection fails. This is different from userspace
mode: in that scenario, kube-proxy would detect that the connection to the first
Pod had failed and would automatically retry with a different backend Pod.
You can use Pod [readiness probes](/docs/concepts/workloads/pods/pod-lifecycle/#container-probes)
to verify that backend Pods are working OK, so that kube-proxy in iptables mode
only sees backends that test out as healthy. Doing this means you avoid
having traffic sent via kube-proxy to a Pod that's known to have failed.
{{< figure src="/images/docs/services-iptables-overview.svg" title="Services overview diagram for iptables proxy" class="diagram-medium" >}}
#### Example {#packet-processing-iptables}
Again, consider the image processing application described [earlier](#example).
When the backend Service is created, the Kubernetes control plane assigns a virtual
IP address, for example 10.0.0.1. For this example, assume that the
Service port is 1234.
All of the kube-proxy instances in the cluster observe the creation of the new
Service.
When kube-proxy on a node sees a new Service, it installs a series of iptables rules
which redirect from the virtual IP address to more iptables rules, defined per Service.
The per-Service rules link to further rules for each backend endpoint, and the per-
endpoint rules redirect traffic (using destination NAT) to the backends.
When a client connects to the Service's virtual IP address the iptables rule kicks in.
A backend is chosen (either based on session affinity or randomly) and packets are
redirected to the backend. Unlike the userspace proxy, packets are never
copied to userspace, the kube-proxy does not have to be running for the virtual
IP address to work, and Nodes see traffic arriving from the unaltered client IP
address.
This same basic flow executes when traffic comes in through a node-port or
through a load-balancer, though in those cases the client IP address does get altered.
### IPVS proxy mode {#proxy-mode-ipvs}
In `ipvs` mode, kube-proxy watches Kubernetes Services and EndpointSlices,
calls `netlink` interface to create IPVS rules accordingly and synchronizes
IPVS rules with Kubernetes Services and EndpointSlices periodically.
This control loop ensures that IPVS status matches the desired
state.
When accessing a Service, IPVS directs traffic to one of the backend Pods.
The IPVS proxy mode is based on netfilter hook function that is similar to
iptables mode, but uses a hash table as the underlying data structure and works
in the kernel space.
That means kube-proxy in IPVS mode redirects traffic with lower latency than
kube-proxy in iptables mode, with much better performance when synchronizing
proxy rules. Compared to the other proxy modes, IPVS mode also supports a
higher throughput of network traffic.
IPVS provides more options for balancing traffic to backend Pods;
these are:
* `rr`: round-robin
* `lc`: least connection (smallest number of open connections)
* `dh`: destination hashing
* `sh`: source hashing
* `sed`: shortest expected delay
* `nq`: never queue
{{< note >}}
To run kube-proxy in IPVS mode, you must make IPVS available on
the node before starting kube-proxy.
When kube-proxy starts in IPVS proxy mode, it verifies whether IPVS
kernel modules are available. If the IPVS kernel modules are not detected, then kube-proxy
falls back to running in iptables proxy mode.
{{< /note >}}
{{< figure src="/images/docs/services-ipvs-overview.svg" title="Services overview diagram for IPVS proxy" class="diagram-medium" >}}
## Session affinity
In these proxy models, the traffic bound for the Service's IP:Port is
proxied to an appropriate backend without the clients knowing anything
about Kubernetes or Services or Pods.
If you want to make sure that connections from a particular client
are passed to the same Pod each time, you can select the session affinity based
on the client's IP addresses by setting `.spec.sessionAffinity` to `ClientIP`
for a Service (the default is `None`).
### Session stickiness timeout
You can also set the maximum session sticky time by setting
`.spec.sessionAffinityConfig.clientIP.timeoutSeconds` appropriately for a Service.
(the default value is 10800, which works out to be 3 hours).
{{< note >}}
On Windows, setting the maximum session sticky time for Services is not supported.
{{< /note >}}
## IP address assignment to Services
Unlike Pod IP addresses, which actually route to a fixed destination,
Service IPs are not actually answered by a single host. Instead, kube-proxy
uses packet processing logic (such as Linux iptables) to define _virtual_ IP
addresses which are transparently redirected as needed.
When clients connect to the VIP, their traffic is automatically transported to an
appropriate endpoint. The environment variables and DNS for Services are actually
populated in terms of the Service's virtual IP address (and port).
### Avoiding collisions
One of the primary philosophies of Kubernetes is that you should not be
exposed to situations that could cause your actions to fail through no fault
of your own. For the design of the Service resource, this means not making
you choose your own port number if that choice might collide with
someone else's choice. That is an isolation failure.
In order to allow you to choose a port number for your Services, we must
ensure that no two Services can collide. Kubernetes does that by allocating each
Service its own IP address from within the `service-cluster-ip-range`
CIDR range that is configured for the API server.
To ensure each Service receives a unique IP, an internal allocator atomically
updates a global allocation map in {{< glossary_tooltip term_id="etcd" >}}
prior to creating each Service. The map object must exist in the registry for
Services to get IP address assignments, otherwise creations will
fail with a message indicating an IP address could not be allocated.
In the control plane, a background controller is responsible for creating that
map (needed to support migrating from older versions of Kubernetes that used
in-memory locking). Kubernetes also uses controllers to check for invalid
assignments (e.g. due to administrator intervention) and for cleaning up allocated
IP addresses that are no longer used by any Services.
#### IP address ranges for Service virtual IP addresses {#service-ip-static-sub-range}
{{< feature-state for_k8s_version="v1.25" state="beta" >}}
Kubernetes divides the `ClusterIP` range into two bands, based on
the size of the configured `service-cluster-ip-range` by using the following formula
`min(max(16, cidrSize / 16), 256)`. That formula paraphrases as _never less than 16 or
more than 256, with a graduated step function between them_.
Kubernetes prefers to allocate dynamic IP addresses to Services by choosing from the upper band,
which means that if you want to assign a specific IP address to a `type: ClusterIP`
Service, you should manually assign an IP address from the **lower** band. That approach
reduces the risk of a conflict over allocation.
If you disable the `ServiceIPStaticSubrange`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) then Kubernetes
uses a single shared pool for both manually and dynamically assigned IP addresses,
that are used for `type: ClusterIP` Services.
## Traffic policies
You can set the `.spec.internalTrafficPolicy` and `.spec.externalTrafficPolicy` fields
to control how Kubernetes routes traffic to healthy (“ready”) backends.
### Internal traffic policy
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
You can set the `.spec.internalTrafficPolicy` field to control how traffic from
internal sources is routed. Valid values are `Cluster` and `Local`. Set the field to
`Cluster` to route internal traffic to all ready endpoints and `Local` to only route
to ready node-local endpoints. If the traffic policy is `Local` and there are no
node-local endpoints, traffic is dropped by kube-proxy.
### External traffic policy
You can set the `.spec.externalTrafficPolicy` field to control how traffic from
external sources is routed. Valid values are `Cluster` and `Local`. Set the field
to `Cluster` to route external traffic to all ready endpoints and `Local` to only
route to ready node-local endpoints. If the traffic policy is `Local` and there are
are no node-local endpoints, the kube-proxy does not forward any traffic for the
relevant Service.
### Traffic to terminating endpoints
{{< feature-state for_k8s_version="v1.26" state="beta" >}}
If the `ProxyTerminatingEndpoints`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)
is enabled in kube-proxy and the traffic policy is `Local`, that node's
kube-proxy uses a more complicated algorithm to select endpoints for a Service.
With the feature enabled, kube-proxy checks if the node
has local endpoints and whether or not all the local endpoints are marked as terminating.
If there are local endpoints and **all** of them are terminating, then kube-proxy
will forward traffic to those terminating endpoints. Otherwise, kube-proxy will always
prefer forwarding traffic to endpoints that are not terminating.
This forwarding behavior for terminating endpoints exist to allow `NodePort` and `LoadBalancer`
Services to gracefully drain connections when using `externalTrafficPolicy: Local`.
As a deployment goes through a rolling update, nodes backing a load balancer may transition from
N to 0 replicas of that deployment. In some cases, external load balancers can send traffic to
a node with 0 replicas in between health check probes. Routing traffic to terminating endpoints
ensures that Node's that are scaling down Pods can gracefully receive and drain traffic to
those terminating Pods. By the time the Pod completes termination, the external load balancer
should have seen the node's health check failing and fully removed the node from the backend pool.
## {{% heading "whatsnext" %}}
To learn more about Services,
read [Connecting Applications with Services](/docs/concepts/services-networking/connect-applications-service/).
You can also:
* Read about [Services](/docs/concepts/services-networking/service/)
* Read the [API reference](/docs/reference/kubernetes-api/service-resources/service-v1/) for the Service API

View File

@ -1,4 +1,17 @@
---
title: Node Reference Information
weight: 80
no_list: true
---
This section contains the following reference topics about nodes:
* the kubelet's [checkpoint API](/docs/reference/node/kubelet-checkpoint-api/)
* a list of [Articles on dockershim Removal and on Using CRI-compatible Runtimes](/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes/)
You can also read node reference details from elsewhere in the
Kubernetes documentation, including:
* [Node Metrics Data](/docs/reference/instrumentation/node-metrics).

View File

@ -156,13 +156,13 @@ For more information on version skews, see:
2. Download the Google Cloud public signing key:
```shell
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
```
3. Add the Kubernetes `apt` repository:
```shell
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
```
4. Update `apt` package index, install kubelet, kubeadm and kubectl, and pin their version:
@ -172,6 +172,10 @@ For more information on version skews, see:
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
```
{{< note >}}
In releases older than Debian 12 and Ubuntu 22.04, `/etc/apt/keyrings` does not exist by default.
You can create this directory if you need to, making it world-readable but writeable only by admins.
{{< /note >}}
{{% /tab %}}
{{% tab name="Red Hat-based distributions" %}}

View File

@ -1,54 +0,0 @@
---
reviewers:
- andrewsykim
- johnbelamaric
- imroc
title: Enabling Service Topology
content_type: task
min-kubernetes-server-version: 1.17
---
<!-- overview -->
{{< feature-state for_k8s_version="v1.21" state="deprecated" >}}
This feature, specifically the alpha `topologyKeys` field, is deprecated since
Kubernetes v1.21.
[Topology Aware Hints](/docs/concepts/services-networking/topology-aware-hints/),
introduced in Kubernetes v1.21, provide similar functionality.
_Service Topology_ enables a {{< glossary_tooltip term_id="service">}} to route traffic based upon the Node
topology of the cluster. For example, a service can specify that traffic be
preferentially routed to endpoints that are on the same Node as the client, or
in the same availability zone.
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
The following prerequisites are needed in order to enable topology aware service
routing:
* Kubernetes v1.17 or later
* Configure {{< glossary_tooltip text="kube-proxy" term_id="kube-proxy" >}} to run in iptables mode or IPVS mode
<!-- steps -->
## Enable Service Topology
{{< feature-state for_k8s_version="v1.21" state="deprecated" >}}
To enable service topology, enable the `ServiceTopology`
[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) for all Kubernetes components:
```
--feature-gates="ServiceTopology=true`
```
## {{% heading "whatsnext" %}}
* Read about [Topology Aware Hints](/docs/concepts/services-networking/topology-aware-hints/), the replacement for the `topologyKeys` field.
* Read about [EndpointSlices](/docs/concepts/services-networking/endpoint-slices/)
* Read about the [Service Topology](/docs/concepts/services-networking/service-topology/) concept
* Read [Connecting Applications with Services](/docs/tutorials/services/connect-applications-service/)

View File

@ -92,7 +92,7 @@ illustrates how the management of groups occurs.
## Memory Manager configuration
Other Managers should be first pre-configured. Next, the Memory Manger feature should be enabled
Other Managers should be first pre-configured. Next, the Memory Manager feature should be enabled
and be run with `Static` policy (section [Static policy](#policy-static)).
Optionally, some amount of memory can be reserved for system or kubelet processes to increase
node stability (section [Reserved memory flag](#reserved-memory-flag)).

View File

@ -423,7 +423,7 @@ often good enough for the application to load the token on a schedule
{{< feature-state for_k8s_version="v1.21" state="stable" >}}
If you have enabled [token projection](#service-account-token-volume-projection)
If you have enabled [token projection](#serviceaccount-token-volume-projection)
for ServiceAccounts in your cluster, then you can also make use of the discovery
feature. Kubernetes provides a way for clients to federate as an _identity provider_,
so that one or more external systems can act as a _relying party_.

View File

@ -232,6 +232,8 @@ to collect metrics from each node. Depending on the metrics-server version it us
* Metrics resource endpoint `/metrics/resource` in version v0.6.0+ or
* Summary API endpoint `/stats/summary` in older versions
## {{% heading "whatsnext" %}}
To learn more about the metrics-server, see the
[metrics-server repository](https://github.com/kubernetes-sigs/metrics-server).
@ -243,26 +245,5 @@ You can also check out the following:
* [metrics-server releases](https://github.com/kubernetes-sigs/metrics-server/releases)
* [Horizontal Pod Autoscaling](/docs/tasks/run-application/horizontal-pod-autoscale/)
### Summary API source
The [kubelet](/docs/reference/command-line-tools-reference/kubelet/) gathers stats at the node,
volume, pod and container level, and emits this information in
the [Summary API](https://github.com/kubernetes/kubernetes/blob/7d309e0104fedb57280b261e5677d919cb2a0e2d/staging/src/k8s.io/kubelet/pkg/apis/stats/v1alpha1/types.go)
for consumers to read.
Here is an example of a Summary API request for a `minikube` node:
```shell
kubectl get --raw "/api/v1/nodes/minikube/proxy/stats/summary"
```
Here is the same API call using `curl`:
```shell
curl http://localhost:8080/api/v1/nodes/minikube/proxy/stats/summary
```
{{< note >}}
The summary API `/stats/summary` endpoint will be replaced by the `/metrics/resource` endpoint
beginning with metrics-server 0.6.x.
{{< /note >}}
To learn about how the kubelet serves node metrics, and how you can access those via
the Kubernetes API, read [Node Metrics Data](/docs/reference/instrumentation/node-metrics).

View File

@ -0,0 +1,128 @@
---
title: Job with Pod-to-Pod Communication
content_type: task
min-kubernetes-server-version: v1.21
weight: 30
---
<!-- overview -->
In this example, you will run a Job in [Indexed completion mode](/blog/2021/04/19/introducing-indexed-jobs/) configured such that
the pods created by the Job can communicate with each other using pod hostnames rather than pod IP addresses.
Pods within a Job might need to communicate among themselves. The user workload running in each pod could query the Kubernetes API server
to learn the IPs of the other Pods, but it's much simpler to rely on Kubernetes' built-in DNS resolution.
Jobs in Indexed completion mode automatically set the pods' hostname to be in the format of
`${jobName}-${completionIndex}`. You can use this format to deterministically build
pod hostnames and enable pod communication *without* needing to create a client connection to
the Kubernetes control plane to obtain pod hostnames/IPs via API requests.
This configuration is useful
for use cases where pod networking is required but you don't want to depend on a network
connection with the Kubernetes API server.
## {{% heading "prerequisites" %}}
You should already be familiar with the basic use of [Job](/docs/concepts/workloads/controllers/job/).
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{<note>}}
If you are using MiniKube or a similar tool, you may need to take
[extra steps](https://minikube.sigs.k8s.io/docs/handbook/addons/ingress-dns/)
to ensure you have DNS.
{{</note>}}
<!-- steps -->
## Starting a Job with Pod-to-Pod Communication
To enable pod-to-pod communication using pod hostnames in a Job, you must do the following:
1. Set up a [headless service](/docs/concepts/services-networking/service/#headless-services)
with a valid label selector for the pods created by your Job. The headless service must be in the same namespace as
the Job. One easy way to do this is to use the `job-name: <your-job-name>` selector, since the `job-name` label will be automatically added by Kubernetes. This configuration will trigger the DNS system to create records of the hostnames of
the pods running your Job.
2. Configure the headless service as subdomain service for the Job pods by including the following value in your Job template spec:
```yaml
subdomain: <headless-svc-name>
```
### Example
Below is a working example of a Job with pod-to-pod communication via pod hostnames enabled.
The Job is completed only after all pods successfully ping each other using hostnames.
{{<note>}}
In the Bash script executed on each pod in the example below, the pod hostnames can be prefixed
by the namespace as well if the pod needs to be reached from outside the namespace.
{{</note>}}
```yaml
apiVersion: v1
kind: Service
metadata:
name: headless-svc
spec:
clusterIP: None # clusterIP must be None to create a headless service
selector:
job-name: example-job # must match Job name
---
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
completions: 3
parallelism: 3
completionMode: Indexed
template:
spec:
subdomain: headless-svc # has to match Service name
restartPolicy: Never
containers:
- name: example-workload
image: bash:latest
command:
- bash
- -c
- |
for i in 0 1 2
do
gotStatus="-1"
wantStatus="0"
while [ $gotStatus -ne $wantStatus ]
do
ping -c 1 example-job-${i}.headless-svc > /dev/null 2>&1
gotStatus=$?
if [ $gotStatus -ne $wantStatus ]; then
echo "Failed to ping pod example-job-${i}.headless-svc, retrying in 1 second..."
sleep 1
fi
done
echo "Successfully pinged pod: example-job-${i}.headless-svc"
done
```
After applying the example above, reach each other over the network
using: `<pod-hostname>.<headless-service-name>`. You should see output similar to the following:
```shell
kubectl logs example-job-0-qws42
```
```
Failed to ping pod example-job-0.headless-svc, retrying in 1 second...
Successfully pinged pod: example-job-0.headless-svc
Successfully pinged pod: example-job-1.headless-svc
Successfully pinged pod: example-job-2.headless-svc
```
{{<note>}}
Keep in mind that the `<pod-hostname>.<headless-service-name>` name format used
in this example would not work with DNS policy set to `None` or `Default`.
You can learn more about pod DNS policies [here](/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy).
{{</note>}}

View File

@ -47,7 +47,30 @@ horizontal pod autoscaling.
## How does a HorizontalPodAutoscaler work?
{{< figure src="/images/docs/horizontal-pod-autoscaler.svg" caption="HorizontalPodAutoscaler controls the scale of a Deployment and its ReplicaSet" class="diagram-medium">}}
{{< mermaid >}}
graph BT
hpa[Horizontal Pod Autoscaler] --> scale[Scale]
subgraph rc[RC / Deployment]
scale
end
scale -.-> pod1[Pod 1]
scale -.-> pod2[Pod 2]
scale -.-> pod3[Pod N]
classDef hpa fill:#D5A6BD,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D;
classDef rc fill:#F9CB9C,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D;
classDef scale fill:#B6D7A8,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D;
classDef pod fill:#9FC5E8,stroke:#1E1E1D,stroke-width:1px,color:#1E1E1D;
class hpa hpa;
class rc rc;
class scale scale;
class pod1,pod2,pod3 pod
{{< /mermaid >}}
Figure 1. HorizontalPodAutoscaler controls the scale of a Deployment and its ReplicaSet
Kubernetes implements horizontal pod autoscaling as a control loop that runs intermittently
(it is not a continuous process). The interval is set by the

View File

@ -35,7 +35,7 @@ shows you what you need to do to get up and running with kind.
## minikube
Like `kind`, [`minikube`](https://minikube.sigs.k8s.io/) is a tool that lets you run Kubernetes
locally. `minikube` runs a single-node Kubernetes cluster on your personal
locally. `minikube` runs an all-in-one or a multi-node local Kubernetes cluster on your personal
computer (including Windows, macOS and Linux PCs) so that you can try out
Kubernetes, or for daily development work.

View File

@ -120,13 +120,13 @@ For example, to download version {{< param "fullversion" >}} on Linux, type:
2. Download the Google Cloud public signing key:
```shell
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
```
3. Add the Kubernetes `apt` repository:
```shell
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
```
4. Update `apt` package index with the new repository and install kubectl:
@ -135,6 +135,10 @@ For example, to download version {{< param "fullversion" >}} on Linux, type:
sudo apt-get update
sudo apt-get install -y kubectl
```
{{< note >}}
In releases older than Debian 12 and Ubuntu 22.04, `/etc/apt/keyrings` does not exist by default.
You can create this directory if you need to, making it world-readable but writeable only by admins.
{{< /note >}}
{{% /tab %}}

View File

@ -194,6 +194,7 @@ GitHub team: [@kubernetes/sig-release-leads](https://github.com/orgs/kubernetes/
### Chairs
- Jeremy Rickard ([@jeremyrickard](https://github.com/jeremyrickard))
- Sascha Grunert ([@saschagrunert](https://github.com/saschagrunert))
- Stephen Augustus ([@justaugustus](https://github.com/justaugustus))
@ -201,7 +202,7 @@ GitHub team: [@kubernetes/sig-release-leads](https://github.com/orgs/kubernetes/
- Adolfo García Veytia ([@puerco](https://github.com/puerco))
- Carlos Panato ([@cpanato](https://github.com/cpanato))
- Jeremy Rickard ([@jeremyrickard](https://github.com/jeremyrickard))
- Verónica López ([@verolop](https://github.com/verolop))
---

View File

@ -899,7 +899,7 @@ Un Secret solo se envía a un nodo si un pod en ese nodo lo requiere. Kubelet al
Puede haber Secrets para varios Pods en el mismo nodo. Sin embargo, solo los Secrets que solicita un Pod son potencialmente visibles dentro de sus contenedores. Por lo tanto, un Pod no tiene acceso a los Secrets de otro Pod.
Puede haver varios contenedores en un Pod. Sin embargo, cada contenedor en un pod tiene que solicitar el volumen del Secret en su
Puede haber varios contenedores en un Pod. Sin embargo, cada contenedor en un pod tiene que solicitar el volumen del Secret en su
`volumeMounts` para que sea visible dentro del contenedor. Esto se puede usar para construir particiones de seguridad útiles en el Pod level](#use-case-secret-visible-to-one-container-in-a-pod).
En la mayoría de las distribuciones Kubernetes-project-maintained, la comunicación entre usuario a el apiserver, y del apiserver a kubelets, ista protegido por SSL/TLS.

View File

@ -242,7 +242,7 @@ Au lieu de cela, un volume existant est redimensionné.
#### Redimensionnement de volume CSI
{{< feature-state for_k8s_version="v1.16" state="beta" >}}
{{< feature-state for_k8s_version="v1.24" state="stable" >}}
La prise en charge du redimensionnement des volumes CSI est activée par défaut, mais elle nécessite également un pilote CSI spécifique pour prendre en charge le redimensionnement des volumes.
Reportez-vous à la documentation du pilote CSI spécifique pour plus d'informations.

View File

@ -0,0 +1,20 @@
---
title: रेप्लिकासेट (ReplicaSet)
id: replica-set
date: 2018-04-12
full_link: /docs/concepts/workloads/controllers/replicaset/
short_description: >
रेप्लिकासेट यह सुनिश्चित करता है कि किसी एक अवसर पर निर्दिष्ट संख्या में पॉड प्रतिकृतियां चल रही हैं।
aka:
tags:
- fundamental
- core-object
- workload
---
एक रेप्लिकासेट (का उद्देश्य) किसी भी समय चल रहे रेप्लिका पॉड्स का एक समूह बनाए रखना है।
<!--more-->
वर्कलोड ऑब्जेक्ट्स, जैसे {{< glossary_tooltip text="डिप्लॉयमेंट" term_id="deployment" >}}, रेप्लिकासेट्स
के विनिर्देश के आधार पर आपके क्लस्टर पर कॉन्फ़िगर की गई संख्या में {{< glossary_tooltip term_id="pod" text="पॉड्स" >}} चल रहे है ये सुनिश्चित करते हैं।

View File

@ -91,7 +91,7 @@ Kubernetes {{< param "version" >}}では、OpenAPI v3によるAPI仕様をベー
}
}
```
<!-- for editors: intionally use yaml instead of json here, to prevent syntax highlight error. -->
<!-- for editors: intentionally use yaml instead of json here, to prevent syntax highlight error. -->
クライアントサイドのキャッシングを改善するために、相対URLはイミュータブルな(不変の)OpenAPI記述を指しています。
また、APIサーバーも、同様の目的で適切なHTTPキャッシュヘッダー(`Expires`には1年先の日付、`Cache-Control`には`immutable`)をセットします。廃止されたURLが使用された場合、APIサーバーは最新のURLへのリダイレクトを返します。

View File

@ -6,7 +6,7 @@ weight: 30
<!-- overview -->
{{< feature-state for_k8s_version="v1.18" state="beta" >}}
{{< feature-state for_k8s_version="v1.24" state="stable" >}}
PodをNode上で実行する時に、Pod自身は大量のシステムリソースを消費します。これらのリソースは、Pod内のコンテナ(群)を実行するために必要なリソースとして追加されます。Podのオーバーヘッドは、コンテナの要求と制限に加えて、Podのインフラストラクチャで消費されるリソースを計算するための機能です。
@ -29,16 +29,15 @@ Podのオーバーヘッドを有効にした場合、Podのスケジューリ
Podのオーバーヘッド機能を使用するためには、`overhead`フィールドが定義されたRuntimeClassが必要です。例として、仮想マシンとゲストOSにPodあたり約120MiBを使用する仮想化コンテナランタイムで、次のようなRuntimeClassを定義できます。
```yaml
---
kind: RuntimeClass
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: kata-fc
name: kata-fc
handler: kata-fc
overhead:
podFixed:
memory: "120Mi"
cpu: "250m"
podFixed:
memory: "120Mi"
cpu: "250m"
```
`kata-fc`RuntimeClassハンドラーを指定して作成されたワークロードは、リソースクォータの計算や、Nodeのスケジューリング、およびPodのcgroupのサイズ決定にメモリーとCPUのオーバーヘッドが考慮されます。
@ -54,7 +53,7 @@ spec:
runtimeClassName: kata-fc
containers:
- name: busybox-ctr
image: busybox
image: busybox:1.28
stdin: true
tty: true
resources:
@ -108,9 +107,9 @@ kubectl describe node | grep test-pod -B2
出力では、2250mのCPUと320MiBのメモリーが要求されており、Podのオーバーヘッドが含まれていることが分かります。
```
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
default test-pod 2250m (56%) 2250m (56%) 320Mi (1%) 320Mi (1%) 36m
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
default test-pod 2250m (56%) 2250m (56%) 320Mi (1%) 320Mi (1%) 36m
```
## Podのcgroupの制限を確認
@ -132,7 +131,7 @@ sudo crictl inspectp -o=json $POD_ID | grep cgroupsPath
結果のcgroupパスにはPodの`ポーズ中`コンテナも含まれます。Podレベルのcgroupはつ上のディレクトリです。
```
"cgroupsPath": "/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/7ccf55aee35dd16aca4189c952d83487297f3cd760f1bbf09620e206e7d0c27a"
"cgroupsPath": "/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/7ccf55aee35dd16aca4189c952d83487297f3cd760f1bbf09620e206e7d0c27a"
```
今回のケースでは、Podのcgroupパスは、`kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2`となります。メモリーのPodレベルのcgroupの設定を確認しましょう。

View File

@ -5,13 +5,17 @@ feature:
description: >
Serviceのトラフィックをクラスタートポロジーに基づいてルーティングします。
content_type: concept
weight: 10
weight: 150
---
<!-- overview -->
{{< feature-state for_k8s_version="v1.17" state="alpha" >}}
{{< feature-state for_k8s_version="v1.21" state="deprecated" >}}
{{< note >}}
この機能、特にアルファ版の`topologyKeys`APIは、Kubernetes v1.21以降では非推奨です。Kubernetes v1.21で導入された、[トポロジーを意識したヒント](/ja/docs/concepts/services-networking/topology-aware-hints/)が同様の機能を提供します。
{{</ note >}}
*Serviceトポロジー*を利用すると、Serviceのトラフィックをクラスターのードトポロジーに基づいてルーティングできるようになります。たとえば、あるServiceのトラフィックに対して、できるだけ同じードや同じアベイラビリティゾーン上にあるエンドポイントを優先してルーティングするように指定できます。
@ -139,6 +143,6 @@ spec:
## {{% heading "whatsnext" %}}
* [Serviceトポトジーを有効にする](/ja/docs/tasks/administer-cluster/enabling-service-topology)を読む。
* [サービスとアプリケーションの接続](/ja/docs/concepts/services-networking/connect-applications-service/)を読む。
* [トポロジーを意識したヒント](/ja/docs/concepts/services-networking/topology-aware-hints/)を読む。
* [サービスとアプリケーションの接続](/ja/docs/tutorials/services/connect-applications-service/)を読む。

View File

@ -243,7 +243,7 @@ PVCに対してさらに大きなボリュームを要求するには、PVCオ
#### CSIボリュームの拡張
{{< feature-state for_k8s_version="v1.16" state="beta" >}}
{{< feature-state for_k8s_version="v1.24" state="stable" >}}
CSIボリュームの拡張のサポートはデフォルトで有効になっていますが、ボリューム拡張をサポートするにはボリューム拡張を利用できるCSIドライバーも必要です。詳細については、それぞれのCSIドライバーのドキュメントを参照してください。

View File

@ -0,0 +1,30 @@
---
title: ボリュームヘルスモニタリング
content_type: concept
weight: 100
---
<!-- overview -->
{{< feature-state for_k8s_version="v1.21" state="alpha" >}}
{{< glossary_tooltip text="CSI" term_id="csi" >}}ボリュームヘルスモニタリングにより、CSIドライバーは、基盤となるストレージシステムから異常なボリューム状態を検出し、それらを{{< glossary_tooltip text="PVC" term_id= "persistent-volume-claim" >}}または{{< glossary_tooltip text="Pod" term_id="pod" >}}のイベントとして報告できます。
<!-- body -->
## ボリュームヘルスモニタリング
Kubernetes _volume health monitoring_ は、KubernetesがContainerStorageInterface(CSI)を実装する方法の一部です。ボリュームヘルスモニタリング機能は、外部のヘルスモニターコントローラーと{{< glossary_tooltip term_id="kubelet" text="kubelet" >}}の2つのコンポーネントで実装されます。
CSIドライバーがコントローラー側からのボリュームヘルスモニタリング機能をサポートしている場合、CSIボリュームで異常なボリューム状態が検出されると、関連する{{< glossary_tooltip text="PersistentVolumeClaim" term_id="persistent-volume-claim" >}}(PVC)でイベントが報告されます。
外部ヘルスモニター{{< glossary_tooltip text="コントローラー" term_id="controller" >}}も、ノード障害イベントを監視します。`enable-node-watcher`フラグをtrueに設定することで、ード障害の監視を有効にできます。外部ヘルスモニターがード障害イベントを検出すると、コントローラーは、このPVCを使用するポッドが障害ード上にあることを示すために、PVCでイベントが報告されることを報告します。
CSIドライバーがード側からのボリュームヘルスモニタリング機能をサポートしている場合、CSIボリュームで異常なボリューム状態が検出されると、PVCを使用するすべてのPodでイベントが報告されます。さらに、ボリュームヘルス情報はKubelet VolumeStatsメトリクスとして公開されます。新しいメトリックkubelet_volume_stats_health_status_abnormalが追加されました。このメトリックには`namespace`と`persistentvolumeclaim`の2つのラベルが含まれます。カウントは1または0です。1はボリュームが異常であることを示し、0はボリュームが正常であることを示します。詳細については、[KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1432-volume-health-monitor#kubelet-metrics-changes)を確認してください。
{{< note >}}
ノード側からこの機能を使用するには、`CSIVolumeHealth`[feature gate](/docs/reference/command-line-tools-reference/feature-gates/)を有効にする必要があります。
{{< /note >}}
## {{% heading "whatsnext" %}}
[CSIドライバーのドキュメント](https://kubernetes-csi.github.io/docs/drivers.html)を参照して、この機能を実装しているCSIドライバーを確認してください。

View File

@ -35,121 +35,154 @@ content_type: concept
| 機能名 | デフォルト値 | ステージ | 導入開始バージョン | 最終利用可能バージョン |
|---------|---------|-------|-------|-------|
| `AnyVolumeDataSource` | `false` | Alpha | 1.18 | |
| `APIListChunking` | `false` | Alpha | 1.8 | 1.8 |
| `APIListChunking` | `true` | Beta | 1.9 | |
| `APIPriorityAndFairness` | `false` | Alpha | 1.17 | |
| `APIResponseCompression` | `false` | Alpha | 1.7 | |
| `APIPriorityAndFairness` | `false` | Alpha | 1.18 | 1.19 |
| `APIPriorityAndFairness` | `true` | Beta | 1.20 | |
| `APIResponseCompression` | `false` | Alpha | 1.7 | 1.15 |
| `APIResponseCompression` | `true` | Beta | 1.16 | |
| `APIServerIdentity` | `false` | Alpha | 1.20 | |
| `APIServerTracing` | `false` | Alpha | 1.22 | |
| `AllowInsecureBackendProxy` | `true` | Beta | 1.17 | |
| `AnyVolumeDataSource` | `false` | Alpha | 1.18 | 1.23 |
| `AnyVolumeDataSource` | `true` | Beta | 1.24 | |
| `AppArmor` | `true` | Beta | 1.4 | |
| `BalanceAttachedNodeVolumes` | `false` | Alpha | 1.11 | |
| `BoundServiceAccountTokenVolume` | `false` | Alpha | 1.13 | |
| `CPUManager` | `false` | Alpha | 1.8 | 1.9 |
| `CPUManager` | `true` | Beta | 1.10 | |
| `CRIContainerLogRotation` | `false` | Alpha | 1.10 | 1.10 |
| `CRIContainerLogRotation` | `true` | Beta| 1.11 | |
| `CSIInlineVolume` | `false` | Alpha | 1.15 | 1.15 |
| `CSIInlineVolume` | `true` | Beta | 1.16 | - |
| `CSIMigration` | `false` | Alpha | 1.14 | 1.16 |
| `CSIMigration` | `true` | Beta | 1.17 | |
| `CSIMigrationAWS` | `false` | Alpha | 1.14 | |
| `CSIMigrationAWS` | `false` | Beta | 1.17 | |
| `CSIMigrationAWSComplete` | `false` | Alpha | 1.17 | |
| `CSIMigrationAzureDisk` | `false` | Alpha | 1.15 | |
| `CSIMigrationAzureDiskComplete` | `false` | Alpha | 1.17 | |
| `CSIMigrationAzureFile` | `false` | Alpha | 1.15 | |
| `CSIMigrationAzureFileComplete` | `false` | Alpha | 1.17 | |
| `CSIMigrationGCE` | `false` | Alpha | 1.14 | 1.16 |
| `CSIMigrationGCE` | `false` | Beta | 1.17 | |
| `CSIMigrationGCEComplete` | `false` | Alpha | 1.17 | |
| `CSIMigrationOpenStack` | `false` | Alpha | 1.14 | |
| `CSIMigrationOpenStackComplete` | `false` | Alpha | 1.17 | |
| `ConfigurableFSGroupPolicy` | `false` | Alpha | 1.18 | |
| `CPUManagerPolicyAlphaOptions` | `false` | Alpha | 1.23 | |
| `CPUManagerPolicyBetaOptions` | `true` | Beta | 1.23 | |
| `CPUManagerPolicyOptions` | `false` | Alpha | 1.22 | 1.22 |
| `CPUManagerPolicyOptions` | `true` | Beta | 1.23 | |
| `CSIMigrationAzureFile` | `false` | Alpha | 1.15 | 1.20 |
| `CSIMigrationAzureFile` | `false` | Beta | 1.21 | 1.23 |
| `CSIMigrationAzureFile` | `true` | Beta | 1.24 | |
| `CSIMigrationPortworx` | `false` | Alpha | 1.23 | 1.24 |
| `CSIMigrationPortworx` | `false` | Beta | 1.25 | |
| `CSIMigrationRBD` | `false` | Alpha | 1.23 | |
| `CSIMigrationvSphere` | `false` | Alpha | 1.18 | 1.18 |
| `CSIMigrationvSphere` | `false` | Beta | 1.19 | 1.24 |
| `CSIMigrationvSphere` | `true` | Beta | 1.25 | |
| `CSINodeExpandSecret` | `false` | Alpha | 1.25 | |
| `CSIVolumeHealth` | `false` | Alpha | 1.21 | |
| `ContainerCheckpoint` | `false` | Alpha | 1.25 | |
| `ContextualLogging` | `false` | Alpha | 1.24 | |
| `CustomCPUCFSQuotaPeriod` | `false` | Alpha | 1.12 | |
| `CustomResourceDefaulting` | `false` | Alpha| 1.15 | 1.15 |
| `CustomResourceDefaulting` | `true` | Beta | 1.16 | |
| `CustomResourceValidationExpressions` | `false` | Alpha | 1.23 | 1.24 |
| `CustomResourceValidationExpressions` | `true` | Beta | 1.25 | |
| `DelegateFSGroupToCSIDriver` | `false` | Alpha | 1.22 | 1.22 |
| `DelegateFSGroupToCSIDriver` | `true` | Beta | 1.23 | |
| `DevicePlugins` | `false` | Alpha | 1.8 | 1.9 |
| `DevicePlugins` | `true` | Beta | 1.10 | |
| `DryRun` | `false` | Alpha | 1.12 | 1.12 |
| `DryRun` | `true` | Beta | 1.13 | |
| `DynamicAuditing` | `false` | Alpha | 1.13 | |
| `DynamicKubeletConfig` | `false` | Alpha | 1.4 | 1.10 |
| `DynamicKubeletConfig` | `true` | Beta | 1.11 | |
| `EndpointSlice` | `false` | Alpha | 1.16 | 1.16 |
| `EndpointSlice` | `false` | Beta | 1.17 | |
| `EndpointSlice` | `true` | Beta | 1.18 | |
| `EndpointSliceProxying` | `false` | Alpha | 1.18 | |
| `EphemeralContainers` | `false` | Alpha | 1.16 | |
| `ExpandCSIVolumes` | `false` | Alpha | 1.14 | 1.15 |
| `ExpandCSIVolumes` | `true` | Beta | 1.16 | |
| `ExpandInUsePersistentVolumes` | `false` | Alpha | 1.11 | 1.14 |
| `ExpandInUsePersistentVolumes` | `true` | Beta | 1.15 | |
| `ExpandPersistentVolumes` | `false` | Alpha | 1.8 | 1.10 |
| `ExpandPersistentVolumes` | `true` | Beta | 1.11 | |
| `DisableCloudProviders` | `false` | Alpha | 1.22 | |
| `DisableKubeletCloudCredentialProviders` | `false` | Alpha | 1.23 | |
| `DownwardAPIHugePages` | `false` | Alpha | 1.20 | 1.20 |
| `DownwardAPIHugePages` | `false` | Beta | 1.21 | 1.21 |
| `DownwardAPIHugePages` | `true` | Beta | 1.22 | |
| `EndpointSliceTerminatingCondition` | `false` | Alpha | 1.20 | 1.21 |
| `EndpointSliceTerminatingCondition` | `true` | Beta | 1.22 | |
| `ExpandedDNSConfig` | `false` | Alpha | 1.22 | |
| `ExperimentalHostUserNamespaceDefaulting` | `false` | Beta | 1.5 | |
| `EvenPodsSpread` | `false` | Alpha | 1.16 | 1.17 |
| `EvenPodsSpread` | `true` | Beta | 1.18 | |
| `GRPCContainerProbe` | `false` | Alpha | 1.23 | 1.23 |
| `GRPCContainerProbe` | `true` | Beta | 1.24 | |
| `GracefulNodeShutdown` | `false` | Alpha | 1.20 | 1.20 |
| `GracefulNodeShutdown` | `true` | Beta | 1.21 | |
| `GracefulNodeShutdownBasedOnPodPriority` | `false` | Alpha | 1.23 | 1.23 |
| `GracefulNodeShutdownBasedOnPodPriority` | `true` | Beta | 1.24 | |
| `HPAContainerMetrics` | `false` | Alpha | 1.20 | |
| `HPAScaleToZero` | `false` | Alpha | 1.16 | |
| `HugePageStorageMediumSize` | `false` | Alpha | 1.18 | |
| `HyperVContainer` | `false` | Alpha | 1.10 | |
| `ImmutableEphemeralVolumes` | `false` | Alpha | 1.18 | |
| `HonorPVReclaimPolicy` | `false` | Alpha | 1.23 | |
| `InTreePluginAWSUnregister` | `false` | Alpha | 1.21 | |
| `InTreePluginAzureDiskUnregister` | `false` | Alpha | 1.21 | |
| `InTreePluginAzureFileUnregister` | `false` | Alpha | 1.21 | |
| `InTreePluginGCEUnregister` | `false` | Alpha | 1.21 | |
| `InTreePluginOpenStackUnregister` | `false` | Alpha | 1.21 | |
| `InTreePluginPortworxUnregister` | `false` | Alpha | 1.23 | |
| `InTreePluginRBDUnregister` | `false` | Alpha | 1.23 | |
| `InTreePluginvSphereUnregister` | `false` | Alpha | 1.21 | |
| `IPTablesOwnershipCleanup` | `false` | Alpha | 1.25 | |
| `JobMutableNodeSchedulingDirectives` | `true` | Beta | 1.23 | |
| `JobPodFailurePolicy` | `false` | Alpha | 1.25 | - |
| `JobReadyPods` | `false` | Alpha | 1.23 | 1.23 |
| `JobReadyPods` | `true` | Beta | 1.24 | |
| `JobTrackingWithFinalizers` | `false` | Alpha | 1.22 | 1.22 |
| `JobTrackingWithFinalizers` | `false` | Beta | 1.23 | 1.24 |
| `JobTrackingWithFinalizers` | `true` | Beta | 1.25 | |
| `KubeletCredentialProviders` | `false` | Alpha | 1.20 | 1.23 |
| `KubeletCredentialProviders` | `true` | Beta | 1.24 | |
| `KubeletInUserNamespace` | `false` | Alpha | 1.22 | |
| `KubeletPodResources` | `false` | Alpha | 1.13 | 1.14 |
| `KubeletPodResources` | `true` | Beta | 1.15 | |
| `LegacyNodeRoleBehavior` | `true` | Alpha | 1.16 | |
| `LocalStorageCapacityIsolation` | `false` | Alpha | 1.7 | 1.9 |
| `LocalStorageCapacityIsolation` | `true` | Beta | 1.10 | |
| `LocalStorageCapacityIsolationFSQuotaMonitoring` | `false` | Alpha | 1.15 | |
| `MountContainers` | `false` | Alpha | 1.9 | |
| `NodeDisruptionExclusion` | `false` | Alpha | 1.16 | |
| `NonPreemptingPriority` | `false` | Alpha | 1.15 | |
| `PodDisruptionBudget` | `false` | Alpha | 1.3 | 1.4 |
| `PodDisruptionBudget` | `true` | Beta | 1.5 | |
| `PodOverhead` | `false` | Alpha | 1.16 | - |
| `KubeletPodResourcesGetAllocatable` | `false` | Alpha | 1.21 | 1.22 |
| `KubeletPodResourcesGetAllocatable` | `true` | Beta | 1.23 | |
| `KubeletTracing` | `false` | Alpha | 1.25 | |
| `LegacyServiceAccountTokenNoAutoGeneration` | `true` | Beta | 1.24 | |
| `LocalStorageCapacityIsolationFSQuotaMonitoring` | `false` | Alpha | 1.15 | 1.24 |
| `LocalStorageCapacityIsolationFSQuotaMonitoring` | `true` | Beta | 1.25 | |
| `LogarithmicScaleDown` | `false` | Alpha | 1.21 | 1.21 |
| `LogarithmicScaleDown` | `true` | Beta | 1.22 | |
| `MatchLabelKeysInPodTopologySpread` | `false` | Alpha | 1.25 | |
| `MaxUnavailableStatefulSet` | `false` | Alpha | 1.24 | |
| `MemoryManager` | `false` | Alpha | 1.21 | 1.21 |
| `MemoryManager` | `true` | Beta | 1.22 | |
| `MemoryQoS` | `false` | Alpha | 1.22 | |
| `MinDomainsInPodTopologySpread` | `false` | Alpha | 1.24 | 1.24 |
| `MinDomainsInPodTopologySpread` | `false` | Beta | 1.25 | |
| `MixedProtocolLBService` | `false` | Alpha | 1.20 | 1.23 |
| `MixedProtocolLBService` | `true` | Beta | 1.24 | |
| `MultiCIDRRangeAllocator` | `false` | Alpha | 1.25 | |
| `NetworkPolicyStatus` | `false` | Alpha | 1.24 | |
| `NodeInclusionPolicyInPodTopologySpread` | `false` | Alpha | 1.25 | |
| `NodeOutOfServiceVolumeDetach` | `false` | Alpha | 1.24 | |
| `NodeSwap` | `false` | Alpha | 1.22 | |
| `OpenAPIEnums` | `false` | Alpha | 1.23 | 1.23 |
| `OpenAPIEnums` | `true` | Beta | 1.24 | |
| `OpenAPIV3` | `false` | Alpha | 1.23 | 1.23 |
| `OpenAPIV3` | `true` | Beta | 1.24 | |
| `PodAndContainerStatsFromCRI` | `false` | Alpha | 1.23 | |
| `PodDeletionCost` | `false` | Alpha | 1.21 | 1.21 |
| `PodDeletionCost` | `true` | Beta | 1.22 | |
| `PodDisruptionConditions` | `false` | Alpha | 1.25 | - |
| `PodHasNetworkCondition` | `false` | Alpha | 1.25 | |
| `ProbeTerminationGracePeriod` | `false` | Alpha | 1.21 | 1.21 |
| `ProbeTerminationGracePeriod` | `false` | Beta | 1.22 | 1.24 |
| `ProbeTerminationGracePeriod` | `true` | Beta | 1.25 | |
| `ProcMountType` | `false` | Alpha | 1.12 | |
| `ProxyTerminatingEndpoints` | `false` | Alpha | 1.22 | |
| `QOSReserved` | `false` | Alpha | 1.11 | |
| `RemainingItemCount` | `false` | Alpha | 1.15 | |
| `ResourceLimitsPriorityFunction` | `false` | Alpha | 1.9 | |
| `RotateKubeletClientCertificate` | `true` | Beta | 1.8 | |
| `ReadWriteOncePod` | `false` | Alpha | 1.22 | |
| `RecoverVolumeExpansionFailure` | `false` | Alpha | 1.23 | |
| `RemainingItemCount` | `false` | Alpha | 1.15 | 1.15 |
| `RemainingItemCount` | `true` | Beta | 1.16 | |
| `RetroactiveDefaultStorageClass` | `false` | Alpha | 1.25 | |
| `RotateKubeletServerCertificate` | `false` | Alpha | 1.7 | 1.11 |
| `RotateKubeletServerCertificate` | `true` | Beta | 1.12 | |
| `RunAsGroup` | `true` | Beta | 1.14 | |
| `RuntimeClass` | `false` | Alpha | 1.12 | 1.13 |
| `RuntimeClass` | `true` | Beta | 1.14 | |
| `SCTPSupport` | `false` | Alpha | 1.12 | |
| `ServerSideApply` | `false` | Alpha | 1.14 | 1.15 |
| `ServerSideApply` | `true` | Beta | 1.16 | |
| `ServiceAccountIssuerDiscovery` | `false` | Alpha | 1.18 | |
| `ServiceAppProtocol` | `false` | Alpha | 1.18 | |
| `ServiceNodeExclusion` | `false` | Alpha | 1.8 | |
| `ServiceTopology` | `false` | Alpha | 1.17 | |
| `StartupProbe` | `false` | Alpha | 1.16 | 1.17 |
| `StartupProbe` | `true` | Beta | 1.18 | |
| `SELinuxMountReadWriteOncePod` | `false` | Alpha | 1.25 | |
| `SeccompDefault` | `false` | Alpha | 1.22 | 1.24 |
| `SeccompDefault` | `true` | Beta | 1.25 | |
| `ServerSideFieldValidation` | `false` | Alpha | 1.23 | 1.24 |
| `ServerSideFieldValidation` | `true` | Beta | 1.25 | |
| `ServiceIPStaticSubrange` | `false` | Alpha | 1.24 | 1.24 |
| `ServiceIPStaticSubrange` | `true` | Beta | 1.25 | |
| `ServiceInternalTrafficPolicy` | `false` | Alpha | 1.21 | 1.21 |
| `ServiceInternalTrafficPolicy` | `true` | Beta | 1.22 | |
| `SizeMemoryBackedVolumes` | `false` | Alpha | 1.20 | 1.21 |
| `SizeMemoryBackedVolumes` | `true` | Beta | 1.22 | |
| `StatefulSetAutoDeletePVC` | `false` | Alpha | 1.22 | |
| `StorageVersionAPI` | `false` | Alpha | 1.20 | |
| `StorageVersionHash` | `false` | Alpha | 1.14 | 1.14 |
| `StorageVersionHash` | `true` | Beta | 1.15 | |
| `StreamingProxyRedirects` | `false` | Beta | 1.5 | 1.5 |
| `StreamingProxyRedirects` | `true` | Beta | 1.6 | |
| `SupportNodePidsLimit` | `false` | Alpha | 1.14 | 1.14 |
| `SupportNodePidsLimit` | `true` | Beta | 1.15 | |
| `SupportPodPidsLimit` | `false` | Alpha | 1.10 | 1.13 |
| `SupportPodPidsLimit` | `true` | Beta | 1.14 | |
| `Sysctls` | `true` | Beta | 1.11 | |
| `TokenRequest` | `false` | Alpha | 1.10 | 1.11 |
| `TokenRequest` | `true` | Beta | 1.12 | |
| `TokenRequestProjection` | `false` | Alpha | 1.11 | 1.11 |
| `TokenRequestProjection` | `true` | Beta | 1.12 | |
| `TTLAfterFinished` | `false` | Alpha | 1.12 | 1.20 |
| `TTLAfterFinished` | `true` | Beta | 1.21 | |
| `TopologyAwareHints` | `false` | Alpha | 1.21 | 1.22 |
| `TopologyAwareHints` | `false` | Beta | 1.23 | 1.23 |
| `TopologyAwareHints` | `true` | Beta | 1.24 | |
| `TopologyManager` | `false` | Alpha | 1.16 | 1.17 |
| `TopologyManager` | `true` | Beta | 1.18 | |
| `ValidateProxyRedirects` | `false` | Alpha | 1.12 | 1.13 |
| `ValidateProxyRedirects` | `true` | Beta | 1.14 | |
| `VolumePVCDataSource` | `false` | Alpha | 1.15 | 1.15 |
| `VolumePVCDataSource` | `true` | Beta | 1.16 | |
| `VolumeSnapshotDataSource` | `false` | Alpha | 1.12 | 1.16 |
| `VolumeSnapshotDataSource` | `true` | Beta | 1.17 | - |
| `WindowsGMSA` | `false` | Alpha | 1.14 | |
| `WindowsGMSA` | `true` | Beta | 1.16 | |
| `UserNamespacesStatelessPodsSupport` | `false` | Alpha | 1.25 | |
| `VolumeCapacityPriority` | `false` | Alpha | 1.21 | - |
| `WinDSR` | `false` | Alpha | 1.14 | |
| `WinOverlay` | `false` | Alpha | 1.14 | |
| `WinOverlay` | `false` | Alpha | 1.14 | 1.19 |
| `WinOverlay` | `true` | Beta | 1.20 | |
| `WindowsHostProcessContainers` | `false` | Alpha | 1.22 | 1.22 |
| `WindowsHostProcessContainers` | `true` | Beta | 1.23 | |
{{< /table >}}
### GraduatedまたはDeprecatedのフィーチャーゲート {#feature-gates-for-graduated-or-deprecated-features}

View File

@ -11,7 +11,7 @@ Kubernetesには、Kubernetesシステムの操作に役立ついくつかの組
[`kubectl`](/ja/docs/tasks/tools/install-kubectl/)は、Kubernetesのためのコマンドラインツールです。このコマンドはKubernetes cluster managerを操作します。
## Kubeadm
[`kubeadm`](docs/setup/production-environment/tools/kubeadm/install-kubeadm/)は、物理サーバやクラウドサーバ、仮想マシン上にKubernetesクラスタを容易にプロビジョニングするためのコマンドラインツールです(現在はアルファ版です)。
[`kubeadm`](/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)は、物理サーバやクラウドサーバ、仮想マシン上にKubernetesクラスタを容易にプロビジョニングするためのコマンドラインツールです(現在はアルファ版です)。
## Minikube
[`minikube`](https://minikube.sigs.k8s.io/docs/)は、開発やテストのためにワークステーション上でシングルードのKubernetesクラスタをローカルで実行するツールです。

View File

@ -1,44 +0,0 @@
---
title: Serviceトポロジーを有効にする
content_type: task
---
<!-- overview -->
このページでは、Kubernetes上でServiceトポロジーを有効にする方法の概要について説明します。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
<!-- steps -->
## はじめに
*Serviceトポロジー*は、クラスターのードのトポロジーに基づいてトラフィックをルーティングできるようにする機能です。たとえば、あるServiceのトラフィックに対して、できるだけ同じードや同じアベイラビリティゾーン上にあるエンドポイントを優先してルーティングするように指定できます。
## 前提
トポロジーを考慮したServiceのルーティングを有効にするには、以下の前提を満たしている必要があります。
* Kubernetesバージョン1.17以降である
* {{< glossary_tooltip text="Kube-proxy" term_id="kube-proxy" >}}がiptableモードまたはIPVSモードで稼働している
* [Endpoint Slice](/docs/concepts/services-networking/endpoint-slices/)を有効にしている
## Serviceトポロジーを有効にする
{{< feature-state for_k8s_version="v1.17" state="alpha" >}}
Serviceトポロジーを有効にするには、すべてのKubernetesコンポーネントで`ServiceTopology`と`EndpointSlice`フィーチャーゲートを有効にする必要があります。
```
--feature-gates="ServiceTopology=true,EndpointSlice=true"
```
## {{% heading "whatsnext" %}}
* [Serviceトポロジー](/ja/docs/concepts/services-networking/service-topology)のコンセプトについて読む
* [Endpoint Slice](/docs/concepts/services-networking/endpoint-slices)について読む
* [サービスとアプリケーションの接続](/ja/docs/concepts/services-networking/connect-applications-service/)を読む

View File

@ -8,7 +8,7 @@ sitemap:
{{< blocks/section id="oceanNodes" >}}
{{% blocks/feature image="flower" %}}
K8s라고도 알려진 [쿠버네티스]({{< relref "/docs/concepts/overview/what-is-kubernetes" >}})는 컨테이너화된 애플리케이션을 자동으로 배포, 스케일링 및 관리해주는 오픈소스 시스템입니다.
K8s라고도 알려진 [쿠버네티스]({{< relref "/docs/concepts/overview/" >}})는 컨테이너화된 애플리케이션을 자동으로 배포, 스케일링 및 관리해주는 오픈소스 시스템입니다.
애플리케이션을 구성하는 컨테이너들의 쉬운 관리 및 발견을 위해서 컨테이너들을 논리적인 단위로 그룹화합니다. 쿠버네티스는 [Google에서 15년간 프로덕션 워크로드 운영한 경험](https://queue.acm.org/detail.cfm?id=2898444)을 토대로 구축되었으며, 커뮤니티에서 제공한 최상의 아이디어와 방법들이 결합되어 있습니다.
{{% /blocks/feature %}}

View File

@ -0,0 +1,173 @@
---
layout: blog
title: '쿠버네티스에서 어려움 없이 gRPC 로드밸런싱하기'
date: 2018-11-07
---
**저자**: William Morgan (Buoyant)
**번역**: 송원석 (쏘카), 김상홍 (국민대), 손석호 (ETRI)
다수의 새로운 gRPC 사용자는 쿠버네티스의 기본 로드
밸런싱이 종종 작동하지 않는 것에 놀란다. 예를 들어, 만약
[단순한 gRPC Node.js 마이크로서비스
앱](https://github.com/sourishkrout/nodevoto)을 만들고 쿠버네티스에 배포하면 어떤 일이 생기는지 살펴보자.
![](/images/blog/grpc-load-balancing-with-linkerd/Screenshot2018-11-0116-c4d86100-afc1-4a08-a01c-16da391756dd.34.36.png)
여기 표시된 `voting` 서비스는 여러 개의 파드로 구성되어 있지만, 쿠버네티스의 CPU 그래프는 명확하게
파드 중 하나만 실제 작업을 수행하고 있는 것(하나의 파드만 트래픽을 수신하고 있으므로)을
보여준다. 왜 그런 것일까?
이 블로그 게시물에서는, 이런 일이 발생하는 이유를 설명하고,
[CNCF](https://cncf.io)의 서비스 메시(mesh)인 [Linkerd](https://linkerd.io) 및 서비스 사이드카(sidecar)를 활용한
gRPC 로드밸런싱을 쿠버네티스 앱에 추가하여, 이 문제를 쉽게 해결할 수 있는 방법을 설명한다.
# 왜 gRPC에 특별한 로드밸런싱이 필요한가?
먼저, 왜 gRPC를 위해 특별한 작업이 필요한지 살펴보자.
gRPC는 애플리케이션 개발자에게 점점 더 일반적인 선택지가 되고 있다.
JSON-over-HTTP와 같은 대체 프로토콜에 비해, gRPC는
극적으로 낮은 (역)직렬화 비용과, 자동 타입
체크, 공식화된 APIs, 적은 TCP 관리 오버헤드 등에 상당한 이점이 있다.
그러나, gRPC는 쿠버네티스에서 제공하는 것과 마찬가지로
표준(일반)적으로 사용되는 연결 수준 로드밸런싱(connection-level load balancing)을 어렵게 만드는 측면도 있다. gRPC는 HTTP/2로
구축되었고, HTTP/2는 하나의 오래 지속되는 TCP 연결을 갖도록 설계되있기 때문에,
모든 요청은 *다중화(multiplexed)*(특정 시점에 다수의 요청이
하나의 연결에서만 동작하는 것을 의미)된다. 일반적으로, 그것은
연결 관리 오버헤드를 줄이는 장점이 있다. 그러나, 그것은 또한
(상상할 수 있듯이) 연결 수준의 밸런싱(balancing)에는 유용하지 않다는 것을 의미한다. 일단
연결이 설정되면, 더 이상 밸런싱을 수행할 수 없기 때문이다. 모든 요청이
아래와 같이 단일 파드에 고정될 것이다.
![](/images/blog/grpc-load-balancing-with-linkerd/Mono-8d2e53ef-b133-4aa0-9551-7e36a880c553.png)
# 왜 HTTP/1.1에는 이러한 일이 발생하지 않는가?
HTTP/1.1 또한 수명이 긴 연결의 개념이 있지만,
HTTP/1.1에는 TCP 연결을 순환시키게 만드는 여러 특징들이 있기 때문에,
이러한 문제가 발생하지 않는다. 그래서,
연결 수준 밸런싱은 "충분히 양호"하며, 대부분의 HTTP/1.1 앱에 대해서는
더 이상 아무것도 할 필요가 없다.
그 이유를 이해하기 위해, HTTP/1.1을 자세히 살펴보자. HTTP/2와 달리
HTTP/1.1은 요청을 다중화할 수 없다. TCP 연결 시점에 하나의 HTTP 요청만
활성화될 수 있다. 예를 들어 클라이언트가 'GET /foo'를 요청하고,
서버가 응답할 때까지 대기한다. 요청-응답 주기가
발생하면, 해당 연결에서 다른 요청을 실행할 수 없다.
일반적으로, 우리는 병렬로 많은 요청이 발생하기 원한다. 그러므로,
HTTP/1.1 동시 요청을 위해, 여러 HTTP/1.1 연결을 만들어야 하고,
그 모두에 걸쳐 우리의 요청을 발행해야 한다. 또한, 수명이 긴 HTTP/1.1
연결은 일반적으로 일정 시간 후 만료되고 클라이언트(또는 서버)에 의해 끊어진다.
이 두 가지 요소를 결합하면 일반적으로 HTTP/1.1 요청이
여러 TCP 연결에서 순환하며, 연결 수준 밸런싱이 작동한다.
# 그래서 우리는 어떻게 gRPC의 부하를 분산할 수 있을까??
이제 gRPC로 돌아가보자. 연결 수준에서 밸런싱을 맞출 수 없기 때문에, gRPC 로드 밸런싱을
수행하려면, 연결 밸런싱에서 *요청* 밸런싱으로 전환해야
한다. 즉, 각각에 대한 HTTP/2 연결을 열어야
하고, 아래와 같이, 이러한 연결들로 *요청*의 밸런싱을 맞춘다.
![](/images/blog/grpc-load-balancing-with-linkerd/Stereo-09aff9d7-1c98-4a0a-9184-9998ed83a531.png)
네트워크 측면에서, L3/L4에서 결정을 내리기 보다는 L5/L7에서 결정을
내려야 한다. 즉, TCP 연결을 통해 전송된 프로토콜을 이해해야 한다.
우리는 이것을 어떻게 달성해야할까? 몇 가지 옵션이 있다. 먼저, 우리의 애플리케이션
코드는 대상에 대한 자체 로드 밸런싱 풀을 수동으로 유지 관리할 수 있고,
gRPC 클라이언트에 [로드 밸런싱 풀을
사용](https://godoc.org/google.golang.org/grpc/balancer)하도록 구성할 수 있다. 이 접근 방식은
우리에게 높은 제어력을 제공하지만, 시간이 지남에 따라 파드가 리스케줄링(reschedule)되면서 풀이 변경되는
쿠버네티스와 같은 환경에서는 매우 복잡할 수 있다. 이 경우, 우리의
애플리케이션은 파드와 쿠버네티스 API를 관찰하고 자체적으로 최신 상태를
유지해야 한다.
대안으로, 쿠버네티스에서 앱을 [헤드리스(headless)
서비스](/ko/docs/concepts/services-networking/service/#헤드리스-headless-서비스)로 배포할 수 있다.
이 경우, 쿠버네티스는 서비스를 위한 DNS 항목에
[다중 A 레코드를 생성할 것이다](/ko/docs/concepts/services-networking/service/#헤드리스-headless-서비스).
만약 충분히 진보한 gRPC 클라이언트를 사용한다면,
해당 DNS 항목에서 로드 밸런싱 풀을 자동으로 유지 관리할 수 있다.
그러나 이 접근 방식은 우리를 특정 gRPC 클라이언트로를 사용하도록 제한할 뿐만 아니라,
헤드리스 서비스만 사용하는 경우도 거의 없으므로 제약이 크다.
마지막으로, 세 번째 접근 방식을 취할 수 있다. 경량 프록시를 사용하는 것이다.
# Linkerd를 사용하여 쿠버네티스에서 gRPC 로드 밸런싱
[Linkerd](https://linkerd.io)는 [CNCF](https://cncf.io)에서 관리하는 쿠버네티스용
*서비스 메시*이다. 우리의 목적과 가장 관련이 깊은 Linkerd는, 클러스터 수준의 권한
없이도 단일 서비스에 적용할 수 있는
*서비스 사이드카*로써도 작동한다. Linkerd를 서비스에 추가하는
것은, ​​각 파드에 작고, 초고속인 프록시를 추가하는 것을 의미하며, 이러한 프록시가
쿠버네티스 API를 와치(watch)하고 gRPC 로드 밸런싱을 자동으로 수행하는 것을 의미이다. 우리가 수행한 배포는
다음과 같다.
![](/images/blog/grpc-load-balancing-with-linkerd/Linkerd-8df1031c-cdd1-4164-8e91-00f2d941e93f.io.png)
Linkerd를 사용하면 몇 가지 장점이 있다. 첫째, 어떠한 언어로 작성된 서비스든지, 어떤 gRPC 클라이언트든지
그리고 어떠한 배포 모델과도 (헤드리스 여부와 상관없이) 함께 작동한다.
Linkerd의 프록시는 완전히 투명하기 때문에, HTTP/2와 HTTP/1.x를 자동으로 감지하고
L7 로드 밸런싱을 수행하며, 다른 모든 트래픽을
순수한 TCP로 통과(pass through)시킨다. 이것은 모든 것이 *그냥 작동*한다는 것을 의미한다.
둘째, Linkerd의 로드 밸런싱은 매우 정교하다. Linkerd는
쿠버네티스 API에 대한 와치(watch)를 유지하고 파드가 리스케술링 될 때
로드 밸런싱 풀을 자동으로 갱신할 뿐만 아니라, Linkerd는 응답 대기 시간이 가장 빠른 파드에
요청을 자동으로 보내기 위해 *지수 가중 이동 평균(exponentially-weighted moving average)*
사용한다. 하나의 파드가 잠시라도 느려지면, Linkerd가 트래픽을
변경할 것이다. 이를 통해 종단 간 지연 시간을 줄일 수 있다.
마지막으로, Linkerd의 Rust 기반 프록시는 매우 작고 빠르다. 그것은 1ms 미만의
p99 지연 시간(<1ms of p99 latency) 지원할 뿐만 아니라, 파드당 10mb 미만의 RSS(<10mb of RSS) 필요로 하므로
시스템 성능에도 거의 영향을 미치지 않는다.
# 60초 안에 gRPC 부하 분산
Linkerd는 시도하기가 매우 쉽다. 단지 &mdash;랩탑에 CLI를 설치하고&mdash; [Linkerd 시작
지침](https://linkerd.io/2/getting-started/)의 단계만 따르면 된다.
클러스터에 컨트롤 플레인과 "메시"
서비스(프록시를 각 파드에 주입)를 설치한다. 서비스에 Linkerd가 즉시
실행될 것이므로 적절한 gRPC 밸런싱을 즉시 확인할 수 있다.
Linkerd 설치 후에, 예시 `voting` 서비스를
다시 살펴보자.
![](/images/blog/grpc-load-balancing-with-linkerd/Screenshot2018-11-0116-24b8ee81-144c-4eac-b73d-871bbf0ea22e.57.42.png)
그림과 같이, 모든 파드에 대한 CPU 그래프가 활성화되어 모든 파드가
&mdash;코드를 변경하지 않았지만&mdash; 트래픽을 받고 있다. 짜잔,
마법처럼 gRPC 로드 밸런싱이 됐다!
Linkerd는 또한 내장된 트래픽 수준 대시보드를 제공하므로, 더 이상
CPU 차트에서 무슨 일이 일어나고 있는지 추측하는 것이 필요하지 않다. 다음은 각 파드의
성공률, 요청 볼륨 및 지연 시간 백분위수를 보여주는
Linkerd 그래프이다.
![](/images/blog/grpc-load-balancing-with-linkerd/Screenshot2018-11-0212-15ed0448-5424-4e47-9828-20032de868b5.08.38.png)
각 파드가 약 5 RPS를 얻고 있음을 알 수 있다. 또한,
로드 밸런싱 문제는 해결되었지만 해당 서비스의
성공률에 대해서는 아직 할 일이 남았다는 것도 살펴볼 수 있다. (데모 앱은 독자에 대한 연습을 위해 의도적으로
실패 상태로 만들었다. Linkerd 대시보드를 사용하여
문제를 해결할 수 있는지 살펴보자!)
# 마지막으로
쿠버네티스 서비스에 gRPC 로드 밸런싱을 추가하는 방법에
흥미가 있다면, 어떤 언어로 작성되었든 상관없이, 어떤 gRPC
클라이언트를 사용중이든지, 또는 어떻게 배포되었든지, Linkerd를 사용하여 단 몇 개의 명령으로
gRPC 로드 밸런싱을 추가할 수 있다.
보안, 안정성 및 디버깅을 포함하여 Linkerd에는 더 많은 특징
및 진단 기능이 있지만 이는 향후 블로그 게시물의 주제로 남겨두려 한다.
더 알고 싶은가? 빠르게 성장하고 있는 우리 커뮤니티는 여러분의 참여를 환영한다!
Linkerd는 [CNCF](https://cncf.io) 프로젝트로
[GitHub에 호스팅 되어 있고](https://github.com/linkerd/linkerd2), [Slack](https://slack.linkerd.io),
[Twitter](https://twitter.com/linkerd), 그리고 [이메일 리스트](https://lists.cncf.io/g/cncf-linkerd-users)를 통해 커뮤니티를 만날 수 있다.
접속하여 커뮤니티에 참여하는 즐거움을 느껴보길 바란다!

View File

@ -6,7 +6,7 @@ slug: dont-panic-kubernetes-and-docker
evergreen: true
---
**업데이트:** _쿠버네티스의 `dockershim`을 통한 도커 지원이 제거되었습니다.
**업데이트:** _쿠버네티스의 도커심을 통한 도커 지원이 제거되었습니다.
더 자세한 정보는 [제거와 관련된 자주 묻는 질문](/dockershim/)을 참고하세요.
또는 지원 중단에 대한 [GitHub 이슈](https://github.com/kubernetes/kubernetes/issues/106917)에서 논의를 할 수도 있습니다._

View File

@ -1,6 +1,6 @@
<!-- Do not edit this file directly. Get the latest from
https://github.com/cncf/foundation/blob/main/code-of-conduct.md -->
## CNCF 커뮤니티 행동 강령 v1.1
## CNCF 커뮤니티 행동 강령 v1.2
### 기여자 행동 강령
@ -9,58 +9,63 @@ CNCF 커뮤니티의 기여자 및 메인테이너(maintainer)로서 개방적
풀 리퀘스트(pull request) 또는 패치 제출, 그리고 기타 다른 활동으로 기여하는
모든 분들을 존중할 것을 약속합니다.
우리는 경험의 수준, 성별, 성 정체성 및 표현(gender identity and expression),
성적 지향, 장애, 외양, 신체 크기, 인종, 민족, 나이, 종교,
우리는 경험의 수준, 성별, 성 정체성 및 표현(gender identity and expression), 성적 지향, 장애, 외양, 신체 크기, 인종, 민족, 나이, 종교,
또는 국적에 상관 없이 모두가 차별 없는 환경에서 CNCF 커뮤니티에
참여할 수 있도록 최선을 다하고 있습니다.
## 범위
본 행동 강령은 프로젝트 활동 영역 내에서뿐만 아니라 개인이 프로젝트 또는 커뮤니티를 대변하는 공공의 활동 영역에서도 적용됩니다.
## CNCF 이벤트
CNCF 이벤트, 혹은 리눅스 재단에서 이벤트 전문 직원과 운영하는 이벤트는 이벤트 페이지에 명시된 Linux Foundation [이벤트 행동 강령](https://events.linuxfoundation.org/code-of-conduct)에 의거하여 운영됩니다. 해당 행동 강령은 CNCF의 행동 강령과 함께 사용하도록 고안되었습니다.
## 우리의 원칙
긍정적인 환경을 조성하는 행위는 다음과 같습니다.
* 타인에게 친절과 공감 실천
* 타인의 의견, 관점, 그리고 경험에 대한 포용
* 건설적 피드백에 대한 수용
* 실수에 대한 책임과 사과, 그리고 경험을 통한 배움
* 개인의 최선이 아닌 커뮤니티 전반의 선을 위한 노력
* 실수에 대한 책임과 사과,
그리고 경험을 통한 배움
* 개인의 최선이 아닌 커뮤니티 전반의
선을 위한 노력
참여자에게 금지하는 행위의 예시는 다음과 같습니다.
* 성적인 언어 또는 이미지 사용, 혹은 그 외 성적으로 부적절한 행동
* 성적인 언어 또는 이미지 사용, 혹은
그 외 성적으로 부적절한 행동
* 선동적, 모욕적, 경멸적 언사, 그리고 개인적 혹은 정치적 공격
* 공개적이거나 사적인 괴롭힘
* 타인의 주소 및 전자주소와 같은 개인 정보의 동의 없는 공개
* 타인의 주소 및 전자주소와 같은
개인 정보의 동의 없는 공개
* 기타 비윤리적이거나 비전문적인 행동
프로젝트 메인테이너에게는 본 행동 강령을 위반하는 코멘트, 커밋(commit),
코드, 위키(wiki) 수정, 이슈, 그리고 그 밖의 기여에 대해서 삭제, 수정,
프로젝트 메인테이너에게는 본 행동 강령을 위반하는 코멘트, 커밋(commit), 코드, 위키(wiki) 수정, 이슈, 그리고 그 밖의 기여에 대해서 삭제, 수정,
거부할 수 있는 권한과 책임이 있습니다. 프로젝트 메인테이너는 프로젝트 관리의
모든 관점에서 이러한 행동 강령 원칙을 공정하고 일관되게 적용할 것을 약속해야 합니다.
행동 강령을 준수하지 않거나 시행하지 않는 프로젝트 메인테이너는 프로젝트 팀에서
영구적으로 제적될 수 있습니다.
## 신고
쿠버네티스 커뮤니티에서 발생하는 사건들은 [쿠버네티스 행동 강령 위원회](https://git.k8s.io/community/committee-code-of-conduct)에 이메일 <conduct@kubernetes.io>를 통해 신고할 수 있습니다. 신고시 3일 내 회신을 받을 수 있습니다.
기타 다른 프로젝트에 관해서는 CNCF 직원에게 이메일 <conduct@cncf.io>으로 문의하십시오.
쿠버네티스 커뮤니티에서 발생하는 사건들은 [쿠버네티스 행동 강령 위원회](https://git.k8s.io/community/committee-code-of-conduct)에 이메일 <conduct@kubernetes.io>를 통해 신고할 수 있습니다. 영업일 기준 3일 이내에 답변을 받으실 수 있습니다.
CNCF는 외부 중재자로 Mishi Choudhary <mishi@linux.com>를 두고 있습니다. 외부 중재자는 CNCF 직원의 안내에 따라 의뢰 가능합니다. 보통의 경우 <conduct@cncf.io>로 직접 연락하는 것을 추천합니다.
쿠버네티스(Kubernetes)에서의 폭력, 학대 또는 기타 허용되지 않는 행위는 [쿠버네티스 행동 강령 위원회](https://git.k8s.io/community/committee-code-of-conduct)에 이메일 <conduct@kubernetes.io>를 통해 신고할 수 있습니다. 다른 프로젝트의 경우는 CNCF 프로젝트 메인테이너 또는 중재자인 Mishi Choudhary의 이메일 <mishi@linux.com>으로 문의하십시오.
기타 다른 프로젝트, 프로젝트에 무관하거나, 여러 CNCF 프로젝트에 영향을 주는 사건들은 [CNCF 행동 강령 위원회](https://www.cncf.io/conduct/committee/)에 이메일 <conduct@cncf.io>를 통해 신고할 수 있습니다. 또는 [CNCF 행동 강령 위원회](https://www.cncf.io/conduct/committee/)의 각 구성원에게 연락하여 보고서를 제출할 수 있습니다. 익명으로 보고서를 제출하는 방법을 포함하여 보고서 제출 방법에 대한 자세한 내용은 [사건 해결 절차](https://www.cncf.io/conduct/procedures/)를 참조하십시오. 영업일 기준 3일 이내에 답변을 받으실 수 있습니다.
## 집행
쿠버네티 프로젝트의 [행동 강령 위원회](https://github.com/kubernetes/community/tree/master/committee-code-of-conduct)가 행동 강령 발행을 시행합니다. 기타 프로젝트에 관하여는 CNCF가 행동강력 발행을 시행합니다.
쿠버네티 프로젝트의 [행동 강령 위원회](https://github.com/kubernetes/community/tree/master/committee-code-of-conduct)가 쿠버네티스 프로젝트에 대하여 행동 강령 이슈에 대한 집행을 수행합니다.
자체 행동 강령 위원회 또는 행동 강령 사고 대응자가 없는 모든 프로젝트와, 프로젝트에 해당하지 않거나(project-agnostic) 여러 프로젝트에 영향을 미치는 사건에 대해서는 [CNCF 행동 강령 위원회](https://www.cncf.io/conduct/committee/)가 행동 강령 이슈에 대한 집행을 수행합니다. 자세한 내용은 [관할(jurisdiction) 및 에스컬레이션(escalation) 정책](https://www.cncf.io/conduct/jurisdiction/)을 참조하십시오.
양 기관은 처벌 없는 문제 해결을 추구합니다. 하지만 CNCF의 재량에 따라 회원 혹은 프로젝트를 퇴출시킬 수 있습니다.
### 확인
본 행동 강령은 기여자 서약(https://contributor-covenant.org)에서
본 행동 강령은 기여자 서약(http://contributor-covenant.org)에서
제공하는 버전 2.0을 적용하였으며, 해당 내용은
https://contributor-covenant.org/version/2/0/code_of_conduct/ 에서 확인할 수 있습니다.
http://contributor-covenant.org/version/2/0/code_of_conduct/ 에서 확인할 수 있습니다.

View File

@ -8,7 +8,6 @@ weight: 50
{{<glossary_definition term_id="garbage-collection" length="short">}}
다음과 같은 리소스를 정리한다:
* [실패한 파드](/ko/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection)
* [종료된 잡](/ko/docs/concepts/workloads/controllers/ttlafterfinished/)
* [소유자 참조가 없는 오브젝트](#owners-dependents)
* [사용되지 않는 컨테이너와 컨테이너 이미지](#containers-images)

View File

@ -194,9 +194,9 @@ kubectl describe node <insert-node-name-here>
{{< /table >}}
{{< note >}}
커맨드 라인 도구를 사용해서 코드화된 노드의 세부 정보를 출력하는 경우 조건에는
커맨드 라인 도구를 사용해서 통제된(cordoned) 노드의 세부 정보를 출력하는 경우 조건에는
`SchedulingDisabled` 이 포함된다. `SchedulingDisabled` 은 쿠버네티스 API의 조건이 아니며,
대신 코드화된 노드는 사양에 스케줄 불가로 표시된다.
대신 통제된(cordoned) 노드는 사양에 스케줄 불가로 표시된다.
{{< /note >}}
쿠버네티스 API에서, 노드의 컨디션은 노드 리소스의 `.status` 부분에
@ -476,9 +476,8 @@ kubelet의 노드 셧다운 관리자(Node Shutdown Mananger)가
기존의 셧다운된 노드가 정상으로 돌아오지 못하면,
이러한 파드는 셧다운된 노드에 '종료 중(terminating)' 상태로 영원히 고착될 것이다.
위와 같은 상황을 완화하기 위해, 사용자가 `node.kubernetes.io/out-of-service` 테인트를
`NoExecute` 또는 `NoSchedule` 값으로 추가하여
노드를 서비스 불가(out-of-service) 상태로 표시할 수 있다.
위와 같은 상황을 완화하기 위해, 사용자가 `node.kubernetes.io/out-of-service` 테인트를 `NoExecute` 또는 `NoSchedule` 값으로
추가하여 노드를 서비스 불가(out-of-service) 상태로 표시할 수 있다.
`kube-controller-manager``NodeOutOfServiceVolumeDetach`[기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)
가 활성화되어 있고, 노드가 이 테인트에 의해 서비스 불가 상태로 표시되어 있는 경우,
노드에 매치되는 톨러레이션이 없다면 노드 상의 파드는 강제로 삭제될 것이고,

View File

@ -74,7 +74,7 @@ no_list: true
관리자가 `sysctl` 커맨드라인 도구를 사용하여 커널 파라미터를 설정하는 방법에 대해 설명한다
.
* [감사(audit)](/docs/tasks/debug/debug-cluster/audit/)는
* [감사(audit)](/ko/docs/tasks/debug/debug-cluster/audit/)는
쿠버네티스의 감사 로그를 다루는 방법에 대해 설명한다.
### kubelet 보안

View File

@ -9,7 +9,7 @@ content_type: concept
애드온은 쿠버네티스의 기능을 확장한다.
이 페이지는 사용 가능한 일부 애드온과 관련 설치 지침 링크를 나열한다.
이 페이지는 사용 가능한 일부 애드온과 관련 설치 지침 링크를 나열한다. 이 목차에서 전체를 다루지는 않는다.
<!-- body -->
@ -19,7 +19,7 @@ content_type: concept
* [Antrea](https://antrea.io/)는 레이어 3/4에서 작동하여 쿠버네티스를 위한 네트워킹 및 보안 서비스를 제공하며, Open vSwitch를 네트워킹 데이터 플레인으로 활용한다.
* [Calico](https://docs.projectcalico.org/latest/introduction/)는 네트워킹 및 네트워크 폴리시 제공자이다. Calico는 유연한 네트워킹 옵션을 지원하므로 BGP 유무에 관계없이 비-오버레이 및 오버레이 네트워크를 포함하여 가장 상황에 맞는 옵션을 선택할 수 있다. Calico는 동일한 엔진을 사용하여 서비스 메시 계층(service mesh layer)에서 호스트, 파드 및 (이스티오(istio)와 Envoy를 사용하는 경우) 애플리케이션에 대한 네트워크 폴리시를 적용한다.
* [Canal](https://projectcalico.docs.tigera.io/getting-started/kubernetes/flannel/flannel)은 Flannel과 Calico를 통합하여 네트워킹 및 네트워크 폴리시를 제공한다.
* [Cilium](https://github.com/cilium/cilium)은 L3 네트워크 및 네트워크 폴리시 플러그인으로 HTTP/API/L7 폴리시를 투명하게 시행할 수 있다. 라우팅 및 오버레이/캡슐화 모드를 모두 지원하며, 다른 CNI 플러그인 위에서 작동할 수 있다.
* [Cilium](https://github.com/cilium/cilium)은 네트워킹, 관측 용의성(Observability), 보안 특징을 지닌 eBPF 기반 데이터 플레인을 갖춘 솔루션입니다. Cilium은 기본 라우팅 및 오버레이/캡슐화 모드를 모두 지원하며, 여러 클러스터를 포괄할 수 있는 단순한 플랫(flat) Layer 3 네트워크를 제공합니다. 또한, Cilium은 (네트워크 주소 지정 방식에서 분리된) 신원 기반 보안 모델(identity-based security model)을 사용하여 L3-L7에서 네트워크 정책을 시행할 수 있습니다. Cilium은 kube-proxy를 대체하는 역할을 할 수 있습니다. 또한 부가적으로, 옵트인(opt-in) 형태로 관측 용의성(Observability) 및 보안 기능을 제공합니다.
* [CNI-Genie](https://github.com/cni-genie/CNI-Genie)를 사용하면 쿠버네티스는 Calico, Canal, Flannel, Romana 또는 Weave와 같은 CNI 플러그인을 완벽하게 연결할 수 있다.
* [Contiv](https://contivpp.io/)는 다양한 유스케이스와 풍부한 폴리시 프레임워크를 위해 구성 가능한 네트워킹(BGP를 사용하는 네이티브 L3, vxlan을 사용하는 오버레이, 클래식 L2 그리고 Cisco-SDN/ACI)을 제공한다. Contiv 프로젝트는 완전히 [오픈소스](https://github.com/contiv)이다. [인스톨러](https://github.com/contiv/install)는 kubeadm을 이용하거나, 그렇지 않은 경우에 대해서도 설치 옵션을 모두 제공한다.
* [Contrail](https://www.juniper.net/us/en/products-services/sdn/contrail/contrail-networking/)은 [Tungsten Fabric](https://tungsten.io)을 기반으로 하며, 오픈소스이고, 멀티 클라우드 네트워크 가상화 및 폴리시 관리 플랫폼이다. Contrail과 Tungsten Fabric은 쿠버네티스, OpenShift, OpenStack 및 Mesos와 같은 오케스트레이션 시스템과 통합되어 있으며, 가상 머신, 컨테이너/파드 및 베어 메탈 워크로드에 대한 격리 모드를 제공한다.
@ -27,7 +27,7 @@ content_type: concept
* [Knitter](https://github.com/ZTE/Knitter/)는 쿠버네티스 파드에서 여러 네트워크 인터페이스를 지원하는 플러그인이다.
* [Multus](https://github.com/k8snetworkplumbingwg/multus-cni)는 쿠버네티스의 다중 네트워크 지원을 위한 멀티 플러그인이며, 모든 CNI 플러그인(예: Calico, Cilium, Contiv, Flannel)과 쿠버네티스 상의 SRIOV, DPDK, OVS-DPDK 및 VPP 기반 워크로드를 지원한다.
* [OVN-Kubernetes](https://github.com/ovn-org/ovn-kubernetes/)는 Open vSwitch(OVS) 프로젝트에서 나온 가상 네트워킹 구현인 [OVN(Open Virtual Network)](https://github.com/ovn-org/ovn/)을 기반으로 하는 쿠버네티스용 네트워킹 제공자이다. OVN-Kubernetes는 OVS 기반 로드 밸런싱과 네트워크 폴리시 구현을 포함하여 쿠버네티스용 오버레이 기반 네트워킹 구현을 제공한다.
* [OVN4NFV-K8S-Plugin](https://github.com/opnfv/ovn4nfv-k8s-plugin)은 OVN 기반의 CNI 컨트롤러 플러그인으로 클라우드 네이티브 기반 서비스 기능 체인(Service function chaining(SFC)), 다중 OVN 오버레이 네트워킹, 동적 서브넷 생성, 동적 가상 네트워크 생성, VLAN 공급자 네트워크, 직접 공급자 네트워크와 멀티 클러스터 네트워킹의 엣지 기반 클라우드 등 네이티브 워크로드에 이상적인 멀티 네티워크 플러그인이다.
* [Nodus](https://github.com/akraino-edge-stack/icn-nodus)는 클라우드 네이티브 기반 서비스 기능 체인(SFC)을 제공하는 OVN 기반 CNI 컨트롤러 플러그인이다.
* [NSX-T](https://docs.vmware.com/en/VMware-NSX-T-Data-Center/index.html) 컨테이너 플러그인(NCP)은 VMware NSX-T와 쿠버네티스와 같은 컨테이너 오케스트레이터 간의 통합은 물론 NSX-T와 PKS(Pivotal 컨테이너 서비스) 및 OpenShift와 같은 컨테이너 기반 CaaS/PaaS 플랫폼 간의 통합을 제공한다.
* [Nuage](https://github.com/nuagenetworks/nuage-kubernetes/blob/v5.1.1-1/docs/kubernetes-1-installation.rst)는 가시성과 보안 모니터링 기능을 통해 쿠버네티스 파드와 비-쿠버네티스 환경 간에 폴리시 기반 네트워킹을 제공하는 SDN 플랫폼이다.
* [Romana](https://github.com/romana)는 [네트워크폴리시 API](/ko/docs/concepts/services-networking/network-policies/)도 지원하는 파드 네트워크용 Layer 3 네트워킹 솔루션이다.

View File

@ -34,170 +34,9 @@ weight: 50
## 쿠버네티스 네트워크 모델의 구현 방법
이 네트워크 모델을 구현할 수 있는 방법에는 여러 가지가 있다. 이
문서는 다양한 방법에 대한 철저한 연구는 아니지만, 다양한 기술에 대한
소개로 활용되며 도약하는 포인트로 사용되기를 바란다.
네트워크 모델은 각 노드의 컨테이너 런타임에 의해 구현된다. 가장 일반적인 컨테이너 런타임은 [컨테이너 네트워크 인터페이스](https://github.com/containernetworking/cni)(CNI) 플러그인을 사용하여 네트워크 및 보안 기능을 관리한다. 여러 공급 업체의 다양한 CNI 플러그인이 존재하며, 이들 중 일부는 네트워크 인터페이스를 추가 및 제거하는 기본 기능만 제공하는 반면, 다른 일부는 다른 컨테이너 오케스트레이션 시스템과의 통합, 여러 CNI 플러그인 실행, 고급 IPAM 기능 등과 같은 보다 정교한 솔루션을 제공한다.
이 목록은 알파벳 순으로 정렬되어 있으며, 정렬된 순서가
우선 상태를 의미하는 것은 아니다.
{{% thirdparty-content %}}
### ACI
[Cisco 애플리케이션 센트릭 인프라스트럭처(Application Centric Infrastructure)](https://www.cisco.com/c/en/us/solutions/data-center-virtualization/application-centric-infrastructure/index.html)는 컨테이너, 가상 머신 및 베어메탈 서버를 지원하는 통합 오버레이 및 언더레이 SDN 솔루션을 제공한다. [ACI](https://www.github.com/noironetworks/aci-containers)는 ACI를 위한 컨테이너 네트워킹 통합을 제공한다. 통합의 개요는 [여기](https://www.cisco.com/c/dam/en/us/solutions/collateral/data-center-virtualization/application-centric-infrastructure/solution-overview-c22-739493.pdf)에서 제공된다.
### Antrea
프로젝트 [Antrea](https://github.com/vmware-tanzu/antrea)는 쿠버네티스 고유의 오픈소스 쿠버네티스 네트워킹 솔루션이다. 네트워킹 데이터 플레인으로 Open vSwitch를 활용한다. Open vSwitch는 리눅스와 윈도우를 모두 지원하는 고성능의 프로그래밍이 가능한 가상 스위치이다. Antrea는 Open vSwitch를 통해 쿠버네티스 네트워크 정책을 고성능의 효율적인 방식으로 구현할 수 있다.
Antrea는 Open vSwitch의 "프로그래밍이 가능한" 특성으로 인해 Open vSwitch 위에 광범위한 네트워킹 및 보안 기능과 서비스를 구현할 수 있다.
### 쿠버네티스용 AWS VPC CNI
[AWS VPC CNI](https://github.com/aws/amazon-vpc-cni-k8s)는 쿠버네티스 클러스터를 위한 통합된 AWS 버추얼 프라이빗 클라우드(Virtual Private Cloud, VPC) 네트워킹을 제공한다. 이 CNI 플러그인은 높은 처리량과 가용성, 낮은 레이턴시(latency) 그리고 최소 네트워크 지터(jitter)를 제공한다. 또한, 사용자는 쿠버네티스 클러스터를 구축하기 위한 기존의 AWS VPC 네트워킹 및 보안 모범 사례를 적용할 수 있다. 여기에는 VPC 플로우 로그, VPC 라우팅 정책과 네트워크 트래픽 격리를 위한 보안 그룹을 사용하는 기능이 포함되어 있다.
이 CNI 플러그인을 사용하면 쿠버네티스 파드는 VPC 네트워크와 동일한 IP 주소를 파드 내부에 가질 수 있다. CNI는 각 쿠버네티스 노드에 AWS 엘라스틱 네트워킹 인터페이스(Elastic Networking Interfaces, ENI)를 할당하고 노드의 파드에 대해 각 ENI의 보조 IP 범위를 사용한다. CNI에는 파드를 빠르게 시작하기 위해 ENI와 IP 주소의 사전 할당 제어 기능이 포함되어 있으며 최대 2,000개의 노드로 구성된 대규모 클러스터가 가능하다.
또한, CNI는 [네트워크 폴리시 적용을 위해 캘리코(Calico)](https://docs.aws.amazon.com/eks/latest/userguide/calico.html)와 함께 실행할 수 있다. AWS VPC CNI 프로젝트는 [GitHub의 문서](https://github.com/aws/amazon-vpc-cni-k8s)와 함께 오픈소스로 공개되어 있다.
### 쿠버네티스용 Azure CNI
[Azure CNI](https://docs.microsoft.com/en-us/azure/virtual-network/container-networking-overview)는 VM과 동등한 네트워크 성능을 제공하는 Azure 버추얼 네트워크(VNet이라고도 알려진)와 쿠버네티스 파드를 통합하는 [오픈소스](https://github.com/Azure/azure-container-networking/blob/master/docs/cni.md) 플러그인이다. 파드는 피어링된 VNet과 Express Route 또는 사이트 간 VPN을 통해 온-프레미스에 연결할 수 있으며 이러한 네트워크에서 직접 연결할 수도 있다. 파드는 서비스 엔드포인트 또는 프라이빗 링크로 보호되는 스토리지와 SQL과 같은 Azure 서비스에 접근할 수 있다. VNet 보안 정책과 라우팅을 사용하여 파드 트래픽을 필터링할 수 있다. 플러그인은 쿠버네티스 노드의 네트워크 인터페이스에 사전 구성된 보조 IP 풀을 활용하여 VNet IP를 파드에 할당한다.
Azure CNI는 [Azure 쿠버네티스 서비스(Azure Kubernetes Service, AKS)](https://docs.microsoft.com/en-us/azure/aks/configure-azure-cni)에서 기본적으로 사용할 수 있다.
### 캘리코
[캘리코](https://projectcalico.docs.tigera.io/about/about-calico/)는 컨테이너, 가상 시스템 및 기본 호스트 기반 워크로드를 위한 오픈소스 네트워킹 및 네트워크 보안 솔루션이다. 캘리코는 순수 리눅스 eBPF 데이터플레인, 표준 리눅스 네트워킹 데이터플레인, 윈도우 HNS 데이터플레인을 포함한 여러 데이터플레인을 지원한다. 캘리코는 완전한 네트워킹 스택을 제공하지만, [클라우드 제공자 CNI](https://projectcalico.docs.tigera.io/networking/determine-best-networking#calico-compatible-cni-plugins-and-cloud-provider-integrations)와 함께 사용하여 네트워크 정책 시행을 제공할 수도 있다.
### 실리움(Cilium)
[실리움](https://github.com/cilium/cilium)은 애플리케이션 컨테이너 간에
네트워크 연결을 제공하고 투명하게 보호하기 위한 오픈소스 소프트웨어이다.
실리움은 L7/HTTP를 인식하며 네트워크 주소 지정에서 분리된 ID 기반 보안 모델을 사용하여 L3-L7에서
네트워크 정책을 적용할 수 있으며,
다른 CNI 플러그인과 함께 사용할 수 있다.
### 화웨이의 CNI-Genie
[CNI-Genie](https://github.com/cni-genie/CNI-Genie)는 쿠버네티스가 런타임 시 [쿠버네티스 네트워크 모델](/ko/docs/concepts/cluster-administration/networking/#쿠버네티스-네트워크-모델)의 [서로 다른 구현에 동시에 접근](https://github.com/cni-genie/CNI-Genie/blob/master/docs/multiple-cni-plugins/README.md#what-cni-genie-feature-1-multiple-cni-plugins-enables)할 수 있는 CNI 플러그인이다. 여기에는 [플라넬(Flannel)](https://github.com/flannel-io/flannel#flannel), [캘리코](https://projectcalico.docs.tigera.io/about/about-calico/), [위브넷(Weave-net)](https://www.weave.works/oss/net/)과 같은 [CNI 플러그인](https://github.com/containernetworking/cni#3rd-party-plugins)으로 실행되는 모든 구현이 포함된다.
CNI-Genie는 각각 다른 CNI 플러그인에서 [하나의 파드에 여러 IP 주소를 할당](https://github.com/cni-genie/CNI-Genie/blob/master/docs/multiple-ips/README.md#feature-2-extension-cni-genie-multiple-ip-addresses-per-pod)하는 것도 지원한다.
### cni-ipvlan-vpc-k8s
[cni-ipvlan-vpc-k8s](https://github.com/lyft/cni-ipvlan-vpc-k8s)는
L2 모드에서 리눅스 커널의 IPvlan 드라이버를 사용하여 Amazon 엘라스틱 네트워크 인터페이스(ENI)를
사용하고 AWS 매니지드 IP를 파드에 바인딩하는
Amazon 버추얼 프라이빗 클라우드(VPC) 환경 내에서 쿠버네티스를 위한
간단하고, 호스트 로컬, 낮은 레이턴시, 높은 처리량 및 호환 네트워킹 스택을 제공하는
CNI와 IPAM 플러그인 셋을 포함한다.
플러그인은 VPC 내에서 구성하고 배포할 수 있도록 간단하게 설계되었다.
Kubelets는 오버레이 네트워크 관리, BGP 관리, 소스/대상 확인 비활성화 또는
VPC 라우팅 테이블을 조정하여 각 호스트에 인스턴스별 서브넷을
제공(VPC별 50-100개 항목으로 제한)하는 등의 자주 권장되는 복잡성을 요구하지 않고
부팅한 다음 필요에 따라 IP 사용량을 자체 구성하고 확장할
수 있다. 즉, cni-ipvlan-vpc-k8s는 AWS 내에서 쿠버네티스를
대규모로 배포하는 데 필요한 네트워크 복잡성을 크게 줄인다.
### Coil
[Coil](https://github.com/cybozu-go/coil)은 통합이 용이하도록 설계된 CNI 플러그인으로 유연한 이그레스(egress) 네트워킹을 제공한다.
Coil은 베어메탈에 비해 낮은 오버헤드로 작동하며, 외부 네트워크에 대해 임의의 이그레스 NAT 게이트웨이를 정의할 수 있다.
### 콘티브-VPP(Contiv-VPP)
[Contiv-VPP](https://contivpp.io/)는 유저 스페이스에서 동작하고 성능을 중시하는 쿠버네티스 네트워크 플러그인이며,
데이터 플레인으로 [fd.io](https://fd.io/)를 사용한다.
### 콘트레일(Contrail) / 텅스텐 패브릭(Tungsten Fabric)
[텅스텐 패브릭](https://tungsten.io)을 기반으로 하는 [콘트레일](https://www.juniper.net/us/en/products-services/sdn/contrail/contrail-networking/)은 진정한 개방형 멀티 클라우드 네트워크 가상화 및 정책 관리 플랫폼이다. 콘트레일 및 텅스텐 패브릭은 쿠버네티스, OpenShift, OpenStack 및 Mesos와 같은 다양한 오케스트레이션 시스템과 통합되어 있으며, 가상 머신, 컨테이너/파드 및 베어메탈 워크로드에 대해 서로 다른 격리 모드를 제공한다.
### DANM
[DANM](https://github.com/nokia/danm)은 쿠버네티스 클러스터에서 실행되는 통신사 워크로드를 위한 네트워킹 솔루션이다. 다음의 컴포넌트로 구성된다.
* 고급 기능들로 IPVLAN 인터페이스를 프로비저닝할 수 있는 CNI 플러그인
* 여러 클러스터 전체의 불연속 L3 네트워크를 관리하고 요청 시 동적, 정적 또는 IP를 할당하지 않는 방식을 제공하는 내장 IPAM 모듈
* 자체 CNI를 통해서, 또는 SRI-OV나 플라넬과 같은 널리 사용되는 CNI 솔루션에 잡을 동시에 위임하여 여러 네트워크 인터페이스를 컨테이너에 연결할 수 있는 CNI 메타플러그인
* 모든 쿠버네티스 호스트의 VxLAN 및 VLAN 인터페이스를 중앙에서 관리할 수 있는 쿠버네티스 컨트롤러
* 쿠버네티스의 서비스 기반의 서비스 검색 개념을 확장하여 파드의 모든 네트워크 인터페이스에서 작동하는 다른 쿠버네티스 컨트롤러
이 도구 셋을 통해 DANM은 여러 개의 분리된 네트워크 인터페이스를 제공할 수 있으며, 파드에 다른 네트워킹 백엔드 및 고급 IPAM 기능을 사용할 수 있다.
### 플라넬
[플라넬](https://github.com/flannel-io/flannel#flannel)은 쿠버네티스 요구 사항을
충족하는 매우 간단한 오버레이 네트워크이다. 많은
경우에 쿠버네티스와 플라넬은 성공적으로 적용이 가능하다.
### Hybridnet
[Hybridnet](https://github.com/alibaba/hybridnet)은 하이브리드 클라우드를 위해 디자인된 오픈소스 CNI 플러그인이며 하나 또는 다수의 클러스터에 있는 컨테이너를 위한 오버레이 및 언더레이 네트워킹을 제공한다. 오버레이 및 언더레이 컨테이너는 동일한 노드에서 실행될 수 있으며 클러스터 범위의 양방향 네트워크 연결성을 가진다.
### 재규어(Jaguar)
[재규어](https://gitlab.com/sdnlab/jaguar)는 OpenDaylight 기반의 쿠버네티스 네트워크를 위한 오픈소스 솔루션이다. 재규어는 vxlan을 사용하여 오버레이 네트워크를 제공하고 재규어 CNI 플러그인은 파드별로 하나의 IP 주소를 제공한다.
### k-vswitch
[k-vswitch](https://github.com/k-vswitch/k-vswitch)는 [Open vSwitch](https://www.openvswitch.org/) 기반의 간단한 쿠버네티스 네트워킹 플러그인이다. Open vSwitch의 기존 기능을 활용하여 운영하기 쉽고, 성능이 뛰어나고 안전한 강력한 네트워킹 플러그인을 제공한다.
### Knitter
[Knitter](https://github.com/ZTE/Knitter/)는 쿠버네티스에서 여러 네트워킹을 지원하는 네트워크 솔루션이다. 테넌트 관리 및 네트워크 관리 기능을 제공한다. Knitter에는 애플리케이션의 IP 주소 유지, IP 주소 마이그레이션 등과 같은 여러 네트워크 플레인 외에 엔드-투-엔드 NFV 컨테이너 네트워킹 솔루션 셋이 포함되어 있다.
### Kube-OVN
[Kube-OVN](https://github.com/alauda/kube-ovn)은 기업을 위한 OVN 기반 쿠버네티스 네트워크 패브릭이다. OVN/OVS의 도움으로, 서브넷, QoS, 고정 IP 할당, 트래픽 미러링, 게이트웨이, 오픈플로우 기반 네트워크 정책 및 서비스 프록시와 같은 고급 오버레이 네트워크 기능을 제공한다.
### Kube-router
[kube-router](https://github.com/cloudnativelabs/kube-router)는 쿠버네티스를 위한 특수 목적의 네트워킹 솔루션으로 고성능 및 운영 단순성을 제공한다. 큐브 라우터는 리눅스 [LVS/IPVS](https://www.linuxvirtualserver.org/software/ipvs.html) 기반 서비스 프록시, 오버레이가 없는 리눅스 커널 포워딩 기반의 파드 간 네트워킹 솔루션 그리고 iptables/ipset 기반 네트워크 정책 집행도구를 제공한다.
### L2 네트워크 및 리눅스 브릿지
"베어메탈" 환경의 간단한 스위치와 같은 "더미(dumb)" L2 네트워크가 있는 경우,
위의 GCE 설정과 비슷한 작업을 수행할 수 있어야 한다.
이 방법은 매우 우연히 시도되었고 작동하는 것으로 보이지만
철저히 테스트되지 않았다. 이 기술을 사용하여
프로세스를 완료한 경우, 알려주길 바란다.
Lars Kellogg-Stedman이 제공하는
[이 훌륭한 튜토리얼](https://blog.oddbit.com/2014/08/11/four-ways-to-connect-a-docker/)의
"With Linux Bridge devices" 섹션을 참고한다.
### Multus(멀티 네트워크 플러그인)
Multus는 쿠버네티스의 CRD 기반 네트워크 오브젝트를 사용하여 쿠버네티스에서 멀티 네트워킹 기능을 지원하는 멀티 CNI 플러그인이다.
Multus는 CNI 명세를 구현하는 모든 [레퍼런스 플러그인](https://github.com/containernetworking/plugins)(예: [플라넬](https://github.com/containernetworking/cni.dev/blob/main/content/plugins/v0.9/meta/flannel.md), [DHCP](https://github.com/containernetworking/plugins/tree/master/plugins/ipam/dhcp), [Macvlan](https://github.com/containernetworking/plugins/tree/master/plugins/main/macvlan)) 및 써드파티 플러그인(예: [캘리코](https://github.com/projectcalico/cni-plugin), [위브(Weave)](https://github.com/weaveworks/weave), [실리움](https://github.com/cilium/cilium), [콘티브](https://github.com/contiv/netplugin))을 지원한다. 또한, Multus는 쿠버네티스의 클라우드 네이티브 애플리케이션과 NFV 기반 애플리케이션을 통해 쿠버네티스의 [SRIOV](https://github.com/hustcat/sriov-cni), [DPDK](https://github.com/Intel-Corp/sriov-cni), [OVS-DPDK 및 VPP](https://github.com/intel/vhost-user-net-plugin) 워크로드를 지원한다.
### OVN4NFV-K8s-Plugin (OVN 기반의 CNI 컨트롤러 & 플러그인)
[OVN4NFV-K8S-Plugin](https://github.com/opnfv/ovn4nfv-k8s-plugin)은 OVN 기반의 CNI 컨트롤러 플러그인으로 클라우드 네이티브 기반 서비스 기능 체인(Service function chaining(SFC)), 다중 OVN 오버레이 네트워킹, 동적 서브넷 생성, 동적 가상 네트워크 생성, VLAN 공급자 네트워크, 직접 공급자 네트워크와 멀티 클러스터 네트워킹의 엣지 기반 클라우드 등 네이티브 워크로드에 이상적인 멀티 네티워크 플러그인이다.
### NSX-T
[VMware NSX-T](https://docs.vmware.com/en/VMware-NSX-T/index.html)는 네트워크 가상화 및 보안 플랫폼이다. NSX-T는 멀티 클라우드 및 멀티 하이퍼바이저 환경에 네트워크 가상화를 제공할 수 있으며 이기종 엔드포인트와 기술 스택이 있는 새로운 애플리케이션 프레임워크 및 아키텍처에 중점을 둔다. vSphere 하이퍼바이저 외에도, 이러한 환경에는 KVM, 컨테이너 및 베어메탈과 같은 다른 하이퍼바이저가 포함된다.
[NSX-T 컨테이너 플러그인(NCP)](https://docs.vmware.com/en/VMware-NSX-T/2.0/nsxt_20_ncp_kubernetes.pdf)은 NSX-T와 쿠버네티스와 같은 컨테이너 오케스트레이터 사이의 통합은 물론, NSX-T와 Pivotal 컨테이너 서비스(PKS) 및 OpenShift와 같은 컨테이너 기반 CaaS/PaaS 플랫폼 간의 통합을 제공한다.
### OVN(오픈 버추얼 네트워킹)
OVN은 Open vSwitch 커뮤니티에서 개발한 오픈소스 네트워크
가상화 솔루션이다. 논리적 스위치, 논리적 라우터, 스테이트풀 ACL, 로드 밸런서 등을 생성하여
서로 다른 가상 네트워킹 토폴로지를 구축할 수 있다. 이 프로젝트에는
[ovn-kubernetes](https://github.com/openvswitch/ovn-kubernetes)에
특정 쿠버네티스 플러그인 및 문서가 있다.
### Weaveworks의 위브넷
[위브넷](https://www.weave.works/oss/net/)은
쿠버네티스 및 호스팅된 애플리케이션을 위한 탄력적이고 사용하기 쉬운 네트워크이다.
위브넷은 [CNI 플러그인](https://www.weave.works/docs/net/latest/cni-plugin/) 또는
독립형으로 실행된다. 두 버전에서, 실행하기 위해 구성이나 추가 코드가 필요하지 않으며,
두 경우 모두, 쿠버네티스의 표준과 같이 네트워크에서 파드별로 하나의 IP 주소를 제공한다.
쿠버네티스에서 지원하는 네트워킹 애드온의 일부 목록은 [이 페이지](/ko/docs/concepts/cluster-administration/addons/#network-and-networking-policy)를 참조한다.
## {{% heading "whatsnext" %}}

View File

@ -23,7 +23,7 @@ weight: 90
- API 서버를 찾는다.
- 인증 헤더를 추가한다.
1. [apiserver proxy](/ko/docs/tasks/access-application-cluster/access-cluster/#빌트인-서비스들의-발견):
1. [apiserver proxy](/ko/docs/tasks/access-application-cluster/access-cluster-services/#discovering-builtin-services):
- API 서버에 내장된 요새(bastion)이다.
- 클러스터 외부의 사용자가 도달할 수 없는 클러스터 IP 주소로 연결한다.

View File

@ -29,7 +29,7 @@ gRPC exporter를 이용하여 추적을 생성하고
기본적으로, 쿠버네티스 컴포넌트들은 [IANA OpenTelemetry 포트](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=opentelemetry)인
4317 포트로 OTLP에 대한 grpc exporter를 이용하여 추적를 내보낸다.
예를 들면, 수집기가 쿠버네티스 컴포넌트에 대해 사이드카(sidecar)로 동작한다면,
다음과 같은 리시버 설정을 통해 span을 수집하고 그 로그를 표준 출력(standard output)으로 내보낼 것이다.
다음과 같은 리시버 설정을 통해 스팬(span)을 수집하고 그 로그를 표준 출력(standard output)으로 내보낼 것이다.
```yaml
receivers:
@ -76,10 +76,40 @@ samplingRatePerMillion: 100
`TracingConfiguration` 구조체에 대해 더 많은 정보를 얻고 싶다면
[API server config API (v1alpha1)](/docs/reference/config-api/apiserver-config.v1alpha1/#apiserver-k8s-io-v1alpha1-TracingConfiguration)를 참고한다.
### kubelet 추적
{{< feature-state for_k8s_version="v1.25" state="alpha" >}}
kubelet CRI 인터페이스와 인증된 http 서버는 추적(trace) 스팬(span)을 생성하도록 설정 할수 있다.
apiserver와 마찬가지로 해당 엔드포인트 및 샘플링률을 구성할 수 있다.
추적 컨텍스트 전파(trace context propagation)도 구성할 수 있다. 상위 스팬(span)의 샘플링 설정이 항상 적용된다.
제공되는 설정의 샘플링률은 상위가 없는 스팬(span)에 기본 적용된다.
엔드포인트를 구성하지 않고 추적을 활성화로 설정하면, 기본 OpenTelemetry Collector receiver 주소는 "localhost:4317"으로 기본 설정된다.
#### kubelet tracing 활성화
추적을 활성화하려면 kubelet에서 `KubeletTracing`
[기능 게이트(feature gate)](/ko/docs/reference/command-line-tools-reference/feature-gates/)을 활성화한다.
또한 kubelet에서
[tracing configuration](https://github.com/kubernetes/component-base/blob/release-1.25/tracing/api/v1/types.go)을 제공한다.
[tracing 구성](https://github.com/kubernetes/component-base/blob/release-1.25/tracing/api/v1/types.go)을 참조한다.
다음은 10000개 요청 중 1개에 대하여 스팬(span)을 기록하고, 기본 OpenTelemetry 앤드포인트를 사용하도록 한 kubelet 구성 예시이다.
```yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
featureGates:
KubeletTracing: true
tracing:
# 기본값
#endpoint: localhost:4317
samplingRatePerMillion: 100
```
## 안정성
추적의 계측화(tracing instrumentation)는 여전히 활발히 개발되는 중이어서 다양한 형태로 변경될 수 있다.
span의 이름, 첨부되는 속성, 계측될 엔드포인트(instrumented endpoints)들 등이 그렇다.
스팬(span)의 이름, 첨부되는 속성, 계측될 엔드포인트(instrumented endpoints)들 등이 그렇다.
이 속성이 안정화(graduates to stable)되기 전까지는
이전 버전과의 호환성은 보장되지 않는다.

View File

@ -236,7 +236,7 @@ kubelet은 파드의 리소스 사용량을 파드
## 로컬 임시(ephemeral) 스토리지
<!-- feature gate LocalStorageCapacityIsolation -->
{{< feature-state for_k8s_version="v1.10" state="beta" >}}
{{< feature-state for_k8s_version="v1.25" state="stable" >}}
노드에는 로컬에 연결된 쓰기 가능 장치 또는, 때로는 RAM에 의해
지원되는 로컬 임시 스토리지가 있다.
@ -305,14 +305,9 @@ kubelet에 지시하는 디렉터리는 이 두 번째 파일시스템에 있다
{{% /tab %}}
{{< /tabs >}}
kubelet은 사용 중인 로컬 스토리지 양을 측정할 수 있다. 이것은 다음을
제공한다.
- `LocalStorageCapacityIsolation`
[기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)(이
기능이 기본적으로 설정되어 있음)를 활성화하고,
- 로컬 임시 스토리지에 대한 지원되는 구성 중 하나를
사용하여 노드를 설정한다.
kubelet은 사용 중인 로컬 스토리지 양을 측정할 수 있다.
임시 볼륨(ephemeral storage)을 설정하기 위해 지원되는 구성 중 하나를 사용하여
노드를 설정한 경우 제공된다.
다른 구성을 사용하는 경우, kubelet은 임시 로컬 스토리지에 대한 리소스
제한을 적용하지 않는다.

View File

@ -566,7 +566,7 @@ metadata:
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
image: registry.k8s.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- secretRef:
@ -794,7 +794,7 @@ spec:
secretName: dotfile-secret
containers:
- name: dotfile-test-container
image: k8s.gcr.io/busybox
image: registry.k8s.io/busybox
command:
- ls
- "-l"

View File

@ -103,9 +103,9 @@ Kubelet이 구동된 후에 해당 훅은 재전송될 것이다.
훅 핸들러의 로그는 파드 이벤트로 노출되지 않는다.
만약 핸들러가 어떠한 이유로 실패하면, 핸들러는 이벤트를 방송한다.
`PostStart`의 경우, 이것은 `FailedPostStartHook` 이벤트이며,
`PreStop`의 경우, 이것은 `FailedPreStopHook` 이벤트이다.
실패한 `FailedPreStopHook` 이벤트를 직접 생성하려면, [lifecycle-events.yaml](https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/pods/lifecycle-events.yaml) 파일을 수정하여 postStart 명령을 "badcommand"로 변경하고 이를 적용한다.
`PostStart`의 경우 `FailedPostStartHook` 이벤트이며,
`PreStop`의 경우 `FailedPreStopHook` 이벤트이다.
실패한 `FailedPostStartHook` 이벤트를 직접 생성하려면, [lifecycle-events.yaml](https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/pods/lifecycle-events.yaml) 파일을 수정하여 postStart 명령을 "badcommand"로 변경하고 이를 적용한다.
다음은 `kubectl describe pod lifecycle-demo` 를 실행하여 볼 수 있는 이벤트 출력 예시이다.
```

View File

@ -24,8 +24,8 @@ weight: 10
## 이미지 이름
컨테이너 이미지는 일반적으로 `pause`, `example/mycontainer` 또는 `kube-apiserver` 와 같은 이름을 부여한다.
이미지는 또한 레지스트리 호스트 이름을 포함할 수 있다. 예를 들면, `fictional.registry.example/imagename`
과 같다. 그리고 포트 번호도 포함할 수 있다. 예를 들면, `fictional.registry.example:10443/imagename` 과 같다.
이미지는 또한 레지스트리 호스트 이름을 포함할 수 있다. 예를 들 `fictional.registry.example/imagename`
와 같다. 그리고 `fictional.registry.example:10443/imagename` 와 같이 포트 번호도 포함할 수 있다.
레지스트리 호스트 이름을 지정하지 않으면, 쿠버네티스는 도커 퍼블릭 레지스트리를 의미한다고 가정한다.
@ -275,6 +275,8 @@ kubelet은 크리덴셜을 순차적으로 사용하여 풀을 시도한다.
{{< /note >}}
쿠버네티스는 파드에 컨테이너 이미지 레지스트리 키를 명시하는 것을 지원한다.
`imagePullSecrets`은 모두 파드와 동일한 네임스페이스에 있어야 한다.
참조되는 시크릿의 타입은 `kubernetes.io/dockercfg` 이거나 `kubernetes.io/dockerconfigjson` 이어야 한다.
#### 도커 구성으로 시크릿 생성

View File

@ -26,7 +26,7 @@ weight: 10
동적 등록을 통해 실행 중인 클러스터에서 커스텀 리소스가 나타나거나 사라질 수 있으며
클러스터 관리자는 클러스터 자체와 독립적으로 커스텀 리소스를 업데이트 할 수 있다.
커스텀 리소스가 설치되면 사용자는 *파드* 와 같은 빌트인 리소스와 마찬가지로
[kubectl](/ko/docs/reference/kubectl/)을 사용하여 해당 오브젝트를 생성하고
{{< glossary_tooltip text="kubectl" term_id="kubectl" >}}을 사용하여 해당 오브젝트를 생성하고
접근할 수 있다.
## 커스텀 컨트롤러
@ -99,7 +99,7 @@ _선언적(declarative) API_ 를 제공하게 된다.
* 파일이 업데이트될 때 디플로이먼트 등을 통해 롤링 업데이트를 수행하려고 한다.
{{< note >}}
민감한 데이터에는 [시크릿](/ko/docs/concepts/configuration/secret/)을 사용하자. 이는 컨피그맵과 비슷하지만 더 안전한다.
민감한 데이터에는 {{< glossary_tooltip text="시크릿" term_id="secret" >}}을 사용하자. 이는 컨피그맵과 비슷하지만 더 안전하다.
{{< /note >}}
다음 중 대부분이 적용되는 경우 커스텀 리소스(CRD 또는 애그리게이트 API(aggregated API))를 사용하자.

View File

@ -68,7 +68,7 @@ metadata:
spec:
containers:
- name: demo-container-1
image: k8s.gcr.io/pause:2.0
image: registry.k8s.io/pause:2.0
resources:
limits:
hardware-vendor.example/foo: 2

View File

@ -32,7 +32,7 @@ CNI 스펙 [v1.0.0](https://github.com/containernetworking/cni/blob/spec-v1.0.0/
쿠버네티스 1.24 이전까지는 `cni-bin-dir``network-plugin` 커맨드 라인 파라미터를 사용해 kubelet이 CNI 플러그인을 관리하게 할 수도 있었다.
이 커맨드 라인 파라미터들은 쿠버네티스 1.24에서 제거되었으며, CNI 관리는 더 이상 kubelet 범위에 포함되지 않는다.
dockershim 제거 후 문제가 발생하는 경우
도커심 제거 후 문제가 발생하는 경우
[CNI 플러그인 관련 오류 문제 해결](/docs/tasks/administer-cluster/migrating-from-dockershim/troubleshooting-cni-plugin-related-errors/)을 참조하자.
{{< /note >}}

View File

@ -15,7 +15,7 @@ weight: 30
## 동기 부여
오퍼레이터 패턴은 서비스 또는 서비스 셋을 관리하는 운영자의
_오퍼레이터 패턴_은 서비스 또는 서비스 셋을 관리하는 운영자의
주요 목표를 포착하는 것을 목표로 한다. 특정 애플리케이션 및
서비스를 돌보는 운영자는 시스템의 작동 방식, 배포 방법 및 문제가 있는 경우
대처 방법에 대해 깊이 알고 있다.

View File

@ -1,7 +1,97 @@
---
title: "개요"
weight: 20
description: 쿠버네티스와 그 컴포넌트에 대한 하이-레벨(high-level) 개요를 제공한다.
sitemap:
priority: 0.9
# reviewers:
# - bgrant0607
# - mikedanese
title: 쿠버네티스란 무엇인가?
description: >
쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식할 수 있고, 확장 가능한 오픈소스 플랫폼으로, 선언적 구성과 자동화를 모두 지원한다. 쿠버네티스는 크고 빠르게 성장하는 생태계를 가지고 있다. 쿠버네티스 서비스, 지원 그리고 도구들은 광범위하게 제공된다.
content_type: concept
weight: 10
card:
name: concepts
weight: 10
no_list: true
---
<!-- overview -->
이 페이지에서는 쿠버네티스 개요를 설명한다.
<!-- body -->
쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼이다. 쿠버네티스는 선언적 구성과 자동화를 모두 용이하게 해준다. 쿠버네티스는 크고, 빠르게 성장하는 생태계를 가지고 있다. 쿠버네티스 서비스, 기술 지원 및 도구는 어디서나 쉽게 이용할 수 있다.
쿠버네티스란 명칭은 키잡이(helmsman)나 파일럿을 뜻하는 그리스어에서 유래했다. K8s라는 표기는 "K"와 "s"와 그 사이에 있는 8글자를 나타내는 약식 표기이다. 구글이 2014년에 쿠버네티스 프로젝트를 오픈소스화했다. 쿠버네티스는 프로덕션 워크로드를 대규모로 운영하는 [15년 이상의 구글 경험](/blog/2015/04/borg-predecessor-to-kubernetes/)과 커뮤니티의 최고의 아이디어와 적용 사례가 결합되어 있다.
## 여정 돌아보기
시간이 지나면서 쿠버네티스가 왜 유용하게 되었는지 살펴보자.
![배포 혁명](/images/docs/Container_Evolution.svg)
**전통적인 배포 시대:**
초기 조직은 애플리케이션을 물리 서버에서 실행했었다. 한 물리 서버에서 여러 애플리케이션의 리소스 한계를 정의할 방법이 없었기에, 리소스 할당의 문제가 발생했다. 예를 들어 물리 서버 하나에서 여러 애플리케이션을 실행하면, 리소스 전부를 차지하는 애플리케이션 인스턴스가 있을 수 있고, 결과적으로는 다른 애플리케이션의 성능이 저하될 수 있었다. 이에 대한 해결책은 서로 다른 여러 물리 서버에서 각 애플리케이션을 실행하는 것이 있다. 그러나 이는 리소스가 충분히 활용되지 않는다는 점에서 확장 가능하지 않았으므로, 물리 서버를 많이 유지하기 위해서 조직에게 많은 비용이 들었다.
**가상화된 배포 시대:** 그 해결책으로 가상화가 도입되었다. 이는 단일 물리 서버의 CPU에서 여러 가상 시스템 (VM)을 실행할 수 있게 한다. 가상화를 사용하면 VM간에 애플리케이션을 격리하고 애플리케이션의 정보를 다른 애플리케이션에서 자유롭게 액세스 할 수 없으므로, 일정 수준의 보안성을 제공할 수 있다.
가상화를 사용하면 물리 서버에서 리소스를 보다 효율적으로 활용할 수 있으며, 쉽게 애플리케이션을 추가하거나 업데이트할 수 있고 하드웨어 비용을 절감할 수 있어 더 나은 확장성을 제공한다. 가상화를 통해 일련의 물리 리소스를 폐기 가능한(disposable) 가상 머신으로 구성된 클러스터로 만들 수 있다.
각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함한 모든 구성 요소를 실행하는 하나의 완전한 머신이다.
**컨테이너 개발 시대:** 컨테이너는 VM과 유사하지만 격리 속성을 완화하여 애플리케이션 간에 운영체제(OS)를 공유한다. 그러므로 컨테이너는 가볍다고 여겨진다. VM과 마찬가지로 컨테이너에는 자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간 등이 있다. 기본 인프라와의 종속성을 끊었기 때문에, 클라우드나 OS 배포본에 모두 이식할 수 있다.
컨테이너는 다음과 같은 추가적인 혜택을 제공하기 때문에 인기가 있다.
* 기민한 애플리케이션 생성과 배포: VM 이미지를 사용하는 것에 비해 컨테이너 이미지 생성이 보다 쉽고 효율적임.
* 지속적인 개발, 통합 및 배포: 안정적이고 주기적으로 컨테이너 이미지를 빌드해서 배포할 수 있고 (이미지의 불변성 덕에) 빠르고 효율적으로 롤백할 수 있다.
* 개발과 운영의 관심사 분리: 배포 시점이 아닌 빌드/릴리스 시점에 애플리케이션 컨테이너 이미지를 만들기 때문에, 애플리케이션이 인프라스트럭처에서 분리된다.
* 가시성(observability): OS 수준의 정보와 메트릭에 머무르지 않고, 애플리케이션의 헬스와 그 밖의 시그널을 볼 수 있다.
* 개발, 테스팅 및 운영 환경에 걸친 일관성: 랩탑에서도 클라우드에서와 동일하게 구동된다.
* 클라우드 및 OS 배포판 간 이식성: Ubuntu, RHEL, CoreOS, 온-프레미스, 주요 퍼블릭 클라우드와 어디에서든 구동된다.
* 애플리케이션 중심 관리: 가상 하드웨어 상에서 OS를 실행하는 수준에서 논리적인 리소스를 사용하는 OS 상에서 애플리케이션을 실행하는 수준으로 추상화 수준이 높아진다.
* 느슨하게 커플되고, 분산되고, 유연하며, 자유로운 마이크로서비스: 애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고 보다 작고 독립적인 단위로 쪼개져서 동적으로 배포되고 관리될 수 있다.
* 리소스 격리: 애플리케이션 성능을 예측할 수 있다.
* 리소스 사용량: 고효율 고집적.
## 쿠버네티스가 왜 필요하고 무엇을 할 수 있나 {#why-you-need-kubernetes-and-what-can-it-do}
컨테이너는 애플리케이션을 포장하고 실행하는 좋은 방법이다. 프로덕션 환경에서는 애플리케이션을 실행하는 컨테이너를 관리하고 가동 중지 시간이 없는지 확인해야 한다. 예를 들어 컨테이너가 다운되면 다른 컨테이너를 다시 시작해야 한다. 이 문제를 시스템에 의해 처리한다면 더 쉽지 않을까?
그것이 쿠버네티스가 필요한 이유이다! 쿠버네티스는 분산 시스템을 탄력적으로 실행하기 위한 프레임 워크를 제공한다. 애플리케이션의 확장과 장애 조치를 처리하고, 배포 패턴 등을 제공한다. 예를 들어, 쿠버네티스는 시스템의 카나리아 배포를 쉽게 관리 할 수 있다.
쿠버네티스는 다음을 제공한다.
* **서비스 디스커버리와 로드 밸런싱**
쿠버네티스는 DNS 이름을 사용하거나 자체 IP 주소를 사용하여 컨테이너를 노출할 수 있다. 컨테이너에 대한 트래픽이 많으면, 쿠버네티스는 네트워크 트래픽을 로드밸런싱하고 배포하여 배포가 안정적으로 이루어질 수 있다.
* **스토리지 오케스트레이션**
쿠버네티스를 사용하면 로컬 저장소, 공용 클라우드 공급자 등과 같이 원하는 저장소 시스템을 자동으로 탑재 할 수 있다.
* **자동화된 롤아웃과 롤백**
쿠버네티스를 사용하여 배포된 컨테이너의 원하는 상태를 서술할 수 있으며 현재 상태를 원하는 상태로 설정한 속도에 따라 변경할 수 있다. 예를 들어 쿠버네티스를 자동화해서 배포용 새 컨테이너를 만들고, 기존 컨테이너를 제거하고, 모든 리소스를 새 컨테이너에 적용할 수 있다.
* **자동화된 빈 패킹(bin packing)**
컨테이너화된 작업을 실행하는데 사용할 수 있는 쿠버네티스 클러스터 노드를 제공한다. 각 컨테이너가 필요로 하는 CPU와 메모리(RAM)를 쿠버네티스에게 지시한다. 쿠버네티스는 컨테이너를 노드에 맞추어서 리소스를 가장 잘 사용할 수 있도록 해준다.
* **자동화된 복구(self-healing)**
쿠버네티스는 실패한 컨테이너를 다시 시작하고, 컨테이너를 교체하며, '사용자 정의 상태 검사'에 응답하지 않는 컨테이너를 죽이고, 서비스 준비가 끝날 때까지 그러한 과정을 클라이언트에 보여주지 않는다.
* **시크릿과 구성 관리**
쿠버네티스를 사용하면 암호, OAuth 토큰 및 SSH 키와 같은 중요한 정보를 저장하고 관리 할 수 있다. 컨테이너 이미지를 재구성하지 않고 스택 구성에 시크릿을 노출하지 않고도 시크릿 및 애플리케이션 구성을 배포 및 업데이트 할 수 있다.
## 쿠버네티스가 아닌 것
쿠버네티스는 전통적인, 모든 것이 포함된 Platform as a Service(PaaS)가 아니다. 쿠버네티스는 하드웨어 수준보다는 컨테이너 수준에서 운영되기 때문에, PaaS가 일반적으로 제공하는 배포, 스케일링, 로드 밸런싱과 같은 기능을 제공하며, 사용자가 로깅, 모니터링 및 알림 솔루션을 통합할 수 있다. 하지만, 쿠버네티스는 모놀리식(monolithic)이 아니어서, 이런 기본 솔루션이 선택적이며 추가나 제거가 용이하다. 쿠버네티스는 개발자 플랫폼을 만드는 구성 요소를 제공하지만, 필요한 경우 사용자의 선택권과 유연성을 지켜준다.
쿠버네티스는:
* 지원하는 애플리케이션의 유형을 제약하지 않는다. 쿠버네티스는 상태 유지가 필요 없는(stateless) 워크로드, 상태 유지가 필요한(stateful) 워크로드, 데이터 처리를 위한 워크로드를 포함해서 극단적으로 다양한 워크로드를 지원하는 것을 목표로 한다. 애플리케이션이 컨테이너에서 구동될 수 있다면, 쿠버네티스에서도 잘 동작할 것이다.
* 소스 코드를 배포하지 않으며 애플리케이션을 빌드하지 않는다. 지속적인 통합과 전달과 배포, 곧 CI/CD 워크플로우는 조직 문화와 취향에 따를 뿐만 아니라 기술적인 요구사항으로 결정된다.
* 애플리케이션 레벨의 서비스를 제공하지 않는다. 애플리케이션 레벨의 서비스에는 미들웨어(예, 메시지 버스), 데이터 처리 프레임워크(예, Spark), 데이터베이스(예, MySQL), 캐시 또는 클러스터 스토리지 시스템(예, Ceph) 등이 있다. 이런 컴포넌트는 쿠버네티스 상에서 구동될 수 있고, 쿠버네티스 상에서 구동 중인 애플리케이션이 [Open Service Broker](https://openservicebrokerapi.org/) 와 같은 이식 가능한 메커니즘을 통해 접근할 수도 있다.
* 로깅, 모니터링 또는 경보 솔루션을 포함하지 않는다. 개념 증명을 위한 일부 통합이나, 메트릭을 수집하고 노출하는 메커니즘을 제공한다.
* 기본 설정 언어/시스템(예, Jsonnet)을 제공하거나 요구하지 않는다. 선언적 명세의 임의적인 형식을 목적으로 하는 선언적 API를 제공한다.
* 포괄적인 머신 설정, 유지보수, 관리, 자동 복구 시스템을 제공하거나 채택하지 않는다.
* 추가로, 쿠버네티스는 단순한 오케스트레이션 시스템이 아니다. 사실, 쿠버네티스는 오케스트레이션의 필요성을 없애준다. 오케스트레이션의 기술적인 정의는 A를 먼저 한 다음, B를 하고, C를 하는 것과 같이 정의된 워크플로우를 수행하는 것이다. 반면에, 쿠버네티스는 독립적이고 조합 가능한 제어 프로세스들로 구성되어 있다. 이 프로세스는 지속적으로 현재 상태를 입력받은 의도한 상태로 나아가도록 한다. A에서 C로 어떻게 갔는지는 상관이 없다. 중앙화된 제어도 필요치 않다. 이로써 시스템이 보다 더 사용하기 쉬워지고, 강력해지며, 견고하고, 회복력을 갖추게 되며, 확장 가능해진다.
## {{% heading "whatsnext" %}}
* [쿠버네티스 구성요소](/ko/docs/concepts/overview/components/) 살펴보기
* [쿠버네티스 API](/ko/docs/concepts/overview/kubernetes-api/) 살펴보기
* [클러스터 아키텍처](/ko/docs/concepts/architecture/) 살펴보기
* [시작하기](/ko/docs/setup/) 준비가 되었는가?

View File

@ -51,8 +51,8 @@ card:
이들 컨트롤러는 다음을 포함한다.
* 노드 컨트롤러: 노드가 다운되었을 때 통지와 대응에 관한 책임을 가진다.
* 레플리케이션 컨트롤러: 시스템의 모든 레플리케이션 컨트롤러 오브젝트에 대해 알맞은 수의 파드들
유지시켜 주는 책임을 가진다.
* 잡 컨트롤러: 일회성 작업을 나타내는 잡 오브젝트를 감시한 다음, 해당 작업
완료할 때까지 동작하는 파드를 생성한다.
* 엔드포인트 컨트롤러: 엔드포인트 오브젝트를 채운다(즉, 서비스와 파드를 연결시킨다.)
* 서비스 어카운트 & 토큰 컨트롤러: 새로운 네임스페이스에 대한 기본 계정과 API 접근 토큰을 생성한다.

View File

@ -93,19 +93,22 @@ kube-apiserver 구성 요소에
`/openapi/v3` 디스커버리 엔드포인트는 사용 가능한 모든
그룹/버전의 목록을 제공한다. 이 엔드포인트는 JSON 만을 반환한다.
이러한 그룹/버전은 다음과 같은 형식으로 제공된다.
```json
```yaml
{
"paths": {
...
...,
"api/v1": {
"serverRelativeURL": "/openapi/v3/api/v1?hash=CC0E9BFD992D8C59AEC98A1E2336F899E8318D3CF4C68944C3DEC640AF5AB52D864AC50DAA8D145B3494F75FA3CFF939FCBDDA431DAD3CA79738B297795818CF"
},
"apis/admissionregistration.k8s.io/v1": {
"serverRelativeURL": "/openapi/v3/apis/admissionregistration.k8s.io/v1?hash=E19CC93A116982CE5422FC42B590A8AFAD92CDE9AE4D59B5CAAD568F083AD07946E6CB5817531680BCE6E215C16973CD39003B0425F3477CFD854E89A9DB6597"
},
...
....
}
}
```
<!-- for editors: intentionally use yaml instead of json here, to prevent syntax highlight error. -->
위의 상대 URL은 변경 불가능한(immutable) OpenAPI 상세를 가리키고 있으며,
이는 클라이언트에서의 캐싱을 향상시키기 위함이다.

View File

@ -1,96 +0,0 @@
---
# reviewers:
# - bgrant0607
# - mikedanese
title: 쿠버네티스란 무엇인가?
description: >
쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식할 수 있고, 확장 가능한 오픈소스 플랫폼으로, 선언적 구성과 자동화를 모두 지원한다. 쿠버네티스는 크고 빠르게 성장하는 생태계를 가지고 있다. 쿠버네티스 서비스, 지원 그리고 도구들은 광범위하게 제공된다.
content_type: concept
weight: 10
card:
name: concepts
weight: 10
sitemap:
priority: 0.9
---
<!-- overview -->
이 페이지에서는 쿠버네티스 개요를 설명한다.
<!-- body -->
쿠버네티스는 컨테이너화된 워크로드와 서비스를 관리하기 위한 이식성이 있고, 확장가능한 오픈소스 플랫폼이다. 쿠버네티스는 선언적 구성과 자동화를 모두 용이하게 해준다. 쿠버네티스는 크고, 빠르게 성장하는 생태계를 가지고 있다. 쿠버네티스 서비스, 기술 지원 및 도구는 어디서나 쉽게 이용할 수 있다.
쿠버네티스란 명칭은 키잡이(helmsman)나 파일럿을 뜻하는 그리스어에서 유래했다. K8s라는 표기는 "K"와 "s"와 그 사이에 있는 8글자를 나타내는 약식 표기이다. 구글이 2014년에 쿠버네티스 프로젝트를 오픈소스화했다. 쿠버네티스는 프로덕션 워크로드를 대규모로 운영하는 [15년 이상의 구글 경험](/blog/2015/04/borg-predecessor-to-kubernetes/)과 커뮤니티의 최고의 아이디어와 적용 사례가 결합되어 있다.
## 여정 돌아보기
시간이 지나면서 쿠버네티스가 왜 유용하게 되었는지 살펴보자.
![배포 혁명](/images/docs/Container_Evolution.svg)
**전통적인 배포 시대:**
초기 조직은 애플리케이션을 물리 서버에서 실행했었다. 한 물리 서버에서 여러 애플리케이션의 리소스 한계를 정의할 방법이 없었기에, 리소스 할당의 문제가 발생했다. 예를 들어 물리 서버 하나에서 여러 애플리케이션을 실행하면, 리소스 전부를 차지하는 애플리케이션 인스턴스가 있을 수 있고, 결과적으로는 다른 애플리케이션의 성능이 저하될 수 있었다. 이에 대한 해결책은 서로 다른 여러 물리 서버에서 각 애플리케이션을 실행하는 것이 있다. 그러나 이는 리소스가 충분히 활용되지 않는다는 점에서 확장 가능하지 않았으므로, 물리 서버를 많이 유지하기 위해서 조직에게 많은 비용이 들었다.
**가상화된 배포 시대:** 그 해결책으로 가상화가 도입되었다. 이는 단일 물리 서버의 CPU에서 여러 가상 시스템 (VM)을 실행할 수 있게 한다. 가상화를 사용하면 VM간에 애플리케이션을 격리하고 애플리케이션의 정보를 다른 애플리케이션에서 자유롭게 액세스 할 수 없으므로, 일정 수준의 보안성을 제공할 수 있다.
가상화를 사용하면 물리 서버에서 리소스를 보다 효율적으로 활용할 수 있으며, 쉽게 애플리케이션을 추가하거나 업데이트할 수 있고 하드웨어 비용을 절감할 수 있어 더 나은 확장성을 제공한다. 가상화를 통해 일련의 물리 리소스를 폐기 가능한(disposable) 가상 머신으로 구성된 클러스터로 만들 수 있다.
각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함한 모든 구성 요소를 실행하는 하나의 완전한 머신이다.
**컨테이너 개발 시대:** 컨테이너는 VM과 유사하지만 격리 속성을 완화하여 애플리케이션 간에 운영체제(OS)를 공유한다. 그러므로 컨테이너는 가볍다고 여겨진다. VM과 마찬가지로 컨테이너에는 자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간 등이 있다. 기본 인프라와의 종속성을 끊었기 때문에, 클라우드나 OS 배포본에 모두 이식할 수 있다.
컨테이너는 다음과 같은 추가적인 혜택을 제공하기 때문에 인기가 있다.
* 기민한 애플리케이션 생성과 배포: VM 이미지를 사용하는 것에 비해 컨테이너 이미지 생성이 보다 쉽고 효율적임.
* 지속적인 개발, 통합 및 배포: 안정적이고 주기적으로 컨테이너 이미지를 빌드해서 배포할 수 있고 (이미지의 불변성 덕에) 빠르고 효율적으로 롤백할 수 있다.
* 개발과 운영의 관심사 분리: 배포 시점이 아닌 빌드/릴리스 시점에 애플리케이션 컨테이너 이미지를 만들기 때문에, 애플리케이션이 인프라스트럭처에서 분리된다.
* 가시성(observability): OS 수준의 정보와 메트릭에 머무르지 않고, 애플리케이션의 헬스와 그 밖의 시그널을 볼 수 있다.
* 개발, 테스팅 및 운영 환경에 걸친 일관성: 랩탑에서도 클라우드에서와 동일하게 구동된다.
* 클라우드 및 OS 배포판 간 이식성: Ubuntu, RHEL, CoreOS, 온-프레미스, 주요 퍼블릭 클라우드와 어디에서든 구동된다.
* 애플리케이션 중심 관리: 가상 하드웨어 상에서 OS를 실행하는 수준에서 논리적인 리소스를 사용하는 OS 상에서 애플리케이션을 실행하는 수준으로 추상화 수준이 높아진다.
* 느슨하게 커플되고, 분산되고, 유연하며, 자유로운 마이크로서비스: 애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고 보다 작고 독립적인 단위로 쪼개져서 동적으로 배포되고 관리될 수 있다.
* 리소스 격리: 애플리케이션 성능을 예측할 수 있다.
* 자원 사용량: 리소스 사용량: 고효율 고집적.
## 쿠버네티스가 왜 필요하고 무엇을 할 수 있나 {#why-you-need-kubernetes-and-what-can-it-do}
컨테이너는 애플리케이션을 포장하고 실행하는 좋은 방법이다. 프로덕션 환경에서는 애플리케이션을 실행하는 컨테이너를 관리하고 가동 중지 시간이 없는지 확인해야 한다. 예를 들어 컨테이너가 다운되면 다른 컨테이너를 다시 시작해야 한다. 이 문제를 시스템에 의해 처리한다면 더 쉽지 않을까?
그것이 쿠버네티스가 필요한 이유이다! 쿠버네티스는 분산 시스템을 탄력적으로 실행하기 위한 프레임 워크를 제공한다. 애플리케이션의 확장과 장애 조치를 처리하고, 배포 패턴 등을 제공한다. 예를 들어, 쿠버네티스는 시스템의 카나리아 배포를 쉽게 관리 할 수 있다.
쿠버네티스는 다음을 제공한다.
* **서비스 디스커버리와 로드 밸런싱**
쿠버네티스는 DNS 이름을 사용하거나 자체 IP 주소를 사용하여 컨테이너를 노출할 수 있다. 컨테이너에 대한 트래픽이 많으면, 쿠버네티스는 네트워크 트래픽을 로드밸런싱하고 배포하여 배포가 안정적으로 이루어질 수 있다.
* **스토리지 오케스트레이션**
쿠버네티스를 사용하면 로컬 저장소, 공용 클라우드 공급자 등과 같이 원하는 저장소 시스템을 자동으로 탑재 할 수 있다.
* **자동화된 롤아웃과 롤백**
쿠버네티스를 사용하여 배포된 컨테이너의 원하는 상태를 서술할 수 있으며 현재 상태를 원하는 상태로 설정한 속도에 따라 변경할 수 있다. 예를 들어 쿠버네티스를 자동화해서 배포용 새 컨테이너를 만들고, 기존 컨테이너를 제거하고, 모든 리소스를 새 컨테이너에 적용할 수 있다.
* **자동화된 빈 패킹(bin packing)**
컨테이너화된 작업을 실행하는데 사용할 수 있는 쿠버네티스 클러스터 노드를 제공한다. 각 컨테이너가 필요로 하는 CPU와 메모리(RAM)를 쿠버네티스에게 지시한다. 쿠버네티스는 컨테이너를 노드에 맞추어서 리소스를 가장 잘 사용할 수 있도록 해준다.
* **자동화된 복구(self-healing)**
쿠버네티스는 실패한 컨테이너를 다시 시작하고, 컨테이너를 교체하며, '사용자 정의 상태 검사'에 응답하지 않는 컨테이너를 죽이고, 서비스 준비가 끝날 때까지 그러한 과정을 클라이언트에 보여주지 않는다.
* **시크릿과 구성 관리**
쿠버네티스를 사용하면 암호, OAuth 토큰 및 SSH 키와 같은 중요한 정보를 저장하고 관리 할 수 있다. 컨테이너 이미지를 재구성하지 않고 스택 구성에 시크릿을 노출하지 않고도 시크릿 및 애플리케이션 구성을 배포 및 업데이트 할 수 있다.
## 쿠버네티스가 아닌 것
쿠버네티스는 전통적인, 모든 것이 포함된 Platform as a Service(PaaS)가 아니다. 쿠버네티스는 하드웨어 수준보다는 컨테이너 수준에서 운영되기 때문에, PaaS가 일반적으로 제공하는 배포, 스케일링, 로드 밸런싱과 같은 기능을 제공하며, 사용자가 로깅, 모니터링 및 알림 솔루션을 통합할 수 있다. 하지만, 쿠버네티스는 모놀리식(monolithic)이 아니어서, 이런 기본 솔루션이 선택적이며 추가나 제거가 용이하다. 쿠버네티스는 개발자 플랫폼을 만드는 구성 요소를 제공하지만, 필요한 경우 사용자의 선택권과 유연성을 지켜준다.
쿠버네티스는:
* 지원하는 애플리케이션의 유형을 제약하지 않는다. 쿠버네티스는 상태 유지가 필요 없는(stateless) 워크로드, 상태 유지가 필요한(stateful) 워크로드, 데이터 처리를 위한 워크로드를 포함해서 극단적으로 다양한 워크로드를 지원하는 것을 목표로 한다. 애플리케이션이 컨테이너에서 구동될 수 있다면, 쿠버네티스에서도 잘 동작할 것이다.
* 소스 코드를 배포하지 않으며 애플리케이션을 빌드하지 않는다. 지속적인 통합과 전달과 배포, 곧 CI/CD 워크플로우는 조직 문화와 취향에 따를 뿐만 아니라 기술적인 요구사항으로 결정된다.
* 애플리케이션 레벨의 서비스를 제공하지 않는다. 애플리케이션 레벨의 서비스에는 미들웨어(예, 메시지 버스), 데이터 처리 프레임워크(예, Spark), 데이터베이스(예, MySQL), 캐시 또는 클러스터 스토리지 시스템(예, Ceph) 등이 있다. 이런 컴포넌트는 쿠버네티스 상에서 구동될 수 있고, 쿠버네티스 상에서 구동 중인 애플리케이션이 [Open Service Broker](https://openservicebrokerapi.org/) 와 같은 이식 가능한 메커니즘을 통해 접근할 수도 있다.
* 로깅, 모니터링 또는 경보 솔루션을 포함하지 않는다. 개념 증명을 위한 일부 통합이나, 메트릭을 수집하고 노출하는 메커니즘을 제공한다.
* 기본 설정 언어/시스템(예, Jsonnet)을 제공하거나 요구하지 않는다. 선언적 명세의 임의적인 형식을 목적으로 하는 선언적 API를 제공한다.
* 포괄적인 머신 설정, 유지보수, 관리, 자동 복구 시스템을 제공하거나 채택하지 않는다.
* 추가로, 쿠버네티스는 단순한 오케스트레이션 시스템이 아니다. 사실, 쿠버네티스는 오케스트레이션의 필요성을 없애준다. 오케스트레이션의 기술적인 정의는 A를 먼저 한 다음, B를 하고, C를 하는 것과 같이 정의된 워크플로우를 수행하는 것이다. 반면에, 쿠버네티스는 독립적이고 조합 가능한 제어 프로세스들로 구성되어 있다. 이 프로세스는 지속적으로 현재 상태를 입력받은 의도한 상태로 나아가도록 한다. A에서 C로 어떻게 갔는지는 상관이 없다. 중앙화된 제어도 필요치 않다. 이로써 시스템이 보다 더 사용하기 쉬워지고, 강력해지며, 견고하고, 회복력을 갖추게 되며, 확장 가능해진다.
## {{% heading "whatsnext" %}}
* [쿠버네티스 구성요소](/ko/docs/concepts/overview/components/) 살펴보기
* [시작하기](/ko/docs/setup/) 준비가 되었는가?

View File

@ -40,7 +40,6 @@ kubectl과 대시보드와 같은 많은 도구들로 쿠버네티스 오브젝
| `app.kubernetes.io/component` | 아키텍처 내 구성요소 | `database` | 문자열 |
| `app.kubernetes.io/part-of` | 이 애플리케이션의 전체 이름 | `wordpress` | 문자열 |
| `app.kubernetes.io/managed-by` | 애플리케이션의 작동을 관리하는 데 사용되는 도구 | `helm` | 문자열 |
| `app.kubernetes.io/created-by` | 이 리소스를 만든 컨트롤러/사용자 | `controller-manager` | 문자열 |
위 레이블의 실제 예시는 다음 {{< glossary_tooltip text="스테이트풀셋" term_id="statefulset" >}} 오브젝트를 고려한다.
@ -56,7 +55,6 @@ metadata:
app.kubernetes.io/component: database
app.kubernetes.io/part-of: wordpress
app.kubernetes.io/managed-by: helm
app.kubernetes.io/created-by: controller-manager
```
## 애플리케이션과 애플리케이션 인스턴스

View File

@ -124,7 +124,7 @@ metadata:
spec:
containers:
- name: cuda-test
image: "k8s.gcr.io/cuda-vector-add:v0.1"
image: "registry.k8s.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1

View File

@ -203,7 +203,6 @@ spec:
정보를 제공한다.
파드 P는 반드시 "지정된 노드"로 스케줄링되지는 않는다.
The scheduler always tries the "nominated Node" before iterating over any other nodes.
스케줄러는 다른 노드에 스케줄링을 시도하기 전에 항상 "지정된 노드"부터 시도한다.
피해자 파드가 축출된 후, 그것은 정상적(graceful)으로 종료되는 기간을 갖는다.
스케줄러가 종료될 피해자 파드를 기다리는 동안 다른 노드를 사용할 수

View File

@ -54,8 +54,8 @@ profiles:
할당된 리소스의 구성된 기능에 따라 노드를 선호하게 한다. `NodeResourcesFit`점수 기능의
`RequestedToCapacityRatio` 동작은 [scoringStrategy](/docs/reference/config-api/kube-scheduler-config.v1beta3/#kubescheduler-config-k8s-io-v1beta3-ScoringStrategy)필드를
이용하여 제어할 수 있다.
`scoringStrategy` 필드에서 `requestedToCapacityRatioParam`와 `resources`라는 두 개의 파라미터를
구성할 수 있다. `requestedToCapacityRatioParam`파라미터의
`scoringStrategy` 필드에서 `requestedToCapacityRatio`와 `resources`라는 두 개의 파라미터를
구성할 수 있다. `requestedToCapacityRatio`파라미터의
`shape`를 사용하면 `utilization``score` 값을 기반으로
최소 요청 혹은 최대 요청된 대로 기능을 조정할 수 있게 한다.
`resources` 파라미터는 점수를 매길 때 고려할 리소스의 `name`
@ -77,7 +77,7 @@ profiles:
weight: 3
- name: intel.com/bar
weight: 3
requestedToCapacityRatioParam:
requestedToCapacityRatio:
shape:
- utilization: 0
score: 0

View File

@ -48,7 +48,8 @@ weight: 40
## `topologySpreadConstraints` 필드
파드 API에 `spec.topologySpreadConstraints` 필드가 있다. 예시는 다음과 같다.
파드 API에 `spec.topologySpreadConstraints` 필드가 있다. 이 필드는 다음과 같이
쓰인다.
```yaml
---
@ -60,14 +61,18 @@ spec:
# 토폴로지 분배 제약 조건을 구성한다.
topologySpreadConstraints:
- maxSkew: <integer>
minDomains: <integer> # 선택 사항이며, v1.24에서 알파 기능으로 도입되었다.
minDomains: <integer> # 선택 사항이며, v1.25에서 베타 기능으로 도입되었다.
topologyKey: <string>
whenUnsatisfiable: <string>
labelSelector: <object>
matchLabelKeys: <list> # 선택 사항이며, v1.25에서 알파 기능으로 도입되었다.
nodeAffinityPolicy: [Honor|Ignore] # 선택 사항이며, v1.25에서 알파 기능으로 도입되었다.
nodeTaintsPolicy: [Honor|Ignore] # 선택 사항이며, v1.25에서 알파 기능으로 도입되었다.
### 파드의 다른 필드가 이 아래에 오게 된다.
```
`kubectl explain Pod.spec.topologySpreadConstraints` 명령을 실행하여 이 필드에 대해 좀 더 알아볼 수 있다.
`kubectl explain Pod.spec.topologySpreadConstraints` 명령을 실행하거나 파드에 관한 API 레퍼런스의
[스케줄링](/docs/reference/kubernetes-api/workload-resources/pod-v1/#scheduling) 섹션을 참조해서 이 필드에 대해 좀 더 알아볼 수 있다.
### 분배 제약 조건 정의
@ -81,10 +86,10 @@ kube-scheduler가 어떻게 클러스터 내에서 기존 파드와의 관계를
- `whenUnsatisfiable: DoNotSchedule`을 선택했다면,
`maxSkew`는 대상 토폴로지에서 일치하는 파드 수와
_전역 최솟값(global minimum)_ (토폴로지 도메인에서 레이블 셀렉터와 일치하는 최소 파드 수)
_전역 최솟값(global minimum)_ (적절한 도메인 내에서 일치하는 파드의 최소 수, 또는 적절한 도메인의 수가 `minDomains`보다 작은 경우에는 0)
사이의 최대 허용 차이를 나타낸다.
예를 들어, 3개의 존에 각각 2, 4, 5개의 일치하는 파드가 있으면,
전역 최솟값은 2이며 시스템은 이 숫자를 `maxSkew`와 비교한다.
예를 들어, 3개의 존에 각각 2, 2, 1개의 일치하는 파드가 있으면,
`maxSkew`는 1로 설정되고 전역 최솟값은 1로 설정된다.
- `whenUnsatisfiable: ScheduleAnyway`를 선택하면,
스케줄러는 차이(skew)를 줄이는 데 도움이 되는 토폴로지에 더 높은 우선 순위를 부여한다.
@ -93,9 +98,8 @@ kube-scheduler가 어떻게 클러스터 내에서 기존 파드와의 관계를
도메인의 노드가 노드 셀렉터에 매치되면 그 도메인은 적합한 도메인이다.
{{< note >}}
`minDomains` 필드는 1.24에서 추가된 알파 필드이다.
이를 사용하려면 `MinDomainsInPodToplogySpread`
[기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 활성화해야 한다.
`minDomains` 필드는 1.25에서 기본적으로 사용하도록 설정된 베타 필드이다. 사용을 원하지 않을 경우
`MinDomainsInPodToplogySpread` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 비활성화한다.
{{< /note >}}
- `minDomains` 값을 명시하는 경우, 이 값은 0보다 커야 한다.
@ -108,10 +112,12 @@ kube-scheduler가 어떻게 클러스터 내에서 기존 파드와의 관계를
이 값은 스케줄링에 영향을 미치지 않는다.
- `minDomains`를 명시하지 않으면, 분배 제약 조건은 `minDomains`가 1이라고 가정하고 동작한다.
- **topologyKey** 는 [노드 레이블](#node-labels)의 키(key)이다.
만약 두 노드가 이 키로 레이블이 지정되고 레이블이 동일한 값을 가진다면,
스케줄러는 두 노드를 같은 토폴로지에 있는 것으로 여기게 된다.
스케줄러는 각 토폴로지 도메인에 균형잡힌 수의 파드를 배치하려고 시도한다.
- **topologyKey** 는 [노드 레이블](#node-labels)의 키(key)이다. 이 키와 동일한 값을 가진
레이블이 있는 노드는 동일한 토폴로지에 있는 것으로 간주된다.
토폴로지의 각 인스턴스(즉, <, > 쌍)를 도메인이라고 한다. 스케줄러는
각 도메인에 균형잡힌 수의 파드를 배치하려고 시도할 것이다.
또한, 노드가 nodeAffinityPolicy 및 nodeTaintsPolicy의 요구 사항을 충족하는 도메인을
적절한 도메인이라고 정의한다.
- **whenUnsatisfiable** 는 분산 제약 조건을 만족하지 않을 경우에 파드를 처리하는 방법을 나타낸다.
- `DoNotSchedule`(기본값)은 스케줄러에 스케줄링을 하지 말라고 알려준다.
@ -123,6 +129,54 @@ kube-scheduler가 어떻게 클러스터 내에서 기존 파드와의 관계를
자세한 내용은
[레이블 셀렉터](/ko/docs/concepts/overview/working-with-objects/labels/#레이블-셀렉터)를 참조한다.
- **matchLabelKeys** 는 분배도(spreading)가 계산될 파드를 선택하기 위한 파드 레이블
키 목록이다. 키는 파드 레이블에서 값을 조회하는 데 사용되며, 이러한 키-값 레이블은 `labelSelector`와 AND 처리되어 들어오는 파드(incoming pod)에 대해 분배도가 계산될 기존 파드 그룹의 선택에 사용된다. 파드 레이블에 없는 키는 무시된다. null 또는 비어 있는 목록은 `labelSelector`와만 일치함을 의미한다.
`matchLabelKeys`를 사용하면, 사용자는 다른 리비전 간에 `pod.spec`을 업데이트할 필요가 없다. 컨트롤러/오퍼레이터는 다른 리비전에 대해 동일한 `label`키에 다른 값을 설정하기만 하면 된다. 스케줄러는 `matchLabelKeys`를 기준으로 값을 자동으로 가정할 것이다. 예를 들어 사용자가 디플로이먼트를 사용하는 경우, 디플로이먼트 컨트롤러에 의해 자동으로 추가되는 `pod-template-hash`로 키가 지정된 레이블을 사용함으로써 단일 디플로이먼트에서 서로 다른 리비전을 구별할 수 있다.
```yaml
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
matchLabelKeys:
- app
- pod-template-hash
```
{{< note >}}
`matchLabelKeys` 필드는 1.25에서 추가된 알파 필드이다. 이 필드를 사용하려면
`MatchLabelKeysInPodTopologySpread` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)
를 활성화시켜야 한다.
{{< /note >}}
- **nodeAffinityPolicy**는 파드 토폴로지의 스프레드 스큐(spread skew)를 계산할 때
파드의 nodeAffinity/nodeSelector를 다루는 방법을 나타낸다. 옵션은 다음과 같다.
- Honor: nodeAffinity/nodeSelector와 일치하는 노드만 계산에 포함된다.
- Ignore: nodeAffinity/nodeSelector는 무시된다. 모든 노드가 계산에 포함된다.
옵션의 값이 null일 경우, Honor 정책과 동일하게 동작한다.
{{< note >}}
`nodeAffinityPolicy` 필드는 1.25에서 추가된 알파 필드이다. 이 필드를 사용하려면
`NodeInclusionPolicyInPodTopologySpread` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)
를 활성화시켜야 한다.
{{< /note >}}
- **nodeTaintsPolicy**는 파드 토폴로지의 스프레드 스큐(spread skew)를 계산할 때 노드 테인트(taint)를
다루는 방법을 나타낸다. 옵션은 다음과 같다.
- Honor: 테인트가 없는 노드, 그리고 노드가 톨러레이션이 있는 들어오는 파드(incoming pod)를 위한 테인트가 설정된
노드가 포함된다.
- Ignore: 노드 테인트는 무시된다. 모든 노드가 포함된다.
옵션의 값이 null일 경우, Ignore 정책과 동일하게 동작한다.
{{< note >}}
`nodeTaintsPolicy` 필드는 1.25에서 추가된 알파 필드이다. 이 필드를 사용하려면
`NodeInclusionPolicyInPodTopologySpread` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)
를 활성화시켜야 한다.
{{< /note >}}
파드에 2개 이상의 `topologySpreadConstraint`가 정의되어 있으면,
각 제약 조건은 논리 AND 연산으로 조합되며,
kube-scheduler는 새로운 파드의 모든 제약 조건을 만족하는 노드를 찾는다.
@ -557,6 +611,7 @@ profiles:
예를 들어 노드 풀(또는 노드 그룹)이 0으로 스케일 다운되고,
클러스터가 다시 스케일 업 되기를 기대하는 경우,
해당 토폴로지 도메인은 적어도 1개의 노드가 존재하기 전에는 고려가 되지 않을 것이다.
이를 극복하기 위해, 파드 토폴로지 분배 제약 조건과
전반적인 토폴로지 도메인 집합에 대한 정보를 인지하고 동작하는
클러스터 오토스케일링 도구를 이용할 수 있다.

View File

@ -136,7 +136,7 @@ Bob이 `projectCaribou` 네임스페이스에 있는 오브젝트에 쓰기(`cre
쿠버네티스 감사는 클러스터에서 발생하는 일들의 순서를 문서로 기록하여, 보안과 관련되어 있고 시간 순서로 정리된 기록을 제공한다.
클러스터는 사용자, 쿠버네티스 API를 사용하는 애플리케이션, 그리고 컨트롤 플레인 자신이 생성한 활동을 감사한다.
더 많은 정보는 [감사](/docs/tasks/debug/debug-cluster/audit/)를 참고한다.
더 많은 정보는 [감사](/ko/docs/tasks/debug/debug-cluster/audit/)를 참고한다.
## {{% heading "whatsnext" %}}

View File

@ -0,0 +1,516 @@
---
title: 멀티 테넌시(multi-tenancy)
content_type: concept
weight: 70
---
<!-- overview -->
이 페이지는 클러스터 멀티 테넌시를 구현하기 위해 유효한 구성 옵션과 모범 사례에 대한 개요를
제공한다.
클러스터 공유를 통해 비용 절감 및 운영을 간편화할 수 있다. 그러나 클러스터를 공유하게 되면
보안, 공평성, _소란스러운 이웃(noisy neighbors)_ 관리와 같이 여러 문제 상황이 발생할 수 있다.
클러스터는 다양한 방법을 통해 공유될 수 있다. 특정 경우에는 같은 클러스터 내 서로 다른 애플리케이션이 실행될 수 있다.
또 다른 경우에는 하나의 애플리케이션에서 각 엔드유저에 대한 인스턴스가 모여 여러 인스턴스가 같은 클러스터 내에서 실행될 수 있다.
이러한 모든 종류의 공유 방법은 주로
_멀티 테넌시_ 라는 포괄적 용어로 통칭한다.
쿠버네티스에서는 엔드 유저 또는 테넌트에 대한 정형화된 개념을 정해놓고 있지는 않지만,
다양한 테넌시 요구사항을 관리하기 위한 몇 가지 기능을 제공한다. 이에 대한 내용은 밑에서 다룬다.
<!-- body -->
## 유스케이스
클러스터를 공유하기 위해 고려해야 하는 첫 번째 단계는,
사용 가능한 패턴과 툴을 산정하기 위해 유스케이스를 이해하는 것이다. 일반적으로 쿠버네티스에서의 멀티 테넌시는
다양한 형태로 변형 또는 혼합이 가능하지만, 넓게는 두 가지 범주로 분류된다.
### 다수의 팀
흔히 사용하는 멀티 테넌시의 형태는 하나 또는 그 이상의 워크로드를
운영하는 한 조직 소속의 여러 팀이 하나의 클러스터를 공유하는 형태이다. 이러한 워크로드는
같은 클러스터 내외의 다른 워크로드와 잦은 통신이 필요하다.
이러한 시나리오에서 팀에 속한 멤버는 보통 `kubectl`과 같은 툴을 통해 쿠버네티스 리소스에 직접적으로 접근하거나,
GitOps 컨트롤러 혹은 다른 종류의 배포 자동화 툴을 통해 간접적으로 접근한다.
대개는 다른 팀 멤버 간에 일정량의 신뢰가 형성되어 있지만,
안전하고 공평한 클러스터 공유를 위해서는
RBAC, 쿼터(quota), 네트워크 정책과 같은 쿠버네티스 정책이 필수이다.
### 다수의 고객
다른 주요 멀티 테넌시 형태로는 서비스형소프트웨어(SaaS) 사업자가
여러 고객의 워크로드 인스턴스를 실행하는 것과 관련이 있다.
이러한 비즈니스 모델은 많은 이들이 "SaaS 테넌시"라고 부르는 배포 스타일과 밀접한 연관이 있다.
그러나 SaaS 사업자는 다른 배포 모델을 사용할 수 있기도 하며 SaaS가 아니어도 이러한 배포 모델의 적용이 가능하기 때문에,
"다중 고객 테넌시(multi-customer tenancy)"를 더 적합한 용어로 볼 수 있다.
고객은 이러한 시나리오에서 클러스터에 대한 접근 권한을 가지지 않는다. 쿠버네티스는 그들의
관점에서는 보이지 않으며, 사업자가 워크로드를 관리하기 위해서만 사용된다. 비용 최적화는
주로 중대한 관심사가 되며,
워크로드 간의 확실한 격리를 보장하기 위해 쿠버네티스 정책이 사용된다.
## 용어
### 테넌트
쿠버네티스에서의 멀티 테넌시를 논할 때는,
"테넌트(tenant)"를 하나의 의미로 해석할 수 없다.
오히려 다중 팀 혹은 다중 고객 테넌시의 여부에 따라 테넌트의 정의는 달라진다.
다중 팀 사용(multi-team usage)에서의 테넌트는 일반적으로 하나의 팀을 의미하며,
이 팀은 일반적으로 서비스의 복잡도에 따라 스케일 하는 작은 양의 워크로드를 다수 배포한다.
그러나 "팀" 자체에 대한 정의도 상위 조직으로
구성될 수 있기도 하고 작은 팀으로 세분화될 수 있기 때문에 정의가 모호할 수 있다.
반대로 각 팀이 새로운 고객에 대한 전용 워크로드를 배포하게 된다면,
다중 고객 테넌시 모델을 사용한다고 볼 수 있다. 이와 같은 경우에서는,
"테넌트"는 하나의 워크로드를 공유하는 사용자의 집합을 의미한다.
이는 하나의 기업만큼 큰 규모일 수도 있고, 해당 기업의 한 팀 정도의 작은 규모일수도 있다.
같은 조직이 "테넌트"에 대한 두 개의 정의를 서로 다른 맥락에서 사용할 수 있는 경우가 많다.
예를 들어, 플랫폼 팀은 다수의 내부 "고객"을 위해 보안 툴 및 데이터베이스와 같은 공유된 서비스를 제공할 수 있고,
SaaS 사업자는 공유된 개발 클러스터를 다수의 팀에게 제공할 수 있다.
마지막으로, SaaS 제공자는 민감한 데이터를 다루는 고객별 워크로드와
공유된 서비스를 다루는 멀티 테넌트를 혼합하여 제공하는 하이브리드 구조도
사용이 가능하다.
{{< figure src="/images/docs/multi-tenancy.png" title="공존하는 테넌시 모델을 나타내고 있는 클러스터" class="diagram-large" >}}
### 격리
쿠버네티스에서 멀티 테넌트 솔루션을 설계하고 빌드 하는 방법은 몇 가지가 있다.
각 방법은 격리 수준, 구현 비용, 운영 복잡도, 서비스 비용에
영향을 미치는 각자만의 상충 요소를 가지고 있다.
각 쿠버네티스 클러스터는 쿠버네티스 소프트웨어를 실행하는 컨트롤 플레인과
테넌트의 워크로드가 파드의 형태로 실행되고 있는 워커 노드로 구성된 데이터 플레인으로 구성되어 있다.
테넌트 격리는 조직의 요구사항에 따라 컨트롤 플레인 및 데이터 플레인 모두에 대해 적용할 수 있다.
제공되는 격리의 수준은 강한 격리를 의미하는 "하드(hard)" 멀티 테넌시와
약한 격리를 의미하는 "소프트(soft)" 멀티 테넌시와 같은 용어를 통해 정의한다.
특히 "하드" 멀티 테넌시는 주로 보안이나 리소스 공유 관점(예를 들어, 데이터 유출 및 DoS 공격에 대한 방어)에서
테넌트가 서로 신뢰하지 않는 상황을 설명할 때 주로 사용한다.
데이터 플레인은 일반적으로 더 큰 공격 영역을 가지고 있기 때문에,
컨트롤 플레인 격리 또한 중요하지만 데이터 플레인을 격리하는 데 있어서
"하드" 멀티 테넌시는 추가적인 주의를 요구한다.
그러나 모든 사용자에게 적용할 수 있는 하나의 정의가 없기 때문에,
"하드"와 "소프트" 용어에 대한 혼동이 생길 수 있다.
오히려 요구사항에 따라 클러스터 내에서 다양한 종류의 격리를 유지할 수 있는 다양한 기법을 다루는 "하드한 정도"
혹은 "소프트한 정도"가 넓은 범위에서는 이해하기에 편하다.
극단적인 경우에는 클러스터 레벨의 공유를 모두 포기하고 각 테넌트에 대한 전용 클러스터를 할당하거나,
가상머신을 통한 보안 경계가 충분하지 않다고 판단될 시에는
전용 하드웨어에서 실행하는 것이 쉽고 적절한 방법일 수 있다.
클러스터를 생성하고 운영하는데 필요한 오버헤드를 클라우드 공급자가 맡게 되는
매니지드 쿠버네티스 클러스터에서는 이와 같은 방식을 사용하기에 더 쉬울 수 있다.
강한 테넌트 격리의 장점은 여러 클러스터를 관리하는데 필요한 비용과 복잡도와 비교하여 산정되어야 한다.
[멀티 클러스터 SIG](https://git.k8s.io/community/sig-multicluster/README.md)는 이러한 종류의 유스케이스를 다루는 작업을 담당한다.
이 페이지의 남은 부분에서는 공유 쿠버네티스 클러스터에서 사용되는 격리 기법을 중점적으로 다룬다.
그러나 전용 클러스터를 고려하고 있다 하더라도, 요구사항 혹은 기능에 대한 변화가 생겼을 때
공유 클러스터로 전환할 수 있는 유연성을 제공할 수 있기 때문에,
이러한 권고사항을 검토해 볼 가치가 있다.
## 컨트롤 플레인 격리
컨트롤 플레인 격리는 서로 다른 테넌트가 서로의 쿠버네티스 API 리소스에
대한 접근 및 영향을 미치지 못하도록 보장한다.
### 네임스페이스
쿠버네티스에서 {{< glossary_tooltip text="네임스페이스" term_id="namespace" >}}는
하나의 클러스터 내에서 API 리소스 그룹을 격리하는 데 사용하는 기능이다.
이러한 격리는 두 가지 주요 특징을 지닌다.
1. 네임스페이스 내의 오브젝트 이름은 폴더 내의 파일과 유사하게 다른 네임스페이스에 속한
이름과 중첩될 수 있다. 이를 통해 각 테넌트는 다른 테넌트의 활동과 무관하게 자신의
리소스에 대한 이름을 정할 수 있다.
2. 많은 쿠버네티스 보안 정책은 네임스페이스 범위에서 사용한다. 예를 들어, RBAC 역할과
네트워크 정책은 네임스페이스 범위의 리소스이다. RBAC를 사용함으로써 사용자 및 서비스
어카운트는 하나의 네임스페이스에 대해 제한될 수 있다.
멀티 테넌트 환경에서의 각 네임스페이스는 테넌트의 워크로드를 논리적이고 구별되는 관리
단위로 분할할 수 있다. 실제로 일반적인 관습에서는 여러 워크로드가 하나의 테넌트에 의해
운영되더라도, 각 워크로드를 개별 네임스페이스로 격리한다. 이를 통해 각 워크로드는 개별
정체성을 가질 수 있으며 적절한 보안 정책을 적용 받을 수 있게끔 보장한다.
네임스페이스 격리 모델은 테넌트 워크로드를 제대로 격리 시키기 위해 몇 가지 다른
쿠버네티스 리소스, 네트워크 플러그인, 보안 모범 사례에 대한 준수가 필요하다. 이와 같이
고려해야 하는 사항은 아래에 명시되어 있다.
### 접근 제어
컨트롤 플레인에서의 가장 중요한 격리 방식은 인증이다. 만일 팀 또는 해당 팀의 워크로드가
서로 다른 API 리소스에 대한 접근 및 수정이 가능하다면, 다른 종류의 정책을 모두 바꾸거나
비활성화할 수 있게 되어 해당 정책이 제공하는 보호를 무효화한다. 따라서 각 테넌트가 필요로
하는 네임스페이스에 대한 적절한 최소의 권한만을 부여하는 것이 중요하다. 이는 "최소 권한의
원칙(Principle of Least Privilege)"이라고 부른다.
역할 기반 접근 제어(RBAC)는 흔히 쿠버네티스 컨트롤 플레인에서의 사용자와 워크로드에
(서비스 어카운트) 대한 인증을 시행하기 위해 사용된다.
[롤(Roles)](/docs/reference/access-authn-authz/rbac/#role-and-clusterrole)과
[롤바인딩(RoleBindings)](/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding)은 네임스페이스 레벨에서 애플리케이션의
접근 제어를 시행하기 위해 사용되는 쿠버네티스 오브젝트이다.
클러스터 레벨의 오브젝트에 대한 접근 권한을 인증하기 위해 사용되는 유사한 오브젝트도 존재하지만, 이는 멀티 테넌트 클러스터에서는 비교적 유용성이 떨어진다.
다중 팀 환경에서는, 클러스터 전범위 리소스에 대해 클러스터 운영자와 같이 특권을 가진
사용자에 의해서만 접근 또는 수정이 가능하도록 보장하기 위해 RBAC를 사용하여 테넌트의
접근을 적합한 네임스페이스로 제한해야 한다.
만일 사용자에게 필요 이상으로 권한을 부여하는 정책이 있다면, 이는 영향 받는 리소스를
포함하고 있는 네임스페이스가 더 세분화된 네임스페이스로 재구성 되어야 한다는 신호일
가능성이 높다. 네임스페이스 관리 툴을 통해 공통된 RBAC 정책을 서로 다른 네임스페이스에
적용하고 필요에 따라 세분화된 정책은 허용하며, 세분화된 네임스페이스를
간편하게 관리할 수 있다.
### 쿼터
쿠버네티스 워크로드는 CPU 및 메모리와 같은 노드 리소스를 소모한다. 멀티 테넌트 환경에서는,
테넌트 워크로드의 리소스 사용량을 관리하기 위해 [리소스 쿼터](/ko/docs/concepts/policy/resource-quotas/)를 사용할 수 있다.
테넌트가 쿠버네티스 API에 대한 접근 권한을 가지는 다수 팀 유스케이스의 경우에는,
테넌트가 생성할 수 있는 API 리소스(예를 들어, 파드의 개수 혹은 컨피그맵의 개수)의
개수를 리소스 쿼터를 사용하여 제한할 수 있다.
오브젝트 개수에 대한 제한은 공평성을 보장하고 같은 컨트롤 플레인을 공유하는 테넌트 간 침범이 발생하는
_소란스러운 이웃_ 문제를 예방하기 위한 목적을 가지고 있다.
리소스 쿼터는 네임스페이스 오브젝트이다. 테넌트를 네임스페이스에 대해 매핑함으로써,
클러스터 운영자는 쿼터를 사용하여 하나의 테넌트가 클러스터의 리소스를 독점하거나 컨트롤
플레인을 압도하지 못하도록 보장할 수 있다. 네임스페이스 관리 툴은 쿼터 운영을
간편화해준다. 이에 더해 쿠버네티스 쿼터는 하나의 네임스페이스 내에서만 적용이 가능하지만,
특정 네임스페이스 관리 툴은 네임스페이스 그룹이 쿼터를 공유할 수 있도록 허용함으로써
운영자에게 내장된 쿼터에 비해 적은 수고로 더 많은 유연성을 제공한다.
쿼터는 하나의 테넌트가 자신에게 할당된 몫의 리소스 보다 많이 사용하는 것을 방지하며, 이를
통해 하나의 테넌트가 다른 테넌트의 워크로드 성능에 부정적 영향을 미치는 "소란스러운 이웃"
문제를 최소화할 수 있다.
쿠버네티스에서 네임스페이스에 대한 쿼터를 적용할 시에는 각 컨테이너에 대한 리소스 요청과
제한을 명시하도록 요구한다. 제한은 각 컨테이너가 소모할 수 있는 리소스의 양에 대한
상한선이다. 설정된 제한을 초과하여 리소스 소모를 시도하는 컨테이너는 리소스의 종류에 따라
스로틀(throttled)되거나 종료(killed)된다. 리소스 요청이 제한보다 낮게 설정되었을 시에는,
각 컨테이너가 요청한 리소스의 양은 보장되지만
워크로드 간의 영향이 있을 가능성은 존재한다.
쿼터는 네트워크 트래픽과 같이 모든 종류의 리소스 공유에 대한 보호는 할 수 없다.
노드 격리(아래에서 설명)가 이러한 문제에 대해서는 더 나은 해결책일 수 있다.
## 데이터 플레인 격리
데이터 플레인 격리는 다른 테넌트의 파드 및 워크로드와 충분히 격리가 이루어질 수 있도록
보장한다.
### 네트워크 격리
기본적으로 쿠버네티스 클러스터의 모든 파드는 서로 통신을 할 수 있도록 허용되어 있으며 모든
네트워크 트래픽은 암호화되어 있지 않다. 이는 트래픽이 실수 또는 악의적으로 의도되지 않은
목적지로 전송되거나 신뢰가 손상된(compromised) 노드 상의 워크로드에 의해 가로채지는 것과
같은 보안 취약점으로 이어질 수 있다.
파드에서 파드로의 통신은 네임스페이스 레이블 혹은 IP 주소 범위를 통해 파드 간의 통신을
제한하는 [네트워크 정책](/ko/docs/concepts/services-networking/network-policies/)에
의해 제어될 수 있다. 테넌트 간의 엄격한 네트워크 격리가 필요한 멀티 테넌트 환경에서는,
파드 간의 통신을 거부하는 기본 정책과 모든 파드가 네임 해석(name resolution)을 위해
DNS 서버를 쿼리하도록 하는 규칙을 시작에 설정하는 것을 권고한다. 이러한 기본 정책을
기반으로 하여, 네임스페이스 내에서 통신을 허용하는 관대한 규칙을 추가할 수 있다. 이러한
방식은 요구에 따라 한 단계 더 정제할 수 있다. 이는 하나의 컨트롤 플레인 내의 파드에
대해서만 적용된다는 것을 알아두어야 한다. 서로 다른 가상의 컨트롤 플레인에 소속된 파드는
쿠버네티스 네트워킹을 통해 통신할 수 없다.
네임스페이스 관리 툴을 통해 기본 또는 공통 네트워크 정책을 간편하게 생성할 수 있다. 이에
더해, 몇 가지 툴은 클러스터 상에서 일관된 집합의 네임스페이스 레이블을 사용할 수 있게
함으로써 정책에 대한 신뢰 가능한 기반이 마련될 수 있도록 보장한다.
{{< warning >}}
네트워크 정책은 구현 과정에서 지원되는 [CNI 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#cni)을 요구한다.
만일 그렇지 않으면, 네트워크폴리시 리소스는 무시된다.
{{< /warning >}}
추가적으로, 서비스 메쉬(service mesh)는 워크로드 특징에 따른 OSI 7 계층 정책을
제공하므로 네임스페이스보다 더 고도의 네트워크 격리를 제공할 수 있다. 이러한 상위 정책은 특히
하나의 테넌트에 대한 여러 네임스페이스가 있는 경우와 같이, 네임스페이스 기반 멀티 테넌시를
더욱 쉽게 관리할 수 있도록 한다. 신뢰가 손상된(compromised) 노드가 발생했을 시에도 데이터를 보호할 수
있는 상호 간의 TLS을 통해 암호화도 제공하며 전용 또는 가상의 클러스터 사이에서도
동작한다. 그러나 관리하기에 더 복잡할 수 있으며 모든 사용자에게 적합한 방법이 아닐 수 있다.
### 스토리지 격리
쿠버네티스는 워크로드가 퍼시스턴트 스토리지로 사용할 수 있는 몇 가지 종류의 볼륨을
제공한다. 보안 및 데이터 격리를 위해서는 [동적 볼륨 프로비저닝](/ko/docs/concepts/storage/dynamic-provisioning/)을
권고하며 노드 리소스를 사용하는 볼륨 타입은 피해야 한다.
[스토리지 클래스](/ko/docs/concepts/storage/storage-classes/)는 클러스터에
제공하는 사용자 정의 "클래스"를 서비스 품질 수준(quality-of-service level), 백업 정책 혹은 클러스터 운영자에 의해
결정된 사용자 정의 정책을 기반으로 명시할 수 있도록 허용한다.
파드는 [퍼시스턴트 볼륨 클레임](/ko/docs/concepts/storage/persistent-volumes/)을
통해 스토리지를 요청할 수 있다. 퍼시스턴트 볼륨 클레임은 공용 쿠버네티스 클러스터 내에서
스토리지 시스템의 부분 단위 격리를 가능하게끔 하는 네임스페이스 리소스이다. 그러나
퍼시스턴트 볼륨은 클러스터 전범위(cluster-wide)의 리소스이며 워크로드와 네임스페이스의 라이프사이클에
독립적이므로, 이를 염두에 둘 필요가 있다.
예를 들어, 각 테넌트에 대한 별도의 스토리지 클래스를 설정할 수 있으며 이를 통해 격리를 강화할 수 있다.
만일 스토리지 클래스가 공유된다면, [`Delete` 리클레임(reclaim) 정책](/ko/docs/concepts/storage/storage-classes/#리클레임-정책)을 설정하여
퍼시스턴트 볼륨이 다른 네임스페이스에서 재사용되지 못하도록 보장해야 한다.
### 컨테이너 샌드박싱(sandboxing)
{{% thirdparty-content %}}
쿠버네티스 파드는 워커 노드 상에서 실행되는 하나 또는 그 이상의 컨테이너로 구성되어 있다.
컨테이너는 OS 레벨의 가상화를 활용하기 때문에 하드웨어 기반의 가상화를 활용하는
가상 머신에 비해 격리의 경계가 약하다.
공유 환경에서 애플리케이션 및 시스템 계층 상 패치되지 않은 취약점은
컨테이너 탈출(container breakout) 또는 원격 코드 실행과 같이 호스트 리소스에 대한
접근을 허용하여 공격자에 의해 악용될 수 있다. 컨텐츠 매니지먼트 시스템(CMS)과 같은 특정
애플리케이션에서는, 고객이 신뢰되지 않은 스크립트 및 코드를 업로드할 수 있는 기능이 허용될 수 있다.
어떤 경우이든, 강한 격리를 통해 워크로드를 한 단계 더 격리하고 보호하기 위한 기능은 필요하다.
샌드박싱은 공유 클러스터에서 실행되는 워크로드를 격리하는 방법을 제공한다. 일반적으로 각
파드를 가상 머신 또는 유저스페이스 커널(userspace kernel)과 같은 별도의 실행 환경에서 실행하는 것과 연관이
있다. 샌드박싱은 주로 워크로드가 악의적으로 판단되는 신뢰되지 않은 코드를 실행할 때
권고된다. 이러한 격리가 필요한 이유는 컨테이너가 공유된 커널에서 실행되기 때문이다.
컨테이너는 하위 호스트의 `/sys``/proc` 와 같은 파일 시스템을 마운트 하기 때문에,
개별 커널을 가지는 가상 머신에서 실행되는 애플리케이션과 비교하였을 때는 보안성이 낮다.
Seccomp, AppArmor, SELinux와 같은 제어를 통해 컨테이너의 보안을 강화할 수 있지만,
공유 클러스터에서 실행되고 있는 모든 워크로드에 대해 공통된 규칙을 적용하는 데는 어려움이
있다. 워크로드를 샌드박스 환경에서 실행함으로써, 공격자가 호스트의 취약점을 악용하여
호스트 시스템 및 해당 호스트에서 실행되고 있느 모든 프로세스와 파일 대한 권한을 얻을 수
있는 컨테이너 탈출로 부터 호스트를 보호할 수 있다.
가상 머신 및 유저스페이스 커널은 샌드박싱을 제공하는 대표적인 두 가지 방법이다.
다음과 같은 샌드박싱 구현이 가능하다.
* [gVisor](https://gvisor.dev/)는 컨테이너로부터 시스템 호출을 가로채 Go로 작성된
유저스페이스 커널을 통해 실행하므로, 컨테이너가 호스트 내부(underlying host)에 대한 제한적인 접근 권한만 가진다.
* [Kata 컨테이너](https://katacontainers.io/)는 OCI에 부합하는 런타임으로 가상 머신 내에서
컨테이너가 실행되도록 한다. Kata는 하드웨어 가상화를 통해, 신뢰되지 않은
코드를 실행하는 컨테이너에 대해 추가적인 보안 계층을 제공한다.
### 노드 격리
노드 격리는 테넌트 워크로드를 서로 격리시킬 수 있는 또 다른 기법이다. 노드 격리를 통해
하나의 노드 집합은 특정 테넌트의 파드를 전용으로 실행할 수 있으며 테넌트 파드 간의 혼합(co-mingling)은
금지되어 있다. 이러한 구성을 사용하게 되면 노드 상에서 실행되는 파드가 모두 하나의 테넌트
소유이기 때문에 소란스러운 테넌트 문제를 줄일 수 있다. 컨테이너 탈출에 성공한 공격자가
있다 하더라도, 해당 노드의 컨테이너 및 마운트 된 볼륨에 대해서만 접근 권한을 가지므로,
노드 격리를 통해 정보 유출의 위험도 비교적 감소한다.
다른 테넌트의 워크로드가 다른 노드에서 실행되고 있다 하더라도, Kubelet과 (가상 컨트롤
플레인을 사용하지 않는 한) API 서비스는 여전히 공유되고 있다는 사실을 이해하는 것은 중요하다.
능숙한 공격자는 Kubelet 또는 노드에서 실행되고 있는 다른 파드에 부여된 권한을 이용하여
클러스터 내에서 좌우로 이동하며 다른 노드에서 실행되고 있는 테넌트 워크로드에 대한 접근
권한을 얻을 수 있다. 만일 이러한 사항이 우려된다면, seccomp, AppArmor, SELinux와 같은
제어 방식을 이용하거나, 샌드박스 컨테이너 이용 또는 각 테넌트에 대한 개별 클러스터를
생성하는 방안을 검토해 보아야 한다.
노드 격리를 통해 파드가 아닌 노드 별 비용을 청구할 수 있으므로, 비용 관점에서는 샌드박스 컨테이너에
비해 이해 및 파악이 수월하다. 또한 호환성 및
성능 문제 발생 가능성이 낮으며 샌드박스 컨테이너 보다 구현도 더 쉬운 편이다. 예를 들어, 각
테넌트에 대한 노드는 대응하는 톨러레이션(toleration)을 가진 파드만 실행할 수 있도록 테인트(taint)를 통해
설정할 수 있다. 변화하는 웹훅을 통해 자동으로 톨러레이션과 노드 어피니티를 테넌트
네임스페이스에 배포된 파드에 추가하여, 해당 파드를 특정 테넌트를 위해 지정된 특정 노드의
집합에서 실행될 수 있도록 한다.
노드 격리는 [파드 노드 셀렉터](/ko/docs/concepts/scheduling-eviction/assign-pod-node/)
또는 [가상 Kubelet(Virtual Kubelet)](https://github.com/virtual-kubelet)을 통해 구현할 수 있다.
## 추가적인 고려 사항
해당 섹션에서는 멀티 테넌시와 연관 있는 이외의 쿠버네티스 구성 및 패턴에 대한 내용을 다룬다.
### API 우선순위와 공평성
[API 우선순위(priority)와 공평성(fairness)](/docs/concepts/cluster-administration/flow-control/)은
쿠버네티스의 기능 중 하나로, 클러스터 내 실행 중인 특정 파드에 대해 우선순위를 부여할 수
있다. 애플리케이션이 쿠버네티스 API를 호출하게 되면, API 서버는 해당 파드에 부여된
우선순위를 산정한다. 더 높은 우선순위를 가진 파드의 호출은 낮은 우선순위를 가진 파드의
호출보다 먼저 수행된다. 경합률(contention)이 높을 시에는 낮은 우선순위의 호출은 서버 리소스가 한가해질
때까지 대기하거나 해당 요청을 거부할 수 있다.
고객이 쿠버네티스 API와 상호작용하는 애플리케이션(예를 들어, 컨트롤러)을 실행하지 않은 한,
SaaS 환경에서 API 우선순위와 공평성을 사용하는 일은
흔치 않을 것이다.
### 서비스 품질(QoS) {#qos}
SaaS 애플리케이션을 실행할 시에는, 각 테넌트에게 다른 수준의 서비스 품질 티어(tier)를
제공하는 기능이 필요할 수 있다. 예를 들어, 낮은 성능 및 기능을 보장하는 무료 서비스와 특정
수준의 성능을 보장하는 유료 서비스를 제공할 수 있다. 다행히 쿠버네티스는 이러한 티어를 공유 클러스터
내에서 구현하기 위한 네트워크 QoS, 스토리지 클래스, 파드 우선순위 및 선점과 같은
몇 가지 구성들을 제공한다. 이는 각 테넌트가 지불한 비용에 적합한 서비스 품질을
제공하기 위한 목적이다.
우선 네트워크 QoS에 대해 먼저 살펴본다.
일반적으로 하나의 노드에 위치한 모든 파드는 네트워크 인터페이스를 공유한다. 네트워크
QoS 없이는, 몇 개의 파드가 가용 대역폭 중 다른 파드의 대역폭까지
소모하여 불공평한 공유를 야기할 수 있다.
쿠버네티스 [대역폭 플러그인](https://www.cni.dev/plugins/current/meta/bandwidth/)은
리눅스 tc 큐를 이용하여 파드에 비율 제한을 적용할 수 있는 쿠버네티스 리소스 구성(예를 들어, 요청/제한)을 사용 가능하게 하는 네트워킹
[확장 리소스](/ko/docs/concepts/configuration/manage-resources-containers/#확장된-리소스)를 생성한다.
[네트워크 플러그인](/ko/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#support-traffic-shaping)
문서에 따르면 해당 플러그인은 아직은 실험 목적으로 사용되고 있다는 점에 대한 주의가
필요하며 프로덕션 환경에서 사용하기 전에는 철저한 테스트가 이루어져야 한다.
스토리지 서비스 품질과 같은 경우에는, 각 성능 특징을 나타내기 위해 서로 다른 스토리지
클래스 또는 프로필을 생성할 필요가 있다. 각 스토리지 프로필은 IO, 중복성, 처리량과 같이
서로 다른 워크로드에 최적화된 티어의 서비스와 묶을 수 있다. 테넌트가 자신의 워크로드에
적합한 스토리지 프로필을 적용하기 위해서는
추가적인 로직이 필요할 수 있다.
마지막으로, 파드에 우선순위 값을 부여할 수 있는
[파드 우선순위와 선점](/ko/docs/concepts/scheduling-eviction/pod-priority-preemption/)이 있다.
파드 스케줄링 시에 우선순위가 높은 파드를 스케줄링하기 위한 리소스가 부족하다면,
스케줄러는 낮은 우선순위의 파드에 대한 축출을 시도한다. 공유 클러스터 내에서 다른 서비스
티어(예를 들어, 무료 및 유료)를 사용하는 테넌트를 가진 유스케이스가 있다면, 이러한 기능을
활용하여 특정 티어에 더 높은 우선순위를 부여할 수 있다.
### DNS
쿠버네티스 클러스터는 네임과 IP 주소 간의 변환을 제공하기 위해 모든 서비스와 파드에서
도메인 네임 시스템(DNS) 서비스를 포함하고 있다. 기본적으로 쿠버네티스 DNS 서비스를 통해
클러스터 내 모든 네임스페이스를 조회할 수 있다.
테넌트가 파드 및 다른 쿠버네티스 리소스에 접근할 수 있거나,
더욱 강력한 격리가 필요한 멀티 테넌트 환경에서는
파드가 다른 네임스페이스의 서비스를 조회하는 것을 막는 것이 적절할 수 있다.
네임스페이스 교차 DNS 조회(cross-namespace DNS lookup)는 DNS 서비스의 보안 규칙 설정을 통해 제한할 수 있다.
예를 들어, CoreDNS(쿠버네티스 기본 DNS 서비스)는 쿠버네티스 메타데이터를 이용하여 네임스페이스 내의 파드 및 서비스에 대한 쿼리를 제한할 수 있다.
추가적인 정보는
CoreDNS 문서에 포함된 해당 사항을 설정하는
[예시](https://github.com/coredns/policy#kubernetes-metadata-multi-tenancy-policy)에서 확인할 수 있다.
[테넌트 별 가상 컨트롤 플레인](#테넌트-별-가상-컨트롤-플레인) 모델이 사용될 시에는,
테넌트 별 DNS 서비스가 설정하거나 멀티 테넌트 DNS 서비스를 사용해야 한다.
[CoreDNS 사용자 맞춤 버전](https://github.com/kubernetes-sigs/cluster-api-provider-nested/blob/main/virtualcluster/doc/tenant-dns.md)은
멀티 테넌트를 지원하는 하나의 예시이다.
### 오퍼레이터
[오퍼레이터](/ko/docs/concepts/extend-kubernetes/operator/)는
애플리케이션을 관리하는 쿠버네티스 컨트롤러이다. 오퍼레이터는 데이터베이스 서비스와
유사하게 애플리케이션의 여러 인스턴스를 간편하게 관리할 수 있어, 다중 소비자 (SaaS) 멀티
테넌시 유스케이스의 중요한 기반이 된다.
멀티 테넌트 환경에서 사용되는 오퍼레이터는 더욱 엄격한 가이드라인을 준수해야 한다.
다음은 오퍼레이터가 지켜야 할 사항이다.
* 오퍼레이터가 배포된 네임스페이스뿐만 아니라,
다른 테넌트 네임스페이스에서의 리소스 생성도 지원해야 한다.
* 스케줄링과 공평성을 보장하기 위해, 파드에 대한 리소스 요청 및 제한을 설정한다.
* 파드에서 노드 격리 및 샌드박스 컨테이너와 같은 데이터 플레인 격리 기법을 설정할 수
있도록 지원한다.
## 구현
{{% thirdparty-content %}}
멀티 테넌시를 위해 쿠버네티스 클러스터를 공유하는 대표적인 방법은 두 가지가 있으며,
이는 네임스페이스 사용 (테넌트 별 네임스페이스) 또는 컨트롤 플레인 가상화 (테넌트 별 가상
컨트롤 플레인)이다.
두 경우 모두 데이터 플레인 격리와 API 우선순위 및 공평성과 같은 추가적인 고려 사항에 대한
관리를 권고한다.
네임스페이스 격리는 쿠버네티스에서 지원이 잘 이루어지고 있으며, 아주 적은 리소스 비용을
소모하며 서비스 간의 통신과 같은 테넌트가 상호작용하기 위한 기능을 제공한다. 그러나
설정하는 과정이 복잡하며 커스텀 리소스 데피니션 정의, 스토리지 클래스, 웹훅과 같이
네임스페이스 적용을 받지 않은 쿠버네티스 리소스에 대해서는 적용되지 않는다.
컨트롤 플레인 가상화는 더 많은 리소스 사용량과 더 어려운 테넌트 교차 공유(cross-tenant sharing)를 대가로,
네임스페이스 되지 않은 리소스에 대한 격리 기능을 제공한다.
네임스페이스 격리로는 충분하지 않으며 높은 운영 비용 (특히 온 프레미스)
또는 큰 오버헤드와 리소스 공유의 부재로 인한 전용 클러스터는 사용하지 못할 때 좋은 선택지다.
그러나, 가상 컨트롤 플레인을 사용하더라도 네임스페이스를
같이 사용하면 이익을 볼 수 있다.
두 가지의 옵션은 다음 섹션에서 상세히 다룬다.
### 테넌트 별 네임스페이스
이전에 언급하였듯이, 전용 클러스터 또는 가상 컨트롤 플레인을 사용하더라도 각 워크로드를
개별 네임스페이스로 격리하는 것을 고려해 보아야 한다.
이를 통해 각 워크로드는 컨피그맵 및 시크릿과 같이 자신의 리소스에만 접근할 수 있으며
각 워크로드에 대한 전용 보안 정책을 조정할 수 있다.
추가적으로, 전용 및 공유 클러스터 간 전환 혹은 서비스 메쉬와 같은 멀티
클러스터 툴을 이용할 수 있는 유연성을 제공받기 위해 각 네임스페이스 이름을 전체 클러스터
무리 사이에서도 고유하게 짓는 것이 (즉, 서로 다른 클러스터에 위치하더라도) 모범 사례이다.
반대로 워크로드 레벨이 아닌, 하나의 테넌트가 소유한 모든 워크로드에 대해 적용되는 정책도
있기 때문에 테넌트 레벨에서의 네임스페이스 적용도 장점이 있다. 그러나 이는 또 다른 문제를
제기한다. 첫 번째로 개별 워크로드에 대한 맞춤 정책을 적용하는 것이 어렵거나 불가능해지며,
두 번째로는 네임스페이스를 적용받을 하나의 "테넌시" 레벨을 정하는 것이 어려울 수 있다.
예를 들어, 하나의 조직에 부서, 팀, 하위 팀이 있다고 하면 어떤 단위에 대해
네임스페이스를 적용해야 하는가?
이러한 문제의 해결책으로, 네임스페이스를 계층으로 정리하고 특정 정책 및 리소스를 사이에서
공유할 수 있는 [계층적 네임스페이스 컨트롤러(HNC)](https://github.com/kubernetes-sigs/hierarchical-namespaces)를
쿠버네티스에서 제공하고 있다. 또한 네임스페이스 레이블 관리, 네임스페이스 라이프사이클,
관리 위임, 관련된 네임스페이스 사이에서 리소스 쿼터 공유와 같은 이점도 있다. 이러한
기능은 다중 팀 및 다중 고객 시나리오에서도 유용하다.
유사한 기능을 제공하며 네임스페이스 리소스 관리를 돕는 다른 프로젝트는
다음과 같다.
#### 다중 팀 테넌시
* [Capsule](https://github.com/clastix/capsule)
* [Kiosk](https://github.com/loft-sh/kiosk)
#### 다중 고객 테넌시
* [Kubeplus](https://github.com/cloud-ark/kubeplus)
#### 정책 엔진
정책 엔진은 테넌트 구성을 생성하고 검증하는 기능을 제공한다.
* [Kyverno](https://kyverno.io/)
* [OPA/Gatekeeper](https://github.com/open-policy-agent/gatekeeper)
### 테넌트 별 가상 컨트롤 플레인
컨트롤 플레인 격리의 또 다른 형태로는 쿠버네티스 확장을 이용하여 클러스터 전범위의 API
리소스를 세분화할 수 있는, 각 테넌트에 가상 컨트롤 플레인을 제공하는 형태이다.
[데이터 플레인 격리](#데이터-플레인-격리) 기법을 이러한 모델과 함께 이용하여 테넌트
간의 워커 노드를 안전하게 관리할 수 있다.
가상 컨트롤 플레인 기반의 멀티 테넌시 모델은 각 테넌트에게 전용 컨트롤 플레인 요소를
제공하며 클러스터 전범위 리소스 및 애드온 서비스에 대한 완전한 제어를 부여하게 되어
네임스페이스 기반 멀티 테넌시를 확장한다. 워커 노드는 모든 테넌트 간 공유 되며,
일반적으로 테넌트에 의해 접근이 불가능한 쿠버네티스 클러스터에 의해 관리된다.
이러한 클러스터를 _슈퍼 클러스터_ (혹은 _호스트 클러스터_)라고 부른다.
테넌트의 컨트롤 플레인은 하위 컴퓨팅 리소스와 직접적으로 연결된 것이 아니기 때문에
_가상 컨트롤 플레인_ 이라고 부른다.
가상 컨트롤 플레인은 일반적으로 쿠버네티스 API 서버, 컨트롤러 매니저, etcd 데이터
스토어로 구성되어 있다. 테넌트 컨트롤 플레인과 슈퍼 클러스터 컨트롤 플레인 간 변화를
조정하는 메타데이터 동기화 컨트롤러를 통해
슈퍼 클러스터와 상호작용한다.
하나의 API 서버를 사용하였을 때 나타나는 격리 문제는 테넌트 별 전용 컨트롤 플레인을
이용하면 해결된다. 몇 가지 예시로는, 컨트롤 플레인 내의 소란스러운 이웃 문제,
잘못된 정책 설정으로 인한 제어불능 영향 반경, 웹훅 및 CRD와 같은
클러스터 범위 오브젝트 간의 충돌이 있다.
그러므로 각 테넌트가 쿠버네티스 API 서버에 대한 접근 권한 및 완전한 클러스터 관리
기능이 필요한 경우, 가상 컨트롤 플레인 모델이 적합하다.
개선된 격리의 대가는 각 테넌트 별 가상 컨트롤 플레인을 운영하고 유지하는 비용에서
나타난다. 추가적으로, 각 테넌트 컨트롤 플레인은 노드 레벨에서의 소란스러운 이웃 문제 또는
보안 위협과 같은 데이터 플레인에서의 격리 문제를 해결하지 못한다. 이러한 문제에 대해서는
별도로 대응해야 한다.
쿠버네티스 [클러스터 API - 네스티드(CAPN)](https://github.com/kubernetes-sigs/cluster-api-provider-nested/tree/main/virtualcluster)
프로젝트는 가상 컨트롤 플레인 구현 방식을 제공한다.
#### 이외의 구현 방식
* [Kamaji](https://github.com/clastix/kamaji)
* [vcluster](https://github.com/loft-sh/vcluster)

View File

@ -58,6 +58,7 @@ IaaS 공급자 | 링크 |
Alibaba Cloud | https://www.alibabacloud.com/trust-center |
Amazon Web Services | https://aws.amazon.com/security/ |
Google Cloud Platform | https://cloud.google.com/security/ |
Huawei Cloud | https://www.huaweicloud.com/securecenter/overallsafety.html |
IBM Cloud | https://www.ibm.com/cloud/security |
Microsoft Azure | https://docs.microsoft.com/en-us/azure/security/azure-security |
Oracle Cloud Infrastructure | https://www.oracle.com/security/ |

View File

@ -1,6 +1,6 @@
---
# reviewers:
# - pweil-
# - liggitt
# - tallclair
title: 파드 시큐리티 폴리시
content_type: concept
@ -11,770 +11,19 @@ weight: 30
{{< feature-state for_k8s_version="v1.21" state="deprecated" >}}
{{< caution >}}
파드시큐리티폴리시(PodSecurityPolicy)는 쿠버네티스 v1.21부터 더 이상 사용되지 않으며, **v1.25에서 제거될 예정**이다.
[파드 시큐리티 어드미션](/docs/concepts/security/pod-security-admission/) 혹은 써드파티 어드미션 플러그인으로 대체하는 것을 권장한다.
상세 가이드는 [파드시큐리티폴리시를 파드 시큐리티 어드미션 컨트롤러로 대체하기](/docs/tasks/configure-pod-container/migrate-from-psp/)를 참조한다.
사용 중단에 대한 상세 사항은
[파드시큐리티폴리시 사용 중단: 과거, 현재, 그리고 미래](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/)를 참조한다.
{{< /caution >}}
파드 시큐리티 폴리시를 사용하면 파드 생성 및 업데이트에 대한 세분화된 권한을
부여할 수 있다.
<!-- body -->
## 파드 시큐리티 폴리시란?
_Pod Security Policy_ 는 파드 명세의 보안 관련 측면을 제어하는 클러스터-레벨의
리소스이다.
[파드시큐리티폴리시](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy) 오브젝트는
관련 필드에 대한 기본값뿐만 아니라 시스템에 적용하기 위해 파드가 실행해야만 하는
조건 셋을 정의한다.
관리자는 다음을 제어할 수 있다.
| 제어 측면 | 필드 이름 |
| ----------------------------------------------------| ------------------------------------------- |
| 특권을 가진(privileged) 컨테이너의 실행 | [`privileged`](#특권을-가진) |
| 호스트 네임스페이스의 사용 | [`hostPID`, `hostIPC`](#호스트-네임스페이스) |
| 호스트 네트워킹과 포트의 사용 | [`hostNetwork`, `hostPorts`](#호스트-네임스페이스) |
| 볼륨 유형의 사용 | [`volumes`](#볼륨-및-파일시스템) |
| 호스트 파일시스템의 사용 | [`allowedHostPaths`](#볼륨-및-파일시스템) |
| 특정 FlexVolume 드라이버의 허용 | [`allowedFlexVolumes`](#flexvolume-드라이버) |
| 파드 볼륨을 소유한 FSGroup 할당 | [`fsGroup`](#볼륨-및-파일시스템) |
| 읽기 전용 루트 파일시스템 사용 필요 | [`readOnlyRootFilesystem`](#볼륨-및-파일시스템) |
| 컨테이너의 사용자 및 그룹 ID | [`runAsUser`, `runAsGroup`, `supplementalGroups`](#사용자-및-그룹) |
| 루트 특권으로의 에스컬레이션 제한 | [`allowPrivilegeEscalation`, `defaultAllowPrivilegeEscalation`](#권한-에스컬레이션) |
| 리눅스 기능 | [`defaultAddCapabilities`, `requiredDropCapabilities`, `allowedCapabilities`](#기능) |
| 컨테이너의 SELinux 컨텍스트 | [`seLinux`](#selinux) |
| 컨테이너에 허용된 Proc 마운트 유형 | [`allowedProcMountTypes`](#allowedprocmounttypes) |
| 컨테이너가 사용하는 AppArmor 프로파일 | [어노테이션](#apparmor) |
| 컨테이너가 사용하는 seccomp 프로파일 | [어노테이션](#seccomp) |
| 컨테이너가 사용하는 sysctl 프로파일 | [`forbiddenSysctls`,`allowedUnsafeSysctls`](#sysctl) |
## 파드 시큐리티 폴리시 활성화
파드 시큐리티 폴리시 제어는 선택 사항인 [어드미션
컨트롤러](/docs/reference/access-authn-authz/admission-controllers/#podsecuritypolicy)로 구현된다.
[어드미션 컨트롤러를 활성화](/docs/reference/access-authn-authz/admission-controllers/#how-do-i-turn-on-an-admission-control-plug-in)하면
파드시큐리티폴리시가 적용되지만,
정책을 승인하지 않고 활성화하면 클러스터에
**파드가 생성되지 않는다.**
파드 시큐리티 폴리시 API(`policy/v1beta1/podsecuritypolicy`)는
어드미션 컨트롤러와 독립적으로 활성화되므로 기존 클러스터의 경우
어드미션 컨트롤러를 활성화하기 전에 정책을 추가하고 권한을
부여하는 것이 좋다.
## 정책 승인
파드시큐리티폴리시 리소스가 생성되면 아무 것도 수행하지 않는다. 이를 사용하려면
요청 사용자 또는 대상 파드의
[서비스 어카운트](/docs/tasks/configure-pod-container/configure-service-account/)는
정책에서 `use` 동사를 허용하여 정책을 사용할 권한이 있어야 한다.
대부분의 쿠버네티스 파드는 사용자가 직접 만들지 않는다. 대신 일반적으로
컨트롤러 관리자를 통해
[디플로이먼트](/ko/docs/concepts/workloads/controllers/deployment/),
[레플리카셋](/ko/docs/concepts/workloads/controllers/replicaset/), 또는 기타
템플릿 컨트롤러의 일부로 간접적으로 생성된다. 컨트롤러에 정책에 대한 접근 권한을 부여하면
해당 컨트롤러에 의해 생성된 *모든* 파드에 대한 접근 권한이 부여되므로 정책을 승인하는
기본 방법은 파드의 서비스 어카운트에 대한 접근 권한을
부여하는 것이다([예](#다른-파드를-실행) 참고).
### RBAC을 통한 방법
[RBAC](/docs/reference/access-authn-authz/rbac/)은 표준 쿠버네티스 권한 부여 모드이며,
정책 사용 권한을 부여하는 데 쉽게 사용할 수 있다.
먼저, `Role` 또는 `ClusterRole`은 원하는 정책을 `use` 하려면 접근 권한을 부여해야 한다.
접근 권한을 부여하는 규칙은 다음과 같다.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: <role name>
rules:
- apiGroups: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- <list of policies to authorize>
```
그런 다음 `(Cluster)Role`이 승인된 사용자에게 바인딩된다.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: <binding name>
roleRef:
kind: ClusterRole
name: <role name>
apiGroup: rbac.authorization.k8s.io
subjects:
# 네임스페이스의 모든 서비스 어카운트 승인(권장):
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:serviceaccounts:<authorized namespace>
# 특정 서비스 어카운트 승인(권장하지 않음):
- kind: ServiceAccount
name: <authorized service account name>
namespace: <authorized pod namespace>
# 특정 사용자 승인(권장하지 않음):
- kind: User
apiGroup: rbac.authorization.k8s.io
name: <authorized user name>
```
`RoleBinding`(`ClusterRoleBinding` 아님)을 사용하는 경우, 바인딩과 동일한 네임스페이스에서
실행되는 파드에 대해서만 사용 권한을 부여한다. 네임스페이스에서 실행되는 모든 파드에 접근 권한을
부여하기 위해 시스템 그룹과 쌍을 이룰 수 있다.
```yaml
# 네임스페이스의 모든 서비스 어카운트 승인:
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:serviceaccounts
# 또는 동일하게, 네임스페이스의 모든 승인된 사용자에게 사용 권한 부여
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:authenticated
```
RBAC 바인딩에 대한 자세한 예는,
[역할 바인딩 예제](/docs/reference/access-authn-authz/rbac#role-binding-examples)를 참고한다.
파드시큐리티폴리시 인증에 대한 전체 예제는
[아래](#예제)를 참고한다.
### 추천 예제
파드시큐리티폴리시는 새롭고 간결해진 `PodSecurity` {{< glossary_tooltip
text="어드미션 컨트롤러" term_id="admission-controller" >}}로 대체되고 있다.
이 변경에 대한 상세사항은
[파드시큐리티폴리시 사용 중단: 과거, 현재, 그리고 미래](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/)를 참조한다.
다음 가이드라인을 참조하여 파드시큐리티폴리시를
새로운 어드미션 컨트롤러로 쉽게 전환할 수 있다.
1. 파드시큐리티폴리시를
[파드 보안 표준](/ko/docs/concepts/security/pod-security-standards/)에 의해 정의된 폴리시로 한정한다.
- {{< example file="policy/privileged-psp.yaml" >}}Privileged{{< /example >}}
- {{< example file="policy/baseline-psp.yaml" >}}Baseline{{< /example >}}
- {{< example file="policy/restricted-psp.yaml" >}}Restricted{{< /example >}}
1. `system:serviceaccounts:<namespace>` (여기서 `<namespace>`는 타겟 네임스페이스) 그룹을 사용하여
파드시큐리티폴리시를 전체 네임스페이스에만 바인드한다. 예시는 다음과 같다.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
# 이 클러스터롤바인딩(ClusterRoleBinding)을 통해 "development" 네임스페이스의 모든 파드가 기준 파드시큐리티폴리시(PSP)를 사용할 수 있다.
kind: ClusterRoleBinding
metadata:
name: psp-baseline-namespaces
roleRef:
kind: ClusterRole
name: psp-baseline
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:serviceaccounts:development
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: system:serviceaccounts:canary
apiGroup: rbac.authorization.k8s.io
```
### 문제 해결
- [컨트롤러 관리자](/docs/reference/command-line-tools-reference/kube-controller-manager/)는
보안 API 포트에 대해 실행되어야 하며 수퍼유저 권한이 없어야 한다.
API 서버 접근 제어에 대한 자세한 내용은
[쿠버네티스 API에 대한 접근 제어](/ko/docs/concepts/security/controlling-access)를 참고하길 바란다.
컨트롤러 관리자가 신뢰할 수 있는 API 포트(`localhost` 리스너라고도 함)를
통해 연결된 경우, 요청이 인증 및 권한 부여 모듈을 우회하고,
모든 파드시큐리티폴리시 오브젝트가 허용되며 사용자는 특권을 가진 컨테이너를
만들 수 있는 권한을 부여할 수 있다.
컨트롤러 관리자 권한 구성에 대한 자세한 내용은
[컨트롤러 역할](/docs/reference/access-authn-authz/rbac/#controller-roles)을 참고한다.
## 정책 순서
파드 생성 및 업데이트를 제한할 뿐만 아니라 파드 시큐리티 폴리시를 사용하여
제어하는 많은 필드에 기본값을 제공할 수도 있다. 여러 정책을
사용할 수 있는 경우 파드 시큐리티 폴리시 컨트롤러는
다음 기준에 따라 정책을 선택한다.
1. 기본 설정을 변경하거나 파드를 변경하지 않고 파드를 있는 그대로 허용하는 파드시큐리티폴리시가
선호된다. 이러한 비-변이(non-mutating) 파드시큐리티폴리시의
순서는 중요하지 않다.
2. 파드를 기본값으로 설정하거나 변경해야 하는 경우, 파드를 허용할 첫 번째 파드시큐리티폴리시
(이름순)가 선택된다.
파드시큐리티폴리시에 대해 파드의 유효성이 검증되면,
파드시큐리티폴리시의 이름을 어노테이션 값으로 사용하는 [`kubernetes.io/psp` 어노테이션]이 파드에 추가된다.
{{< note >}}
업데이트 작업 중(파드 스펙에 대한 변경이 허용되지 않는 동안) 비-변이 파드시큐리티폴리시만
파드의 유효성을 검사하는 데 사용된다.
파드시큐리티폴리시(PodSecurityPolicy)는 쿠버네티스 1.21 버전부터 [사용 중단(deprecated)](/blog/2021/04/08/kubernetes-1-21-release-announcement/#podsecuritypolicy-deprecation)되었으며,
v1.25 버전 때 쿠버네티스에서 제거되었다.
파드시큐리티폴리시를 사용하는 것 대신, 다음 중 하나를 사용하거나 둘 다 사용하여 파드에 유사한 제한을
적용할 수 있다.
- [파드 시큐리티 어드미션](/docs/concepts/security/pod-security-admission/)
- 직접 배포하고 구성할 수 있는 서드파티 어드미션 플러그인
마이그레이션에 관한 설명이 필요하다면 [파드시큐리티폴리시(PodSecurityPolicy)에서 빌트인 파드시큐리티어드미션컨트롤러(PodSecurity Admission Controller)로 마이그레이션](/docs/tasks/configure-pod-container/migrate-from-psp/)을 참고한다.
이 API 제거에 대해 더 많은 정보가 필요하다면,
[파드시큐리티폴리시(PodSecurityPolicy) 사용 중단: 과거, 현재, 미래](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/)를 참고한다.
쿠버네티스 v{{< skew currentVersion >}} 이외의 버전을 실행 중이라면,
해당 쿠버네티스 버전에 대한 문서를 확인한다.
{{< /note >}}
## 예제
_이 예에서는 파드시큐리티폴리시 어드미션 컨트롤러가 활성화된 클러스터가 실행 중이고
클러스터 관리자 권한이 있다고 가정한다._
### 설정
이 예제와 같이 네임스페이스와 서비스 어카운트를 설정한다.
이 서비스 어카운트를 사용하여 관리자가 아닌 사용자를 조정한다.
```shell
kubectl create namespace psp-example
kubectl create serviceaccount -n psp-example fake-user
kubectl create rolebinding -n psp-example fake-editor --clusterrole=edit --serviceaccount=psp-example:fake-user
```
어떤 사용자로 활동하고 있는지 명확하게 하고 입력 내용을 저장하려면 2개의 별칭(alias)을
만든다.
```shell
alias kubectl-admin='kubectl -n psp-example'
alias kubectl-user='kubectl --as=system:serviceaccount:psp-example:fake-user -n psp-example'
```
### 정책과 파드 생성
이는 특권있는 파드를 만들지 못하게 하는 정책이다.
파드시큐리티폴리시 오브젝트의 이름은 유효한
[DNS 서브도메인 이름](/ko/docs/concepts/overview/working-with-objects/names#dns-서브도메인-이름)이어야 한다.
{{< codenew file="policy/example-psp.yaml" >}}
그리고 kubectl로 생성한다.
```shell
kubectl-admin create -f https://k8s.io/examples/policy/example-psp.yaml
```
이제 권한이 없는 사용자로서 간단한 파드를 생성해보자.
```shell
kubectl-user create -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: pause
spec:
containers:
- name: pause
image: k8s.gcr.io/pause
EOF
```
이것의 출력은 다음과 같을 것이다.
```
Error from server (Forbidden): error when creating "STDIN": pods "pause" is forbidden: unable to validate against any pod security policy: []
```
**무슨 일이 일어났나?** 파드시큐리티폴리시가 생성되었지만, 파드의 서비스 어카운트나 `fake-user`
새 정책을 사용할 권한이 없다.
```shell
kubectl-user auth can-i use podsecuritypolicy/example
```
결과는 다음과 같다:
```
no
```
예제 정책에서 `fake-user`에게 `use` 동사를 부여하는 rolebinding을
생성한다.
{{< note >}}
이 방법은 권장하지 않는다! 선호하는 방법은 [다음 절](#다른-파드를-실행)을
참고하길 바란다.
{{< /note >}}
```shell
kubectl-admin create role psp:unprivileged \
--verb=use \
--resource=podsecuritypolicy \
--resource-name=example
```
```
role "psp:unprivileged" created
```
```shell
kubectl-admin create rolebinding fake-user:psp:unprivileged \
--role=psp:unprivileged \
--serviceaccount=psp-example:fake-user
```
```
rolebinding "fake-user:psp:unprivileged" created
```
```shell
kubectl-user auth can-i use podsecuritypolicy/example
```
```
yes
```
이제 파드 생성을 다시 시도하자.
```shell
kubectl-user create -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: pause
spec:
containers:
- name: pause
image: k8s.gcr.io/pause
EOF
```
이것의 출력은 다음과 같을 것이다.
```
pod "pause" created
```
예상대로 작동한다!
새로 생성된 파드시큐리티폴리시에 대해서도 파드가 유효한지 검증한다:
```shell
kubectl-user get pod pause -o yaml | grep kubernetes.io/psp
```
결과는 다음과 같다:
```
kubernetes.io/psp: example
```
그러나 특권있는 파드를 만들려는 시도는 여전히
거부되어야 한다.
```shell
kubectl-user create -f- <<EOF
apiVersion: v1
kind: Pod
metadata:
name: privileged
spec:
containers:
- name: pause
image: k8s.gcr.io/pause
securityContext:
privileged: true
EOF
```
이것의 출력은 다음과 같을 것이다.
```
Error from server (Forbidden): error when creating "STDIN": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
```
계속 진행하기 전에 파드를 삭제하자.
```shell
kubectl-user delete pod pause
```
### 다른 파드를 실행
약간 다르게 다시 시도해보자.
```shell
kubectl-user create deployment pause --image=k8s.gcr.io/pause
```
```none
deployment "pause" created
```
```shell
kubectl-user get pods
```
```
No resources found.
```
```shell
kubectl-user get events | head -n 2
```
```
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
1m 2m 15 pause-7774d79b5 ReplicaSet Warning FailedCreate replicaset-controller Error creating: pods "pause-7774d79b5-" is forbidden: no providers available to validate pod request
```
**무슨 일이 일어났나?** 우리는 이미 `fake-user`에 대해 `psp:unprivileged` 역할을 바인딩했는데,
`Error creating: pods "pause-7774d79b5-" is
forbidden: no providers available to validate pod request` 오류가
발생하는 이유는 무엇인가? 그 답은 소스인 `replicaset-controller`에 있다. Fake-user가
디플로이먼트를 성공적으로 생성했지만(레플리카셋을 성공적으로 생성했음), 레플리카셋이
파드를 생성했을 때 podsecuritypolicy 예제를
사용할 권한이 없었다.
이 문제를 해결하려면 `psp:unprivileged` 역할을 파드의 서비스 어카운트에 대신
바인딩한다. 이 경우(지정하지 않았으므로) 서비스 어카운트는
`default`이다.
```shell
kubectl-admin create rolebinding default:psp:unprivileged \
--role=psp:unprivileged \
--serviceaccount=psp-example:default
```
```none
rolebinding "default:psp:unprivileged" created
```
이제 다시 한번 해본다면 replicaset-controller가
파드를 성공적으로 생성할 것이다.
```shell
kubectl-user get pods --watch
```
```none
NAME READY STATUS RESTARTS AGE
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
pause-7774d79b5-qrgcb 0/1 Pending 0 1s
pause-7774d79b5-qrgcb 0/1 ContainerCreating 0 1s
pause-7774d79b5-qrgcb 1/1 Running 0 2s
```
### 정리
네임스페이스를 삭제하여 대부분의 예제 리소스를 정리한다.
```shell
kubectl-admin delete ns psp-example
```
```
namespace "psp-example" deleted
```
`PodSecurityPolicy` 리소스는 네임스페이스에 포함되지 않으므로 별도로
정리해야 한다.
```shell
kubectl-admin delete psp example
```
```
podsecuritypolicy "example" deleted
```
### 정책 예제
다음은 파드 시큐리티 폴리시 어드미션 컨트롤러를 사용하지 않는 것과 동일하게 만들 수 있는
최소한의 제한 정책이다.
{{< codenew file="policy/privileged-psp.yaml" >}}
다음은 권한이 없는 사용자로서의 실행을 필요로 하고, 루트로의 에스컬레이션(escalation) 가능성을 차단하고,
여러 보안 메커니즘을 사용을 필요로 하는 제한적
정책의 예제이다.
{{< codenew file="policy/restricted-psp.yaml" >}}
더 많은 예제는
[파드 보안 표준](/ko/docs/concepts/security/pod-security-standards/#정책-초기화)을 본다.
## 정책 레퍼런스
### 특권을 가진
**Privileged** - 파드의 컨테이너가 특권 모드를 사용할 수 있는지 여부를 결정한다.
기본적으로 컨테이너는 호스트의 모든 장치에 접근할 수 없지만
"특권을 가진" 컨테이너는 호스트의 모든 장치에 접근할 수 있다. 이것은
컨테이너가 호스트에서 실행되는 프로세스와 거의 동일한 접근을 허용한다.
이것은 네트워크 스택 조작 및 장치 접근과 같은
리눅스 기능을 사용하려는 컨테이너에 유용하다.
### 호스트 네임스페이스
**HostPID** - 파드 컨테이너가 호스트 프로세스 ID 네임스페이스를 공유할 수 있는지 여부를
제어한다. ptrace와 함께 사용하면 컨테이너 외부로 권한을 에스컬레이션하는 데 사용할 수
있다(ptrace는 기본적으로 금지되어 있음).
**HostIPC** - 파드 컨테이너가 호스트 IPC 네임스페이스를 공유할 수 있는지 여부를
제어한다.
**HostNetwork** - 파드가 노드 네트워크 네임스페이스를 사용할 수 있는지 여부를 제어한다.
이렇게 하면 파드에 루프백 장치에 접근 권한을 주고, 서비스는 로컬호스트(localhost)를 리스닝할 수 있으며,
동일한 노드에 있는 다른 파드의 네트워크 활동을 스누핑(snoop)하는 데
사용할 수 있다.
**HostPorts** - 호스트 네트워크 네임스페이스에 허용되는 포트 범위의 목록을
제공한다. `min``max`를 포함하여 `HostPortRange`의 목록으로 정의된다.
기본값은 허용하는 호스트 포트 없음(no allowed host ports)이다.
### 볼륨 및 파일시스템
**Volumes** - 허용되는 볼륨 유형의 목록을 제공한다. 허용 가능한 값은
볼륨을 생성할 때 정의된 볼륨 소스에 따른다. 볼륨 유형의 전체 목록은
[볼륨 유형들](/ko/docs/concepts/storage/volumes/#볼륨-유형들)에서 참고한다.
또한 `*`를 사용하여 모든 볼륨 유형을
허용할 수 있다.
새 PSP에 허용되는 볼륨의 **최소 권장 셋** 은 다음과 같다.
- 컨피그맵
- 다운워드API
- emptyDir
- 퍼시스턴트볼륨클레임
- 시크릿
- 프로젝티드(projected)
{{< warning >}}
파드시큐리티폴리시는 `PersistentVolumeClaim`이 참조할 수 있는 `PersistentVolume`
오브젝트의 유형을 제한하지 않으며 hostPath 유형
`PersistentVolumes`은 읽기-전용 접근 모드를 지원하지 않는다. 신뢰할 수 있는 사용자만
`PersistentVolume` 오브젝트를 생성할 수 있는 권한을 부여 받아야 한다.
{{< /warning >}}
**FSGroup** - 일부 볼륨에 적용되는 보충 그룹(supplemental group)을 제어한다.
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
기본값으로 사용한다. 모든 범위에 대해 검증한다.
- *MayRunAs* - 하나 이상의 `range`를 지정해야 한다. 기본값을 제공하지 않고
`FSGroups`을 설정하지 않은 상태로 둘 수 있다. `FSGroups`이 설정된 경우 모든 범위에 대해
유효성을 검사한다.
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `fsGroup` ID의 지정도 허용한다.
**AllowedHostPaths** - hostPath 볼륨에서 사용할 수 있는 호스트 경로의 목록을
지정한다. 빈 목록은 사용되는 호스트 경로에 제한이 없음을 의미한다.
이는 단일 `pathPrefix` 필드가 있는 오브젝트 목록으로 정의되며, hostPath 볼륨은
허용된 접두사로 시작하는 경로를 마운트할 수 있으며 `readOnly` 필드는
읽기-전용으로 마운트 되어야 함을 나타낸다.
예를 들면 다음과 같습니다.
```yaml
allowedHostPaths:
# 이 정책은 "/foo", "/foo/", "/foo/bar" 등을 허용하지만,
# "/fool", "/etc/foo" 등은 허용하지 않는다.
# "/foo/../" 는 절대 유효하지 않다.
- pathPrefix: "/foo"
readOnly: true # 읽기 전용 마운트만 허용
```
{{< warning >}}
호스트 파일시스템에 제한없는 접근을 부여하며, 컨테이너가 특권을 에스컬레이션
(다른 컨테이너들에 있는 데이터를 읽고, 시스템 서비스의 자격 증명을 어뷰징(abusing)하는 등)할
수 있도록 만드는 다양한 방법이 있다. 예를 들면, Kubelet과 같다.
쓰기 가능한 hostPath 디렉터리 볼륨을 사용하면, 컨테이너가 `pathPrefix` 외부의
호스트 파일시스템에 대한 통행을 허용하는 방식으로 컨테이너의 파일시스템 쓰기(write)를 허용한다.
쿠버네티스 1.11 이상 버전에서 사용 가능한 `readOnly: true`는 지정된 `pathPrefix`에 대한
접근을 효과적으로 제한하기 위해 **모든** `allowedHostPaths`에서 사용해야 한다.
{{< /warning >}}
**ReadOnlyRootFilesystem** - 컨테이너는 읽기-전용 루트 파일시스템(즉, 쓰기 가능한 레이어 없음)으로
실행해야 한다.
### FlexVolume 드라이버
flexvolume에서 사용할 수 있는 FlexVolume 드라이버의 목록을 지정한다.
빈 목록 또는 nil은 드라이버에 제한이 없음을 의미한다.
[`volumes`](#볼륨-및-파일시스템) 필드에 `flexVolume` 볼륨 유형이 포함되어
있는지 확인한다. 그렇지 않으면 FlexVolume 드라이버가 허용되지 않는다.
예를 들면 다음과 같다.
```yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: allow-flex-volumes
spec:
# ... 다른 스펙 필드
volumes:
- flexVolume
allowedFlexVolumes:
- driver: example/lvm
- driver: example/cifs
```
### 사용자 및 그룹
**RunAsUser** - 컨테이너를 실행할 사용자 ID를 제어힌다.
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
기본값으로 사용한다. 모든 범위에 대해 검증한다.
- *MustRunAsNonRoot* - 파드가 0이 아닌 `runAsUser`로 제출되거나
이미지에 `USER` 지시문이 정의되어 있어야 한다(숫자 UID 사용). `runAsNonRoot` 또는
`runAsUser` 설정을 지정하지 않은 파드는 `runAsNonRoot=true`를 설정하도록
변경되므로 컨테이너에 0이 아닌 숫자가 정의된 `USER` 지시문이
필요하다. 기본값은 제공되지 않는다.
이 전략에서는 `allowPrivilegeEscalation=false`를 설정하는 것이 좋다.
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `runAsUser`의 지정도 허용한다.
**RunAsGroup** - 컨테이너가 실행될 기본 그룹 ID를 제어한다.
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
기본값으로 사용한다. 모든 범위에 대해 검증한다.
- *MayRunAs* - `RunAsGroup`을 지정할 필요가 없다. 그러나 `RunAsGroup`을 지정하면
정의된 범위에 속해야 한다.
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `runAsGroup`의 지정도 허용한다.
**SupplementalGroups** - 컨테이너가 추가할 그룹 ID를 제어한다.
- *MustRunAs* - 하나 이상의 `range`를 지정해야 한다. 첫 번째 범위의 최솟값을
기본값으로 사용한다. 모든 범위에 대해 검증한다.
- *MayRunAs* - 하나 이상의 `range`를 지정해야 한다. `supplementalGroups`
기본값을 제공하지 않고 설정하지 않은 상태로 둘 수 있다.
`supplementalGroups`가 설정된 경우 모든 범위에 대해 유효성을 검증한다.
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `supplementalGroups`의 지정도
허용한다.
### 권한 에스컬레이션
이 옵션은 `allowPrivilegeEscalation` 컨테이너 옵션을 제어한다. 이 bool은
컨테이너 프로세스에서
[`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt)
플래그가 설정되는지 여부를 직접 제어한다. 이 플래그는 `setuid` 바이너리가
유효 사용자 ID를 변경하지 못하게 하고 파일에 추가 기능을 활성화하지 못하게
한다(예: `ping` 도구 사용을 못하게 함). `MustRunAsNonRoot`를 효과적으로
강제하려면 이 동작이 필요하다.
**AllowPrivilegeEscalation** - 사용자가 컨테이너의 보안 컨텍스트를
`allowPrivilegeEscalation=true`로 설정할 수 있는지 여부를 게이트한다.
이 기본값은 setuid 바이너리를 중단하지 않도록 허용한다. 이를 `false`로 설정하면
컨테이너의 하위 프로세스가 상위 프로세스보다 더 많은 권한을 얻을 수 없다.
**DefaultAllowPrivilegeEscalation** - `allowPrivilegeEscalation` 옵션의
기본값을 설정한다. 이것이 없는 기본 동작은 setuid 바이너리를 중단하지 않도록
권한 에스컬레이션을 허용하는 것이다. 해당 동작이 필요하지 않은 경우 이 필드를 사용하여
기본적으로 허용하지 않도록 설정할 수 있지만 파드는 여전히 `allowPrivilegeEscalation`
명시적으로 요청할 수 있다.
### 기능
리눅스 기능은 전통적으로 슈퍼유저와 관련된 권한을 보다 세밀하게 분류한다.
이러한 기능 중 일부는 권한 에스컬레이션 또는 컨테이너 분류에 사용될 수 있으며
파드시큐리티폴리시에 의해 제한될 수 있다. 리눅스 기능에 대한 자세한 내용은
[기능(7)](https://man7.org/linux/man-pages/man7/capabilities.7.html)을
참고하길 바란다.
다음 필드는 대문자로 표기된 기능 이름 목록을
`CAP_` 접두사 없이 가져온다.
**AllowedCapabilities** - 컨테이너에 추가될 수 있는 기능의 목록을
제공한다. 기본적인 기능 셋은 암시적으로 허용된다. 비어있는 셋은
기본 셋을 넘어서는 추가 기능이 추가되지 않는 것을
의미한다. `*`는 모든 기능을 허용하는 데 사용할 수 있다.
**RequiredDropCapabilities** - 컨테이너에서 삭제해야 하는 기능이다.
이러한 기능은 기본 셋에서 제거되며 추가해서는 안된다.
`RequiredDropCapabilities`에 나열된 기능은 `AllowedCapabilities` 또는
`DefaultAddCapabilities`에 포함되지 않아야 한다.
**DefaultAddCapabilities** - 런타임 기본값 외에 기본적으로 컨테이너에 추가되는 기능이다.
도커 런타임을 사용할 때 기본 기능 목록은
[도커 문서](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)를 참고한다.
### SELinux
- *MustRunAs* - `seLinuxOptions`을 구성해야 한다.
`seLinuxOptions`을 기본값으로 사용한다. `seLinuxOptions`에 대해 유효성을 검사한다.
- *RunAsAny* - 기본값은 제공되지 않는다. 어떠한 `seLinuxOptions`의 지정도
허용한다.
### AllowedProcMountTypes
`allowedProcMountTypes`는 허용된 ProcMountTypes의 목록이다.
비어 있거나 nil은 `DefaultProcMountType`만 사용할 수 있음을 나타낸다.
`DefaultProcMount`는 /proc의 읽기 전용 및 마스킹(masking)된 경로에 컨테이너 런타임
기본값을 사용한다. 대부분의 컨테이너 런타임은 특수 장치나 정보가 실수로 보안에
노출되지 않도록 /proc의 특정 경로를 마스킹한다. 이것은 문자열
`Default`로 표시된다.
유일하게 다른 ProcMountType은 `UnmaskedProcMount`로, 컨테이너 런타임의
기본 마스킹 동작을 무시하고 새로 작성된 /proc 컨테이너가 수정없이
그대로 유지되도록 한다. 이 문자열은
`Unmasked`로 표시된다.
### AppArmor
파드시큐리티폴리시의 어노테이션을 통해 제어된다. [AppArmor
문서](/ko/docs/tutorials/security/apparmor/#podsecuritypolicy-annotations)를 참고하길 바란다.
### Seccomp
쿠버네티스 v1.19부터 파드나 컨테이너의 `securityContext` 에서
`seccompProfile` 필드를 사용하여 [seccomp 프로파일 사용을
제어](/docs/tutorials/security/seccomp/)할 수 있다.
이전 버전에서는, 파드에 어노테이션을 추가하여 seccomp를 제어했다.
두 버전에서 동일한 파드시큐리티폴리시를 사용하여
이러한 필드나 어노테이션이 적용되는 방식을 적용할 수 있다.
**seccomp.security.alpha.kubernetes.io/defaultProfileName** - 컨테이너에
적용할 기본 seccomp 프로파일을 지정하는 어노테이션이다. 가능한 값은
다음과 같다.
- `unconfined` - 대안이 제공되지 않으면 Seccomp가 컨테이너 프로세스에 적용되지
않는다(쿠버네티스의 기본값임).
- `runtime/default` - 기본 컨테이너 런타임 프로파일이 사용된다.
- `docker/default` - 도커 기본 seccomp 프로파일이 사용된다. 쿠버네티스 1.11 부터 사용 중단(deprecated)
되었다. 대신 `runtime/default` 사용을 권장한다.
- `localhost/<path>` - `<seccomp_root>/<path>`에 있는 노드에서 파일을 프로파일로
지정한다. 여기서 `<seccomp_root>`는 Kubelet의 `--seccomp-profile-root` 플래그를
통해 정의된다. `--seccomp-profile-root` 플래그가
정의되어 있지 않으면, `<root-dir>``--root-dir` 플래그로
지정된 `<root-dir>/seccomp` 기본 경로가 사용된다.
{{< note >}}
`--seccomp-profile-root` 플래그는 쿠버네티스 v1.19부터 더 이상 사용되지
않는다. 사용자는 기본 경로를 사용하는 것이 좋다.
{{< /note >}}
**seccomp.security.alpha.kubernetes.io/allowedProfileNames** - 파드 seccomp
어노테이션에 허용되는 값을 지정하는 어노테이션. 쉼표로 구분된
허용된 값의 목록으로 지정된다. 가능한 값은 위에 나열된 값과
모든 프로파일을 허용하는 `*` 이다.
이 주석이 없으면 기본값을 변경할 수 없다.
### Sysctl
기본적으로 모든 안전한 sysctls가 허용된다.
- `forbiddenSysctls` - 특정 sysctls를 제외한다.
목록에서 안전한 것과 안전하지 않은 sysctls의 조합을 금지할 수 있다.
모든 sysctls 설정을 금지하려면 자체적으로 `*`를 사용한다.
- `allowedUnsafeSysctls` - `forbiddenSysctls`에 나열되지 않는 한
기본 목록에서 허용하지 않은 특정 sysctls를 허용한다.
[Sysctl 문서](/ko/docs/tasks/administer-cluster/sysctl-cluster/#파드시큐리티폴리시-podsecuritypolicy)를 참고하길 바란다.
## {{% heading "whatsnext" %}}
- [파드시큐리티폴리시 사용 중단: 과거, 현재, 그리고
미래](/blog/2021/04/06/podsecuritypolicy-deprecation-past-present-and-future/)에서
파드시큐리티폴리시의 미래에 대해 알아본다.
- 폴리시 권장 사항에 대해서는 [파드 보안 표준](/ko/docs/concepts/security/pod-security-standards/)을 참조한다.
- API 세부 정보는
[파드 시큐리티 폴리시 레퍼런스](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritypolicy-v1beta1-policy) 참조한다.

View File

@ -407,7 +407,7 @@ weight: 10
<td>
<p>
컨테이너는 <code>ALL</code> 능력을 내려놓아야 하며,
<code>NET_BIND_SERVICE</code> 능력을 다시 추가하기 위한 목적일 때만 허용되어야 한다. <em>v1.25+에서는 <a href="#policies-specific-to-linux">리눅스 전용 정책이다.</a><code>(spec.os.name != windows)</code></em></p>
<code>NET_BIND_SERVICE</code> 능력을 다시 추가하기 위한 목적일 때만 허용되어야 한다. <em>v1.25+에서는 <a href="#policies-specific-to-linux">리눅스 전용 정책이다.</a><code>(spec.os.name != windows)</code></em>
</p>
<p><strong>제한된 필드</strong></p>
<ul>
@ -521,3 +521,4 @@ v1.24 이전 Kubelet은 파드 OS 필드를 필수로 요구하지 않으며,
추가적으로, 샌드박스 방식에 따라 샌드박스 워크로드에 대한 보호가 달라진다.
이와 같은 경우에는, 하나의 프로필만을 모든 샌드박스 워크로드에 대해 권장할 수 없다.

View File

@ -12,7 +12,7 @@ weight: 60
쿠버네티스 {{< glossary_tooltip text="RBAC" term_id="rbac" >}}는
클러스터 사용자 및 워크로드가 자신의 역할을 수행하기 위해 필요한 자원에 대해서만
접근 권한을 가지도록 보장하는 핵심 보안 제어 방식이다. 클러스터 관리자가 클러스터 사용자 권한을 설정할 시에는,
보안 사고로 이어지는 과도한 접근 권한 부여의 위험을 줄이기 위해
보안 사고로 이어지는 과도한 접근 권한 부여의 위험을 줄이기 위해
권한 에스컬레이션 발생 가능성에 대해 이해하는 것이 중요하다.
여기서 제공하는 모범 사례는 [RBAC 문서](/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update)
@ -33,7 +33,7 @@ weight: 60
- 와일드카드(wildcard)를 사용한 권한 지정을 할 시에는, 특히 모든 리소스에 대해서는 가능하면 지양한다.
쿠버네티스는 확장성을 지니는 시스템이기 때문에,
와일드카드를 이용한 권한 지정은 현재 클러스터에 있는 모든 오브젝트 타입뿐만 아니라
추후에 생성될 오브젝트 타입에 대해서도 권한을 부여하게 된다.
모든 오브젝트 타입에 대해서도 권한을 부여하게 된다.
- 운영자는 `cluster-admin` 계정이 필수로 요구되지 않을시에는 사용을 지양한다.
적은 권한을 가진 계정과
[가장 (impersonation) 권한](/docs/reference/access-authn-authz/authentication/#user-impersonation)을
@ -99,10 +99,13 @@ weight: 60
### 워크로드 생성
워크로드(파드 혹은 파드를 관리하는
[워크로드 리소스](/ko/docs/concepts/workloads/controllers/))를 생성할 수 있는 사용자는
[파드 시큐리티 스탠다드](/ko/docs/concepts/security/pod-security-standards/)에
기반한 제한 사항이 없을 시에는 해당 노드에 대한 접근 권한을 부여받을 수 있다.
네임스페이스에 워크로드(파드 혹은 파드를 관리하는
[워크로드 리소스](/ko/docs/concepts/workloads/controllers/))를 생성할 수 있는 권한은
파드에 마운트할 수 있는 시크릿, 컨피그맵 그리고 퍼시스턴트볼륨(PersistentVolume)과 같은 해당 네임스페이스의 다른 많은 리소스에 대한
액세스 권한을 암묵적으로 부여한다. 또한 파드는 모든 [서비스어카운트](/ko/docs/reference/access-authn-authz/service-accounts-admin/)로
실행할 수 있기 때문에, 워크로드 생성 권한을 부여하면
해당 네임스페이스에 있는 모든 서비스어카운트의 API 액세스 수준도 암묵적으로
부여된다.
특권 파드 실행 권한을 가지는 사용자는 해당 노드에 대한 권한을 부여받을 수 있으며,
더 나아가 권한을 상승시킬 수 있는 가능성도 존재한다.
@ -111,13 +114,10 @@ weight: 60
이는 [파드 시큐리티 어드미션](/docs/concepts/security/pod-security-admission/)
또는 다른 (서드 파티) 매커니즘을 통해 시행할 수 있다.
사용자의 특권을 가진 파드 생성 자격을 제한하기 위해,
현재는 사용이 중지 된 [파드시큐리티폴리시](/ko/docs/concepts/security/pod-security-policy/)
매커니즘도 사용할 수 있다. (주의 - 파드시큐리티폴리시는 1.25 버전 이후로 중지될 예정이다.)
사용자가 네임스페이스 내에서 워크로드를 생성하면, 해당 네임스페이스에 위치한 시크릿에 대한 간접적 접근 권한을 부여 받게 된다.
사용자가 kube-system 또는 유사한 특권을 가진 네임스페이스에서 파드를 생성하게 되면,
RBAC를 통해 직접적으로는 접근 권한을 가지지 못할 시크릿에 대한 권한도 부여받게 된다.
이러한 이유로, 네임스페이스는 서로 다른 수준의 보안 또는 테넌시가 필요한 리소스들을 분리하는 데 사용해야
한다. [최소 권한](#least-privilege) 원칙을 따르고 권한을 가장 적게 할당하는 것이
바람직하지만, 네임스페이스 내의 경계는 약한 것으로 간주되어야
한다.
### 퍼시스턴트 볼륨 생성
@ -186,4 +186,3 @@ CSR API를 통해 CSR에 대한 `create` 권한 및 `certificatesigningrequests/
## {{% heading "whatsnext" %}}
* RBAC에 대한 추가적인 정보를 얻기 위해서는 [RBAC 문서](/docs/reference/access-authn-authz/rbac/)를 참고한다.

View File

@ -45,9 +45,10 @@ my-nginx-3800858182-kna2y 1/1 Running 0 13s 10.244.2.5
파드의 IP를 확인한다.
```shell
kubectl get pods -l run=my-nginx -o yaml | grep podIP
podIP: 10.244.3.4
podIP: 10.244.2.5
kubectl get pods -l run=my-nginx -o custom-columns=POD_IP:.status.podIPs
POD_IP
[map[ip:10.244.3.4]]
[map[ip:10.244.2.5]]
```
이제 클러스터의 모든 노드로 ssh 접속하거나 `curl`과 같은 도구를 사용하여 두 IP 주소에 질의를 전송할 수 있을 것이다. 컨테이너는 노드의 포트 80을 사용하지 *않으며* , 트래픽을 파드로 라우팅하는 특별한 NAT 규칙도 없다는 것을 참고한다. 이것은 동일한 `containerPort`를 사용하여 동일한 노드에서 여러 nginx 파드를 실행하는 것이 가능하고, 또한 서비스에 할당된 IP 주소를 사용하여 클러스터의 다른 파드나 노드에서 접근할 수 있다는 의미이다. 호스트 노드의 특정 포트를 배후(backing) 파드로 포워드하고 싶다면, 가능은 하지만 네트워킹 모델을 사용하면 그렇게 할 필요가 없어야 한다.
@ -243,7 +244,6 @@ kubectl get secrets
```
```
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret kubernetes.io/tls 2 1m
```
그리고 또한 컨피그맵:
@ -290,7 +290,6 @@ kubectl get secrets
```
```
NAME TYPE DATA AGE
default-token-il9rc kubernetes.io/service-account-token 1 1d
nginxsecret kubernetes.io/tls 2 1m
```
@ -314,8 +313,12 @@ kubectl delete deployments,svc my-nginx; kubectl create -f ./nginx-secure-app.ya
이 시점에서 모든 노드에서 nginx 서버에 연결할 수 있다.
```shell
kubectl get pods -o yaml | grep -i podip
podIP: 10.244.3.5
kubectl get pods -l run=my-nginx -o custom-columns=POD_IP:.status.podIPs
POD_IP
[map[ip:10.244.3.5]]
```
```shell
node $ curl -k https://10.244.3.5
...
<h1>Welcome to nginx!</h1>
@ -424,3 +427,5 @@ LoadBalancer Ingress: a320587ffd19711e5a37606cf4a74574-1142138393.us-east-1.el
* [서비스를 사용해서 클러스터 내 애플리케이션에 접근하기](/ko/docs/tasks/access-application-cluster/service-access-application-cluster/)를 더 자세히 알아본다.
* [서비스를 사용해서 프론트 엔드부터 백 엔드까지 연결하기](/ko/docs/tasks/access-application-cluster/connecting-frontend-backend/)를 더 자세히 알아본다.
* [외부 로드 밸런서를 생성하기](/ko/docs/tasks/access-application-cluster/create-external-load-balancer/)를 더 자세히 알아본다.

View File

@ -308,7 +308,7 @@ kubectl exec -it dns-example -- cat /etc/resolv.conf
```
출력은 다음과 같은 형식일 것이다.
```
nameserver fd00:79:30::a
nameserver 2001:db8:30::a
search default.svc.cluster-domain.example svc.cluster-domain.example cluster-domain.example
options ndots:5
```
@ -344,6 +344,5 @@ kube-apiserver와 kubelet에 `ExpandedDNSConfig` 기능 게이트가 활성화
## {{% heading "whatsnext" %}}
DNS 구성 관리에 대한 지침은
[DNS 서비스 구성](/ko/docs/tasks/administer-cluster/dns-custom-nameservers/)에서 확인할 수 있다.

View File

@ -108,7 +108,7 @@ endpoints:
#### 제공(Serving)
{{< feature-state for_k8s_version="v1.20" state="alpha" >}}
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
`serving`은 종료 상태를 고려하지 않는다는 점을 제외하면 `ready` 조건과 동일하다.
엔드포인트슬라이스 API 컨슈머는 파드가 종료되는 동안 파드 준비 상태에 관심이 있다면
@ -127,7 +127,7 @@ endpoints:
#### 종료(Terminating)
{{< feature-state for_k8s_version="v1.20" state="alpha" >}}
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
`종료(Terminating)`는 엔드포인트가 종료되는지 여부를 나타내는 조건이다.
파드의 경우 삭제 타임 스탬프가 설정된 모든 파드이다.

View File

@ -70,7 +70,7 @@ __egress__: 각 네트워크폴리시에는 화이트리스트 `egress` 규칙
따라서 예시의 네트워크폴리시는 다음과 같이 동작한다.
1. 인그레스 및 이그레스 트래픽에 대해 "default" 네임스페이스에서 "role=db"인 파드를 격리한다(아직 격리되지 않은 경우).
2. (인그레스 규칙)은 "role=db" 레이블을 사용하는 "default" 네임스페이스의 모든 파드에 대해서 TCP 포트 6397로의 연결을 허용한다. 인그레스을 허용 할 대상은 다음과 같다.
2. (인그레스 규칙)은 "role=db" 레이블을 사용하는 "default" 네임스페이스의 모든 파드에 대해서 TCP 포트 6379로의 연결을 허용한다. 인그레스을 허용 할 대상은 다음과 같다.
* "role=frontend" 레이블이 있는 "default" 네임스페이스의 모든 파드
* 네임스페이스와 "project=myproject" 를 레이블로 가지는 모든 파드
@ -195,7 +195,7 @@ SCTP 프로토콜 네트워크폴리시를 지원하는 {{< glossary_tooltip tex
## 포트 범위 지정
{{< feature-state for_k8s_version="v1.22" state="beta" >}}
{{< feature-state for_k8s_version="v1.25" state="stable" >}}
네트워크폴리시를 작성할 때, 단일 포트 대신 포트 범위를 대상으로 지정할 수 있다.
@ -228,10 +228,6 @@ spec:
TCP를 통해 `10.0.0.0/24` 범위 내의 모든 IP와 통신하도록 허용한다.
이 필드를 사용할 때 다음의 제한 사항이 적용된다.
* 베타 기능으로, 기본적으로 활성화되어 있다.
클러스터 수준에서 `endPort` 필드를 비활성화하려면, 사용자(또는 클러스터 관리자)가
API 서버에 대해 `--feature-gates=NetworkPolicyEndPort=false,…` 명령을 이용하여
`NetworkPolicyEndPort` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 비활성화해야 한다.
* `endPort` 필드는 `port` 필드보다 크거나 같아야 한다.
* `endPort``port` 도 정의된 경우에만 정의할 수 있다.
* 두 포트 모두 숫자여야 한다.

View File

@ -287,7 +287,7 @@ DNS 레코드를 구성하고, 라운드-로빈 이름 확인 방식을
낮거나 0이면 DNS에 부하가 높아 관리하기가
어려워 질 수 있다.
본 페이지의 뒷 부분에서 다양한 kube-proxy 구현의 동작에 대해 읽을 수 있다.
본 페이지의 뒷 부분에서 다양한 kube-proxy 구현이 동작하는 방식에 대해 읽을 수 있다.
우선 알아두어야 할 것은, `kube-proxy`를 구동할 때, 커널 수준의 규칙이
수정(예를 들어, iptables 규칙이 생성될 수 있음)될 수 있고,
이는 때로는 리부트 전까지 정리되지 않을 수도 있다.
@ -504,17 +504,17 @@ kube-proxy는 마치 외부 트래픽 정책이 `Cluster`로 설정되어 있는
지원한다.
예를 들어, TCP 포트 6379를 개방하고
클러스터 IP 주소 10.0.0.11이 할당된 서비스 `redis-master`는,
클러스터 IP 주소 10.0.0.11이 할당된 서비스 `redis-primary`는,
다음 환경 변수를 생성한다.
```shell
REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
REDIS_PRIMARY_SERVICE_HOST=10.0.0.11
REDIS_PRIMARY_SERVICE_PORT=6379
REDIS_PRIMARY_PORT=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_PRIMARY_PORT_6379_TCP_PROTO=tcp
REDIS_PRIMARY_PORT_6379_TCP_PORT=6379
REDIS_PRIMARY_PORT_6379_TCP_ADDR=10.0.0.11
```
{{< note >}}
@ -1325,15 +1325,15 @@ IP 주소를 정리한다.
#### `type: ClusterIP` 서비스의 IP 주소 범위 {#service-ip-static-sub-range}
{{< feature-state for_k8s_version="v1.24" state="alpha" >}}
{{< feature-state for_k8s_version="v1.25" state="beta" >}}
그러나, 이러한 `ClusterIP` 할당 전략에는 한 가지 문제가 있는데,
그것은 사용자 또한 [서비스의 IP 주소를 직접 고를 수 있기 때문이다](#choosing-your-own-ip-address).
이로 인해 만약 내부 할당기(allocator)가 다른 서비스에 대해 동일한 IP 주소를 선택하면
충돌이 발생할 수 있다.
`ServiceIPStaticSubrange`
[기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 활성화하면,
할당 전략은 `min(max(16, cidrSize / 16), 256)` 공식을 사용하여 얻어진
[기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)는 v1.25 이상에서 기본적으로 활성화되며,
이 때 사용하는 할당 전략은 `min(max(16, cidrSize / 16), 256)` 공식을 사용하여 얻어진
`service-cluster-ip-range`의 크기에 기반하여 `ClusterIP` 범위를 두 대역으로 나누며,
여기서 이 공식은 _16 이상 256 이하이며, 그 사이에 계단 함수가 있음_ 으로 설명할 수 있다.
동적 IP 할당은 상위 대역에서 우선적으로 선택하며,

View File

@ -147,7 +147,7 @@ kube-proxy 구성요소는 엔드포인트슬라이스 컨트롤러가 설정한
준비되지 않은(unready) 노드는 무시한다.
이 때문에 많은 노드가 준비되지 않은 상태에서는 의도하지 않은 결과가 나타날 수도 있다.
* 엔드포인트슬라이스 컨트롤러는 각 존 내의 비율을 계산할 때
* 엔드포인트슬라이스 컨트롤러는 각 존 내의 비율을 배포하거나 계산할 때
{{< glossary_tooltip text="톨러레이션" term_id="toleration" >}}은 고려하지 않는다.
서비스를 구성하는 파드가 클러스터의 일부 노드에만 배치되어 있는 경우,
이러한 상황은 고려되지 않을 것이다.

View File

@ -74,10 +74,7 @@ kubelet에서 관리하는 디스크와 성능 특성이 다른 스토리지,
### CSI 임시 볼륨 {#csi-ephemeral-volumes}
{{< feature-state for_k8s_version="v1.16" state="beta" >}}
이 기능을 사용하려면 `CSIInlineVolume` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 활성화해야 한다.
쿠버네티스 1.16부터는 기본적으로 활성화되어 있다.
{{< feature-state for_k8s_version="v1.25" state="stable" >}}
{{< note >}}
CSI 드라이버 중 일부만 CSI 임시 볼륨을 지원한다.

View File

@ -9,7 +9,7 @@ title: 퍼시스턴트 볼륨
feature:
title: 스토리지 오케스트레이션
description: >
로컬 스토리지, <a href="https://cloud.google.com/storage/">GCP</a><a href="https://aws.amazon.com/products/storage/">AWS</a>와 같은 퍼블릭 클라우드 공급자 또는 NFS, iSCSI, Gluster, Ceph, Cinder나 Flocker와 같은 네트워크 스토리지 시스템에서 원하는 스토리지 시스템을 자동으로 마운트한다.
로컬 스토리지, <a href="https://aws.amazon.com/products/storage/">AWS</a><a href="https://cloud.google.com/storage/">GCP</a>와 같은 퍼블릭 클라우드 공급자 또는 NFS, iSCSI, Ceph, Cinder와 같은 네트워크 스토리지 시스템에서 원하는 스토리지 시스템을 자동으로 마운트한다.
content_type: concept
weight: 20
---
@ -166,7 +166,7 @@ spec:
path: /any/path/it/will/be/replaced
containers:
- name: pv-recycler
image: "k8s.gcr.io/busybox"
image: "registry.k8s.io/busybox"
command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/* && test -z \"$(ls -A /scrub)\" || exit 1"]
volumeMounts:
- name: vol
@ -238,10 +238,9 @@ Source:
Events: <none>
```
특정 인-트리 볼륨 플러그인에 대해 `CSIMigration` 기능을 활성화하면 `kubernetes.io/pv-controller` 파이널라이저는 제거되고,
`external-provisioner.volume.kubernetes.io/finalizer` 파이널라이저가 추가된다.
이와 비슷하게, `CSIMigration` 기능을 비활성화하면 `external-provisioner.volume.kubernetes.io/finalizer` 파이널라이저는 제거되고,
`kubernetes.io/pv-controller` 파이널라이저가 추가된다.
특정 인-트리 볼륨 플러그인에 대해 `CSIMigration{provider}` 기능 플래그가 활성화되어 있을 때,
`kubernetes.io/pv-controller` 파이널라이저는
`external-provisioner.volume.kubernetes.io/finalizer` 파이널라이저로 대체된다.
### 퍼시스턴트볼륨 예약
@ -286,7 +285,7 @@ spec:
### 퍼시스턴트 볼륨 클레임 확장
{{< feature-state for_k8s_version="v1.11" state="beta" >}}
{{< feature-state for_k8s_version="v1.24" state="stable" >}}
퍼시스턴트볼륨클레임(PVC) 확장 지원은 기본적으로 활성화되어 있다. 다음 유형의
볼륨을 확장할 수 있다.
@ -413,14 +412,9 @@ PVC 확장 실패의 사용자에 의한 복구는 쿠버네티스 1.23부터
퍼시스턴트볼륨 유형은 플러그인으로 구현된다. 쿠버네티스는 현재 다음의 플러그인을 지원한다.
* [`awsElasticBlockStore`](/ko/docs/concepts/storage/volumes/#awselasticblockstore) - AWS Elastic Block Store (EBS)
* [`azureDisk`](/ko/docs/concepts/storage/volumes/#azuredisk) - Azure Disk
* [`azureFile`](/ko/docs/concepts/storage/volumes/#azurefile) - Azure File
* [`cephfs`](/ko/docs/concepts/storage/volumes/#cephfs) - CephFS 볼륨
* [`csi`](/ko/docs/concepts/storage/volumes/#csi) - 컨테이너 스토리지 인터페이스 (CSI)
* [`fc`](/ko/docs/concepts/storage/volumes/#fc) - Fibre Channel (FC) 스토리지
* [`gcePersistentDisk`](/ko/docs/concepts/storage/volumes/#gcepersistentdisk) - GCE Persistent Disk
* [`glusterfs`](/ko/docs/concepts/storage/volumes/#glusterfs) - Glusterfs 볼륨
* [`hostPath`](/ko/docs/concepts/storage/volumes/#hostpath) - HostPath 볼륨
(단일 노드 테스트 전용. 다중-노드 클러스터에서 작동하지 않음.
대신 `로컬` 볼륨 사용 고려)
@ -428,29 +422,41 @@ PVC 확장 실패의 사용자에 의한 복구는 쿠버네티스 1.23부터
* [`local`](/ko/docs/concepts/storage/volumes/#local) - 노드에 마운트된
로컬 스토리지 디바이스
* [`nfs`](/ko/docs/concepts/storage/volumes/#nfs) - 네트워크 파일 시스템 (NFS) 스토리지
* [`portworxVolume`](/ko/docs/concepts/storage/volumes/#portworxvolume) - Portworx 볼륨
* [`rbd`](/ko/docs/concepts/storage/volumes/#rbd) - Rados Block Device (RBD) 볼륨
* [`vsphereVolume`](/ko/docs/concepts/storage/volumes/#vspherevolume) - vSphere VMDK 볼륨
아래의 PersistentVolume 타입은 사용 중단되었다. 이 말인 즉슨, 지원은 여전히 제공되지만 추후 쿠버네티스 릴리스에서는 삭제될 예정이라는 것이다.
* [`awsElasticBlockStore`](/ko/docs/concepts/storage/volumes/#awselasticblockstore) - AWS Elastic Block Store (EBS)
(v1.17에서 **사용 중단**)
* [`azureDisk`](/ko/docs/concepts/storage/volumes/#azuredisk) - Azure Disk
(v1.19에서 **사용 중단**)
* [`azureFile`](/ko/docs/concepts/storage/volumes/#azurefile) - Azure File
(v1.21에서 **사용 중단**)
* [`cinder`](/ko/docs/concepts/storage/volumes/#cinder) - Cinder (오픈스택 블록 스토리지)
(v1.18에서 **사용 중단**)
* [`flexVolume`](/ko/docs/concepts/storage/volumes/#flexvolume) - FlexVolume
(v1.23에서 **사용 중단**)
* [`flocker`](/ko/docs/concepts/storage/volumes/#flocker) - Flocker 스토리지
(v1.22에서 **사용 중단**)
* [`quobyte`](/ko/docs/concepts/storage/volumes/#quobyte) - Quobyte 볼륨
(v1.22에서 **사용 중단**)
* [`storageos`](/ko/docs/concepts/storage/volumes/#storageos) - StorageOS 볼륨
(v1.22에서 **사용 중단**)
* [`gcePersistentDisk`](/ko/docs/concepts/storage/volumes/#gcepersistentdisk) - GCE Persistent Disk
(v1.17에서 **사용 중단**)
* [`glusterfs`](/ko/docs/concepts/storage/volumes/#glusterfs) - Glusterfs 볼륨
(v1.25에서 **사용 중단**)
* [`portworxVolume`](/ko/docs/concepts/storage/volumes/#portworxvolume) - Portworx 볼륨
(v1.25에서 **사용 중단**)
* [`vsphereVolume`](/ko/docs/concepts/storage/volumes/#vspherevolume) - vSphere VMDK 볼륨
(v1.19에서 **사용 중단**)
이전 쿠버네티스 버전은 아래의 인-트리 PersistentVolume 타입도 지원했었다.
* `photonPersistentDisk` - Photon 컨트롤러 퍼시스턴트 디스크.
(v1.15 이후 **사용 불가**)
(v1.15부터 **사용 불가**)
* [`scaleIO`](/ko/docs/concepts/storage/volumes/#scaleio) - ScaleIO 볼륨
(v1.21 이후 **사용 불가**)
(v1.21부터 **사용 불가**)
* [`flocker`](/ko/docs/concepts/storage/volumes/#flocker) - Flocker 스토리지
(v1.25부터 **사용 불가**)
* [`quobyte`](/ko/docs/concepts/storage/volumes/#quobyte) - Quobyte 볼륨
(v1.25부터 **사용 불가**)
* [`storageos`](/ko/docs/concepts/storage/volumes/#storageos) - StorageOS 볼륨
(v1.25부터 **사용 불가**)
## 퍼시스턴트 볼륨
@ -562,17 +568,14 @@ CLI에서 접근 모드는 다음과 같이 약어로 표시된다.
| CSI | 드라이버에 의존 | 드라이버에 의존 | 드라이버에 의존 | 드라이버에 의존 |
| FC | &#x2713; | &#x2713; | - | - |
| FlexVolume | &#x2713; | &#x2713; | 드라이버에 의존 | - |
| Flocker | &#x2713; | - | - | - |
| GCEPersistentDisk | &#x2713; | &#x2713; | - | - |
| Glusterfs | &#x2713; | &#x2713; | &#x2713; | - |
| HostPath | &#x2713; | - | - | - |
| iSCSI | &#x2713; | &#x2713; | - | - |
| Quobyte | &#x2713; | &#x2713; | &#x2713; | - |
| NFS | &#x2713; | &#x2713; | &#x2713; | - |
| RBD | &#x2713; | &#x2713; | - | - |
| VsphereVolume | &#x2713; | - | - (파드를 배치할(collocated) 때 동작한다) | - |
| PortworxVolume | &#x2713; | - | &#x2713; | - | - |
| StorageOS | &#x2713; | - | - | - |
### 클래스
@ -616,9 +619,7 @@ PV는 `storageClassName` 속성을
* `glusterfs`
* `iscsi`
* `nfs`
* `quobyte` (v1.22에서 **사용 중단됨**)
* `rbd`
* `storageos` (v1.22에서 **사용 중단됨**)
* `vsphereVolume`
마운트 옵션의 유효성이 검사되지 않는다. 마운트 옵션이 유효하지 않으면, 마운트가 실패한다.
@ -718,9 +719,13 @@ PVC는 항상 클래스가 없는 PV를 요청하는 것으로 해석되므로
플러그인은 모든 PVC 생성을
금지한다.
* 어드미션 플러그인이 꺼져 있으면 기본 스토리지클래스에 대한 기본값 자체가 없다.
`storageClassName`이 없는 모든 PVC는 클래스가 없는 PV에만 바인딩할 수 있다. 이 경우
`storageClassName`이 없는 PVC는 `storageClassName``""`로 설정된 PVC와
같은 방식으로 처리된다.
`storageClassName``""`으로 설정된 모든 PVC는
`storageClassName`이 마찬가지로 `""`로 설정된 PV에만 바인딩할 수 있다.
하지만, `storageClassName`이 없는 PVC는
기본 스토리지클래스가 사용 가능해지면 갱신될 수 있다. PVC가 갱신되면
해당 PVC는 더 이상 `storageClassName``""`로 설정된 PV와 바인딩되어있지 않게 된다.
더 자세한 정보는 [retroactive default StorageClass assignment](#retroactive-default-storageclass-assignment)를 참조한다.
설치 방법에 따라 설치 중에 애드온 관리자가 기본 스토리지클래스를 쿠버네티스 클러스터에
배포할 수 있다.
@ -737,6 +742,20 @@ AND 조건으로 동작한다. 요청된 클래스와 요청된 레이블이 있
속성 대신 사용되었다. 이 어노테이션은 아직까지는 사용할 수 있지만,
향후 쿠버네티스 릴리스에서는 지원되지 않는다.
#### 기본 스토리지클래스 할당 소급 적용하기 {#retroactive-default-storageclass-assignment}
{{< feature-state for_k8s_version="v1.25" state="alpha" >}}
새로운 PVC를 위한 `storageClassName`을 설정하지 않고 퍼시스턴트볼륨클레임을 생성할 수 있으며, 이는 클러스터에 기본 스토리지클래스가 존재하지 않을 때에도 가능하다. 이 경우, 새로운 PVC는 정의된 대로 생성되며, 해당 PVC의 `storageClassName`은 기본값이 사용 가능해질 때까지 미설정 상태로 남는다.
하지만, [`RetroactiveDefaultStorageClass` 기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를 활성화하면 쿠버네티스는 다르게 동작하여, 기존에 존재하는 PVC 중 `storageClassName`가 설정되지 않은 PVC는 새로운 기본 스토리지클래스를 사용하도록 갱신된다.
기본 스토리지클래스가 사용 가능해지면, 컨트롤플레인은 `storageClassName`가 없는 PVC를 찾는다. `storageClassName`의 값이 비어있거나 해당 키 자체가 없는 PVC라면, 컨트롤플레인은 해당 PVC의 `storageClassName`가 새로운 기본 스토리지클래스와 일치하도록 설정하여 갱신한다. `storageClassName``""`인 PVC가 있고, 기본 스토리지클래스를 설정한다면, 해당 PVC는 갱신되지 않는다.
기본 스토리지클래스가 존재할 때 `storageClassName``""`로 설정된 PV와의 바인딩을 유지하고싶다면, 연결된 PVC의 `storageClassName``""`로 설정해야 한다.
이 행동은 관리자가 오래된 기본 스토리지클래스를 삭제하고 새로운 기본 스토리지클래스를 생성하거나 설정하여 기본 스토리지클래스를 변경하는 데 도움이 된다. 기본값이 설정되어있지 않을 때의 이 작은 틈새로 인해 이 때 생성된 `storageClassName`가 없는 PVC는 아무런 기본값도 없이 생성될 수 있지만, 기본 스토리지클래스 할당 소급 적용에 의해 이러한 방식으로 기본값을 변경하는 것은 안전하다.
## 볼륨으로 클레임하기
클레임을 볼륨으로 사용해서 파드가 스토리지에 접근한다. 클레임은 클레임을 사용하는 파드와 동일한 네임스페이스에 있어야 한다. 클러스터는 파드의 네임스페이스에서 클레임을 찾고 이를 사용하여 클레임과 관련된 퍼시스턴트볼륨을 얻는다. 그런 다음 볼륨이 호스트와 파드에 마운트된다.

View File

@ -70,7 +70,7 @@ weight: 70
볼륨을 생성한 후에, 스케줄러는
볼륨을 사용할 수 있는 노드에 파드를 스케줄링한다.
[CSI 임시 볼륨](/ko/docs/concepts/storage/volumes/#csi)의 경우에는
[CSI 임시 볼륨](/ko/docs/concepts/storage/ephemeral-volumes/#csi-ephemeral-volumes)의 경우에는
볼륨 유형이 로컬 볼륨이고
큰 자원이 필요하지 않은 특정 CSI 드라이버에서만 사용된다는 가정하에,
항상 스토리지 용량을 고려하지 않고

View File

@ -71,17 +71,13 @@ volumeBindingMode: Immediate
| Cinder | &#x2713; | [OpenStack Cinder](#openstack-cinder)|
| FC | - | - |
| FlexVolume | - | - |
| Flocker | &#x2713; | - |
| GCEPersistentDisk | &#x2713; | [GCE PD](#gce-pd) |
| Glusterfs | &#x2713; | [Glusterfs](#glusterfs) |
| iSCSI | - | - |
| Quobyte | &#x2713; | [Quobyte](#quobyte) |
| NFS | - | [NFS](#nfs) |
| RBD | &#x2713; | [Ceph RBD](#ceph-rbd) |
| VsphereVolume | &#x2713; | [vSphere](#vsphere) |
| PortworxVolume | &#x2713; | [Portworx 볼륨](#portworx-볼륨) |
| ScaleIO | &#x2713; | [ScaleIO](#scaleio) |
| StorageOS | &#x2713; | [StorageOS](#storageos) |
| Local | - | [Local](#local) |
여기 목록에서 "내부" 프로비저너를 지정할 수 있다(이
@ -413,7 +409,7 @@ parameters:
* Distribute 볼륨: `volumetype: none`
사용 가능한 볼륨 유형과 관리 옵션에 대해서는
[관리 가이드](https://access.redhat.com/documentation/en-US/Red_Hat_Storage/3.1/html/Administration_Guide/part-Overview.html)를 참조한다.
[관리 가이드](https://access.redhat.com/documentation/en-us/red_hat_gluster_storage/)를 참조한다.
자세한 정보는
[Heketi 구성 방법](https://github.com/heketi/heketi/wiki/Setting-up-the-topology)을 참조한다.
@ -473,7 +469,7 @@ vSphere 스토리지 클래스에는 두 가지 유형의 프로비저닝 도구
- [CSI 프로비저닝 도구](#vsphere-provisioner-csi): `csi.vsphere.vmware.com`
- [vCP 프로비저닝 도구](#vcp-프로비저닝-도구): `kubernetes.io/vsphere-volume`
인-트리 프로비저닝 도구는 [사용 중단](/blog/2019/12/09/kubernetes-1-17-feature-csi-migration-beta/#why-are-we-migrating-in-tree-plugins-to-csi)되었다. CSI 프로비저닝 도구에 대한 자세한 내용은 [쿠버네티스 vSphere CSI 드라이버](https://vsphere-csi-driver.sigs.k8s.io/) 및 [vSphereVolume CSI 마이그레이션](/ko/docs/concepts/storage/volumes/#csi-마이그레이션)을 참고한다.
인-트리 프로비저닝 도구는 [사용 중단](/blog/2019/12/09/kubernetes-1-17-feature-csi-migration-beta/#why-are-we-migrating-in-tree-plugins-to-csi)되었다. CSI 프로비저닝 도구에 대한 자세한 내용은 [쿠버네티스 vSphere CSI 드라이버](https://vsphere-csi-driver.sigs.k8s.io/) 및 [vSphereVolume CSI 마이그레이션](/ko/docs/concepts/storage/volumes/#vsphere-csi-migration)을 참고한다.
#### CSI 프로비저닝 도구 {#vsphere-provisioner-csi}
@ -544,7 +540,7 @@ vSphere CSI 스토리지클래스 프로비저닝 도구는 Tanzu 쿠버네티
스토어에 분산되어 요구 사항을 충족시키게 된다.
퍼시스턴트 볼륨 관리에 스토리지 정책을 사용하는 방법에 대한 자세한 내용은
[볼륨의 동적 프로비저닝을 위한 스토리지 정책 기반 관리(SPBM)](https://vmware.github.io/vsphere-storage-for-kubernetes/documentation/policy-based-mgmt.html)를
[볼륨의 동적 프로비저닝을 위한 스토리지 정책 기반 관리(SPBM)](https://github.com/vmware-archive/vsphere-storage-for-kubernetes/blob/fa4c8b8ad46a85b6555d715dd9d27ff69839df53/documentation/policy-based-mgmt.md)를
참조한다.
vSphere용 쿠버네티스 내에서 퍼시스턴트 볼륨 관리를 시도하는
@ -599,61 +595,6 @@ parameters:
경우에만 사용해야 한다. 현재 `layering` 에서만 기능이 지원된다.
기본값은 ""이며, 기능이 설정되어 있지 않다.
### Quobyte
{{< feature-state for_k8s_version="v1.22" state="deprecated" >}}
Quobyte 인-트리 스토리지 플러그인은 사용 중단되었으며,
아웃-오브-트리 Quobyte 플러그인에 대한 [예제](https://github.com/quobyte/quobyte-csi/blob/master/example/StorageClass.yaml)
`StorageClass`는 Quobyte CSI 저장소에서 찾을 수 있다.
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/quobyte
parameters:
quobyteAPIServer: "http://138.68.74.142:7860"
registry: "138.68.74.142:7861"
adminSecretName: "quobyte-admin-secret"
adminSecretNamespace: "kube-system"
user: "root"
group: "root"
quobyteConfig: "BASE"
quobyteTenant: "DEFAULT"
```
* `quobyteAPIServer`: `"http(s)://api-server:7860"` 형식의
Quobyte의 API 서버이다.
* `registry`: 볼륨을 마운트하는 데 사용할 Quobyte 레지스트리이다. 레지스트리를
``<host>:<port>`` 의 쌍으로 지정하거나 여러 레지스트리를
지정하려면 쉼표만 있으면 된다.
예: ``<host1>:<port>,<host2>:<port>,<host3>:<port>``
호스트는 IP 주소이거나 DNS가 작동 중인 경우
DNS 이름을 제공할 수도 있다.
* `adminSecretNamespace`: `adminSecretName` 의 네임스페이스.
기본값은 "default".
* `adminSecretName`: 시크릿은 API 서버에 대해 인증하기 위한 Quobyte 사용자와 암호에
대한 정보를 담고 있다. 제공된 시크릿은 "kubernetes.io/quobyte"
유형과 `user``password` 키를 가져야 하며, 예를 들면
다음과 같다.
```shell
kubectl create secret generic quobyte-admin-secret \
--type="kubernetes.io/quobyte" --from-literal=user='admin' --from-literal=password='opensesame' \
--namespace=kube-system
```
* `user`: 이 사용자에 대한 모든 접근을 매핑한다. 기본값은 "root".
* `group`: 이 그룹에 대한 모든 접근을 매핑한다. 기본값은 "nfsnobody".
* `quobyteConfig`: 지정된 구성을 사용해서 볼륨을 생성한다. 웹 콘솔
또는 quobyte CLI를 사용해서 새 구성을 작성하거나 기존 구성을
수정할 수 있다. 기본값은 "BASE".
* `quobyteTenant`: 지정된 테넌트 ID를 사용해서 볼륨을 생성/삭제한다.
이 Quobyte 테넌트는 이미 Quobyte에 있어야 한다.
기본값은 "DEFAULT".
### Azure 디스크
#### Azure 비관리 디스크 스토리지 클래스 {#azure-unmanaged-disk-storage-class}
@ -782,96 +723,6 @@ parameters:
카산드라와 같은 데이터베이스는 false로 설정해야 한다. `true/false` (기본값 `false`)
여기에는 문자열, 즉 `true` 가 아닌, `"true"` 가 필요하다.
### ScaleIO
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/scaleio
parameters:
gateway: https://192.168.99.200:443/api
system: scaleio
protectionDomain: pd0
storagePool: sp1
storageMode: ThinProvisioned
secretRef: sio-secret
readOnly: "false"
fsType: xfs
```
* `provisioner`: 속성이 `kubernetes.io/scaleio` 로 설정되어 있다.
* `gateway`: ScaleIO API 게이트웨이 주소(필수)
* `system`: ScaleIO 시스템의 이름(필수)
* `protectionDomain`: ScaleIO 보호 도메인의 이름(필수)
* `storagePool`: 볼륨 스토리지 풀의 이름(필수)
* `storageMode`: 스토리지 프로비전 모드: `ThinProvisioned` (기본값) 또는
`ThickProvisioned`
* `secretRef`: 구성된 시크릿 오브젝트에 대한 참조(필수)
* `readOnly`: 마운트된 볼륨에 대한 접근 모드의 지정(기본값: false)
* `fsType`: 볼륨에 사용할 파일 시스템 유형(기본값: ext4)
ScaleIO 쿠버네티스 볼륨 플러그인에는 구성된 시크릿 오브젝트가 필요하다.
시크릿은 다음 명령에 표시된 것처럼 `kubernetes.io/scaleio` 유형으로
작성해야 하며, PVC와 동일한 네임스페이스
값을 사용해야 한다.
```shell
kubectl create secret generic sio-secret --type="kubernetes.io/scaleio" \
--from-literal=username=sioadmin --from-literal=password=d2NABDNjMA== \
--namespace=default
```
### StorageOS
```yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast
provisioner: kubernetes.io/storageos
parameters:
pool: default
description: Kubernetes volume
fsType: ext4
adminSecretNamespace: default
adminSecretName: storageos-secret
```
* `pool`: 볼륨을 프로비전할 StorageOS 분산 용량
풀의 이름. 지정되지 않은 경우 일반적으로 존재하는 `default` 풀을 사용한다.
* `description`: 동적으로 생성된 볼륨에 할당할 설명.
모든 볼륨 설명은 스토리지 클래스에 대해 동일하지만, 서로 다른
유스케이스에 대한 설명을 허용하기 위해 다른 스토리지 클래스를 사용할 수 있다.
기본값은 `Kubernetes volume`.
* `fsType`: 요청할 기본 파일 시스템 유형. StorageOS 내의 사용자
정의 규칙이 이 값을 무시할 수 있다. 기본 값은 `ext4`.
* `adminSecretNamespace`: API 구성 시크릿이 있는 네임스페이스.
adminSecretName 이 설정된 경우 필수이다.
* `adminSecretName`: StorageOS API 자격증명을 얻는 데 사용할 시크릿의 이름.
지정하지 않으면 기본값이 시도된다.
StorageOS 쿠버네티스 볼륨 플러그인은 시크릿 오브젝트를 사용해서 StorageOS API에
접근하기 위한 엔드포인트와 자격증명을 지정할 수 있다. 이것은 기본값이
변경된 경우에만 필요하다.
시크릿은 다음의 명령과 같이 `kubernetes.io/storageos` 유형으로
만들어야 한다.
```shell
kubectl create secret generic storageos-secret \
--type="kubernetes.io/storageos" \
--from-literal=apiAddress=tcp://localhost:5705 \
--from-literal=apiUsername=storageos \
--from-literal=apiPassword=storageos \
--namespace=default
```
동적으로 프로비전된 볼륨에 사용되는 시크릿은 모든 네임스페이스에서
생성할 수 있으며 `adminSecretNamespace` 파라미터로 참조될 수 있다.
사전에 프로비전된 볼륨에서 사용하는 시크릿은 이를 참조하는 PVC와
동일한 네임스페이스에서 작성해야 한다.
### Local
{{< feature-state for_k8s_version="v1.14" state="stable" >}}
@ -892,3 +743,4 @@ volumeBindingMode: WaitForFirstConsumer
볼륨 바인딩을 지연시키면 스케줄러가 퍼시스턴트볼륨클레임에
적절한 퍼시스턴트볼륨을 선택할 때 파드의 모든 스케줄링
제약 조건을 고려할 수 있다.

View File

@ -32,8 +32,8 @@ weight: 60
* 복제 지원은 동적 프로비저너만 사용할 수 있다.
* CSI 드라이버는 볼륨 복제 기능을 구현했거나 구현하지 않았을 수 있다.
* PVC는 대상 PVC와 동일한 네임스페이스에 있는 경우에만 복제할 수 있다(소스와 대상은 동일한 네임스페이스에 있어야 함).
* 복제는 동일한 스토리지 클래스 내에서만 지원된다.
- 대상 볼륨은 소스와 동일한 스토리지 클래스여야 한다.
* 복제는 서로 다른 스토리지 클래스에 대해서도 지원된다.
- 대상 볼륨은 소스와 동일하거나 다른 스토리지 클래스여도 된다.
- 기본 스토리지 클래스를 사용할 수 있으며, 사양에 storageClassName을 생략할 수 있다.
* 동일한 VolumeMode 설정을 사용하는 두 볼륨에만 복제를 수행할 수 있다(블록 모드 볼륨을 요청하는 경우에는 반드시 소스도 블록 모드여야 한다).

View File

@ -155,6 +155,8 @@ spec:
소스 볼륨 모드가 명시되어 있지 않으면,
쿠버네티스는 해당 스냅샷의 소스 볼륨 모드를 알려지지 않은 상태(unknown)로 간주하여 스냅샷을 처리한다.
`volumeSnapshotRef`은 상응하는 `VolumeSnapshot`의 참조이다. `VolumeSnapshotContent`이 이전에 프로비전된 스냅샷으로 생성된 경우, `volumeSnapshotRef`에서 참조하는 `VolumeSnapshot`은 아직 존재하지 않을 수도 있음에 주의한다.
## 스냅샷의 볼륨 모드 변환하기 {#convert-volume-mode}
클러스터에 설치된 `VolumeSnapshots` API가 `sourceVolumeMode` 필드를 지원한다면,

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