본문 바로가기

KOSA 클라우드 솔루션즈 아키텍트 양성과정

[7.14] Kubernetes (ECS, ad-hoc, yaml, Node, Cluster)

--- Amazon ECS(Elastic Container Service)

ECS : manager 역할
EC2 : worker 역할
작업 정의 => 클러스터 생성

# ECS 작업 정의

EC2 선택

 

 

- 테스크 정의 이름 : MY-TD(Task Definition)

- 테스크 역할(role) : AWS의 서비스가 이용하는 권한 정책, 비워 두면 알아서 테스크 역할을 부여함

 

실습용 t2.micro는 케파가 작아서 테스크 하나만 넣을 것이므로 비워 두기

 

 

이미지 : nginx 라고만 입력하고, 따로 주소를 주지 않으면, 도커 허브를 우선적으로 탐색함

메모리 제한 : 메모리를 의무적으로 제한하게 설정되어 있음


# 클러스터 생성

 

EC2 Linux + 네트워킹 선택

 

 

스팟 : 만약 다른 사람이 더 높은 가격을 제시하여 EC2 하나가 지워져도 자아치유 기능으로 새로운 EC2를 생성함

 

 


# 서비스 생성

 

작업 개수 : EC2 안에 테스크를 한 개씩 넣게 되면 EC2가 두 개니까 테스크도 두 개가 되는 것

최소 정상 상태 백분율 : 50으로 설정 시 1개까지 줄어들 수 있음

최대 백분율 : 작업 개수 대비 백분율을 의미, 백분율이 200이면 작업 개수가 최대 4개까지 증가할 수 있는 것

 

 

 


# kube-controller-manager

 

- 노드 컨트롤러
=> 노드가 다운되었을 때 통지와 대응에 관한 책임
- 레플리케이션 컨트롤러
=> 알맞은 수의 pod를 유지하는 책임(Desired state를 유지), 실제로 pod를 증가시키는 것은 스케쥴러의 역할
엔드포인트 컨트롤러
=> 서비스와 pod를 연결(pod안의 컨테이너에 접속)
서비스 어카운트 & 토큰 컨트롤러
=> 새로운 네임스페이스에 대한 기본 계정과 API 접근 토큰 생성

# 노드 컴포넌트

- 동작 중인 pod를 유지시키고 쿠버네티스 런타임 환경 제공

- 모든 노드 상에서 동작


# kublet(worker node)

- 클러스터의 각 노드에서 실행되는 에이전트

- pod에서 컨테이너가 확실하게 동작하도록 관리

- 다양한 메커니즘을 통해 제공된 PodSpec의 집합을 받아서 컨테이너가 해당 pod의 스펙에 따라 동작하는지 확인

- kublet은 쿠버네티스를 통해 생성되지 않는 컨테이너는 관리하지 않음


# kube-proxy(worker node)

- 클러스터 외부의 사용자들이 네트워크를 통해 pod로 통신할 수 있도록 해주는 역할


# container-runtime(worker node)

- 컨테이너 런타임은 컨테이너의 실행을 담당하는 소프트웨어(실습에서는 도커를 사용)


--- Kubernetes

 

- Minikube 설치(Minikube는 Single Node : Mater Node + Woker Node), (Multi Node : Mater Node와 Woker Node 별개)

# curl -fsSL https://get.docker.com/ | sudo sh
# systemctl enable --now docker
# yum install -y conntrack git
# curl -Lo minikube https://storage.googleapis.com/minikube/releases/v1.23.2/minikube-linux-amd64 && chmod +x minikube
=> minickube를 내려 받음과 동시에 누구나 이용할 수 있도록 실행 권한(-x) 부여
# mkdir -p /usr/local/bin/
=> 해당 경로에 bin 폴더가 없으면 생성하라는 명령어
# install minikube /usr/local/bin/
# minikube version
# minikube start --driver=none
=> driver를 아무 것도 지정하지 않는 것이 가장 간단하게 설정하는 방법임
# minikube status

- kubectl 설치(API서버와 연결하는 도구)
# curl -LO https://dl.k8s.io/release/v1.22.2/bin/linux/amd64/kubectl
# install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# source <(kubectl completion bash)
# echo "source <(kubectl completion bash)" >> ~/.bashrc
=> 위 두 줄은 자동완성을 위한 명령어
# kubectl version
# kubectl get svc
=> 클러스터의 IP 확인 가능
 => 클러스터 내부의 컴포넌트 간의 통신을 위해 존재
=> svc는 service의 약어
# kubectl get nodes

--- Pod(pod 안에 컨테이너가 담겨 있음)

 

# mkdir workspace && cd $_
# kubectl run nginx-pod --image=nginx
=> nginx-pod는 pod의 이름이 됨
# kubectl get pod
=> 만들어진 pod에 대한 정보를 확인할 수 있음
# kubectl exec -it nginx-pod -- bash
=> pod로 접속해서 컨테이너 수정하고 싶을 때 사용
# kubectl expose pod nginx-pod --name clusterip --type=ClusterIP --port 80
=> expose : pod에 접속할 수 있게 해주는 명령어
=> --name clusterip : 서비스의 이름
=> --port : 호스트 포트를 의미
=> 접속 유형 : ClusterIP, NodePort, LoadBalancer 접속하는 방법이 다름
# kubectl expose pod nginx-pod --name nodeport --type=NodePort --port 80
NodePort의 IP로 클러스터 내부에서 접속 + NodePort의

