링크세상 링크모음
링크세상 링크모음 링크 애니 웹툰 링크 드라마 영화 링크 세상의모든링크

Kubernetes: 임시 컨테이너를 사용한 디버깅

Kubernetes를 조작해야 했던 사람이라면 누구나 포드 오류를 해결해야 하는 상황에 직면했을 것입니다. 이 목적을 위해 제공된 방법은 효율적이며 가장 빈번한 오류를 극복할 수 있습니다. 그러나 일부 상황에서는 이러한 방법이 제한적입니다. 그러면 디버깅이 섬세해집니다. Cloud Native Computing Foundation이 발표한 발렌시아의 Kubecon 2022에서 버전 1.23의 베타 버전으로 제공되는 Kubernetes에서 포드를 디버깅하는 새로운 방법에 대한 Aaron Alpar의 프레젠테이션에 참석할 수 있었습니다. kubectl debug.

먼저 Pod를 디버깅하는 일반적인 방법을 살펴보겠습니다. 그런 다음 네임스페이스의 개념을 발전시키겠습니다. 마지막으로 임시 컨테이너가 무엇인지 정의하겠습니다.

포드를 디버깅하는 방법은 무엇입니까?

지금까지는 Pod의 로그를 확인한 후 kubectl log 보다 심층적인 디버깅을 위해 두 가지 솔루션을 사용할 수 있었습니다. exec 그리고 copy.

첫 번째는 다음과 같은 형태입니다.

kubectl exec         \
  -it                \ 
  -n <namespace_pod> \
  <pod>              \
  -c <container>     \ 
  -- /bin/sh           

이 명령은 대상 컨테이너에서 명령 프롬프트를 엽니다. 명령을 실행할 수 있는 사용자 권한의 범위는 프롬프트가 시작된 Kubernetes 역할에 따라 달라집니다. 권한이 높아지면 컨테이너에서 수행 방법을 아는 한 컨테이너에서 거의 모든 작업을 수행할 수 있습니다. 실제로 컨테이너는 경량으로 설계되었습니다. 각 컨테이너에는 해당 애플리케이션과 해당 종속성만 포함됩니다. 효율적인 오류 해결에 필수적인 도구는 존재하지 않기 때문에 사용할 수 없습니다. 다음을 사용하여 디렉토리의 파일 나열 ls특정 파일을 검색하는 방법 find 또는 다음을 사용하여 파일에 대한 액세스 권한을 변경합니다. chmod: 이러한 모든 작업은 일반적으로 컨테이너 런타임 시스템에 기본적으로 제공되므로 가능합니다. 반면에 활성 네트워크 포트에 대한 보다 고급 분석은 다음과 같습니다. netstat또는 연결 테스트 curl 대부분의 경우 실현 가능하지 않습니다.

두 번째 명령의 형식은 다음과 같습니다.

kubectl debug                  \
  -it                          \ 
  -n <namespace_pod>           \
  <pod>                        \
  --copy-to=<pod_name>         \ 
  --container <container_name> \ 
  --image=busybox              \ 
  --share-processes            \ 
  -- /bin/sh                     

이 명령은 새 포드를 생성하고 자체 새 컨테이너에서 애플리케이션을 다시 시작합니다. 그러면 새 컨테이너에 대한 명령 프롬프트가 열립니다. 여기서 선택한 이미지를 선택할 수 있으면 새 컨테이너에 오류 해결을 위한 관련 도구가 제공됩니다. 그러나 이 방법에는 두 가지 주요 단점이 있습니다.

  • 새 포드를 생성하려면 애플리케이션을 다시 시작해야 합니다.
  • 복제가 포함된 Pod인 경우(예: 배포 그리고 상태 저장 세트), 이 방법은 새로운 복제가 비자발적으로 생성될 수 있기 때문에 위험할 수 있습니다.

Linux 네임스페이스

컨테이너란 무엇입니까? 컨테이너에 대한 우리의 생각은 때때로 현실과 완전히 일치하지 않습니다. 컨테이너는 Linux 커널의 주요 기능인 네임스페이스에 따라 격리되는 일종의 샌드박스입니다.

네임스페이스는 공유 리소스에 대한 공통 보기를 갖는 모든 프로세스(예: 컨테이너의 모든 프로세스)를 그룹화합니다. 네임스페이스는 컨테이너와 해당 프로세스의 격리를 제어하고 리소스를 구분합니다. 네임스페이스는 컨테이너 외부에서 시스템의 나머지 부분을 볼 수 없도록 방지합니다. 환경의 각 특성에 대한 네임스페이스가 있습니다.

  • mnt: 마운트 지점을 분리합니다.
  • pid: 프로세스 ID를 분리합니다.
  • net: 네트워크 인터페이스를 격리합니다.
  • ipc: 프로세스 간 통신을 격리합니다.
  • uts: 호스트 이름과 도메인 이름을 분리합니다.
  • user: 사용자 식별과 권한을 분리합니다.
  • cgroup: 프로세스 멤버십을 제어 그룹으로 격리합니다.

