k8s 도입하면서 겪은 일들
볼 사람 추천
1. 쿠버네티스에 관심이 있는 사람
2. 내 애플리케이션을 쿠버네티스로 운영하고 싶은 사람
다룰 내용
1. 쿠버네티스란, 도입 배경과 배포
2. 도입 후 장단점
3. Pod와 Deployment
4. Ingress
5. Liveness Probe와 Readiness Probe
6. K8s 운영 꿀팁 (10개 실제 적용사례를 바탕으로)
쿠버네티스란?
여러 서버로 구성된 클러스터 환경에서 컨테이너화된 프로세스를 관리하기 위한 컨테이너 오케스트레이션
기존 vm하고 비교해서 설명을 하면,
서버가 10개가 있다면
- [2개] 내가 만든 애플리케이션
- [4개] 다른 개발자가 만든 애플리케이션
- [4개] 또 다른 개발자가 만든 애플리케이션
쿠버네티스는 이렇게 구성되지 않습니다.
10개의 서버가 있으면 한꺼번에 들어가서 한꺼번에 관리되는 구조입니다.
쿠버네티스 -> K8s 같은 말
리소스
사실 3개(Pod, svc, node)만 있어도 운영하는데 문제 없습니다.
운영편의성을 위해 아래 2개를 도입했습니다.
pod | svc | node | ingress | deployment |
내 애플리케이션 서비스가 올라가는 곳.(vm == 인스턴스 1개) | pod앞단에서 분기해주는 곳 | 장비 1개, vm 1개입니다. |
네트워크 트래픽을 받아서 네트워크를 관장하는 리소 | 배포와 관련된 리소스 |
쿠버네티스 도입 배경
새로운 애플리케이션을 개발했는데 서브서비스였음.
이런걸로 서버를 할당받아서 하기에는 비용문제가 있었고, 쿠버네티스는 함께 관리하기 때문에 비용문제에서 벗어날 수 있음.
MSA에서의 쿠버네티스
기존에 운영하던 애플리케이션 서비스는 쿠버네티스로 전부 옮겨야할까?
기존 서비스는 VM 유지, 새로운 서비스만 쿠버네티스 운영
장점: 기존 애플리케이션 건들지 않고, 쿠버 체험 가능
배포 구조
쿠버네티스를 쓸 때, 배포를 어떻게 하지? 라고 처음에 되게 막막함.
ArgoCD, FluxCD 이쁘게 구성해야하는데 그렇게 해야할까요?
일단 레거시한 방법 택하기.
개발자가 소스 코드 작성(커밋, 푸시) -> 레포지토리에 올라감 -> 개발자가 빌드를 요청하면, 젠킨스가 2가지 일함. -> 아까 소스코드를 도커 이미지로 말아서 Nexus에 올려준다. -> .yml 파일(설정파일) NHN 클라우드 디플로이에 올려준다 -> 개발자가 마지막에 배포를 요청하면 -> NHN 클라우드 디플로이에서는 yml파일을 K8s 마스터 노드에 올려주고 적용한다 ->
도커 이미지 저장소에 저장된 이미지를 가져와서 쿠버네티스 클러스터에 올려준다.
개발자: 소스코드 작성하는 곳
Repository: 코드가 올라가는 곳
Jenkins: 빌드를 도와주는 빌드툴
Nexus: 이미지가 저장되는 이미지 저장소
NHN Cloud Deploy: NHN Cloud에 올려주는 툴
K8s Master Node: 쿠버네티스 클러스터에 있는 노드
도입 후 장점과 단점
장점 1) 실행환경 보장
애플리케이션이 사람들이 많이 쓰고 인기가 많아져서, 서버를 1개 더 설치해야함.
그러면 장비를 받아서 Java설치, WAS설치, 스크립트 필요하다면?(로그 분할, 새벽 배치 작업) 진행
쿠버네티스를 쓰면 이거 필요없다.
실행환경이 고립화가 되어있음, 워커노드에 컨테이너 런타임이 실행환경 보장
pod하나 더 늘린다고 매번 설치가 없다.
장점 2) 배포의 편리함
운영을 하는 입장에서 배포편리함이 중요함.
기존의 VM 배포는 문제 2개 있음, 여러개의 터미널을 띄어야 함.
롤백에 대한 스트레스 -> 내가 해야 되니까 재빠르게 하면서 팀원에게도 문제(바쁘다 바빠 현대사회!)
쿠버네티스는 선언형의 설정파일을 만든다.
pod는 2개를 띄우고, 레이블 설정을 하고, nginx 최신버전을 쓰고, CPU는 요만큼만 써라.
예를들어, 도커이미지를 변경했다.
쿠버는 이를 이벤트로 받아들여서 1개씩 배포해준다.
지금 Pod가 2개 운영중인데, 1개씩 새로운 pod가 올라오고 기존 pod는 내려감.
그래서
새로운 Pod가 ContainerCreating이 되고
그 다음에 기존pod가 내려가게 되고 -> 새로 배포가 됨.
장점
1) 터미널 여러개에서 해방됨.(1개씩 roleout)
2) 로그들이 색깔로 구분해서 1개씩 띄움(보기쉬움)
3) 롤백에 대한 스트레스(어느정도 해소가능)
이유: container creating 에서 어떤 문제가 생기면 기존에 있던 pod로 계속 운영해준다.
롤백을 제때못해서 생기는 문제를 어느정도 해소가능.
장점 3) 셀프 힐링
개발할 때 경험한 적 있음, 주기적으로 OOM이 발생한 경험을 했음.
이유를 떠나서 문제 발생 당일날에 꿀잠자버림(밤에 발생함 ㅠㅠ)
원인: 스프링배치를 쓸 때, 메타테이블을 자동으로 쓴다, 배치를 언제 쓰고 스탭이 (1,2,3)이 있고 어떻게 진행되고 언제 끝난다.
의미있는 정보를 이미 로그에 저장하고 있기 때문에, 주기적으로 메모리에 올리고 지우는 작업을 하는데(너무 오래올려서 문제가 생겼다.)
쿠버네티스에 셀프 힐링특징으로 다음날에 기분좋게 해결함.
단점 1) 러닝커브 높음
1. http://10.10.10.10/mynginx로 요청이 들어오면, 클라이언트에 요청이 먼저 ip, port를 보고 Ingress로 트래픽이 먼저 들어온다.
*Ingress: 외부에 있는 트래픽을 받는 역할
2. /mynginx 주소를 보고 서비스로 보내서 트래픽을 전달받아서 Pod 3개중에 1개로 트래픽을 전달.
*Service: Pod앞단에서 말단이 되는 리소스
3. 애플리케이션에서 트래픽을 요청을 받고 응답을 처리해서 클라이언트한테 전달을한다.
*pod에는 내가 만든 애플리케이션 서비스가 올라감
노드
노드란 장비 1대를 의미함.
1. 마스커 노드: 쿠버네티스를 관리할 수 있는 핵심 컴포넌
2. 워커 노드: 내가 만든 애플리케이션 서비스가 올라가는 곳
cubectl 명령어를 앞으로 계속 날릴건데 그거를 받아준다
ex) 애플리케이션 서버를 배포를 했는데, 3번 워커노드에 가장 여유가 있어서 배치를 해준다.
문제점
case1) 마스터 노드가 반응이 없어짐
이유: pod를 운영할 때, 마스터노드, 워커 노드 전부 올림.
마스터 노드 pod가 너무 많이 올라가서 cpu, 메모리가 부족해졌음.
cubectl이란 명령어를 받아들일 여유가 없어져서 클러스터 전체가 문제가 생김.
그래서 배포를 확인하는데
문제해결법: pod를 워커노드에만 걸어주면 된다.
마스터노드에 taint(더럽히다, 얼룩)을 건다.
kebectl describe로 확인을해보면
key, value가 들어간걸 확인할 수 있다.
Pod
이미지 주소가 들어감.
kubectl apply -f mynginx.yaml로 쿠버에 적용해줘라는 명령어로 된다.
case2: 노드가 먹통이 됨.
*노드: 피지컬머신 vm 1개임
Pod 1개가 (CPU, 메모리)를 내가 생각한 것보다 많이 사용했다.
이런상황에 1개의 Pod만 문제생길 줄 알았는데, 다른 Pod도 문제가 생긴거임.
그래서 클라이언트는 다른 서비스를 사용하는데도 문제를 느꼈음.
이거를 해결하는 방법.
Pod 최대 사용량 지정 - 각 Pod에 (CPU,메모리) 리소스 사용량 제한을 두면됨.
CPU를 많이 사용했을 때 -> 그 곳만 재시작을 하면 다른 Pod 사용자가 영향없이 사용 가능.
Deployment
배포 관련 편의 기능 제공
1) 롤백을 편하게
2) 배포상태를 편하게 보고싶다.
3) 레플리카를 2로 설정 -> 하면 바로 Pod 갯수 변경됨.
디플로이먼트에 또 다른 장점.
Pod는 쿠버네티스에서 불안정한 자원 사람 추천
1. 쿠버네티스에 관심이 있는 사람
2. 내 애플리케이션을 쿠버네티스로 운영하고 싶은 사람
다룰 내용
1. 쿠버네티스란, 도입 배경과 배포
2. 도입 후 장단점
3. Pod와 Deployment
4. Ingress
5. Liveness Probe와 Readiness Probe
6. K8s 운영 꿀팁 (10개 실제 적용사례를 바탕으로)
쿠버네티스란?
여러 서버로 구성된 클러스터 환경에서 컨테이너화된 프로세스를 관리하기 위한 컨테이너 오케스트레이션
기존 vm하고 비교해서 설명을 하면,
서버가 10개가 있다면
- [2개] 내가 만든 애플리케이션
- [4개] 다른 개발자가 만든 애플리케이션
- [4개] 또 다른 개발자가 만든 애플리케이션
쿠버네티스는 이렇게 구성되지 않습니다.
10개의 서버가 있으면 한꺼번에 들어가서 한꺼번에 관리되는 구조입니다.
쿠버네티스 -> K8s 같은 말
리소스

