diff --git a/content/reliability/docs/application.ko.md b/content/reliability/docs/application.ko.md new file mode 100644 index 000000000..15967f545 --- /dev/null +++ b/content/reliability/docs/application.ko.md @@ -0,0 +1,368 @@ +# 고가용성 애플리케이션 실행 + +고객은 애플리케이션을 변경할 때나 트래픽이 급증할 때 조차 애플리케이션이 항상 사용 가능하기를 기대합니다. 확장 가능하고 복원력이 뛰어난 아키텍처를 통해 애플리케이션과 서비스를 중단 없이 실행하여 사용자 만족도를 유지할 수 있습니다. 확장 가능한 인프라는 비즈니스 요구 사항에 따라 확장 및 축소됩니다. 단일 장애 지점을 제거하는 것은 애플리케이션의 가용성을 개선하고 복원력을 높이기 위한 중요한 단계입니다. + +쿠버네티스를 사용하면 가용성과 복원력이 뛰어난 방식으로 애플리케이션을 운영하고 실행할 수 있습니다. 선언적 관리를 통해 애플리케이션을 설정한 후에는 쿠버네티스가 지속적으로 [현재 상태를 원하는 상태와 일치](https://kubernetes.io/docs/concepts/architecture/controller/#desired-vs-current)하도록 시도할 수 있습니다. + +## 권장 사항 + +### 싱글톤 파드를 실행하지 마세요 + +전체 애플리케이션이 단일 파드에서 실행되는 경우, 해당 파드가 종료되면 애플리케이션을 사용할 수 없게 됩니다. 개별 포드를 사용하여 애플리케이션을 배포하는 대신 [디플로이먼트](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)를 생성하십시오. 디플로이먼트로 생성된 파드가 실패하거나 종료되는 경우, 디플로이먼트 [컨트롤러](https://kubernetes.io/docs/concepts/architecture/controller/)는 새 파드를 시작하여 지정된 개수의 레플리카 파드가 항상 실행되도록 합니다. + +### 여러 개의 레플리카 실행 + +디플로이먼트를 사용하여 앱의 여러 복제본 파드를 실행하면 가용성이 높은 방식으로 앱을 실행할 수 있습니다. 하나의 복제본에 장애가 발생하더라도 쿠버네티스가 손실을 만회하기 위해 다른 파드를 생성하기 전까지는 용량이 줄어들기는 하지만 나머지 복제본은 여전히 작동한다. 또한 [Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/)를 사용하여 워크로드 수요에 따라 복제본을 자동으로 확장할 수 있습니다. + +### 여러 노드에 복제본을 스케줄링합니다. + +모든 복제본이 동일한 노드에서 실행되고 있고 노드를 사용할 수 없게 되면 여러 복제본을 실행하는 것은 그다지 유용하지 않습니다. 파드 anti-affinity 또는 파드 topology spread contraints을 사용해 디플로이먼트의 복제본을 여러 워커 노드에 분산시키는 것을 고려해 보십시오. + +여러 AZ에서 실행하여 일반적인 애플리케이션의 신뢰성을 더욱 개선할 수 있습니다. + +#### 파드 anti-affinity 규칙 사용 + +아래 매니페스트는 쿠버네티스 스케줄러에게 파드를 별도의 노드와 AZ에 배치하도록 *prefer*라고 지시합니다. 이렇게 되어있다면 별도의 노드나 AZ가 필요하지 않습니다. 그렇게 하면 각 AZ에서 실행 중인 포드가 있으면 쿠버네티스가 어떤 파드도 스케줄링할 수 없기 때문입니다. 애플리케이션에 단 세 개의 복제본이 필요한 경우, `topologyKey: topology.kubernetes.io/zone`에 대해 `requiredDuringSchedulingIgnoredDuringExecution`를 사용할 수 있으며, 쿠버네티스 스케줄러는 동일한 AZ에 두 개의 파드를 스케줄링하지 않습니다. + +``` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spread-host-az + labels: + app: web-server +spec: + replicas: 4 + selector: + matchLabels: + app: web-server + template: + metadata: + labels: + app: web-server + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - web-server + topologyKey: topology.kubernetes.io/zone + weight: 100 + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - web-server + topologyKey: kubernetes.io/hostname + weight: 99 + containers: + - name: web-app + image: nginx:1.16-alpine +``` + +#### 포드 topology spread constraints 사용 + +포드 anti-affinity 규칙과 마찬가지로, 포드 topology spread constraints을 사용하면 호스트 또는 AZ와 같은 다양한 장애 (또는 토폴로지) 도메인에서 애플리케이션을 사용할 수 있습니다. 이 접근 방식은 서로 다른 토폴로지 도메인 각각에 여러 복제본을 보유하여 내결함성과 가용성을 보장하려는 경우에 매우 효과적입니다. 반면, 파드 anti-affinity 규칙은 anti-affinity가 있는 파드 서로에 대해 거부 효과가 있기 때문에 토폴로지 도메인에 단일 복제본이 있도록 쉽게 만들 수 있습니다. 이러한 경우 전용 노드의 단일 복제본은 내결함성 측면에서 이상적이지도 않고 리소스를 적절하게 사용하지도 않습니다. topology spread constraints을 사용하면 스케줄러가 토폴로지 도메인 전체에 적용하려고 시도하는 분배 또는 배포를 보다 효과적으로 제어할 수 있습니다. 이 접근 방식에서 사용할 수 있는 몇 가지 중요한 속성은 다음과 같습니다. +1. `MaxSkew`는 토폴로지 도메인 전체에서 균등하지 않게 분산될 수 있는 최대 정도를 제어하거나 결정하는 데 사용됩니다. 예를 들어 애플리케이션에 10개의 복제본이 있고 3개의 AZ에 배포된 경우 균등하게 분산될 수는 없지만 분포의 불균일성에 영향을 미칠 수 있습니다. 이 경우 `MaxSkew`는 1에서 10 사이일 수 있습니다.값이 1이면 3개의 AZ에 걸쳐 `4,3,3`, `3,4,3` 또는 `3,3,4`와 같은 분배가 생성될 수 있습니다. 반대로 값이 10이면 3개의 AZ에 걸쳐 `10,0,0`, `0,10,0` 또는 `0,0,10`과 같은 분배가 나올 수 있다는 의미입니다. +2. `TopologyKey`는 노드 레이블 중 하나의 키이며 포드 배포에 사용해야 하는 토폴로지 도메인 유형을 정의합니다. 예를 들어 존(zone)별 분배는 다음과 같은 키-값 쌍을 가집니다. +``` +topologyKey: "topology.kubernetes.io/zone" +``` +3. `WhenUnsatisfiable` 속성은 원하는 제약 조건을 충족할 수 없는 경우 스케줄러가 어떻게 응답할지 결정하는 데 사용됩니다. +4. `LabelSelector`는 일치하는 파드를 찾는 데 사용되며, 이를 통해 스케줄러는 지정한 제약 조건에 따라 파드를 배치할 위치를 결정할 때 이를 인지할 수 있습니다. + +위의 필드 외에도, 다른 필드에 대해서는 [쿠버네티스 설명서](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)에서 더 자세히 알아볼 수 있습니다. + +![포드 토폴로지는 제약 조건을 3개 AZ에 분산시킵니다.](./images/pod-topology-spread-constraints.jpg) + +``` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: spread-host-az + labels: + app: web-server +spec: + replicas: 10 + selector: + matchLabels: + app: web-server + template: + metadata: + labels: + app: web-server + spec: + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: "topology.kubernetes.io/zone" + whenUnsatisfiable: ScheduleAnyway + labelSelector: + matchLabels: + app: express-test + containers: + - name: web-app + image: nginx:1.16-alpine +``` + +### 쿠버네티스 메트릭 서버 실행 + +쿠버네티스 [메트릭 서버](https://github.com/kubernetes-sigs/metrics-server) 를 설치하면 애플리케이션 확장에 도움이 됩니다. [HPA](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) 및 [VPA](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler)와 같은 쿠버네티스 오토스케일러 애드온은 애플리케이션의 메트릭을 추적하여 애플리케이션을 확장합니다. 메트릭 서버는 규모 조정 결정을 내리는 데 사용할 수 있는 리소스 메트릭을 수집합니다. 메트릭은 kubelets에서 수집되어 [메트릭 API 형식](https://github.com/kubernetes/metrics)으로 제공됩니다. + +메트릭 서버는 데이터를 보관하지 않으며 모니터링 솔루션도 아닙니다. 그 목적은 CPU 및 메모리 사용량 메트릭을 다른 시스템에 공개하는 것입니다. 시간 경과에 따른 애플리케이션 상태를 추적하려면 Prometheus 또는 Amazon CloudWatch와 같은 모니터링 도구가 필요합니다. + +[EKS 설명서](https://docs.aws.amazon.com/eks/latest/userguide/metrics-server.html)에 따라 EKS 클러스터에 메트릭 서버를 설치하십시오. + +## Horizontal Pod Autoscaler (HPA) + +HPA는 수요에 따라 애플리케이션을 자동으로 확장하고 트래픽이 최고조에 달할 때 고객에게 영향을 미치지 않도록 도와줍니다. 쿠버네티스에는 제어 루프로 구현되어 있어 리소스 메트릭을 제공하는 API에서 메트릭을 정기적으로 쿼리합니다. + +HPA는 다음 API에서 메트릭을 검색할 수 있습니다. +1. 리소스 메트릭 API라고도 하는 `metrics.k8s.io` — 파드의 CPU 및 메모리 사용량을 제공합니다. +2. `custom.metrics.k8s.io` — 프로메테우스와 같은 다른 메트릭 콜렉터의 메트릭을 제공합니다. 이러한 메트릭은 쿠버네티스 클러스터에 __internal__ 입니다. +3. `external.metrics.k8s.io` — 쿠버네티스 클러스터에 __external__인 메트릭을 제공합니다 (예: SQS 대기열 길이, ELB 지연 시간). + +애플리케이션을 확장하기 위한 메트릭을 제공하려면 이 세 가지 API 중 하나를 사용해야 합니다. + +### 사용자 지정 또는 외부 지표를 기반으로 애플리케이션 규모 조정 + +사용자 지정 또는 외부 지표를 사용하여 CPU 또는 메모리 사용률 이외의 지표에 따라 애플리케이션을 확장할 수 있습니다.[커스텀 메트릭](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/custom-metrics-api.md) API 서버는 HPA가 애플리케이션을 자동 스케일링하는 데 사용할 수 있는 `custom-metrics.k8s.io` API를 제공합니다. + +[쿠버네티스 메트릭 API용 프로메테우스 어댑터](https://github.com/directxman12/k8s-prometheus-adapter)를 사용하여 프로메테우스에서 메트릭을 수집하고 HPA에서 사용할 수 있습니다. 이 경우 프로메테우스 어댑터는 프로메테우스 메트릭을 [메트릭 API 형식](https://github.com/kubernetes/metrics/blob/master/pkg/apis/metrics/v1alpha1/types.go)으로 노출합니다. 모든 커스텀 메트릭 구현 목록은 [쿠버네티스 설명서](https://github.com/kubernetes/metrics/blob/master/IMPLEMENTATIONS.md#custom-metrics-api)에서 확인할 수 있습니다. + +프로메테우스 어댑터를 배포한 후에는 kubectl을 사용하여 사용자 지정 메트릭을 쿼리할 수 있습니다. +`kubectl get —raw /apis/custom.metrics.k8s.io/v1beta1/ ` + +[외부 메트릭](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/instrumentation/external-metrics-api.md)은 이름에서 알 수 있듯이 Horizontal Pod Autoscaler에 쿠버네티스 클러스터 외부의 메트릭을 사용하여 배포를 확장할 수 있는 기능을 제공합니다. 예를 들어 배치 처리 워크로드에서는 SQS 대기열에서 진행 중인 작업 수에 따라 복제본 수를 조정하는 것이 일반적입니다. + +예를 들어 [SQS 대기열 깊이에 따라 배치-프로세서 애플리케이션 크기 조정](https://github.com/awslabs/k8s-cloudwatch-adapter/blob/master/samples/sqs/README.md)과 같이 CloudWatch 지표를 사용하여 디플로이먼트를 자동 확장하려면 [`k8s-cloudwatch-adapter`](https://github.com/awslabs/k8s-cloudwatch-adapter)를 사용할 수 있습니다. `k8s-클라우드워치 어댑터`는 커뮤니티 프로젝트이며 AWS에서 유지 관리하지 않습니다. + +## Vertical Pod Autoscaler (VPA) + +VPA는 파드의 CPU 및 메모리 예약을 자동으로 조정하여 애플리케이션을 “적절한 크기”로 조정할 수 있도록 합니다. 리소스 할당을 늘려 수직으로 확장해야 하는 애플리케이션의 경우 [VPA](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler)를 사용하여 포드 복제본을 자동으로 확장하거나 규모 조정 권장 사항을 제공할 수 있습니다. + +VPA의 현재 구현은 파드에 대한 인플레이스 조정을 수행하지 않고 대신 스케일링이 필요한 파드를 다시 생성하기 때문에 VPA가 애플리케이션을 확장해야 하는 경우 애플리케이션을 일시적으로 사용할 수 없게 될 수 있습니다. + +[EKS 설명서](https://docs.aws.amazon.com/eks/latest/userguide/vertical-pod-autoscaler.html)에는 VPA 설정 방법이 수록되어 있습니다. + +[Fairwinds Goldilocks](https://github.com/FairwindsOps/goldilocks/) 프로젝트는 CPU 및 메모리 요청 및 제한에 대한 VPA 권장 사항을 시각화할 수 있는 대시보드를 제공합니다. VPA 업데이트 모드를 사용하면 VPA 권장 사항에 따라 파드를 자동 확장할 수 있습니다. + +## 애플리케이션 업데이트 + +최신 애플리케이션에는 높은 수준의 안정성과 가용성을 갖춘 빠른 혁신이 필요합니다. 쿠버네티스는 고객에게 영향을 주지 않으면서 애플리케이션을 지속적으로 업데이트할 수 있는 도구를 제공합니다. + +가용성 저하 없이 변경 사항을 신속하게 배포할 수 있는 몇 가지 모범 사례를 살펴보겠습니다. + +### 롤백을 수행할 수 있는 메커니즘 마련 + +실행 취소 버튼이 있으면 재해를 피할 수 있습니다. 프로덕션 클러스터를 업데이트하기 전에 별도의 하위 환경(테스트 또는 개발 환경)에서 배포를 테스트하는 것이 가장 좋습니다. CI/CD 파이프라인을 사용하면 배포를 자동화하고 테스트하는 데 도움이 될 수 있습니다. 지속적 배포 파이프라인을 사용하면 업그레이드에 결함이 발생할 경우 이전 버전으로 빠르게 되돌릴 수 있습니다. + +디플로이먼트를 사용하여 실행 중인 애플리케이션을 업데이트할 수 있습니다. 이는 일반적으로 컨테이너 이미지를 업데이트하여 수행됩니다. `kubectl`을 사용하여 다음과 같이 디플로이먼트를 업데이트할 수 있습니다. + +```bash +kubectl --record deployment.apps/nginx-deployment set image nginx-deployment nginx=nginx:1.16.1 +``` + +`--record` 인수는 디플로이먼트의 변경 사항을 기록하고 롤백을 수행해야 하는 경우 도움이 됩니다. `kubectl rollout history deployment`는 클러스터의 디플로이먼트에 대해 기록된 변경 사항을 보여준다. `kubectl rollout undo deployment `을 사용하여 변경사항을 롤백할 수 있습니다. + +기본적으로, 파드를 재생성해야 하는 디플로이먼트를 업데이트하면 디플로이먼트는 [롤링 업데이트](https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/)를 수행합니다. 즉, 쿠버네티스는 디플로이먼트에서 실행 중인 파드의 일부만 업데이트하고 모든 파드는 한 번에 업데이트하지 않습니다. `RollingUpdateStrategy` 프로퍼티를 통해 쿠버네티스가 롤링 업데이트를 수행하는 방식을 제어할 수 있습니다. + +디플로이먼트의 *롤링 업데이트*를 수행할 때, [`Max Unavailable`](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#max-unavailable) 프로퍼티를 사용하여 업데이트 중에 사용할 수 없는 파드의 최대 개수를 지정할 수 있습니다. 디플로이먼트의 `Max Surge` 프로퍼티를 사용하면 원하는 파드 수보다 더 생성할 수 있는 최대 파드 수를 설정할 수 있습니다. + +롤아웃으로 인해 고객이 혼란에 빠지지 않도록 `max unavailable`을 조정하는 것을 고려해 보십시오. 예를 들어 쿠버네티스는 기본적으로 25%의 `max unavailable`을 설정합니다. 즉, 100개의 파드가 있는 경우 롤아웃 중에 활성 상태로 작동하는 파드는 75개만 있을 수 있습니다. 애플리케이션에 최소 80개의 파드가 필요한 경우 이 롤아웃으로 인해 중단이 발생할 수 있습니다. 대신, `max unavailable`을 20% 로 설정하여 롤아웃 내내 작동하는 파드가 80개 이상 있도록 할 수 있습니다. + +### 블루/그린 배포 사용 + +변경은 본질적으로 위험하지만, 취소할 수 없는 변경은 잠재적으로 치명적일 수 있습니다. *롤백*을 통해 시간을 효과적으로 되돌릴 수 있는 변경 절차를 사용하면 향상된 기능과 실험이 더 안전해집니다. 블루/그린 배포는 문제가 발생할 경우 변경 사항을 신속하게 철회할 수 있는 방법을 제공합니다. 이 배포 전략에서는 새 버전을 위한 환경을 만듭니다. 이 환경은 업데이트 중인 애플리케이션의 현재 버전과 동일합니다. 새 환경이 프로비전되면 트래픽이 새 환경으로 라우팅됩니다. 새 버전에서 오류가 발생하지 않고 원하는 결과를 얻을 경우 이전 환경은 종료됩니다. 그렇지 않으면 트래픽이 이전 버전으로 복원됩니다. + +기존 버전의 디플로이먼트와 동일한 새 디플로이먼트를 생성하여 쿠버네티스에서 블루/그린 디플로이먼트를 수행할 수 있습니다. 새 디플로이먼트의 파드가 오류 없이 실행되고 있는지 확인했으면, 트래픽을 애플리케이션의 파드로 라우팅하는 서비스의 `selector` 스펙을 변경하여 새 디플로이먼트로 트래픽을 보내기 시작할 수 있습니다. + +[Flux](https://fluxcd.io), [Jenkins](https://www.jenkins.io), [Spinnaker](https://spinnaker.io)와 같은 많은 지속적 통합(CI) 도구를 사용하면 블루/그린 배포를 자동화할 수 있습니다. 쿠버네티스 블로그에는 Jenkins를 사용한 단계별 설명이 포함되어 있습니다: [Jenkins를 사용한 쿠버네티스의 제로 다운타임 배포](https://kubernetes.io/blog/2018/04/30/zero-downtime-deployment-kubernetes-jenkins/) + +### Canary 디플로이먼트 사용하기 + +Canary 배포는 블루/그린 배포의 변형으로, 변경으로 인한 위험을 크게 제거할 수 있습니다. 이 배포 전략에서는 기존 디플로이먼트와 함께 더 적은 수의 파드가 포함된 새 디플로이먼트를 생성하고 소량의 트래픽을 새 디플로이먼트로 전환하는 것입니다. 지표에서 새 버전이 기존 버전과 같거나 더 나은 성능을 보인다면, 새 디플로이먼트로 향하는 트래픽을 점진적으로 늘리면서 모든 트래픽이 새 디플로이먼트로 전환될 때까지 규모를 늘립니다. 만약 문제가 발생하면 모든 트래픽을 이전 디플로이먼트로 라우팅하고 새 디플로이먼트로의 트래픽 전송을 중단할 수 있습니다. + +쿠버네티스는 canary 배포를 수행하는 기본 방법을 제공하지 않지만, [Flagger](https://github.com/weaveworks/flagger)와 같은 도구를 [Istio](https://docs.flagger.app/tutorials/istio-progressive-delivery) 또는 [App Mesh](https://docs.flagger.app/install/flagger-install-on-eks-appmesh)와 함께 사용할 수 있다. + + +## 상태 점검 및 자가 복구 + +버그가 없는 소프트웨어는 없지만 쿠버네티스를 사용하면 소프트웨어 오류의 영향을 최소화할 수 있습니다. 과거에는 애플리케이션이 충돌하면 누군가 애플리케이션을 수동으로 다시 시작하여 상황을 해결해야 했습니다. 쿠버네티스를 사용하면 파드의 소프트웨어 장애를 감지하고 자동으로 새 복제본으로 교체할 수 있습니다. 쿠버네티스를 사용하면 애플리케이션의 상태를 모니터링하고 비정상 인스턴스를 자동으로 교체할 수 있습니다. + +쿠버네티스는 세 가지 유형의 [상태 검사](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/)를 지원합니다. + +1. Liveness probe +2. Startup probe (쿠버네티스 버전 1.16 이상에서 지원) +3. Readiness probe + +쿠버네티스 에이전트인 [Kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)은 위에서 언급한 모든 검사를 실행할 책임이 있습니다. Kubelet은 세 가지 방법으로 파드의 상태를 확인할 수 있습니다. kubelet은 파드의 컨테이너 내에서 셸 명령을 실행하거나, 컨테이너에 HTTP GET 요청을 보내거나, 지정된 포트에 TCP 소켓을 열 수 있습니다. + +컨테이너 내에서 셸 스크립트를 실행하는 `exec` 기반 프로브를 선택하는 경우, `TimeoutSeconds` 값이 만료되기 *전에* 셸 명령어가 종료되는지 확인하십시오. 그렇지 않으면 노드에 노드 장애를 일으키는 `` 프로세스가 생깁니다. + +## 권장 사항 +### Liveness Probe를 사용하여 비정상 파드 제거 + +Liveness probe는 프로세스가 계속 실행되지만 애플리케이션이 응답하지 않는 *교착* 상태를 감지할 수 있습니다. 예를 들어 포트 80에서 수신 대기하는 웹 서비스를 실행 중인 경우 파드의 포트 80에서 HTTP GET 요청을 보내도록 Liveness 프로브를 구성할 수 있습니다. Kubelet은 주기적으로 GET 요청을 파드에 보내고 응답을 기다립니다. 파드가 200-399 사이에서 응답하면 kubelet은 파드가 정상이라고 간주하고, 그렇지 않으면 파드는 비정상으로 표시됩니다. 파드가 상태 체크에 계속 실패하면 kubelet은 파드를 종료합나다. + +`initialDelaySeconds`를 사용하여 첫 번째 프로브를 지연시킬 수 있습니다. + +Liveness Probe를 사용할 때는 모든 파드가 동시에 Liveness Probe에 실패하는 상황이 발생하지 않도록 해야 합니다. 쿠버네티스는 모든 파드를 교체하려고 시도하여 애플리케이션을 오프라인으로 전환하기 때문입니다. 게다가 쿠버네티스는 계속해서 새로운 파드를 만들지만 Liveness Probe도 실패할 것이기 때문에 컨트롤 플레인에 불필요한 부담을 줍니다. 파드 외부 요소(예: 외부 데이터베이스)에 의존하도록 Liveness Probe를 구성하지 마십시오. 다시 말해, 파드 외부 데이터베이스가 응답하지 않는다고 해서 파드가 Liveness Probe에 실패하는 일이 있어서는 안 됩니다. + +Sandor Szücs의 게시물 [활성 프로브는 위험하다](https://srcco.de/posts/kubernetes-liveness-probes-are-dangerous.html)에서는 잘못 구성된 프로브로 인해 발생할 수 있는 문제를 설명합니다. + +### 시작하는 데 시간이 오래 걸리는 어플리케이션에는 Startup Probe를 사용하십시오. + +앱을 시작하는 데 추가 시간이 필요한 경우 Startup Probe를 사용하여 Liveness 및 Readniness Probe를 지연시킬 수 있습니다. 예를 들어 데이터베이스로 부터 데이터를 캐싱해야 하는 Java 앱이 제대로 작동하려면 최대 2분이 걸릴 수 있습니다. 완전히 작동하기 전까지는 모든 Liveness 또는 Readniness Probe가 실패할 수 있습니다. Startup Probe를 구성하면 Liveness 또는 Readniness Probe를 실행하기 전에 Java 앱을 *정상*상태로 만들 수 있습니다. + +Startup Probe가 성공할 때까지 다른 모든 프로브는 비활성화됩니다. 쿠버네티스가 애플리케이션 시작을 위해 대기해야 하는 최대 시간을 정의할 수 있습니다. 최대 구성 시간이 지난 후에도 파드가 여전히 스타트업 프로브에 실패하면 파드는 종료되고 새 파드가 생성됩니다. + +Startup Probe는 Liveness Probe와 비슷합니다. 즉, 실패하면 파드가 다시 생성됩니다. Ricardo A.가 자신의 글 [환상적인 프로브 및 구성 방법](https://medium.com/swlh/fantastic-probes-and-how-to-configure-them-fef7e030bd2f)에서 설명했듯이, 애플리케이션 시작 시간을 예측할 수 없는 경우에는 Startup Probe를 사용해야 합니다. 애플리케이션을 시작하는 데 10초가 걸린다는 것을 알고 있다면 대신 `initialDelaySeconds`와 함께 Liveness/Readiness Probe를 사용해야 합니다. + +### Readiness Probe를 사용하여 부분적으로 사용할 수 없는 상태를 감지하세요 + +Liveness probe는 파드 종료(즉, 앱 재시작)를 통해 해결되는 앱 장애를 감지하는 반면, Readiness Probe는 앱을 _temporarily_ 사용할 수 없는 상태를 감지합니다. 이러한 상황에서는 앱이 일시적으로 응답하지 않을 수 있지만 이 작업이 완료되면 다시 정상이 될 것으로 예상됩니다. + +예를 들어, 집중적인 디스크 I/O 작업 중에는 애플리케이션이 일시적으로 요청을 처리할 수 없을 수 있습니다. 여기서 애플리케이션의 파드를 종료하는 것은 해결책이 아니며, 동시에 파드로 전송된 추가 요청이 실패할 수 있습니다. + +Readiness Probe를 사용하여 앱의 일시적인 가용성 중단을 감지하고 다시 작동할 때까지 해당 파드에 대한 요청 전송을 중단할 수 있습니다. *실패로 인해 파드가 재생성되는 Liveness Probe와 달리, Readiness Probe가 실패하면 파드는 쿠버네티스 서비스로부터 어떠한 트래픽도 수신하지 않게 됩니다*. Readiness Probe가 성공하면 파드는 서비스로부터 트래픽을 다시 수신합니다. + +Liveness Probe와 마찬가지로 파드 외부의 리소스(예: 데이터베이스)에 의존하는 Readiness Probe를 구성하지 마십시오. 다음은 잘못 구성된 Readiness로 인해 애플리케이션이 작동하지 않을 수 있는 시나리오입니다. 앱의 데이터베이스에 연결할 수 없을 때 파드의 Readiness Probe에 장애가 발생하면 다른 파드 복제본도 동일한 상태 점검 기준을 공유하므로 동시에 실패합니다. 이러한 방식으로 프로브를 설정하면 데이터베이스를 사용할 수 없을 때마다 파드의 Readiness Probe가 실패하고 쿠버네티스가 *all* 파드로 트래픽 전송을 중지할 수 있습니다. + +Readiness Probes 사용의 부작용은 디플로이먼트를 업데이트하는 데 걸리는 시간을 늘릴 수 있다는 것입니다. Readiness Probe가 성공하지 않는 한 새 복제본은 트래픽을 수신하지 않습니다. 그때까지는 기존 복제본이 계속해서 트래픽을 수신하게 됩니다. + +--- + +## 장애 처리 + +파드의 수명은 유한합니다. - 파드를 오래 실행하더라도 때가 되면 파드가 올바르게 종료되도록 하는 것이 현명합니다. 업그레이드 전략에 따라 쿠버네티스 클러스터를 업그레이드하려면 새 워커 노드를 생성해야 할 수 있으며, 이 경우 모든 파드를 새 노드에서 다시 생성해야 합니다. 적절한 종료 처리 및 파드 중단 예산을 마련하면 파드가 이전 노드에서 제거되고 새 노드에서 재생성될 때 서비스 중단을 피할 수 있습니다. + +워커 노드를 업그레이드하는 가장 좋은 방법은 새 워커 노드를 만들고 기존 워커 노드를 종료하는 것입니다. 워커 노드를 종료하기 전에 먼저 워커 노드를 `drain` 해야 합니다. 워커 노드가 비워지면 해당 노드의 모든 포드가 *안전하게* 제거됩니다. 여기서 가장 중요한 단어는 안전입니다. 워커 노드에서 파드가 제거되면 단순히 `SIGKILL` 시그널이 전송되는 것이 아닙니다. 대신, `SIGTERM` 신호가 제거되는 파드에 있는 각 컨테이너의 메인 프로세스(PID 1)로 보내진다. `SIGTERM` 신호가 전송된 후, 쿠버네티스는 프로세스에 `SIGKILL` 신호가 전송되기까지 일정 시간(유예 기간)을 줍니다. 이 유예 기간은 기본적으로 30초입니다. kubectl에서 `grace-period` 플래그를 사용하여 기본값을 재정의하거나 Podspec에서 `terminationGracePeriodSeconds`를 선언할 수 있습니다. + +`kubectl delete pod —grace-period=` + +메인 프로세스에 PID 1이 없는 컨테이너를 사용하는 것이 일반적입니다. 다음과 같은 Python 기반 샘플 컨테이너를 고려해 보십시오. + +``` +$ kubectl exec python-app -it ps + PID USER TIME COMMAND + 1 root 0:00 {script.sh} /bin/sh ./script.sh + 5 root 0:00 python app.py +``` + +이 예제에서 셸 스크립트는 `SIGTERM`을 수신하는데, 이 예제의 메인 프로세스는 파이썬 응용 프로그램이지만 `SIGTERM` 신호를 받지 않습니다. 파드가 종료되면, 파이썬 애플리케이션이 갑자기 종료됩니다. 이 문제는 컨테이너의 [`ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint)를 변경하여 파이썬 애플리케이션을 실행함으로써 해결할 수 있습니다. 또는 [dumb-init](https://github.com/Yelp/dumb-init)과 같은 도구를 사용하여 애플리케이션이 신호를 처리할 수 있도록 할 수 있습니다. + +[컨테이너 후크](https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/#container-hooks)를 사용하여 컨테이너 시작 또는 중지 시 스크립트 또는 HTTP 요청을 실행할 수도 있습니다. `Prestop` 후크 액션은 컨테이너가 `SIGTERM` 신호를 수신하기 전에 실행되며 이 신호가 전송되기 전에 완료되어야 합니다. `terminationGracePeriodSeconds` 값은 `SIGTERM` 신호가 전송될 때가 아니라 `PreStop` 후크 액션이 실행되기 시작할 때부터 적용됩니다. + +## 권장 사항 + +### Pod Disruption Budget으로 중요한 워크로드를 보호하세요 + +Pod Disruption Budget 또는 PDB는 애플리케이션의 복제본 수가 선언된 임계값 아래로 떨어지면 제거 프로세스를 일시적으로 중단할 수 있습니다. 사용 가능한 복제본 수가 임계값을 초과하면 제거 프로세스가 계속됩니다. PDB를 사용하여 복제본의 `minAvailable` 및 `maxUnavailable` 수를 선언할 수 있습니다. 예를 들어 앱 복제본을 3개 이상 사용할 수 있게 하려면 PDB를 만들 수 있습니다. + +``` +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: my-svc-pdb +spec: + minAvailable: 3 + selector: + matchLabels: + app: my-svc +``` + +위의 PDB 정책은 쿠버네티스에게 3개 이상의 복제본을 사용할 수 있을 때까지 제거 프로세스를 중단하도록 지시합니다. 노드 드레이닝은 `PodDisruptionBudgets`을 고려합니다. EKS 관리형 노드 그룹 업그레이드 중에는 [15분 타임아웃으로 노드가 고갈됩니다](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-update-behavior.html). 15분 후 업데이트를 강제 실행하지 않으면(EKS 콘솔에서는 롤링 업데이트라고 함) 업데이트가 실패합니다. 업데이트를 강제로 적용하면 파드가 삭제됩니다. + +자체 관리형 노드의 경우 [AWS Node Termination Handler](https://github.com/aws/aws-node-termination-handler)와 같은 도구를 사용할 수도 있습니다. 이 도구를 사용하면 Kubernetes 컨트롤 플레인이 [EC2 유지 관리](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/monitoring-instances-status-check_sched.html) 이벤트 및 [EC2 스팟 중단](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-interruptions.html) 등 EC2 인스턴스를 사용할 수 없게 될 수 있는 이벤트에 적절하게 대응합니다. 쿠버네티스 API를 사용하여 노드를 비우고 새 파드가 스케줄되지 않도록 한 다음, 파드를 드레이닝하여 실행 중인 파드를 종료한다. + +파드 anti-affinity를 사용해 디플로이먼트의 파드를 다른 노드에 스케줄링하고 노드 업그레이드 중 PDB 관련 지연을 피할 수 있습니다. + +### 카오스 엔지니어링 연습 +> 카오스 엔지니어링은 프로덕션에서의 격렬한 조건을 견딜 수 있는 시스템의 성능에 대한 신뢰를 구축하기 위해 분산 시스템을 실험하는 분야입니다. + +Dominik Tornow는 자신의 블로그 [쿠버네티스는 선언적 시스템](https://medium.com/@dominik.tornow/the-mechanics-of-kubernetes-ac8112eaa302)에서 “*사용자가 원하는 시스템 상태를 시스템에 표시합니다. 그런 다음 시스템은 현재 상태와 원하는 상태를 고려하여 현재 상태에서 원하는 상태로 전환하기 위한 명령 순서를 결정합니다.*”라고 설명합니다. 즉, 쿠버네티스는 항상 *원하는 상태*를 저장하고 시스템이 이를 벗어나면 쿠버네티스는 상태를 복원하기 위한 조치를 취합니다. 예를 들어 워커 노드를 사용할 수 없게 되면 쿠버네티스는 파드를 다른 워커 노드로 다시 스케줄합니다. 마찬가지로, `replica`가 충돌하면 [디플로이먼트 컨트롤러](https://kubernetes.io/docs/concepts/architecture/controller/#design)가 새 `replica`를 생성합니다. 이런 방식으로 쿠버네티스 컨트롤러는 장애를 자동으로 수정합니다. + +[Gremlin](https://www.gremlin.com)과 같은 카오스 엔지니어링 도구를 사용하면 쿠버네티스 클러스터의 복원력을 테스트하고 단일 장애 지점을 식별할 수 있습니다. 클러스터(및 그 이상)에 인위적인 혼돈을 유발하는 도구를 사용하면 시스템 약점을 발견하고 병목 현상과 잘못된 구성을 식별하며 통제된 환경에서 문제를 수정할 수 있습니다. 카오스 엔지니어링 철학은 의도적으로 문제를 해결하고 인프라에 스트레스를 주어 예상치 못한 다운타임을 최소화하는 것을 권장합니다. + +### 서비스 메시 사용 + +서비스 메시를 사용하여 애플리케이션의 복원력을 개선할 수 있습니다. 서비스 메시는 서비스 간 통신을 가능하게 하고 마이크로서비스 네트워크의 가시성을 높입니다. 대부분의 서비스 메시 제품은 애플리케이션의 네트워크 트래픽을 가로채고 검사하는 소규모 네트워크 프록시를 각 서비스와 함께 실행하는 방식으로 작동합니다. 애플리케이션을 수정하지 않고도 애플리케이션을 메시에 배치할 수 있습니다. 서비스 프록시에 내장된 기능을 사용하여 네트워크 통계를 생성하고, 액세스 로그를 생성하고, 분산 추적을 위한 아웃바운드 요청에 HTTP 헤더를 추가하도록 할 수 있습니다. + +서비스 메시를 사용하면 자동 요청 재시도, 제한 시간, 회로 차단, 속도 제한과 같은 기능을 통해 마이크로서비스의 복원력을 높일 수 있습니다. + +여러 클러스터를 운영하는 경우 서비스 메시를 사용하여 클러스터 간 서비스 간 통신을 활성화할 수 있습니다. + +### 서비스 메시 ++ [AWS App Mesh](https://aws.amazon.com/app-mesh/) ++ [Istio](https://istio.io) ++ [LinkerD](http://linkerd.io) ++ [Consul](https://www.consul.io) + +--- + +## Observability + +Observability는 모니터링, 로깅, 추적을 포함하는 포괄적인 용어입니다. 마이크로서비스 기반 애플리케이션은 기본적으로 배포됩니다. 단일 시스템을 모니터링하는 것으로 충분한 모놀리식 애플리케이션과 달리 분산 애플리케이션 아키텍처에서는 각 구성 요소의 성능을 모니터링해야 합니다. 클러스터 수준 모니터링, 로깅 및 분산 추적 시스템을 사용하여 고객이 중단되기 전에 클러스터의 문제를 식별할 수 있습니다. + +문제 해결 및 모니터링을 위한 쿠버네티스 내장 도구는 제한적입니다. 메트릭 서버는 리소스 메트릭을 수집하여 메모리에 저장하지만 유지하지는 않습니다. kubectl을 사용하여 파드의 로그를 볼 수 있지만, 쿠버네티스는 로그를 자동으로 보관하지 않습니다. 그리고 분산 추적 구현은 애플리케이션 코드 수준에서 또는 서비스 메시를 사용하여 수행됩니다. + +쿠버네티스의 확장성은 여기서 빛을 발합니다. 쿠버네티스를 사용하면 선호하는 중앙 집중식 모니터링, 로깅 및 추적 솔루션을 가져올 수 있습니다. + +## 권장 사항 + +### 애플리케이션 모니터링 + +최신 애플리케이션에서 모니터링해야 하는 지표의 수는 계속 증가하고 있습니다. 애플리케이션을 자동으로 추적하면 고객의 문제를 해결하는데 집중할 수 있어 도움이 됩니다. [Prometheus](https://prometheus.io) 또는 [CloudWatch Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights.html)와 같은 클러스터 전반의 모니터링 도구는 클러스터 및 워크로드를 모니터링하고 문제가 발생할 때 또는 가급적이면 문제가 발생하기 전에 신호를 제공할 수 있습니다. + +모니터링 도구를 사용하면 운영 팀이 구독할 수 있는 알림을 생성할 수 있습니다. 악화 시 가동 중단으로 이어지거나 애플리케이션 성능에 영향을 미칠 수 있는 이벤트에 대해 경보를 활성화하는 규칙을 고려해 보십시오. + +어떤 메트릭을 모니터링해야 할지 잘 모르겠다면 다음 방법에서 영감을 얻을 수 있습니다. + +- [RED method](https://www.weave.works/blog/a-practical-guide-from-instrumenting-code-to-specifying-alerts-with-the-red-method). 요청, 오류, 기간을 나타냅니다. +- [USE method](http://www.brendangregg.com/usemethod.html). 사용률, 포화도, 오류를 나타냅니다. + +Sysdig의 게시물 [쿠버네티스 알림 모범 사례](https://sysdig.com/blog/alerting-kubernetes/)에는 애플리케이션 가용성에 영향을 미칠 수 있는 구성 요소의 포괄적인 목록이 포함되어 있습니다. + +### 프로메테우스 클라이언트 라이브러리를 사용하여 애플리케이션 메트릭을 공개하세요 + +애플리케이션 상태를 모니터링하고 표준 메트릭을 집계하는 것 외에도 [프로메테우스 클라이언트 라이브러리](https://prometheus.io/docs/instrumenting/clientlibs/)를 사용하여 애플리케이션별 사용자 지정 메트릭을 공개하여 애플리케이션의 가시성을 개선할 수 있습니다. + +### 중앙 집중식 로깅 도구를 사용하여 로그를 수집하고 유지합니다. + +EKS 로깅은 컨트롤 플레인 로그와 애플리케이션 로그의 두 가지 범주에 속합니다. EKS 컨트롤 플레인 로깅은 컨트롤 플레인의 감사 및 진단 로그를 계정의 CloudWatch Logs로 직접 제공합니다. 애플리케이션 로그는 클러스터 내에서 실행되는 파드에서 생성되는 로그입니다. 애플리케이션 로그에는 비즈니스 로직 애플리케이션을 실행하는 파드와 CoreDNS, Cluster Autoscaler, Prometheus 등과 같은 쿠버네티스 시스템 컴포넌트에서 생성된 로그가 포함됩니다. + +[EKS는 다섯 가지 유형의 컨트롤 플레인 로그를 제공합니다.](https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html): + +1. 쿠버네티스 API 서버 구성 요소 로그 +2. 감사 +3. 인증자(Authenticator) +4. 컨트롤러 매니저 +5. 스케줄러 + +컨트롤러 관리자 및 스케줄러 로그는 병목 현상 및 오류와 같은 컨트롤 플레인 문제를 진단하는 데 도움이 될 수 있습니다. 기본적으로 EKS 컨트롤 플레인 로그는 CloudWatch Logs로 전송되지 않습니다. 컨트롤 플레인 로깅을 활성화하고 계정의 각 클러스터에 대해 캡처하려는 EKS 컨트롤 플레인 로그의 유형을 선택할 수 있습니다. + +애플리케이션 로그를 수집하려면 클러스터에 [Fluent Bit](http://fluentbit.io), [Fluentd](https://www.fluentd.org) 또는 [CloudWatch Container Insights](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/deploy-container-insights-EKS.html)와 같은 로그 수집 도구를 설치해야 합니다. + +쿠버네티스 로그 애그리게이터 도구는 데몬셋으로 실행되며 노드의 컨테이너 로그를 스크랩합니다. 그러면 애플리케이션 로그가 중앙 집중식 대상으로 전송되어 저장됩니다. 예를 들어 CloudWatch 컨테이너 인사이트는 Fluent Bit 또는 Fluentd를 사용하여 로그를 수집하고 이를 CloudWatch Logs로 전송하여 저장할 수 있습니다. Fluent Bit과 Fluentd는 Elasticsearch 및 InfluxDB와 같은 널리 사용되는 여러 로그 분석 시스템을 지원하므로 Fluent Bit 또는 Fluentd의 로그 구성을 수정하여 로그의 스토리지 백엔드를 변경할 수 있습니다. + + +### 분산 추적 시스템을 사용하여 병목 현상을 식별하십시오. + +일반적인 최신 응용 프로그램에는 네트워크를 통해 구성 요소가 분산되어 있으며 응용 프로그램을 구성하는 각 구성 요소가 제대로 작동하는지에 따라 신뢰성이 달라집니다. 분산 추적 솔루션을 사용하면 요청의 흐름과 시스템이 통신하는 방식을 이해할 수 있습니다. 추적을 통해 애플리케이션 네트워크에서 병목 현상이 발생하는 위치를 파악하고 연쇄적 장애를 일으킬 수 있는 문제를 예방할 수 있습니다. + +애플리케이션에서 추적을 구현하는 방법에는 두 가지가 있습니다. 공유 라이브러리를 사용하여 코드 수준에서 분산 추적을 구현하거나 서비스 메시를 사용할 수 있습니다. + +코드 수준에서 추적을 구현하는 것은 불리할 수 있습니다. 이 메서드에서는 코드를 변경해야 합니다. 다국어 응용 프로그램을 사용하는 경우 이는 더 복잡합니다. 또한 서비스 전체에 걸쳐 또 다른 라이브러리를 유지 관리할 책임도 있습니다. + +[LinkerD](http://linkerd.io), [Istio](http://istio.io), [AWS App Mesh](https://aws.amazon.com/app-mesh/)와 같은 서비스 메시를 사용하면 애플리케이션 코드를 최소한으로 변경하여 애플리케이션에서 분산 추적을 구현할 수 있습니다. 서비스 메시를 사용하여 지표 생성, 로깅 및 추적을 표준화할 수 있습니다. + +[AWS X-Ray](https://aws.amazon.com/xray/), [Jaeger](https://www.jaegertracing.io)와 같은 추적 도구는 공유 라이브러리와 서비스 메시 구현을 모두 지원합니다. + +(공유 라이브러리 및 서비스 메시) 구현을 모두 지원하는 [AWS X-Ray](https://aws.amazon.com/xray/) 또는 [Jaeger](https://www.jaegertracing.io)와 같은 추적 도구를 사용해 보싮시오. 그러면 나중에 서비스 메시를 채택할 때 도구를 전환하지 않아도 됩니다. diff --git a/content/reliability/docs/controlplane.ko.md b/content/reliability/docs/controlplane.ko.md new file mode 100644 index 000000000..1911f5834 --- /dev/null +++ b/content/reliability/docs/controlplane.ko.md @@ -0,0 +1,221 @@ +# EKS 컨트롤 플레인 + +Amazon Elastic Kubernetes Service(EKS)는 자체 쿠버네티스 컨트롤 플레인 또는 워커 노드를 설치, 운영 및 유지 관리할 필요 없이 AWS에서 쉽게 쿠버네티스를 실행할 수 있게 해주는 관리형 쿠버네티스 서비스입니다. 업스트림 쿠버네티스를 실행하며 쿠버네티스 규정 준수 인증을 받았습니다. 이러한 규정 준수를 통해 EKS는 EC2 또는 온프레미스에 설치할 수 있는 오픈 소스 커뮤니티 버전과 마찬가지로 쿠버네티스 API를 지원합니다. 업스트림 쿠버네티스에서 실행되는 기존 애플리케이션은 Amazon EKS와 호환됩니다. + +EKS는 쿠버네티스 컨트롤 플레인 노드의 가용성과 확장성을 자동으로 관리하고 비정상 컨트롤 플레인 노드를 자동으로 대체합니다. + +## EKS 아키텍처 + +EKS 아키텍처는 쿠버네티스 컨트롤 플레인의 가용성과 내구성을 손상시킬 수 있는 단일 장애 지점을 제거하도록 설계되었습니다. + +EKS로 관리되는 쿠버네티스 컨트롤 플레인은 EKS 관리형 VPC 내에서 실행됩니다. EKS 컨트롤 플레인은 쿠버네티스 API 서버 노드, 기타 클러스터로 구성됩니다. API 서버, 스케줄러, `kube-controller-manager`와 같은 구성 요소를 실행하는 쿠버네티스 API 서버 노드는 오토 스케일링 그룹에서 실행됩니다. EKS는 AWS 리전 내의 별개의 가용 영역(AZ)에서 최소 2개의 API 서버 노드를 실행합니다. 마찬가지로 내구성을 위해 etcd 서버 노드도 3개의 AZ에 걸친 자동 크기 조정 그룹에서 실행됩니다. EKS는 각 AZ에서 NAT 게이트웨이를 실행하고, API 서버 및 etcd 서버는 프라이빗 서브넷에서 실행됩니다. 이 아키텍처는 단일 AZ의 이벤트가 EKS 클러스터의 가용성에 영향을 미치지 않도록 합니다. + +새 클러스터를 생성하면 Amazon EKS는 클러스터와 통신하는 데 사용하는 관리형 쿠버네티스 API 서버를 위한 고가용성 엔드포인트를 생성합니다(`kubectl`과 같은 도구 사용). 관리형 엔드포인트는 NLB를 사용하여 쿠버네티스 API 서버의 부하를 분산합니다. 또한 EKS는 워커 노드와의 원활한 통신을 위해 서로 다른 AZ에 두 개의 [ENI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html)를 프로비저닝합니다. + +![EKS 데이터 플레인 네트워크 연결](./images/eks-data-plane-connectivity.jpeg) + +[쿠버네티스 클러스터의 API 서버](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html)는 퍼블릭 인터넷(퍼블릭 엔드포인트 사용) 또는 VPC(EKS 관리 ENI 사용) 또는 둘 다를 통해 연결할 수 있습니다. + +사용자와 워커 노드가 퍼블릭 엔드포인트를 사용하여 API 서버에 연결하든 EKS에서 관리하는 ENI를 사용하든 관계없이 연결을 위한 중복 경로가 있습니다. + +## 권장 사항 + +## 컨트롤 플레인 메트릭 모니터링 + +쿠버네티스 API 메트릭을 모니터링하면 컨트롤 플레인 성능에 대한 통찰력을 얻고 문제를 식별할 수 있습니다. 비정상 컨트롤 플레인은 클러스터 내에서 실행되는 워크로드의 가용성을 손상시킬 수 있습니다. 예를 들어 잘못 작성된 컨트롤러는 API 서버에 과부하를 일으켜 애플리케이션의 가용성에 영향을 미칠 수 있습니다. + +쿠버네티스는 `/metrics` 엔드포인트에서 컨트롤 플레인 메트릭을 노출합니다. + +`kubectl`을 사용하여 노출된 메트릭을 볼 수 있습니다. + +```shell +kubectl get --raw /metrics +``` + +이러한 지표는 [프로메테우스 텍스트 형식](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md)으로 표시됩니다. + +프로메테우스를 사용하여 이러한 지표를 수집하고 저장할 수 있습니다. 2020년 5월, CloudWatch는 CloudWatch Container Insights에 프로메테우스 지표 모니터링에 대한 지원을 추가했습니다. 따라서 Amazon CloudWatch를 사용하여 EKS 컨트롤 플레인을 모니터링할 수도 있습니다. [새 Prometheus 스크랩 대상 추가 자습서: 프로메테우스 KPI 서버 지표](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights-Prometheus-Setup-configure.html#ContainerInsights-Prometheus-Setup-new-exporters)를 사용하여 지표를 수집하고 CloudWatch 대시보드를 생성하여 클러스터의 컨트롤 플레인을 모니터링할 수 있습니다. + +쿠버네티스 API 서버 메트릭은 [여기](https://github.com/kubernetes/apiserver/blob/master/pkg/endpoints/metrics/metrics.go)에서 찾을 수 있습니다. 예를 들어, `apiserver_request_duration_seconds`는 API 요청을 실행하는 데 걸리는 시간을 나타낼 수 있습니다. + +다음과 같은 컨트롤 플레인 메트릭을 모니터링해 보십시오. + +### API 서버 + +| 메트릭 | 설명 | +|: --|: --| +| `apiserver_request_total` | 각 메소드, 드라이 런 값, 그룹, 버전, 리소스, 범위, 구성 요소, HTTP 응답 코드에 대해 구분된 API 서버 요청 카운터입니다.| +| `apiserver_request_duration_seconds*` | 각 메소드, 드라이 런 값, 그룹, 버전, 리소스, 하위 리소스, 범위, 구성 요소에 대한 응답 지연 시간 분포(초 단위)| +| `apiserver_admission_controller_admission_duration_seconds` | admission controller 지연 시간 히스토그램(초), 이름으로 식별되며 각 작업, API 리소스 및 유형별로 구분됨(검증 또는 승인).| +| `apiserver_admission_webhook_rejection_count` | admission webhook 거부 건수.이름, 작업, 거부 코드, 유형(검증 또는 승인), 오류 유형(calling_webhook_error, apiserver_internal_error, no_error) 으로 식별됩니다.| +| `rest_client_request_duration_seconds` | 요청 지연 시간(초)동사와 URL별로 분류되어 있습니다.| +| `rest_client_requests_total` | 상태 코드, 메서드, 호스트별로 파티션을 나눈 HTTP 요청 수| + +### etcd + +| 메트릭 | 설명 +|: --|: --| +| `etcd_request_duration_seconds` | 각 작업 및 객체 유형에 대한 Etcd 요청 지연 시간(초)| +| `etcd_db_total_size_in_bytes` 또는
`apiserver_storage_db_total_size_in_bytes` (EKS v1.26부터 시작) | Etcd 데이터베이스 크기 | + +[쿠버네티스 모니터링 개요 대시보드](https://grafana.com/grafana/dashboards/14623)를 사용하여 쿠버네티스 API 서버 요청과 지연 시간 및 etcd 지연 시간 메트릭을 시각화하고 모니터링하는 것을 고려해 보십시오. + +다음 프로메테우스 쿼리를 사용하여 etcd의 현재 크기를 모니터링할 수 있습니다. 이 쿼리는 API 메트릭 엔드포인트에서 메트릭을 스크랩하는 `kube-apiserver`라는 작업이 있고 EKS 버전이 v1.26 미만인 것으로 가정합니다. + +```text +max(etcd_db_total_size_in_bytes{job="kube-apiserver"} / (8 * 1024 * 1024 * 1024)) +``` + +## 클러스터 인증 + +EKS는 현재 [bearer/서비스 계정 토큰](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens)과 [웹후크 토큰 인증](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication)을 사용하는 IAM 인증 등 두 가지 유형의 인증을 지원합니다. 사용자가 쿠버네티스 API를 호출하면 웹후크는 요청에 포함된 인증 토큰을 IAM에 전달합니다. base 64로 서명된 URL인 토큰은 AWS 명령줄 인터페이스([AWS CLI](https://aws.amazon.com/cli/))에 의해 생성됩니다. + +EKS 클러스터를 생성하는 IAM 사용자 또는 역할은 자동으로 클러스터에 대한 전체 액세스 권한을 얻습니다. [`aws-auth` configmap](https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html)을 편집하여 EKS 클러스터에 대한 액세스를 관리할 수 있습니다. + +`aws-auth` 컨피그맵을 잘못 구성하여 클러스터에 대한 액세스 권한을 잃은 경우에도 클러스터 생성자의 사용자 또는 역할을 사용하여 EKS 클러스터에 액세스할 수 있습니다. + +드문 경우이긴 하지만 AWS 리전에서 IAM 서비스를 사용할 수 없는 경우에도 쿠버네티스 서비스 계정의 bearer 토큰을 사용하여 클러스터를 관리할 수 있습니다. + +클러스터에서 모든 작업을 수행할 수 있는 “super-admin” 계정을 생성하십시오. + +``` +kubectl -n kube-system create serviceaccount super-admin +``` + +super-admin cluster-admin 역할을 부여하는 역할 바인딩을 생성합니다. + +``` +kubectl create clusterrolebinding super-admin-rb --clusterrole=cluster-admin --serviceaccount=kube-system:super-admin +``` + +서비스 계정 시크릿 가져오기: + +``` +secret_name=`kubectl -n kube-system get serviceaccount/super-admin -o jsonpath=' {.secrets [0] .name} '` +``` + +시크릿과 관련된 토큰 가져오기: + +``` +SECRET_NAME=`kubectl -n kube-system get serviceaccount/super-admin -o jsonpath='{.secrets[0].name}'` +``` + +서비스 계정과 토큰을 `kubeconfig'에 추가합니다. + +``` +TOKEN=`kubectl -n kube-system get secret $SECRET_NAME -o jsonpath='{.data.token}'| base64 --decode` +``` + +super-admin 계정을 사용하도록 `kubeconfig`에서 현재 컨텍스트를 설정합니다. + +``` +kubectl config set-credentials super-admin --token=$TOKEN +``` + +최종 `kubeconfig`는 다음과 같아야 합니다. + +``` +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: + server: https://.gr7.us-west-2.eks.amazonaws.com + name: arn:aws:eks:us-west-2::cluster/ +contexts: +- context: + cluster: arn:aws:eks:us-west-2::cluster/ + user: super-admin + name: arn:aws:eks:us-west-2::cluster/ +current-context: arn:aws:eks:us-west-2::cluster/ +kind: Config +preferences: {} +users: +#- name: arn:aws:eks:us-west-2::cluster/ +# user: +# exec: +# apiVersion: client.authentication.k8s.io/v1alpha1 +# args: +# - --region +# - us-west-2 +# - eks +# - get-token +# - --cluster-name +# - <> +# command: aws +# env: null +- name: super-admin + user: + token: <> +``` + +## Admission Webhooks + +쿠버네티스에는 [admission webhooks 검증 및 변경](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers)이라는 두 가지 유형의 admission webhooks이 있습니다. 이를 통해 사용자는 쿠버네티스 API를 확장하고 API에서 객체를 승인하기 전에 객체를 검증하거나 변경할 수 있습니다. 이러한 웹후크를 잘못 구성하면 클러스터의 중요한 작업이 차단되어 EKS 컨트롤 플레인이 불안정해질 수 있습니다. + +클러스터 크리티컬 작업에 영향을 주지 않으려면 다음과 같은 “catch-all” 웹훅을 설정하지 마십시오. + +``` +- name: "pod-policy.example.com" + rules: + - apiGroups: ["*"] + apiVersions: ["*"] + operations: ["*"] + resources: ["*"] + scope: "*" +``` + +또는 웹후크에 30초 미만의 제한 시간을 가진 Fail Open 정책이 있는지 확인하여 웹후크를 사용할 수 없는 경우 클러스터의 중요한 워크로드에 영향을 주지 않도록 하십시오. + +### 안전하지 않은 `sysctls`가 있는 파드를 차단한다. + +`Sysctl`은 사용자가 런타임 중에 커널 파라미터를 수정할 수 있는 리눅스 유틸리티입니다. 이러한 커널 매개변수는 네트워크, 파일 시스템, 가상 메모리, 프로세스 관리 등 운영 체제 동작의 다양한 측면을 제어합니다. + +쿠버네티스를 사용하면 파드에 `sysctl` 프로필을 할당할 수 있다.쿠버네티스는 `systcls`를 안전한 것과 안전하지 않은 것으로 분류합니다. 안전한 `sysctls`는 컨테이너 또는 파드에 네임스페이스가 지정되며, 이를 설정해도 노드의 다른 파드나 노드 자체에는 영향을 주지 않습니다. 반대로 안전하지 않은 sysctl은 다른 파드를 방해하거나 노드를 불안정하게 만들 수 있으므로 기본적으로 비활성화되어 있습니다. + +안전하지 않은 `sysctls`가 기본적으로 비활성화되므로, kubelet은 안전하지 않은 `sysctl` 프로필을 가진 파드를 생성하지 않습니다. 이러한 파드를 생성하면, 스케줄러는 해당 파드를 노드에 반복적으로 할당하지만 노드는 실행에 실패합니다. 이 무한 루프는 궁극적으로 클러스터 컨트롤 플레인에 부담을 주어 클러스터를 불안정하게 만듭니다. + +안전하지 않은 `sysctls`가 있는 파드를 거부하려면 [OPA 게이트키퍼](https://github.com/open-policy-agent/gatekeeper-library/blob/377cb915dba2db10702c25ef1ee374b4aa8d347a/src/pod-security-policy/forbidden-sysctls/constraint.tmpl) 또는 [Kyverno](https://kyverno.io/policies/pod-security/baseline/restrict-sysctls/restrict-sysctls/)를 사용하는 것을 고려해 보십시오. + + + +## 클러스터 업그레이드 처리 +2021년 4월부터 쿠버네티스 릴리스 주기가 연간 4개 릴리스(분기에 한 번)에서 연간 세 번의 릴리스로 변경되었습니다. 새 마이너 버전(예: 1.**21** 또는 1.**22**) 은 대략 [15주마다](https://kubernetes.io/blog/2021/07/20/new-kubernetes-release-cadence/#what-s-changing-and-when) 릴리스됩니다. 쿠버네티스 1.19부터 각 마이너 버전은 처음 릴리스된 후 약 12개월 동안 지원됩니다. 쿠버네티스는 최소 두 개의 마이너 버전에 대해 컨트롤 플레인과 워커 노드 간의 호환성을 지원합니다. + +쿠버네티스 커뮤니티의 쿠버네티스 버전 지원에 따라 EKS는 언제든지 최소 3개의 프로덕션 버전의 쿠버네티스 제공하며, 네 번째 버전은 지원 중단될 예정입니다. + +EKS는 지원 종료일 최소 60일 전에 해당 쿠버네티스 마이너 버전의 지원 중단을 발표합니다. 지원 종료일이 되면 지원 중단된 버전을 실행하는 클러스터는 EKS가 지원하는 다음 쿠버네티스 버전으로 자동 업데이트되기 시작합니다. + +EKS는 [쿠버네티스](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)와 [EKS 플랫폼 버전](https://docs.aws.amazon.com/eks/latest/userguide/platform-versions.html) 모두에 대해 in-place 클러스터 업그레이드를 수행합니다. 이를 통해 클러스터 운영이 단순화되고 다운타임 없이 최신 쿠버네티스 기능을 활용하고 보안 패치를 적용할 수 있습니다. + +새 쿠버네티스 버전에는 중요한 변경 사항이 적용되며 업그레이드 후에는 클러스터를 다운그레이드할 수 없습니다. 최신 쿠버네티스 버전으로 원활하게 전환하려면 클러스터 업그레이드 처리를 위한 프로세스를 잘 문서화해야 합니다. 최신 쿠버네티스 버전으로 업그레이드할 때 in-place 클러스터 업그레이드를 수행하는 대신 새 클러스터로 마이그레이션하는 것을 고려할 수 있습니다. [VMware의 Velero](https://github.com/vmware-tanzu/velero)와 같은 클러스터 백업 및 복원 도구를 사용하면 새 클러스터로 마이그레이션하는데 도움이 될 수 있습니다. + +- 새 버전에서는 기존 애플리케이션을 손상시킬 수 있는 API와 기능을 더 이상 사용하지 못할 수 있으므로 [쿠버네티스 지원 중단 정책](https://kubernetes.io/docs/reference/using-api/deprecation-policy/)을 숙지해야 합니다. +- 클러스터를 업그레이드하기 전에 [쿠버네티스 변경 로그](https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG) 및 [Amazon EKS 쿠버네티스 버전](https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html)을 검토하여 워크로드에 미치는 부정적인 영향을 파악해야 합니다. +- 비프로덕션 환경에서 클러스터 업그레이드를 테스트하고 현재 워크로드 및 컨트롤러에 미치는 영향을 파악해 보십시오. 새 쿠버네티스 버전으로 이동하기 전에 애플리케이션, 컨트롤러 및 사용자 지정 통합의 호환성을 테스트하는 지속적 통합 워크플로를 구축하여 테스트를 자동화할 수 있습니다. +- 클러스터를 업그레이드한 후 쿠버네티스 애드온을 업그레이드해야 할 수도 있습니다. [Amazon EKS 클러스터 쿠버네티스 버전 업데이트](https://docs.aws.amazon.com/eks/latest/userguide/update-cluster.html)를 검토하여 클러스터 애드온과 클러스터 버전의 호환성을 검증하십시오. +- [컨트롤 플레인 로깅](https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html)을 켜고 로그에서 오류가 있는지 검토해 보십시오. +- EKS 클러스터를 관리할 때는 `eksctl`을 사용하는 것을 고려해 보십시오. `eksctl`을 사용하여 [컨트롤 플레인, 애드온, 워커 노드 업데이트](https://eksctl.io/usage/cluster-upgrade/)할 수 있습니다. +- EKS 컨트롤 플레인 업그레이드에는 워커 노드 업그레이드가 포함되지 않습니다. EKS 워커 노드 업데이트는 사용자의 책임입니다. 워커 노드 업그레이드 프로세스를 자동화하려면 [EKS 관리 노드 그룹](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) 또는 [EKS on Fargate](https://docs.aws.amazon.com/eks/latest/userguide/fargate.html)를 사용하는 것을 고려해 보십시오. +- 필요한 경우 [`kubectl convert`](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-convert-plugin) 플러그인을 사용하여 [쿠버네티스 매니페스트 파일을 다른 API 버전 간에 변환](https://kubernetes.io/docs/tasks/tools/included/kubectl-convert-overview/)할 수 있습니다 + +## 대규모 클러스터 실행 + +EKS는 컨트롤 플레인 인스턴스의 부하를 능동적으로 모니터링하고 자동으로 확장하여 고성능을 보장합니다. 하지만 대규모 클러스터를 실행할 때는 쿠버네티스 및 AWS 서비스의 할당량 내에서 발생할 수 있는 성능 문제와 한계를 고려해야 합니다. + +- [ProjectCalico 팀에서 수행한 테스트](https://www.projectcalico.org/comparing-kube-proxy-modes-iptables-or-ipvs/)에 따르면, 서비스가 1000개 이상인 클러스터에서 `iptables` 모드에서 `kube-proxy`를 사용할 경우 네트워크 지연이 발생할 수 있습니다. 해결 방법은 [`ipvs` 모드에서 `kube-proxy`로 실행](https://medium.com/@jeremy.i.cowan/the-problem-with-kube-proxy-enabling-ipvs-on-eks-169ac22e237e)으로 전환하는 것입니다. +- CNI에서 파드의 IP 주소를 요청해야 하거나 새 EC2 인스턴스를 자주 생성해야 하는 경우에도 [EC2 API 요청 제한](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/throttling.html)이 발생할 수 있습니다. IP 주소를 캐싱하도록 CNI를 구성하면 EC2 API 호출을 줄일 수 있습니다. 더 큰 EC2 인스턴스 유형을 사용하여 EC2 조정 이벤트를 줄일 수 있습니다. + +## 한도 및 서비스 할당량 알아보기 + +AWS는 실수로 리소스를 과도하게 프로비저닝하는 것을 방지하기 위해 서비스 한도(팀이 요청할 수 있는 각 리소스 수의 상한선)를 설정합니다. [Amazon EKS 서비스 할당량](https://docs.aws.amazon.com/eks/latest/userguide/service-quotas.html)에는 서비스 한도가 나와 있습니다. [AWS 서비스 할당량](https://docs.aws.amazon.com/eks/latest/userguide/service-quotas.html)을 사용하여 변경할 수 있는 두 가지 유형의 한도, Soft limit가 있습니다. Hard limit는 변경할 수 없습니다. 애플리케이션을 설계할 때는 이러한 값을 고려해야 합니다. 이러한 서비스 제한을 정기적으로 검토하여 애플리케이션 설계 중에 통합하는 것이 좋습니다. + +- 오케스트레이션 엔진의 제한 외에도 ELB(Elastic Load Balancing) 및 Amazon VPC와 같은 다른 AWS 서비스에는 애플리케이션 성능에 영향을 미칠 수 있는 제한이 있습니다. +- EC2 한도에 대한 자세한 내용은 [EC2 서비스 제한](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html)을 참조하십시오. +- 각 EC2 인스턴스는 [Amazon 제공 DNS 서버](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-dns.html#vpc-dns-limits)로 전송할 수 있는 패킷 수를 네트워크 인터페이스당 초당 최대 1024 패킷으로 제한합니다. +- EKS 환경에서 etcd 스토리지 한도는 [업스트림 지침](https://etcd.io/docs/v3.5/dev-guide/limit/#storage-size-limit)에 따라 **8GB**입니다. etcd db 크기를 추적하려면 `etcd_db_total_size_in_bytes` 지표를 모니터링하십시오. 이 모니터링을 설정하려면 [경고 규칙](https://github.com/etcd-io/etcd/blob/main/contrib/mixin/mixin.libsonnet#L213-L240) `etcdBackendQuotaLowSpace` 및 `etcdExcessiveDatabaseGrowth`를 참조할 수 있습니다. + +## 추가 리소스: + +- [Amazon EKS 워커 노드의 클러스터 네트워킹에 대한 이해하기 쉬운 설명](https://aws.amazon.com/blogs/containers/de-mystifying-cluster-networking-for-amazon-eks-worker-nodes/) +- [아마존 EKS 클러스터 엔드포인트 액세스 제어](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html) +- [AWS re:Invent 2019: 아마존 EKS 언더 더 후드 (CON421-R1)](https://www.youtube.com/watch?v=7vxDWDD2YnM) diff --git a/content/reliability/docs/dataplane.ko.md b/content/reliability/docs/dataplane.ko.md new file mode 100644 index 000000000..f4223e919 --- /dev/null +++ b/content/reliability/docs/dataplane.ko.md @@ -0,0 +1,289 @@ +# EKS 데이터 플레인 + +가용성과 복원력이 뛰어난 애플리케이션을 운영하려면 가용성과 복원력이 뛰어난 데이터 플레인이 필요합니다. 탄력적인 데이터 플레인을 사용하면 쿠버네티스가 애플리케이션을 자동으로 확장하고 복구할 수 있습니다. 복원력이 뛰어난 데이터 플레인은 2개 이상의 워커 노드로 구성되며, 워크로드에 따라 확장 및 축소될 수 있으며 장애 발생 시 자동으로 복구할 수 있습니다. + +EKS를 사용하는 워커 노드에는 [EC2 인스턴스](https://docs.aws.amazon.com/eks/latest/userguide/worker.html)와 [Fargate] (https://docs.aws.amazon.com/eks/latest/userguide/fargate.html)라는 두 가지 옵션이 있습니다. EC2 인스턴스를 선택하면 워커 노드를 직접 관리하거나 [EKS 관리 노드 그룹](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)을 사용할 수 있습니다. 관리형 워커 노드와 자체 관리형 워커 노드와 Fargate가 혼합된 클러스터를 구성할 수 있습니다. + +Fargate의 EKS는 복원력이 뛰어난 데이터 플레인을 위한 가장 쉬운 방법을 제공합니다. Fargate는 격리된 컴퓨팅 환경에서 각 파드를 실행합니다. Fargate에서 실행되는 각 파드에는 자체 워커 노드가 있습니다. 쿠버네티스가 파드를 확장함에 따라 Fargate는 데이터 플레인을 자동으로 확장합니다. [horizontal pod autoscaler](https://docs.aws.amazon.com/eks/latest/userguide/horizontal-pod-autoscaler.html)를 사용하여 데이터 플레인과 워크로드를 모두 확장할 수 있습니다. + +EC2 워커 노드를 확장하는 데 선호되는 방법은 [쿠버네티스 Cluster Autoscaler](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/aws/README.md), [EC2 Auto Scaling 그룹](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html) 또는 [Atlassian's Esclator](https://github.com/atlassian/escalator)와 같은 커뮤니티 프로젝트를 사용하는 것입니다. + +## 권장 사항 + +### EC2 오토 스케일링 그룹을 사용하여 워커 노드 생성 + +개별 EC2 인스턴스를 생성하여 클러스터에 조인하는 대신 EC2 오토 스케일링 그룹을 사용하여 워커 노드를 생성하는 것이 가장 좋습니다. 오토 스케일링 그룹은 종료되거나 장애가 발생한 노드를 자동으로 교체하므로 클러스터가 항상 워크로드를 실행할 수 있는 용량을 확보할 수 있습니다. + +### 쿠버네티스 Cluster Autoscaler를 사용하여 노드를 확장하세요 + +Cluster Autoscaler는 클러스터의 리소스가 충분하지 않아 실행할 수 없는 파드가 있을 때 데이터 플레인 크기를 조정하며, 다른 워커 노드를 추가하여 도움을 줍니다. Cluster Autoscaler는 반응형 프로세스이긴 하지만 클러스터의 용량이 충분하지 않아 파드가 *pending* 상태가 될 때까지 기다립니다. 이러한 이벤트가 발생하면 클러스터에 EC2 인스턴스가 추가됩니다. 클러스터의 용량이 부족해지면 워커 노드가 추가될 때까지 새 복제본 또는 새 파드를 사용할 수 없게 됩니다(*Pending 상태*). 데이터 플레인이 워크로드 수요를 충족할 만큼 충분히 빠르게 확장되지 않는 경우 이러한 지연은 애플리케이션의 신뢰성에 영향을 미칠 수 있습니다. 워커 노드의 사용률이 지속적으로 낮고 해당 노드의 모든 파드를 다른 워커 노드에 스케줄링할 수 있는 경우 Cluster Autoscaler는 해당 워커 노드를 종료합니다. + +### Cluster Autoscaler를 사용하여 오버 프로비저닝을 구성합니다. + +Cluster Autoscaler는 클러스터의 파드가 이미 *pending* 상태일 때 데이터 플레인 스케일링을 트리거합니다. 따라서 애플리케이션에 더 많은 복제본이 필요한 시점과 실제로 더 많은 복제본을 가져오는 시점 사이에 지연이 있을 수 있습니다. 이러한 지연을 방지할 수 있는 방법은 필요한 것보다 많은 복제본을 추가하여 애플리케이션의 복제본 수를 늘리는 것입니다. + +Cluster Autoscaler에서 권장하는 또 다른 패턴은 [*pause* 파드와 우선순위 선점 기능](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md#how-can-i-configure-overprovisioning-with-cluster-autoscaler)입니다. *pause 파드*는 [pause 컨테이너](https://github.com/kubernetes/kubernetes/tree/master/build/pause)를 실행하는데, 이름에서 알 수 있듯이 클러스터의 다른 파드에서 사용할 수 있는 컴퓨팅 용량의 placeholder 역할을 하는 것 외에는 아무것도 하지 않습니다. *매우 낮은 할당 우선 순위*로 실행되기 때문에, 다른 파드를 생성해야 하고 클러스터에 가용 용량이 없을 때 일시 중지 파드가 노드에서 제거됩니다. 쿠버네티스 스케줄러는 pause 파드의 축출을 감지하고 스케줄을 다시 잡으려고 합니다. 하지만 클러스터가 최대 용량으로 실행되고 있기 때문에 일시 중지 파드는 *pending* 상태로 유지되며, Cluster Autoscaler는 이에 대응하여 노드를 추가합니다. + +Helm 차트를 통해 [클러스터 오버프로비저너](https://github.com/helm/charts/tree/master/stable/cluster-overprovisioner)를 설치할 수 있다. + +### 여러 오토 스케일링 그룹과 함께 Cluster Autoscaler 사용 + +`--node-group-auto-discovery` 플래그를 활성화한 상태로 Cluster Autoscaler를 실행합니다.이렇게 하면 Cluster Autoscaler가 정의된 특정 태그가 포함된 모든 오토스케일링 그룹을 찾을 수 있으므로 매니페스트에서 각 오토스케일링 그룹을 정의하고 유지할 필요가 없습니다. + +### 로컬 스토리지와 함께 Cluster Autoscaler 사용 + +기본적으로 Cluster Autoscaler는 로컬 스토리지가 연결된 상태로 배포된 파드가 있는 노드를 축소하지 않습니다. `--skip-nodes-with-local-storage` 플래그를 false로 설정하면 Cluster Autoscaler가 이러한 노드를 축소할 수 있습니다. + +### 워커 노드와 워크로드를 여러 AZ에 분산합니다. + +여러 AZ에서 워커 노드와 파드를 실행하여 개별 AZ에서 장애가 발생하지 않도록 워크로드를 보호할 수 있습니다. 노드를 생성하는 서브넷을 사용하여 워커 노드가 생성되는 AZ를 제어할 수 있습니다. + +쿠버네티스 1.18+를 사용하는 경우 AZ에 파드를 분산하는 데 권장되는 방법은 [파드에 대한 토폴로지 분산 제약](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#spread-constraints-for-pods)을 사용하는 것입니다. + +아래 디플로이먼트는 가능한 경우 AZ에 파드를 분산시키고, 그렇지 않을 경우 해당 파드는 그냥 실행되도록 합니다. + +``` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-server +spec: + replicas: 3 + selector: + matchLabels: + app: web-server + template: + metadata: + labels: + app: web-server + spec: + topologySpreadConstraints: + - maxSkew: 1 + whenUnsatisfiable: ScheduleAnyway + topologyKey: topology.kubernetes.io/zone + labelSelector: + matchLabels: + app: web-server + containers: + - name: web-app + image: nginx + resources: + requests: + cpu: 1 +``` + +!!! 참고 + `kube-scheduler`는 해당 레이블이 있는 노드를 통한 토폴로지 도메인만 인식합니다. 위의 디플로이먼트를 단일 존에만 노드가 있는 클러스터에 배포하면, `kube-scheduler`가 다른 존을 인식하지 못하므로 모든 파드가 해당 노드에서 스케줄링됩니다. 이 Topology Spread가 스케줄러와 함께 예상대로 작동하려면 모든 존에 노드가 이미 있어야 합니다. 이 문제는 쿠버네티스 1.24에서 `MinDomainsInPodToplogySpread` [기능 게이트](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/#api)가 추가되면서 해결될 것입니다. 이 기능을 사용하면 스케줄러에 적격 도메인 수를 알리기 위해 `MinDomains` 속성을 지정할 수 있습니다. + +!!! 경고 + `whenUnsatisfiable`를 `Donot Schedule`로 설정하면 Topology Spread Constraints을 충족할 수 없는 경우 파드를 스케줄링할 수 없게 됩니다. Topology Spread Constraints을 위반하는 대신 파드를 실행하지 않는 것이 더 좋은 경우에만 설정해야 합니다. + +이전 버전의 쿠버네티스에서는 파드 anti-affinity 규칙을 사용하여 여러 AZ에 걸쳐 파드를 스케줄링할 수 있습니다. 아래 매니페스트는 쿠버네티스 스케줄러에게 별개의 AZ에서 파드를 스케줄링하는 것을 *선호*한다고 알려줍니다. + +``` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-server + labels: + app: web-server +spec: + replicas: 4 + selector: + matchLabels: + app: web-server + template: + metadata: + labels: + app: web-server + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - web-server + topologyKey: failure-domain.beta.kubernetes.io/zone + weight: 100 + containers: + - name: web-app + image: nginx +``` + +!!! 경고 + 파드를 서로 다른 AZ에 스케줄할 필요는 없습니다. 그렇지 않으면 디플로이먼트의 파드 수가 AZ 수를 절대 초과하지 않습니다. + +### EBS 볼륨을 사용할 때 각 AZ의 용량을 확보하십시오. + +[Amazon EBS를 사용하여 영구 볼륨 제공](https://docs.aws.amazon.com/eks/latest/userguide/ebs-csi.html)을 사용하는 경우 파드 및 관련 EBS 볼륨이 동일한 AZ에 있는지 확인해야 합니다. 이 글을 쓰는 시점에서 EBS 볼륨은 단일 AZ 내에서만 사용할 수 있습니다. 파드는 다른 AZ에 위치한 EBS 지원 영구 볼륨에 액세스할 수 없습니다. 쿠버네티스 [스케줄러는 워커 노드가 어느 AZ에 위치하는지 알고 있습니다](https://kubernetes.io/docs/reference/kubernetes-api/labels-annotations-taints/#topologykubernetesiozone). 쿠버네티스는 해당 볼륨과 동일한 AZ에 EBS 볼륨이 필요한 파드를 항상 스케줄링합니다. 하지만 볼륨이 위치한 AZ에 사용 가능한 워커 노드가 없는 경우 파드를 스케줄링할 수 없습니다. + +클러스터가 항상 필요한 EBS 볼륨과 동일한 AZ에 파드를 스케줄링할 수 있는 용량을 확보할 수 있도록 충분한 용량을 갖춘 각 AZ에 오토 스케일링 그룹을 생성하십시오. 또한 클러스터 오토스케일러에서 `--balance-similar-similar-node groups` 기능을 활성화해야 합니다. + +EBS 볼륨을 사용하지만 가용성을 높이기 위한 요구 사항이 없는 애플리케이션을 실행 중인 경우 애플리케이션 배포를 단일 AZ로 제한할 수 있습니다. EKS에서는 워커 노드에 AZ 이름이 포함된 `failure-domain.beta.kubernetes.io/zone` 레이블이 자동으로 추가됩니다. `kubectl get nodes --show-labels`를 실행하여 노드에 첨부된 레이블을 확인할 수 있습니다. 빌트인 노드 레이블에 대한 자세한 내용은 [여기] (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#built-in-node-labels)에서 확인할 수 있습니다. 노드 셀렉터를 사용하여 특정 AZ에서 파드를 스케줄링할 수 있습니다. + +아래 예시에서는 파드가 `us-west-2c` AZ에서만 스케줄링됩니다. + +``` +apiVersion: v1 +kind: Pod +metadata: + name: single-az-pod +spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: failure-domain.beta.kubernetes.io/zone + operator: In + values: + - us-west-2c + containers: + - name: single-az-container + image: kubernetes/pause +``` + +퍼시스턴트 볼륨(EBS 지원) 역시 AZ 이름으로 자동 레이블이 지정됩니다. `kubectl get pv -L topology.ebs.csi.aws.com/zone` 명령을 실행해 퍼시스턴트 볼륨이 어느 AZ에 속하는지 확인할 수 있습니다. 파드가 생성되고 볼륨을 요청하면, 쿠버네티스는 해당 볼륨과 동일한 AZ에 있는 노드에 파드를 스케줄링합니다. + +노드 그룹이 하나인 EKS 클러스터가 있는 시나리오를 생각해 보십시오. 이 노드 그룹에는 3개의 AZ에 분산된 세 개의 워커 노드가 있습니다. EBS 지원 퍼시스턴트 볼륨을 사용하는 애플리케이션이 있습니다. 이 애플리케이션과 해당 볼륨을 생성하면 해당 파드가 세 개의 AZ 중 첫 번째 AZ에 생성됩니다. 그러면 이 파드를 실행하는 워커 노드가 비정상 상태가 되고 이후에는 사용할 수 없게 된다. Cluster Autoscaler는 비정상 노드를 새 워커 노드로 교체합니다. 그러나 자동 확장 그룹이 세 개의 AZ에 걸쳐 있기 때문에 상황에 따라 새 워커 노드가 두 번째 또는 세 번째 AZ에서 시작될 수 있지만 첫 번째 AZ에서는 실행되지 않을 수 있습니다. AZ 제약이 있는 EBS 볼륨은 첫 번째 AZ에만 존재하고 해당 AZ에는 사용 가능한 워커 노드가 없으므로 파드를 스케줄링할 수 없습니다. 따라서 각 AZ에 노드 그룹을 하나씩 생성해야 합니다. 그래야 다른 AZ에서 스케줄링할 수 없는 파드를 실행할 수 있는 충분한 용량이 항상 확보됩니다. + + +또는 영구 스토리지가 필요한 애플리케이션을 실행할 때 [EFS] (https://github.com/kubernetes-sigs/aws-efs-csi-driver)를 사용하여 클러스터 자동 크기 조정을 단순화할 수 있습니다. 클라이언트는 리전 내 모든 AZ에서 동시에 EFS 파일 시스템에 액세스할 수 있습니다. EFS 기반 퍼시스턴트 볼륨을 사용하는 파드가 종료되어 다른 AZ에 스케줄되더라도 볼륨을 마운트할 수 있습니다. + +### 노드 문제 감지기 실행 + +워커 노드의 장애는 애플리케이션의 가용성에 영향을 미칠 수 있습니다. [node-problem-detector](https://github.com/kubernetes/node-problem-detector)는 클러스터에 설치하여 워커 노드 문제를 탐지할 수 있는 쿠버네티스 애드온입니다. [npd의 치료 시스템](https://github.com/kubernetes/node-problem-detector#remedy-systems)을 사용하여 노드를 자동으로 비우고 종료할 수 있습니다. + +### 시스템 및 쿠버네티스 데몬을 위한 리소스 예약 + +[운영 체제 및 쿠버네티스 데몬을 위한 컴퓨팅 용량를 예약](https://kubernetes.io/docs/tasks/administer-cluster/reserve-compute-resources/)하여 워커 노드의 안정성을 개선할 수 있습니다. 파드, 특히 `limits`이 선언되지 않은 파드는 시스템 리소스를 포화시켜 운영체제 프로세스와 쿠버네티스 데몬 (`kubelet`, 컨테이너 런타임 등)이 시스템 리소스를 놓고 파드와 경쟁하는 상황에 놓이게 됩니다.`kubelet` 플래그 `--system-reserved`와 `--kube-reserved`를 사용하여 시스템 프로세스 (`udev`, `sshd` 등)와 쿠버네티스 데몬을 위한 리소스를 각각 예약할 수 있습니다. + +[EKS에 최적화된 Linux AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html)를 사용하는 경우 CPU, 메모리 및 스토리지는 기본적으로 시스템 및 쿠버네티스 데몬용으로 예약됩니다. 이 AMI를 기반으로 하는 워커 노드가 시작되면 [`bootstrap.sh` 스크립트](https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh) 를 트리거하도록 EC2 사용자 데이터가 구성됩니다. 이 스크립트는 EC2 인스턴스에서 사용할 수 있는 CPU 코어 수와 총 메모리를 기반으로 CPU 및 메모리 예약을 계산합니다. 계산된 값은 `/etc/kubernetes/kubelet/kubelet-config.json`에 있는 `KubeletConfiguration` 파일에 기록됩니다. + +노드에서 사용자 지정 데몬을 실행하고 기본적으로 예약된 CPU 및 메모리 양이 충분하지 않은 경우 시스템 리소스 예약을 늘려야 할 수 있습니다. + +`eksctl`은 [시스템 및 쿠버네티스 데몬의 리소스 예약](https://eksctl.io/usage/customizing-the-kubelet/)을 사용자 지정하는 가장 쉬운 방법을 제공합니다. + +### QoS 구현 + +중요한 애플리케이션의 경우, 파드의 컨테이너에 대해 `requests`=`limits` 정의를 고려해보십시오. 이렇게 하면 다른 파드가 리소스를 요청하더라도 컨테이너가 종료되지 않습니다. + +모든 컨테이너에 CPU 및 메모리 제한을 적용하는 것이 가장 좋습니다. 이렇게 하면 컨테이너가 실수로 시스템 리소스를 소비하여 같은 위치에 배치된 다른 프로세스의 가용성에 영향을 미치는 것을 방지할 수 있기 때문입니다. + +### 모든 워크로드에 대한 리소스 요청/제한 구성 및 크기 조정 + +리소스 요청의 크기 조정 및 워크로드 한도에 대한 몇 가지 일반적인 지침을 적용할 수 있습니다. + +- CPU에 리소스 제한을 지정하지 마십시오. 제한이 없는 경우 요청은 [컨테이너의 상대적 CPU 사용 시간](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#how-pods-with-resource-limits-are-run)에 가중치 역할을 합니다. 이렇게 하면 인위적인 제한이나 과다 현상 없이 워크로드에서 CPU 전체를 사용할 수 있습니다. + +- CPU가 아닌 리소스의 경우, `requests`=`limits`를 구성하면 가장 예측 가능한 동작이 제공됩니다. 만약 `requests`!=`limits`이면, 컨테이너의 [QOS](https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/#qos-classes)도 Guaranteed에서 Burstable로 감소하여 [node pressure](https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/) 이벤트에 축출될 가능성이 높아졌습니다. + +- CPU가 아닌 리소스의 경우 요청보다 훨씬 큰 제한을 지정하지 마십시오. `limits`이 `requests`에 비해 크게 구성될수록 노드가 오버 커밋되어 워크로드가 중단될 가능성이 높아집니다. + +- [Karpenter](https://aws.github.io/aws-eks-best-practices/karpenter/) 또는 [Cluster AutoScaler](https://aws.github.io/aws-eks-best-practices/cluster-autoscaling/)와 같은 노드 자동 크기 조정 솔루션을 사용할 때는 요청 크기를 올바르게 지정하는 것이 특히 중요합니다. 이러한 도구는 워크로드 요청을 검토하여 프로비저닝할 노드의 수와 크기를 결정합니다. 요청이 너무 작아 제한이 더 큰 경우, 워크로드가 노드에 꽉 차 있으면 워크로드가 제거되거나 OOM으로 종료될 수 있습니다. + +리소스 요청을 결정하는 것은 어려울 수 있지만 [Vertical Pod Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler)와 같은 도구를 사용하면 런타임 시 컨테이너 리소스 사용량을 관찰하여 요청 규모를 '적정'하게 조정할 수 있습니다. 요청 크기를 결정하는 데 유용할 수 있는 다른 도구는 다음과 같습니다. + +- [Goldilocks](https://github.com/FairwindsOps/goldilocks) +- [Parca](https://www.parca.dev/) +- [Prodfiler](https://prodfiler.com/) +- [rsg](https://mhausenblas.info/right-size-guide/) + + +### 네임스페이스의 리소스 할당량 구성 + +네임스페이스는 사용자가 여러 팀 또는 프로젝트에 분산되어 있는 환경에서 사용하기 위한 것입니다. 이름 범위를 제공하고 클러스터 리소스를 여러 팀, 프로젝트, 워크로드 간에 나누는 방법입니다. 네임스페이스의 총 리소스 사용량을 제한할 수 있습니다. [`ResourceQuota`](https://kubernetes.io/docs/concepts/policy/resource-quotas/) 객체는 유형별로 네임스페이스에 만들 수 있는 개체 수와 해당 프로젝트의 리소스가 소비할 수 있는 총 컴퓨팅 리소스 양을 제한할 수 있습니다. 지정된 네임스페이스에서 요청할 수 있는 스토리지 및/또는 컴퓨팅(CPU 및 메모리) 리소스의 총합을 제한할 수 있습니다. + +> CPU 및 메모리와 같은 컴퓨팅 리소스의 네임스페이스에 리소스 쿼터가 활성화된 경우 사용자는 해당 네임스페이스의 각 컨테이너에 대한 요청 또는 제한을 지정해야 합니다. + +각 네임스페이스에 할당량을 구성하는 것을 고려해 보십시오. 네임스페이스 내의 컨테이너에 사전 구성된 제한을 자동으로 적용하려면 `LimitRanges`를 사용해 보십시오. + +### 네임스페이스 내에서 컨테이너 리소스 사용을 제한합니다. + +리소스 쿼터는 네임스페이스가 사용할 수 있는 리소스의 양을 제한하는 데 도움이 됩니다. [`LimitRange` 개체](https://kubernetes.io/docs/concepts/policy/limit-range/)는 컨테이너가 요청할 수 있는 최소 및 최대 리소스를 구현하는 데 도움이 될 수 있습니다. `LimitRange`를 사용하면 컨테이너에 대한 기본 요청 및 제한을 설정할 수 있는데, 이는 컴퓨팅 리소스 제한을 설정하는 것이 조직의 표준 관행이 아닌 경우에 유용합니다. 이름에서 알 수 있듯이, `LimitRange`는 네임스페이스의 파드 또는 컨테이너당 최소 및 최대 컴퓨팅 리소스 사용량을 적용할 수 있습니다. 또한 네임스페이스에서 퍼시스턴트볼륨클레임당 최소 및 최대 스토리지 요청을 적용할 수 있습니다. + +컨테이너와 네임스페이스 수준에서 제한을 적용하려면 `LimitRange`와 `ResourceQuota`를 함께 사용하는 것이 좋습니다. 이러한 제한을 설정하면 컨테이너 또는 네임스페이스가 클러스터의 다른 테넌트가 사용하는 리소스에 영향을 주지 않도록 할 수 있습니다. + +## CoreDNS + +CoreDNS는 쿠버네티스에서 이름 확인 및 서비스 검색 기능을 수행합니다. EKS 클러스터에 기본적으로 설치됩니다. 상호 운용성을 위해 CoreDNS용 쿠버네티스 서비스의 이름은 여전히 [kube-dns](https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/)로 지정됩니다. CoreDNS 파드는 디플로이먼트의 일부로 `kube-system` 네임스페이스에서 실행되며, EKS에서는 기본적으로 요청과 제한이 선언된 두 개의 복제본을 실행합니다. DNS 쿼리는 `kube-system` 네임스페이스에서 실행되는 `kube-dns` 서비스로 전송됩니다. + +## 권장 사항 +### 핵심 DNS 지표 모니터링 +CoreDNS는 [프로메테우스](https://github.com/coredns/coredns/tree/master/plugin/metrics)에 대한 지원을 내장하고 있습니다. 특히 CoreDNS 지연 시간(`coredns_dns_request_duration_seconds_sum`, [1.7.0](https://github.com/coredns/coredns/blob/master/notes/coredns-1.7.0.md) 버전 이전에는 메트릭이 `core_dns_response_rcode_count_total`이라고 불렸음), 오류 (`coredns_dns_responses_total`, NXDOMAIN, SERVFAIL, FormErr) 및 CoreDNS 파드의 메모리 사용량에 대한 모니터링을 고려해야 합니다. + +문제 해결을 위해 kubectl을 사용하여 CoreDNS 로그를 볼 수 있습니다. + +```shell +for p in $(kubectl get pods —namespace=kube-system -l k8s-app=kube-dns -o name); do kubectl logs —namespace=kube-system $p; done +``` + +### 노드 로컬 DNS 캐시 사용 +[노드 로컬 DNS 캐시](https://kubernetes.io/docs/tasks/administer-cluster/nodelocaldns/)를 실행하여 클러스터 DNS 성능을 개선할 수 있습니다. 이 기능은 클러스터 노드에서 DNS 캐싱 에이전트를 데몬셋으로 실행합니다. 모든 포드는 이름 확인을 위해 `kube-dns` 서비스를 사용하는 대신 노드에서 실행되는 DNS 캐싱 에이전트를 사용합니다. + +### CoreDNS의 cluster-proportional-scaler를 구성합니다. + +클러스터 DNS 성능을 개선하는 또 다른 방법은 클러스터의 노드 및 CPU 코어 수에 따라 [CoreDNS 배포를 자동으로 수평으로 확장](https://kubernetes.io/docs/tasks/administer-cluster/dns-horizontal-autoscaling/#enablng-dns-horizontal-autoscaling)하는 것입니다. [수평 클러스터 비례 자동 확장](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler/blob/master/README.md)은 스케줄 가능한 데이터 플레인의 크기에 따라 디플로이먼트의 복제본 수를 조정하는 컨테이너입니다. + +노드와 노드의 CPU 코어 집계는 CoreDNS를 확장할 수 있는 두 가지 지표입니다. 두 지표를 동시에 사용할 수 있습니다. 더 큰 노드를 사용하는 경우 CoreDNS 스케일링은 CPU 코어 수를 기반으로 합니다. 반면 더 작은 노드를 사용하는 경우 CoreDNS 복제본의 수는 데이터 플레인의 CPU 코어에 따라 달라집니다. 비례 오토스케일러 구성은 다음과 같습니다. + +``` +linear: '{"coresPerReplica":256,"min":1,"nodesPerReplica":16}' +``` + +### 노드 그룹이 있는 AMI 선택 +EKS는 고객이 자체 관리형 노드 그룹과 관리형 노드 그룹을 모두 생성하는 데 사용하는 최적화된 EC2 AMI를 제공합니다. 이러한 AMI는 지원되는 모든 쿠버네티스 버전에 대해 모든 리전에 게시됩니다. EKS는 CVE 또는 버그가 발견되면 이러한 AMI를 더 이상 사용되지 않는 것으로 표시합니다. 따라서 노드 그룹에 사용할 AMI를 선택할 때는 더 이상 사용되지 않는 AMI를 사용하지 않는 것이 좋습니다. + +Ec2 describe-images api를 사용하여 아래 명령을 사용하여 더 이상 사용되지 않는 AMI를 필터링할 수 있습니다. + +``` +aws ec2 describe-images --image-id ami-0d551c4f633e7679c --no-include-deprecated +``` + +이미지 설명 출력에 DeprecationTime이 필드로 포함되어 있는지 확인하여 지원 중단된 AMI를 식별할 수도 있습니다. 예를 들면: + +``` +aws ec2 describe-images --image-id ami-xxx --no-include-deprecated +{ + "Images": [ + { + "Architecture": "x86_64", + "CreationDate": "2022-07-13T15:54:06.000Z", + "ImageId": "ami-xxx", + "ImageLocation": "123456789012/eks_xxx", + "ImageType": "machine", + "Public": false, + "OwnerId": "123456789012", + "PlatformDetails": "Linux/UNIX", + "UsageOperation": "RunInstances", + "State": "available", + "BlockDeviceMappings": [ + { + "DeviceName": "/dev/xvda", + "Ebs": { + "DeleteOnTermination": true, + "SnapshotId": "snap-0993a2fc4bbf4f7f4", + "VolumeSize": 20, + "VolumeType": "gp2", + "Encrypted": false + } + } + ], + "Description": "EKS Kubernetes Worker AMI with AmazonLinux2 image, (k8s: 1.19.15, docker: 20.10.13-2.amzn2, containerd: 1.4.13-3.amzn2)", + "EnaSupport": true, + "Hypervisor": "xen", + "Name": "aws_eks_optimized_xxx", + "RootDeviceName": "/dev/xvda", + "RootDeviceType": "ebs", + "SriovNetSupport": "simple", + "VirtualizationType": "hvm", + "DeprecationTime": "2023-02-09T19:41:00.000Z" + } + ] +} +``` + diff --git a/content/reliability/docs/index.ko.md b/content/reliability/docs/index.ko.md new file mode 100644 index 000000000..c4b6b7117 --- /dev/null +++ b/content/reliability/docs/index.ko.md @@ -0,0 +1,45 @@ +# 신뢰성을 위한 Amazon EKS 모범 사례 가이드 + +이 섹션에서는 EKS에서 실행되는 워크로드의 복원력과 가용성을 높이는 방법에 대한 지침을 제공합니다. + +## 이 가이드를 사용하는 방법 + +이 안내서는 EKS에서 가용성이 높고 내결함성이 있는 서비스를 개발하고 운영하려는 개발자와 설계자를 대상으로 합니다. 이 가이드는 보다 쉽게 사용할 수 있도록 다양한 주제 영역으로 구성되어 있습니다. 각 항목은 간략한 개요로 시작하여 EKS 클러스터의 신뢰성을 위한 권장 사항 및 모범 사례 목록이 이어집니다. + +## 소개 + +EKS의 신뢰성 모범 사례는 다음 주제에 따라 그룹화되었습니다. + +* 애플리케이션 +* 컨트롤 플레인 +* 데이터 플레인 + +--- + +무엇이 시스템을 신뢰할 수 있게 만드나요? 일정 기간의 환경 변화에도 불구하고 시스템이 일관되게 작동하고 요구 사항을 충족할 수 있다면 신뢰할 수 있다고 할 수 있습니다. 이를 위해서는 시스템이 장애를 감지하고 자동으로 복구하며 수요에 따라 확장할 수 있어야 합니다. + +고객은 Kubernetes를 기반으로 사용하여 업무상 중요한 애플리케이션 및 서비스를 안정적으로 운영할 수 있습니다. 그러나 컨테이너 기반 애플리케이션 설계 원칙을 통합하는 것 외에도 워크로드를 안정적으로 실행하려면 신뢰할 수 있는 인프라가 필요합니다. 쿠버네티스에서 인프라는 컨트롤 플레인과 데이터 플레인으로 구성됩니다. + +EKS는 가용성과 내결함성을 제공하도록 설계된 프로덕션 등급의 Kubernetes 컨트롤 플레인을 제공합니다. + +EKS에서 AWS는 쿠버네티스 컨트롤 플레인의 신뢰성을 책임집니다. EKS는 AWS 리전의 세 가용 영역에서 쿠버네티스 컨트롤 플레인을 실행합니다. 쿠버네티스 API 서버 및 etcd 클러스터의 가용성과 확장성을 자동으로 관리합니다. + +데이터 플레인의 신뢰성에 대한 책임은 사용자, 고객, AWS 간에 공유됩니다. EKS는 Kubernetes 데이터 플레인에 대한 세 가지 옵션을 제공합니다. 가장 많이 관리되는 옵션인 Fargate는 데이터 플레인의 프로비저닝 및 확장을 처리합니다. 두 번째 옵션인 관리형 노드 그룹화는 데이터 플레인의 프로비저닝 및 업데이트를 처리합니다. 마지막으로, 자체 관리형 노드는 데이터 플레인에 대한 관리가 가장 적은 옵션입니다. AWS 관리형 데이터 플레인을 더 많이 사용할수록 책임은 줄어듭니다. + +[관리형 노드 그룹](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)은 EC2 노드의 프로비저닝 및 수명 주기 관리를 자동화합니다. EKS API (EKS 콘솔, AWS API, AWS CLI, CloudFormation, Terraform 또는 `eksctl` 사용)를 사용하여 관리형 노드를 생성, 확장 및 업그레이드할 수 있습니다. 관리형 노드는 계정에서 EKS에 최적화된 Amazon Linux 2 EC2 인스턴스를 실행하며, SSH 액세스를 활성화하여 사용자 지정 소프트웨어 패키지를 설치할 수 있습니다. 관리형 노드를 프로비저닝하면 여러 가용 영역에 걸쳐 있을 수 있는 EKS 관리형 Auto Scaling 그룹의 일부로 실행되므로 관리형 노드를 생성할 때 제공하는 서브넷을 통해 이를 제어할 수 있습니다. 또한 EKS는 관리형 노드에 자동으로 태그를 지정하여 클러스터 오토스케일러에서 사용할 수 있도록 합니다. + +> Amazon EKS는 관리형 노드 그룹의 CVE 및 보안 패치에 대한 공동 책임 모델을 따릅니다. 관리형 노드는 Amazon EKS에 최적화된 AMI들을 실행하므로 Amazon EKS는 버그 수정 시 이러한 AMI들의 패치 버전을 만들 책임이 있습니다. 하지만 이러한 패치가 적용된 AMI 버전을 관리형 노드 그룹에 배포하는 것은 사용자의 책임입니다. + +EKS는 업데이트 프로세스를 시작해야 하지만 [노드 업데이트도 관리](https://docs.aws.amazon.com/eks/latest/userguide/update-managed-node-group.html)합니다. [관리형 노드 업데이트](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-update-behavior.html) 프로세스는 EKS 설명서에 설명되어 있습니다. + +자체 관리형 노드를 실행하는 경우 [Amazon EKS에 최적화된 Linux AMI](https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html)를 사용하여 작업자 노드를 생성할 수 있습니다. AMI와 노드의 패치 및 업그레이드는 사용자가 담당합니다. `eksctl`, CloudFormation 또는 코드형 인프라 도구를 사용하여 자체 관리형 노드를 프로비저닝하는 것이 가장 좋습니다. 이렇게 하면 [자체 관리형 노드 업그레이드](https://docs.aws.amazon.com/eks/latest/userguide/update-workers.html)를 쉽게 할 수 있기 때문입니다. 마이그레이션 프로세스에서는 이전 노드 그룹을 `NoSchedule`로 **taints**하고 새 스택이 기존 포드 워크로드를 수용할 준비가 되면 노드를 **drains**하기 때문에 작업자 노드를 업데이트할 때 [새 노드로 마이그레이션](https://docs.aws.amazon.com/eks/latest/userguide/migrate-stack.html)하는 것을 고려해 보십시오. 하지만 [자체 관리형 노드의 in-place 업그레이드](https://docs.aws.amazon.com/eks/latest/userguide/update-stack.html)를 수행할 수도 있습니다. + +![공동 책임 모델 - Fargate](./images/SRM-Fargate.jpeg) + +![공동 책임 모델 - MNG](./images/SRM-MNG.jpeg) + +이 가이드에는 EKS 데이터 플레인, Kubernetes 핵심 구성 요소 및 애플리케이션의 신뢰성을 개선하는 데 사용할 수 있는 일련의 권장 사항이 포함되어 있습니다. + +## 피드백 + +이 가이드는 광범위한 EKS/Kubernetes 커뮤니티로부터 직접적인 피드백과 제안을 수집하기 위해 GitHub에 게시 되었습니다. 가이드에 포함시켜야 한다고 생각되는 모범 사례가 있다면 GitHub 리포지토리에 문제를 제출하거나 PR을 제출해 주세요. 서비스에 새로운 기능이 추가되거나 새로운 모범 사례가 개발되면 가이드를 정기적으로 업데이트할 계획입니다. diff --git a/content/security/docs/compliance.md b/content/security/docs/compliance.md index ff3cb7b49..24fbf931f 100644 --- a/content/security/docs/compliance.md +++ b/content/security/docs/compliance.md @@ -53,3 +53,4 @@ Policy can be thought of as a set of rules for governing behaviors, i.e. behavio + [docker-bench-security](https://github.com/docker/docker-bench-security) + [AWS Inspector](https://aws.amazon.com/inspector/) + [Kubernetes Security Review](https://github.com/kubernetes/community/blob/master/sig-security/security-audit-2019/findings/Kubernetes%20Final%20Report.pdf) A 3rd party security assessment of Kubernetes 1.13.4 (2019) ++ [NeuVector by SUSE](https://www.suse.com/neuvector/) open source, zero-trust container security platform, provides compliance reporting and custom compliance checks \ No newline at end of file diff --git a/content/security/docs/iam.md b/content/security/docs/iam.md index f50998dc0..6796b5893 100644 --- a/content/security/docs/iam.md +++ b/content/security/docs/iam.md @@ -63,7 +63,7 @@ Once the user's identity has been authenticated by the AWS IAM service, the kube ### The `aws-auth` ConfigMap -One way Kubernetes integration with AWS authentication can be done is via the `aws-auth` ConfigMap, which resides in the `kube-system` Namespace. It's is responsible for mapping the AWS IAM Identities (Users, Groups, and Roles) authentication, to Kubernates role-based access control (RBAC) authorization. The `aws-auth` ConfigMap is automatically created in your Amazon EKS cluster during its provisioning phase. It was initially created to allow nodes to join your cluster, but as mentioned you can also use this ConfigMap to add RBACs access to IAM principals. +One way Kubernetes integration with AWS authentication can be done is via the `aws-auth` ConfigMap, which resides in the `kube-system` Namespace. It is responsible for mapping the AWS IAM Identities (Users, Groups, and Roles) authentication, to Kubernetes role-based access control (RBAC) authorization. The `aws-auth` ConfigMap is automatically created in your Amazon EKS cluster during its provisioning phase. It was initially created to allow nodes to join your cluster, but as mentioned you can also use this ConfigMap to add RBACs access to IAM principals. To check your cluster's `aws-auth` ConfigMap, you can use the following command. @@ -102,7 +102,7 @@ To manage permissions, you can edit the `aws-auth` ConfigMap adding or removing ### Cluster Access Manager -Cluster Access Manager, now the preferred way to manage access of AWS IAM principals to Amazon EKS clusters, is a functionality of the AWS API as is an opt-in feature for EKS v1.23 and later clusters (new or existing). It simplifies identity mapping between AWS IAM and Kubernetes RBACs, eliminating the need to switch between AWS and Kubernetes APIs or editing the the `aws-auth` ConfigMap for access management, reducing operational overhead, and helping address misconfigurations. The tool also enables cluster administrators to revoke or refine `cluster-admin` permissions automatically granted to the AWS IAM principal used to create the cluster. +Cluster Access Manager, now the preferred way to manage access of AWS IAM principals to Amazon EKS clusters, is a functionality of the AWS API and is an opt-in feature for EKS v1.23 and later clusters (new or existing). It simplifies identity mapping between AWS IAM and Kubernetes RBACs, eliminating the need to switch between AWS and Kubernetes APIs or editing the the `aws-auth` ConfigMap for access management, reducing operational overhead, and helping address misconfigurations. The tool also enables cluster administrators to revoke or refine `cluster-admin` permissions automatically granted to the AWS IAM principal used to create the cluster. This API relies on two concepts: @@ -111,9 +111,9 @@ This API relies on two concepts: > At launch Amazon EKS supports only predefined and AWS managed policies. Access policies are not IAM entities and are defined and managed by Amazon EKS. -Cluster Access Manager allows the combiniation of upstream RBAC with Access Policies supporting allow and pass (but not deny) on Kubernetes AuthZ decisions regarding API server requests. A deny descision will happen when both, the upstream RBAC and Amazon EKS authorizers can't determine the outcome of a request evaluation. +Cluster Access Manager allows the combination of upstream RBAC with Access Policies supporting allow and pass (but not deny) on Kubernetes AuthZ decisions regarding API server requests. A deny descision will happen when both, the upstream RBAC and Amazon EKS authorizers can't determine the outcome of a request evaluation. -With this feature, Amazon EKS support three modes of authentication: +With this feature, Amazon EKS supports three modes of authentication: 1. `CONFIG_MAP` to continue using `aws-auth` configMap exclusively. 2. `API_AND_CONFIG_MAP` to source authenticated IAM principals from both EKS Access Entry APIs and the `aws-auth` configMap, prioritizing the Access Entries. Ideal to migrate existing `aws-auth` permissions to Access Entries. diff --git a/content/security/docs/image.md b/content/security/docs/image.md index 48571d288..65723140f 100644 --- a/content/security/docs/image.md +++ b/content/security/docs/image.md @@ -214,3 +214,4 @@ RUN apt-get update && apt-get install -y \ * [Notary](https://github.com/theupdateframework/notary) A project for signing container images * [Notary v2](https://github.com/notaryproject/nv2) * [Grafeas](https://grafeas.io/) An open artifact metadata API to audit and govern your software supply chain +* [NeuVector by SUSE](https://www.suse.com/neuvector/) open source, zero-trust container security platform, provides container, image and registry scanning for vulnerabilities, secrets and compliance. diff --git a/content/security/docs/incidents.md b/content/security/docs/incidents.md index d0b8de796..87fc7af51 100644 --- a/content/security/docs/incidents.md +++ b/content/security/docs/incidents.md @@ -120,6 +120,7 @@ Periodically attacking your own cluster can help you discover vulnerabilities an + [Gremlin](https://www.gremlin.com/product/#kubernetes), a chaos engineering toolkit that you can use to simulate attacks against your applications and infrastructure. + [Attacking and Defending Kubernetes Installations](https://github.com/kubernetes/sig-security/blob/main/sig-security-external-audit/security-audit-2019/findings/AtredisPartners_Attacking_Kubernetes-v1.0.pdf) + [kubesploit](https://www.cyberark.com/resources/threat-research-blog/kubesploit-a-new-offensive-tool-for-testing-containerized-environments) ++ [NeuVector by SUSE](https://www.suse.com/neuvector/) open source, zero-trust container security platform, provides vulnerability- and risk reporting as well as security event notification ## Videos + [Advanced Persistent Threats](https://www.youtube.com/watch?v=CH7S5rE3j8w) diff --git a/content/security/docs/network.md b/content/security/docs/network.md index 09ebe8a91..c874e1f4c 100644 --- a/content/security/docs/network.md +++ b/content/security/docs/network.md @@ -531,3 +531,4 @@ kubectl apply -f istio-custom-config.yaml + [Verifying Service Mesh TLS in Kubernetes, Using ksniff and Wireshark](https://itnext.io/verifying-service-mesh-tls-in-kubernetes-using-ksniff-and-wireshark-2e993b26bf95) + [ksniff](https://github.com/eldadru/ksniff) + [egress-operator](https://github.com/monzo/egress-operator) An operator and DNS plugin to control egress traffic from your cluster without protocol inspection ++ [NeuVector by SUSE](https://www.suse.com/neuvector/) open source, zero-trust container security platform, provides policy network rules, data loss prevention (DLP), web application firewall (WAF) and network threat signatures. \ No newline at end of file diff --git a/content/security/docs/pods.md b/content/security/docs/pods.md index ba7b5a4ca..e264957d0 100644 --- a/content/security/docs/pods.md +++ b/content/security/docs/pods.md @@ -483,3 +483,4 @@ Policy-as-code and Pod Security Standards can be used to enforce this behavior. + [Policy based countermeasures: part 1](https://aws.amazon.com/blogs/containers/policy-based-countermeasures-for-kubernetes-part-1/) + [Policy based countermeasures: part 2](https://aws.amazon.com/blogs/containers/policy-based-countermeasures-for-kubernetes-part-2/) + [Pod Security Policy Migrator](https://appvia.github.io/psp-migration/) a tool that converts PSPs to OPA/Gatekeeper, KubeWarden, or Kyverno policies ++ [NeuVector by SUSE](https://www.suse.com/neuvector/) open source, zero-trust container security platform, provides process and filesystem policies as well as admission control rules. diff --git a/content/security/docs/runtime.md b/content/security/docs/runtime.md index bbc030523..ac1152f57 100644 --- a/content/security/docs/runtime.md +++ b/content/security/docs/runtime.md @@ -71,3 +71,4 @@ Pod Security Policies offer a lot of different ways to improve your security pos + [Stackrox](https://www.stackrox.com/use-cases/threat-detection/) + [Sysdig Secure](https://sysdig.com/products/kubernetes-security/) + [Prisma](https://docs.paloaltonetworks.com/cn-series) ++ [NeuVector by SUSE](https://www.suse.com/neuvector/) open source, zero-trust container security platform, provides process profile rules and file access rules. \ No newline at end of file diff --git a/content/upgrades/index.md b/content/upgrades/index.md index 0c646a4fd..22337f3b9 100644 --- a/content/upgrades/index.md +++ b/content/upgrades/index.md @@ -203,6 +203,75 @@ Running the check against static manifest files is generally more accurate. If r A deprecated Kubernetes API does not mean the API has been removed. You should check the [Kubernetes Deprecation Policy](https://kubernetes.io/docs/reference/using-api/deprecation-policy/) to understand how API removal affects your workloads. +### Cluster Insights +[Cluster Insights](https://docs.aws.amazon.com/eks/latest/userguide/cluster-insights.html) is a feature that provides findings on issues that may impact the ability to upgrade an EKS cluster to newer versions of Kubernetes. These findings are curated and managed by Amazon EKS and offer recommendations on how to remediate them. By leveraging Cluster Insights, you can minimize the effort spent to upgrade to newer Kubernetes versions. + +To view insights of an EKS cluster, you can run the command: +``` +aws eks list-insights --region --cluster-name + +{ + "insights": [ + { + "category": "UPGRADE_READINESS", + "name": "Deprecated APIs removed in Kubernetes v1.29", + "insightStatus": { + "status": "PASSING", + "reason": "No deprecated API usage detected within the last 30 days." + }, + "kubernetesVersion": "1.29", + "lastTransitionTime": 1698774710.0, + "lastRefreshTime": 1700157422.0, + "id": "123e4567-e89b-42d3-a456-579642341238", + "description": "Checks for usage of deprecated APIs that are scheduled for removal in Kubernetes v1.29. Upgrading your cluster before migrating to the updated APIs supported by v1.29 could cause application impact." + } + ] +} +``` + +For a more descriptive output about the insight received, you can run the command: +``` +aws eks describe-insight --region --id --cluster-name +``` + +You also have the option to view insights in the [Amazon EKS Console](https://console.aws.amazon.com/eks/home#/clusters). After selecting your cluster from the cluster list, insight findings are located under the ```Upgrade Insights``` tab. + +If you find a cluster insight with `"status": ERROR`, you must address the issue prior to performing the cluster upgrade. Run the `aws eks describe-insight` command which will share the following remediation advice: + +Resources affected: +``` +"resources": [ + { + "insightStatus": { + "status": "ERROR" + }, + "kubernetesResourceUri": "/apis/policy/v1beta1/podsecuritypolicies/null" + } +] +``` + +APIs deprecated: +``` +"deprecationDetails": [ + { + "usage": "/apis/flowcontrol.apiserver.k8s.io/v1beta2/flowschemas", + "replacedWith": "/apis/flowcontrol.apiserver.k8s.io/v1beta3/flowschemas", + "stopServingVersion": "1.29", + "clientStats": [], + "startServingReplacementVersion": "1.26" + } +] +``` + +Recommended action to take: +``` +"recommendation": "Update manifests and API clients to use newer Kubernetes APIs if applicable before upgrading to Kubernetes v1.26." +``` + +Utilizing cluster insights through the EKS Console or CLI help speed the process of successfully upgrading EKS cluster versions. Learn more with the following resources: +* [Official EKS Docs](https://docs.aws.amazon.com/eks/latest/userguide/cluster-insights.html) +* [Cluster Insights launch blog](https://aws.amazon.com/blogs/containers/accelerate-the-testing-and-verification-of-amazon-eks-upgrades-with-upgrade-insights/). + ### Kube-no-trouble [Kube-no-trouble](https://github.com/doitintl/kube-no-trouble) is an open source command line utility with the command `kubent`. When you run `kubent` without any arguments it will use your current KubeConfig context and scan the cluster and print a report with what APIs will be deprecated and removed.