logo
logo
데브옵스
Karpenter
쿠버네티스 환경에서 애플리케이션의 가용성 및 리소스 사용률을 효율적으로 운영할 수 있도록 도와주는 오토스케일러입니다.
StackOverflow 질문 수: 11
Github Stars : ★ 7191
사용 기업
패션
푸드테크
소셜/컨텐츠
블록체인
이커머스
techstack-logo
카카오스타일
techstack-logo
마켓컬리
techstack-logo
리디
techstack-logo
폴라리스쉐어테크
techstack-logo
퍼플아이오
기술 블로그 글
당근
Karpenter 트러블슈팅 — 비용과 안정성 두마리 토끼 잡기
Karpenter 트러블슈팅 — 비용과 안정성 두 마리 토끼 잡기안녕하세요, 저는 당근페이 인프라팀에서 Site Reliability Engineer로 일하고 있는 Yany라고 해요. 저희 팀은 당근페이의 인프라를 안정적으로 관리해요. 개발자들의 프로덕트 개발 속도를 향상하고, 동시에 비용도 최적화하죠.저희는 클러스터 오토스케일링 없이 ASG(AWS EC2 AutoScaling Group)로, 그리고 HorizontalPodAutoscaler 없이 클러스터를 관리하고 있었어요. 여기에는 몇 가지 문제가 있었어요:스케일 아웃 과정에서 네트워크에 여러 병목 지점이 생겼어요.클러스터 업데이트를 진행하면서 ASG마다 AMI를 업데이트해야 했고, 오토스케일링이 원활하지 못했어요.컴플라이언스 이슈로 인해 분리된 노드, 서브넷에서 동작해야 하는 워크로드가 증가하면서 ASG가 늘어나 관리 포인트가 증가하고 있었어요.새벽 시간대에 트래픽이 현저히 적은 것에 비해 리소스를 너무 많이 사용하고 있었어요.당근페이의 거래량과 유저 수가 급격히 증가하면서, 기존의 ASG 기반 인프라 운영 방식으로는 한계가 명확해졌어요. 이에 따라 더 유연하고 자동화된 클러스터 스케일링이 필요했고, 그 해답으로 Karpenter를 도입하게 되었어요.그 여정은 저희가 생각한 것만큼 마냥 쉽지만은 않았는데요. 이번 글에서는 그 트러블슈팅 과정을 구체적으로 소개해드리려고 해요. Karpenter 도입을 고민 중이시거나 더 효율적으로 사용할 방법을 찾고 계신다면, 이 글이 큰 도움이 되길 바라요.Karpenter란?Karpenter는 쿠버네티스 클러스터에서 파드의 수요에 맞춰 노드의 양을 조절하는 Cluster Autoscaling Operator에요. 여러 컴포넌트를 통해 원하는 규격의 노드를 생성하고, 생성된 노드의 생명주기를 관리하도록 도와줘요.출처: [https://karpenter.sh/]대표적인 기능은 아래와 같아요:ProvisioningPending 상태의 파드가 존재하면, 스케줄링을 통해 필요한 노드를 생성하여 해당 파드가 스케줄링될 수 있도록 해요.각 CSP(Cloud Service Provider, 저희의 경우 AWS가 여기에 해당해요.)에서 만든 NodeClass 구현체를 통해 인스턴스의 규격을 정해요.- AWS로 가정했을 때 AMI, Subnet, Storage, Security Group, Userdata 등 EC2 인스턴스 자체와 관련된 설정을 진행할 수 있어요.NodePool을 통해 기존 ASG처럼 목적별로 노드를 생성할 수 있어요.- 여러 타입의 인스턴스를 생성할 수 있어, Cluster Autoscaler (이하 CA)보다 훨씬 효율적으로 스케일링을 진행할 수 있어요.DisruptionDrift: NodeClass, NodePool이 바뀌면 Drift를 통해 노드들을 원하는 상태로 Sync할 수 있어요.Consolidation: 충분히 사용하고 있지 않은 노드를 삭제해서 최적화된 양의 리소스를 사용할 수 있어요.- SingleNodeConsolidation
karpenter
kubernetes
nodejs
사람인에이치알
Karpenter 파일럿
지난 포스팅과(사이트 신뢰성에 대한 지표는 어떻게 구성할까?) 다르게 이번엔, AWS EKS 환경을 좀 더 안정적이며 확장성 있게 운영하기 위해 고민하고 테스트 했던 내용에 대해 공유 드리고자 합니다.사람인은 K8S 플랫폼으로 On-Premise가 주이고 최근 서비스는 AWS EKS를 사용하고 있습니다. 초기 EKS를 구축 했을 때 CA를 사용하지 않고 Auto Scaling Group을 이용하여 명시적으로 관리 했었습니다.하지만 거기서 오는 문제점들이 하나씩 발견 되기 시작 했습니다.• 신규 서비스로 낮은 인스턴스 타입 또는 적은 인스턴스의 RI 설정• 신규 버전에 대해 배포시 많은 리소스 요청으로 인해 Node의 상태가 자주 발생• Auto Scaling Group이 있지만 제대로 감지가 되지 않고, 속도가 느리기 때문에 Node가 죽기 전에• 문제 발생 할 때 마다 으로 노드그룹 수치를 변경하여 축소와 확장으로 임시 조치문제 발생 할 때 마다 항상 대응 할 수 없고, On-Demand 비용 증가와 안정성 결여로 많은 문제점이 존재 했습니다.Autoscaling에서도 여러 종류가 있는데, 먼저 Pod Autoscaling으로는 수평적으로 Scale-out 해주는 HPA가 있고 수직으로 Scale-up 해주는 VPA가 있습니다. Node Autoscaling으로는 CA와 Karpenter가 있는데 Karpenter는 CA와 달리 노드그룹과 같은 추가 오케스트레이션 메커니즘 없이 인스턴스를 직접 관리합니다.Karpenter에 대해 검증을 하기 위해 먼저 케이스를 작성 한다음 케이스에 맞게 테스트를 진행 했습니다.Karpenter를 안정적으로 운영하기 위해 첫번째로 해야 할 부분이 아무래도 Karpenter Controller를 분리 하는 것일 거 같습니다. Karpenter가 생성한 노드에 자기 자신이 동작하고 있다면 나중에 노드를 줄이게 될 때 Karpenter가 죽게 되는 상황이 발생 할 것 입니다. ASG(Auto Scaling Group)에서 동작하는 노드들에 대해서는 Karpenter Controller, CoreDNS 등 과 같은 Pod가 동작하도록 Taint & Toleration설정을 하였습니다.ASG 노드에 Taint 설정을 하고, 거기서 동작하는 Pod에 대해 Toleration 설정을 하여 키밸류가 일치 해야만 Running 될 수 있도록 했습니다.RI 계약이 On-demand 3대로 되어 있기 때문에 ASG 노드 3대에서 1대를 줄이고, Karpenter에서 On-demand를 1대 생성하도록 했습니다. (검증 겸)같은 Node Pool에 에 spot 과 on-demand를 같이 넣으면 우선순위로 어차피 Spot을 먼저 할당 하겠지만, 노드풀은 나눠놓은 이유는 disruption을 다르게 가져가기 위해서 입니다. on-demand에서는 파드가 완전히 없기 전까지 disruption 하지 않도록 를 WhenEmpty로 설정 하였습니다. 그리고 weight를 on-demand를 낮도록 설정하여 spot을 먼저 할당 받도록 했습니다.매칭 되는 Spot Instance가 없으면 사진과 같이 인스턴스가 없다고 나타납니다.매칭 되는 Spot Instance가 없으면 on-demand의 Nodepool에서 할당 받게 됩니다.각 노드에 파드 하나씩 러닝 되도록 분배처리 하기 (TopologySpreadConstraints)파드를 리전, 존, 노드 등의 기준으로 파드를 균등하게 배포 될 수 있도록 하기 위해 설정을 해주었습니다.maxSkew: 노드간 파드 개수 차이가 최대 1개까지 허용 topologyKey: 이 키를 가진 노드는 동일한 토폴로지에 있는 것으로 간주 합니다. matchLabels: 일치하는 파드를 찾는데 사용 됩니다.이러한 설정으로 각 AZ에 파드가 분배 될 수 있도록 합니다.Karpenter는 Utilization을 토대로 노드를 할당 해주지 않습니다. 이것은 Kubernetes Schdeduler가 Request 기반으로 동작하기 때문에 이에 맞게 동작하도록 되어 있습니다. 그래서 최대한 Utilization에 맞게 Request를 주는 것이 좋습니다. 다만 Java의 경우 Initializing 때 실제로 사용하는 리소스보다 많이 잡아 먹습니다. Metric을 보고 Request를 잘 조절 해주면 Karpenter가 빈패킹 단계에서 좀 더 정확하게 인스턴스 타입을 선별 할 수 있도록 합니다. 최대한 게런티 파드로 구성하도록 했습니다.Karpenter에서 생성할 노드에서 동작한 Kubelet에 대한 설정도 진행 할 수 있습니다. 이 부분 Karpenter의 영역이라기 보단 EKS에서도 많은 분들이 기본적으로 설정 해두는 부분 입니다.먼저 kubelet의 Reserved 영역을 지정하는 것 입니다.Application에서 리소스를 100% 다 잡아 먹는다 하더라도 Reserved 영역을 설정하여 Node 와 같은 상황에 안빠지도록 안전장치를 추가 했습니다.이렇게 설정하여 인스턴스 리소스를 어플리케이션이 모두 할당해서 Hang 걸리는 일이 없도록 하였습니다.해당 인스턴스의 공간으로 인한 DiskPresure가 발생할 수 있기 때문에 Image Garbage Collection을 위한 WaterMark 설정을 하였습니다.eviction에 대한 처리 방식인데, evictionSoft도 있지만 아무래도 eviction 시킬 때에는 노드의 자원 등 위급할 때 배출 하는거라 Hard가 나은 결과로 나왔습니다. 여러 안전장치를 통해 eviction 되는 경우는 거의 줄었습니다.개발 환경의 경우 업무시간 외에는 Karpenter 노드가 중지되도록(주말, 공휴일, 전사휴무일)안정성과 확장성을 위해 사용하지만 Spot Instance를 쉽게 이용 할 수 있다는 점에서 비용적인 측면도 무시 할 수 없어서 효율을 극대화 하기 위해 비업무시간에는 Karpenter 노드가 중지되도록 CronJob과 Python code를 걸었습니다.22시 이후에는 Karpenter 노드에 대해 memory limit을 0으로 설정 하도록 했습니다. Karpenter는 limit의 수치
karpenter
nodejs
여기어때컴퍼니
Karpenter 0.3x
안녕하세요. 여기어때컴퍼니 SRE팀에서 EKS(Elastic Kubernetes Service, AWS의 관리형 Kubernetes 서비스)를 담당하고 있는 젠슨입니다.기존에 Karpenter 사용 방법에 대한 블로그를 작성한 적이 있습니다. 최근 신규로 Karpenter를 설치할 일이 있어 최신 버전을 찾아보니 API Version이 변경 되면서 사용 방법 또한 조금 변경된 점이 있어 해당 내용을 보충 하려고 블로그를 작성하게 되었습니다.Karpenter 0.3x그럼 하나 씩 살펴 보도록 하겠습니다.1. 변경 사항가장 중요한 변경 사항으로 아래 세 가지를 말씀 드리고 싶습니다. 물론 공식 Git에 더 자세하고 많은 내용이 나와 있습니다.API Version 변경Drift 기본 활성화spotToSpotConsolidation 기능우선 API Version이 기존까지 karpenter.sh/v1alpha5였는데 이제 karpenter.sh/v1beta1으로 변경 되었습니다. 곧 정식 v1을 출시 한다고 하니 조금만 더 기다려 보시면 좋을 것 같습니다.다음으로는 Drift 입니다. Drift는 Karpenter에 의해서 생성된 WorkerNode 에 새로운 변경사항을 담은 Manifest가 배포 되면 해당 내용을 감지하고 바로 현재 운영 중인 WorkerNode에 변경된 내용을 적용해 주는 기능입니다. 예를 들어 현재 c5.large Type의 WorkerNode를 운영 중일 때 m5.large로 변경된 Manifest를 배포 하면, Drift 기능이 활성화 되어 있지 않을 경우 기존에 운영 중이던 c5.large Type의 WorkerNode들은 영향을 받지 않고 신규로 생성되는 WorkerNode들만 m5.large Type으로 생성될 것입니다.만약 Drift가 활성화 되어 있다면 Manifest가 배포되는 순간 이미 운영중이던 모든 WorkerNode들의 Type을 m5.large로 변경해 줍니다. Instance Type 에 대한 예를 들었지만 Tag, AMI, SG등 여러가지 변경 사항들을 바로 적용해 주는 기술 입니다. 이 Drift 기능이 0.3x부터는 Default 값이 true 입니다. 만약 해당 기술이 운영에 문제를 일으킬 수 있다면 false로 변경해 주셔야 합니다. 아래와 같은 상황이 발생할 수 있기 때문입니다.만약 amiFamily와 같은 설정을 이용하여 AL2023, AL2와 같은 값을 넣어 놓았다고 가정해 보겠습니다. 이렇게 되면 해당 Family의 최신 버전 AMI ID를 자동으로 가져오게 되는데, 현재 운영 중이던 WorkerNode의 AMI ID 값과 Manifest의 ID 값이 다르다면 Drift에 의해 WorkerNode가 변경될 것입니다. Drift 활성화로 운영 중 WorkerNode의 교체가 이루어져서 장애를 발생시킬 수 있기 때문에 주의 하셔야 합니다.이제 마지막으로 spotToSpotConsolidation 기능 입니다. 이미 기존에 Consolidation 기능에 대해서 설명해 드린 적이 있는데
karpenter
kubernetes
여기어때컴퍼니
NTH(NodeTerminationHandler)
안녕하세요. 여기어때컴퍼니 SRE팀에서 EKS(Elastic Kubernetes Service, AWS의 관리형 Kubernetes 서비스)를 담당하고 있는 젠슨입니다.Karpenter 0.3x에 대한 블로그 마지막에 NTH에 대해서 예고해 드린 적이 있습니다. NTH는 Spot Instance를 사용할 때 Node가 갑작스럽게 종료되면서 해당 Node에서 운영중이던 Pod들이 안정적으로 종료되고 신규 Node에서 배포될 수 있도록 도와주는 기능입니다.이러한 기능을 사용할 수 있는 이유는 Spot Instance가 종료되기 2분 전에 Interruption Event를 받기 때문입니다. 기본적으로 Karpenter에서는 이러한 Event에 대응할 수 있는 InterruptionQueueName이라는 옵션을 제공합니다. 그러면 NTH는 왜 필요한 것일까요?1. NodeTerminationHandlerSpot Instance는 2분 전에 Interruption Event를 통해서 ‘내가 곧 종료된다’라는 것을 알 수 있다고 했습니다. 그러나 2분이라는 시간 안에 해당 WorkerNode에서 수행 중이던 Pod들이 모두 다른 WorkerNode로 이동하기에는 다소 부족할 수 있습니다. 그러면 이렇게 종료된다는 Event를 조금 더 빠르게 받을 수는 없을까요? 애매하긴 하지만 15분 전에 Rebalance Recommendation이라는 Event를 받을 수 있습니다. 제가 애매하다는 표현을 썼는데 그 이유는 Rebalance Recommendation Event를 받았다고해서 해당 Node가 반드시 죽는 것은 아니기 때문입니다. 아래 그림을 보면서 설명해 드리도록 하겠습니다.1. Interruption Event가 발생할 경우2. Interruption Event가 발생하지 않을 경우같은 시간에 Launch된 Instance가 있다고 할 때 2개의 Instance가 모두 Rebalance Recommendation Event를 받았다고 가정해 보겠습니다. 첫 번째 Instance는 Interruption Event를 받아서 Terminated되었고 두 번째 Instance는 Interruption Event를 받지 않아서 계속해서 Running되고 있습니다. 결국 Rebalance Recommendation은 WorkerNode가 종료된다라는 의미가 아니라 Interruption의 대상 리스트에 올라갔다 정도로 생각할 수 있습니다. 그러면 Rebalance Recommendation이 발생할 때 해당 WorkerNode에서 수행중이던 Pod들을 종료하고 재배포 해주면 충분한 시간이 보장되면서 완벽하지 않을까? 라는 생각을 할 수 있습니다. 물론 저도 그렇게 생각하며 이러한 Event가 얼마나 발생하는지 뽑아보았습니다.Interruption EventRebalance Recommendation EventSpot Instance를 사용해 보신 분들은 아시겠지만 생각보다 Instance의 교체가 자주 발생합니다. 위의 그래프는 Interruptio
awssqs
helm
karpenter
kubernetes
slack
연관 기술 스택
techstack-logo
Kubernetes
Copyright © 2025. Codenary All Rights Reserved.