✅ 2주차 과제
Kubernetes 기반의 EKS 환경 구성과 웹 서비스 구축
- Kubernetes 환경을 구축
- EKS 클러스터와 노드 그룹 생성
- Nginx 서비스 배포
📌 What is Kubernetes?
- Container 오케스트레이션 툴 (ex. Docker Swarm)
- Container를 쉽고 빠르게 배포/확장하고 관리를 자동화하는 오픈 소스 플랫폼 = 컨테이너 관리 툴
- Docker가 Container 기반 가상화를 실현한 플랫폼이라면, Container를 관리하는 것이 Kubernetes
즉, 모놀리식에서 MSA로 넘어가는 추세에 Container 기반의 가상화 기술을 가진 Docker가 나왔다.
Dockerfile을 이용해 Image를 생성하고 Container를 실행시키기만 하면 애플리케이션 배포가 손쉽게 이루어지니 좋긴 좋았는데, 문제는 Container들 간의 컨트롤이나 개수가 많아졌을 때 커버하기가 힘들어졌다.
그러한 Container들을 관리해주는 것이 Kubernetes다.
가끔 Kubernetes가 Docker를 여러 개 관리한다는 식으로 언급을 하거나 이미지를 가져다 놓은 사람이 있던데, 둘 다 Container를 관리하는 플랫폼이다.
Kubernetes가 Docker를 관리하는 것은 아니다.
요새 내가 서버 분리 작업하고 있는 프로젝트 페이지 🤭
재밌는 글이 있어서 들고 왔다.
📌 용어 정리
1️⃣ Master & Node
- Master : 클러스터 전체를 관리하는 Controller
- Node : Container가 배포되는 (가상 혹은 물리적인)Machine
2️⃣ Object
쿠버네티스는 가장 기본적인 구성단위인 기본 오브젝트와, 기본 오브텍트를 생성하고 관리하는 컨트롤러, 오브젝트의 스펙 이외에 추가 정보인 메타 정보들로 구성이 된다.
- 오브젝트 스펙(Object Spec)
- Object들은 모두 Obeject의 설정 정보를 기술한 Object Spec으로 정의가 된다.
- kubectl 커맨드 라인을 통해서 Object 생성 시 인자로 전달하여 정의할 수 있다.
- kubectl : Kubernetes를 다루기 위한 명령행 도구
- 혹은 yaml이나 json 파일로 설정할 수도 있다.
- 기본 오브젝트(Basic Object)
- Kubernetes에 의해 배포 및 관리되는 가장 기본적인 Object
- Pod(컨테이너화된 애플리케이션), Service(로드밸런서), Volume(디스크), Namespace(패키지명) 4가지
- Pod
- Kubernetes에서 가장 기본적인 배포 단위, Container를 포함하는 단위
- Pod은 하나 이상의 Container를 포함하며, Pod이라는 단위로 배포한다.
- Pod 내의 Container는 IP와 Port를 공유한다.
- Pod 내에 배포된 Container 간에는 Disk Volume을 공유할 수 있다.
- Pod는 동적으로 생성되고, 장애가 생기면 리스타트 되면서 IP 주소가 바뀐다.
- Pod 당 하나의 Container를 넣을 수도 있지만, 애플리케이션에서 사용하는 주변 프로그램을 같이 배포하는 패턴을 MSA에서 사이드카 패턴(Side car pattern)이라고 한다.
- Deployment
- 애플리케이션 배포의 단위가 되는 Resource. Controller의 한 종류
- 몇 개의 Pod가 얼마만큼의 자원을 사용할지, 어떤 방식으로 배포할지 정의한다. ⇒ Pod 관리(Contoller)
- Pod 배포를 위해 RC를 생성 및 관리하며, 롤백을 위한 기존 버전 RC 등의 과정을 자동화하고 추상화한 개념
- (쉽게 말해서, Pod는 객체같은 애고 Deployment는 클래스같은 애다.)
- Service
- Pod를 외부에 노출시켜주는 로드밸런서
- Pod는 각각의 WorkerNode에 배포되고 Service를 통해 외부에 노출된다.
- Pod는 동적으로 추가/삭제 되기 때문에 로드밸런서가 라벨(label)과 라벨 셀렉터(label selector)로 유연하게 선택한다.
- Label Selector : 어떤 Pod을 Service로 묶을 것인지 meta data 정보 부분에 label을 정의
- Label : Kubernetes의 Resource를 선택하는데 사용된다.
- Volume
- Pod가 기동할 때 기본적으로 Container마다 Local Disk를 생성한다. (비영구적)
- 영구 저장을 위한 외부 Storage며, Pod가 기동할 때 Container에 mount한다.
- Pod 내 Container 간에 공유가 가능하다.
- Name space
- Kubernetes 클러스터 내의 논리적인 분리 단위
- Pod, Service 등은 Name space 별로 생성 및 관리될 수 있으며, 사용자 권한 역시 Name space 별로 나누어 부여할 수 있다.
📌 Kubernetes Cluster Architecture
위에서 열심히 떠든 건 우측 하단의 Kubernetes 워커 노드 부분(ex. EKS Node Group)이다.
좌측의 Master는 보통 빌려 쓴다. (왜? 그걸 만들었으면 기업들이 날 모셔갔겠지..)
- Master : Kubernetes 클러스터 전체를 Control하는 System
- API Server
- Kubernetes는 모든 명령과 통신을 REST API로 제공하고 그에 대한 명령을 처리한다.
- Etcd
- Kubernetes 클러스터의 Database 역할이 되는 서버
- 설정값이나 클러스터의 상태를 저장한다.
- 분산형 key-value store 오픈소스
- Scheduler
- Pod, Service 등 각 Resource들을 적절한 Node에 할당한다.
- Controller Manager
- Controller(Replica controller, Service controller, Volume controller, Node controller 등)를 생성하고 각 Node에 배포하며 관리하는 역할
- DNS
- Kubernetes는 Resource의 End-point를 DNS로 매핑하고 관리한다.
- Pod나 Service는 동적 Resource이므로 IP 주소가 고정이 되지 않아서 Resource의 위치 정보가 필요하다. (Service discovery 패턴)
- 새로운 Resource가 생기면, 해당 Resource의 IP와 DNS 이름을 등록하여, DNS 이름을 기반으로 Resource에서 접근하는 Server
- API Server
- Node : Master에 의해 명령을 받고 실제 워크로드를 생성하여 서비스하는 Component
- Kuberlet
- Node에 배포되는 에이전트
- Master의 API Server와 통신을 하면서, Node가 수행해야할 명령을 받고, Node의 상태 등을 Master로 전달
- Kube-proxy
- Node로 들어오는 Network 트래픽을 적절한 Container로 Routing
- 로드 밸런싱 등 Node로 들어오고 나가는 Network 트래픽을 Proxy
- Node와 Master 간의 Network 통신 관리
- Container runtime
- Pod를 통해서 배포된 Container를 실행하는 Container runtime
- Docker 외에도 rkt, Hyper container 등 다양한 런타임이 존재한다.
- cAdvisor
- 각 Node에서 기동되는 모니터링 에이전트
- Node 내에서 가동되는 Container들의 상태와 성능 등의 정보를 수집하여, Master Server의 API Server로 전달한다.
- 주로 모니터링을 위해 사용되는 데이터들이다.
- Kuberlet
✒️ 관리형 Kubernetes VS. 자체 호스팅
Kubernetes를 자체적으로 구축이 가능하지만, 위의 Architecture을 구축하고 지속적인 관리가 필요하다.
문제는 설치도 어렵고, Kubernetes의 업데이트가 빨라서 관리가 굉장히 힘들다.
따라서 AWS의 EKS, Google의 GKE, Azure의 AKS 같은 고가용성이 보장된 관리형 Kubernetes를 사용하는 것이 좋다. (EKS = Elastric Kubernetes Service)
📌 EKS 환경 구성
0️⃣ 시작하기 앞서..
$ sudo yum update
$ aws --version
aws version이 1.18 이상임을 확인해주어야 한다. (그래야 kubectl 명령어에서 에러가 안 뜬다.)
1️⃣ Bastion에 kubectl 설치
// 1.8 버전의 kubectl 설치
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.18.0/bin/linux/amd64/kubectl
// 실행권한 추가
$ chmod +x ./kubectl
// PATH가 설정된 디렉터리로 변경
$ sudo mv ./kubectl /usr/local/bin/kubectl
// 설치 확인
$ kubectl version --client
2️⃣ IAM 설정
이런 식으로 따라서 만들면 된다.
다시 EC2로 돌아와서 생성한 Instance에 우클릭을 해보면
방금 생성한 mission-admin-Role을 넣어준다.
3️⃣ eksctl 명령어 설치
// eksctl 설치 파일 다운로드
$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
// PATH가 설정된 디렉토리로 변경
$ sudo mv /tmp/eksctl /usr/local/bin
// 설치 확인
$ eksctl version
4️⃣ WorkerNode 용 Key 생성
$ mkdir .ssh
$ cd .ssh
$ ssh-keygen
$ aws configure set region ap-northeast-2
// 생성된 public key를 사용중인 EC2 리전으로 업로드
$ aws ec2 import-key-pair --key-name "workernode-key" --public-key-material file://~/.ssh/id_rsa.pub
실제로 key pair가 올라온 것을 EC2에서도 확인할 수 있다.
5️⃣ EKS Cluster와 worker Node 생성
(여기 20분이나 걸린다..새벽에 빨리 하고 치우려다가 강제 수면권 박탈...)
$ eksctl create cluster --name mission-cluster --version 1.26 --region ap-northeast-2 --nodegroup-name mission-wn --node-type t3.medium --nodes 1 --nodes-min 1 --nodes-max 1 --ssh-access --ssh-public-key workernode-key --managed
- --name : EKS Cluster 이름
- --version : EKS Cluster 버전
- --region : 지역
- --nodegroup-name : Node group 이름
- --node-type : Node xkdlq
- --ssh-public-key : worker node 접속에 사용할 key
"region is ready"라는 문구가 뜨면 설치가 완료된 것이다.
$ kubectl get node
이렇게 정상적으로 뜬다면 Cluster와 Node Group까지 만들어졌다.
📌 Nginx Service 배포
1. Deployment를 정의하여 Nginx Container를 담은 Pod를 띄운다.
2. Pod를 LoadBalancer Type의 Service를 통해 배포한다.
3. 자동 생성된 ELB를 통해 Nginx가 배포된 것을 확인한다.
Deployment에 대한 정의는 강의에서 제공해주셨는데, 내용 분석은 다음에 하도록 하고 이걸 어떻게 잘 올린 후라면 다음과 같은 명령어를 수행해주면 된다.
// 작성한 nginx-depolyment.yaml로 배포
kubectl apply -f nginx-deployment.yaml
// 생성한 pod 확인
kubectl get pod
Service에 대한 yaml도 따로 작성을 하고 배포를 해주면 된다. (로드 밸런서)
$ kubectl apply -f nginx-service.yaml
$ kubectl get service
그러면 실제로 Load balancers가 생긴다.
그리고 여기서 DNS name을 통해 web에서 EXTERNAL-IP:80으로 Nginx 접속을 확인할 수 있다.
📌 Cluster와 NodeGroup 삭제
//nginx-service 삭제
$ kubectl delete –f nginx-service.yaml
//nginx-deployment 삭제
$ kubectl delete –f nginx-deployment.yaml
돈 나가니까 빨리 없애버리고 EC2 > 로드밸런서 > CLB 삭제 확인까지 해주어야 한다.
$ eksctl delete cluster --region ap-northeast-2 --name=mission-cluster
EKS Cluster와 Node Group까지 삭제해버리자.