그만큼 pid 예를 들어 네임스페이스는 호스트 시스템의 PID에 대한 지식이 없기 때문에 컨테이너가 자체 프로세스 ID를 가질 수 있도록 허용합니다. 마찬가지로, uts 네임스페이스를 사용하면 컨테이너가 호스트 시스템과 관계없이 자체 호스트 이름을 가질 수 있습니다. 컨테이너는 여러 유형의 네임스페이스에 속할 수 있습니다. 예를 들어 자체 마운트 지점과 네트워크 인터페이스를 가질 수 있습니다. 또한 이러한 네임스페이스는 한 컨테이너에서 다른 컨테이너로 복사될 수 있습니다.

네임스페이스는 머신에서 실행되는 모든 프로세스에서 사용됩니다. 그만큼 /proc/ /ns/* 폴더에는 프로세스에 대한 모든 네임스페이스 관련 파일과 해당 프로세스에서 현재 사용되는 네임스페이스가 포함됩니다. 컨테이너가 사용하는 네임스페이스는 머신의 네임스페이스와 부모-자식 관계를 갖습니다. 부모 네임스페이스는 자식을 인식하지만 그 반대는 사실이 아닙니다. 이는 다음을 통해 확인할 수 있습니다. nsenter 네임스페이스에서 명령을 실행할 수 있는 명령(즉, 상위 네임스페이스의 셸에서 실행):

nsenter
  --target <pid> \ 
  --all          \ 
  /bin/ps -ef      

이 명령은 지정된 프로세스에서 사용하는 네임스페이스에 속하는 모든 프로세스를 표시합니다. 컨테이너(즉, 하위 네임스페이스를 사용하는 프로세스)의 PID를 지정하면 호스트 시스템의 관점에서 이 컨테이너에서 실행 중인 프로세스 목록을 얻을 수 있습니다. 다음은 호스트 노드에서 실행되는 PostgreSQL 컨테이너가 있는 포드에 대한 이 명령의 예입니다.

nsenter --target $(pgrep -o postgres) --all /bin/ps -ef


nsenter 출력

그런 다음 동일한 작업을 수행하지만 이번에는 kubectl exec이번에는 컨테이너 자체의 관점에서 이 컨테이너에서 실행 중인 프로세스 목록을 얻습니다. 다음은 동일한 PostgreSQL Pod 내부의 예입니다.

kubectl exec -it -n pg pg-postgresql -- ps -ef


kubectl exec 출력

두 목록이 동일하다는 것을 알 수 있습니다. 따라서 호스트 시스템은 하위 네임스페이스를 인식하므로 네임스페이스가 공유된다고 말합니다.

임시 컨테이너

임시 컨테이너는 대상 컨테이너와 동일한 포드에 위치한 새 컨테이너입니다. 동일한 Pod에 있기 때문에 리소스를 공유하므로 즉시 떨어지는 컨테이너를 디버깅하는 등 까다로운 상황에 이상적입니다.

임시 컨테이너를 생성하는 명령은 다음과 같습니다.

kubectl debug          \
  -it                  \ 
  -n <namespace_pod>   \
  <pod>                \
  --image busybox      \ 
  --target <container> \ 
  -- /bin/sh             

일단 생성되면 임시 컨테이너가 사양에 나타납니다. 그러면 두 개의 새로운 항목이 “컨테이너”와 “상태”에 표시됩니다.


kubectl 설명 출력

그러면 다음 명령을 사용하여 활성 임시 컨테이너를 나열할 수 있습니다.

kubectl get pod -n <namespace> <pod> -o json 
  | jq '"ephemeralContainers": [(.spec.ephemeralContainers[].name)], "ephemeralContainersStatuses": [(.status.ephemeralContainersStatuses[].name]'

이런 방식으로 임시 컨테이너를 만들 때 두 개의 네임스페이스가 원래 컨테이너와 다르다는 것을 알 수 있습니다. cgroup 그리고 mnt. 이는 다른 모든 네임스페이스와 관련된 리소스가 원래 컨테이너와 해당 임시 버전에서 공유된다는 의미입니다. 이러한 새로운 컨테이너를 사용하면 처리되는 리소스의 무결성을 exec 명령과 사용자가 사용할 수 있는 도구 copy 명령. 실제로 이 마지막 명령으로 생성된 컨테이너는 원래 컨테이너와 다른 네임스페이스만 갖게 됩니다.

그만큼 mnt 일부 중요한 마운트 지점은 공유하면 안 되기 때문에 네임스페이스를 공유할 수 없습니다. 그러나 임시 컨테이너에 원래 컨테이너와 동일한 일부 마운트 지점이 필요한 경우 수동으로 마운트할 수 있습니다.

결론

Kubernetes에 도입된 이 새로운 기능은 강력하고 완전한 Pod 오류 해결 방법을 표준화하는 동시에 새롭고 까다로운 사례를 해결합니다. 또한 디버깅 도구를 제공하지 않는 가벼운 컨테이너인 소위 “distroless” 컨테이너의 민주화를 촉진하므로 배포 속도가 더 빨라집니다. 그러면 도구는 기본 클라우드 사고 방식에 따라 프로덕션과 완전히 독립됩니다.