Merge pull request #29237 from kubernetes/dev-1.21-ko.7

[ko] 7th Korean localization work for v1.21
pull/29249/head
Kubernetes Prow Robot 2021-08-05 02:25:22 -07:00 committed by GitHub
commit a772fcf9cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 1525 additions and 250 deletions

View File

@ -210,7 +210,7 @@ rules:
자체 클라우드 컨트롤러 매니저를 구현하거나 기존 프로젝트를 확장하는 방법을 알고 싶은가?
클라우드 컨트롤러 매니저는 Go 인터페이스를 사용해서 모든 클라우드 플러그인을 구현할 수 있다. 구체적으로, [kubernetes/cloud-provider](https://github.com/kubernetes/cloud-provider)의 [`cloud.go`](https://github.com/kubernetes/cloud-provider/blob/release-1.17/cloud.go#L42-L62)에 정의된 `CloudProvider` 인터페이스를 사용한다.
클라우드 컨트롤러 매니저는 Go 인터페이스를 사용함으로써, 어떠한 클라우드에 대한 구현체(implementation)라도 플러그인 될 수 있도록 한다. 구체적으로는, [kubernetes/cloud-provider](https://github.com/kubernetes/cloud-provider)의 [`cloud.go`](https://github.com/kubernetes/cloud-provider/blob/release-1.21/cloud.go#L42-L69)에 정의된 `CloudProvider` 인터페이스를 사용한다.
이 문서(노드, 라우트와 서비스)에서 강조된 공유 컨트롤러의 구현과 공유 cloudprovider 인터페이스와 함께 일부 스캐폴딩(scaffolding)은 쿠버네티스 핵심의 일부이다. 클라우드 공급자 전용 구현은 쿠버네티스의 핵심 바깥에 있으며 `CloudProvider` 인터페이스를 구현한다.

View File

@ -83,8 +83,11 @@ kubectl logs counter
[`configure-helper` 스크립트](https://github.com/kubernetes/kubernetes/blob/{{< param "githubbranch" >}}/cluster/gce/gci/configure-helper.sh)를 통해
자세히 알 수 있다.
**CRI 컨테이너 런타임** 을 사용할 때, kubelet은 로그를 로테이션하고 로깅 디렉터리 구조를 관리한다. kubelet은
이 정보를 CRI 컨테이너 런타임에 전송하고 런타임은 컨테이너 로그를 지정된 위치에 기록한다. 두 개의 kubelet 플래그 `container-log-max-size``container-log-max-files` 를 사용하여 각 로그 파일의 최대 크기와 각 컨테이너에 허용되는 최대 파일 수를 각각 구성할 수 있다.
**CRI 컨테이너 런타임** 을 사용할 때, kubelet은 로그를 로테이션하고 로깅 디렉터리 구조를 관리한다.
kubelet은 이 정보를 CRI 컨테이너 런타임에 전송하고 런타임은 컨테이너 로그를 지정된 위치에 기록한다.
[kubelet config file](/docs/tasks/administer-cluster/kubelet-config-file/)에 있는
두 개의 kubelet 파라미터 [`containerLogMaxSize` 및 `containerLogMaxFiles`](/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)를
사용하여 각 로그 파일의 최대 크기와 각 컨테이너에 허용되는 최대 파일 수를 각각 구성할 수 있다.
기본 로깅 예제에서와 같이 [`kubectl logs`](/docs/reference/generated/kubectl/kubectl-commands#logs)를
실행하면, 노드의 kubelet이 요청을 처리하고

View File

@ -1156,8 +1156,8 @@ HTTP 요청을 처리하고, 복잡한 비즈니스 로직을 수행한 다음,
### 시크릿 API를 사용하는 클라이언트
시크릿 API와 상호 작용하는 애플리케이션을 배포할 때,
[RBAC](/docs/reference/access-authn-authz/rbac/)과 같은
시크릿 API와 상호 작용하는 애플리케이션을 배포할 때,
[RBAC](/docs/reference/access-authn-authz/rbac/)과 같은
[인가 정책](/ko/docs/reference/access-authn-authz/authorization/)을
사용하여 접근을 제한해야 한다.
@ -1235,10 +1235,6 @@ API 서버에서 kubelet으로의 통신은 SSL/TLS로 보호된다.
- 시크릿을 사용하는 파드를 생성할 수 있는 사용자는 해당 시크릿의 값도 볼 수 있다.
API 서버 정책이 해당 사용자가 시크릿을 읽을 수 있도록 허용하지 않더라도, 사용자는
시크릿을 노출하는 파드를 실행할 수 있다.
- 현재, 모든 노드에 대한 루트 권한이 있는 모든 사용자는 kubelet을 가장하여
API 서버에서 _모든_ 시크릿을 읽을 수 있다. 단일 노드에 대한 루트 취약점 공격의
영향을 제한하기 위해, 실제로 필요한 노드에만 시크릿을 보내는 것이 앞으로 계획된
기능이다.
## {{% heading "whatsnext" %}}

View File

@ -51,8 +51,7 @@ weight: 30
* 내부 멤버 선출 절차없이 분산 애플리케이션의
리더를 선택
오퍼레이터의 모습을 더 자세하게 볼 수 있는 방법은 무엇인가? 자세한 예는
다음과 같다.
오퍼레이터의 모습을 더 자세하게 볼 수 있는 방법은 무엇인가? 예시는 다음과 같다.
1. 클러스터에 구성할 수 있는 SampleDB라는 사용자 정의 리소스.
2. 오퍼레이터의 컨트롤러 부분이 포함된 파드의 실행을

View File

@ -72,7 +72,7 @@ spec:
## 넘어가기 전에: 내장 노드 레이블들 {#built-in-node-labels}
[붙인](#1-단계-노드에-레이블-붙이기) 레이블뿐만 아니라, 노드에는
표준 레이블 셋이 미리 채워져 있다. 이들 목록은 [잘 알려진 레이블, 어노테이션 및 테인트](/docs/reference/labels-annotations-taints/)를 참고한다.
표준 레이블 셋이 미리 채워져 있다. 이들 목록은 [잘 알려진 레이블, 어노테이션 및 테인트](/ko/docs/reference/labels-annotations-taints/)를 참고한다.
{{< note >}}
이 레이블들의 값은 클라우드 공급자에 따라 다르고 신뢰성이 보장되지 않는다.

View File

@ -0,0 +1,411 @@
---
title: 노드-압박 축출
content_type: concept
weight: 60
---
{{<glossary_definition term_id="node-pressure-eviction" length="short">}}</br>
{{<glossary_tooltip term_id="kubelet" text="kubelet">}}은
클러스터 노드의 CPU, 메모리, 디스크 공간, 파일시스템 inode와 같은 자원을 모니터링한다.
이러한 자원 중 하나 이상이 특정 소모 수준에 도달하면,
kubelet은 하나 이상의 파드를 능동적으로 중단시켜
자원을 회수하고 고갈 상황을 방지할 수 있다.
노드-압박 축출 과정에서, kubelet은 축출할 파드의 `PodPhase`
`Failed`로 설정한다. 이로써 파드가 종료된다.
노드-압박 축출은
[API를 이용한 축출](/ko/docs/concepts/scheduling-eviction/api-eviction/)과는 차이가 있다.
kubelet은 이전에 설정된 `PodDisruptionBudget` 값이나 파드의 `terminationGracePeriodSeconds` 값을 따르지 않는다.
[소프트 축출 임계값](#soft-eviction-thresholds)을 사용하는 경우,
kubelet은 이전에 설정된 `eviction-max-pod-grace-period` 값을 따른다.
[하드 축출 임계값](#hard-eviction-thresholds)을 사용하는 경우, 파드 종료 시 `0s` 만큼 기다린 후 종료한다(즉, 기다리지 않고 바로 종료한다).
실패한 파드를 새로운 파드로 교체하는
{{< glossary_tooltip text="워크로드" term_id="workload" >}} 리소스(예:
{{< glossary_tooltip text="스테이트풀셋(StatefulSet)" term_id="statefulset" >}} 또는
{{< glossary_tooltip text="디플로이먼트(Deployment)" term_id="deployment" >}})가 파드를 관리하는 경우,
컨트롤 플레인이나 `kube-controller-manager`가 축출된 파드를 대신할 새 파드를 생성한다.
{{<note>}}
kubelet은 최종 사용자 파드를 종료하기 전에
먼저 [노드 수준 자원을 회수](#reclaim-node-resources)하려고 시도한다.
예를 들어, 디스크 자원이 부족하면 먼저 사용하지 않는 컨테이너 이미지를 제거한다.
{{</note>}}
kubelet은 축출 결정을 내리기 위해 다음과 같은 다양한 파라미터를 사용한다.
* 축출 신호
* 축출 임계값
* 모니터링 간격
### 축출 신호 {#eviction-signals}
축출 신호는 특정 시점에서 특정 자원의 현재 상태이다.
Kubelet은 노드에서 사용할 수 있는 리소스의 최소량인
축출 임계값과 축출 신호를 비교하여
축출 결정을 내린다.
Kubelet은 다음과 같은 축출 신호를 사용한다.
| 축출 신호 | 설명 |
|----------------------|---------------------------------------------------------------------------------------|
| `memory.available` | `memory.available` := `node.status.capacity[memory]` - `node.stats.memory.workingSet` |
| `nodefs.available` | `nodefs.available` := `node.stats.fs.available` |
| `nodefs.inodesFree` | `nodefs.inodesFree` := `node.stats.fs.inodesFree` |
| `imagefs.available` | `imagefs.available` := `node.stats.runtime.imagefs.available` |
| `imagefs.inodesFree` | `imagefs.inodesFree` := `node.stats.runtime.imagefs.inodesFree` |
| `pid.available` | `pid.available` := `node.stats.rlimit.maxpid` - `node.stats.rlimit.curproc` |
이 표에서, `설명` 열은 kubelet이 축출 신호 값을 계산하는 방법을 나타낸다.
각 축출 신호는 백분율 또는 숫자값을 지원한다.
Kubelet은 총 용량 대비 축출 신호의 백분율 값을
계산한다.
`memory.available` 값은 `free -m`과 같은 도구가 아니라 cgroupfs로부터 도출된다.
이는 `free -m`이 컨테이너 안에서는 동작하지 않고, 또한 사용자가
[node allocatable](/docs/tasks/administer-cluster/reserve-compute-resources/#node-allocatable)
기능을 사용하는 경우 자원 부족에 대한 결정은 루트 노드뿐만 아니라
cgroup 계층 구조의 최종 사용자 파드 부분에서도 지역적으로 이루어지기 때문에 중요하다.
이 [스크립트](/examples/admin/resource/memory-available.sh)는
kubelet이 `memory.available`을 계산하기 위해 수행하는 동일한 단계들을 재현한다.
kubelet은 메모리 압박 상황에서 메모리가 회수 가능하다고 가정하므로,
inactive_file(즉, 비활성 LRU 목록의 파일 기반 메모리 바이트 수)을
계산에서 제외한다.
kubelet은 다음과 같은 파일시스템 파티션을 지원한다.
1. `nodefs`: 노드의 메인 파일시스템이며, 로컬 디스크 볼륨, emptyDir,
로그 스토리지 등에 사용된다. 예를 들어 `nodefs``/var/lib/kubelet/`을 포함한다.
1. `imagefs`: 컨테이너 런타임이 컨테이너 이미지 및
컨테이너 쓰기 가능 레이어를 저장하는 데 사용하는 선택적 파일시스템이다.
Kubelet은 이러한 파일시스템을 자동으로 검색하고 다른 파일시스템은 무시한다.
Kubelet은 다른 구성은 지원하지 않는다.
{{<note>}}
일부 kubelet 가비지 수집 기능은 더 이상 사용되지 않으며 축출로 대체되었다.
사용 중지된 기능의 목록은 [kubelet 가비지 수집 사용 중단](/ko/docs/concepts/cluster-administration/kubelet-garbage-collection/#사용-중단-deprecation)을 참조한다.
{{</note>}}
### 축출 임계값
kubelet이 축출 결정을 내릴 때 사용하는 축출 임계값을
사용자가 임의로 설정할 수 있다.
축출 임계값은 `[eviction-signal][operator][quantity]` 형태를 갖는다.
* `eviction-signal`에는 사용할 [축출 신호](#eviction-signals)를 적는다.
* `operator`에는 [관계연산자](https://ko.wikipedia.org/wiki/관계연산자#표준_관계연산자)를
적는다(예: `<` - 미만)
* `quantity`에는 `1Gi`와 같이 축출 임계값 수치를 적는다.
`quantity`에 들어가는 값은 쿠버네티스가 사용하는 수치 표현 방식과 맞아야 한다.
숫자값 또는 백분율(`%`)을 사용할 수 있다.
예를 들어, 노드에 총 `10Gi`의 메모리가 있고
`1Gi` 아래로 내려갔을 때 축출이 시작되도록 만들고 싶으면, 축출 임계값을
`memory.available<10%` 또는 `memory.available<1Gi` 형태로 정할 수 있다. 둘을 동시에 사용할 수는 없다.
소프트 축출 임계값과 하드 축출 임계값을 설정할 수 있다.
#### 소프트 축출 임계값 {#soft-eviction-thresholds}
소프트 축출 임계값은 관리자가 설정하는 유예 시간(필수)과 함께 정의된다.
kubelet은 유예 시간이 초과될 때까지 파드를 제거하지 않는다.
유예 시간이 지정되지 않으면 kubelet 시작 시
오류가 반환된다.
kubelet이 축출 과정에서 사용할 수 있도록,
'소프트 축출 임계값'과 '최대 허용 파드 종료 유예 시간' 둘 다를 설정할 수 있다.
'최대 허용 파드 종료 유예 시간'이 설정되어 있는 상태에서 '소프트 축출 임계값'에 도달하면,
kubelet은 두 유예 시간 중 작은 쪽을 적용한다.
'최대 허용 파드 종료 유예 시간'을 설정하지 않으면,
kubelet은 축출된 파드를 유예 시간 없이 즉시 종료한다.
소프트 축출 임계값을 설정할 때 다음과 같은 플래그를 사용할 수 있다.
* `eviction-soft`: 축출 임계값(예: `memory.available<1.5Gi`)의 집합이며,
지정된 유예 시간동안 이 축출 임계값 조건이 충족되면 파드 축출이 트리거된다.
* `eviction-soft-grace-period`: 축출 유예 시간의 집합이며,
소프트 축출 임계값 조건이 이 유예 시간동안 충족되면 파드 축출이 트리거된다.
* `eviction-max-pod-grace-period`: '최대 허용 파드 종료 유예 시간(단위: 초)'이며,
소프트 축출 임계값 조건이 충족되어 파드를 종료할 때 사용한다.
#### 하드 축출 임계값 {#hard-eviction-thresholds}
하드 축출 임계값에는 유예 시간이 없다. 하드 축출 임계값 조건이 충족되면,
kubelet은 고갈된 자원을 회수하기 위해 파드를 유예 시간 없이
즉시 종료한다.
`eviction-hard` 플래그를 사용하여 하드 축출
임계값(예: `memory.available<1Gi`)을 설정할 수 있다.
kubelet은 다음과 같은 하드 축출 임계값을 기본적으로 설정하고 있다.
* `memory.available<100Mi`
* `nodefs.available<10%`
* `imagefs.available<15%`
* `nodefs.inodesFree<5%` (리눅스 노드)
### 축출 모니터링 시간 간격
kubelet은 `housekeeping-interval`에 설정된 시간 간격(기본값: `10s`)마다
축출 임계값을 확인한다.
### 노드 컨디션 {#node-conditions}
kubelet은 하드/소프트 축출 임계값 조건이 충족되어
노드 압박이 발생했다는 것을 알리기 위해,
설정된 유예 시간과는 관계없이 노드 컨디션을 보고한다.
kubelet은 다음과 같이 노드 컨디션과 축출 신호를 매핑한다.
| 노드 컨디션 | 축출 신호 | 설명 |
|-------------------|---------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| `MemoryPressure` | `memory.available` | 노드의 가용 메모리 양이 축출 임계값에 도달함 |
| `DiskPressure` | `nodefs.available`, `nodefs.inodesFree`, `imagefs.available`, 또는 `imagefs.inodesFree` | 노드의 루트 파일시스템 또는 이미지 파일시스템의 가용 디스크 공간 또는 inode의 수가 축출 임계값에 도달함 |
| `PIDPressure` | `pid.available` | (리눅스) 노드의 가용 프로세스 ID(PID)가 축출 임계값 이하로 내려옴 |
kubelet은 `--node-status-update-frequency`에 설정된
시간 간격(기본값: `10s`)마다 노드 컨디션을 업데이트한다.
#### 노드 컨디션 진동(oscillation)
경우에 따라, 노드의 축출 신호값이 사전에 설정된 유예 시간 동안 유지되지 않고
소프트 축출 임계값을 중심으로 진동할 수 있다. 이로 인해 노드 컨디션이 계속
`true``false`로 바뀌며, 잘못된 축출 결정을 야기할 수 있다.
이러한 진동을 방지하기 위해, `eviction-pressure-transition-period` 플래그를
사용하여 kubelet이 노드 컨디션을 다른 상태로 바꾸기 위해 기다려야 하는 시간을
설정할 수 있다. 기본값은 `5m`이다.
### 노드-수준 자원 회수하기 {#reclaim-node-resources}
kubelet은 최종 사용자 파드를 축출하기 전에 노드-수준 자원 회수를 시도한다.
`DiskPressure` 노드 컨디션이 보고되면,
kubelet은 노드의 파일시스템을 기반으로 노드-수준 자원을 회수한다.
#### `imagefs`가 있는 경우
컨테이너 런타임이 사용할 전용 `imagefs` 파일시스템이 노드에 있으면,
kubelet은 다음 작업을 수행한다.
* `nodefs` 파일시스템이 축출 임계값 조건을 충족하면,
kubelet은 종료된 파드와 컨테이너에 대해 가비지 수집을 수행한다.
* `imagefs` 파일시스템이 축출 임계값 조건을 충족하면,
kubelet은 모든 사용중이지 않은 이미지를 삭제한다.
#### `imagefs`가 없는 경우
노드에 `nodefs` 파일시스템만 있고 이것이 축출 임계값 조건을 충족한 경우,
kubelet은 다음 순서로 디스크 공간을 확보한다.
1. 종료된 파드와 컨테이너에 대해 가비지 수집을 수행한다.
1. 사용중이지 않은 이미지를 삭제한다.
### kubelet 축출을 위한 파드 선택
kubelet이 노드-수준 자원을 회수했음에도 축출 신호가 임계값 아래로 내려가지 않으면,
kubelet은 최종 사용자 파드 축출을 시작한다.
kubelet은 파드 축출 순서를 결정하기 위해 다음의 파라미터를 활용한다.
1. 파드의 자원 사용량이 요청량을 초과했는지 여부
1. [파드 우선순위](/ko/docs/concepts/scheduling-eviction/pod-priority-preemption/)
1. 파드의 자원 요청량 대비 자원 사용량
결과적으로, kubelet은 다음과 같은 순서로 파드의 축출 순서를 정하고 축출을 수행한다.
1. `BestEffort` 또는 `Burstable` 파드 중 자원 사용량이 요청량을 초과한 파드.
이 파드들은 파드들의 우선순위, 그리고 자원 사용량이 요청량을
얼마나 초과했는지에 따라 축출된다.
1. `Guaranteed`, `Burstable` 파드 중 자원 사용량이 요청량보다 낮은 파드는
우선순위에 따라 후순위로 축출된다.
{{<note>}}
kubelet이 파드 축출 순서를 결정할 때 파드의 QoS 클래스는 이용하지 않는다.
메모리 등의 자원을 회수할 때, QoS 클래스를 이용하여 가장 가능성이 높은 파드 축출 순서를 예측할 수는 있다.
QoS는 EphemeralStorage 요청에 적용되지 않으므로,
노드가 예를 들어 `DiskPressure` 아래에 있는 경우 위의 시나리오가 적용되지 않는다.
{{</note>}}
`Guaranteed` 파드는 모든 컨테이너에 대해 자원 요청량과 제한이 명시되고
그 둘이 동일할 때에만 보장(guaranteed)된다. 다른 파드의 자원 사용으로 인해
`Guaranteed` 파드가 축출되는 일은 발생하지 않는다. 만약 시스템 데몬(예:
`kubelet`, `docker`, `journald`)이 `system-reserved` 또는 `kube-reserved`
할당을 통해 예약된 것보다 더 많은 자원을 소비하고, 노드에는 요청량보다 적은 양의
자원을 사용하고 있는 `Guaranteed` / `Burstable` 파드만 존재한다면,
kubelet은 노드 안정성을 유지하고 자원 고갈이 다른 파드에 미칠 영향을 통제하기 위해
이러한 파드 중 하나를 골라 축출해야 한다.
이 경우, 가장 낮은 `Priority`를 갖는 파드가 선택된다.
`inodes``PIDs`에 대한 요청량은 정의하고 있지 않기 때문에, kubelet이 `inode`
또는 `PID` 고갈 때문에 파드를 축출할 때에는 파드의 `Priority`를 이용하여 축출
순위를 정한다.
노드에 전용 `imagefs` 파일시스템이 있는지 여부에 따라 kubelet이 파드 축출 순서를
정하는 방식에 차이가 있다.
#### `imagefs`가 있는 경우
`nodefs`로 인한 축출의 경우, kubelet은 `nodefs`
사용량(`모든 컨테이너의 로컬 볼륨 + 로그`)을 기준으로 축출 순서를 정한다.
`imagefs`로 인한 축출의 경우, kubelet은 모든 컨테이너의
쓰기 가능한 레이어(writable layer) 사용량을 기준으로 축출 순서를 정한다.
#### `imagefs`가 없는 경우
`nodefs`로 인한 축출의 경우, kubelet은 각 파드의 총
디스크 사용량(`모든 컨테이너의 로컬 볼륨 + 로그 + 쓰기 가능한 레이어`)을 기준으로 축출 순서를 정한다.
### 최소 축출 회수량
경우에 따라, 파드를 축출했음에도 적은 양의 자원만이 회수될 수 있다.
이로 인해 kubelet이 반복적으로 축출 임계값 도달을 감지하고
여러 번의 축출을 수행할 수 있다.
`--eviction-minimum-reclaim` 플래그 또는
[kubelet 설정 파일](/docs/tasks/administer-cluster/kubelet-config-file/)을 이용하여
각 자원에 대한 최소 회수량을 설정할 수 있다. kubelet이 자원 부족 상황을 감지하면,
앞서 설정한 최소 회수량에 도달할때까지 회수를 계속 진행한다.
예를 들어, 다음 YAML은 최소 회수량을 정의하고 있다.
```yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
evictionHard:
memory.available: "500Mi"
nodefs.available: "1Gi"
imagefs.available: "100Gi"
evictionMinimumReclaim:
memory.available: "0Mi"
nodefs.available: "500Mi"
imagefs.available: "2Gi"
```
이 예제에서, 만약 `nodefs.available` 축출 신호가 축출 임계값 조건에 도달하면,
kubelet은 축출 신호가 임계값인 `1Gi`에 도달할 때까지 자원을 회수하며,
이어서 축출 신호가 `1.5Gi`에 도달할 때까지 최소 `500Mi` 이상의 자원을
회수한다.
유사한 방식으로, kubelet은 `imagefs.available` 축출 신호가
`102Gi`에 도달할 때까지 `imagefs` 자원을 회수한다.
모든 자원에 대해 `eviction-minimum-reclaim`의 기본값은 `0`이다.
### 노드 메모리 부족 시의 동작
kubelet의 메모리 회수가 가능하기 이전에
노드에 메모리 부족(out of memory, 이하 OOM) 이벤트가 발생하면,
노드는 [oom_killer](https://lwn.net/Articles/391222/)에 의존한다.
kubelet은 각 파드에 설정된 QoS를 기반으로 각 컨테이너에 `oom_score_adj` 값을 설정한다.
| 서비스 품질(Quality of Service) | oom_score_adj |
|--------------------|-----------------------------------------------------------------------------------|
| `Guaranteed` | -997 |
| `BestEffort` | 1000 |
| `Burstable` | min(max(2, 1000 - (1000 * memoryRequestBytes) / machineMemoryCapacityBytes), 999) |
{{<note>}}
또한, kubelet은 `system-node-critical` {{<glossary_tooltip text="파드 우선 순위(Priority)" term_id="pod-priority">}}를 갖는 파드의 컨테이너에
`oom_score_adj` 값을 `-997`로 설정한다.
{{</note>}}
노드가 OOM을 겪기 전에 kubelet이 메모리를 회수하지 못하면, `oom_killer`가 노드의
메모리 사용률 백분율을 이용하여 `oom_score`를 계산하고, 각 컨테이너의 실질
`oom_score`를 구하기 위해 `oom_score_adj`를 더한다. 그 뒤 `oom_score`가 가장 높은
컨테이너부터 종료시킨다.
이는 곧, 스케줄링 요청에 비해 많은 양의 메모리를 사용하면서
QoS가 낮은 파드에 속한 컨테이너가 먼저 종료됨을 의미한다.
파드 축출과 달리, 컨테이너가 OOM으로 인해 종료되면,
`kubelet`이 컨테이너의 `RestartPolicy`를 기반으로 컨테이너를 다시 실행할 수 있다.
### 추천 예시 {#node-pressure-eviction-good-practices}
아래 섹션에서 축출 설정에 대한 추천 예시를 소개한다.
#### 스케줄 가능한 자원과 축출 정책
kubelet에 축출 정책을 설정할 때, 만약 어떤 파드 배치가 즉시 메모리 압박을
야기하기 때문에 축출을 유발한다면 스케줄러가 그 파드 배치를 수행하지 않도록
설정해야 한다.
다음 시나리오를 가정한다.
* 노드 메모리 용량: `10Gi`
* 운영자는 시스템 데몬(커널, `kubelet` 등)을 위해 메모리 용량의 10%를 확보해 놓고 싶어 한다.
* 운영자는 시스템 OOM 발생을 줄이기 위해 메모리 사용률이 95%인 상황에서 파드를 축출하고 싶어한다.
이것이 실현되도록, kubelet이 다음과 같이 실행된다.
```
--eviction-hard=memory.available<500Mi
--system-reserved=memory=1.5Gi
```
이 환경 설정에서, `--system-reserved` 플래그는 시스템 용으로 `1.5Gi` 메모리를
확보하는데, 이는 `총 메모리의 10% + 축출 임계값`에 해당된다.
파드가 요청량보다 많은 메모리를 사용하거나 시스템이 `1Gi` 이상의 메모리를
사용하여, `memory.available` 축출 신호가 `500Mi` 아래로 내려가면 노드가 축출
임계값에 도달할 수 있다.
#### 데몬셋(DaemonSet)
파드 우선 순위(Priority)는 파드 축출 결정을 내릴 때의 주요 요소이다.
kubelet이 `DaemonSet`에 속하는 파드를 축출하지 않도록 하려면
해당 파드의 파드 스펙에 충분히 높은 `priorityClass`를 지정한다.
또는 낮은 `priorityClass`나 기본값을 사용하여
리소스가 충분할 때만 `DaemonSet` 파드가 실행되도록 허용할 수도 있다.
### 알려진 이슈
다음 섹션에서는 리소스 부족 처리와 관련된 알려진 이슈에 대해 다룬다.
#### kubelet이 메모리 압박을 즉시 감지하지 못할 수 있음
기본적으로 kubelet은 `cAdvisor`를 폴링하여
일정한 간격으로 메모리 사용량 통계를 수집한다.
해당 타임 윈도우 내에서 메모리 사용량이 빠르게 증가하면 kubelet이
`MemoryPressure`를 충분히 빠르게 감지하지 못해 `OOMKiller`가 계속 호출될 수 있다.
`--kernel-memcg-notification` 플래그를 사용하여
kubelet의 `memcg` 알림 API가 임계값을 초과할 때 즉시 알림을 받도록
할 수 있다.
사용률(utilization)을 극단적으로 높이려는 것이 아니라 오버커밋(overcommit)에 대한 합리적인 조치만 원하는 경우,
이 문제에 대한 현실적인 해결 방법은 `--kube-reserved`
`--system-reserved` 플래그를 사용하여 시스템에 메모리를 할당하는 것이다.
#### `active_file` 메모리가 사용 가능한 메모리로 간주되지 않음
리눅스에서, 커널은 활성 LRU 목록의 파일 지원 메모리 바이트 수를 `active_file`
통계로 추적한다. kubelet은 `active_file` 메모리 영역을 회수할 수 없는 것으로
취급한다. 임시 로컬 스토리지를 포함하여 블록 지원 로컬 스토리지를 집중적으로
사용하는 워크로드의 경우 파일 및 블록 데이터의 커널 수준 캐시는 최근에 액세스한
많은 캐시 페이지가 `active_file`로 계산될 가능성이 있음을 의미한다. 활성 LRU
목록에 이러한 커널 블록 버퍼가 충분히 많으면, kubelet은 이를 높은 자원 사용
상태로 간주하고 노드가 메모리 압박을 겪고 있다고 테인트를 표시할 수 있으며, 이는
파드 축출을 유발한다.
더 자세한 사항은 [https://github.com/kubernetes/kubernetes/issues/43916](https://github.com/kubernetes/kubernetes/issues/43916)를 참고한다.
집중적인 I/O 작업을 수행할 가능성이 있는 컨테이너에 대해 메모리 제한량 및 메모리
요청량을 동일하게 설정하여 이 문제를 해결할 수 있다. 해당 컨테이너에 대한 최적의
메모리 제한량을 추정하거나 측정해야 한다.
## {{% heading "whatsnext" %}}
* [API를 이용한 축출](/ko/docs/concepts/scheduling-eviction/api-eviction/)에 대해 알아본다.
* [파드 우선순위와 선점](/ko/docs/concepts/scheduling-eviction/pod-priority-preemption/)에 대해 알아본다.
* [PodDisruptionBudgets](/docs/tasks/run-application/configure-pdb/)에 대해 알아본다.
* [서비스 품질](/ko/docs/tasks/configure-pod-container/quality-service-pod/)(QoS)에 대해 알아본다.
* [축출 API](/docs/reference/generated/kubernetes-api/{{<param "version">}}/#create-eviction-pod-v1-core)를 확인한다.

View File

@ -1,4 +1,9 @@
---
title: 스토리지 클래스
content_type: concept
weight: 30
@ -184,7 +189,7 @@ CSI | 1.14 (alpha), 1.16 (beta)
CSI 드라이버에 대한 문서를 본다.
{{< note >}}
`waitForFirstConsumer`를 사용한다면, 노드 어피니티를 지정하기 위해서 파드 스펙에 `nodeName`을 사용하지는 않아야 한다.
`WaitForFirstConsumer`를 사용한다면, 노드 어피니티를 지정하기 위해서 파드 스펙에 `nodeName`을 사용하지는 않아야 한다.
만약 `nodeName`을 사용한다면, 스케줄러가 바이패스되고 PVC가 `pending` 상태로 있을 것이다.
대신, 아래와 같이 호스트네임을 이용하는 노드셀렉터를 사용할 수 있다.

View File

@ -304,13 +304,23 @@ kubelet은 실행 중인 컨테이너들에 대해서 선택적으로 세 가지
보일 수도 있지만, 스팩에 준비성 프로브가 존재한다는 것은 파드가
트래픽을 받지 않는 상태에서 시작되고 프로브가 성공하기 시작한 이후에만
트래픽을 받는다는 뜻이다.
만약 컨테이너가 대량의 데이터, 설정 파일들,
또는 시동 중 마그레이션을 처리해야 한다면, 준비성 프로브를 지정하길 바란다.
만약 당신의 컨테이너가 유지 관리를 위해서 자체 중단되게 하려면,
만약 컨테이너가 유지 관리를 위해서 자체 중단되게 하려면,
준비성 프로브를 지정하길 바란다.
준비성 프로브는 활성 프로브와는 다르게 준비성에 특정된 엔드포인트를 확인한다.
만약 애플리케이션이 백엔드 서비스에 엄격한 의존성이 있다면,
활성 프로브와 준비성 프로브 모두 활용할 수도 있다. 활성 프로브는 애플리케이션 스스로가 건강한 상태면
통과하지만, 준비성 프로브는 추가적으로 요구되는 각 백-엔드 서비스가 가용한지 확인한다. 이를 이용하여,
오류 메시지만 응답하는 파드로
트래픽이 가는 것을 막을 수 있다.
만약 컨테이너가 시동 시 대량 데이터의 로딩, 구성 파일, 또는
마이그레이션에 대한 작업을
수행해야 한다면, [스타트업 프로브](#언제-스타트업-프로브를-사용해야-하는가)를 사용하면 된다. 그러나, 만약
failed 애플리케이션과 시동 중에 아직 데이터를 처리하고 있는 애플리케이션을 구분하여 탐지하고
싶다면, 준비성 프로브를 사용하는 것이 더 적합할 것이다.
{{< note >}}
파드가 삭제될 때 요청들을 흘려 보내기(drain) 위해
준비성 프로브가 꼭 필요한 것은 아니다. 삭제 시에, 파드는

View File

@ -9,6 +9,7 @@ content_type: concept
no_list: true
---
<!-- overview -->
쿠버네티스 문서의 본 섹션에서는 레퍼런스를 다룬다.
@ -48,26 +49,26 @@ no_list: true
## 컴포넌트
* [kubelet](/docs/reference/command-line-tools-reference/kubelet/) - 각
노드에서 구동되는 주요한 에이전트. kubelet은 PodSpecs 집합을 가지며
* [kubelet](/docs/reference/command-line-tools-reference/kubelet/) - 각
노드에서 구동되는 주요한 에이전트. kubelet은 PodSpecs 집합을 가지며
기술된 컨테이너가 구동되고 있는지, 정상 작동하는지를 보장한다.
* [kube-apiserver](/docs/reference/command-line-tools-reference/kube-apiserver/) -
파드, 서비스, 레플리케이션 컨트롤러와 같은 API 오브젝트에 대한 검증과 구성을
* [kube-apiserver](/docs/reference/command-line-tools-reference/kube-apiserver/) -
파드, 서비스, 레플리케이션 컨트롤러와 같은 API 오브젝트에 대한 검증과 구성을
수행하는 REST API.
* [kube-controller-manager](/docs/reference/command-line-tools-reference/kube-controller-manager/) - 쿠버네티스에 탑재된 핵심 제어 루프를 포함하는 데몬.
* [kube-proxy](/ko/docs/reference/command-line-tools-reference/kube-proxy/) - 간단한
TCP/UDP 스트림 포워딩이나 백-엔드 집합에 걸쳐서 라운드-로빈 TCP/UDP 포워딩을
* [kube-proxy](/ko/docs/reference/command-line-tools-reference/kube-proxy/) - 간단한
TCP/UDP 스트림 포워딩이나 백-엔드 집합에 걸쳐서 라운드-로빈 TCP/UDP 포워딩을
할 수 있다.
* [kube-scheduler](/docs/reference/command-line-tools-reference/kube-scheduler/) - 가용성, 성능 및 용량을 관리하는 스케줄러.
* [kube-scheduler 정책](/ko/docs/reference/scheduling/policies)
* [kube-scheduler 프로파일](/ko/docs/reference/scheduling/config/#여러-프로파일)
## 환경설정 API
## API 설정
이 섹션은 쿠버네티스 구성요소 또는 도구를 환경설정하는 데에 사용되는
"미발표된" API를 다룬다. 이 API들은 사용자나 관리자가 클러스터를
사용/관리하는 데에 중요하지만, 이들 API의 대부분은 아직 API 서버가
이 섹션은 쿠버네티스 구성요소 또는 도구를 환경설정하는 데에 사용되는
"미발표된" API를 다룬다. 이 API들은 사용자나 관리자가 클러스터를
사용/관리하는 데에 중요하지만, 이들 API의 대부분은 아직 API 서버가
제공하지 않는다.
* [kubelet 환경설정 (v1beta1)](/docs/reference/config-api/kubelet-config.v1beta1/)
@ -78,6 +79,10 @@ TCP/UDP 스트림 포워딩이나 백-엔드 집합에 걸쳐서 라운드-로
* [클라이언트 인증 API (v1beta1)](/docs/reference/config-api/client-authentication.v1beta1/)
* [WebhookAdmission 환경설정 (v1)](/docs/reference/config-api/apiserver-webhookadmission.v1/)
## kubeadm을 위한 API 설정
* [v1beta2](/docs/reference/config-api/kubeadm-config.v1beta2/)
## 설계 문서
쿠버네티스 기능에 대한 설계 문서의 아카이브.

View File

@ -61,6 +61,7 @@ kubelet과 같은 컴포넌트의 기능 게이트를 설정하려면, 기능
| `BalanceAttachedNodeVolumes` | `false` | 알파 | 1.11 | |
| `BoundServiceAccountTokenVolume` | `false` | 알파 | 1.13 | 1.20 |
| `BoundServiceAccountTokenVolume` | `true` | 베타 | 1.21 | |
| `ControllerManagerLeaderMigration` | `false` | 알파 | 1.21 | |
| `CPUManager` | `false` | 알파 | 1.8 | 1.9 |
| `CPUManager` | `true` | 베타 | 1.10 | |
| `CSIInlineVolume` | `false` | 알파 | 1.15 | 1.15 |
@ -379,7 +380,6 @@ kubelet과 같은 컴포넌트의 기능 게이트를 설정하려면, 기능
| `TokenRequestProjection` | `false` | 알파 | 1.11 | 1.11 |
| `TokenRequestProjection` | `true` | 베타 | 1.12 | 1.19 |
| `TokenRequestProjection` | `true` | GA | 1.20 | - |
| `VolumeCapacityPriority` | `false` | 알파 | 1.21 | - |
| `VolumePVCDataSource` | `false` | 알파 | 1.15 | 1.15 |
| `VolumePVCDataSource` | `true` | 베타 | 1.16 | 1.17 |
| `VolumePVCDataSource` | `true` | GA | 1.18 | - |
@ -479,6 +479,11 @@ kubelet과 같은 컴포넌트의 기능 게이트를 설정하려면, 기능
`kube-apiserver`를 시작하여 확장 토큰 기능을 끈다.
자세한 내용은 [바운드 서비스 계정 토큰](https://github.com/kubernetes/enhancements/blob/master/keps/sig-auth/1205-bound-service-account-tokens/README.md)을
확인한다.
- `ControllerManagerLeaderMigration`: HA 클러스터에서 클러스터 오퍼레이터가
kube-controller-manager의 컨트롤러들을 외부 controller-manager(예를 들면,
cloud-controller-manager)로 다운타임 없이 라이브 마이그레이션할 수 있도록 허용하도록
[kube-controller-manager](/docs/tasks/administer-cluster/controller-manager-leader-migration/#initial-leader-migration-configuration)와 [cloud-controller-manager](/docs/tasks/administer-cluster/controller-manager-leader-migration/#deploy-cloud-controller-manager)의
리더 마이그레이션(Leader Migration)을 활성화한다.
- `CPUManager`: 컨테이너 수준의 CPU 어피니티 지원을 활성화한다.
[CPU 관리 정책](/docs/tasks/administer-cluster/cpu-management-policies/)을 참고한다.
- `CRIContainerLogRotation`: cri 컨테이너 런타임에 컨테이너 로그 로테이션을 활성화한다. 로그 파일 사이즈 기본값은 10MB이며,
@ -637,7 +642,7 @@ kubelet과 같은 컴포넌트의 기능 게이트를 설정하려면, 기능
- `ExperimentalCriticalPodAnnotation`: 특정 파드에 *critical*
어노테이션을 달아서 [스케줄링이 보장되도록](/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/) 한다.
이 기능은 v1.13부터 파드 우선 순위 및 선점으로 인해 사용 중단되었다.
- `ExperimentalHostUserNamespaceDefaultingGate`: 사용자 네임스페이스를 호스트로
- `ExperimentalHostUserNamespaceDefaulting`: 사용자 네임스페이스를 호스트로
기본 활성화한다. 이것은 다른 호스트 네임스페이스, 호스트 마운트,
권한이 있는 컨테이너 또는 특정 비-네임스페이스(non-namespaced) 기능(예: `MKNODE`, `SYS_MODULE` 등)을
사용하는 컨테이너를 위한 것이다. 도커 데몬에서 사용자 네임스페이스
@ -764,6 +769,8 @@ kubelet과 같은 컴포넌트의 기능 게이트를 설정하려면, 기능
- `RotateKubeletClientCertificate`: kubelet에서 클라이언트 TLS 인증서의 로테이션을 활성화한다.
자세한 내용은 [kubelet 구성](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#kubelet-configuration)을 참고한다.
- `RotateKubeletServerCertificate`: kubelet에서 서버 TLS 인증서의 로테이션을 활성화한다.
자세한 사항은
[kubelet 구성](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/#kubelet-configuration)을 확인한다.
- `RunAsGroup`: 컨테이너의 init 프로세스에 설정된 기본 그룹 ID 제어를
활성화한다.
- `RuntimeClass`: 컨테이너 런타임 구성을 선택하기 위해 [런타임클래스(RuntimeClass)](/ko/docs/concepts/containers/runtime-class/)
@ -794,6 +801,8 @@ kubelet과 같은 컴포넌트의 기능 게이트를 설정하려면, 기능
- `SetHostnameAsFQDN`: 전체 주소 도메인 이름(FQDN)을 파드의 호스트 이름으로
설정하는 기능을 활성화한다.
[파드의 `setHostnameAsFQDN` 필드](/ko/docs/concepts/services-networking/dns-pod-service/#pod-sethostnameasfqdn-field)를 참고한다.
- `SizeMemoryBackedVolumes`: memory-backed 볼륨(보통 `emptyDir` 볼륨)의 크기 상한을
지정할 수 있도록 kubelets를 활성화한다.
- `StartupProbe`: kubelet에서
[스타트업](/ko/docs/concepts/workloads/pods/pod-lifecycle/#언제-스타트업-프로브를-사용해야-하는가)
프로브를 활성화한다.

View File

@ -4,15 +4,15 @@ id: kube-controller-manager
date: 2018-04-12
full_link: /docs/reference/command-line-tools-reference/kube-controller-manager/
short_description: >
{{< glossary_tooltip text="컨트롤러" term_id="controller" >}} 프로세스를 실행하는 컨트롤 플레인 컴포넌트.
컨트롤러 프로세스를 실행하는 컨트롤 플레인 컴포넌트.
aka:
aka:
tags:
- architecture
- fundamental
---
{{< glossary_tooltip text="컨트롤러" term_id="controller" >}}를 구동하는 마스터 상의 컴포넌트.
{{< glossary_tooltip text="컨트롤러" term_id="controller" >}} 프로세스를 실행하는 컨트롤 플레인 컴포넌트.
<!--more-->
<!--more-->
논리적으로, 각 {{< glossary_tooltip text="컨트롤러" term_id="controller" >}}는 개별 프로세스이지만, 복잡성을 낮추기 위해 모두 단일 바이너리로 컴파일되고 단일 프로세스 내에서 실행된다.
논리적으로, 각 {{< glossary_tooltip text="컨트롤러" term_id="controller" >}}는 분리된 프로세스이지만, 복잡성을 낮추기 위해 모두 단일 바이너리로 컴파일되고 단일 프로세스 내에서 실행된다.

View File

@ -0,0 +1,24 @@
---
title: 노드-압박 축출
id: node-pressure-eviction
date: 2021-05-13
full_link: /ko/docs/concepts/scheduling-eviction/node-pressure-eviction/
short_description: >
노드-압박 축출은 kubelet이 노드의 자원을 회수하기 위해
파드를 능동적으로 중단시키는 절차이다.
aka:
- kubelet eviction
tags:
- operation
---
노드-압박 축출은 {{<glossary_tooltip term_id="kubelet" text="kubelet">}}이 노드의 자원을 회수하기 위해
파드를 능동적으로 중단시키는 절차이다.
<!--more-->
kubelet은 클러스터 노드의 CPU, 메모리, 디스크 공간, 파일시스템
inode와 같은 자원을 모니터링한다. 이러한 자원 중 하나 이상이
특정 소모 수준에 도달하면, kubelet은 하나 이상의 파드를 능동적으로 중단시켜
자원을 회수하고 고갈 상황을 방지할 수 있다.
노드-압박 축출은 [API를 이용한 축출](/ko/docs/concepts/scheduling-eviction/api-eviction/)과는 차이가 있다.

View File

@ -1,8 +1,10 @@
---
title: 도구
content_type: concept
weight: 80
no_list: true
---
<!-- overview -->
@ -10,13 +12,6 @@ content_type: concept
<!-- body -->
## Kubectl
[`kubectl`](/ko/docs/tasks/tools/#kubectl)은 쿠버네티스를 위한 커맨드라인 툴이며, 쿠버네티스 클러스터 매니저을 제어한다.
## Kubeadm
[`kubeadm`](/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)은 물리적 환경, 클라우드 서버, 또는 가상머신 상에서 안전한 쿠버네티스를 쉽게 프로비저닝하기 위한 커맨드라인 툴이다(현재는 알파 상태).
## Minikube
@ -31,8 +26,8 @@ content_type: concept
## Helm
[`쿠버네티스 Helm`](https://github.com/kubernetes/helm)은 사전 구성된 쿠버네티스 리소스를 관리하기위한 도구이며
또한 Helm의 쿠버네티스 차트라고도 한다.
[Helm](https://helm.sh/)은 사전 구성된 쿠버네티스 리소스 패키지를 관리하기 위한 도구이다.
이 패키지는 _Helm charts_ 라고 알려져 있다.
Helm의 용도

View File

@ -23,7 +23,7 @@ kubeadm의 `ClusterConfiguration` 오브젝트는 API 서버, 컨트롤러매니
3. `kubeadm init``--config <CONFIG YAML 파일>` 파라미터를 추가해서 실행한다.
각 필드의 구성에서 자세한 정보를 보려면,
[API 참고 문서](https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2#ClusterConfiguration)에서 확인해 볼 수 있다.
[API 참고 문서](/docs/reference/config-api/kubeadm-config.v1beta2/)에서 확인해 볼 수 있다.
{{< note >}}
`kubeadm config print init-defaults`를 실행하고 원하는 파일에 출력을 저장하여 기본값인 `ClusterConfiguration` 오브젝트를 생성할 수 있다.

View File

@ -102,6 +102,8 @@ weight: 65
Microsoft는 `mcr.microsoft.com/oss/kubernetes/pause:3.4.1`에서
윈도우 퍼즈 인프라 컨테이너를 유지한다.
이외에도 `k8s.gcr.io/pause:3.5`를 통해 쿠버네티스에서 관리하는 다중 아키텍처 이미지를
사용할 수도 있는데, 이 이미지는 리눅스와 윈도우를 모두 지원한다.
#### 컴퓨트

View File

@ -0,0 +1,29 @@
---
title: 쿠버네티스 API 활성화 혹은 비활성화하기
content_type: task
---
<!-- overview -->
이 페이지는 클러스터 {{< glossary_tooltip text="컨트롤 플레인" term_id="control-plane" >}}의
특정한 API 버전을 활성화하거나 비활성화하는 방법에 대해 설명한다.
<!-- steps -->
API 서버에 `--runtime-config=api/<version>` 커맨드 라인 인자를 사용함으로서 특정한 API 버전을
활성화하거나 비활성화할 수 있다. 이 인자에 대한 값으로는 콤마로 구분된 API 버전의 목록을 사용한다.
뒤쪽에 위치한 값은 앞쪽의 값보다 우선적으로 사용된다.
`runtime-config` 커맨드 라인 인자에는 다음의 두 개의 특수 키를 사용할 수도 있다.
- `api/all`: 사용할 수 있는 모든 API를 선택한다.
- `api/legacy`: 레거시 API만을 선택한다. 여기서 레거시 API란 명시적으로
[사용이 중단된](/docs/reference/using-api/deprecation-policy/) 모든 API를 가리킨다.
예를 들어서, v1을 제외한 모든 API 버전을 비활성화하기 위해서는 `kube-apiserver`
`--runtime-config=api/all=false,api/v1=true` 인자를 사용한다.
## {{% heading "whatsnext" %}}
`kube-apiserver` 컴포넌트에 대한 더 자세한 내용은 다음의 [문서](/docs/reference/command-line-tools-reference/kube-apiserver/)
를 참고한다.

View File

@ -0,0 +1,38 @@
---
title: 토폴로지 인지 힌트 활성화하기
content_type: task
min-kubernetes-server-version: 1.21
---
<!-- overview -->
{{< feature-state for_k8s_version="v1.21" state="alpha" >}}
_토폴로지 인지 힌트_ 는 {{< glossary_tooltip text="엔드포인트슬라이스(EndpointSlices)" term_id="endpoint-slice" >}}에 포함되어 있는
토폴로지 정보를 이용해 토폴로지 인지 라우팅을 가능하게 한다.
이 방법은 트래픽을 해당 트래픽이 시작된 곳과 최대한 근접하도록 라우팅하는데,
이를 통해 비용을 줄이거나 네트워크 성능을 향상시킬 수 있다.
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
토폴로지 인지 힌트를 활성화하기 위해서는 다음의 필수 구성 요소가 필요하다.
* {{< glossary_tooltip text="kube-proxy" term_id="kube-proxy" >}}가
iptables 모드 혹은 IPVS 모드로 동작하도록 설정
* 엔드포인트슬라이스가 비활성화되지 않았는지 확인
## 토폴로지 인지 힌트 활성화하기
서비스 토폴로지 힌트를 활성화하기 위해서는 kube-apiserver, kube-controller-manager, kube-proxy에 대해
`TopologyAwareHints` [기능 게이트](/ko/docs/reference/command-line-tools-reference/feature-gates/)를
활성화한다.
```
--feature-gates="TopologyAwareHints=true"
```
## {{% heading "whatsnext" %}}
* 서비스 항목 아래의 [토폴로지 인지 힌트](/docs/concepts/services-networking/topology-aware-hints)를 참고
* [서비스와 애플리케이션 연결하기](/ko/docs/concepts/services-networking/connect-applications-service/)를 참고

View File

@ -0,0 +1,25 @@
---
title: 중요한 애드온 파드 스케줄링 보장하기
content_type: concept
---
<!-- overview -->
API 서버, 스케줄러 및 컨트롤러 매니저와 같은 쿠버네티스 주요 컴포넌트들은 컨트롤 플레인 노드에서 동작한다. 반면, 애드온들은 일반 클러스터 노드에서 동작한다.
이러한 애드온들 중 일부(예: 메트릭 서버, DNS, UI)는 클러스터 전부가 정상적으로 동작하는 데 필수적일 수 있다.
만약, 필수 애드온이 축출되고(수동 축출, 혹은 업그레이드와 같은 동작으로 인한 의도하지 않은 축출)
pending 상태가 된다면, 클러스터가 더 이상 제대로 동작하지 않을 수 있다. (사용률이 매우 높은 클러스터에서 해당 애드온이
축출되자마자 다른 대기중인 파드가 스케줄링되거나 다른 이유로 노드에서 사용할 수 있는 자원량이 줄어들어 pending 상태가 발생할 수 있다)
유의할 점은, 파드를 중요(critical)로 표시하는 것은 축출을 완전히 방지하기 위함이 아니다. 이것은 단지 파드가 영구적으로 사용할 수 없게 되는 것만을 방지하기 위함이다.
중요로 표시한 스태틱(static) 파드는 축출될 수 없다. 반면, 중요로 표시한 일반적인(non-static) 파드의 경우 항상 다시 스케줄링된다.
<!-- body -->
### 파드를 중요(critical)로 표시하기
파드를 중요로 표시하기 위해서는, 해당 파드에 대해 priorityClassName을 `system-cluster-critical`이나 `system-node-critical`로 설정한다. `system-node-critical`은 가장 높은 우선 순위를 가지며, 심지어 `system-cluster-critical`보다도 우선 순위가 높다.

View File

@ -10,7 +10,7 @@ content_type: task
{{< feature-state for_k8s_version="v1.5" state="alpha" >}}
구글 컴퓨트 엔진(Google Compute Engine, 이하 GCE)의 `kube-up`이나 `kube-down` 스크립트에 쿠버네티스 컨트롤 플레인 노드를 복제할 수 있다.
구글 컴퓨트 엔진(Google Compute Engine, 이하 GCE)의 `kube-up`이나 `kube-down` 스크립트에 쿠버네티스 컨트롤 플레인 노드를 복제할 수 있다. 하지만 이러한 스크립트들은 프로덕션 용도로 사용하기에 적합하지 않으며, 프로젝트의 CI에서만 주로 사용된다.
이 문서는 kube-up/down 스크립트를 사용하여 고가용(HA) 컨트롤 플레인을 관리하는 방법과 GCE와 함께 사용하기 위해 HA 컨트롤 플레인을 구현하는 방법에 관해 설명한다.

View File

@ -161,7 +161,7 @@ HA 클러스터를 실행 중인 경우, 모든 컨트롤 플레인 노드에서
빌트인 서명자를 활성화하려면, `--cluster-signing-cert-file``--cluster-signing-key-file` 플래그를 전달해야 한다.
새 클러스터를 생성하는 경우, kubeadm [구성 파일](https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2)을 사용할 수 있다.
새 클러스터를 생성하는 경우, kubeadm [구성 파일](/docs/reference/config-api/kubeadm-config.v1beta2/)을 사용할 수 있다.
```yaml
apiVersion: kubeadm.k8s.io/v1beta2

View File

@ -38,7 +38,7 @@ weight: 20
### 추가 정보
- kubelet 마이너 버전을 업그레이드하기 전에 [노드 드레이닝(draining)](/docs/tasks/administer-cluster/safely-drain-node/)이
필요하다. 컨트롤 플레인 노드의 경우 CoreNDS 파드 또는 기타 중요한 워크로드를 실행할 수 있다.
필요하다. 컨트롤 플레인 노드의 경우 CoreDNS 파드 또는 기타 중요한 워크로드를 실행할 수 있다.
- 컨테이너 사양 해시 값이 변경되므로, 업그레이드 후 모든 컨테이너가 다시 시작된다.
<!-- steps -->

View File

@ -0,0 +1,6 @@
---
title: "시크릿(Secret) 관리"
weight: 28
description: 시크릿을 사용하여 기밀 설정 데이터 관리.
---

View File

@ -0,0 +1,198 @@
---
title: 환경 설정 파일을 사용하여 시크릿을 관리
content_type: task
weight: 20
description: 환경 설정 파일을 사용하여 시크릿 오브젝트를 생성.
---
<!-- overview -->
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
<!-- steps -->
## 환경 설정 파일 생성
먼저 새 파일에 JSON 이나 YAML 형식으로 시크릿(Secret)에 대한 상세 사항을 기록하고,
이 파일을 이용하여 해당 시크릿 오브젝트를 생성할 수 있다. 이
[시크릿](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#secret-v1-core)
리소스에는 `data``stringData` 의 두 가지 맵이 포함되어 있다.
`data` 필드는 base64로 인코딩된 임의의 데이터를 기입하는 데 사용된다.
`stringData` 필드는 편의를 위해 제공되며, 이를 사용해 시크릿 데이터를 인코딩되지 않은 문자열로
기입할 수 있다.
`data``stringData`은 영숫자,
`-`, `_` 그리고 `.`로 구성되어야 한다.
예를 들어 시크릿에 `data` 필드를 사용하여 두 개의 문자열을 저장하려면 다음과 같이
문자열을 base64로 변환한다.
```shell
echo -n 'admin' | base64
```
출력은 다음과 유사하다.
```
YWRtaW4=
```
```shell
echo -n '1f2d1e2e67df' | base64
```
출력은 다음과 유사하다.
```
MWYyZDFlMmU2N2Rm
```
다음과 같이 시크릿 구성 파일을 작성한다.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
```
시크릿 오브젝트의 이름은 유효한
[DNS 서브도메인 이름](/ko/docs/concepts/overview/working-with-objects/names/#dns-서브도메인-이름)이어야 한다.
{{< note >}}
시크릿 데이터의 직렬화된(serialized) JSON 및 YAML 값은 base64 문자열로 인코딩된다.
이러한 문자열에는 개행(newline)을 사용할 수 없으므로 생략해야 한다.
Darwin/macOS에서 `base64` 도구를 사용할 경우, 사용자는 긴 줄을 분할하는 `-b` 옵션을 사용해서는 안 된다.
반대로, 리눅스 사용자는 `-w` 옵션을 사용할 수 없는 경우
`base64` 명령어 또는 `base64 | tr -d '\n'` 파이프라인에
`-w 0` 옵션을 *추가해야 한다*.
{{< /note >}}
특정 시나리오의 경우 `stringData` 필드를 대신 사용할 수 있다. 이
필드를 사용하면 base64로 인코딩되지 않은 문자열을 시크릿에 직접 넣을 수 있으며,
시크릿이 생성되거나 업데이트될 때 문자열이 인코딩된다.
이에 대한 실제적인 예로,
시크릿을 사용하여 구성 파일을 저장하는 애플리케이션을 배포하면서,
배포 프로세스 중에 해당 구성 파일의 일부를 채우려는 경우를 들 수 있다.
예를 들어 애플리케이션에서 다음 구성 파일을 사용하는 경우:
```yaml
apiUrl: "https://my.api.com/api/v1"
username: "<user>"
password: "<password>"
```
다음 정의를 사용하여 이를 시크릿에 저장할 수 있다.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
stringData:
config.yaml: |
apiUrl: "https://my.api.com/api/v1"
username: <user>
password: <password>
```
## 시크릿 오브젝트 생성
[`kubectl apply`](/docs/reference/generated/kubectl/kubectl-commands#apply)를 이용하여 시크릿 오브젝트를 생성한다.
```shell
kubectl apply -f ./secret.yaml
```
출력은 다음과 유사하다.
```
secret/mysecret created
```
## 시크릿 확인
`stringData` 필드는 쓰기 전용 편의 필드이다. 시크릿을 조회할 때 절대 출력되지 않는다.
예를 들어 다음 명령을 실행하는 경우:
```shell
kubectl get secret mysecret -o yaml
```
출력은 다음과 유사하다.
```yaml
apiVersion: v1
data:
config.yaml: YXBpVXJsOiAiaHR0cHM6Ly9teS5hcGkuY29tL2FwaS92MSIKdXNlcm5hbWU6IHt7dXNlcm5hbWV9fQpwYXNzd29yZDoge3twYXNzd29yZH19
kind: Secret
metadata:
creationTimestamp: 2018-11-15T20:40:59Z
name: mysecret
namespace: default
resourceVersion: "7225"
uid: c280ad2e-e916-11e8-98f2-025000000001
type: Opaque
```
`kubectl get``kubectl describe` 명령은 기본적으로 `시크릿`의 내용을 표시하지 않는다.
이는 `시크릿`이 실수로 구경꾼에게 노출되거나
터미널 로그에 저장되는 것을 방지하기 위한 것이다.
인코딩된 데이터의 실제 내용을 확인하려면 다음을 참조한다.
[시크릿 디코딩](/ko/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret).
하나의 필드(예: `username`)가 `data``stringData`에 모두 명시되면, `stringData`에 명시된 값이 사용된다.
예를 들어 다음과 같은 시크릿인 경우:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
stringData:
username: administrator
```
결과는 다음과 같은 시크릿이다.
```yaml
apiVersion: v1
data:
username: YWRtaW5pc3RyYXRvcg==
kind: Secret
metadata:
creationTimestamp: 2018-11-15T20:46:46Z
name: mysecret
namespace: default
resourceVersion: "7579"
uid: 91460ecb-e917-11e8-98f2-025000000001
type: Opaque
```
여기서 `YWRtaW5pc3RyYXRvcg==``administrator`으로 디코딩된다.
## 삭제
생성한 시크릿을 삭제하려면 다음 명령을 실행한다.
```shell
kubectl delete secret mysecret
```
## {{% heading "whatsnext" %}}
- [시크릿 개념](/ko/docs/concepts/configuration/secret/)에 대해 자세히 알아보기
- [`kubectl` 커맨드를 사용하여 시크릿을 관리](/ko/docs/tasks/configmap-secret/managing-secret-using-kubectl/)하는 방법 알아보기
- [kustomize를 사용하여 시크릿을 관리](/ko/docs/tasks/configmap-secret/managing-secret-using-kustomize/)하는 방법 알아보기

View File

@ -0,0 +1,156 @@
---
title: kubectl을 사용한 시크릿 관리
content_type: task
weight: 10
description: kubectl 커맨드를 사용하여 시크릿 오브젝트를 생성.
---
<!-- overview -->
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
<!-- steps -->
## 시크릿 생성
`시크릿`에는 파드가 데이터베이스에 접근하는 데 필요한 사용자 자격 증명이 포함될 수 있다.
예를 들어 데이터베이스 연결 문자열은 사용자 이름과 암호로 구성된다.
사용자 이름은 로컬 컴퓨터의 `./username.txt` 파일에, 비밀번호는
`./password.txt` 파일에 저장할 수 있다.
```shell
echo -n 'admin' > ./username.txt
echo -n '1f2d1e2e67df' > ./password.txt
```
이 명령에서 `-n` 플래그는 생성된 파일의
텍스트 끝에 추가 개행 문자가 포함되지 않도록 해 준다. 이는 `kubectl`이 파일을 읽고
내용을 base64 문자열로 인코딩할 때 개행 문자도 함께 인코딩될 수 있기 때문에
중요하다.
`kubectl create secret` 명령은 이러한 파일들을 시크릿으로 패키징하고
API 서버에 오브젝트를 생성한다.
```shell
kubectl create secret generic db-user-pass \
--from-file=./username.txt \
--from-file=./password.txt
```
출력은 다음과 유사하다.
```
secret/db-user-pass created
```
기본 키 이름은 파일 이름이다. 선택적으로 `--from-file=[key=]source`를 사용하여 키 이름을 설정할 수 있다.
예제:
```shell
kubectl create secret generic db-user-pass \
--from-file=username=./username.txt \
--from-file=password=./password.txt
```
파일에 포함하는 암호 문자열에서
특수 문자를 이스케이프하지 않아도 된다.
`--from-literal=<key>=<value>` 태그를 사용하여 시크릿 데이터를 제공할 수도 있다.
이 태그는 여러 키-값 쌍을 제공하기 위해 두 번 이상 지정할 수 있다.
`$`, `\`, `*`, `=``!`와 같은 특수 문자는
[shell](https://en.wikipedia.org/wiki/Shell_(computing))에 해석하고 처리하기 때문에
이스케이프할 필요가 있다.
대부분의 셸에서 암호를 이스케이프하는 가장 쉬운 방법은 암호를 작은따옴표(`'`)로 둘러싸는 것이다.
예를 들어, 비밀번호가 `S!B\*d$zDsb=`인 경우,
다음 커맨드를 실행한다.
```shell
kubectl create secret generic dev-db-secret \
--from-literal=username=devuser \
--from-literal=password='S!B\*d$zDsb='
```
## 시크릿 확인
시크릿이 생성되었는지 확인한다.
```shell
kubectl get secrets
```
출력은 다음과 유사하다.
```
NAME TYPE DATA AGE
db-user-pass Opaque 2 51s
```
다음 명령을 실행하여 `시크릿`에 대한 상세 사항을 볼 수 있다.
```shell
kubectl describe secrets/db-user-pass
```
출력은 다음과 유사하다.
```
Name: db-user-pass
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password: 12 bytes
username: 5 bytes
```
`kubectl get``kubectl describe` 명령은
기본적으로 `시크릿`의 내용을 표시하지 않는다. 이는 `시크릿`이 실수로 노출되거나
터미널 로그에 저장되는 것을 방지하기 위한 것이다.
## 시크릿 디코딩 {#decoding-secret}
생성한 시크릿을 보려면 다음 명령을 실행한다.
```shell
kubectl get secret db-user-pass -o jsonpath='{.data}'
```
출력은 다음과 유사하다.
```json
{"password":"MWYyZDFlMmU2N2Rm","username":"YWRtaW4="}
```
이제 `password` 데이터를 디코딩할 수 있다.
```shell
echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
```
출력은 다음과 유사하다.
```
1f2d1e2e67df
```
## 삭제
생성한 시크릿을 삭제하려면 다음 명령을 실행한다.
```shell
kubectl delete secret db-user-pass
```
<!-- discussion -->
## {{% heading "whatsnext" %}}
- [시크릿 개념](/ko/docs/concepts/configuration/secret/)에 대해 자세히 알아보기
- [환경 설정 파일을 사용하여 시크릿을 관리](/ko/docs/tasks/configmap-secret/managing-secret-using-config-file/)하는 방법 알아보기
- [kustomize를 사용하여 시크릿을 관리](/ko/docs/tasks/configmap-secret/managing-secret-using-kustomize/)하는 방법 알아보기

View File

@ -0,0 +1,139 @@
---
title: kustomize를 사용하여 시크릿 관리
content_type: task
weight: 30
description: kustomization.yaml 파일을 사용하여 시크릿 오브젝트 생성.
---
<!-- overview -->
쿠버네티스 v1.14부터 `kubectl`
[Kustomize를 이용한 쿠버네티스 오브젝트의 선언형 관리](/ko/docs/tasks/manage-kubernetes-objects/kustomization/)를 지원한다.
Kustomize는 시크릿 및 컨피그맵을 생성하기 위한 리소스 생성기를 제공한다.
Kustomize 생성기는 디렉토리 내의 `kustomization.yaml` 파일에 지정되어야 한다.
시크릿 생성 후 `kubectl apply`를 통해 API
서버에 시크릿을 생성할 수 있다.
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
<!-- steps -->
## Kustomization 파일 생성
`kustomization.yaml` 파일에 다른 기존 파일을 참조하는
`secretGenerator`를 정의하여 시크릿을 생성할 수 있다.
예를 들어 다음 kustomization 파일은
`./username.txt``./password.txt` 파일을 참조한다.
```yaml
secretGenerator:
- name: db-user-pass
files:
- username.txt
- password.txt
```
`kustomization.yaml` 파일에 리터럴을 명시하여 `secretGenerator`
정의할 수도 있다.
예를 들어 다음 `kustomization.yaml` 파일에는
각각 `username``password`에 대한 두 개의 리터럴이 포함되어 있다.
```yaml
secretGenerator:
- name: db-user-pass
literals:
- username=admin
- password=1f2d1e2e67df
```
`kustomization.yaml` 파일에 `.env` 파일을 명시하여
`secretGenerator`를 정의할 수도 있다.
예를 들어 다음 `kustomization.yaml` 파일은
`.env.secret` 파일에서 데이터를 가져온다.
```yaml
secretGenerator:
- name: db-user-pass
envs:
- .env.secret
```
모든 경우에 대해, 값을 base64로 인코딩하지 않아도 된다.
## 시크릿 생성
다음 명령을 실행하여 시크릿을 생성한다.
```shell
kubectl apply -k .
```
출력은 다음과 유사하다.
```
secret/db-user-pass-96mffmfh4k created
```
시크릿이 생성되면 시크릿 데이터를 해싱하고
이름에 해시 값을 추가하여 시크릿 이름이 생성된다. 이렇게 함으로써
데이터가 수정될 때마다 시크릿이 새롭게 생성된다.
## 생성된 시크릿 확인
시크릿이 생성된 것을 확인할 수 있다.
```shell
kubectl get secrets
```
출력은 다음과 유사하다.
```
NAME TYPE DATA AGE
db-user-pass-96mffmfh4k Opaque 2 51s
```
다음 명령을 실행하여 시크릿에 대한 상세 사항을 볼 수 있다.
```shell
kubectl describe secrets/db-user-pass-96mffmfh4k
```
출력은 다음과 유사하다.
```
Name: db-user-pass-96mffmfh4k
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password.txt: 12 bytes
username.txt: 5 bytes
```
`kubectl get``kubectl describe` 명령은 기본적으로 `시크릿`의 내용을 표시하지 않는다.
이는 `시크릿`이 실수로 구경꾼에게 노출되는 것을 방지하기 위한 것으로,
또는 터미널 로그에 저장되지 않는다.
인코딩된 데이터의 실제 내용을 확인하려면 다음을 참조한다.
[시크릿 디코딩](/ko/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret).
## 삭제
생성한 시크릿을 삭제하려면 다음 명령을 실행한다.
```shell
kubectl delete secret db-user-pass-96mffmfh4k
```
<!-- Optional section; add links to information related to this topic. -->
## {{% heading "whatsnext" %}}
- [시크릿 개념](/ko/docs/concepts/configuration/secret/)에 대해 자세히 알아보기
- [`kubectl` 커맨드을 사용하여 시크릿 관리](/ko/docs/tasks/configmap-secret/managing-secret-using-kubectl/) 방법 알아보기
- [환경 설정 파일을 사용하여 시크릿을 관리](/ko/docs/tasks/configmap-secret/managing-secret-using-config-file/)하는 방법 알아보기

View File

@ -0,0 +1,11 @@
---
title: "kubectl-convert 개요"
description: >-
특정 버전의 쿠버네티스 API로 작성된 매니페스트를 다른 버전으로 변환하는
kubectl 플러그인.
headless: true
---
이것은 쿠버네티스 커맨드 라인 도구인 `kubectl`의 플러그인으로서, 특정 버전의 쿠버네티스 API로 작성된 매니페스트를 다른 버전으로
변환할 수 있도록 한다. 이것은 매니페스트를 최신 쿠버네티스 릴리스의 사용 중단되지 않은 API로 마이그레이션하는 데 특히 유용하다.
더 많은 정보는 다음의 [사용 중단되지 않은 API로 마이그레이션](/docs/reference/using-api/deprecation-guide/#migrate-to-non-deprecated-apis)을 참고한다.

View File

@ -82,6 +82,7 @@ card:
대상 시스템에 root 접근 권한을 가지고 있지 않더라도, `~/.local/bin` 디렉터리에 kubectl을 설치할 수 있다.
```bash
chmod +x kubectl
mkdir -p ~/.local/bin/kubectl
mv ./kubectl ~/.local/bin/kubectl
# 그리고 ~/.local/bin/kubectl을 $PATH에 추가
@ -171,7 +172,7 @@ kubectl version --client
{{< include "included/verify-kubectl.md" >}}
## 선택적 kubectl 구성
## 선택적 kubectl 구성 및 플러그인
### 셸 자동 완성 활성화
@ -184,6 +185,61 @@ kubectl은 Bash 및 Zsh에 대한 자동 완성 지원을 제공하므로 입력
{{< tab name="Zsh" include="included/optional-kubectl-configs-zsh.md" />}}
{{< /tabs >}}
### `kubectl convert` 플러그인 설치
{{< include "included/kubectl-convert-overview.md" >}}
1. 다음 명령으로 최신 릴리스를 다운로드한다.
```bash
curl -LO https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl-convert
```
1. 바이너리를 검증한다. (선택 사항)
kubectl-convert 체크섬(checksum) 파일을 다운로드한다.
```bash
curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl-convert.sha256"
```
kubectl-convert 바이너리를 체크섬 파일을 통해 검증한다.
```bash
echo "$(<kubectl-convert.sha256) kubectl-convert" | sha256sum --check
```
검증이 성공한다면, 출력은 다음과 같다.
```console
kubectl-convert: OK
```
검증이 실패한다면, `sha256`이 0이 아닌 상태로 종료되며 다음과 유사한 결과를 출력한다.
```bash
kubectl-convert: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match
```
{{< note >}}
동일한 버전의 바이너리와 체크섬을 다운로드한다.
{{< /note >}}
1. kubectl-convert 설치
```bash
sudo install -o root -g root -m 0755 kubectl-convert /usr/local/bin/kubectl-convert
```
1. 플러그인이 정상적으로 설치되었는지 확인한다.
```shell
kubectl convert --help
```
에러가 출력되지 않는다면, 플러그인이 정상적으로 설치된 것이다.
## {{% heading "whatsnext" %}}
{{< include "included/kubectl-whats-next.md" >}}

View File

@ -155,7 +155,7 @@ macOS에서 [Macports](https://macports.org/) 패키지 관리자를 사용하
{{< include "included/verify-kubectl.md" >}}
## 선택적 kubectl 구성
## 선택적 kubectl 구성 및 플러그인
### 셸 자동 완성 활성화
@ -168,6 +168,82 @@ kubectl은 Bash 및 Zsh에 대한 자동 완성 지원을 제공하므로 입력
{{< tab name="Zsh" include="included/optional-kubectl-configs-zsh.md" />}}
{{< /tabs >}}
### `kubectl convert` 플러그인 설치
{{< include "included/kubectl-convert-overview.md" >}}
1. 다음 명령으로 최신 릴리스를 다운로드한다.
{{< tabs name="download_convert_binary_macos" >}}
{{< tab name="Intel" codelang="bash" >}}
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl-convert"
{{< /tab >}}
{{< tab name="Apple Silicon" codelang="bash" >}}
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl-convert"
{{< /tab >}}
{{< /tabs >}}
1. 바이너리를 검증한다. (선택 사항)
kubectl-convert 체크섬(checksum) 파일을 다운로드한다.
{{< tabs name="download_convert_checksum_macos" >}}
{{< tab name="Intel" codelang="bash" >}}
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl-convert.sha256"
{{< /tab >}}
{{< tab name="Apple Silicon" codelang="bash" >}}
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl-convert.sha256"
{{< /tab >}}
{{< /tabs >}}
kubectl-convert 바이너리를 체크섬 파일을 통해 검증한다.
```bash
echo "$(<kubectl-convert.sha256) kubectl-convert" | shasum -a 256 --check
```
검증이 성공한다면, 출력은 다음과 같다.
```console
kubectl-convert: OK
```
검증이 실패한다면, `shasum`이 0이 아닌 상태로 종료되며 다음과 유사한 결과를 출력한다.
```bash
kubectl-convert: FAILED
shasum: WARNING: 1 computed checksum did NOT match
```
{{< note >}}
동일한 버전의 바이너리와 체크섬을 다운로드한다.
{{< /note >}}
1. kubectl-convert 바이너리를 실행 가능하게 한다.
```bash
chmod +x ./kubectl-convert
```
1. kubectl-convert 바이너리를 시스템 `PATH` 의 파일 위치로 옮긴다.
```bash
sudo mv ./kubectl /usr/local/bin/kubectl-convert
sudo chown root: /usr/local/bin/kubectl-convert
```
{{< note >}}
`PATH` 환경 변수 안에 `/usr/local/bin` 이 있는지 확인한다.
{{< /note >}}
1. 플러그인이 정상적으로 설치되었는지 확인한다.
```shell
kubectl convert --help
```
에러가 출력되지 않는다면, 플러그인이 정상적으로 설치된 것이다.
## {{% heading "whatsnext" %}}
{{< include "included/kubectl-whats-next.md" >}}

View File

@ -130,7 +130,7 @@ card:
{{< include "included/verify-kubectl.md" >}}
## 선택적 kubectl 구성
## 선택적 kubectl 구성 및 플러그인
### 셸 자동 완성 활성화
@ -140,6 +140,49 @@ kubectl은 Bash 및 Zsh에 대한 자동 완성 지원을 제공하므로 입력
{{< include "included/optional-kubectl-configs-zsh.md" >}}
### `kubectl convert` 플러그인 설치
{{< include "included/kubectl-convert-overview.md" >}}
1. 다음 명령으로 최신 릴리스를 다운로드한다.
```powershell
curl -LO https://dl.k8s.io/release/{{< param "fullversion" >}}/bin/windows/amd64/kubectl-convert.exe
```
1. 바이너리를 검증한다. (선택 사항)
kubectl-convert 체크섬(checksum) 파일을 다운로드한다.
```powershell
curl -LO https://dl.k8s.io/{{< param "fullversion" >}}/bin/windows/amd64/kubectl-convert.exe.sha256
```
kubectl-convert 바이너리를 체크섬 파일을 통해 검증한다.
- 수동으로 `CertUtil` 의 출력과 다운로드한 체크섬 파일을 비교하기 위해서 커맨드 프롬프트를 사용한다.
```cmd
CertUtil -hashfile kubectl-convert.exe SHA256
type kubectl-convert.exe.sha256
```
- `-eq` 연산자를 통해 `True` 또는 `False` 결과를 얻는 자동 검증을 위해서 PowerShell을 사용한다.
```powershell
$($(CertUtil -hashfile .\kubectl-convert.exe SHA256)[1] -replace " ", "") -eq $(type .\kubectl-convert.exe.sha256)
```
1. 바이너리를 `PATH` 가 설정된 디렉터리에 추가한다.
1. 플러그인이 정상적으로 설치되었는지 확인한다.
```shell
kubectl convert --help
```
에러가 출력되지 않는다면, 플러그인이 정상적으로 설치된 것이다.
## {{% heading "whatsnext" %}}
{{< include "included/kubectl-whats-next.md" >}}

View File

@ -25,8 +25,8 @@ weight: 20
</div>
<div class="row">
<div class="col-md-12">
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/" role="button">
모듈 2로 진행하기<span class="btn__next"></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/" role="button">홈으로 이동<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/" role="button">모듈 2로 진행하기 &gt<span class=""></span></a>
</div>
</div>

View File

@ -37,8 +37,9 @@ weight: 20
</div>
<div class="row">
<div class="col-md-12">
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/explore/explore-intro/" role="button">
모듈 3으로 진행하기<span class="btn__next"></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro/" role="button"> &lt 모듈 1로 돌아가기<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/" role="button">홈으로 이동<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/explore/explore-intro/" role="button">모듈 3으로 진행하기 &gt<span class=""></span></a>
</div>
</div>

View File

@ -29,8 +29,9 @@ weight: 20
</div>
<div class="row">
<div class="col-md-12">
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/expose/expose-intro/" role="button">모듈 4로
진행하기<span class="btn__next"></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/" role="button">&lt 모듈 2로 돌아가기<span class="btn"></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/" role="button">홈으로 이동<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/expose/expose-intro/" role="button">모듈 4로 진행하기 &gt<span class="btn"></span></a>
</div>
</div>

View File

@ -74,11 +74,11 @@ weight: 10
<div class="row">
<div class="col-md-8">
<h2>노드</h2>
<p>파드는 언제나 <b>노드</b> 상에서 동작한다. 노드는 쿠버네티스에서 워커 머신을 말하며 클러스터에 따라 가상 또는 물리 머신일 수 있다. 각 노드는 마스터에 의해 관리된다. 하나의 노드는 여러 개의 파드를 가질 수 있고, 쿠버네티스 마스터는 클러스터 내 노드를 통해서 파드에 대한 스케쥴링을 자동으로 처리한다.</p>
<p>파드는 언제나 <b>노드</b> 상에서 동작한다. 노드는 쿠버네티스에서 워커 머신을 말하며 클러스터에 따라 가상 또는 물리 머신일 수 있다. 각 노드는 컨트롤 플레인에 의해 관리된다. 하나의 노드는 여러 개의 파드를 가질 수 있고, 쿠버네티스 컨트롤 플레인은 클러스터 내 노드를 통해서 파드에 대한 스케쥴링을 자동으로 처리한다. 컨트롤 플레인의 자동 스케줄링은 각 노드의 사용 가능한 리소스를 모두 고려합니다.</p>
<p>모든 쿠버네티스 노드는 최소한 다음과 같이 동작한다.</p>
<ul>
<li>Kubelet은, 쿠버네티스 마스터와 노드 간 통신을 책임지는 프로세스이며, 하나의 머신 상에서 동작하는 파드와 컨테이너를 관리한다.</li>
<li>Kubelet은, 쿠버네티스 컨트롤 플레인과 노드 간 통신을 책임지는 프로세스이며, 하나의 머신 상에서 동작하는 파드와 컨테이너를 관리한다.</li>
<li>컨테이너 런타임(도커와 같은)은 레지스트리에서 컨테이너 이미지를 가져와 묶여 있는 것을 풀고 애플리케이션을 동작시키는 책임을 맡는다. </li>
</ul>

View File

@ -26,7 +26,9 @@ weight: 20
</div>
<div class="row">
<div class="col-md-12">
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/scale/scale-intro/" role="button">모듈 5로 진행하기<span class="btn__next"></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/explore/explore-intro/" role="button">&lt 모듈 3으로 돌아가기<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/" role="button">홈으로 이동<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/scale/scale-intro/" role="button">모듈 5로 진행하기 &gt<span class=""></span></a>
</div>
</div>

View File

@ -26,8 +26,9 @@ weight: 20
</div>
<div class="row">
<div class="col-md-12">
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/update/update-intro/" role="button">
모듈 6으로 진행하기<span class="btn__next"></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/expose/expose-interactive/" role="button">&lt 모듈 4로 돌아가기<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/" role="button">홈으로 이동<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/update/update-intro/" role="button">모듈 6으로 진행하기 &gt<span class=""></span></a>
</div>
</div>

View File

@ -26,7 +26,8 @@ weight: 20
</div>
<div class="row">
<div class="col-md-12">
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/" role="button">쿠버네티스 기초로 돌아가기<span class="btn__next"></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/scale/scale-interactive/" role="button">&lt 모듈 5로 돌아가기<span class=""></span></a>
<a class="btn btn-lg btn-success" href="/ko/docs/tutorials/kubernetes-basics/" role="button">쿠버네티스 기초로 돌아가기<span class=""></span></a>
</div>
</div>
</main>

View File

@ -14,7 +14,10 @@ source: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
---
<!-- overview -->
이 튜토리얼에서는 쿠버네티스와 [Docker](https://www.docker.com/)를 사용하여 간단한 _(운영 수준이 아닌)_ 멀티 티어 웹 애플리케이션을 빌드하고 배포하는 방법을 보여준다. 이 예제는 다음과 같은 구성으로 이루어져 있다.
이 튜토리얼에서는 쿠버네티스와 [Docker](https://www.docker.com/)를 사용하여 간단한
_(운영 수준이 아닌)_ 멀티 티어 웹 애플리케이션을 빌드하고 배포하는 방법을 보여준다.
이 예제는 다음과 같은 구성으로
이루어져 있다.
* 방명록 항목을 저장하기 위한 단일 인스턴스 [Redis](https://www.redis.com/)
* 여러 개의 웹 프론트엔드 인스턴스
@ -48,142 +51,157 @@ source: https://cloud.google.com/kubernetes-engine/docs/tutorials/guestbook
1. 매니페스트 파일을 다운로드한 디렉터리에서 터미널 창을 시작한다.
1. `redis-leader-deployment.yaml` 파일을 이용하여 Redis 디플로이먼트를 생성한다.
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-deployment.yaml
-->
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-deployment.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
```
1. 파드의 목록을 질의하여 Redis 파드가 실행 중인지 확인한다.
```shell
kubectl get pods
```
```shell
kubectl get pods
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME READY STATUS RESTARTS AGE
redis-leader-fb76b4755-xjr2n 1/1 Running 0 13s
```
```
NAME READY STATUS RESTARTS AGE
redis-leader-fb76b4755-xjr2n 1/1 Running 0 13s
```
2. Redis 리더 파드의 로그를 보려면 다음 명령어를 실행한다.
```shell
kubectl logs -f deployment/redis-leader
```
```shell
kubectl logs -f deployment/redis-leader
```
### Redis 리더 서비스 생성하기
방명록 애플리케이션에서 데이터를 쓰려면 Redis와 통신해야 한다. Redis 파드로 트래픽을 프록시하려면 [서비스](/ko/docs/concepts/services-networking/service/)를 생성해야 한다. 서비스는 파드에 접근하기 위한 정책을 정의한다.
방명록 애플리케이션에서 데이터를 쓰려면 Redis와 통신해야 한다.
Redis 파드로 트래픽을 프록시하려면 [서비스](/ko/docs/concepts/services-networking/service/)를 생성해야 한다.
서비스는 파드에 접근하기 위한 정책을
정의한다.
{{< codenew file="application/guestbook/redis-leader-service.yaml" >}}
1. `redis-leader-service.yaml` 파일을 이용하여 Redis 서비스를 실행한다.
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-service.yaml
-->
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-leader-service.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml
```
1. 서비스의 목록을 질의하여 Redis 서비스가 실행 중인지 확인한다.
```shell
kubectl get service
```
```shell
kubectl get service
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1m
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 16s
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 1m
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 16s
```
{{< note >}}
이 매니페스트 파일은 이전에 정의된 레이블과 일치하는 레이블 집합을 가진 `redis-leader`라는 서비스를 생성하므로, 서비스는 네트워크 트래픽을 Redis 파드로 라우팅한다.
이 매니페스트 파일은 이전에 정의된 레이블과 일치하는 레이블 집합을 가진
`redis-leader`라는 서비스를 생성하므로, 서비스는 네트워크 트래픽을
Redis 파드로 라우팅한다.
{{< /note >}}
### Redis 팔로워 구성하기
Redis 리더는 단일 파드이지만, 몇 개의 Redis 팔로워 또는 복제본을 추가하여 가용성을 높이고 트래픽 요구를 충족할 수 있다.
Redis 리더는 단일 파드이지만, 몇 개의 Redis 팔로워 또는 복제본을 추가하여
가용성을 높이고 트래픽 요구를 충족할 수 있다.
{{< codenew file="application/guestbook/redis-follower-deployment.yaml" >}}
1. `redis-follower-deployment.yaml` 파일을 이용하여 Redis 서비스를 실행한다.
<!---
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-follower-deployment.yaml
-->
<!---
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-follower-deployment.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml
```
1. 파드의 목록을 질의하여 2개의 Redis 팔로워 레플리카가 실행 중인지 확인한다.
```shell
kubectl get pods
```
```shell
kubectl get pods
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME READY STATUS RESTARTS AGE
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 37s
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 38s
redis-leader-fb76b4755-xjr2n 1/1 Running 0 11m
```
```
NAME READY STATUS RESTARTS AGE
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 37s
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 38s
redis-leader-fb76b4755-xjr2n 1/1 Running 0 11m
```
### Redis 팔로워 서비스 생성하기
방명록 애플리케이션이 데이터를 읽으려면 Redis 팔로워와 통신해야 한다. Redis 팔로워를 발견 가능(discoverable)하게 만드려면, 새로운 [서비스](/ko/docs/concepts/services-networking/service/)를 구성해야 한다.
방명록 애플리케이션이 데이터를 읽으려면 Redis 팔로워와 통신해야 한다.
Redis 팔로워를 발견 가능(discoverable)하게 만드려면, 새로운
[서비스](/ko/docs/concepts/services-networking/service/)를 구성해야 한다.
{{< codenew file="application/guestbook/redis-follower-service.yaml" >}}
1. `redis-follower-service.yaml` 파일을 이용하여 Redis 서비스를 실행한다.
<!---
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-follower-service.yaml
-->
<!---
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/redis-follower-service.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml
```
1. 서비스의 목록을 질의하여 Redis 서비스가 실행 중인지 확인한다.
```shell
kubectl get service
```
```shell
kubectl get service
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 9s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 6m10s
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 9s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 6m10s
```
{{< note >}}
이 매니페스트 파일은 이전에 정의된 레이블과 일치하는 레이블 집합을 가진 `redis-follower`라는 서비스를 생성하므로, 서비스는 네트워크 트래픽을 Redis 파드로 라우팅한다.
이 매니페스트 파일은 이전에 정의된 레이블과 일치하는 레이블 집합을 가진
`redis-follower`라는 서비스를 생성하므로, 서비스는 네트워크 트래픽을
Redis 파드로 라우팅한다.
{{< /note >}}
## 방명록 프론트엔드를 설정하고 노출하기
방명록을 위한 Redis 저장소를 구성하고 실행했으므로, 이제 방명록 웹 서버를 실행한다. Redis 팔로워와 마찬가지로, 프론트엔드는 쿠버네티스 디플로이먼트(Deployment)를 사용하여 배포된다.
방명록을 위한 Redis 저장소를 구성하고 실행했으므로, 이제 방명록 웹 서버를 실행한다.
Redis 팔로워와 마찬가지로, 프론트엔드는 쿠버네티스 디플로이먼트(Deployment)를
사용하여 배포된다.
방명록 앱은 PHP 프론트엔드를 사용한다. DB에 대한 요청이 읽기인지 쓰기인지에 따라, Redis 팔로워 또는 리더 서비스와 통신하도록 구성된다. 프론트엔드는 JSON 인터페이스를 노출하고, jQuery-Ajax 기반 UX를 제공한다.
방명록 앱은 PHP 프론트엔드를 사용한다. DB에 대한 요청이 읽기인지 쓰기인지에 따라,
Redis 팔로워 또는 리더 서비스와 통신하도록 구성된다. 프론트엔드는 JSON 인터페이스를
노출하고,
jQuery-Ajax 기반 UX를 제공한다.
### 방명록 프론트엔드의 디플로이먼트 생성하기
@ -191,195 +209,210 @@ Redis 리더는 단일 파드이지만, 몇 개의 Redis 팔로워 또는 복제
1. `frontend-deployment.yaml` 파일을 이용하여 프론트엔드 디플로이먼트를 생성한다.
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/frontend-deployment.yaml
-->
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/frontend-deployment.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
```
1. 파드의 목록을 질의하여 세 개의 프론트엔드 복제본이 실행되고 있는지 확인한다.
```shell
kubectl get pods -l app=guestbook -l tier=frontend
```
```shell
kubectl get pods -l app=guestbook -l tier=frontend
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5tqhb 1/1 Running 0 47s
frontend-85595f5bf9-qbzwm 1/1 Running 0 47s
frontend-85595f5bf9-zchwc 1/1 Running 0 47s
```
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5tqhb 1/1 Running 0 47s
frontend-85595f5bf9-qbzwm 1/1 Running 0 47s
frontend-85595f5bf9-zchwc 1/1 Running 0 47s
```
### 프론트엔드 서비스 생성하기
서비스의 기본 유형은 [ClusterIP](/ko/docs/concepts/services-networking/service/#publishing-services-service-types)이기 때문에 생성한 `Redis` 서비스는 컨테이너 클러스터 내에서만 접근할 수 있다. `ClusterIP`는 서비스가 가리키는 파드 집합에 대한 단일 IP 주소를 제공한다. 이 IP 주소는 클러스터 내에서만 접근할 수 있다.
서비스의 기본 유형은
[ClusterIP](/ko/docs/concepts/services-networking/service/#publishing-services-service-types)
이기 때문에 생성한 `Redis` 서비스는 컨테이너 클러스터 내에서만 접근할 수 있다.
`ClusterIP`는 서비스가 가리키는 파드 집합에 대한
단일 IP 주소를 제공한다. 이 IP 주소는 클러스터 내에서만 접근할 수 있다.
게스트가 방명록에 접근할 수 있도록 하려면, 외부에서 볼 수 있도록 프론트엔드 서비스를 구성해야 한다. 그렇게 하면 클라이언트가 쿠버네티스 클러스터 외부에서 서비스를 요청할 수 있다. 그러나 쿠버네티스 사용자는 `ClusterIP`를 사용하더라도 `kubectl port-forward`를 사용해서 서비스에 접근할 수 있다.
게스트가 방명록에 접근할 수 있도록 하려면, 외부에서 볼 수 있도록 프론트엔드
서비스를 구성해야 한다. 그렇게 하면 클라이언트가 쿠버네티스 클러스터 외부에서
서비스를 요청할 수 있다. 그러나 쿠버네티스 사용자는 `ClusterIP`
사용하더라도 `kubectl port-forward`를 사용해서 서비스에
접근할 수 있다.
{{< note >}}
Google Compute Engine 또는 Google Kubernetes Engine과 같은 일부 클라우드 공급자는 외부 로드 밸런서를 지원한다. 클라우드 공급자가 로드 밸런서를 지원하고 이를 사용하려면 `type : LoadBalancer`의 주석을 제거해야 한다.
Google Compute Engine 또는 Google Kubernetes Engine
과 같은 일부 클라우드 공급자는 외부 로드 밸런서를 지원한다. 클라우드 공급자가 로드
밸런서를 지원하고 이를 사용하려면 `type : LoadBalancer`의 주석을 제거해야 한다.
{{< /note >}}
{{< codenew file="application/guestbook/frontend-service.yaml" >}}
1. `frontend-service.yaml` 파일을 이용하여 프론트엔드 서비스를 실행한다.
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/frontend-service.yaml
-->
<!--
로컬에 있는 파일로 테스트하려면 다음과 같이 상대 경로로 기재한다.
kubectl apply -f ./content/en/examples/application/guestbook/frontend-service.yaml
-->
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
```
```shell
kubectl apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml
```
1. 서비스의 목록을 질의하여 프론트엔드 서비스가 실행 중인지 확인한다.
```shell
kubectl get services
```
```shell
kubectl get services
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.97.28.230 <none> 80/TCP 19s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 5m48s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 11m
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend ClusterIP 10.97.28.230 <none> 80/TCP 19s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d19h
redis-follower ClusterIP 10.110.162.42 <none> 6379/TCP 5m48s
redis-leader ClusterIP 10.103.78.24 <none> 6379/TCP 11m
```
### `kubectl port-forward`를 통해 프론트엔드 서비스 확인하기
1. 다음 명령어를 실행해서 로컬 머신의 `8080` 포트를 서비스의 `80` 포트로 전달한다.
```shell
kubectl port-forward svc/frontend 8080:80
```
```shell
kubectl port-forward svc/frontend 8080:80
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
```
```
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
```
1. 방명록을 보기 위해 브라우저에서 [http://localhost:8080](http://localhost:8080) 페이지를 로드한다.
### `LoadBalancer`를 통해 프론트엔드 서비스 확인하기
`frontend-service.yaml` 매니페스트를 `LoadBalancer`와 함께 배포한 경우, 방명록을 보기 위해 IP 주소를 찾아야 한다.
`frontend-service.yaml` 매니페스트를 `LoadBalancer`와 함께 배포한 경우,
방명록을 보기 위해 IP 주소를 찾아야 한다.
1. 프론트엔드 서비스의 IP 주소를 얻기 위해 아래 명령어를 실행한다.
```shell
kubectl get service frontend
```
```shell
kubectl get service frontend
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.51.242.136 109.197.92.229 80:32372/TCP 1m
```
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
frontend LoadBalancer 10.51.242.136 109.197.92.229 80:32372/TCP 1m
```
1. IP 주소를 복사하고, 방명록을 보기 위해 브라우저에서 페이지를 로드한다.
{{< note >}}
메시지를 입력하고 'Submit'을 클릭하여 방명록에 글을 작성해 본다. 입력한 메시지가 프론트엔드에 나타난다. 이 메시지는 앞서 생성한 서비스를 통해 데이터가 Redis에 성공적으로 입력되었음을 나타낸다.
메시지를 입력하고 'Submit'을 클릭하여 방명록에 글을 작성해 본다.
입력한 메시지가 프론트엔드에 나타난다. 이 메시지는 앞서 생성한 서비스를
통해 데이터가 Redis에 성공적으로 입력되었음을 나타낸다.
{{< /note >}}
## 웹 프론트엔드 확장하기
서버가 디플로이먼트 컨트롤러를 사용하는 서비스로 정의되어 있으므로 필요에 따라 확장 또는 축소할 수 있다.
서버가 디플로이먼트 컨트롤러를 사용하는 서비스로 정의되어 있으므로
필요에 따라 확장 또는 축소할 수 있다.
1. 프론트엔드 파드의 수를 확장하기 위해 아래 명령어를 실행한다.
```shell
kubectl scale deployment frontend --replicas=5
```
```shell
kubectl scale deployment frontend --replicas=5
```
1. 파드의 목록을 질의하여 실행 중인 프론트엔드 파드의 수를 확인한다.
```shell
kubectl get pods
```
```shell
kubectl get pods
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5df5m 1/1 Running 0 83s
frontend-85595f5bf9-7zmg5 1/1 Running 0 83s
frontend-85595f5bf9-cpskg 1/1 Running 0 15m
frontend-85595f5bf9-l2l54 1/1 Running 0 14m
frontend-85595f5bf9-l9c8z 1/1 Running 0 14m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 97m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 97m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 108m
```
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-5df5m 1/1 Running 0 83s
frontend-85595f5bf9-7zmg5 1/1 Running 0 83s
frontend-85595f5bf9-cpskg 1/1 Running 0 15m
frontend-85595f5bf9-l2l54 1/1 Running 0 14m
frontend-85595f5bf9-l9c8z 1/1 Running 0 14m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 97m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 97m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 108m
```
1. 프론트엔드 파드의 수를 축소하기 위해 아래 명령어를 실행한다.
```shell
kubectl scale deployment frontend --replicas=2
```
```shell
kubectl scale deployment frontend --replicas=2
```
1. 파드의 목록을 질의하여 실행 중인 프론트엔드 파드의 수를 확인한다.
```shell
kubectl get pods
```
```shell
kubectl get pods
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-cpskg 1/1 Running 0 16m
frontend-85595f5bf9-l9c8z 1/1 Running 0 15m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 98m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 98m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 109m
```
```
NAME READY STATUS RESTARTS AGE
frontend-85595f5bf9-cpskg 1/1 Running 0 16m
frontend-85595f5bf9-l9c8z 1/1 Running 0 15m
redis-follower-dddfbdcc9-82sfr 1/1 Running 0 98m
redis-follower-dddfbdcc9-qrt5k 1/1 Running 0 98m
redis-leader-fb76b4755-xjr2n 1/1 Running 0 109m
```
## {{% heading "cleanup" %}}
디플로이먼트 및 서비스를 삭제하면 실행 중인 모든 파드도 삭제된다. 레이블을 사용하여 하나의 명령어로 여러 자원을 삭제해보자.
디플로이먼트 및 서비스를 삭제하면 실행 중인 모든 파드도 삭제된다.
레이블을 사용하여 하나의 명령어로 여러 자원을 삭제해보자.
1. 모든 파드, 디플로이먼트, 서비스를 삭제하기 위해 아래 명령어를 실행한다.
```shell
kubectl delete deployment -l app=redis
kubectl delete service -l app=redis
kubectl delete deployment frontend
kubectl delete service frontend
```
```shell
kubectl delete deployment -l app=redis
kubectl delete service -l app=redis
kubectl delete deployment frontend
kubectl delete service frontend
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
deployment.apps "redis-follower" deleted
deployment.apps "redis-leader" deleted
deployment.apps "frontend" deleted
service "frontend" deleted
```
```
deployment.apps "redis-follower" deleted
deployment.apps "redis-leader" deleted
deployment.apps "frontend" deleted
service "frontend" deleted
```
1. 파드의 목록을 질의하여 실행 중인 파드가 없는지 확인한다.
```shell
kubectl get pods
```
```shell
kubectl get pods
```
결과는 아래와 같은 형태로 나타난다.
결과는 아래와 같은 형태로 나타난다.
```
No resources found in default namespace.
```
```
No resources found in default namespace.
```
## {{% heading "whatsnext" %}}