사실 3개(Pod, svc, node)만 있어도 운영하는데 문제 없습니다.
운영편의성을 위해 아래 2개를 도입했습니다.
pod svc node ingress deployment
내 애플리케이션 서비스가 올라가는 곳.(vm == 인스턴스 1개) pod앞단에서 분기해주는 곳 장비 1개, vm 1개입니다.
네트워크 트래픽을 받아서 네트워크를 관장하는 리소 배포와 관련된 리소스
쿠버네티스 도입 배경
새로운 애플리케이션을 개발했는데 서브서비스였음.

이런걸로 서버를 할당받아서 하기에는 비용문제가 있었고, 쿠버네티스는 함께 관리하기 때문에 비용문제에서 벗어날 수 있음.
MSA에서의 쿠버네티스
기존에 운영하던 애플리케이션 서비스는 쿠버네티스로 전부 옮겨야할까?

기존 서비스는 VM 유지, 새로운 서비스만 쿠버네티스 운영
장점: 기존 애플리케이션 건들지 않고, 쿠버 체험 가능
배포 구조
쿠버네티스를 쓸 때, 배포를 어떻게 하지? 라고 처음에 되게 막막함.
ArgoCD, FluxCD 이쁘게 구성해야하는데 그렇게 해야할까요?
일단 레거시한 방법 택하기.

