블로그
전체 14#카테고리
- 데브옵스 · 인프라
#태그
- 쿠버네티스
- 일프로
- 인프라
2025. 06. 24.
1
미션 #6. ArgoCD Github 업데이트
자동 배포 해보기~ 문어는 항상 승리한다.
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 22.
1
[워밍업 클럽 스터디-DevOps] 4주차 진행 회고
4주차 느낌점무엇이든 꾸준히 하자네트워크와 리눅스를 꾸준히 하자지금보다 많이 그림으로 설명하자 재밌었습니다.감사합니다.
데브옵스 · 인프라
・
쿠버네티스
・
인프라
2025. 06. 17.
1
미션 #5. 컨테이너 이미지 사례 실습
빌드 docker build -t test/hello:1.0.0 . [+] Building 12.3s (8/8) FINISHED docker:desktop-linux => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 97B 0.0s => [internal] load metadata for docker.io/library/node:slim 2.3s => [auth] library/node:pull token for registry-1.docker.io 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load build context 0.0s => => transferring context: 215B 0.0s => [1/2] FROM docker.io/library/node:slim@sha256:b30c143a092c7dced8e17ad67a8783c03234d4844ee 9.6s => => resolve docker.io/library/node:slim@sha256:b30c143a092c7dced8e17ad67a8783c03234d4844ee 0.0s => => sha256:34ef2a75627f6089e01995bfd3b3786509bbdc7cfb4dbc804b642e195340d 28.08MB / 28.08MB 7.7s => => sha256:00b6bc59183634774862a1f5d9fa777966ffdd8b4edd6fe07006671358dfc24 3.31kB / 3.31kB 0.7s => => sha256:7293ae927b976710c33b54ae3957471f36b9e1150408853c3dfbd7baff3f5 50.52MB / 50.52MB 8.7s => => sha256:b30c143a092c7dced8e17ad67a8783c03234d4844ee84c39090c9780491aaf8 5.20kB / 5.20kB 0.0s => => sha256:af442a7998c3f3a985309cfa7b709ea8d3f1911ea19a598f1f1a2e158273c73 1.93kB / 1.93kB 0.0s => => sha256:85878ac12a824d35ede83635c5aa0a6b4c83fe0b8fa5fb125e1fc839a5af01a 6.59kB / 6.59kB 0.0s => => sha256:148b7926ba2143f7dbd1efaab45bd08b5fde13f01510d1319ee7cd0aa781f8d 1.71MB / 1.71MB 1.5s => => sha256:0a5428d7ed1bdde6d0638d39b519fcd3307eb60e70ba9f220d1066b39a71de93 447B / 447B 1.9s => => extracting sha256:34ef2a75627f6089e01995bfd3b3786509bbdc7cfb4dbc804b642e195340dbc9 0.8s => => extracting sha256:00b6bc59183634774862a1f5d9fa777966ffdd8b4edd6fe07006671358dfc249 0.0s => => extracting sha256:7293ae927b976710c33b54ae3957471f36b9e1150408853c3dfbd7baff3f59d1 0.8s => => extracting sha256:148b7926ba2143f7dbd1efaab45bd08b5fde13f01510d1319ee7cd0aa781f8d0 0.0s => => extracting sha256:0a5428d7ed1bdde6d0638d39b519fcd3307eb60e70ba9f220d1066b39a71de93 0.0s => [2/2] COPY hello.js . 0.2s => exporting to image 0.1s => => exporting layers 0.0s => => writing image sha256:7d635123c7017af009e6818217e513383410b544c4f5aad555221a02b1b4e1d7 0.0s => => naming to docker.io/hello:1.0.0 0.0s 이미지 조회docker image list REPOSITORY TAG IMAGE ID CREATED SIZE /hello 1.0.0 7d635123c701 2 minutes ago 249MB jenkins/jenkins lts-jdk17 eb3da18f5f0b 8 months ago 499MB kindest/node 1cf551538f7d 16 months ago 96 이미지 태그 변경docker login -u hamtaro Password: Login Succeeded 이미지 푸쉬docker push /hello:1.0.0 The push refers to repository [docker.io/hello] ab1c299e0236: Pushed a04dc377afe1: Mounted from library/node 1b2a793e9797: Mounted from library/node 0fa9dab4f369: Mounted from library/node abb3903f11f9: Mounted from library/node 6edfb9bfff29: Mounted from library/node 1.0.0: digest: sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a size: 1574 이미지 삭제docker rmi -f 7d635123701 Untagged: /hello:1.0.0 Untagged: /hello:2.0.0 Untagged: /hello@sha256:603e375fb7f34d7f376f13c8193864b914742d186371f6c6cfa99132bd9a Deleted: sha256:7d635123c7017af009e6818217e5133844c4f5aad555221a02b1b4e1d7 이미지 다운로드docker pull /hello:1.0.0 1.0.0: Pulling from /hello 34ef2a75627f: Already exists 00b6bc591836: Already exists 7293ae927b97: Already exists 148b7926ba21: Already exists 0a5428d7ed1b: Already exists d03369722173: Already exists Digest: sha256:603e375fb7f34d7f376f13c81186371f60842c6cfa99132bd9a Status: Downloaded newer image for /hello:1.0.0 docker.io/hello:1.0.0 이미지 파일 변환docker save -o file.tar 7d635123c701 ls Dockerfile file.tar hello.js docker load -i file.tar Loaded image ID: 7d635123c7017af009e6818217e513383410b544c4f5aad555221a02b1b4e1d7 containerd[root@k8s-master ~]# ctr ns list NAME LABELS k8s.io [root@k8s-master ~]# ctr -n k8s.io image list REF TYPE DIGEST SIZE PLATFORMS LABELS docker.io/1pro/api-tester:v1.0.0 application/vnd.oci.image.index.v1+json sha256:6b38dd347b66c7f14c393280a040831a72b4a93fd5beddc011ee852c26f35058 247.8 MiB linux/amd64,linux/arm64,unknown/unknown io.cri-containerd.image=managed docker.io/1pro/api-tester:v2.0.0 ... [root@k8s-master ~]# ctr images pull docker.io/sd0241/hello:1.0.0 docker.io/sd0241/hello:1.0.0: resolved |++++++++++++++++++++++++++++++++++++++| manifest-sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:00b6bc59183634774862a1f5d9fa777966ffdd8b4edd6fe07006671358dfc249: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:d0336972217335effba593a6a5da5d1732e7c19c5953843cffb2e71d279196e7: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:148b7926ba2143f7dbd1efaab45bd08b5fde13f01510d1319ee7cd0aa781f8d0: done |++++++++++++++++++++++++++++++++++++++| config-sha256:7d635123c7017af009e6818217e513383410b544c4f5aad555221a02b1b4e1d7: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:0a5428d7ed1bdde6d0638d39b519fcd3307eb60e70ba9f220d1066b39a71de93: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:7293ae927b976710c33b54ae3957471f36b9e1150408853c3dfbd7baff3f59d1: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:34ef2a75627f6089e01995bfd3b3786509bbdc7cfb4dbc804b642e195340dbc9: done |++++++++++++++++++++++++++++++++++++++| elapsed: 12.1s total: 76.6 M (6.3 MiB/s) unpacking linux/arm64/v8 sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a... done: 1.269243327s [root@k8s-master ~]# ctr ns list NAME LABELS default k8s.io [root@k8s-master ~]# ctr images list REF TYPE DIGEST SIZE PLATFORMS LABELS docker.io/sd0241/hello:1.0.0 application/vnd.docker.distribution.manifest.v2+json sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a 76.6 MiB linux/arm64 - [root@k8s-master ~]# ctr images tag docker.io/sd0241/hello:1.0.0 docker.io/sd0241/hello:2.0.0 docker.io/sd0241/hello:2.0.0 [root@k8s-master ~]# ctr images list REF TYPE DIGEST SIZE PLATFORMS LABELS docker.io/sd0241/hello:1.0.0 application/vnd.docker.distribution.manifest.v2+json sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a 76.6 MiB linux/arm64 - docker.io/sd0241/hello:2.0.0 application/vnd.docker.distribution.manifest.v2+json sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a 76.6 MiB linux/arm64 - [root@k8s-master ~]# ctr images tag docker.io/sd0241/hello:1.0.0 docker.io/sd0241/hello:2.0.0 docker.io/sd0241/hello:2.0.0 [root@k8s-master ~]# ctr images list REF TYPE DIGEST SIZE PLATFORMS LABELS docker.io/sd0241/hello:1.0.0 application/vnd.docker.distribution.manifest.v2+json sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a 76.6 MiB linux/arm64 - docker.io/sd0241/hello:2.0.0 application/vnd.docker.distribution.manifest.v2+json sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a 76.6 MiB linux/arm64 - [root@k8s-master ~]# ctr image push docker.io/sd0241/hello:2.0.0 --user sd0241 Password: manifest-sha256:603e375fb7f34d7f376f13c8193864b914742d186371f60842c6cfa99132bd9a: done |++++++++++++++++++++++++++++++++++++++| config-sha256:7d635123c7017af009e6818217e513383410b544c4f5aad555221a02b1b4e1d7: done |++++++++++++++++++++++++++++++++++++++| elapsed: 3.0 s
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 15.
1
[워밍업 클럽 스터디-DevOps] 3주차 진행 회고
3주차 느낌점DevOps 직무란 무엇인가?DataOps, AIOps, ML, Fin, No, Cloud, DevSec, Net, .. SRE 기타 회고기술에좋은 시각 자료를 만들어서 공유해주셔서 감사합니다.
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 08.
1
[쿠버네티스] Component 동작으로 k8s 이해 #11
들어가며Kubernetes를 사용하다 보면 "내부적으로 어떻게 동작하는 걸까?" 하는 궁금증이 생긴다. 각 컴포넌트들이 어떻게 상호작용하며 우리가 만든 애플리케이션이 실행되는지 알아보자. 이런 내용을 모른다고 해서 Kubernetes를 사용하는 데 문제가 생기는 건 아니지만, 이해하고 있으면 문제 해결과 운영에 큰 도움이 된다. 1. Kubernetes 클러스터 구성과 컴포넌트마스터 노드 (Control Plane) 구성마스터 노드에는 Kubernetes가 돌아가는 데 필요한 핵심 컴포넌트들이 설치된다. 이들을 컨트롤 플레인 컴포넌트라고 부른다.API Server: 모든 Kubernetes 요청의 중앙 처리소etcd: 클러스터의 모든 데이터를 저장하는 분산 키-값 저장소Controller Manager: 각종 컨트롤러들을 실행하여 클러스터 상태 관리Scheduler: 파드를 적절한 워커 노드에 배치하는 역할워커 노드 구성워커 노드는 실제 애플리케이션이 실행되는 공간이다. 마스터 노드와 동일한 기본 컴포넌트가 설치되지만, 추가로 다음 요소들이 있다:kubelet: 노드의 파드 생명주기를 관리하는 에이전트kube-proxy: 네트워크 규칙을 관리하는 네트워크 프록시Container Runtime: 실제 컨테이너를 실행하는 런타임 (containerd 등)중요한 점: 운영 환경에서는 마스터 노드에 애플리케이션을 올리면 안 된다. CPU 사용량이 올라가서 마스터 노드가 죽으면 전체 클러스터가 멈추기 때문이다. 애플리케이션은 반드시 워커 노드에 배치해야 한다.Add-on Pod들Kubernetes의 기본 기능을 확장시키기 위한 애플리케이션들이다:Dashboard: 웹 UI를 통한 클러스터 관리Metrics Server: 리소스 사용량 수집 및 제공CNI Plugin: 네트워크 구성 (Calico 등)기타 모니터링 도구들 앞으로 더 많은 Add-on Pod들을 설치하게 될 텐데, 그만큼 Kubernetes가 복잡해지지만 제대로 사용하기 위해서는 필요한 구성 요소들이다. 2. 오브젝트 vs 컨트롤러 vs 리소스Kubernetes를 이해하려면 이 세 개념의 차이를 명확히 알아야 한다.오브젝트 (Object)정의: 인프라의 개별 요소를 나타내는 개념특성: 각각이 독립적인 기능을 수행예시: Pod, Service, ConfigMap, Secret, PersistentVolume 등컨트롤러 (Controller)정의: 오브젝트들을 제어하고 관리하는 상위 개념특성: 다른 오브젝트들의 상태를 모니터링하고 원하는 상태로 유지예시: Deployment, ReplicaSet, DaemonSet, StatefulSet 등리소스 (Resource)정의: 오브젝트와 컨트롤러를 통틀어서 부르는 용어분류:네임스페이스 레벨 리소스: 특정 네임스페이스에 속함클러스터 레벨 리소스: 전체 클러스터에 영향을 미침인프라 요소의 Kubernetes 추상화인프라에는 네트워크, 볼륨, 환경 변수 등의 요소들이 있다. Kubernetes는 이런 요소들을 오브젝트로 정의하고, 이 오브젝트들을 자동화시킬 목적으로 컨트롤러라는 개념을 만들었다.이 전체 리소스들은 컨트롤 플레인 컴포넌트라는 파드들에 의해서 동작한다. 각자의 역할이 있고 리소스들을 동작시키기 위해서 컨트롤러들과 통신하지만, 실제 컨테이너는 Kubernetes가 직접 만드는 게 아니다. Kubernetes는 컨테이너 생성 요청만 하고, 노드 위에 설치된 특정 기술들(Container Runtime)이 실제 작업을 수행한다. 3. 파드 생성 과정 상세 분석파드가 생성되는 과정을 단계별로 자세히 살펴보자.1단계: API 요청 및 데이터 저장kubectl create deployment → API Server → etcd 저장요청 접수: kubectl 명령어나 Dashboard를 통해 Deployment 생성 요청API 처리: API Server가 요청을 받아서 검증 및 처리데이터 저장: etcd에 Deployment 데이터 저장조회 가능: 이 시점에서 Deployment가 조회되고 Dashboard에 나타남중요: 아직 실제 컨테이너는 생성되지 않음. 단순히 데이터만 저장된 상태2단계: Controller Manager의 ReplicaSet 생성Controller Manager → ReplicaSet 생성 API → etcd 저장모니터링: Controller Manager가 지속적으로 etcd 데이터베이스를 모니터링Deployment 발견: 새로운 Deployment가 생성된 것을 감지ReplicaSet 생성: Deployment 스펙에 따라 ReplicaSet 생성 요청연결 관계: Deployment와 ReplicaSet 간의 관계 설정3단계: ReplicaSet Controller의 Pod 생성ReplicaSet Controller → Pod 생성 API → etcd 저장ReplicaSet 모니터링: ReplicaSet Controller가 새로운 ReplicaSet 발견Pod 생성 요청: ReplicaSet의 replicas 수만큼 Pod 생성 API 호출Pod 데이터 저장: etcd에 Pod 데이터 저장여전히 데이터만 존재: 실제 컨테이너는 아직 생성되지 않음4단계: Scheduler의 노드 선택Scheduler → 노드 리소스 분석 → Pod에 노드 정보 업데이트Pod 감지: Scheduler가 노드가 할당되지 않은 Pod 발견노드 분석: 각 워커 노드의 자원 상태 (CPU, 메모리, 디스크) 분석스케줄링 결정: Pod의 요구사항과 노드 affinity 등을 고려하여 최적 노드 선택노드 할당: Pod에 선택된 노드 정보 업데이트5단계: kubelet의 실제 컨테이너 생성kubelet → Container Runtime → 실제 컨테이너 실행Pod 발견: 각 노드의 kubelet이 자신에게 할당된 Pod 발견컨테이너 런타임 호출: containerd 등의 Container Runtime에 컨테이너 생성 요청컨테이너 실행: 실제 컨테이너가 생성되고 실행됨상태 업데이트: Pod 상태를 API Server를 통해 업데이트6단계: Health Check 설정kubelet → Health Check API → 주기적 상태 확인Probe 설정을 했다면:Probe 설정 확인: kubelet이 Pod의 Probe 설정 확인Health Check 실행: 설정에 맞게 컨테이너로 Health Check API 주기적 호출상태 반영: Health Check 결과에 따라 Pod 상태 업데이트 4. 서비스(Service) 네트워킹 동작 원리NodePort 서비스 생성 과정Service 생성 → kubelet 감지 → kube-proxy 호출 → iptables 규칙 추가Service 생성: NodePort 타입의 Service 리소스 생성kubelet 감지: Service와 Pod의 연결 관계 파악kube-proxy 요청: kubelet이 kube-proxy에게 네트워크 설정 요청iptables 업데이트: kube-proxy가 iptables에 라우팅 규칙 추가실제 트래픽 흐름외부 요청(31231 포트) → iptables 규칙 → Service → Pod → Container외부 요청: 클라이언트가 NodePort(예: 31231)로 요청iptables 처리: iptables가 해당 포트를 Service로 라우팅Service 라우팅: Service가 연결된 Pod 중 하나를 선택CNI 네트워킹: Calico 등의 CNI가 Pod 간 네트워크 통신 처리최종 전달: 대상 컨테이너로 트래픽 전달iptables의 역할: 리눅스로 들어오는 모든 패킷을 관리하는 도구. kube-proxy가 iptables에 규칙을 추가하여 서비스 이름을 주석으로 포함한 맵핑 규칙을 생성한다. 5. Secret의 보안 메커니즘과 동작 방식Secret의 메모리 기반 저장Secret은 일반적인 파일 시스템이 아닌 노드의 메모리 영역에 마운트된다.보안상 장점:휘발성: 전원이 꺼지면 데이터가 완전히 삭제됨물리적 보안: 디스크를 물리적으로 탈취당해도 Secret 데이터는 복구 불가능디스크 변경시 안전: 물리적으로 디스크를 교체해야 할 때도 Secret 데이터 유출 위험 없음실무에서 고려사항메모리 사용량 문제:Secret을 많이 만들수록 노드의 메모리 사용량 증가실제로는 그렇게 많은 Secret을 만들 일은 없지만 알아두어야 할 제약사항업데이트 딜레이:Secret 내용을 수정해도 즉시 반영되지 않음kubelet이 주기적으로 체크하여 변경사항을 반영하므로 약간의 딜레이 존재Secret vs 일반 데이터Secret이 제공하는 보안 기능은 있지만 극도로 제한적이다. 완벽한 보안을 원한다면 별도의 보안 솔루션을 사용해야 한다. Secret은 기본적인 보안 수준을 제공하는 정도로 이해하는 것이 좋다. 6. HPA(Horizontal Pod Autoscaler) 상세 동작메트릭 수집 체계의 복잡성HPA가 동작하기 위해서는 여러 컴포넌트가 순차적으로 작동해야 한다.Container Runtime → kubelet(10초) → Metrics Server(60초) → Controller Manager(15초)1단계: Container Runtime의 리소스 모니터링기본 역할: containerd 등이 실제 컨테이너의 CPU, 메모리 사용량 파악데이터 제공: kubelet이 접근할 수 있는 형태로 리소스 정보 제공2단계: kubelet의 주기적 수집수집 주기: 10초마다 Container Runtime에서 리소스 사용량 수집로컬 저장: 수집한 데이터를 노드 내에서 임시 저장3단계: Metrics Server의 중앙 집중화수집 주기: 60초마다 각 노드의 kubelet에서 메트릭 수집중앙 저장: 클러스터 전체의 리소스 사용량 데이터를 중앙에서 관리API 제공: Controller Manager가 조회할 수 있는 API 제공중요: Metrics Server가 설치되지 않으면 HPA가 전혀 동작하지 않는다!4단계: Controller Manager의 스케일링 결정비교 주기: 15초마다 HPA 설정값과 현재 메트릭 비교임계값 체크: CPU/메모리 사용률이 설정된 임계값을 초과하는지 확인스케일링 실행: 필요시 Deployment의 replicas 수 조정HPA 동작 타이밍 분석최적의 경우: 모든 수집 주기가 완벽하게 맞아떨어지면 즉시 스케일링 동작최악의 경우: 다음과 같은 시나리오에서 최대 85초 소요부하 발생: 애플리케이션에 갑작스런 부하 발생kubelet 수집 대기: 최대 10초 대기 (다음 수집 주기까지)Metrics Server 수집 대기: 최대 60초 대기 (다음 수집 주기까지)Controller Manager 판단 대기: 최대 15초 대기 (다음 체크 주기까지)총 최대 대기시간: 10 + 60 + 15 = 85초이런 타이밍 특성을 이해하고 있어야 HPA의 한계를 알고 적절한 임계값을 설정할 수 있다. 7. Kubernetes 아키텍처의 기술 스택다층 구조의 이해Kubernetes는 여러 기술 스택이 조합된 복잡한 시스템이다:Application Layer (Pod, Service, etc.) ↓ Kubernetes Layer (API Server, Controller, etc.) ↓ Container Runtime Layer (containerd, etc.) ↓ Linux Kernel Layer (cgroup, namespace, etc.) ↓ Hardware Layer (CPU, Memory, Network, etc.) 학습 깊이에 대한 고민다양한 학습 접근법:실용주의자: Pod 생성 방법과 기본 사용법만 익히고 싶은 사람구조 탐구자: Kubernetes가 Pod를 만들기 위해 어떤 동작을 하는지 알고 싶은 사람저수준 분석가: Kubernetes가 리눅스의 어떤 기술을 이용해서 컨테이너를 실체화시키는지 공부하고 싶은 사람 실용적 학습 권장사항깊이 있는 학습의 함정:확률적으로 깊은 지식을 써먹을 기회가 많지 않음오버레이 네트워크 같은 복잡한 개념을 깊이 공부해도 실제로는 Kubernetes가 알아서 잘 처리해줌깊이 공부한 내용도 시간이 지나면 까먹게 됨권장하는 접근법:전체적인 구성 파악: 각 컴포넌트의 역할과 상호작용 이해실무 중심 학습: 실제 문제 해결에 도움되는 지식 우선점진적 심화: 정말 필요할 때만 깊이 있게 공부핵심 원칙:큰 틀의 동작 원리만 알아도 충분함ETCD가 데이터를 저장하는 데이터베이스 역할을 한다는 것만 알면 됨 (내부 구조까지 알 필요 없음)확률적으로 공부한 내용을 써먹을 기회의 가성비를 고려해야 함 8. 실전 트러블슈팅 가이드기본 점검 명령어전체 리소스 확인:kubectl api-resources모든 Kubernetes 리소스 목록 조회리소스 이름, 약어, 버전 정보 확인네임스페이스 레벨 vs 클러스터 레벨 구분 (NAMESPACED 컬럼)컴포넌트 로그 확인:# kube-system 네임스페이스의 모든 파드 조회 kubectl get pods -n kube-system # 특정 컴포넌트 로그 확인 kubectl logs -n kube-system 시스템 레벨 진단kubelet 상태 확인:# kubelet 상태 확인 systemctl status kubelet # kubelet 재시작 (문제 발생시) systemctl restart kubelet systemctl start kubelet # 상세 로그 확인 journalctl -u kubelet --no-pagerContainer Runtime 확인:# containerd 상태 확인 systemctl status containerd # 노드 상태 전반적 확인 kubectl get nodes kubectl describe node 애플리케이션 레벨 진단Pod 상태 확인:# 전체 Pod 상태 확인 kubectl get pods --all-namespaces # 특정 네임스페이스의 Pod 확인 kubectl get pods -n # Pod 상세 정보 확인 kubectl describe pod 이벤트 로그 분석:# 전체 이벤트 조회 (너무 많이 나올 수 있음) kubectl get events # 특정 네임스페이스의 Warning 이벤트만 조회 kubectl get events -n --field-selector type=Warning # 특정 시간 이후 이벤트만 조회 kubectl get events --sort-by='.lastTimestamp'애플리케이션 로그 확인:# 기본 로그 확인 kubectl logs # 마지막 10줄만 확인 kubectl logs --tail=10 # 실시간 로그 스트리밍 kubectl logs --follow # 최근 1분간의 로그만 확인 kubectl logs --since=1m # 컨테이너가 여러 개인 경우 특정 컨테이너 지정 kubectl logs -c 네트워크 관련 진단서비스와 iptables 확인:# iptables 규칙 확인 (NodePort 맵핑 확인) iptables -t nat -L | grep # 서비스 정보 확인 kubectl get services kubectl describe service # 엔드포인트 확인 (Service와 Pod 연결 상태) kubectl get endpoints 문제 해결 프로세스1단계: 기본 상태 점검# 전체적인 클러스터 상태 파악 kubectl cluster-info kubectl get nodes kubectl get pods --all-namespaces | grep -v Running2단계: kubelet 및 시스템 컴포넌트 확인kubelet이 정상 동작하는지 확인Container Runtime 상태 점검시스템 리소스 (CPU, 메모리, 디스크) 확인3단계: 애플리케이션 레벨 분석Pod 상태 및 이벤트 로그 확인애플리케이션 로그 분석리소스 요구사항과 실제 할당량 비교4단계: 네트워크 및 보안 설정 확인Service 설정 및 iptables 규칙 점검NetworkPolicy 적용 여부 확인DNS 설정 문제 여부 점검 트러블슈팅 철학과 접근법구글링의 중요성:"구글에는 모든 답이 있다. 단지 내가 찾는 걸 포기했을 뿐이다"실무에서도 트러블슈팅의 대부분은 구글링으로 해결10분 정도 검색해도 답이 없다면 시스템 재시작 고려시스템 재설치 고려:한두 번 이상한 현상이 발생하면 차라리 재설치가 효율적시스템은 거짓말을 하지 않음 - 분명히 뭔가 설정을 건드린 것스크립트가 있다면 재설치 부담이 적음설정 관리의 중요성:추가 작업 내용들을 스크립트에 포함시키거나 문서화 필수정리하지 않은 설정들은 나중에 써먹을 수 없음체계적인 설정 관리가 장기적으로 시간 절약끈기의 중요성:특별한 재능보다는 포기하지 않고 끝까지 하는 자세가 더 중요대부분의 문제는 해결 방법이 존재함에러 로그를 정확히 복사해서 검색하는 것이 핵심 9. Kubernetes 설정 파일과 로그 위치중요 설정 파일 위치Kubernetes 설정 디렉토리:/etc/kubernetes/: 주요 설정 파일들이 위치admin.conf: kubectl이 API Server에 접속할 때 사용하는 인증서 정보manifests/: 컨트롤 플레인 컴포넌트들의 YAML 파일들컨테이너 런타임 설정:Container Runtime 관련 설정 파일들kubelet 설정 파일 로그 파일 위치와 관리파드 로그 저장 위치:/var/log/pods/: 마스터 노드 위에 올라가는 모든 파드들의 로그 저장로그 관리 방식:컨테이너별로 개별 로그 파일 생성두 위치에 중복 저장하는 것이 아니라 링크로 연결된 구조kubectl logs 명령어로 조회하는 것이 일반적이지만, 특정 시간대나 문자열 검색이 필요할 때는 직접 파일에 접근실제 사용 시나리오:로키(Loki) 같은 로그 수집 시스템을 설치한 경우로키의 Promtail이 이 파일들을 읽어서 중앙 로그 저장소로 전송따라서 직접 로그 파일에 접근할 일은 많지 않음 10. 학습 효율성과 실무 적용실습 환경 구축의 가치현재 시점에서의 역량:지금까지 학습한 내용으로 실습 환경 재구축 시간: 약 1시간실무에서 Kubernetes를 처음 접하는 사람이 동일한 환경 구축 시간: 1달 이상 (앱 개발 포함)획득한 능력:1시간 만에 스케일링 테스트 환경 구축 가능프로브 테스트 환경 구축 가능다양한 Kubernetes 기능 실험 환경 준비 가능 DevOps/인프라 분야의 장점표준화의 이점:Kubernetes가 컨테이너 오케스트레이션의 사실상 표준어떤 프로젝트를 가더라도 비슷한 일을 하게 될 확률이 높음한 번 익힌 지식을 지속적으로 활용 가능지속적인 성장 가능성:체계적으로 학습하고 정리한 지식은 오래 활용 가능다른 사람보다 앞선 시작점에서 새 프로젝트 시작 가능실력과 연봉을 꾸준히 높일 수 있는 분야 효과적인 학습 전략공부한 자료의 체계적 정리:시간이 오래 지나도 빠르게 적응할 수 있는 기반 마련설정 스크립트화 및 문서화 필수반복 학습보다는 체계적인 정리가 중요점진적 학습 접근법:한 번에 모든 것을 완벽하게 이해하려 하지 말 것필요에 따라 단계적으로 심화 학습실무에서 당장 필요한 것부터 우선순위를 두고 학습실습 중심의 학습:이론보다는 직접 해보면서 체득문제 상황을 만들어서 해결해보는 경험 축적반복적인 실습을 통해 자연스럽게 명령어와 개념 습득 11. 실제 문제 해결 시나리오ConfigMap 삭제로 인한 Pod 장애 시뮬레이션실제 문제 상황을 만들어서 트러블슈팅 과정을 살펴보자.문제 상황 생성:# ConfigMap 삭제 kubectl delete configmap # Pod 재시작 (문제 상황 유발) kubectl delete pod 증상 확인:# Pod 상태 확인 - CrashLoopBackOff 또는 ContainerCreating 상태 kubectl get pods # 3개의 Pod가 모두 에러 상태로 나타남원인 분석 과정:이벤트 로그 우선 확인:# 전체 이벤트 조회 (너무 많이 나올 수 있음) kubectl get events # 특정 네임스페이스와 타입으로 필터링 kubectl get events -n --field-selector type=Warning결과 분석:Warning FailedMount 5s kubelet MountVolume.SetUp failed for volume "config-volume" : configmap "app-config" not found문제 해결:# ConfigMap 재생성 kubectl create configmap app-config --from-file=config.properties # Pod 자동 복구 확인 kubectl get pods Pod 로그 분석 시나리오애플리케이션 내부 에러 진단:이벤트 로그에 특별한 문제가 없다면 애플리케이션 자체 문제일 가능성이 높다.# 기본 로그 확인 kubectl logs # 실시간 로그 모니터링 kubectl logs --follow # 최근 1분간 로그만 확인 kubectl logs --since=1m # 마지막 10줄만 간단히 확인 kubectl logs --tail=10다중 컨테이너 Pod의 경우:# 특정 컨테이너 로그 확인 kubectl logs -c # 모든 컨테이너 로그 확인 kubectl logs --all-containers=true 네트워크 연결 문제 진단Service 연결 문제 해결:# Service 상태 확인 kubectl get services kubectl describe service # Endpoints 확인 (Service와 Pod 연결 상태) kubectl get endpoints # iptables 규칙 확인 sudo iptables -t nat -L | grep 일반적인 네트워크 문제들:Service Selector가 Pod Label과 일치하지 않음Pod가 Ready 상태가 아님NetworkPolicy에 의한 트래픽 차단DNS 해석 문제 12. Kubernetes 리소스 관리 심화전체 리소스 확인과 관리kubectl api-resources 명령어 활용:# 전체 리소스 목록 확인 kubectl api-resources # 특정 API 버전의 리소스만 확인 kubectl api-resources --api-group=apps # 네임스페이스 레벨 리소스만 확인 kubectl api-resources --namespaced=true # 클러스터 레벨 리소스만 확인 kubectl api-resources --namespaced=false출력 정보 해석:NAME: 리소스의 풀네임SHORTNAMES: kubectl에서 사용할 수 있는 약어APIVERSION: API 버전 정보NAMESPACED: 네임스페이스 레벨 여부 (false면 클러스터 레벨)KIND: YAML 파일에서 사용하는 Kind 값실무 활용팁:자주 사용하는 리소스의 약어를 외워두면 타이핑 시간 절약새로운 리소스를 접할 때 NAMESPACED 여부 확인 필수API 버전 정보는 YAML 파일 작성 시 참고 리소스 간 관계 이해계층적 관계:Deployment (Controller) ↓ 관리 ReplicaSet (Controller) ↓ 관리 Pod (Object) ↓ 사용 ConfigMap, Secret (Object)소유권 관계 확인:# ownerReferences 확인 kubectl get replicaset -o yaml | grep -A 10 ownerReferences # 특정 Deployment의 하위 리소스들 확인 kubectl get all -l app= 13. iptables와 네트워킹 심화iptables 규칙 상세 분석NodePort 매핑 규칙 확인:# NAT 테이블의 모든 규칙 확인 sudo iptables -t nat -L -n --line-numbers # 특정 포트 관련 규칙만 확인 sudo iptables -t nat -L | grep # 자세한 규칙 정보 확인 sudo iptables -t nat -L KUBE-SERVICES -nkube-proxy가 생성하는 규칙들:KUBE-SERVICES: Service 목록과 기본 라우팅KUBE-NODEPORTS: NodePort 서비스 처리KUBE-SEP-xxx: Service Endpoint 개별 처리KUBE-SVC-xxx: Service 로드밸런싱실제 규칙 예시:Chain KUBE-NODEPORTS (1 references) target prot opt source destination KUBE-SVC-xxx tcp -- 0.0.0.0/0 0.0.0.0/0 /* default/my-service:http */ tcp dpt:31231 CNI 네트워킹 이해Calico의 역할:Pod 간 네트워크 통신 제공클러스터 내부 IP 주소 관리네트워크 정책(NetworkPolicy) 구현크로스 노드 통신 터널링네트워크 플로우:Client → NodePort → iptables → kube-proxy → CNI → Pod 14. 메모리와 스토리지 관리Secret과 ConfigMap의 메모리 사용메모리 마운트 확인:# Pod 내부에서 마운트 포인트 확인 kubectl exec -- df -h # Secret이 마운트된 경로 확인 (보통 tmpfs) kubectl exec -- mount | grep tmpfs메모리 사용량 모니터링:# 노드의 메모리 사용량 확인 kubectl top nodes # 특정 Pod의 메모리 사용량 확인 kubectl top pods주의사항:Secret/ConfigMap 데이터가 클수록 메모리 사용량 증가많은 수의 Secret을 생성할 때 노드 메모리 고려 필요메모리 부족 시 Pod 스케줄링 실패 가능 로그 관리와 디스크 사용량로그 파일 크기 관리:# 로그 디렉토리 크기 확인 sudo du -sh /var/log/pods/ # 특정 Pod의 로그 크기 확인 sudo du -sh /var/log/pods/__*/로그 로테이션 설정:kubelet의 로그 로테이션 설정 확인오래된 로그 파일 자동 정리 설정디스크 사용량 모니터링 필수 15. 고급 모니터링과 메트릭스Metrics Server 의존성 이해HPA 동작을 위한 필수 조건:Metrics Server 설치: kubectl apply -f metrics-server.yaml리소스 요청 설정: Pod에 resources.requests 설정 필수충분한 실행 시간: 메트릭 수집을 위한 최소 시간 필요메트릭 수집 체인 검증:# Metrics Server 상태 확인 kubectl get pods -n kube-system | grep metrics-server # 노드 메트릭 확인 kubectl top nodes # Pod 메트릭 확인 kubectl top pods # HPA 상태 확인 kubectl get hpa kubectl describe hpa 리소스 사용량 분석CPU/메모리 사용 패턴 파악:# 실시간 리소스 사용량 모니터링 watch kubectl top pods # 특정 네임스페이스의 리소스 사용량 kubectl top pods -n # 정렬된 리소스 사용량 확인 kubectl top pods --sort-by=cpu kubectl top pods --sort-by=memoryHPA 타이밍 최적화:애플리케이션 시작 시간 고려부하 테스트 시 충분한 대기 시간 설정스케일링 임계값을 실제 사용 패턴에 맞게 조정 16. 실무 운영 시나리오장애 대응 프로세스단계별 장애 대응:1차 진단 (1분 내):kubectl get pods --all-namespaces | grep -v Running kubectl get nodes kubectl cluster-info2차 분석 (5분 내):kubectl describe pod kubectl get events --sort-by='.lastTimestamp' | tail -20 kubectl logs --tail=503차 심화 분석 (10분 내):systemctl status kubelet systemctl status containerd sudo dmesg | tail -20임시 복구 조치:kubectl delete pod # ReplicaSet이 새 Pod 생성 kubectl rollout restart deployment 용량 계획과 리소스 관리클러스터 용량 모니터링:# 전체 클러스터 리소스 사용량 kubectl top nodes # 네임스페이스별 리소스 사용량 kubectl top pods -A --sort-by=memory # 리소스 요청량 vs 실제 사용량 비교 kubectl describe nodes스케일링 전략:수직 스케일링: Pod의 CPU/메모리 제한 증가수평 스케일링: Pod 개수 증가 (HPA)클러스터 스케일링: 노드 개수 증가 보안 및 네트워크 정책기본 보안 체크리스트:# RBAC 설정 확인 kubectl get clusterrolebindings kubectl get rolebindings -A # 네트워크 정책 확인 kubectl get networkpolicies -A # 보안 컨텍스트 확인 kubectl get pods -o yaml | grep -A 10 securityContext 마치며학습 성과 정리이 글을 통해 다음과 같은 내용들을 체계적으로 정리했다:아키텍처 이해: Kubernetes의 전체적인 구성과 각 컴포넌트의 역할동작 원리 파악: 파드 생성부터 서비스 네트워킹까지의 상세 과정실무 트러블슈팅: 실제 문제 상황에서의 체계적인 해결 방법운영 노하우: 효율적인 클러스터 관리와 모니터링 방법 지속적인 성장을 위한 제언실무 적용 시 고려사항:완벽한 이해보다는 문제 해결 능력에 집중체계적인 문서화를 통한 지식 축적실습 환경 유지를 통한 지속적인 실험과 학습앞으로의 학습 방향:CI/CD 파이프라인: Kubernetes와 연계된 배포 자동화모니터링 스택: Prometheus, Grafana 등의 관측 도구보안 강화: Pod Security Standards, Network Policies고가용성: Multi-zone, Multi-region 클러스터 구성마지막 당부: Kubernetes는 빠르게 발전하는 기술이다. 완벽하게 모든 것을 알려고 하기보다는, 핵심 개념을 이해하고 필요할 때 찾아서 활용할 수 있는 능력을 기르는 것이 더 중요하다.구글에는 정말로 모든 답이 있다. 포기하지 말고 끝까지 찾아보자. 그리고 해결한 내용들은 반드시 정리해두자. 그것이 미래의 나와 동료들에게 큰 도움이 될 것이다."시스템은 거짓말을 하지 않는다. 분명히 뭔가를 건드렸을 것이다.""구글에는 모든 답이 있다. 단지 내가 찾는 걸 포기했을 뿐이다."
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 08.
1
[워밍업 클럽 스터디-DevOps] 2주차 진행 회고
2주차 느낌점강사님처럼 부지런하고 꾸준함을 겸비하자코드를 타이핑 하면 더 좋을꺼같다 기술적 회고 기타 회고너무 공부만 하는거같다. 미니 프로젝트 같은걸 기획하여 만들어보자
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 05.
0
미션 #4. PV/PVC, Deployment.. 실습과제
- 1번 API - 파일 생성 http://192.168.56.30:31231/create-file-pod http://192.168.56.30:31231/create-file-pv - 2번 - Container 임시 폴더 확인 [root@k8s-master ~]# kubectl exec -n anotherclass-123 -it api-tester-1231-755676484f-26gmv -- ls /usr/src/myapp/tmp qlifdymaky.txt - 2번 - Container 영구저장 폴더 확인 [root@k8s-master ~]# kubectl exec -n anotherclass-123 -it api-tester-1231-755676484f-26gmv -- ls /usr/src/myapp/files/dev ckxjytizlh.txt - 2번 - master node 폴더 확인 [root@k8s-master ~]# kubectl exec -n anotherclass-123 -it api-tester-1231-755676484f-p9qqt -- ls /usr/src/myapp/files/dev ckxjytizlh.txt [root@k8s-master ~]# kubectl exec -n anotherclass-123 -it api-tester-1231-755676484f-p9qqt -- ls /usr/src/myapp/tmp ls: cannot access '/usr/src/myapp/tmp': No such file or directory command terminated with exit code 2 - 2번 - master node 폴더 확인 [root@k8s-master ~]# ls /root/k8s-local-volume/1231 ckxjytizlh.txt - 3번 - Pod 삭제 [root@k8s-master ~]# kubectl delete -n anotherclass-123 pod api-tester-1231-755676484f-26gmv pod "api-tester-1231-755676484f-26gmv" deleted - 4번 API - 파일 조회 [root@k8s-master ~]# curl http://192.168.56.30:31231/list-file-pod [root@k8s-master ~]# curl http://192.168.56.30:31231/list-file-pv ckxjytizlh.txt hostPath 동작 확인 - Deployment 수정 후 [1~4] 실행 apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: api-tester-1231 volumeMounts: - name: files mountPath: /usr/src/myapp/files/dev - name: secret-datasource mountPath: /usr/src/myapp/datasource volumes: - name: files persistentVolumeClaim: // 삭제 claimName: api-tester-1231-files // 삭제 // 아래 hostPath 추가 hostPath: path: /root/k8s-local-volume/1231 - name: secret-datasource secret: secretName: api-tester-1231-postgresql 2. Deployment - search2-1. update2-2. 동작 확인1. RollingUpdate 하기 // 1) HPA minReplica 2로 바꾸기 (이전 강의에서 minReplicas를 1로 바꿔놨었음) kubectl patch -n anotherclass-123 hpa api-tester-1231-default -p '{"spec":{"minReplicas":2}}' -> horizontalpodautoscaler.autoscaling/api-tester-1231-default patched // 1) 그외 Deployment scale 명령 kubectl scale -n anotherclass-123 deployment api-tester-1231 --replicas=2 -> deployment.apps/api-tester-1231 scaled // 1) edit로 모드로 직접 수정 kubectl edit -n anotherclass-123 deployment api-tester-1231 // 2) 지속적으로 Version호출 하기 (업데이트 동안 리턴값 관찰) while true; do curl http://192.168.56.30:31231/version; sleep 2; echo ''; done; -> [App Version] : Api Tester v1.0.0 -> [App Version] : Api Tester v1.0.0 -> [App Version] : Api Tester v1.0.0 // 3) 별도의 원격 콘솔창을 열어서 업데이트 실행 kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v2.0.0 -> deployment.apps/api-tester-1231 image updated kubectl set image -n anotherclass-123 deployment/api-tester-1231 2. RollingUpdate (maxUnavailable: 0%, maxSurge: 100%) 하기apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: replicas: 2 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% -> 0% # 수정 maxSurge: 25% -> 100% # 수정kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v1.0.03. Recreate 하기apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: replicas: 2 strategy: type: RollingUpdate -> Recreate # 수정 rollingUpdate: # 삭제 maxUnavailable: 0% # 삭제 maxSurge: 100% # 삭제// 이전 버전으로 롤백 kubectl rollout undo -n anotherclass-123 deployment/api-tester-1231 1. 부하 발생http://192.168.56.30:31231/cpu-load?min=3 // 3분 동안 부하 발생 http://192.168.56.30:31231/cpu-load?min=3&thread=5 // 3분 동안 5개의 쓰레드로 80% 부하 발생 // default : min=2, thread=10 부하 확인// 실시간 업데이트는 명령어로 확인하는 게 빨라요 kubectl top -n anotherclass-123 pods kubectl get hpa -n anotherclass-123 -> [root@k8s-master ~]# kubectl get hpa -n anotherclass-123 NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE api-tester-1231-default Deployment/api-tester-1231 86%/60% 2 4 2 3d5h // Grafana는 Prometheus를 거쳐 오기 때문에 좀 늦습니다 Grafana > Home > Dashboards > [Default] Kubernetes / Compute Resources / Pod // 1. hpa 삭제 kubectl delete -n anotherclass-123 hpa api-tester-1231-default // 2. deployment replicas 2로 변경 kubectl scale -n anotherclass-123 deployment api-tester-1231 --replicas=2 // 3. hpa 다시 생성 kubectl apply -f - kubectl edit -n anotherclass-123 hpa api-tester-1231-default --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: namespace: anotherclass-123 name: api-tester-1231-default spec: behavior: # 삭제 scaleUp: # 삭제 stabilizationWindowSeconds: 120 # 삭제 http://192.168.56.30:31231/cpu-load // 2분 동안 10개의 쓰레드로 80% 부하 발생 // default : min=2, thread=10 [root@k8s-master ~]# kubectl get hpa -n anotherclass-123 NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE api-tester-1231-default Deployment/api-tester-1231 138%/60% 2 4 3 3d5h [root@k8s-master ~]# kubectl get hpa -n anotherclass-123 NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE api-tester-1231-default Deployment/api-tester-1231 2%/60% 2 4 3 3d5h
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 05.
1
미션 #3. Configmap, Secret 응용과제
문제 1Configmap의 환경변수들을 Secret을 사용해서 작성하고, App에서는 같은 결과가 나오도록 확인해 보세요. 방법 1: dashborad에서 생성# Secret 리소스 정의 apiVersion: v1 kind: Secret metadata: namespace: anotherclass-123 # Secret이 생성될 네임스페이스 name: api-tester-1231-properties # Secret 이름 labels: # 리소스 식별 레이블 part-of: k8s-anotherclass # 소속 프로젝트 component: backend-server # 구성 요소(백엔드 서버) name: api-tester # 애플리케이션 이름 instance: api-tester-1231 # 인스턴스 식별자 version: 1.0.0 # 버전 정보 managed-by: dashboard # 관리 도구 stringData: # 암호화되지 않은 상태로 값을 입력 (쿠버네티스가 자동으로 base64 인코딩) spring_profiles_active: "dev" # 스프링 프로필 설정 application_role: "ALL" # 애플리케이션 역할 postgresql_filepath: "/usr/src/myapp/datasource/dev/postgresql-info.yaml" # PostgreSQL 설정 파일 경로 방법 2: kubectl 명령어로 생성(YAML 파일)# 인라인 YAML을 사용하여 Secret 생성 kubectl apply -f - 문제 2반대로 Secret의 DB정보를 Configmap으로 만들어보고 App을 동작시켜 보세요. 방법 1: dashborad에서 생성# PostgreSQL 정보를 담은 ConfigMap 생성 apiVersion: v1 kind: ConfigMap metadata: namespace: anotherclass-123 # ConfigMap이 위치할 네임스페이스 name: api-tester-1231-postgresql # ConfigMap 이름 labels: # 리소스 식별 레이블 part-of: k8s-anotherclass # 소속 프로젝트 component: backend-server # 구성 요소 name: api-tester # 애플리케이션 이름 instance: api-tester-1231 # 인스턴스 식별자 version: 1.0.0 # 버전 정보 managed-by: dashboard # 관리 도구 data: # 여러 줄의 YAML 데이터를 ConfigMap에 포함 (파이프 문자 | 사용) postgresql-info.yaml: | driver-class-name: "org.postgresql.Driver" url: "jdbc:postgresql://postgresql:5431" username: "dev" password: "dev123" # 주의: ConfigMap은 암호화되지 않으므로 중요 정보는 Secret 사용 권장 방법 2: Deployment에 ConfigMap 볼륨 마운트하기# kubectl edit 명령어로 Deployment를 직접 수정 kubectl edit -n anotherclass-123 deployments.apps api-tester-1231 # Deployment 리소스 업데이트 apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 # Deployment가 위치한 네임스페이스 name: api-tester-1231 # Deployment 이름 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master # 특정 노드에 배포 containers: - name: api-tester-1231 # 컨테이너 이름 image: 1pro/api-tester:v1.0.0 # 컨테이너 이미지 volumeMounts: # 볼륨 마운트 설정 - name: configmap-datasource # 마운트할 볼륨 이름(아래 volumes 항목과 일치해야 함) mountPath: /usr/src/myapp/datasource/dev # 컨테이너 내부 마운트 경로 volumes: # Pod 레벨 볼륨 정의 - name: configmap-datasource # 볼륨 이름 configMap: # ConfigMap을 볼륨으로 사용 name: api-tester-1231-postgresql # 사용할 ConfigMap 이름 ConfigMap을 볼륨으로 마운트하면 ConfigMap의 각 키가 파일로 생성위 예시에는 /usr/src/myapp/datasource/dev/postgresql-info.yaml 파일 생성
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 05.
0
미션 #2. Probe 응용과제
조건 HPA minReplica 1로 바꾸기kubectl patch -n anotherclass-123 hpa api-tester-1231-default -p '{"spec":{"minReplicas":1}}'단일 Pod 환경 조성 HPA와 Deployment의 관계 이해HPA 우선순위HPA가 활성화 되면 Deployment의 replicas 설정은 무시HPA가 Pod 개수를 직접 관리하기 때문에 minReplicas 설정이 Pod 개수의 기준이 됨https://kubernetes.io/ko/docs/tasks/run-application/horizontal-pod-autoscale/ 문제 1startupProbe가 실패 되도록 설정해서 Pod가 무한 재기동 상태가 되도록 설정해 보세요. 풀이startupProbe: httpGet: path: /startup port: 8080 scheme: HTTP timeoutSeconds: 1 periodSeconds: 5 successThreshold: 1 failureThreshold: 1 # 기존 36에서 1로 변경Pod가 CrashLoopBackOff 상태에 빠져 무한 재기동failureThreshold=1Java 기반 애플리케이션의 경우 JVM 초기화, 클래스 로딩, 의존성 주입 등 복잡한 초기화 과정 필수periodSeconds가 5초로 설정되어 Pod 시작 5초 후 첫 번째 startupProbe 실행대부분의 실제 애플리케이션이 완전히 준비되기에는 부족한 시간애플리케이션이 아직 /startup 엔드포인트에 응답할 수 없는 상태무한 재시작 사이클Pod 종료 → Deployment 컨트롤러가 새로운 Pod 생성 → 동일한 설정으로 인한 재실패 → 무한 반복z백오프 알고리즘 적용Kubernetes가 재시작 간격을 점진적으로 증가시킴처음: 즉시 재시작 → 10초 → 20초 → 40초 → 80초 → 최대 5분까지 대기[root@k8s-master monitoring]# kubectl get pods -n anotherclass-123 NAME READY STATUS RESTARTS AGE api-tester-1231-755676484f-znzlj 1/1 Running 0 94m api-tester-1231-85dd5c8889-2ktz5 0/1 CrashLoopBackOff 2 (7s ago) 22s 문제 2일시적 장애 상황(App 내부 부하 증가)가 시작 된 후, 30초 뒤에 트래픽이 중단되고, 3분 뒤에는 App이 재기동 되도록 설정해 보세요. 풀이livenessProbe: httpGet: path: "/liveness" port: 8080 periodSeconds: 60 # 60초마다 체크 failureThreshold: 3 # 180초 후 Pod 재시작 readinessProbe: httpGet: path: "/readiness" port: 8080 periodSeconds: 10 # 10초마다 체크 failureThreshold: 3 # 30초 후 트래픽 차단 livenessProbe: 60초 * 3 = 180초 후 Pod 재시작readinessProbe: 10초 * 3 = 30초 후 트래픽 차단 부하 시뮬레이션 API// 부하 증가 API - (App 내부 isAppReady와 isAppLive를 False로 바꿈) curl http://192.168.56.30:31231/server-load-on // 외부 API 실패 curl http://192.168.56.30:31231/hello // 부하 감소 API - (App 내부 isAppReady와 isAppLive를 True로 바꿈) curl http://192.168.56.30:31231/server-load-off 로그 결과 정상 동작14:15:17 readinessProbe is Succeed-> isAppReady: true 14:15:17 livenessProbe is Succeed-> isAppLive: true ... ... 14:16:17 readinessProbe is Succeed-> isAppReady: true 14:16:17 livenessProbe is Succeed-> isAppLive: truereadinessProbe: 10초 간격으로 정상 체크livenessProbe: 동시에 정상 체크 부하 발생 시점14:16:20 [SyStem] The system load has occurred정확히 server-load-on API가 호출된 시점이 시점부터 내부 플래그들이 False로 변경 Probe 실패14:16:27 readinessProbe is Failed-> isAppReady: false 14:16:27 livenessProbe is Failed-> isAppLive: false readinessProbe 3회 실패14:16:20 부하 발생 14:16:27 첫 번째 [Kubernetes] readinessProbe is Failed-> [System] isAppReady: false 14:16:37 두 번째 [Kubernetes] readinessProbe is Failed-> [System] isAppReady: false 14:16:47 세 번째 [Kubernetes] readinessProbe is Failed-> [System] isAppReady: false Pod 재시작14:16:47 마지막 실패 로그 14:17:09 Spring Boot 애플리케이션 재시작 시작 14:17:09 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \14:17:09 Spring Boot 시작 14:17:54 Tomcat started on port(s): 8080 14:17:58 startupProbe 실패 14:18:17 startupProbe 성공 14:18:47 readinessProbe 성공 확인curl http://192.168.56.30:31231/hello Welcome to Kubernetes 문제 3Secret 파일(/usr/src/myapp/datasource/postgresql-info.yaml)이 존재하는지 체크하는 readinessProbe를 만들어 보세요. 풀이 readinessProbe: exec: command: ["cat", "/usr/src/myapp/datasource/postgresql-info.yaml"] periodSeconds: 10 failureThreshold: 3 livenessProbe: httpGet: path: "/liveness" port: 8080 periodSeconds: 10 failureThreshold: 3startupProbe: 애플리케이션 HTTP 서비스 시작 확인readinessProbe: 필수 파일 존재 여부로 트래픽 수용 준비 상태 판단livenessProbe: 애플리케이션 내부 로직 헬스 체크 Warning Unhealthy pod/api-tester-1231-564f9446c4-sfczc Readiness probe failed: cat: /usr/src/myapp/datasource/postgresql-info.yaml: No such file or directory
데브옵스 · 인프라
・
쿠버네티스
・
일프로
2025. 06. 01.
1
[쿠버네티스] Object를 그려보며 쿠버네티스 이해 #7
1. 레이블-셀렉터 시스템의 중요성레이블과 셀렉터 시스템은 단순한 메타데이터가 아닌 오브젝트 간 연결의 핵심 메커니즘체계적인 네이밍과 레이블링은 팀 협업과 시스템 유지보수의 필수 요소초기 설계의 중요성과 운영 중 변경의 어려움 고려 필요 2. 기본 환경 구성과 네임스페이스2.1 마스터 노드 디렉토리 구조Kubernetes 실습을 위한 마스터 노드 디렉토리 구조 생성 필요Pod에서 파일 저장 용도로 사용되며 Persistent Volume과 연결되는 중요한 구성 요소/root/k8s-local-volume/1231 로컬 볼륨을 활용한 데이터 저장 시나리오에서 필수적Pod 생성 전에 미리 준비되어야 함실제 운영에서는 네트워크 스토리지나 클라우드 스토리지 사용 권장2.2 네임스페이스의 역할과 네이밍네임스페이스 기본 구조apiVersion: v1 kind: Namespace metadata: name: anotherclass-123 labels: part-of: k8s-anotherclass managed-by: kubectl 클러스터 내에서 고유한 이름 보유 필수수업별 넘버링(123)을 통한 실습 환경 격리각 수업에서 생성된 오브젝트가 다른 수업에 영향 미치지 않도록 구성네임스페이스 네이밍 전략포함될 애플리케이션의 범위를 명확히 표현예시: monitoring (모니터링 관련 앱들), anotherclass-123 (실습 환경)기능별, 환경별, 팀별 구분 기준 적용오브젝트 이름 중복 관리 규칙네임스페이스 내에서 같은 종류 오브젝트 간 이름 중복 불허서로 다른 종류 오브젝트(Deployment와 Service)는 같은 이름 허용각 오브젝트 타입이 독립적인 네임스페이스를 가지기 때문네임스페이스 삭제와 연쇄 효과네임스페이스 삭제 시 해당 네임스페이스에 속한 모든 오브젝트 함께 삭제실습 환경 정리 작업에 유용하지만 운영 환경에서는 신중히 사용한 번의 명령으로 전체 프로젝트 리소스 일괄 삭제 가능참고: Persistent Volume(PV) 같은 클러스터 레벨 오브젝트는 네임스페이스 삭제 시에도 별도 삭제 필요 3. 레이블 시스템의 이해3.1 레이블링의 개념과 현실적 비유옷 라벨과 Kubernetes 레이블의 유사성옷에 붙은 라벨을 통해 제조 정보, 세탁 방법 등을 한눈에 파악 가능Kubernetes에서도 동일한 원리로 오브젝트 관리와 식별에 활용아무리 옷이 많아도 라벨만 잘 붙어있으면 정보 파악 가능레이블링의 실무적 가치초기에는 필요성을 못 느끼지만 오브젝트 수가 증가하면서 관리의 복잡성 증대체계적인 라벨링을 통해 오브젝트가 속한 애플리케이션 정보를 즉시 파악운영 효율성과 장애 대응 속도에 직접적 영향팀 협업과 지식 공유에 필수적인 요소3.2 레이블의 두 가지 역할정보성 라벨링오브젝트에 대한 메타 정보 제공애플리케이션 식별, 버전 관리, 소유자 정보 등사람이 읽고 이해하기 위한 목적기능성 라벨링오브젝트 간 연결과 선택을 위한 식별자셀렉터를 통한 자동 매칭과 연결시스템이 동작하기 위한 필수 요소3.3 Kubernetes 권장 레이블 구조Prometheus를 통한 실제 사례 분석Kubernetes에서 권고하는 레이블링 방법을 실제로 적용한 사례체계적인 레이블 구조를 통한 효과적인 오브젝트 관리 방법 제시app.kubernetes.io/part-of: 애플리케이션 전체 이름labels: app.kubernetes.io/part-of: kube-prometheus전체 서비스를 대표하는 최상위 레이블여러 컴포넌트로 구성된 애플리케이션의 통합 식별자마이크로서비스 아키텍처에서 서비스 그룹핑에 활용app.kubernetes.io/component: 기능별 구성 요소labels: app.kubernetes.io/component: prometheus 애플리케이션 내에서 각각의 분리된 기능을 나타냄Prometheus: 메트릭 수집과 성능 정보 API 제공Exporter: 메트릭 데이터 제공Grafana: 데이터 시각화기능별 명확한 역할 구분을 통한 관리 효율성 증대app.kubernetes.io/name: 실제 애플리케이션 이름labels: app.kubernetes.io/name: prometheus구체적인 애플리케이션의 실제 이름Component와 Name의 차이점 이해 중요하나의 Component 내에 여러 Name이 존재 가능예시: exporter component 내 kube-state-metrics, node-exporter 등app.kubernetes.io/instance: 인스턴스 식별자labels: app.kubernetes.io/instance: prometheus-k8s동일한 애플리케이션을 여러 개 설치할 때 구분하는 식별자환경별(dev, staging, prod) 또는 목적별 구분에 활용클러스터 내 동일 애플리케이션의 복수 배포 시 필수인스턴스별 독립적인 관리와 모니터링 가능app.kubernetes.io/version: 애플리케이션 버전labels: app.kubernetes.io/version: "2.44.0"배포된 애플리케이션의 버전 정보다른 레이블과 달리 애플리케이션 업데이트 시 변경 필요롤백과 버전 관리에 중요한 정보카나리 배포나 A/B 테스트 시 버전 구분에 활용app.kubernetes.io/managed-by: 관리 도구labels: app.kubernetes.io/managed-by: helm오브젝트를 생성하고 관리하는 도구 식별kubectl, helm, kustomize, ArgoCD 등 배포 도구 구분관리 주체 명확화를 통한 책임 소재 확실화자동화 도구와 수동 관리의 구분3.4 실습 환경의 레이블 구조강의에서 사용된 실제 레이블 구조metadata: labels: app.kubernetes.io/part-of: k8s-anotherclass app.kubernetes.io/component: backend-server app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 app.kubernetes.io/version: "1.0.0" app.kubernetes.io/managed-by: kubectl체계적인 레이블 구조를 실제 적용한 사례수업별 인스턴스 넘버링(1231)으로 중복 방지백엔드 서버 기능을 명확히 표시3.5 커스텀 레이블과 프리픽스 활용도메인 기반 프리픽스labels: app.kubernetes.io/name: api-tester company.com/team: platform custom.domain.com/owner: devops-team도메인 프리픽스를 통한 레이블 네임스페이스 구분여러 조직이나 팀에서 동일한 클러스터 사용 시 충돌 방지표준 레이블과 커스텀 레이블의 명확한 구분기타 유용한 레이블들labels: # 환경 정보 environment: production stage: dev # 소유권 정보 owner: team-backend # 애플리케이션 역할 app-role: server # 릴리즈 정보 release: release-1.2.1 4. Deployment와 Pod 관리 체계4.1 Deployment의 역할과 구조Deployment는 Pod 생성과 업그레이드를 담당하는 핵심 오브젝트애플리케이션 생명주기 관리에서 가장 중요한 역할 수행선언적 방식으로 원하는 상태 정의 및 유지기본 구조apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 labels: app.kubernetes.io/part-of: k8s-anotherclass app.kubernetes.io/component: backend-server app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 app.kubernetes.io/version: "1.0.0" spec: replicas: 2 strategy: type: RollingUpdate selector: matchLabels: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 4.2 Deployment-ReplicaSet-Pod 생성 메커니즘실제 동작 과정Deployment 생성: api-tester-1231 이름으로 Deployment 생성ReplicaSet 자동 생성: Kubernetes가 api-tester-1231-xxxx 형태로 ReplicaSet 생성Pod 생성: ReplicaSet이 api-tester-1231-xxxx-yyyy 형태로 Pod 생성이름 생성 규칙Deployment: api-tester-1231 ↓ (임의 문자열 추가) ReplicaSet: api-tester-1231-abc123 ↓ (추가 임의 문자열) Pod: api-tester-1231-abc123-def456Deployment 이름에 임의의 문자열을 추가하여 ReplicaSet 이름 생성ReplicaSet 이름에 다시 임의 문자열을 추가하여 Pod 이름 생성각 레벨에서 고유성 보장역할 분담Deployment: Pod의 업데이트와 롤백 관리 담당ReplicaSet: Pod의 복제본 수 유지와 생성/삭제 담당Pod: 실제 애플리케이션 컨테이너 실행ReplicaSet의 Pod 관리 특성ReplicaSet이 실제로 replicas 수만큼 Pod 생성Pod 하나가 삭제되면 ReplicaSet이 즉시 감지하여 새 Pod 생성항상 지정된 수의 Pod를 유지하는 자가 치유 메커니즘4.3 Pod 템플릿과 레이블 상속template: metadata: labels: app.kubernetes.io/part-of: k8s-anotherclass app.kubernetes.io/component: backend-server app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 app.kubernetes.io/version: "1.0.0" spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: app image: kubetm/appPod 템플릿의 레이블이 실제 생성되는 모든 Pod에 적용nodeSelector를 통한 특정 노드 배치 설정마스터 노드의 실제 레이블(kubernetes.io/hostname: k8s-master)과 매칭 5. 셀렉터를 통한 오브젝트 연결5.1 레이블-셀렉터 매칭 시스템기본 동작 원리레이블은 단순히 정보 제공용이 아닌 오브젝트 간 연결의 핵심 메커니즘셀렉터를 통해 두 오브젝트를 동적으로 연결추가적인 기능이 있는 바로 셀렉터와 매칭되어 두 오브젝트를 연결하는데 사용매칭 규칙# Deployment의 selector selector: matchLabels: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 # Pod의 labels (매칭 대상) metadata: labels: app.kubernetes.io/part-of: k8s-anotherclass app.kubernetes.io/component: backend-server app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 app.kubernetes.io/version: "1.0.0"셀렉터의 모든 조건이 레이블에 존재해야 매칭 성공레이블에 추가 키-값 쌍이 있어도 매칭에 영향 없음 (버전처럼 레이블에 추가로 더 있는 건 괜찮음)셀렉터에만 있고 레이블에 없는 조건이 있으면 매칭 실패인스턴스 기반 고유 매칭인스턴스 이름의 고유성을 활용한 단순 매칭 전략복잡한 다중 조건 대신 인스턴스만으로도 정확한 매칭 가능추가 레이블 조건은 선택사항으로 유연한 운영 가능5.2 주요 오브젝트별 연결 방식Deployment ↔ ReplicaSet ↔ Pod# Deployment selector → ReplicaSet 연결 selector: matchLabels: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 # ReplicaSet selector → Pod 연결 (동일한 selector 사용) Deployment가 ReplicaSet을 통해 Pod 관리레이블-셀렉터 매칭을 통한 계층적 연결 구조Service ↔ Pod# Service apiVersion: v1 kind: Service metadata: name: api-tester-1231 spec: selector: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 ports: - port: 80 targetPort: 8080 Service가 해당 레이블을 가진 모든 Pod에 트래픽 라우팅동적 Pod 생성/삭제에도 자동으로 연결 관계 유지HPA ↔ Deployment# HPA apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: api-tester-1231-default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: api-tester-1231 # 직접 이름 참조 HPA는 scaleTargetRef를 통해 Deployment 직접 참조레이블-셀렉터 방식이 아닌 이름 기반 참조5.3 PVC와 PV 연결# PVC apiVersion: v1 kind: PersistentVolumeClaim metadata: name: api-tester-1231-files spec: selector: matchLabels: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231-files # PV apiVersion: v1 kind: PersistentVolume metadata: name: api-tester-1231-files labels: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231-files스토리지 리소스 할당에서도 동일한 매칭 메커니즘 적용특정 요구사항에 맞는 PV 자동 선택5.4 Kubernetes의 두 가지 연결 방식레이블-셀렉터 방식Deployment, Service, ReplicaSet, PVC 등에서 주로 사용유연하고 동적인 연결 관계 지원조건 기반 다중 오브젝트 선택 가능직접 이름 참조 방식ConfigMap, Secret, PVC 등에서 사용Pod 설정에서 직접 오브젝트 이름 지정volumes: - name: config-volume configMap: name: api-tester-1231-configHPA의 scaleTargetRef: Deployment를 직접 이름으로 참조각 오브젝트 타입별 최적화된 연결 방식 제공 6. 다양한 셀렉터 문법6.1 기본 문법 (Service 등)selector: app: api-tester instance: api-tester-12316.2 matchLabels 문법 (Deployment, ReplicaSet, PVC 등)selector: matchLabels: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-12316.3 노드 어피니티의 복잡한 표현nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8s-master마스터 노드의 실제 레이블과 매칭복잡한 조건식을 통한 정교한 노드 선택6.4 실무에서의 셀렉터 관리 전략모든 문법을 암기할 필요 없음검증된 템플릿 활용하여 필요한 부분만 수정점진적 학습을 통한 복잡한 패턴 습득개인 또는 팀 차원의 템플릿 라이브러리 구축 권장Google Drive나 개인 드라이브에 잘 가지고 있으면 됨 7. 환경변수와 구성 관리7.1 ConfigMap을 통한 환경변수 관리apiVersion: v1 kind: ConfigMap metadata: name: api-tester-1231-properties namespace: anotherclass-123 labels: app.kubernetes.io/part-of: k8s-anotherclass app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 data: database_url: "postgresql://localhost:5432/mydb" log_level: "info"ConfigMap의 다양한 활용환경변수 제공 외에도 다양한 데이터를 Pod에 전달 가능Prometheus 예시에서는 성능 정보 계산 공식을 저장 (prometheus-k8s-rule)애플리케이션 기동 시 초기 데이터로 활용목적에 따른 ConfigMap 네이밍: properties, rules, config 등사용 목적에 따라 네이밍을 추가하면 좋음Pod에서 ConfigMap 참조containers: - name: app envFrom: - configMapRef: name: api-tester-1231-propertiesPod가 ConfigMap 모든 데이터를 환경변수로 수신애플리케이션은 표준적인 환경변수 접근 방법으로 값들 사용7.2 Secret을 통한 민감 정보 관리apiVersion: v1 kind: Secret metadata: name: api-tester-1231-postgresql namespace: anotherclass-123 labels: app.kubernetes.io/part-of: k8s-anotherclass app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 stringData: username: admin password: secretpasswordSecret 데이터는 Pod 내부 특정 경로에 파일로 마운트 가능애플리케이션이 환경변수가 아닌 파일 시스템을 통해 민감 정보 접근ConfigMap과 달리 stringData 필드 사용이 내용들을 가지고 이 파일이 Pod 안에 만들어짐 8. 스토리지 관리와 노드 연결8.1 Persistent Volume의 클러스터 레벨 특성apiVersion: v1 kind: PersistentVolume metadata: name: api-tester-1231-files labels: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231-files spec: capacity: storage: 1Gi volumeMode: Filesystem accessModes: - ReadWriteOnce local: path: /root/k8s-local-volume/1231 nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - k8s-master네임스페이스에 속하지 않는 클러스터 레벨 오브젝트마스터 노드의 실제 레이블(kubernetes.io/hostname: k8s-master)과 연결로컬 볼륨 경로와 노드 어피니티를 통한 정확한 위치 지정PV를 만들 때 문제가 생기기 때문에 디렉토리를 미리 만들어 둔 것8.2 노드 레이블과 연결 메커니즘마스터 노드의 자동 생성 레이블# Kubernetes가 자동으로 생성하는 노드 레이블 labels: kubernetes.io/hostname: k8s-master kubernetes.io/os: linux node-role.kubernetes.io/master: ""Kubernetes가 클러스터를 구성하면서 자동으로 만들어 놓은 오브젝트에 레이블 존재Pod의 노드 선택# Pod template의 nodeSelector nodeSelector: kubernetes.io/hostname: k8s-master노드의 실제 레이블과 정확히 매칭특정 노드에 Pod와 PV를 모두 배치하여 로컬 스토리지 활용nodeSelector로 지정한 마스터 노드에서 이 레이블과 연결레이블의 정보 역할과 기능성 역할정보 역할만 하는 레이블: 사람이 보기 위한 메타데이터기능성 역할을 하는 레이블: 시스템이 오브젝트를 연결하기 위해 사용Pod는 nodeSelector와 PV는 nodeAffinity로 노드 레이블과 연결 9. 서비스와 네트워킹9.1 Service의 용도별 네이밍# 내부 통신용 Service apiVersion: v1 kind: Service metadata: name: api-tester-1231-internal spec: type: ClusterIP selector: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 --- # 외부 노출용 Service apiVersion: v1 kind: Service metadata: name: api-tester-1231-external spec: type: NodePort selector: app.kubernetes.io/name: api-tester app.kubernetes.io/instance: api-tester-1231 Service 네이밍 전략Pod에는 여러 Service 연결 가능클러스터 내부 전용: internal 접미사외부 접속 전용: external 접미사목적에 따른 명확한 네이밍으로 관리 효율성 증대사용 목적에 맞게 네이밍을 추가하면 됨10. 자동 확장과 부하 관리10.1 HPA의 다양한 정책 관리기본 HPA 설정# 기본 HPA apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: api-tester-1231-default spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: api-tester-1231 minReplicas: 2 maxReplicas: 4 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 40특별한 이벤트용 HPA# 특별한 이벤트용 HPA apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: api-tester-1231-event spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: api-tester-1231 minReplicas: 5 maxReplicas: 20HPA 네이밍 전략특정 이벤트를 위한 임계치 조정으로 여러 HPA 오브젝트 생성 가능목적에 따른 네이밍으로 구분 (default, event, peak-hours 등)특정 이벤트를 위해서 임계치를 다르게 해준 오브젝트를 따로 만들어 놓게 되면 이런 이름을 쓸 수 있음 11. 오브젝트 레벨과 스코프11.1 클러스터 레벨 vs 네임스페이스 레벨클러스터 레벨 오브젝트Persistent Volume, Node, Namespace가 대표적전체 클러스터에서 유일하며 모든 네임스페이스에서 접근 가능클러스터 관리자 권한 필요네임스페이스 삭제 시에도 별도 삭제 필요네임스페이스 개념이 없어 글로벌 범위에서 관리네임스페이스 레벨 오브젝트Deployment, Service, ConfigMap, Secret, PVC가 해당특정 네임스페이스 내에서만 존재네임스페이스 삭제 시 함께 삭제멀티 테넌시 환경에서 리소스 격리와 접근 제어의 핵심11.2 오브젝트 연결 방식의 분류레이블-셀렉터 기반 연결Deployment → ReplicaSet → PodService → PodPVC → PV (선택적)동적이고 유연한 연결 관계조건 기반 다중 오브젝트 선택 가능직접 이름 참조 기반 연결HPA → Deployment (scaleTargetRef)Pod → ConfigMap (configMapRef)Pod → Secret (secretRef)Pod → PVC (persistentVolumeClaim)명시적이고 안정적인 연결 관계Kubernetes의 연결 방식 정리크게 두 가지 연결 방식 제공오브젝트마다 다른 방법을 제공각 오브젝트 타입별 최적화된 연결 방식 선택 12. 모니터링과 관찰 가능성12.1 Prometheus를 통한 메트릭 수집메트릭 수집 아키텍처Prometheus: 중앙 집중식 메트릭 수집과 저장, 성능 정보에 대한 API 제공Exporter: 다양한 소스로부터 메트릭 데이터 제공Grafana: 수집된 메트릭의 시각화와 대시보드 구성kube-state-metrics의 역할Kubernetes 클러스터 자체의 메트릭 정보 제공오브젝트 상태, 리소스 사용량, 클러스터 헬스 모니터링클러스터 운영에 필수적인 관찰 데이터 생성Node Exporter의 기능개별 노드(VM)의 시스템 메트릭 수집CPU, 메모리, 디스크, 네트워크 사용률 모니터링인프라 레벨의 성능 데이터 제공12.2 모니터링 네임스페이스 설계metadata: namespace: monitoring모니터링 관련 모든 컴포넌트를 전용 네임스페이스에 배치시스템 모니터링 도구들의 격리와 독립적 관리모니터링 인프라의 안정성 보장네임스페이스 이름은 이 네임스페이스에 들어가는 앱들에 대한 범위를 나타내는 이름이 좋음 13. 실무에서의 고려사항과 교훈13.1 레이블과 네이밍의 중요성에 대한 실무 교훈2년 경력 후의 깨달음강의에서 언급된 실무 경험담이 보여주는 핵심 교훈레이블과 셀렉터, 네이밍 규칙이 단순 기술 설정을 넘어 팀 협업과 시스템 유지보수에 직결초기 설계의 중요성과 나중에 수정하기 어려운 현실적 제약실제로 Kubernetes를 시작하고 2년 정도가 지나서야 이 부분을 신경쓰기 시작조기 학습의 중요성실제 구성한 YAML 파일에 대한 설명 요구 상황 시 당황하지 않기 위함체계적인 레이블링과 네이밍이 전문성의 지표기본기의 탄탄함이 복잡한 운영 환경에서의 자신감으로 연결만약에 이걸 신경쓰기 전에 제가 구성한 야물파일들을 보고 누군가 이 구성을 왜 이렇게 했는지 물어봤다면 매우 부끄러웠을 것현실적인 경험담의 교훈이름을 잘 모르는 동료 상황과 유사한 느낌시간이 어느 정도 지났을 때 모르고 있으면 찾피한 상황들 발생지금부터 배울 내용이 바로 이런 느낌13.2 운영 환경에서의 변경 관리레이블과 이름 변경의 위험성오브젝트 이름과 레이블은 연결 요소이므로 변경 시 연쇄 영향 발생운영 중인 시스템에서는 네이밍 변경이 매우 부담스러운 작업초기 설계 단계에서 충분한 검토와 계획 필요이런 부분들은 운영에 올라가기까지 정말 많이 고민을 해보시고 만들길 당부템플릿 기반 관리 전략개인 또는 팀 차원의 YAML 템플릿 라이브러리 구축Google Drive나 Git 저장소를 활용한 템플릿 관리검증된 패턴을 재사용하여 일관성 유지와 실수 방지그런 템플릿을 불러가가 했던 개인 구글 드라이브가 했던 내가 언제든 바로 쓸 수 있는 형태로만 잘 가지고 있으면 됨13.3 과정에서의 어려움과 중요성이과정이 제일 어려운 부분네이밍과 레이블 구성을 위한 과정이 가장 어려운 부분이런 걸 처음 많이 고민해서 만들어 놔야 되는 게 이름이랑 레이블들은 다 오브젝트 연결 요소나중에 수정하다가 예리가 날 수도 있음운영까지 간 상황에서의 부담이미 운영까지 간 상황이라면 벌써 아닌 네이밍조차도 수정하기가 많이 부담스러움초기 계획과 설계의 중요성13.4 학습과 복습 전략점진적 숙달 방법처음에는 많은 내용처럼 보이지만 실제로는 자주 사용하는 핵심 기능들반복 사용을 통한 자연스러운 습득부담 갖지 말고 꾸준한 실습을 통한 숙련도 향상조금만 쓰다보면 금방 익숙해질 부분들이니까 너무 부담 갖지 마시고실습 환경 활용생성된 오브젝트들을 직접 조작하며 내용 복습다양한 명령어와 참고 자료를 활용한 능동적 학습이론과 실습의 균형을 통한 깊이 있는 이해다음 수업을 들기 전에 현재 만들어진 오브젝트들을 이것저것 놀리보면서 내용을 한번 복습을 해보세요 14. 전체 시스템 아키텍처 정리14.1 실제 구성된 오브젝트 관계도수업별 넘버링 체계Namespace: anotherclass-123 (수업별 넘버링)각 수업에서 만들었던 오브젝트가 전체 수업에 영향이 없도록 하기 위한 목적수업 때마다 네이밍 이름을 다르게 하여 격리Pod 업데이트 관리Deployment: Pod의 업데이트를 관리하고 ReplicaSet이 복제본을 관리하는 역할ReplicaSet: 복제본을 관리하는 역할을 하는 거정확하게는 Deployment가 파드의 업데이트를 관리selector와 matchLabels 연결Deployment와 ReplicaSet에 어떤 select와 label로 연결되어 있음Service도 Pod에 연결할 때 마찬가지PVC랑 PV도 이렇게 연결selector와 label은 오브젝트를 매칭해주는 역할14.2 클러스터 전체 구성네임스페이스와 클러스터 레벨 분리Service, PVC와 PV도 연결되는데 노드도 클러스터를 구성Kubernetes가 자동으로 만들어 놓은 오브젝트가 있고 이 오브젝트에도 레이블이 있음PAD에서는 노드 셀렉터가 그리고 PV에서는 노드 어피니티가 이 레이블과 연결레이블의 이중 역할 재강조레이블에는 정보와 기능성 역할을 하는 레이블의 정보 역할만 하는 레이블이 있음앞에 prefix를 붙일 수도 있어요 (도메인을 가리킴)특히 Kubernetes 분석에 있는 아울 파일들에서 이런 예제들을 많이 볼 수가 있음 15. 결론15.1 핵심 구성 요소별 역할 정리네임스페이스를 통한 논리적 그룹핑으로 리소스 격리와 관리Deployment와 Service를 통한 애플리케이션 배포와 네트워킹ConfigMap과 Secret을 통한 구성 관리와 보안PV/PVC를 통한 데이터 영속성 보장HPA를 통한 자동 확장과 리소스 최적화15.2 레이블-셀렉터 시스템의 핵심 가치오브젝트 간 연결 관계와 레이블-셀렉터 메커니즘의 정확한 이해 필수체계적인 레이블링과 네이밍이 단순 기술 지식을 넘어 실무 성공의 핵심 요소초기 설계의 중요성과 운영 중 변경의 어려움을 고려한 신중한 접근 필요15.3 실무 적용을 위한 권장사항Kubernetes 권장 레이블 적극 활용app.kubernetes.io/* 프리픽스를 활용한 표준화된 레이블링part-of, component, name, instance, version, managed-by 구조 활용추가적으로 의미 있는 정보들을 더 만들면 좋음
데브옵스 · 인프라
・
쿠버네티스
・
일프로