이번 포스트에서는 최근에 발생한 CoreDNS 장애 관련 내용을 공유합니다. 당연한 것들인데 새롭게 배운 것들이 많습니다. Karpenter, CoreDNS 사용하는 분들에게 참고가 되었으면 합니다.
장애 현상
일부 파드에서 DNS 조회 실패(dns resolve fail) 현상이 발생하였습니다.
장애 원인
Karpenter 설정에서 노드 그룹을 On-Demand와 Spot 두 가지로 운영하고 있었지만, interruptionQueue 설정이 누락되어 있었습니다. interruptionQueue 설정이 없으면 Spot 노드 종료 시 실행하고 있는 파드가 Graceful Shutdown하게 기존 세션을 종료하고 정상 종료되지 않아 해당 노드에 실행 중인 CoreDNS 파드 등에 문제가 발생합니다.
장애 조치
1. Karpenter interruptionQueue 설정
3가지 작업이 필요합니다. 순서는 CloudFormation 이용 SQS 생성 - IAM Role SQS 권한 추가 - Karpenter Helm interruptionQueue 추가입니다.
SQS 생성 CloudFormation 코드
----------------------------------------------------------------------------------------------------------------
AWSTemplateFormatVersion: "2010-09-09"
Description: Resources used by https://github.com/aws/karpenter
Parameters:
ClusterName:
Type: String
Description: "EKS cluster name"
Resources:
KarpenterInterruptionQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: !Sub "${ClusterName}"
MessageRetentionPeriod: 300
KarpenterInterruptionQueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref KarpenterInterruptionQueue
PolicyDocument:
Id: EC2InterruptionPolicy
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
- sqs.amazonaws.com
Action: sqs:SendMessage
Resource: !GetAtt KarpenterInterruptionQueue.Arn
ScheduledChangeRule:
Type: 'AWS::Events::Rule'
Properties:
EventPattern:
source:
- aws.health
detail-type:
- AWS Health Event
Targets:
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
SpotInterruptionRule:
Type: 'AWS::Events::Rule'
Properties:
EventPattern:
source:
- aws.ec2
detail-type:
- EC2 Spot Instance Interruption Warning
Targets:
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
RebalanceRule:
Type: 'AWS::Events::Rule'
Properties:
EventPattern:
source:
- aws.ec2
detail-type:
- EC2 Instance Rebalance Recommendation
Targets:
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
InstanceStateChangeRule:
Type: 'AWS::Events::Rule'
Properties:
EventPattern:
source:
- aws.ec2
detail-type:
- EC2 Instance State-change Notification
Targets:
- Id: KarpenterInterruptionQueueTarget
Arn: !GetAtt KarpenterInterruptionQueue.Arn
----------------------------------------------------------------------------------------------------------------
IAM Role
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"sqs:DeleteMessage",
"sqs:GetQueueAttributes",
"sqs:GetQueueUrl",
"sqs:ReceiveMessage"
],
"Effect": "Allow",
"Resource": "arn:aws:sqs:ap-northeast-2:{ACCOUNT_ID}:<SQS-NAME>"
}
]
}
Karpenter Helm 수정
- Values.yaml 추가 내역 (0.33.1 이전 버전)
settings:
aws:
interruptionQueueName: my-dev # Cluster Name 지정
Karpenter interruptionQueue 적용 전 로그
karpenter-6d877b79fc-bjq4f controller 2024-05-28T05:27:16.799Z INFO controller.termination cordoned node {"commit": "xxx-dirty", "node": "ip-10-76-38-71.ap-northeast-2.compute.internal"}
karpenter-6d877b79fc-bjq4f controller 2024-05-28T05:27:24.433Z INFO controller.termination deleted node {"commit": "xxxx-dirty", "node": "ip-xxxx.ap-northeast-2.compute.internal"}
karpenter-6d877b79fc-bjq4f controller 2024-05-28T05:28:15.073Z INFO controller.deprovisioning deprovisioning via consolidation delete, terminating 1 machines ip-xxxx.ap-northeast-2.compute.internal/m7i-flex.xlarge/spot {"commit": "d7e22b1-dirty"}
karpenter-6d877b79fc-bjq4f controller 2024-05-28T05:28:15.112Z INFO controller.termination cordoned node {"commit": "d7e22b1-dirty", "node": "ip-xxxx.ap-northeast-2.compute.internal"}
karpenter-6d877b79fc-bjq4f controller 2024-05-28T05:28:27.657Z INFO controller.termination deleted node {"commit": "xxxx-dirty", "node": "ip-xxxx.ap-northeast-2.compute.internal"}
적용 후
karpenter-dc946fdf9-2q8fn controller {"level":"INFO","time":"2024-05-30T02:56:04.309Z","logger":"controller.interruption","message":"starting controller","commit":"e719109"}
(생략)
karpenter-dc946fdf9-2q8fn controller {"level":"INFO","time":"2024-05-30T03:12:19.013Z","logger":"controller.interruption","message":"initiating delete from interruption message","commit":"e719109","queue":"baas-dev-01","messageKind":"SpotInterruptionKind","nodeclaim":"default-2r9k5","action":"CordonAndDrain","node":"ip-10-62-71-224.ap-northeast-2.compute.internal"}
karpenter-dc946fdf9-2q8fn controller {"level":"INFO","time":"2024-05-30T03:12:19.076Z","logger":"controller.node.termination","message":"tainted node","commit":"e719109","node":"ip-10-62-71-224.ap-northeast-2.compute.internal"}
karpenter-dc946fdf9-2q8fn controller {"level":"INFO","time":"2024-05-30T03:12:20.159Z","logger":"controller.provisioner","message":"found provisionable pod(s)","commit":"e719109","pods":"elastic-system/es6-es-es6-2, eventstore/eventstore-4","duration":"89.178932ms"}
로그를 확인하면 기존과 다르게 controller.interruption 이라는 새로운 컨트롤러를 확인할 수 있습니다. 카펜터 interruption 컨트롤러가 AWS SQS에서 Spot 노드 종료 이벤트를 수신하면 노드에 실행 중인 파드를 Graceful 하게 종료하면서 다른 노드로 파드를 이전합니다.
참고로 interruption 컨트롤러는 kubectl drain {NODE_NAME} 명령어를 실행한 것과 동일한 과정을 실행합니다. 먼저 Cordon 명령어로 해당 노드에 새로운 파드가 실행하지 않게하고 Spot 인스턴스가 종료되는 2분 동안 기존 파드가 정상 종료되도록 파드의 graceful shutdown 설정 등을 존중(?)하고 새로운 노드에 기존 파드가 실행하도록 합니다.
(interruption 컨트롤러 없이도 동일한 프로세스일 것 같은데, 아닌 것은 의아합니다.)
2. EKS Add-on CoreDNS 설정을 수정하여 On-Demand 노드에 실행하도록 수정
CoreDNS를 Add-on 방식으로 설치하여도 헬름 등으로 설치한 것과 동일하게 On-Demand 노드에 실행하도록 설정 가능합니다. 그리고 최근에 Add-on으로 CoreDNS 오토스케일링 설정(1)이 가능합니다.
아래 설정을 EKS - Add-on 메뉴의 'Advanced configuration'에 추가합니다.
{
"autoScaling": {
"enabled": true,
"minReplicas": 3,
"maxReplicas": 10
},
"nodeSelector": {
"nodegroup": "on-demand"
}
}
- autoscaling min, max replicas는 임의로 지정할 수 있습니다.
- nodegroup 이름은 각자 변경하면 됩니다.
3. CoreDNS Graceful Shutdown 설정
CoreDNS가 파드 종료(SIGTERM) 시 기존 DNS 요청을 좀 더 안정적으로 완료할 수 있도록 lameduck(2) 설정을 5초에서 30초로 변경했습니다. lameduck 설정은 파드의 graceful shutdown 설정과 동일합니다.
아래와 같이 ConfigMap의 lameduck 설정을 변경하면 됩니다.
$ kubectl describe cm coredns -n kube-system
Name: coredns
Namespace: kube-system
Labels: eks.amazonaws.com/component=coredns
k8s-app=kube-dns
Annotations: <none>
Data
====
Corefile:
----
.:53 {
errors
health {
lameduck 30s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
참조
- CoreDNS Autoscaling - https://docs.aws.amazon.com/eks/latest/userguide/coredns-autoscaling.html
- CoreDNS lameduck - https://coredns.io/plugins/health/
'쿠버네티스 일반 > Network' 카테고리의 다른 글
EKS 네트워크 아키텍처 현황 (2) | 2024.07.10 |
---|---|
EKS External DNS - Terraform IRSA + Helm (0) | 2023.06.23 |
gRPC in EKS ALB + aws lb controller (0) | 2023.06.21 |
AWS NLB EKS 환경에서 사용자 IP 파드로 전달 (0) | 2022.09.30 |
Tailscale VPN for 쿠버네티스 & VPC (2) | 2022.09.26 |