개발자가 소스 코드 작성(커밋, 푸시) -> 레포지토리에 올라감 -> 개발자가 빌드를 요청하면, 젠킨스가 2가지 일함. -> 아까 소스코드를 도커 이미지로 말아서 Nexus에 올려준다. -> .yml 파일(설정파일) NHN 클라우드 디플로이에 올려준다 -> 개발자가 마지막에 배포를 요청하면 -> NHN 클라우드 디플로이에서는 yml파일을 K8s 마스터 노드에 올려주고 적용한다 ->
도커 이미지 저장소에 저장된 이미지를 가져와서 쿠버네티스 클러스터에 올려준다.
개발자: 소스코드 작성하는 곳
Repository: 코드가 올라가는 곳
Jenkins: 빌드를 도와주는 빌드툴
Nexus: 이미지가 저장되는 이미지 저장소
NHN Cloud Deploy: NHN Cloud에 올려주는 툴
K8s Master Node: 쿠버네티스 클러스터에 있는 노드
도입 후 장점과 단점
장점 1) 실행환경 보장
애플리케이션이 사람들이 많이 쓰고 인기가 많아져서, 서버를 1개 더 설치해야함.
그러면 장비를 받아서 Java설치, WAS설치, 스크립트 필요하다면?(로그 분할, 새벽 배치 작업) 진행

