[![logo](https://www.hongsnet.net/images/logo.gif)](https://www.hongsnet.net)

# Node CPU Context Switching Heavy 검증

## Context Switching 개요

멀티 프로세스환경에서 CPU가 한 개의 Task(Process/Thread)를 실행하고 있는 상태에서 Interrupt 또는 SystemCall의 요청에 의해 새로운/다른 Task로 실행이 전환되는 과정에서 **기존 Task** 상태 및 Register 값들에 대한 정보(Context)를 저장하고, **새로운 Task**의 Context 정보로 `교체하는 작업`을 뜻한다.

**Context**란 CPU가 핸들링하는 Task(Process / Thread)에 대한 정보로 CPU의 Register에 저장되며, `PCB`(Process Control Block)을 통해 관리한다. 또한 Process와 Thread를 처리하는 Context Swiching은 다른데 `PCB`는 **OS 스케줄러가 담당**하고, `Thread`의 경우 Process 내의 TCB(Task Control Block)의 내부 구조를 통해 관리된다.

PCB(Process Control Block)는 주로 다음과 같은 정보들을 저장한다.

- 프로세스 상태 (Process State)
- 명령어 주소 (Program Counter, 다음에 실행할 명령어 주소)
- 레지스터 (프로세스 레지스터 정보)
- 프로세스 번호

> Context Switching은 주로 `Interrupt`에 의해 발생되는데, H/W를 통한 I/O 요청이나 OS Timer, Device Driver 스케줄링 시 주로 발생한다.

> `시스템영향` : Context Switching이 빈번해지면 CPU는 Cache 및 Memory Mapping 정보를 초기화해야하므로, CPU의 성능저하(처리지연)이 발생된다.

> 더 나은(Better) : 일반적으로 멀티스레드를 통해 TCB를 Context Switching 하는 것이 Cost가 적다고 알려져 있다.


# Configuration

**5분** 동안 초당 Context Switching이 `3000`번 이상 경우가 감지된 경우 Alert을 발생시키는 Rule

- **결과**

![context_switching](../../images/context_switching.png)

- **검증 과정**

* [ **STEP 1** ] : Prometheus의 Graph 메뉴의 Expression에서 수식에 대한 검증을 진행한다.

![context_switching_verify](../../images/context_switching_verify.png)

> 대상 Nodes에 현재 Context Switching 값이 쿼리 된다.


* [ **STEP 2** ] : Prometheus Configmap 파일에 ITEM을 추가한다.

```bash
# cat prometheus-config-map.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-server-conf
  labels:
    name: prometheus-server-conf
  namespace: monitoring
data:
  prometheus.rules: |-
    groups:
    - name: Node Context Switching
      rules:
      - alert: HostContextSwitching
        expr: (rate(node_context_switches_total[5m])) / (count without(cpu, mode) (node_cpu_seconds_total{mode="idle"})) > 3000
        for: 0m
        labels:
          severity: warning
        annotations:
          summary: "Host context switching (instance {{ $labels.instance }})"
          description: "Context switching is growing on node (> 3000/s)\n  VALUE = {{ $value }}\n  LABELS: {{ $labels }}"
...하략
```

* [ **STEP 3** ] : kubectl 툴을 이용하여 Replace 처리하고, curl을 이용하여 POST **reload** Payload를 전송한다.

```bash
# kubectl replace -f prometheus-config-map.yaml
# curl -X POST http://172.24.0.222:30003/-/reload
```

> 또는 prometheus를 재시작하면 즉시 적용된다.

# Verify

* [ **STEP 1** ] : 검증을 위해 3000/s 기준을 **1000**/s로 변경한다.

```python
expr: (rate(node_context_switches_total[5m])) / (count without(cpu, mode) (node_cpu_seconds_total{mode="idle"})) > 1000
```

* [ **STEP 2** ] : Alert Manager를 통한 Alert 발송을 확인한다. 1000/s로 변경되었기 때문에 **일부 Node가 해당된 상태**이다.

![context_switching_alert](../../images/context_swiching_alert.png)


* [ **STEP 3** ] : Resolved를 검증하기 위해 다시 기존 3000/s로 변경한다.

```python
expr: (rate(node_context_switches_total[5m])) / (count without(cpu, mode) (node_cpu_seconds_total{mode="idle"})) > 3000
```

* [ **STEP 4** ] : Alert Manager를 통한 `Resolved` Alert 발송을 확인한다.

![context_switching_resolved](../../images/context_switching_resolved.png)
