220714

HyeonKi Jo·2022년 7월 14일
1

Kubernetes

Amazon ECS

  • Amazon Elastic Container Service(Amazon ECS)는 클러스터에서 Docker 컨테이너를 손쉽게 실행, 중지 및 관리할 수 있게 해주는 컨테이너 관리 서비스 이다.
  • AWS(EKS, ECS=Swarm), Azure(AKS), GCP(GKE)들을 클러스터로 사용하여 멀티 클라우드로 사용해 무중단서비스, 고가용성을 지킬 수 있다.

EC2를 사용하여 Amazon Elastic Container Service(Amazon ECS) 시작하기

  • Task(작업, Pods)가 컨테이너를 감싸고 있다.
  • 그 Task는 서비스로 묶여있고, 이 서비스들은 한 Cluster단위로 작업하게될 것이다.

작업정의 생성

  • 작업정의항목을 클릭해서 새로운 작업을 정의해준다.
  • EC2를 사용할 것이다.
  • Cluster에게 작업 명령을 내리려면 역할(roll, 권한)이 필요한데, ECS에서 역할을 자동으로 만들어 줄 것이다.

컨테이너 추가

  • 여기서 docker run으로 생성했던 컨테이너를 미리 정의하게 된다.
  • 컨테이너 이름은 docker에서 --name 옵션과 같다.
  • 이미지는 버전정보를 주지 않으면 자동으로 최신버전을 사용하게 된다.
  • 메모리 제한은 필수입력 정보이다.
    • 하드 제한으로 128Mb를 사용함으로 세팅한다.
  • 포트 매핑은 -p 옵션과 동일하며 80:80으로 설정해준다.

생성

  • 컨테이너만 추가하고 생성버튼을 눌러준다.

클러스터 생성

  • EC2 클러스터를 생성해준다.

클러스터 구성

  • 이름: MY-CLUSTER
  • 프로비저닝 모델에서 온디멘드는 가장 비싼 방법이다.
    • 사용하는 시간당 비용을 지불하게 되며
      • 컨테이너가 갑자기 사라질일이 없다.
      • 스팟 프로비저닝은 경매를 통해 나보다 더 비싼 금액을 부른 사람이 나올때까지 인스턴스를 사용하는 방법이다.
      • 스팟 인스턴스는 언제 생성되고 언제 사라질지 모른다.
      • 그러나 클러스터는 작업목적에따라 다르지만, 자원을 관리할 수 있다면 매우 저렴하게 인스턴스를 사용할 수 있다.
    • 지금은 온디멘드 방식으로 진행해본다.
  • EC2인스턴스 유형은 자동으로 어느정도 용량이 있는 인스턴스가 사용된다.
    • 아래 원하는 인스턴스 유형 직접입력으로 t2.micro를 사용해준다.

네트워킹 구성

  • 기존에 만들어져있는 NEW-VPC, MY-VPC를 사용해준다.
  • 서브넷은 2a, 2c를 사용한다.
  • 퍼블릭 IP를 받을 수 있도록 활성화해준다.
  • 보안그룹은 기존에 만들어져 있는 보안그룸을 사용한다.
    • HTTP, ICMP, SSH허용

컨테이너 인스턴스 IAM역할

  • 컨테이너 인스턴스 IAM역할은 아까 생성한 ECS작업으로 자동으로 고정되어있다.

생성

시작상태

  • 클러스터와 인스턴스 IAM성책이 완성되었다.
  • CloudFormatino이 생성중인데, 에러가난다면, 이전버튼으로 돌아가 수정하면 될 것이다.

결과 확인

  • 클러스터가 잘 생성되엇따.
  • 인스턴스도 생성되어 서비스 중이다.

ECS 서비스

  • 현재 클러스터 화면을 확인한다.
  • ECS인스턴스에 생성된 EC2인스턴스를 볼 수 있다.
  • 여기서 ECS가 Master, Control plane
  • EC2인스턴스가 Worker노드가 되는 것이다.
  • 그러나 이 인스턴스에는 TASK가 들어가 있지 않다.
  • 서비스를 생성해줘야한다.

서비스 생성

  • 여기서 서비스를 생성해준다.

