쿠버네티스
컨테이너 오케스트레이션 중 사실상 표준
여러 서버에 걸쳐있는 컨테이너를 효율적으로 분산/배치/관리하는 기법으로 유용한 기능들을 제공
작은 컨테이너라면 직접 배포하여 사용하면 되지만, 컨테이너 수가 많아지면서 해당 컨테이너를 어디에 배포해야 될지에 대한 결정이 필요해짐
- CPU, memory resource 고려해야하는 경우
- 동일 물리서버에 배포해야하는 경우
- 가용성을 위해 다른 물리서버에 배포해야 하는 경우
이러한 컨테이너를 적절하게 배포하는 스케줄링 역할을 한다. 이 외 정상 작동 체크하고 문제 시 재기동, 모니터링, 삭제등 컨테이너 종합 관리를 해주는 환경이 필요하다. 쿠버네티스는 컨테이너 운영환경 솔루션 중 하나이다.
Object
쿠버네티스는 Basic Object와 이를 생성하고 관리하는 추가적인 기능을 가진 Controller로 이루어 진다. 이러한 오브젝트의 스펙(설정)이외에 추가적인 메타 정보들로 구성된다.
Basic Object : k8s에서 배포 및 관리되는 기본적인 구성단위 (기본 오브젝트 만으로 설정, 배포 가능)
- Pod : 컨테이너화된 애플리케이션
- Service : 로드밸런서
- NameSpace : 패키지명
- Volume : 디스크
Controller : 기본 오브젝트를 생성하고 관리하는 역할 (편리성)
ReplicaSet : Pod 관리 (replica 수 만큼 pod를 배포, 관리)
Deployment : ReplicaSet 추상화된 개념. 실제 운영에서 ReplicatSet보다 Deployment를 사용
StatefulSet : 상태를 가지는 애플리케이션 운용 시 적합
- Job, CronJob : 하나 이상의 pod를 생성해 지정된 pod가 정상 종료될 때까지 관리하는 리소스 (batch)
- ...
Volume : PersistentVolume, PersistentVolumeClaim, StorageClass
파드(Pod)
- 기본적인 배포 단위(컨테이너가 모인 집합체)
- 쿠버네티스는 하나의 컨테이너를 개별적으로 배포하지 않고, pod 단위로 배포한다
- 결합(정합도, 결합도)이 강한 컨테이너를 pod로 묶어 일괄 배포한다 ex) web server + was
- 같은 pod를 한 node에 여러개 배치가 가능하고, 여러 노드에 배치가 가능하지만 한 pod가 2개이상의 node에 배치될 수 없다.
Pod의 특징
Pod 내의 컨테이너는 IP, port를 공유한다 (localhost를 통해 통신 가능)
Pod 내의 배포된 컨테이너간에는 디스크 볼륨을 공유할 수 있다.
파드에는 고유한 가상 IP 주소가 할당되고 이 주소를 컨테이너가 공유하므로 컨테이너간 통신이 가능하다.
이 가상 IP로 다른 파드와의 통신도 가능하다.
(실습) Pod 배포하고 상태 확인 및 삭제 해본다.
실습 시 사용되는 동일 및 주요 명령어
# 매니페스트 배포 kubectl apply -f [매티페스트 파일] # 매니페스트 삭제 kubectl delete -f [매니페스트 파일] # 클러스터 상태 확인 kubectl get pod[,replicaset,deployment]
1) Pod 생성 및 배포하기
# pod 배포 kubectl apply -f simple-pod.yaml
# pod echo 컨테이너 logs 확인 kubectl logs -f simple-echo -c echo
2) Pod 상태 확인
# Pod 상태 확인 kubectl get pod
- 실행화면 ( pod 생성 중 및 생성 되었을 때의 상황이다 )
- READY : 실행 중 컨테이너 수 / 총 컨테이너 수
- STATES : ContainerCreating, Running, Terminating
3) Pod 삭제
# pod 삭제 kubectl delete pod simple-echo # 매니페스트 파일로 삭제 kubectl delete simple-pod.yaml
서비스(Service)
랜덤으로 IP주소가 생성되는 Pod에 고정적인 엔드포인트로 호출할 수 있는 기능을 제공하는 리소스.
여러 pod에 같은 애플리케이션 운용 시 pod간의 로드밸런싱이 필요한데 이를 서비스가 해결한다.
파드의 집합(replicaset)에 대한 경로, 서비스 디스커버리를 제공하는 리소스
서비스의 역할
지정된 IP 생성한다.
여러 Pod를 묶어 로드밸런싱을 한다.
고유한 DNS 이름을 가질 수 있음
Controller
레플리카세트(ReplicaSet)
- 동일한 pod를 여러개로 복제하여 생성/관리하는 리소스 (가용성 확보를 위해)
- 매니페스트 설정 파일 하나로 여러 파드를 관리할 수 있다.
- 파드명은 무작위 접미사가 붙으므로 삭제된 파드는 복원 불가
→ 때문에 stateless application에 적절하다 (webserver, was)
!! state application은 어떻게 처리하는가?
(실습)
# 레프리카세트 배포 kubectl apply -f simple-replicaset-yaml # 생성된 파드 확인 kubectl get pod # 레프리카세트 삭제 kubectl delete -f simple-replicaset.yaml
디플로이먼트(Deployment)
- 레플리카세트를 관리하고 다루기 위한 상위 리소스로 애플리케이션 배포(deploy)의 단위
- 디플로이먼트는 레플리카세트를 제어하여 파드의 개수 증감, 버전 교체가 가능하며, 추가로 이전 버전으로 롤백등 기능을 가진 리소스
레플리카세트의 리비전 관리 가능 (–record)
실제 운영에서는 레플리카세트를 직접 다르기 보다는 디플로이먼트 매니페스트 파일을 통해 운영
(실습)
1) 디플로이먼트 생성
# 옵션으로 기록을 남기며 클러스터에 반영 kubectl apply -f simple-deployment.yaml --record # 상태 확인 kubectl get pod,replicaset,deployment --selector app=echo # 리비전 확인 kubectl rollout history deployment echo
2) 파드 개수 수정
- simple-deployment.yaml replicas 3→4 수정
- 수정된 매니페스트 반영
- 늘어난 파드 갯수 확인
(수정 전) (수정 후)
kubectl rollout history deployment echo
→ 파드의 개수 수정 시 레플리카세트가 새로 생성되지 않으므로 리비전 번호가 변경되지 않음
3) 컨테이너 정의 수정
simple-deployment.yaml 파일의 echo 컨에니어 이미지를 gihyodocker/echo:patched로 수정
디플로이먼트 배포# 디플로이먼트 배포 kubectl apply -f simple-deployment.yaml --record # 리비전 확인 kubectl rollout history deployment echo
- NEW ReplicaSet를 생성하여 새로운 이미지의 컨테이너가 있는 Pod를 배치, Old ReplicaSet의 Pod를 제거 (반복)
>>
4) 롤백
디플로이먼트는 리비전을 관리하므로 특정 버전의 내용을 확인하거나 디플로이먼트 문제 시 이전버전으로 롤백 가능하다.
디플로이먼트 롤백# 리비전 확인 option: --reversion kubectl rollout history deployment echo # 직전 버전 롤백 kubectl rollout undo deployment echo
디플로이먼트 삭제# 매니페스트를 이용해 삭제 시 디플로이먼트, 관련된 레플리카세트, 파드 함께 삭제 kubectl delete --f simple-deployment.yaml
서비스(Service)
파드의 집합(replicaset)에 대한 경로, 서비스 디스커버리를 제공하는 리소스
서비스의 역할
지정된 IP 생성한다.
여러 Pod를 묶어 로드밸런싱
- default) 랜덤으로 부하 분산
- 특정 클라이언트가 특정 pod로 지속적으로 연결 가능하다 (session affinity)
고유한 DNS 이름을 가질 수 있음
- 멀티 포트 지원 : 서비스는 하나의 포트가 아닌 여러개의 포트를 동시에 지원 할 수 있다. ex) HTTP, HTTPS
(실습) 3개의 pod(summer, summer, spring) 존재한다. summer인 pod에만 접근 가능한 서비스를 만들어본다.
1. release 속성값이 spring과 summer인 레플리카세트를 정의하고 배포
# pod 3개 배포 summer(1), spring(2) kubectl apply -f simple-replicaset-with-label.yaml # pod 확인 kubectl get pod -l app=echo -l release=spring kubectl get pod -l app=echo -l release=summer
2. release=summer인 파드만 접근할 수 있는 서비스 생성하고 확인
# 서비스 생성 kubectl apply -f simple-service.yaml # 서비스 확인 kubectl get svc echo
3. 트래픽 전달 확인
클러스터 내부에서 요청을 보내 summer pod에 도달하였는지 확인한다
서비스의 default는 clusterIP 이다.
쿠버네티스 클러스터 안에서만 접근할 수 있으므로 쿠버네티스 클러스터에서 디버깅용 임시 컨테이너를 배포하고 확인한다.
# 디버깅용 임시 컨테이너 배포 kubectl run -i --rm --tty debug --image=gihyodocker/fundamental:0.1.0 --restart=Never -- bash -il # HTTP 요청 curl http://echo/
4. 레이블이 summer인 파드에 해당 파드에 접근하였는지 로그 확인
# summer pod명 복사하여 확인 kubectl logs -f [echo summer pod name] -c echo
서비스의 종류
IP 주소 할당 방식, 연동 서비스등에 따라 크게 4가지로 구분된다.
1) ClusterIP 서비스 (Default)
쿠버네티스 클러스 내부 IP주소에 서비스를 공개하여, 쿠버네티스 클러스터 내에서는 서비스 접근이 가능하나 외부 IP를 할당 받지 못해 외부로부터 접속이 불가능하다.
서비스명으로 네임 레졸루션이 가능
2) NodePort 서비스 (L4)
- 클러스터 외부에서 접속할 수 있는 서비스
- ClusterIP를 만들지만 각 노드에서 서비스 포트로 접속하기 위한 글로벌 포트를 개방한다는 차이점이 있음
노드포트 서비스 생성
NodePort 서비스로 외부에서 접근# 서비스 확인 kubectl get svc echo # HTTP 요청 curl http://localhost:30725
실행결과
3) LoadBalancer 서비스
일반적으로 클라우드 벤더에서 제공하는 설정 방식으로 플랫폼에서 제공하는 로드밸런서와 연동하기 위해 사용한다.
외부 IP를 가지는 로드밸런서를 할당하여 외부 접근 가능하다.
- GCP Cloud Load Balancing, AWS Elastic Load Balancing 지원
4) ExternalName 서비스
- 쿠버네스트 클러스터에서 외부 호스트를 네임 레졸루션 하기 위한 별명을 제공한다.(셀렉터/포트정의 없음)
외부 서비스를 쿠버네티스 내부에서 호출하고자 할 때 사용할 수 있다. (RDS, CloudSQL등 사용 시 이용)
인그레스(Ingress)
외부로 서비스 공개 시 서비스를 NodePort로 노출 시 L4에 TCP단에서 pod를 밸런싱한다
HTTP/HTTPS 경로 기반으로 서비스 제어 필요 시 L7 레벨의 Ingress 사용하여 해결 가능 ( + 로드밸런싱, 인증서 처리등 가능)
Ingress의 구현체
- GKE : 글로벌 로드밸런서
- NginX ingress controller
- Kong ingress controller
(상황)
외부에서 쿠버네티스 클러스터 내부로 들어오는 네트워크 요청 처리를 정의한다
MSA 경우 서비스 하나가 MSA 서비스로 표현되는 경우가 많고, 하나의 URL로 대표되는 경우가 많다.
MSA 라우팅하기 위해 API Gateway를 사용하는 경우가 많은데 사용 시 관리 포인트가 늘어난다. URL기반의 라우팅 기능만 사용한다면 ingress를 사용하여 처리할 수 있다.
(실습) Ingress controller를 이용하여 URI, Host 기반의 라우팅을 해본다
1. Ingress controller 배포
ingress-nginx를 사용하며 'ingress-nginx'라는 namespace로 생성
2. Ingress service 생성
외부에서 접근 가능하도록 Loadbalancer 타입의 Ingress service 생성하고 확인한다
3. Application 및 서비스를 배포
다른 정보를 가진 deployment, service를 생성한다.
예제용 deployment는 자신의 host 정보를 보여주는 nginx container이다. (각 서비스는 Cluster IP로 외부접근 불가)
- deployment : apps/a, apps/b
- service : service/a-svc, service/b-svc
4. URI 기반 라우팅
Path별로 라우팅하여 /a, /b 요청 시 각각 다른 서비스로 연결되도록 설정한다.
- http://localhost/a → a-svc 서비스로 접근
- http://localhost/b→ b-svc 서비스로 접근
4-1) Ingress 생성 ( sample_ingress_uri.yaml 배포 )
4-2. Ingress 생성 확인 후 URI 라우팅 테스트
로드밸런서 생성 확인 결과 (External IP 확인)
테스트 결과
5. 호스트기반 라우팅
Host 기반 라우팅을 테스트 한다.
동일한 External-IP에 각각 다른 도메인으로 요청 시 다른 서비스로 연결되도록 설정한다
- a.svc.com으로 요청 시 → a-svc 서비스로 접근
- b.svc.com으로 요청 시→ b-svc 서비스로 접근
5-0. 이전 URI Ingress 설정 삭제
kubectl delete ingress ab-ingress
5-1. Ingress 생성 ( sample_ingress_host.yaml 배포 )
5-2. Ingress 생성 확인 후 URI 라우팅 테스트
테스트 결과
잡(Job)
하나 이상의 pod를 생성해 지정된 pod가 정상 종료될 때까지 관리하는 리소스
배치 작업 위주의 애플리케이션에 적합
ex1) 원타임으로 파일 변환
ex2) 주기적으로 배치 작업하는 경우
Job에서 관리되는 pod는 job 종료 시 pod 같이 종료한다.
Job이 생성한 pod는 정상 종료 후에도 삭제되지 않고 남아있어 pod의 로그나 실행 결과를 분석 할 수 있다.
Job 특징
completion : 데이터가 커 범위를 나눠 작업해야하는 경우 pod를 순차적으로 여러번 실행할 수 있다.
parallelism : 여러 작업 처리 중 순차적 처리가 필요없는 경우 병렬처리가 가능하다.
- restartPolicy : Job 결과가 실패 일 경우 설정에 따라 재실행 할 지 설정할 수 있다.
- always : Pod가 종료하면 항상 재실행하여 실행 상태 유지 (pod는 이 값이 기본)
- Never : 실패 시 pod를 재생성해 실행
- OnFailure : 실패 시 실패한 pod를 재실행
restartPolicy : 파드 종료 후 재실행 여부로 Job 리소스 Always로 설정불가능(Never 혹은 OnFailure 설정)
# 파드 실행 kubectl apply -f simple-job.yaml # 로그 확인 kubectl logs -l app=pingpong # 파드 상태 확인 (Completed: 종료됨) kubectl get pod -l app=pingpong
크론잡(CronJob)
- 배치성 작업은 주기적으로 자동화하여 실행이 필요하다.
- Job은 단 한번만 실행되는데 반해 CronJob 스케줄을 지정해 정기적으로 pod를 실행할 수 있다.
- 컨테이너에 친화적인 특성을 유지하며 이벤트 애플리케이션을 따로 사용하지 않으며 스케줄에 따른 작업을 수행할 수 있다.
아래의 예제처럼 알파인 리눅스 등 경량 이미지 컨테이너에 작업을 매니페스트 파일로 기술하거나 구현을 매니페스트 파일 대신 도커 이미지에 포함시키는 방법 사용
(실습) 위 실습과 동일하며 1초마다 실행한다
# cronjob 배포 kubectl apply -f simple-cronjob.yaml # job 확인 kubectl get job -l app=pingpong # 로그 확인 kubectl logs -l app=pingpong
참고자료
Naver cloud platform Ingress 튜토리얼
1 개의 댓글
유주영
실습자료 다운로드
(위 실습과 파일명이 다를 수 있습니다. README 참고하세요)
https://github.com/juyoungyoo/slipp-k8s-sample.git