|
| 1 | +--- |
| 2 | + |
| 3 | + |
| 4 | + |
| 5 | +title: 동작 중인 파드 디버그 |
| 6 | +content_type: task |
| 7 | +--- |
| 8 | + |
| 9 | +<!-- overview --> |
| 10 | + |
| 11 | +이 페이지는 노드에서 동작 중인(혹은 크래시된) 파드를 디버그하는 방법에 대해 설명한다. |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +## {{% heading "prerequisites" %}} |
| 16 | + |
| 17 | + |
| 18 | +* 여러분의 {{< glossary_tooltip text="파드" term_id="pod" >}}는 이미 스케줄링 되어 |
| 19 | + 동작하고 있을 것이다. 만약 파드가 아직 동작중이지 않다면, [애플리케이션 |
| 20 | + 트러블슈팅](/docs/tasks/debug-application-cluster/debug-application/)을 참고한다. |
| 21 | +* 일부 고급 디버깅 과정에서는 해당 파드가 어떤 노드에서 동작하고 있는지 |
| 22 | + 알아야 하고, 해당 노드에서 쉘 명령어를 실행시킬 수 있어야 한다. |
| 23 | + `kubectl`을 사용하는 일반적인 디버깅 과정에서는 이러한 접근 권한이 필요하지 않다. |
| 24 | + |
| 25 | + |
| 26 | + |
| 27 | +<!-- steps --> |
| 28 | + |
| 29 | +## 파드의 로그 확인하기 {#examine-pod-logs} |
| 30 | + |
| 31 | +먼저, 확인하고자 하는 컨테이너의 로그를 확인한다. |
| 32 | + |
| 33 | +```shell |
| 34 | +kubectl logs ${POD_NAME} ${CONTAINER_NAME} |
| 35 | +``` |
| 36 | + |
| 37 | +만약 컨테이너가 이전에 크래시 되었다면, 다음의 명령을 통해 컨테이너의 크래시 로그를 살펴볼 수 있다. |
| 38 | + |
| 39 | +```shell |
| 40 | +kubectl logs --previous ${POD_NAME} ${CONTAINER_NAME} |
| 41 | +``` |
| 42 | + |
| 43 | +## exec를 통해 컨테이너 디버깅하기 {#container-exec} |
| 44 | + |
| 45 | +만약 {{< glossary_tooltip text="컨테이너 이미지" term_id="image" >}}에 |
| 46 | +디버깅 도구가 포함되어 있다면, `kubectl exec`을 통해 특정 컨테이너에서 해당 명령들을 |
| 47 | +실행할 수 있다. (리눅스나 윈도우 OS를 기반으로 만들어진 이미지에는 대부분 디버깅 도구를 포함하고 |
| 48 | +있다.) |
| 49 | + |
| 50 | +```shell |
| 51 | +kubectl exec ${POD_NAME} -c ${CONTAINER_NAME} -- ${CMD} ${ARG1} ${ARG2} ... ${ARGN} |
| 52 | +``` |
| 53 | + |
| 54 | +{{< note >}} |
| 55 | +`-c ${CONTAINER_NAME}` 인자는 선택적이다. 만약 하나의 컨테이너만 포함된 파드라면 해당 옵션을 생략할 수 있다. |
| 56 | +{{< /note >}} |
| 57 | + |
| 58 | +예를 들어, 동작 중인 카산드라 파드의 로그를 살펴보기 위해서는 다음과 같은 명령을 실행할 수 있다. |
| 59 | + |
| 60 | +```shell |
| 61 | +kubectl exec cassandra -- cat /var/log/cassandra/system.log |
| 62 | +``` |
| 63 | + |
| 64 | +`kubectl exec`에 `-i`와 `-t` 옵션을 사용해서 터미널에서 접근할 수 있는 쉘을 실행시킬 수도 있다. |
| 65 | +예를 들면 다음과 같다. |
| 66 | + |
| 67 | +```shell |
| 68 | +kubectl exec -it cassandra -- sh |
| 69 | +``` |
| 70 | + |
| 71 | +더욱 상세한 내용은 다음 [동작중인 컨테이너의 쉘에 접근하기]( |
| 72 | +/docs/tasks/debug-application-cluster/get-shell-running-container/)를 참고하라. |
| 73 | + |
| 74 | +## 임시(ephemeral) 디버그 컨테이너를 사용해서 디버깅하기 {#ephemeral-container} |
| 75 | + |
| 76 | +{{< feature-state state="alpha" for_k8s_version="v1.18" >}} |
| 77 | + |
| 78 | +컨테이너가 크래시 됐거나 [distroless 이미지](https://github.com/GoogleContainerTools/distroless)처럼 |
| 79 | +컨테이너 이미지에 디버깅 도구를 포함하고 있지 않아 |
| 80 | +`kubectl exec`가 충분하지 않을 경우에는 |
| 81 | +{{< glossary_tooltip text="임시(Ephemeral) 컨테이너" term_id="ephemeral-container" >}}를 사용하는 것이 |
| 82 | +인터랙티브한 트러블슈팅에 유용하다. `kubectl` `v1.18` |
| 83 | +버전부터는 임시 컨테이너를 생성할 수 있는 알파 단계의 |
| 84 | +명령어가 있다. |
| 85 | + |
| 86 | +### 임시 컨테이너를 사용한 디버깅 예시 {#ephemeral-container-example} |
| 87 | + |
| 88 | +{{< note >}} |
| 89 | +이 섹션에서 소개하는 예시를 사용하기 위해서는 |
| 90 | +여러분의 클러스터에 `EphemeralContainers` [기능 게이트](/docs/reference/command-line-tools-reference/feature-gates/)가 |
| 91 | +활성화되어 있어야 하고 `kubectl`의 버전이 v1.18 이상이어야 한다. |
| 92 | +{{< /note >}} |
| 93 | + |
| 94 | +`kubectl debug` 명령어를 사용해서 동작 중인 파드에 임시 컨테이너를 추가할 수 있다. |
| 95 | +먼저, 다음과 같이 파드를 추가한다. |
| 96 | + |
| 97 | +```shell |
| 98 | +kubectl run ephemeral-demo --image=k8s.gcr.io/pause:3.1 --restart=Never |
| 99 | +``` |
| 100 | + |
| 101 | +이 섹션의 예시에서는 디버깅 도구가 포함되지 않은 이미지의 사례를 보여드리기 위해 |
| 102 | +`pause` 컨테이너 이미지를 사용했는데, 이 대신 어떠한 이미지를 사용해도 |
| 103 | +될 것이다. |
| 104 | + |
| 105 | +만약 `kubectl exec`을 통해 쉘을 생성하려 한다면 다음과 같은 에러를 |
| 106 | +확인할 수 있을 텐데, 그 이유는 이 이미지에 쉘이 존재하지 않기 때문이다. |
| 107 | + |
| 108 | +```shell |
| 109 | +kubectl exec -it ephemeral-demo -- sh |
| 110 | +``` |
| 111 | + |
| 112 | +``` |
| 113 | +OCI runtime exec failed: exec failed: container_linux.go:346: starting container process caused "exec: \"sh\": executable file not found in $PATH": unknown |
| 114 | +``` |
| 115 | + |
| 116 | +이 명령어 대신 `kubectl debug`을 사용해서 디버깅 컨테이너를 생성할 수 있다. |
| 117 | +만약 `-i`/`--interactive` 인자를 사용한다면, `kubectl`은 임시 |
| 118 | +컨테이너의 콘솔에 자동으로 연결할 것이다. |
| 119 | + |
| 120 | +```shell |
| 121 | +kubectl debug -it ephemeral-demo --image=busybox --target=ephemeral-demo |
| 122 | +``` |
| 123 | + |
| 124 | +``` |
| 125 | +Defaulting debug container name to debugger-8xzrl. |
| 126 | +If you don't see a command prompt, try pressing enter. |
| 127 | +/ # |
| 128 | +``` |
| 129 | + |
| 130 | +이 명령어는 새로운 busybox 컨테이너를 추가하고 해당 컨테이너로 연결한다. `--target` |
| 131 | +파라미터를 사용하면 다른 컨테이너의 프로세스 네임스페이스를 대상으로 하게 된다. 여기서는 |
| 132 | +이 옵션이 꼭 필요한데, `kubectl run`이 생성하는 파드에 대해 |
| 133 | +[프로세스 네임스페이스 공유](/docs/tasks/configure-pod-container/share-process-namespace/)를 |
| 134 | +활성화하지 않기 때문이다. |
| 135 | + |
| 136 | +{{< note >}} |
| 137 | +`--target` 파라미터는 사용 중인 {{< glossary_tooltip text="컨테이너 런타임" term_id="container-runtime" >}}에서 |
| 138 | +지원해야지만 사용할 수 있다. 만일 지원되지 않는다면, |
| 139 | +임시 컨테이너가 시작되지 않을 수 있거나 독립적인 프로세스 |
| 140 | +네임스페이스를 가지고 시작될 수 있다. |
| 141 | +{{< /note >}} |
| 142 | + |
| 143 | +`kubectl describe` 명령을 사용하면 새롭게 생성된 임시 컨테이너의 상태를 확인할 수 있다. |
| 144 | + |
| 145 | +```shell |
| 146 | +kubectl describe pod ephemeral-demo |
| 147 | +``` |
| 148 | + |
| 149 | +``` |
| 150 | +... |
| 151 | +Ephemeral Containers: |
| 152 | + debugger-8xzrl: |
| 153 | + Container ID: docker://b888f9adfd15bd5739fefaa39e1df4dd3c617b9902082b1cfdc29c4028ffb2eb |
| 154 | + Image: busybox |
| 155 | + Image ID: docker-pullable://busybox@sha256:1828edd60c5efd34b2bf5dd3282ec0cc04d47b2ff9caa0b6d4f07a21d1c08084 |
| 156 | + Port: <none> |
| 157 | + Host Port: <none> |
| 158 | + State: Running |
| 159 | + Started: Wed, 12 Feb 2020 14:25:42 +0100 |
| 160 | + Ready: False |
| 161 | + Restart Count: 0 |
| 162 | + Environment: <none> |
| 163 | + Mounts: <none> |
| 164 | +... |
| 165 | +``` |
| 166 | + |
| 167 | +디버깅이 다 끝나면 `kubectl delete`을 통해 파드를 제거할 수 있다. |
| 168 | + |
| 169 | +```shell |
| 170 | +kubectl delete pod ephemeral-demo |
| 171 | +``` |
| 172 | + |
| 173 | +## 파드의 복제본을 이용해서 디버깅하기 |
| 174 | + |
| 175 | +때때로 파드의 설정 옵션에 따라 특정 상황에서 트러블슈팅을 하기가 어려울 수 있다. |
| 176 | +예를 들어, 만일 여러분의 컨테이너 이미지가 쉘을 포함하고 있지 않거나, 여러분의 |
| 177 | +애플리케이션이 컨테이너 시작에서 크래시가 발생한다면 `kubectl exec`을 이용해서 |
| 178 | +컨테이너를 트러블슈팅할 수 없을 수 있다. 이러한 상황에서는 `kubectl debug`을 사용해서 |
| 179 | +파드의 복제본을 디버깅을 위한 추가적인 설정 옵션과 함께 생성할 수 있다. |
| 180 | + |
| 181 | +### 새 컨테이너와 함께 파드의 복제본 생성하기 |
| 182 | + |
| 183 | +만일 여러분의 애플리케이션이 동작은 하고 있지만 예상과는 다르게 동작하는 경우, |
| 184 | +파드의 복제본에 새로운 컨테이너를 추가함으로써 추가적인 트러블슈팅 도구들을 |
| 185 | +파드에 함께 추가할 수 있다. |
| 186 | + |
| 187 | +가령, 여러분의 애플리케이션 컨테이너 이미지는 `busybox`를 기반으로 하고 있는데 |
| 188 | +여러분은 `busybox`에는 없는 디버깅 도구를 필요로 한다고 가정해 보자. 이러한 |
| 189 | +시나리오는 `kubectl run` 명령을 통해 시뮬레이션 해볼 수 있다. |
| 190 | + |
| 191 | +```shell |
| 192 | +kubectl run myapp --image=busybox --restart=Never -- sleep 1d |
| 193 | +``` |
| 194 | + |
| 195 | +다음의 명령을 실행시켜 디버깅을 위한 새로운 우분투 컨테이너와 함께 `myapp-debug`이란 |
| 196 | +이름의 `myapp` 컨테이너 복제본을 생성할 수 있다. |
| 197 | + |
| 198 | +```shell |
| 199 | +kubectl debug myapp -it --image=ubuntu --share-processes --copy-to=myapp-debug |
| 200 | +``` |
| 201 | + |
| 202 | +``` |
| 203 | +Defaulting debug container name to debugger-w7xmf. |
| 204 | +If you don't see a command prompt, try pressing enter. |
| 205 | +root@myapp-debug:/# |
| 206 | +``` |
| 207 | + |
| 208 | +{{< note >}} |
| 209 | +* 만일 여러분이 새로 생성되는 컨테이너의 이름을 `--container` 플래그와 함께 지정하지 않는다면, |
| 210 | + `kubectl debug`는 자동으로 새로운 컨테이너 이름을 생성한다. |
| 211 | +* `-i` 플래그를 사용하면 `kubectl debug` 명령이 새로운 컨테이너에 기본적으로 연결되게 된다. |
| 212 | + 이러한 동작은 `--attach=false`을 지정하여 방지할 수 있다. 만일 여러분의 세션이 |
| 213 | + 연결이 끊어진다면 `kubectl attach`를 사용해서 다시 연결할 수 있다. |
| 214 | +* `--share-processes` 옵션은 이 파드에 있는 컨테이너가 해당 파드에 속한 다른 컨테이너의 |
| 215 | + 프로세스를 볼 수 있도록 한다. 이 옵션이 어떻게 동작하는지에 대해 더 알아보기 위해서는 |
| 216 | + 다음의 [파드의 컨테이너 간 프로세스 네임스페이스 공유]( |
| 217 | + /docs/tasks/configure-pod-container/share-process-namespace/)를 참고하라. |
| 218 | +{{< /note >}} |
| 219 | + |
| 220 | +사용이 모두 끝나면, 디버깅에 사용된 파드를 잊지 말고 정리한다. |
| 221 | + |
| 222 | +```shell |
| 223 | +kubectl delete pod myapp myapp-debug |
| 224 | +``` |
| 225 | + |
| 226 | +### 명령어를 변경하며 파드의 복제본 생성하기 |
| 227 | + |
| 228 | +때때로 컨테이너의 명령어를 변경하는 것이 유용한 경우가 있는데, 예를 들면 디버그 플래그를 추가하기 |
| 229 | +위해서나 애플리케이션이 크래시 되는 경우이다. |
| 230 | + |
| 231 | +다음의 `kubectl run` 명령을 통해 즉각적으로 크래시가 발생하는 애플리케이션의 |
| 232 | +사례를 시뮬레이션해 볼 수 있다. |
| 233 | + |
| 234 | +``` |
| 235 | +kubectl run --image=busybox myapp -- false |
| 236 | +``` |
| 237 | + |
| 238 | +`kubectl describe pod myapp` 명령을 통해 이 컨테이너에 크래시가 발생하고 있음을 확인할 수 있다. |
| 239 | + |
| 240 | +``` |
| 241 | +Containers: |
| 242 | + myapp: |
| 243 | + Image: busybox |
| 244 | + ... |
| 245 | + Args: |
| 246 | + false |
| 247 | + State: Waiting |
| 248 | + Reason: CrashLoopBackOff |
| 249 | + Last State: Terminated |
| 250 | + Reason: Error |
| 251 | + Exit Code: 1 |
| 252 | +``` |
| 253 | + |
| 254 | +이러한 경우에 `kubectl debug`을 통해 명령어를 지정함으로써 해당 파드의 |
| 255 | +복제본을 인터랙티브 쉘로 생성할 수 있다. |
| 256 | + |
| 257 | +``` |
| 258 | +kubectl debug myapp -it --copy-to=myapp-debug --container=myapp -- sh |
| 259 | +``` |
| 260 | + |
| 261 | +``` |
| 262 | +If you don't see a command prompt, try pressing enter. |
| 263 | +/ # |
| 264 | +``` |
| 265 | + |
| 266 | +이제 인터랙티브 쉘에 접근할 수 있으니 파일 시스템 경로를 확인하거나 |
| 267 | +동작 중인 컨테이너의 명령어를 직접 확인하는 등의 작업이 가능하다. |
| 268 | + |
| 269 | +{{< note >}} |
| 270 | +* 특정 컨테이너의 명령어를 변경하기 위해서는 `--container` 옵션을 통해 해당 컨테이너의 |
| 271 | + 이름을 지정해야만 한다. 이름을 지정하지 않는다면 `kubectl debug`은 이전에 지정한 명령어를 |
| 272 | + 그대로 사용해서 컨테이너를 생성할 것이다. |
| 273 | +* 기본적으로 `-i` 플래그는 `kubectl debug` 명령이 컨테이너에 바로 연결되도록 한다. |
| 274 | + 이러한 동작을 방지하기 위해서는 `--attach=false` 옵션을 지정할 수 있다. 만약 여러분이 세션이 |
| 275 | + 종료된다면 `kubectl attach` 명령을 통해 다시 연결할 수 있다. |
| 276 | +{{< /note >}} |
| 277 | + |
| 278 | +사용이 모두 끝나면, 디버깅에 사용된 파드들을 잊지 말고 정리한다. |
| 279 | + |
| 280 | +```shell |
| 281 | +kubectl delete pod myapp myapp-debug |
| 282 | +``` |
| 283 | + |
| 284 | +### 컨테이너 이미지를 변경하며 파드의 복제본 생성하기 |
| 285 | + |
| 286 | +특정한 경우에 여러분은 제대로 동작하지 않는 파드의 이미지를 |
| 287 | +기존 프로덕션 컨테이너 이미지에서 디버깅 빌드나 추가적인 도구를 포함한 |
| 288 | +이미지로 변경하고 싶을 수 있다. |
| 289 | + |
| 290 | +이 사례를 보여주기 위해 `kubectl run` 명령을 통해 파드를 생성하였다. |
| 291 | + |
| 292 | +``` |
| 293 | +kubectl run myapp --image=busybox --restart=Never -- sleep 1d |
| 294 | +``` |
| 295 | + |
| 296 | +여기서는 `kubectl debug` 명령을 통해 해당 컨테이너 이미지를 `ubuntu`로 변경하며 |
| 297 | +복제본을 생성하였다. |
| 298 | + |
| 299 | +``` |
| 300 | +kubectl debug myapp --copy-to=myapp-debug --set-image=*=ubuntu |
| 301 | +``` |
| 302 | + |
| 303 | +`--set-image`의 문법은 `kubectl set image`와 동일하게 `container_name=image` |
| 304 | +형식의 문법을 사용한다. `*=ubuntu`라는 의미는 모든 컨테이너의 이미지를 `ubuntu`로 |
| 305 | +변경하겠다는 의미이다. |
| 306 | + |
| 307 | +사용이 모두 끝나면, 디버깅에 사용된 파드를 잊지 말고 정리한다. |
| 308 | + |
| 309 | +```shell |
| 310 | +kubectl delete pod myapp myapp-debug |
| 311 | +``` |
| 312 | + |
| 313 | +## 노드의 쉘을 사용해서 디버깅하기 {#node-shell-session} |
| 314 | + |
| 315 | +만약 위의 어떠한 방법도 사용할 수 없다면, 파드가 현재 동작 중인 노드를 찾아 |
| 316 | +호스트의 네임스페이스로 동작하는 특권 파드를 생성할 수 있다. |
| 317 | +다음 `kubectl debug` 명령을 통해 해당 노드에서 인터랙티브한 쉘을 생성할 수 있다. |
| 318 | + |
| 319 | +```shell |
| 320 | +kubectl debug node/mynode -it --image=ubuntu |
| 321 | +``` |
| 322 | + |
| 323 | +``` |
| 324 | +Creating debugging pod node-debugger-mynode-pdx84 with container debugger on node mynode. |
| 325 | +If you don't see a command prompt, try pressing enter. |
| 326 | +root@ek8s:/# |
| 327 | +``` |
| 328 | + |
| 329 | +노드에서 디버깅 세션을 생성할 때 유의해야 할 점은 다음과 같다. |
| 330 | + |
| 331 | +* `kubectl debug`는 노드의 이름에 기반해 새로운 파드의 이름을 |
| 332 | + 자동으로 생성한다. |
| 333 | +* 컨테이너는 호스트 네임스페이스(IPC, 네트워크, PID 네임스페이스)에서 동작한다. |
| 334 | +* 노드의 루트 파일시스템은 `/host`에 마운트된다. |
| 335 | + |
| 336 | +사용이 모두 끝나면, 디버깅에 사용된 파드를 잊지 말고 정리한다. |
| 337 | + |
| 338 | +```shell |
| 339 | +kubectl delete pod node-debugger-mynode-pdx84 |
| 340 | +``` |
0 commit comments