서비스 구성

  • 시작 유형: EC2
  • 작업 정의는 아까 생성한 작업을 사용해준다.
  • 클러스터도 방금 생성한 클러스터
  • 서비스 이름은 : MY-WEB으로 한다.
  • 서비스 유형: REPLICA
  • 작업 개수: 2
    • 두개의 EC2노드에 2개의 작업을 부여한다.
    • 즉, EC2노드 하나에 한 작업이 부여된다.
  • 최소 정상 상태 백분율 : 50
  • 최대 백분율 : 100
    • 업데이트와 관련된 설정이다.
    • 업데이트를 할 때, 구버전을 지우지않고, 신버전을 생성하녀 2-> 4개의 컨테이너가 운영되는 시점이 생긴다.
    • 최소 정상 상태 백분율은 평소에 50%의 컨테이너만 생성하고, 업데이트시 최대 100%의 컨테이너를 생성한다.
    • 즉 최대 2개일때, 평소 1개의 컨테이너만 사용하고, 최대 2개까지 생성하여 업데이트 한다.

배포

  • 배포시에는 롤링 업데이트를 사용한다.

네트워크 구성

  • 로드밸런서 유형은 ALB(Application Load Balancier)를 사용한다.
  • 상태 검사 유예 기간: 150
    • 인스턴스의 상태검사를 할 때, EC2가 만들어지는 중에 상태검사를 유예해주는 시간이다.

로드밸런서 생성1



대상그룹 생성


로드밸런서 생성2


다시 서비스 생성

  • 여기서 방금 생성한 MY-ALB를 추가하고,
  • 아래 로드 밸런서에 추가 버튼을 눌러준다.
  • 프로덕션 리스너 포트 80:HTTP
  • 대상그룹은 방금 생성한 대상그룹으로 선택한다.

Auto Scaling(선택사항)

자동 작업 조정 정책

  • 먼저 Desired state를 먼저 생성해준다.
  • ScaleOutAlarm과 Policy를 생성한다.
  • 반대로 ScaleInAlarm와 Policy를 생성해준다.

서비스 접속 확인

  • EC2 -> 로드밸런서 에서 DNS주소를 받아 웹브라우저로 접속해본다.
  • 잘 접속되고, 잘 동작한다.
  • Route53에서 등록해준다.

ECS에서 업데이트 하기

작업 정의

  • 새 작업을 정의한다.
  • EC2 시작유형 호환선을 선택한다.
  • 컨테이너를 추가해준다.
    • 컨테이너 이름은 기존과 동일한 이름으로한다.
    • 이미지를 우리가 Docker HUB에서 PUSH했던 이미지를 사용한다.

ECS 정리

작업 정의 정리

  • 각 작업을 클릭해서 등록취소를 눌러준다.

클러스터 삭제

이론

kube-apiserver

  • API 서버는 일종의 마스터의 역할을 한다.

kube-controller-manager

  • 컨트롤러를 구동하는 마스터 상의 컴포넌트
  • 각 컨트롤러는 개별 프로세스지만, 복잡성을 낮추기위해 모두 단일 바이너리로 컴파일되고, 단일 프로세스내에서 실행된다.
  • 이들 컨트롤러는 다음을 포함한다.
    • 노드 컨트롤러 : 노드가 다운되었을 때, 통지와 대응에 관한 책임
    • 레플리케이션 컨트롤러: 시스템의 모든 레플리케이션 컨트롤러 오브젝트에 대해 알맞은 수의 Pods을 유지시켜준느 책임 (replicas=5)
    • 엔드포인스 컨트롤러: 엔드포인트 오브젝트를 채운다.
      • 즉, 서비스와 Pods를 연결시킨다.
    • 서비스 어카운트 & 토큰 컨트롤러: 새로운 네임스페이스에 대한 기본 계정과 API접근 토큰을 생성한다.
      • 사용자가 권한을 가진 사용자인지 토큰을 확인할 수 있음

Cloud-controller-manager

  • 퍼블릭 클라우드에서 제공하는 하나의 컴포넌트이다.
  • 클라우드 컨트롤러 매니저를 통해 클러스터를 클라우드 공급자의 API에 연결한다.
  • 해당 클라우드 플랫폼과 상호작용하는 컴포넌트와 클러스터와 상호 작용하는 컴포넌트를 분리할 수 있다.

노드 컴포넌트

  • 노드 컴포넌트는 동작중인 pods를 유지시키고, 쿠버네티스 런타임 환경을 제공하며, 모든 노드상에서 동작한다.
    • 심지어 master노드에도 worker노드를 생성할 수 있다.