쿠버네티스를 쓰면 이거 필요없다.
실행환경이 고립화가 되어있음, 워커노드에 컨테이너 런타임이 실행환경 보장
pod하나 더 늘린다고 매번 설치가 없다.
장점 2) 배포의 편리함
운영을 하는 입장에서 배포편리함이 중요함.
기존의 VM 배포는 문제 2개 있음, 여러개의 터미널을 띄어야 함.

롤백에 대한 스트레스 -> 내가 해야 되니까 재빠르게 하면서 팀원에게도 문제(바쁘다 바빠 현대사회!)
쿠버네티스는 선언형의 설정파일을 만든다.

pod는 2개를 띄우고, 레이블 설정을 하고, nginx 최신버전을 쓰고, CPU는 요만큼만 써라.
예를들어, 도커이미지를 변경했다.
쿠버는 이를 이벤트로 받아들여서 1개씩 배포해준다.
지금 Pod가 2개 운영중인데, 1개씩 새로운 pod가 올라오고 기존 pod는 내려감.
그래서
새로운 Pod가 ContainerCreating이 되고
그 다음에 기존pod가 내려가게 되고 -> 새로 배포가 됨.
장점
1) 터미널 여러개에서 해방됨.(1개씩 roleout)
2) 로그들이 색깔로 구분해서 1개씩 띄움(보기쉬움)

3) 롤백에 대한 스트레스(어느정도 해소가능)
이유: container creating 에서 어떤 문제가 생기면 기존에 있던 pod로 계속 운영해준다.
롤백을 제때못해서 생기는 문제를 어느정도 해소가능.
장점 3) 셀프 힐링
개발할 때 경험한 적 있음, 주기적으로 OOM이 발생한 경험을 했음.
이유를 떠나서 문제 발생 당일날에 꿀잠자버림(밤에 발생함 ㅠㅠ)
원인: 스프링배치를 쓸 때, 메타테이블을 자동으로 쓴다, 배치를 언제 쓰고 스탭이 (1,2,3)이 있고 어떻게 진행되고 언제 끝난다.
의미있는 정보를 이미 로그에 저장하고 있기 때문에, 주기적으로 메모리에 올리고 지우는 작업을 하는데(너무 오래올려서 문제가 생겼다.)
쿠버네티스에 셀프 힐링특징으로 다음날에 기분좋게 해결함.
단점 1) 러닝커브 높음

