

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# EKS 제어 플레인
<a name="control-plane"></a>

**작은 정보**  
 Amazon EKS 워크숍을 통해 모범 사례를 [살펴봅니다](https://aws-experience.com/emea/smb/events/series/get-hands-on-with-amazon-eks?trk=4a9b4147-2490-4c63-bc9f-f8a84b122c8c&sc_channel=el).

Amazon Elastic Kubernetes Service(EKS)는 자체 Kubernetes 컨트롤 플레인 또는 작업자 노드를 설치, 운영 및 유지 관리할 필요 없이 AWS에서 Kubernetes를 쉽게 실행할 수 있는 관리형 Kubernetes 서비스입니다. 업스트림 Kubernetes를 실행하며 Kubernetes 준수 인증을 받았습니다. 이러한 적합성을 통해 EKS는 EC2 또는 온프레미스에 설치할 수 있는 오픈 소스 커뮤니티 버전과 마찬가지로 Kubernetes APIs를 지원합니다. 업스트림 Kubernetes에서 실행되는 기존 애플리케이션은 Amazon EKS와 호환됩니다.

EKS는 Kubernetes 컨트롤 플레인 노드의 가용성과 확장성을 자동으로 관리하고 비정상 컨트롤 플레인 노드를 자동으로 교체합니다.

## EKS 아키텍처
<a name="reliability_cpeks_architecture"></a>

EKS 아키텍처는 Kubernetes 컨트롤 플레인의 가용성과 내구성을 손상시킬 수 있는 단일 장애 지점을 제거하도록 설계되었습니다.

EKS에서 관리하는 Kubernetes 컨트롤 플레인은 EKS 관리형 VPC 내에서 실행됩니다. EKS 컨트롤 플레인은 Kubernetes API 서버 노드 등 클러스터로 구성됩니다. API 서버, 스케줄러와 같은 구성 요소를 실행하고 Auto Scaling 그룹에서 `kube-controller-manager` 실행되는 Kubernetes API 서버 노드입니다. EKS는 AWS 리전 내의 개별 가용 영역(AZs)에서 최소 2개의 API 서버 노드를 실행합니다. 마찬가지로 내구성을 위해 etcd 서버 노드는 세 개의 AZs. EKS는 각 AZ에서 NAT 게이트웨이를 실행하고 API 서버 및 etcd 서버는 프라이빗 서브넷에서 실행됩니다. 이 아키텍처는 단일 AZ의 이벤트가 EKS 클러스터의 가용성에 영향을 미치지 않도록 합니다.

새 클러스터를 생성하면 Amazon EKS는 클러스터와 통신하는 데 사용하는 관리형 Kubernetes API 서버에 대해 가용성이 높은 엔드포인트를 생성합니다(와 같은 도구 사용`kubectl`). 관리형 엔드포인트는 NLB를 사용하여 Kubernetes API 서버를 로드 밸런싱합니다. 또한 EKS는 작업자 노드와의 통신을 용이하게 하기 위해 서로 다른 AZs에 두 개의 [ENI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-eni.html)를 프로비저닝합니다.

EKS 데이터 영역 네트워크 연결

![연결](http://docs.aws.amazon.com/ko_kr/eks/latest/best-practices/images/reliability/eks-data-plane-connectivity.jpeg)


퍼블릭 인터넷(퍼블릭 엔드포인트 사용) 또는 VPC(EKS 관리형 ENIs 사용) 또는 둘 다에서 [Kubernetes 클러스터의 API 서버에 연결할 수 있는지 여부를 구성할](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html) 수 있습니다.

사용자 및 작업자 노드가 퍼블릭 엔드포인트를 사용하여 API 서버에 연결하든 EKS 관리형 ENI를 사용하여 API 서버에 연결하든, 연결을 위한 중복 경로가 있습니다.

## 권장 사항
<a name="cp-recs"></a>

다음 권장 사항을 검토합니다.

## 컨트롤 플레인 지표 모니터링
<a name="reliability_cpmonitor_control_plane_metrics"></a>

Kubernetes API 지표를 모니터링하면 컨트롤 플레인 성능에 대한 인사이트를 얻고 문제를 식별할 수 있습니다. 비정상 컨트롤 플레인은 클러스터 내에서 실행되는 워크로드의 가용성을 손상시킬 수 있습니다. 예를 들어, 잘못 작성된 컨트롤러는 API 서버를 오버로드하여 애플리케이션의 가용성에 영향을 미칠 수 있습니다.

Kubernetes는 `/metrics` 엔드포인트에서 컨트롤 플레인 지표를 노출합니다.

를 사용하여 노출된 지표를 볼 수 있습니다`kubectl`.

```
kubectl get --raw /metrics
```

이러한 지표는 [Prometheus 텍스트 형식으로](https://github.com/prometheus/docs/blob/master/content/docs/instrumenting/exposition_formats.md) 표시됩니다.

Prometheus를 사용하여 이러한 지표를 수집하고 저장할 수 있습니다. 2020년 5월에 CloudWatch는 CloudWatch Container Insights에서 Prometheus 지표 모니터링에 대한 지원을 추가했습니다. 따라서 Amazon CloudWatch를 사용하여 EKS 컨트롤 플레인을 모니터링할 수도 있습니다. [자습서를 사용하여 새 Prometheus 스크레이프 대상 추가: Prometheus KPI 서버 지표를 사용하여 지표를 수집하고 CloudWatch 대시보드를 생성하여 클러스터의 컨트롤 ](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/ContainerInsights-Prometheus-Setup-configure.html#ContainerInsights-Prometheus-Setup-new-exporters)플레인을 모니터링할 수 있습니다. CloudWatch 

여기에서 Kubernetes API 서버 지표를 찾을 수 [있습니다](https://github.com/kubernetes/apiserver/blob/master/pkg/endpoints/metrics/metrics.go). 예를 들어는 API 요청을 실행하는 데 걸리는 시간을 나타낼 `apiserver_request_duration_seconds` 수 있습니다.

다음 컨트롤 플레인 지표를 모니터링하는 것이 좋습니다.

### API 서버
<a name="reliability_cpapi_server"></a>


| 지표 | 설명 | 
| --- | --- | 
|  `apiserver_request_total`  | 각 동사, 드라이 런 값, 그룹, 버전, 리소스, 범위, 구성 요소 및 HTTP 응답 코드에 대해 분류된 apiserver 요청의 카운터. | 
|  `apiserver_request_duration_seconds*`  | 각 동사, 모의 실행 값, 그룹, 버전, 리소스, 하위 리소스, 범위 및 구성 요소에 대한 초 단위의 응답 지연 시간 히스토그램입니다. | 
|  `apiserver_admission_controller_admission_duration_seconds*`  | 이름별로 식별되고 각 작업과 API 리소스 및 유형에 대해 구분된 초 단위의 허용 컨트롤러 지연 시간 히스토그램(검증 또는 승인). | 
|  `apiserver_admission_webhook_rejection_count`  | 승인 웹후크 거부 수입니다. 이름, 작업, rejection\_code, 유형(검증 또는 승인), error\_type(calling\_webhook\_error, apiserver\_internal\_error, no\_error)으로 식별됨 | 
|  `rest_client_request_duration_seconds*`  | 초 단위로 지연 시간 히스토그램을 요청합니다. 동사 및 URL로 분류됩니다. | 
|  `rest_client_requests_total`  | 상태 코드, 메서드 및 호스트로 분할된 HTTP 요청 수. | 
+ 히스토그램 지표에는 \_bucket, \_sum 및 \_count 접미사가 포함됩니다.

### etcd
<a name="reliability_cpetcd"></a>


| 지표 | 설명 | 
| --- | --- | 
|  `etcd_request_duration_seconds*`  | 각 작업 및 객체 유형에 대한 Etcd 요청 지연 시간 히스토그램. | 
|  `apiserver_storage_db_total_size_in_bytes` 또는 `apiserver_storage_size_bytes` (EKS v1.28로 시작) | Etcd 데이터베이스 크기입니다. | 
+ 히스토그램 지표에는 \_bucket, \_sum 및 \_count 접미사가 포함됩니다.

[Kubernetes 모니터링 개요 대시보드](https://grafana.com/grafana/dashboards/14623)를 사용하여 Kubernetes API 서버 요청, 지연 시간 및 기타 지연 시간 지표를 시각화하고 모니터링하는 것이 좋습니다.

**중요**  
데이터베이스 크기 제한을 초과하면 etcd는 스페이스 없음 경보를 내보내고 추가 쓰기 요청 수행을 중지합니다. 즉, 클러스터는 읽기 전용이 되며 새 포드 생성, 배포 조정 등과 같은 객체를 변경하기 위한 모든 요청은 클러스터의 API 서버에서 거부됩니다.

## 클러스터 인증
<a name="reliability_cpcluster_authentication"></a>

EKS는 현재 [보유자/서비스 계정 토큰](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens)과 [웹후크 토큰 인증을 사용하는 IAM 인증이라는 두 가지 유형의 인증을](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication) 지원합니다. 사용자가 Kubernetes API를 호출하면 웹후크는 요청에 포함된 인증 토큰을 IAM에 전달합니다. 서명된 기본 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 서비스를 사용할 수 없는 경우 Kubernetes 서비스 계정의 보유자 토큰을 사용하여 클러스터를 관리할 수도 있습니다.

클러스터에서 모든 작업을 수행할 수 있는 `super-admin` 계정을 생성합니다.

```
kubectl -n kube-system create serviceaccount super-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}'`
```

보안 암호와 연결된 토큰 가져오기:

```
TOKEN=`kubectl -n kube-system get secret $SECRET_NAME -o jsonpath='{.data.token}'| base64 --decode`
```

에 서비스 계정 및 토큰 추가`kubeconfig`:

```
kubectl config set-credentials super-admin --token=$TOKEN
```

수퍼 관리자 계정을 사용하려면에서 현재 컨텍스트`kubeconfig`를 설정합니다.

```
kubectl config set-context --current --user=super-admin
```

최종는 다음과 같아`kubeconfig`야 합니다.

```
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data:<REDACTED>
    server: https://<CLUSTER>.gr7.us-west-2.eks.amazonaws.com
  name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
contexts:
- context:
    cluster: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
    user: super-admin
  name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
current-context: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
kind: Config
preferences: {}
users:
#- name: arn:aws:eks:us-west-2:<account number>:cluster/<cluster name>
#  user:
#    exec:
#      apiVersion: client.authentication.k8s.io/v1beta1
#      args:
#      - --region
#      - us-west-2
#      - eks
#      - get-token
#      - --cluster-name
#      - <<cluster name>>
#      command: aws
#      env: null
- name: super-admin
  user:
    token: <<super-admin sa's secret>>
```

## Admission Webhook
<a name="reliability_cpadmission_webhooks"></a>

Kubernetes에는 승인 웹후크 [검증과 승인 웹후크 변경이라는 두 가지 유형의 승인 웹후크가 있습니다](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers). 이를 통해 사용자는 kubernetes API를 확장하고 API에서 객체를 수락하기 전에 객체를 검증하거나 변경할 수 있습니다. 이러한 웹후크의 구성이 좋지 않으면 클러스터 중요 작업을 차단하여 EKS 컨트롤 플레인이 불안정해질 수 있습니다.

클러스터 중요 작업에 영향을 주지 않으려면 다음과 같이 "catch-all" 웹후크를 설정하지 마십시오.

```
- name: "pod-policy.example.com"
  rules:
  - apiGroups:   ["*"]
    apiVersions: ["*"]
    operations:  ["*"]
    resources:   ["*"]
    scope: "*"
```

또는 웹후크를 사용할 수 없는 경우 클러스터 중요 워크로드가 손상되지 않도록 웹후크에 제한 시간이 30초 미만인 페일 오픈 정책이 있는지 확인합니다.

### 안전하지 않은 블록 포드 `sysctls`
<a name="reliability_cpblock_pods_with_unsafe_sysctls"></a>

 `Sysctl`는 사용자가 런타임 중에 커널 파라미터를 수정할 수 있는 Linux 유틸리티입니다. 이러한 커널 파라미터는 네트워크, 파일 시스템, 가상 메모리, 프로세스 관리 등 운영 체제 동작의 다양한 측면을 제어합니다.

Kubernetes를 사용하면 포드에 `sysctl` 프로필을 할당할 수 있습니다. Kubernetes는 안전 및 안전하지 않은 `systcls` 것으로 분류됩니다. 안전`sysctls`은 컨테이너 또는 포드에 네임스페이스가 있으며, 이를 설정해도 노드 또는 노드 자체의 다른 포드에는 영향을 주지 않습니다. 반면 안전하지 않은 sysctl은 다른 포드를 중단하거나 노드를 불안정하게 만들 수 있으므로 기본적으로 비활성화됩니다.

안전하지 않은 `sysctls`는 기본적으로 비활성화되어 있으므로 kubelet은 안전하지 않은 `sysctl` 프로파일이 있는 포드를 생성하지 않습니다. 이러한 포드를 생성하면 스케줄러는 노드를 시작하지 못하는 동안 해당 포드를 노드에 반복적으로 할당합니다. 이 무한 루프는 궁극적으로 클러스터 컨트롤 플레인을 변형시켜 클러스터를 불안정하게 만듭니다.

안전하지 않은 포드를 거부하려면 [OPA Gatekeeper](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/)를 사용하는 것이 좋습니다`sysctls`.

## 클러스터 업그레이드 처리
<a name="reliability_cphandling_cluster_upgrades"></a>

2021년 4월 이후 Kubernetes 릴리스 주기가 연간 릴리스 4개(분기당 1회)에서 연간 릴리스 3개로 변경되었습니다. 약 1[5주마다](https://kubernetes.io/blog/2021/07/20/new-kubernetes-release-cadence/#what-s-changing-and-when) 새로운 마이너 버전(예: 1.**21** 또는 1.**22**)이 릴리스됩니다. Kubernetes 1.19부터 각 마이너 버전은 처음 릴리스된 후 약 12개월 동안 지원됩니다. Kubernetes v1.28이 출시되면서 컨트롤 플레인과 작업자 노드 간의 호환성 편차가 n-2에서 n-3 마이너 버전으로 확장되었습니다. 자세한 내용은 [클러스터 업그레이드 모범 사례를 참조하세요](cluster-upgrades.md).

## 클러스터 엔드포인트 연결
<a name="reliability_cpcluster_endpoint_connectivity"></a>

Amazon EKS(Elastic Kubernetes Service)로 작업할 때 Kubernetes 컨트롤 플레인 조정 또는 패치 적용과 같은 이벤트 중에 연결 시간 초과 또는 오류가 발생할 수 있습니다. 이러한 이벤트로 인해 kube-apiserver 인스턴스가 교체되어 FQDN을 해결할 때 다른 IP 주소가 반환될 수 있습니다. 이 문서에서는 Kubernetes API 소비자가 안정적인 연결을 유지하기 위한 모범 사례를 간략하게 설명합니다.

**참고**  
이러한 모범 사례를 구현하려면 새로운 DNS 재해상 및 재시도 전략을 효과적으로 처리하기 위해 클라이언트 구성 또는 스크립트를 업데이트해야 할 수 있습니다.

주요 문제는 DNS 클라이언트 측 캐싱과 퍼블릭 엔드포인트의 *퍼블릭 NLB 또는 프라이빗 엔드포인트의 X-ENI*와 같은 EKS 엔드포인트의 오래된 IP 주소의 가능성에서 비롯됩니다. kube-apiserver 인스턴스를 교체하면 FQDN(정규화된 도메인 이름)이 새 IP 주소로 확인될 수 있습니다. 그러나 AWS 관리형 Route 53 영역에서 60초로 설정된 DNS TTL(Time to Live) 설정으로 인해 클라이언트는 짧은 시간 동안 오래된 IP 주소를 계속 사용할 수 있습니다.

이러한 문제를 완화하기 위해 Kubernetes API 소비자(예: kubectl, CI/CD 파이프라인 및 사용자 지정 애플리케이션)는 다음 모범 사례를 구현해야 합니다.
+ DNS 재분해 구현
+ 백오프 및 지터를 사용하여 재시도를 구현합니다. 예를 들어 [Failures Happen이라는 제목의이 문서를](https://aws.amazon.com/builders-library/timeouts-retries-and-backoff-with-jitter/) 참조하세요.
+ 클라이언트 제한 시간을 구현합니다. 장기 실행 요청이 애플리케이션을 차단하지 못하도록 적절한 제한 시간을 설정합니다. 일부 Kubernetes 클라이언트 라이브러리, 특히 OpenAPI 생성기에서 생성된 라이브러리는 사용자 지정 제한 시간을 쉽게 설정하지 못할 수 있습니다.
  + kubectl이 있는 예제 1:

  ```
    kubectl get pods --request-timeout 10s # default: no timeout
  ```
  + Python을 사용하는 예제 2: [Kubernetes 클라이언트는 \_request\_timeout 파라미터를 제공합니다](https://github.com/kubernetes-client/python/blob/release-30.0/kubernetes/client/api_client.py#L120).

이러한 모범 사례를 구현하면 Kubernetes API와 상호 작용할 때 애플리케이션의 안정성과 복원력을 크게 개선할 수 있습니다. 특히 시뮬레이션된 장애 조건에서 이러한 구현을 철저히 테스트하여 실제 조정 또는 패치 이벤트 중에 예상대로 작동하는지 확인해야 합니다.

## 대규모 클러스터 실행
<a name="reliability_cprunning_large_clusters"></a>

EKS는 컨트롤 플레인 인스턴스의 로드를 능동적으로 모니터링하고 자동으로 규모를 조정하여 고성능을 보장합니다. 그러나 대규모 클러스터를 실행할 때 AWS 서비스의 Kubernetes 및 할당량 내에서 발생할 수 있는 성능 문제와 제한을 고려해야 합니다.
+ 서비스가 1,000개 이상인 클러스터는 ProjectCalico 팀이 수행한 테스트에 따라 `kube-proxy` `iptables` 모드에서를 사용할 때 네트워크 지연 시간이 발생할 수 있습니다. [ ProjectCalico ](https://www.projectcalico.org/comparing-kube-proxy-modes-iptables-or-ipvs/) 해결 방법은 [`ipvs` 모드에서 실행 중으로 전환하는 `kube-proxy` 것입니다](ipvs.md).
+ CNI가 포드의 IP 주소를 요청해야 하거나 새 [EC2 인스턴스를 자주 생성해야 하는 경우에도 EC2 API 요청 제한이](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/throttling.html) 발생할 수 있습니다. EC2 IP 주소를 캐싱하도록 CNI를 구성하여 EC2 API 호출을 줄일 수 있습니다. 더 큰 EC2 인스턴스 유형을 사용하여 EC2 조정 이벤트를 줄일 수 있습니다.

## 추가 리소스:
<a name="reliability_cpadditional_resources"></a>
+  [Amazon EKS 워커 노드에 대한 클러스터 네트워킹 설명 해제](https://aws.amazon.com/blogs/containers/de-mystifying-cluster-networking-for-amazon-eks-worker-nodes/) 
+  [Amazon EKS 클러스터 엔드포인트 액세스 제어](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html) 
+  [AWS re:Invent 2019: Amazon EKS under the hood(CON421-R1)](https://www.youtube.com/watch?v=7vxDWDD2YnM) 