워커노드의 구성요소

Kubelet

  • 클러스터의 각 노드에서 실행되는 에이전트
  • kubelet은 Pods에서 컨테이너가 확실하게 동작하도록 관리한다.

Kube-proxy

  • ha-proxy의 기능도 가지고있다.
  • 엔드 노드들이 여러 작업을 하더라도, 결국 워커노드에서 작업하게 되는데, 쿠버네티스의 서비스 개념의 구현부이다.
  • kube-proxy는 노드의 네트워크 규칙을 유지 관리한다.
  • 또 ,이 네트워크 규칙이 내부 네트워크 세션이나 클러스터 바깥에서 파드로 네트워크 통신을 할 수 있도록 해준다.

Container-runtime

  • 컨테이너 런타임(도커)는 컨테이너 실행을 담당하는 소프트웨어이다.
  • 큐블렛을 실질적으로, Pods를 꾸미고, 그 안에 컨테이너를 생성하게 된다.
  • 쿠버네티스는 여러 컨테이너 런타임을 지원한다.
    • Docker, Containerd, CRI-O

Minikube

환경설정

  • CentOS7의 ISO, CPU:2c, RAM: 4Gb의 VM을 구성한다.
  • 이름: Minikube로 해준다.
  • 네트워크 MAC주소를 업데이트해준다.
  • 시작.

Minikube 설치(Single Node, 실습: Master Node + Worker Node), (Multi Node: Master Node, Worker Node)

  • curl -fsSL https://get.docker.com/ | sudo sh
    • 도커 설치, Node의 컨테이너 런타임을 설치하고잇는 것이다.
  • systemctl enable --now docker
  • yum install -y conntrack git
    • conntrack과 git을 설치해준다.
  • curl -Lo minikube https://storage.googleapis.com/minikube/releases/v1.23.2/minikube-linux-amd64 && chmod +x minikube
    • 미니큐브를 설치한다. 이때 1.23.2버전을 설치하는데, 이후 에러가 날 수 있다. 버전을 계속 수정하며 설치해봐야 한다.
    • 구글에서 개발했기 때문에, 구글의 스토리지에서 가져온다.
    • 또, minikube-linux-amd64라는 이름을 minikube라고 설정하며, && chmod로 실행할 수 있도록 권한을 수정한다.
  • mkdir -p /usr/local/bin/
    • /bin디렉토리가 없다면 만들어준다.
  • install minikube /usr/local/bin/
    • minikube 명령어를 /bin에 설치해준다.
  • 설치확인을 위해 minikube version을 입력해본다.
  • minikube start --driver=none
    • 간단하게 minikube를 시작한다.
    • --driver를 사용하려면, 하이퍼바이저를 넣어줘야 하는데, 이러려면 VM안에 또 하이퍼바이저를 설치해야한다.
    • 지정하지 않는것이 간편하다.
  • minikube status
    • 상태확인

kubectl 설치

  • curl -LO https://dl.k8s.io/release/v1.22.2/bin/linux/amd64/kubectl
    • kubectl을 다운로드 받는다.
  • install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
    • kubectl을 설치해준다.
  • source <(kubectl completion bash) 소스에 kubectl completion bash를 넣어준다.
  • echo "source <(kubectl completion bash)" >> ~/.bashrc
    • .bashrc에 source값을 넣어준다.
  • kubectl version
    • 설치를 확인한다.

Pods

Cluster

  • Master에서 Node들을 관리하며, 자가치유 기능을 가지고 있다.
  • 노드가 정지가되면, 새로 노드를 생성하여 자가치유한다.
    • 또, 노드가 정지될 때, Pod들을 다른 노드로 옮겨 무중단서비스를 이어간다.
  • Master Node (Controller Node)
  • Worker Node (Compute Node)

pod

  • 파드(Pods) : 쿠버네티스에서 배포할 수 있는 가장 작은 단위
  • 한개 이상의 컨테이너와 스토리지, 네트워크 속성을 가진다.
  • pods에 속한 컨테이너는 스토리지와 네트워크를 서로 공유하고, 서로 localhost로 접근할 수 잇다.
  • 도커스웜과 ECS에서는 Task라고 불렀다.

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

  • Pod을 외부 네트워크와 연결해주고, 여러개의 pod을 바라보는 내부 로드 밸런서를 생성할 때 사용한다.
  • 내부 DNS에 서비스 이름을 도메인으로 등록하기 때문에 서비스 디스커버리 역할도 한다.

