# API를 이용한 축출(API-initiated Eviction)

LLMS index: [llms.txt](/llms.txt)

---

API를 이용한 축출은 <a href="/docs/reference/generated/kubernetes-api/v1.36/#create-eviction-pod-v1-core">축출 API</a>를 사용하여
생성된 <code>Eviction</code> 오브젝트로 파드를 정상 종료한다. </br>

축출 API를 직접 호출하거나, 또는 `kubectl drain` 명령과 같이 
<a class='glossary-tooltip' title='쿠버네티스 API를 제공하는 컨트롤 플레인 컴포넌트.' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/concepts/overview/components/#kube-apiserver' target='_blank' aria-label='API 서버'>API 서버</a>의 클라이언트를 사용하여 프로그램적인 방법으로 축출 요청을 할 수 있다. 
이는 `Eviction` 오브젝트를 만들며, API 서버로 하여금 파드를 종료하도록 만든다.

API를 이용한 축출은 사용자가 설정한 [`PodDisruptionBudgets`](/docs/tasks/run-application/configure-pdb/) 및 
[`terminationGracePeriodSeconds`](/ko/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination) 값을 준수한다.

API를 사용하여 `Eviction` 오브젝트를 만드는 것은 
정책 기반의 파드 [`DELETE` 동작](/docs/reference/kubernetes-api/workload-resources/pod-v1/#delete-delete-a-pod)을 수행하는 것과 
비슷한 효과를 낸다.

## 축출 API 호출하기

[각 언어 별 쿠버네티스 클라이언트](/ko/docs/tasks/administer-cluster/access-cluster-api/#api에-프로그래밍-방식으로-접근)를 사용하여 
쿠버네티스 API를 호출하고 `Eviction` 오브젝트를 생성할 수 있다. 
이를 실행하려면, 아래의 예시를 참고하여 POST 호출을 수행한다.

<ul class="nav nav-tabs" id="tabs-eviction-example" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-eviction-example-0" role="tab" aria-controls="tabs-eviction-example-0" aria-selected="true">policy/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-eviction-example-1" role="tab" aria-controls="tabs-eviction-example-1">policy/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-eviction-example-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-eviction-example-0" role="tabpanel" aria-labelledby="tabs-eviction-example-0-tab" tabindex="eviction-example"><div class="alert alert-info" role="note"><h4 class="alert-heading">참고:</h4><code>policy/v1</code> 축출은 v1.22 이상에서 사용 가능하다. 이전 버전에서는 <code>policy/v1beta1</code>를 사용한다.</div>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;apiVersion&#34;</span><span class="p">:</span> <span class="s2">&#34;policy/v1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;kind&#34;</span><span class="p">:</span> <span class="s2">&#34;Eviction&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;metadata&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;quux&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;namespace&#34;</span><span class="p">:</span> <span class="s2">&#34;default&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-eviction-example-1" role="tabpanel" aria-labelledby="tabs-eviction-example-1-tab" tabindex="eviction-example"><div class="alert alert-info" role="note"><h4 class="alert-heading">참고:</h4>v1.22에서 사용 중단 및 <code>policy/v1</code>으로 대체되었다.</div>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;apiVersion&#34;</span><span class="p">:</span> <span class="s2">&#34;policy/v1beta1&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;kind&#34;</span><span class="p">:</span> <span class="s2">&#34;Eviction&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;metadata&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;quux&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;namespace&#34;</span><span class="p">:</span> <span class="s2">&#34;default&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div></div></div>


또는 다음 예시와 같이 `curl` 또는 `wget`으로 API에 접근하여 
축출 동작을 시도할 수도 있다.

```bash
curl -v -H 'Content-type: application/json' https://your-cluster-api-endpoint.example/api/v1/namespaces/default/pods/quux/eviction -d @eviction.json
```

## API를 이용한 축출의 동작

API를 사용하여 축출을 요청하면, 
API 서버는 인가 확인(admission checks)를 수행하고 다음 중 하나로 응답한다.

* `200 OK`: 축출 요청이 허용되었고, `Eviction` 서브리소스가 생성되었고, 
  (마치 파드 URL에 `DELETE` 요청을 보낸 것처럼) 파드가 삭제되었다.
* `429 Too Many Requests`: 현재 설정된 
  <a class='glossary-tooltip' title='An object that limits the number of Pods of a replicated application that are down simultaneously from voluntary disruptions.' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/reference/glossary/?all=true#term-pod-disruption-budget' target='_blank' aria-label='PodDisruptionBudget'>PodDisruptionBudget</a> 때문에 
  축출이 현재 허용되지 않는다. 
  또는 API 요청 속도 제한(rate limiting) 때문에 이 응답을 받았을 수도 있다.
* `500 Internal Server Error`: 잘못된 환경 설정(예: 
  여러 PodDisruptionBudget이 하나의 동일한 파드를 참조함)으로 인해 축출이 허용되지 않는다.

축출하려는 파드가 
PodDisruptionBudget이 설정된 워크로드에 속하지 않는다면, 
API 서버는 항상 `200 OK`를 반환하고 축출을 허용한다.

API 서버가 축출을 허용하면, 파드는 다음과 같이 삭제된다.

1. API 서버 내 `Pod` 리소스의 삭제 타임스탬프(deletion timestamp)가 업데이트되며, 
   이 타임스탬프에 명시된 시각이 경과하면 API 서버는 해당 `Pod` 리소스를 종료 대상으로 간주한다. 
   또한 설정된 그레이스 시간(grace period)이 `Pod` 리소스에 기록된다.
1. 로컬 파드가 실행되고 있는 노드의 <a class='glossary-tooltip' title='클러스터의 각 노드에서 실행되는 에이전트. Kubelet은 파드에서 컨테이너가 확실하게 동작하도록 관리한다.' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/reference/generated/kubelet' target='_blank' aria-label='kubelet'>kubelet</a>이 
   `Pod`가 종료 대상으로 표시된 것을 감지하고 
   로컬 파드의 그레이스풀 셧다운을 시작한다.
1. kubelet이 파드를 종료하는 와중에, 컨트롤 플레인은 
   <a class='glossary-tooltip' title='엔드포인트는 서비스(Service) 셀렉터에 매치되는 파드의 IP 주소를 추적한다.' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/reference/glossary/?all=true#term-endpoint' target='_blank' aria-label='엔드포인트'>엔드포인트</a> 및 
   <a class='glossary-tooltip' title='EndpointSlices track the IP addresses of Pods for Services.' data-bs-toggle='tooltip' data-bs-placement='top' href='/ko/docs/concepts/services-networking/endpoint-slices/' target='_blank' aria-label='엔드포인트슬라이스'>엔드포인트슬라이스</a> 오브젝트에서 파드를 삭제한다. 
   이 결과, 컨트롤러는 파드를 더 이상 유효한 오브젝트로 간주하지 않는다.
1. 파드의 그레이스 시간이 만료되면, 
   kubelet이 로컬 파드를 강제로 종료한다.
1. kubelet이 API 서버에 `Pod` 리소스를 삭제하도록 지시한다.
1. API 서버가 `Pod` 리소스를 삭제한다.

## 문제가 있어 중단된 축출 트러블슈팅하기

일부 경우에, 애플리케이션이 잘못된 상태로 돌입하여, 
직접 개입하기 전에는 축출 API가 `429` 또는 `500` 응답만 반환할 수 있다. 
이러한 현상은, 예를 들면 레플리카셋이 애플리케이션을 서비스할 파드를 생성했지만 
새 파드가 `Ready`로 바뀌지 못하는 경우에 발생할 수 있다. 
또는 마지막으로 축출된 파드가 긴 종료 그레이스 시간을 가진 경우에 이러한 현상을 목격할 수도 있다.

문제가 있어 중단된 축출을 발견했다면, 다음 해결책 중 하나를 시도해 본다.

* 이 문제를 발생시키는 자동 동작(automated operation)을 중단하거나 일시 중지한다. 
  해당 동작을 재시작하기 전에, 문제가 있어 중단된 애플리케이션을 조사한다.
* 잠시 기다린 뒤, 축출 API를 사용하는 것 대신 
  클러스터 컨트롤 플레인에서 파드를 직접 삭제한다.

## 다음 내용

* [Pod Disruption Budget](/docs/tasks/run-application/configure-pdb/)을 사용하여 애플리케이션을 보호하는 방법에 대해 알아본다.
* [노드-압박 축출](/ko/docs/concepts/scheduling-eviction/node-pressure-eviction/)에 대해 알아본다.
* [파드 우선순위와 선점](/ko/docs/concepts/scheduling-eviction/pod-priority-preemption/)에 대해 알아본다.