1. http://10.10.10.10/mynginx로 요청이 들어오면, 클라이언트에 요청이 먼저 ip, port를 보고 Ingress로 트래픽이 먼저 들어온다.
*Ingress: 외부에 있는 트래픽을 받는 역할
2. /mynginx 주소를 보고 서비스로 보내서 트래픽을 전달받아서 Pod 3개중에 1개로 트래픽을 전달.
*Service: Pod앞단에서 말단이 되는 리소스
3. 애플리케이션에서 트래픽을 요청을 받고 응답을 처리해서 클라이언트한테 전달을한다.
*pod에는 내가 만든 애플리케이션 서비스가 올라감
노드
노드란 장비 1대를 의미함.
1. 마스커 노드: 쿠버네티스를 관리할 수 있는 핵심 컴포넌
2. 워커 노드: 내가 만든 애플리케이션 서비스가 올라가는 곳
cubectl 명령어를 앞으로 계속 날릴건데 그거를 받아준다
ex) 애플리케이션 서버를 배포를 했는데, 3번 워커노드에 가장 여유가 있어서 배치를 해준다.
문제점
case1) 마스터 노드가 반응이 없어짐
이유: pod를 운영할 때, 마스터노드, 워커 노드 전부 올림.
마스터 노드 pod가 너무 많이 올라가서 cpu, 메모리가 부족해졌음.
cubectl이란 명령어를 받아들일 여유가 없어져서 클러스터 전체가 문제가 생김.
그래서 배포를 확인하는데
문제해결법: pod를 워커노드에만 걸어주면 된다.
마스터노드에 taint(더럽히다, 얼룩)을 건다.

kebectl describe로 확인을해보면
key, value가 들어간걸 확인할 수 있다.
Pod

이미지 주소가 들어감.
kubectl apply -f mynginx.yaml로 쿠버에 적용해줘라는 명령어로 된다.
case2: 노드가 먹통이 됨.
*노드: 피지컬머신 vm 1개임

Pod 1개가 (CPU, 메모리)를 내가 생각한 것보다 많이 사용했다.
이런상황에 1개의 Pod만 문제생길 줄 알았는데, 다른 Pod도 문제가 생긴거임.
그래서 클라이언트는 다른 서비스를 사용하는데도 문제를 느꼈음.

이거를 해결하는 방법.
Pod 최대 사용량 지정 - 각 Pod에 (CPU,메모리) 리소스 사용량 제한을 두면됨.