pods 실행

  • mkdir workspace && $_
    • 실습을 진행할 workspace 생성
  • kubectl run nginx-pod --image=nginx
    • pod 안쪽에 nginx이미지를 사용하여, nginx-pod라는 pod를 생성했다.

--type 유형

  • --type=ClusterIP : 내부에서 클러스터를 구별하는 IP, 내부에서 서로 통신할 수 있다.
    • 트래픽이 클러스터로 들어올 때, 프록시 설정이 없으면 ClusterIP는 외부에서 접속이 불가능하다.
    • kubeproxy를 통헤 service에 들어오고, service에서 pod로 들어간다.
  • --type=NodePort: 내부에서만 연결되는 ClusterIP와 달리 외부와 연결된다.
  • --type=LoadBalancer

EXPOSE

  • 여기서는 Expose에 의미가 있다.
  • Endpoint 서비스를 위한 포트를 열어준다.
  • kubeproxy가 pod에 접속할 수 있는 네트워크 정보를 만드는 것이다.

ClusterIP 생성


  • kubectl expose pod nginx-pod --name clusterip --type=ClusterIP --port 80
  • Clusterip를 생성했다.
  • kubectl get svc로 서비스들을 본다.
  • 그러나 IP주소로 접속할 수 없다.
    • ClusterIP는 내부 클러스터들 간의 통신하는 IP이기 때문이다.
  • 그래서 노드 안에서 curl명령어로 접속해보니 nginx가 잘 나온다.

Nodeport


  • kubectl expose pod nginx-pod --name nodeport --type=NodePort --port 80
    • NodePort를 생성하였다.
    • ClusterIP처럼 내부에서 통신하는 IP주소도 생성되면서 동시에 호스트의 IP로 포트포워딩되어 접근할 수 있는 Port도 열어준다.(31038포트가 열렸다.)
  • 내부에서 curl명령어로 Nodeport IP로 접속했을 때 잘 나온다.
  • 호스트IP주소에 Nodeport의 포트번호로 접속할 때, 잘 출력된다.

--type=LoadBalancer

  • kubectl expose pod nginx-pod --name loadbalancer --type=LoadBalancer --external-ip 192.168.0.144 --port 80
    • 로드밸런서 유형을 실행해본다.
  • 로드 밸런서는 ClusterIP의 내부 IP와, NodePort의 호스트IP:nodeport 를 동시에 가지고있다.
  • 또, 이제 그냥 호스트IP로 들어가면 서버에 접속할 수있다.
  • 이렇게 호스트IP에서 포트번호80번으로 접속할 수 있다.
  • 이 ClusterIP, NodePort, LoadBalancer들을 서로 포트가 충돌하지 않는다.

생성된 서비스 보기

  • kubectl get all

서비스 삭제하기

  • kubectl delete svc -all
  • kubectl delete pod nginx
  • 남아있던 nginx-pod도 지워준다.
  • 다 지웠으나, 기본 디폴트 Clouster IP는 지울 수 없다.

exec 명령어

  • kubectl exec -it nginx-pod -- bash
  • nginx-pod에 exec로 접속해서 index.html을 수정해본다.
  • 필요할 떄 exec명령어를 이렇게 사용할 수 있다.

Service

vi nginx-pod.yml

apiVersion: v1		# api의 버전
kind: Pod			# yml로 생성하고사하는것은 pod이다.
metadata:			# pod 정보 설정
  name: nginx-pod	# 이름은 nginx-pod
  labels:			# labels
    app: nginx-pod
spec:				
  containers:		# 컨테이너의 이름과 이미지 정의, 
  					#여러개를 -로 구분하여 정의할 수 잇따.
  - name: nginx-pod-container
    image: nginx

문법

pod생성하기

  • kubectl apply -f nginx-pod.yaml
    • docker images를 보면 kube-apiserver, kube-controller-manager, kube-proxy등 docker와 kubernetes는 서로 관련이 많음을 볼 수 있다.
    • 방금 생성한 nginx-pod가 잘 러닝중이다.
  • kubectl get pod -o wide
    • kubectl get pod명령어를 조금 더 자세하게 살펴본다.
  • kubectl describe pod nginx-pod
    • describe 명령어는 docker에서 inspect와 비슷하다. nginx-pod에 대한 자세한 정보를 보여준다.

