많은 기업들에서 kubernetes를 사용하고 있다. 트레픽이 몰리는 경우에 확장성이 쉬우며 사용량 변화에 따라서 리소스를 적게 사용하는것도 가능하기 때문이다.
그리고 kubernetes를 aws환경에서 더 쉽게 사용할 수 있도록 제공해주는 서비스가 EKS이다.
kubernetes에서 각각의 서비스들이 정상 동작하고 있는지 확인하고 컨트롤하는 부분 즉 Control Plane을 AWS에서 모두 처리를 해주기 때문에 사용자는 Master Node를 관리할 필요가 없고 (컨트롤 플레인이 가용성과 확장성을 동시에 관리)
Worker Node만 관리하면 된다. 이 Worker Node도 AWS Node Group으로 관리한다.
또한 EKS에서는 이러한 Master Node와 etcd노드들은 Private Link로 연결되어 내부망 통신으로 안전하게 워커노드와 통신 할 수 있다.
EKS를 사용하기 위해서는 AWS 계정에서 VPC를 생성해야하며 해당하는 VPC에 EKS Cluster를 생성하는 기본 과정을 거쳐야한다.
VPC는 Virtual Private Cloud의 약자로 논리적으로 격리된 가상 네트워크로 해당 네트워크를 생성해야지만 AWS의 리소스들을 생성이 가능하다.
가상 네트워크를 생성할떄는 서브넷 설정과 라우팅 테이블등 다양한 설정이 필요하다.console에서 생성을할때 VPC만이 아닌 VPC등으로 생성을하면 이러한 부분을을 VPC 생성하면서 한번에 생성 처리할 수 있다.
테넌시(tenancy) : ec2인스턴스를 생성할때 테넌시 모델을 설정할 수 있으며 기본(공유)를 설정한 경우 본인의 인스턴스가 하나의 물리적 서버에서 다른 누군가의 인스턴스와 동시에 실행되고 있음을 의미한다.
엄격한 보안 수준이 요구되는 경우에는 전용(dedicated)를 설정하여 사용하는 경우는 물리적으로 격리된 서버를 제공 받아 사용할 수 있다.
가용 역역은(AZ)는 하나의 리전에서 완전이 독립적으로 구성된 영역으로 하나의 지역이 지진, 토네이도등으로 문제가 발생해도 문제로 인한 연쇄작용이 없도록 물리적으로 유의미한 거리를 두고 구성된다.
cidr의 주소 계산이 어려운 경우 다음과 같은 외부 계산기 페이지를 활용할 수 있다.
NAT 게이트웨이를 각각의 AZ에서 설정하는게 나중에 라우팅 테이블 설정이나 설정등에서 깔끔할수도 있지만 비용절감을위해서 1개의 AZ에서 사용해도 괜찮을것 같다.
VPC 엔드포인트의 S3게이트웨이는 불필요한 리소스 사용 금액을 절약하기 위해서 설정을 해준다. s3에 접근할떄 nat g/w 혹은 다른 가용영역을 거쳐서 오는등의 케이스에서 추가적인 요금이 발생하는것을 막아서 s3에 접근할때 인터넷을 거치지 않고 AWS의 private 인터넷을 이용하여 엑세스 하도록 도와준다고 한다.
DNS 호스트 이름 활성화는 VPC내부에서 생성되는 인스턴스에 퍼블릭 DNS 호스트 네임을 할당해주는 기능
DNS 확인 활성화는 DNS 호스트네임을 IP로 해석할때 AWS 에서 제공하는 DNS서버를 사용하는 기능
클러스터 생성을 한다는건 Amazon EKS에 의해 관리되는 컨트롤 플레인을 배포하는 프로세스다.
EKS cluster를 생성하기전에는 해당 cluster에서 사용될 role을 먼저 생성해야한다.
이미지과 같이 IMA에서 EKS를 위한 role을 설정해서 만들어 준다.
EKS에서 관리하는 cluster에서 다른 AWS service resource에 access할 수 있도록 EKS-Cluster를 선택해서 만들어 준다.
이후 EKS를 생성하러 가보면 role이 자동으로 설정되어있는걸 볼 수 있다.
KMS는 key management service의 약자로 해당 기능을 활성화 하면 클러스터의 etcd에 저장된 kubernetes 암호의 엔벨로프 암호화를 제공할 수 있다.
네트워크 설정은 초반에 만들었던 VPC를 사용하며 서브넷을 선택하는거는 private subnet을 설정하면 된다.
서브넷을 설정하는 이유는 클러스터와 원활한 통신을 위해 제어 플레인이 ENI를 배치하는 서브넷을 선택해주는 것이다.
조금 더 상세하게 설명을 하자만 Control plane(EKS master)이 해당 subnet newtork interface를 생성해서 worker node들과 통신을 하기 위함이다. vpc내의 subnet들은 서로 라우팅이 되기 때문에 vpc내의 private subnet을 선택하면된다.
ENI : Elastic Network Interface의 약자로 인스턴스가 AWS의 서비스, 다른 인스턴스, 인터넷등 다른 네트워크 리소스와 통신할 수 있도록 하는 역할을 한다.
설치된 kubernetes 클러스터를 관리하는 api 에 대한 호출을 어떻게 할지 설정하는 부분으로 설정에 따라허 호출이 가능한 영역이 달라지게 된다.
이렇게 EKS를 생성하고 난뒤에는 해당 클러스터의 Node Group을 생성해 줘야한다. 이렇게 생성된 Node 그룹 안에서 내가 서비스하고 싶은 pod들이 배치되고 관리되게 된다.
전체적인 EKS의 그림을 그려보면 위와 같다고 볼 수 있다.
하나의 Region에서 VPC를 생성하고 그 VPC안에는 2개의 가용 영역에 public Subnet과 private Subnet이 존재하며 Eks의 Worknode들은 private subnet에 위치하고 있다.
실제로 서비스를 배포하면서 생기는 Pod들은 이제 work node에 분배되어서 생성되고 관리되게 된다.
EKS의 기본적인 환경설정이 완료된 이후에는 워커노드에서 수행될 쿠버네티스 리소스들을 생성해야한다. 기본적으로 생성된 서비스가 외부의 사용자에게 노출되어 사용되게 하기 위해서 기본적으로 필요한 리소스는 Deployment, Service, Ingress 가 존재한다.
추가로 각각의 서비스별로 논리적인 구분을 위하여 namespace를 사용하는게 좋다.또한 각각의 리소스들에게 권한을 부여하기 위해서 Service Account를 생성해서 생성되는 Pod에 적용되도록 하는 방법이 있다.
Deployment는 실재 앱이 존재하는Pod와 Pod의 복제본 수 인 ReplicaSet을 선언 할 수 있다. 즉 파드와 레플리카세에 대한 선언적 업데이트를 제공한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment #Deployment의 이름이 된다.
labels:
app: nginx
spec:
replicas: 3 # 생성되는 레플리카셋
selector:
matchLabels: # 생성된 레플리카셋이 관리할 파드를 찾아내는 방법을 정의
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2 # 해당파드에서 실행하려는 이미지
ports:
- containerPort: 80
패키지 관리자 없이 직접 해당 yaml을 수행하기를 원한다면 아래의 명령어를 사용하면 된다.
kubectl apply -f /nginx-deployment.yaml
Deployment 를 적용하고 나면 Pod가 생성된다. 생성이되면 각 Pod에는 Ip가 할당되지만 Pod가 죽어서 다시 생성하면 Ip 가변경되는등 유동적이기 때문에 이것만 가지고는 외부에서 혹은 내부에서도 해당하는 Pod를 특정하여 요청을 보낼 수가 없다. 이러한 문제를 해결하기 위해서 Service를 활용한다.
Service는 파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법이다. 서비스가 대상으로 하는 파드 집합은 일반적으로 셀렉터가 결정한다.
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: ClusterIP # 여러종류의 타입을 설정할 수 있다.
ports:
- name: http
protocol: TCP
targetPort: 9376
port: 80
selector:
app: myapp
type: frontend
Service의 대표적인 타입은 아래와 같다.
NLB(Network Load Balancer) : 고성능을 요구하는 환경에서 부하분산에 적합한 솔루션이다. 낮은 레이턴시로 초당 수백만 건의 요청을 처리할 수 있으며 갑작스러운 트래픽 증대 및 변화에도 최적화되어있다.
CLB(Classic Load Balancer) : 레거시 로드 밸런서이다. HTTP, HTTPS, TCP 및 TLS 트래픽을 처리할 수 있지만 ALB 및 NLB 보다 기능은 훨씬 적다
HTTP, HTTPS 요청을 규칙에 따라 Service에 전달해주는 역할을 하며 AWS의 경우 ALB가 생성된다(L7)
EKS에서 Ingress를 생성하고자 할경우 ingress controller가 필요하며
AWS LoadBalancer Controller를 통하여 ingress생성을 위한 alb 구성을 해야한다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubenertes.io/scheme: internet-facing
alb.ingress.kubernetes.io/load-balancer-name: my-alb
alb.ingress.kubernetes.io/target-type: instance
spec:
rules:
- http:
paths:
- path: /
pathType: Prifix
backend:
service:
name: myapp-service
port:
number: 80
Ingress 파일을 작성하면서 알아야할점이 몇가지가 있다.
전체적인 그림을 보면 위와 같이 Ingress 를 적용하면 public subnet에서 alb가 생성되어서 외부의 요청을 전달 받고 설정한 정보에 맞춰서 요청을 분배한다. 그림에는 표기되지 않았지만 ALB가 생성될떄 설정한 정보에 맞게 target group이 생성되며 해당 그룹에서는 연결된 service에 해당하는 정보에 대해서 기본 상태를 확인하면서 연결점을 유지한다.
추가로 외부에서 호출을 할때 Ingress에 설정하는 SG그룹 설정을 잘 해줘야한다. 해당 인바운드 규칙에 허용되는 경우에만 호출이 허용되기 때문이다.
ALB는 7계층에서만 작동하는 로드밸런서이다. WebSocket과 HTTP/2 프로토콜들 지원하며, 표준 프로토콜 지원을 통해서 네트워크 트래픽은 줄이고 접속의 효율을 높이게 된다.
ALB의 장점
AWS EKS 서비스를 관리하기 위해서는 kubecofig 정보를 받아서 lens 혹은 k9s와 같은 모니터링툴을 통해서 정보를 확인하는게 편하다.
AWS Cli가 설치가되고 기본 유저 정보가 들어가 있다고 했을때 아래의 명령어를 통해서 클러스터 정보를 kubeconfig 파일에 업데이트 할 수 있다.
# 설정된 AWS 유저 정보 확인
aws sts get-caller-identity
# 클러스터 정보 업데이트
aws eks update-kubeconfig --region region-code --name my-cluster
정보 출처 : AWS 가이드 문서
참조 문서 : 쿠버네티스 가이드 문서
thanks