CPU를 많이 사용했을 때 -> 그 곳만 재시작을 하면 다른 Pod 사용자가 영향없이 사용 가능.
Deployment
배포 관련 편의 기능 제공
1) 롤백을 편하게
2) 배포상태를 편하게 보고싶다.
3) 레플리카를 2로 설정 -> 하면 바로 Pod 갯수 변경됨.
디플로이먼트에 또 다른 장점.
Pod는 쿠버네티스에서 불안정한 자원
Case3: 변경 사항이 반영되지 않음.
watch kebectl get pod로 pod상태를 보면 재배포가 되는지 봤는데 배포가 안됐음.
스프링에서 자바 소스는 변경하지 않고, propertics만 바꿨는데, 이렇게 되면 쿠버네티스에서 도커이미지가 변경되지 않았다고
판단을하고 배포하지 않았던거임.
kubectl rollout restart deployment mynginx
를 통해서 하나씩 점진적으로 배포됨.
pod가 10개라고 하면 1개씩 내리고 올리면 1분이라고 하면 10분이 걸리는데, 2개씩 배포하면 5분이 걸림.
case4: 내 Pod가 다른 배치 작업에 영향을 받음.
주황색 노드가 배치작업을 할 때만, 주기적으로 장애가 낫다.
결과적 원인: 배치작업에서 CPU랑 메모리를 너무 많이 써서 나의 Pod에 영향을 줬다, 그 시간만큼 장애가 발생
해결방법: 노드를 분리 운영함.
설정하는 방법: Label을 추가하면됨.(operation=true)를 설정한 뒤, 제 Pod를 배포할 때, operation=true에만 배포해줘 라고 하면됨.
case5: 내 Pod가 한 노드에만 있다.
노드는 장비니까
1) 천제지변
2) 디스크가 문제
그럴 때 -> 쿠버네티스는 노드를 옮기면서 계속해서 운영하도록 한다.
문제 애플리케이션 구동시간이 1분정도 걸리는데, 옮겨가는 과정에서 1분동안 장애가 발생한다.
그럼 이거를 어떻게 해결하냐, 노드에 잘 배치해서 운영을 하면 된다.
Pod가 다른 노드에 존재하기 때문에 천제지변이 생겨도 문제가 되지 않는다.(PodAntiAffinity -> 이런 Pod는 피해서 배치해줘라는 뜻)
case 6: 재배포가 안 되는 상황
노드를 보면 2분동안 재배포가 안되는중
노드가 할당이 안됐다(none)
새로운 Pod가 배포될 곳이 없어서 기다리는 상황
해결방법: 노드를 1개 더 사용하자
if 배포가능한 노드수가 Pod수보다 많아지면 새로운 Pod가 새로운 노드에 배치가 됩니다.
기존에 있던 Pod가 내려간다.
실제운영환경: 배포가능한 노드가 Pod수보다 많아야 한다.(이렇게 Affinity를 사용하자.)
Ingress
인그레스 사용전에는 ACL문제가 있었음.
MSA구성을 하면 애플리케이션을 Port로 구분을 많이 한다.
쭉 테이블을 이용해서 구분한다.
이런 문제는 항상 밤에 일어난다.
*ACL(Access Control List): 접근제어목록, 엑세스 권한이 부여된 사용자 또는 시스템 프로세스
Case8: 포트가 기억이 안 나는 문제
처음에는 잘 기억나는데 시간이 지나면 port 번호 기억이 안남.
ex) mynginx가 포트가 30020이였던가?
그래서 포트번호를 보고 라우팅을 해야하니까 -> 테이블을 확인해야함(문제)
Ingress에 path기반 라우팅을 사용하면 그거로부터 해방이 된다.
처음에 쿠버네티스를 구축할때만 인그레스에 해당하는 포트번호만 뚫어주면 된다.
그리고 기억하기 쉬움.
mynginx라면 -> /mynginx로 접속
yournginx라면 -> /yournginx 로 접속
로 접속하면 기억이 된다. (네이밍을 잘하자!)
Liveness Probe와 Readiness Probe
- 잠을 푹 잘 수 있었던 이유
case9: Pod는 살아있는데 애플리케이션 서비스가 비정상인 경우
이럴경우는 Liveness Probe를 설정해주면 된다.
- 원하는 방식으로 Pod를 체크해서 응답이 없으면 자동으로 재시작
주기적으로 get으로 /live요청을 보내서 살아있는지 체크했는데, 404에러 발생
그래서 재시작 강행
case10: 재배포 시 순단 발생
순단을 방지하기
*순단(瞬斷): 짧은 순간 동안 서비스나 연결이 끊기는 현상
방지방법: Readiness Probe 잘 설정하기 (컨테이너 준비 상태인지 확인)
각 Pod에 준비가 됐는지 확인해서, 요청을 받을 수 있는 상태가 아니면 서비스 트래픽을 받지 않음.
구동시점만이 아니라, 서비스중에서도 문제 생기면 트래픽 가지않도록 설정 가능.
Pod를 좀 더 자세히 보자.
어떤 노드에 내 애플리케이션이 올라갔느냐
-o wide 옵션
$ describe
$ describe pod mynginx
로그를 편하게 보자 - stern
$ kubectl logs -f deployment-mynginx-952349b1-8vvs
쫌 구림: Pod가 어떤 이유로 내려갔을 때, 서비스의 로그를 볼 수 없음.
stern을 설치하면 편리하게 보기 가능.
$ stern -s ls deployment-mynginx
로그를 편리하게 보고싶다면 -> 그라파나에서도 볼 수 있음(브라우저 화면에서)
마지막 한 마디
운영은 예술의 영향이다~~
https://www.youtube.com/watch?v=JBGsqsoGxEo&t=79s