# kubectl expose pod nginx-pod --name loadbalancer --type=LoadBalancer --external-ip 192.168.1.165 --port 80
=> --external-ip : minikube 호스트의 IP
=> 호스트(=노드)의 IP를 그대로 활용할 수 있는 장점
# kubectl get all
=> pod와 service를 전부 보여줌
# kubectl delete svc clusterip
=> clusterip처럼 특정 서비스를 지울 때 사용
# kubectl delete svc --all
# kubectl delete pod nginx

- pod는 쿠베네티스에서 배포할 수 있는 가장 작은 단위

=> pod 안에는 컨테이너와 볼륨이 들어 갈 수 있음

=> pod내부의 컨테이너와 볼륨들은 localhost로 통신

=> pod 내부에 여러 개의 컨테이너와 볼륨들이 들어갈 수 있지만, 관리 목적 상 여러 개의 컨테이너와 볼륨X


- 서비스(Service)는 네트워크와 관련된 리소스

=> 내부 DNS에 서비스 이름을 도메인으로 등록하기 때문에 서비스 디스커버리 역할도 함

=> pod를 외부 네트워크와 연결해주고 여러 개의 pod를 바라보는 내부 로드밸런서를 생성할 때 사용


- ClusterIP로 구축되어 있는 pod에 외부 사용자가 접속할 수 없음, proxy를 거쳐야 가능

ex) DB 서버는 내부에서만 접속하니까 클러스터 IP를 주고, 웹 서버는 외부에서 접속해야 하니까 외부IP를 줘야 함

ClusterIP, NodePort, LoadBalancer
클러스터 IP가 달라서 PORT가 80으로 동일해도 무관, 30015, 30199 노드 포트와 클러스터 IP로 외부에서도 접속 가능


--- Service

# vi nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
=> kind에서 pod를 만들겠다고 했으니, name에서 pod의 이름을 정의
=> 헷갈리니까 yaml파일, metadta, labels의 이름을 동일하게 주는 경우가 많음
  labels:
    app: nginx-pod
=> vi clusterip-pod.yaml의 Selector의 app항목과 동일해야 함
spec:
=> pod를 정의하는 핵심 정보
  containers:
  - name: nginx-pod-container
=> 컨테이너의 이름을 정의
=> name 앞에 붙은 - 는 배열을 의미, 여러 개의 컨테이너가 들어갈 수 있으므로 -를 사용
    image: nginx
=> 컨테이너를 구성하고 싶은 도커의 이미지 정의
=> api를 통해 해당 내용들을 etcd 데이터 베이스에 삽입
# kubectl apply -f nginx-pod.yaml
# kubectl get pod -o wide
=> kube scheduler가 어떤 노드에 pod를 배치했는지 확인 가능
# kubectl describe pod nginx-pod
=> pod란 리소스 중 nginx-pod라는 pod의 정보를 자세히 보여달라는 의미
=> 만약 kubectl get pod해서 pod가 애러난 것을 확인했다면, describe명령어를 통해 그 이유를 알 수 있음

# vi clusterip-pod.yaml
apiVersion: v1
kind: Service
metadata:
  name: clusterip-service-pod
spec:
  type: ClusterIP
  selector:
    app: nginx-pod
=> pod의 labels와 일치 : 위에서 만든 pod에 ClusterIP를 적용하기 위함
=> app이 아닌 다른 단어를 써도 상관 없음 pod의 labels와 맞춰주기만 하면 됨, 보통 app이나 prod를 사용
  ports:
  - protocol: TCP
    port: 80
=> 클러스터 IP의 포트
    targetPort: 80
=> 컨테이너 포트를 의미

# kubectl apply -f clusterip-pod.yaml
# kubectl get svc -o wide
# kubectl describe svc clusterip-service-pod
# kubectl edit svc clusterip-service-pod
=> 일일이 vi clusterip-pod.yaml 들어가서 수정할 필요 없이 해당 명령어를 통해 vi창과 비슷한 곳에서 수정 가능

# vi nodeport-pod.yaml
apiVersion: v1
kind: Service
metadata:
  name: nodeport-service-pod
spec:
  type: NodePort
  selector:
    app: nginx-pod
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
    nodePort: 30080
# kubectl apply -f nodeport-pod.yaml
# kubectl get svc -o wide
# kubectl describe svc nodeport-service-pod

# vi loadbalancer-pod.yaml
apiVersion: v1
kind: Service
metadata:
  name: loadbalancer-service-pod
spec:
  type: LoadBalancer
  externalIPs:
  - 192.168.56.119
  selector:
    app: nginx-pod
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
# kubectl apply -f loadbalancer-pod.yaml
# kubectl get svc -o wide
# kubectl describe svc loadbalancer-service-pod