vi clusterip-pod.yaml

apiVersion: v1
kind: Service
metadata:
  name: clusterip-service-pod
spec:
  type: ClusterIP			# --type옵션, ClusterIP를 nginx-pod에 연결해준다.
  selector:
    app: nginx-pod			# 앞서만든 nginx-pod와 이름이 같아야한다.
  ports:					
  - protocol: TCP
    port: 80				# hostport를 말한다.
    targetPort: 80			# 목표 port, 내부에서 들어오는 트래픽을 포트포워딩한다.

  • kubectl apply -f clusterip-pod.yaml
  • kubectl get svc로 생성된것을 확인한다.
  • 내부에서 curl 명령어로 html이 잘 출력된다.
  • kubectl describe svc clusterip-service-pod
    • clusterip-service-pod 의 상세정보를 살펴본다.

만약 yaml파일을 수정해서 selector입력에 오류를 넣어준다면

apiVersion: v1
kind: Service
metadata:
  name: clusterip-service-pod
spec:
  type: ClusterIP
  selector:
    app: nginx-pod1 	# 여기에 1을 넣어서 일부러 오타를 넣어준다.
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

  • 에러는 나지 않는다.
  • 그러나 서비스를 연결하지 못했다.
    • kubectl get svc에 결과가 나오지 않는다.

만약 yaml파일에서 호스트포트를 8080으로 바꾸면?

apiVersion: v1
kind: Service
metadata:
  name: clusterip-service-pod
spec:
  type: ClusterIP
  selector:
    app: nginx-pod
  ports:
  - protocol: TCP
    port: 8080			# 여기를 80 -> 8080으로 수정했다.
    targetPort: 80

  • kubectl get svc로 확인하니, 8080포트로 바뀌엇다.
  • curl에서 8080포트로 적용하니 html이 잘 나온다.

edit 명령어

  • kubectl edit svc clusterip-service-pod
    • 실행중인 서비스를 vi명령어를 쓰듯이 내용을 수정할 수 있다.
    • 방금 변경한 8080포트를 80포트로 돌려주고 저장한다.
  • 80포트로 다시 돌아왔다.

vi nodeport-pod.yaml

apiVersion: v1
kind: Service
metadata:
  name: nodeport-service-pod
spec:
  type: NodePort
  selector:
    app: nginx-pod	# 여기서 app아니라 good이든 어떤거든 pod에 정의된 이름과 매핑만되면 된다.
  ports:
  - protocol: TCP
    port: 80		# 호스트 포트
    targetPort: 80	# 컨테이너 포트
    nodePort: 30080	# 노드포트는 랜덤생성되지만, 30000~32767 정도까지 내 임의로 할당도 가능하다.

  • kubectl apply -f nodeport-pod.yaml
    • nodeport-pod pod에 nodeport를 연결한다.
  • ClusterIP로 curl명령어에서 html 출력된다.
  • 마찬가지로 호스트IP:30080포트도 잘 접속된다.

vi loadbalancer-pod.yaml

apiVersion: v1
kind: Service
metadata:
  name: loadbalancer-service-pod
spec:
  type: LoadBalancer	# LoadBalancer 유형을 사용한다.
  externalIPs:			# 호스트IP를 입력한다.
  - 192.168.56.119
  selector:
    app: nginx-pod
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80		#컨테이너포트라서 함부러 바꾸면 안된다.

  • kubectl apply -f loadbalancer-pod.yml
  • kubectl get svc -o wide
  • kubectl describe svc loadbalancer-service-pod
  • clusterIP로 접속
  • HOST IP로 접속 (LoadBalancer에서 정의)

kubectl edit 명령어

kubectl edit pod nginx-pod

업로드중..

  • kubectl edit pod nginx-pod명령어에서 image를 검색해서 jo1132/web-site:v2.0으로 넣어본다.
    업로드중..
  • 현재 Loadbalancer 서비스가 생성되어 있으니, 호스트IP로 접속이 가능하다.
  • 접속해보니 웹페이지가 바뀌었다.
profile
Talking Potato

0개의 댓글