Kubernetes 시작하기
Kubernetes 고유 특징
- 모든 리소스는 오브젝트 형태로 관리
- 아래 요소들을 모두 오브젝트라고 간주함
- 서비스 : 컨테이너의 묶음
- 파드(Pods) : 컨테이너의 집합
- 컨트롤러(Replica Set) : 컨테이너의 집합을 관리하는 컨트롤러
- 사용자(Service Account)
- 노드(Node)
- 아래 요소들을 모두 오브젝트라고 간주함
- 여러개의 컴포넌트로 구성
- 쿠버네티스 노드
- 마스터 : 클러스터를 관리
- API-Server, 컨트롤러 매니저, 스케줄러, DNS Server, 프록시, 네트워크 플러그인
- 워커 : 애플리케이션 컨테이너가 생성
- 마스터 : 클러스터를 관리
- kubelet : 클러스터 구성을 위한 에이전트
- 쿠버네티스 노드
Pod : 컨테이너를 다루는 기본 단위
- 컨테이너 어플리케이션의 기본 단위
- 하나의 완전한 어플리케이션
- 1개 이상의 컨테이너로 구성된 컨테이너의 집합
- Docker -> 도커 컨테이너 / 스웜 모드 -> 서비스 / 쿠버네티스 -> 파드
- 1개의 포드에서는 1개의 컨테이너가 있을 수도 있고, 여러개의 컨테이너가 존재할 수도 있음
yaml 파일 구조
- apiVersion : 오브젝트의 API 버전을 나타냄
- kind : 리소스의 종류
- 리소스 오브젝트인 pod나 pvc, pv등을 입력함
- metadata : 라벨, 주석, 이름 등과 같은 리소스 부가정보를 입력함
- spec : 리소스 생성을 위한 자세한 정보 입력
- containers 하위에 name(컨테이너 이름), image(사용할 도커 이미지), ports(사용할 컨테이너 포트)를 입력할 수 있음
kubectl apply -f 명령어로 쿠버네티스에 생성할 수 있음
포드 v.s. 도커 컨테이너
- 포드 또한 ip주소를 가지고 있어 클러스터 내부에서 접근 가능
- kubectl exec 명령어로 포드 컨테이너 내부로 들어갈 수 있음
- kubectl logs 명령어로 포드의 로그 확인가능
- 도커 컨테이너 대신 포드라는 개념 사용 이유?
- 여러 리눅스 네임스페이스를 공유하는 여러 컨테이너들을 추상화된 집합으로 사용하기 위함
- 특정 포드에 여러 컨테이너를 넣을 수 있긴 함(잘 안함)
- 명령어를 시행할 때 -c라는 옵션으로 컨테이너를 지정할 수 있음
- 각 내부 컨테이너가 같은 네트워크 네임스페이스를 공유하는 등 같은 리눅스 네임스페이스를 공유해 사용함
- 네트워크 네임스페이스
- 컨테이너의 공유한 네트워크 환경을 제공해주는 역할
- yaml의 command, args
- command : 도커 컨테이너의 Entrypoint(가장 먼저 실행되는 파일)
- args : dockerfile의 Cmd와 동일
- 특정 파드 내에 두개 이상의 컨테이너가 있을 때
- nginx 컨테이너가 실행되기 위해, nginx 설정파일의 변경사항을 갱신해주는 설정 리로더 프로세스 또는 로그 수집해주는 프로세스는 nginx 컨테이너와 함께 실행되야 함
- 주 컨테이너와 서브 컨테이너를 함께 포드에 포함시킬 수 있음
- 부가적인 컨테이너 -> 사이드카 컨테이너
- 동일한 네임스페이스들을 공유하여 사용할 수 있음
Replica Set : 일정 개수의 포드를 유지하는 컨트롤러
Replica Set 사용 이유
- 포드의 생애주기 관리
- 동일한 여러개의 포드를 생성한 뒤, 외부 요청이 각 컨테이너에 적절히 분배(로드 밸런서처럼)
- 이름만 다른 동일 파드를 yaml에 —로 구분하여 원하는 수만큼 띄워둠
- 비효율적인 방법
- 삭제되거나, 해당 노드에 장애가 발생하여 접근하지 못하게 됨 -> 직접 포드 삭제 후 재생성해야함
- 이름만 다른 동일 파드를 yaml에 —로 구분하여 원하는 수만큼 띄워둠
Replica Set 동작 원리
- 정해진 수의 동일한 포드가 항상 실행되도록 관리함
- 노드 장애 등의 이유로 포드를 사용할 수 없다면, 다른 노드에서 포드를 다시 생성함
spec.replicas : 동일한 포드를 몇개 유지시킬지 설정 spec.template : 포드 생성시 사용할 템플릿 포드 사용내용을 동일하게 정의함으로 어던 포드를 어떻게 생성할지 명시
- 레플리카셋을 삭제하거나 수정 시 포드에 변경사항이 반영됨
- yaml파일에 replicas를 3 -> 4로 해도 바로 변경사항이 반영됨
kubectl apply -f yaml
하면, Created가 아닌 configured가 출력되며, 기존 리소스가 수정됨kubectl delete -f || rs yaml
하면, 해당 레플리카가 삭제됨- 레플리카셋에 의해 생성된 포드도 함께 삭제됨
- 하지만 레플리카셋이 포드와 연결되어 있는 것은 아님
- 레플리카셋에 의해 생성된 포드도 함께 삭제됨
- 라벨 셀렉터에 의해 레플리카셋과 포드는 느슨한 연결 상태를 유지하고 있음
- 쿠버네티스 리소스의 부가 정보 표현
- 서로 다른 오브젝트가 서로를 찾아야 할때 사용
- 생성해야 하는 포드를 찾음
- 해당 라벨을 가지는 포드의 개수가 replicas의 수치와 일치하지 않으면 pod templete 항목으로 포드를 생성함
$ kubectl get pods --show-labels
Deployment: 레플리카셋, 포드의 배포를 관리
Deployment란?
- 레플리카셋의 상위 오브젝트
- 컨테이너 어플리케이션을 배포하고 관리하는 역할
- 포드와 레플리카셋을 직접 생성할 필요가 없음
- 실행하면 레플리카셋과 레플리카 수에 따른 파드 n개가 생성됨
$ kubectl apply -f <yaml파일>
로 적용하고,$ kubectl get deploy || deployment
로 배포할 수 있음- 디플로이먼트 삭제 시, 이에 종속된 파드와 레플리카셋도 삭제됨
Deployment 사용 이유
- 어플리케이션의 업데이트와 배포를 더욱 편하게 만들기 위함
- 어플리케이션을 업데이트할 때, 레플리카셋의 변경 사항을 저장하는 리비전(revision)을 남겨 롤백을 가능하게 해줌
$ kubectl set image deployment <deployment_name> nginx=nginx:1.11 --record
- 파드를 업데이트 시킬 때, 이미지를 업데이트 시키면 새롭게 생성된 파드들이 존재함
- Pod도 이전 set이 존재하는 것 같지는 않음
- 이전에 사용한 replica set을 삭제하지 않고 남겨둠 -> 리비전으로 보존함
$ kubectl rollout history deployment <deployment_name>
- undo를 통해 롤백할 수도 있음
- 무중단 서비스를 위해 파드의 롤링업데이트의 전략을 지정할 수 있음
Service : 파드를 연결하고 외부에 노출
Service의 기능
- 포드에 접근하기 위한 규칙 정의
- 여러개의 포드에 쉽게 접근할 수 있도록 고유한 도메인 이름을 부여함
- 여러 개의 포드에 접근할 때, 요청을 분산하는 로드 밸런서 기능을 수행함
- 클라우드 플랫폼의 로드 밸런서, 클러스터 노드의 포트 등을 통해 포드를 외부로 노출함
$ k get pods -o wide
로 파드의 IP 확인가능함- 파드에 어떻게 접근할 것인지에 따라 종류가 여러개
- ClusterIP 타입
- 쿠버네티스 내부에서만 포드에 접근할 때 사용
- 외부로 파드를 노출하지 않음
- NodePort 타입
- 파드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방
- 외부에서 포드에 접근 가능
- 접근할 수 있는 포트는 랜덤으로 정해지나, 특정 포트로 접근하도록 설정할 수도 있음
- LoadBalancer 타입
- 클라우드 플랫폼에서 제공하는 로드 밸런서를 동적으로 프로비저닝해 포드에 연결
- 외부에서 포드에 접근 가능
- AWS, GCP 와 같은 클라우드 플랫폼 환경에서만 사용가능
- ClusterIP 타입
- 서비스를 생성할 때, 별도의 설정없이도 연결된 포드에 대해 로드 밸런싱을 수행함
- ClusterIP web-port
- 쿠버네티스 내부에서만 포드에 접근할 수 있는 포트
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
selector:
app: webserver
type: ClusterIP
- 쿠버네티스 내부에서만 포드에 접근할 수 있는 포트
- spec.selector : 어떤 라벨의 포드에 접근할 지 결정
- spec.ports.port : 서비스의 IP에 접근할 때 사용할 포트
- spec.ports.targetPort : containerPort 항목에서 사용할 포트를 동일하게 설정해야 함
- 포드가 서로 상호작용해야 할 때, 포드의 IP를 몰라도됨
- 서비스 이름을 사용함으로 접근 가능
- NodePort
- 모든 노드의 특정 포트를 개방해 서비스에 접근하는 방식
$ kubectl get service
를 통해 포트를 확인할 수 있음- YAML 파일에 nodePort항목을 지정하여 포트를 선택할 수도 있음
- 너무 낮은 포트의 경우, 시스템에 의해 예약된 포트로 사용불가능 할 수 있음
- 보통 실서비스에서는 노드포트로 서비스를 외부로 직접 제공하기 보다 Ingress라는 오브젝트로 간접 사용됨
- LoadBalancer
- 동적으로 생성하는 기능을 제공하는 환경에서 사용할 수 있음 (GCP, AWS)
$ kubectl get service
를 하면 EXTERNAL-IP 항목을 볼 수 있음