디플로이먼트로 관리되는 파드들은 보통 웹 서버처럼 항상 실행되고 있는 경우가 많기 때문에 파드가 정지되거나 멈추면 디플로이먼트가 계속 파드를 재실행해준다. 만약 buzz 컨테이너 파드가 메시지를 출력하고 종료되면 디플로이먼트가 buzz 파드를 재시작시키는데, 디플로이먼트는 관리 중인 파드가 종료되면 지정된 파드의 개수(replicaset로 지정된 파드_수)를 유지하기 위해서 파드를 자동으로 재실행시켜주기 때문이다. 이렇게 쿠버네티즈가 자동으로 디플로이먼트와 리플리카셋을 통해서 클러스트의 파드를 관리하게 하는 것이 좋은 것이어서 컨테이너 파드 관리를 관리자가가 수동으로 실행시켜서 파드의 갯수를 맞추는 작업을 수행한다면 그런 작업은 디플로이먼트 컨트롤러에 적합한 워크로드가 아닌 셈이다.
잡 컨트롤러를 사용하면 파드가 비정상적인 종료가 있을 때 지정한 횟수만큼 재실행되게 해준다. 문제가 있는 파드로 인해서 무한정 파드가 재시작되게 되면 매우 큰 시스템 리소스 손실이 되기 때문이다.
파드를 명령어로 생성할 수도 있지만 매니페스트파일로 생성할 수도 있다.
kubectl run nignx --image=nginx:latest (--restart=Never)라는 명령어를
매니페스트 파일로 생성한다면
a) 먼저 매니페스트 파일을 YAML 형식이나 JSON 현식으로 만든다.
nano nginx-pod.yml 하고
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers: ## containers가 복수이므로 여러 컨테이너를 기술할 수 있음
- name: nginx
image: nginx:latest
해서 저장하거나 OR
nano nginx-pod.json 하고
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "nginx"
},
"spec": {
"containers": [ ## containers가 복수이므로 여러 컨테이너를 기술할 수 있음
{
"name": "nginx",
"image": "nginx:latest"
}
]
}
} 해서 저장한다.
=>참고로 여기서 사용될 수 있는 옵션으로
apiVersion : 버전,
kind : Pod 설정,
metadata : 파드의 이름으로 필수적이며 네임스페이스에서 유일해야 함,
spec : 파드 사양 기술,
containers : 컨테이너 사양 기술이다. containers, initContainers, 그리고 volumes식으로 복수로 써주면 여러 개가 정의될 수 있다는 의미이다. 여기에는
containers, initContainers, 그리고 volumes식으로 복수로 써주면 여러 개가 정의될 수 있다는 의미이다.
initContainers : 초기화 전용 컨테이너 사양으로써 배열로 기술,
nodeSelector : 파드가 배포될 노드의 레이블 지정,
volumes : 파드 내 컨테이너 간 공유 볼륨설정,
image : 이미지의 리포지터리_명과 태그,
name : 컨테이너를 여러 개 기술할 경우 필수적으로 써줌,
livenessProbe : 컨테이너 어플이 정상적인지 검사,
readiness Probe : 컨테이너 어플이 사용자 요청을 받을 준비가 되었는지 검사,
ports : 외부로부터 요청을 전달받기 위한 포트목록,
resources : CPU와 RAM 요구량과 상한 값,
volume Mounts : 파드에 정의한 볼륨을 컨테이너의 파일 시스템에 마운트하는 설정, 복수 기술 가능,
command : 컨테이너 실행 시 실행할 명령어,
args : command의 인자,
env : 컨테이너 내의 환경변수 설정 등이다.
b) 이제 이 매니페스트 파일을 적용하는데
kubectl apply -f 파일_명 해주면 된다.
현재 실행되고 있는 nginx 웹 서버 파드는 백그라운드에서 클러스터 네트워크의 TCP 80번 포트에서 요청을 대기하게 된다. 클러스터 네트워크는 쿠버네티스 클러스터를 구성하는 노드 간 통신을 위한 폐쇄형 네트워크로써 파드 네트워크로도 불린다. 폐쇄형이라서 클러스터 네트워크에서 열려 있는 포트라도 쿠버네티스 클러스터를 호스팅하는 Ubuntu 머신에서 접근할 수 없다. 쿠버네티스 클러스터 외부에서 이 파드 네트워크에 접근하려면 Service를 이용해야 한다.
로드밸런서와 마찬가지로 HTTP로 헬쓰 체크를 한다면
http://파드_IP:포트/healthz라는 스크립트를 정기적으로 실행시켜서 파드가 이에 적절한 응답을 반환하게 하는데 이 헬쓰체크 프로브에 대응하는 핸들러를 파드에서 다음 세 가지 중 하나로 설정할 수 있다.
핸들러 설명
exec 컨테이너 내 커맨드를 실행, Exit 코드 0으로 종료되면 진단결과를 성공으로 간주, 그 이외에는 실패로 간주
tcpSocket 지정한 TCP 포트 번호로 연결할 수 있으면 진단결과를 성공으로 간주
httpGet 지정한 포트와 경로로 HTTP GET 요청이 정기적으로 실행, HTTP 상태 코드가 200~400이면 성공, 그 외에는 실패로 간주
초기화 전용 컨테이너
파드 내에서 예를 들어 스토리지를 마운트할 때 '스토리지 안에 새로운 디렉터리를 만들고 소유자를 변경한 뒤 마운트 한 곳에 데이터를 저장'하는 것과 같은 일련의 초기화만 담당하는 컨테이너를 설정할 수도 있다. 그러면 초기화만 수행하는 컨테이너와 요청을 처리하는 컨테이너를 별도로 개발해서 각각 재사용할 수 있다.
사이드카 패턴
사이드카 패턴은 하나의 파드 안에 여러 개의 컨테이너를 동시에 실행시키는 기법이다. 앞에서는 초기화 전용 컨테이너가 처리를 완료하면 이제 서비스 전용 컨테이너 시작 구성 패턴이 완성된 것인데, 패턴에 파드 내부의 여러 컨테이너를 동시에 시작시키도록 기술해주면 이 사이드카 패턴이 된다. 예를 들어 웹 서버 컨테이너와 최신 컨텐츠를 GitHub에서 다운받는 컨테이너 두 개가 하나의 파드에 묶여 있을 때 이런 조합을 사이드카라고 부른다. 사이드카 패턴의 장점은 여러 개의 컨터이너를 조합해서 사용함으로써 컨테이너의 재사용성이 높아지고, 생산성이 높아지는 것이다. webserver와 contents-cloner라는 사이드카 컨테이너를 개발해서 조합해보자.
이렇게 하면 콘텐츠 개발자가 git push만 실행하면 개발한 로컬의 콘텐츠를 바로 웹 서버에 업데이트할 수 있다. 그리고 공유 저장소를 사용하는 대신 각 노드의 저장 공간을 사용하기 때문에 성능도 좋아진다. 이때 파드 안의 컨테이너 별로 CPU 사용시간을 제한해서 웹 서버의 응답 시간을 우선하게 하고 남은 CPU 자원을 HTML 컨텐츠 다운로드에 사용하게 하는 식으로 운영할 수 있다.
디플로이먼트(Deployment)
디플로이먼트는 백엔드의 워크로드에서 필요한 컨트롤러로써 리플리카 셋과 함께 파드의 개수를 관리하는 일을 한다. 기존의 수평적 분산 시스템은 로드밸런서와 대등한 스펙의 여러 서버로 구성되는데 로드밸런서는 클라이언트로부터 요청을 받아서 백엔드에 있는 여러 서버 중 하나에게 전송하는 역할을 한다. 어플의 처리를 여러 파드 서버가 분담해서 떠맡는 구조이다. 이런 구조는 서버의 개수를 늘려서 처리능력을 높일 수 있고, 여분의 서버를 미리 투입해 두면 한 대의 서버에서 장애가 발생했을 때에도 문제가 없게 한다. 로드밸런서는 디플로이먼트에 포함되어져 있지 않고 서비스에 포함되어져 있다.
쿠버네티스 클러스터에서는 파드가 서버의 역할을 하기 때문에 처리 능력을 높인다면 파드이 수를 늘리면 된다. 그래서 여분의 파드를 실행시켜 두면 일부 파드에 문제가 있을 때 큰 문제없이 서비스를 제공할 수 있다. 하지만 불필요하게 너무 많은 파드를 실행해두면 시스템의 리소스를 너무 사용하므로 적절히 조절해두어야 한다. 파드의 개수를 조절해두는 것은 시스템의 처리능력, 서비스를 중단하지 않는 가용성, 그리고 비용 측면에서도 매우 중요하다.
디플로이먼트는 클라이언트가 요청한 개수만큼 파드 서버를 실행해주므로 장애 등의 이유로 파드가 줄어들면 새롭게 파드를 생성해서 실행시킨다. 또 어플의 버전 등을 업그레이드할 때에도 새로운 버전의 파드를 하나씩 차례로 변경해서 전체적으로 서비스가 잘 이뤄지게 한다. 디플로이먼트는 단독으로 실행되지 않고 리플리카셋과 함께 동작한다. 리플리카셋은 디플로이먼트의 매니페스트에 기술된 리플리카의 값을 기준으로 파드의 개수를 제어한다.
deployment YAML 파일에서의 설정에 사용되는 지시어로
▸ apiVersion : 쿠버네티스 버전으로 apps/v1, apps/v1beta2, apps/v1beta1, extensions /v1beta1식으로 지정한다.
▸ kind : Deployment 설정
▸ metadata : name에 객체_명을 지정
▸ spec : 디플로이먼트 사양 기술로써, 파드의 매니페스트에 있는 spec은 디플로이먼트의 매 니페스트에도 존재한다. 디플로이먼트의 template는 디플로이먼트에 의해 실행될 때 파드의 템플릿이 되는데, 디플로이먼트의 replicas 항목에 지정한 수 만큼 만들 파드의 spec이다.
▸ replicas : 파드 템플릿을 사용해서 파드의 개수 지정
▸ selector : 디플로이먼트 제어 하에서 리플리카셋과 파드를 matchLabels로 매칭시킨다.
▸ template : 파드의 템플릿
▸ metadata : 이 라벨의 내용은 셀렉터가 지정하는 라벨과 일치해야 함
▸ containers : 파드 컨테이너의 사양이다.
스케일링(Scaling)
스케일 기능이란 리플리카의 값을 변경해서 파드의 개수를 조절해서 처리능력을 높이거나/낮추는 기능을 말하는데 수동으로 리플리카 값을 변경하는 것을 살펴보자. 파드의 컨테이너는 CPU의 프로세스이기 때문에 아무리 가상 웹 서버 10개를 실행시킨다고 했어도 수동으로 지정하는 것보다 메인 CPU의 사용율과 연계해서 파드 내의 웹 서버와 동적으로 리플리카 셋의 값을 조절해서 적절한 규모로 실행시켜주는 오토스케일 기능을 사용하는 것이 좋다.
디플로이먼트는 파드의 수를 늘릴 수 있을 뿐이다. 파드를 생성하는 중에 쿠버네티스 클러스터 자원이 부족해지면 노드를 추가해서 자원이 생길 때까지 파드 생성을 보류한다. 가상 메모리를 사용하면서까지 파드를 늘리지는 않는다. 따라서 파드의 수를 늘리기 전에 클러스터의 가용 자원을 확인해서 노드의 증설을 미리 검토해 둘 필요가 있다.
==>참고로 파드 실행에서 CrashLoopBackOff 머신이 보이면 pod 실행 yml 파일에
command: ["/bin/sh", "-ec", "while :; do echo '.'; sleep 5 ; done"]를 추가하면 빠르게 Running으로 바뀔 수 있다.
롤 아웃(Roll Out)
롤 아웃은 일반적으로 새로운 소프트웨어를 개시한다는 의미인데, 쿠버네티스에서는 컨테이너 업데이트를 의미한다. 롤 아웃을 하기 위해서는 먼저 새로운 이미지를 빌드하고 리포지터리에 등록해 둔 다음, 새로운 이미지를 매니페스트의 image 항목에 기술하고, ‘kubectl apply –f 파일_명’으로 적용하면 롤 아웃이 시작된다. 하지만 새로운 버전과 이전 버전을 동시에 실행한다면 롤 아웃으로만 충분하지 않아서 어플 설계, 테이블 설계, 캐시 이용 등을 함께 고려해 두어야 한다.
현재 10개의 1.16으로 nginx를 실행하고 있는데 1.17로 업데이트한다면
중간의 RollingUpdateStrategy를 보면 25% max unavailable, 25% max surge로 보인다. 이 말은 25%까지 파드를 정지할 수 있고 25% 만큼 파드를 초과해서 실행할 수 있다는 의미이다. 리플리케이션의 10이면 최소 파드는 10-10x0.25=7.5이어서 8개가 실행되고, 업데이트하는 동안 초과 파드 수는 10+10x0.25=12.5이어서 13이 된다. 따라서 최소 8개의 파드를 유지하면서 점차적으로 업데이트하는데 총 13개의 파드가 실행되므로 롤아웃이 10개가 실행되면서도 점진적으로 진행된다는 의미이다. 총 13대까지 실행되므로 3대씩 업데이트하면서 진행된다. 그 동안 10대는 구 버전으로 실행된다.
롤백
롤백이란 용어는 SQL 데이터베이스 등에서는 트랜젝션 처리 중에 데이터의 변경이나 삭제를 취소하고 원래 상태로 되돌리는 것을 의미하는데, 쿠버네티스에서는 롤 아웃 전에 사용하던 예전 컨테이너로 되돌리는 것을 말한다. 앞에서의 롤 아웃처럼 파드를 사용자의 요청대로 점진적으로 버전 업데이트를 진행시켰지만 새로운 버전에서 문제가 발생되면 다시 원래대로 되돌리는 기능이다. 데이터 리커버리는 별도로 구현해야 한다.
파드의 IP_주소가 변경되는 경우와 고정되는 경우
파드의 IP_주소는 특정 이벤트에 의해서 변할 수도/안 변할 수도 있다. 기본적으로 파드의 IP_주소는 실행 시 할당되고 종료 시 회수되어 다른 파드에게 재할당 된다. 즉, 롤 아웃이나 롤 백, 스케일링에 의해서 파드가 종료되거나 새롭게 생성될 때 파드에게 새로운 IP_주소가 할당되는 것이다. 디플로이먼트 관리하의 파드를 하나 지우면, 리플리카로 설정한 파드 수를 유지하기 위해서 새로운 파드가 생성되어 실행되는데 이때 새로운 파드는 새로운 IP_주소를 받는다.
디플로이먼트의 자동복구
디플로이먼트의 자동복구 기능은 파드 내의 컨테이너가 어떤 이유로 종료한 경우 기본적으로 파드가 컨테이너를 재시작시킨다. 즉, 파드의 자동복구는 컨테이너 수준에서 이뤄지지만, 디플로이먼트의 자동복구는 파드 단위로 이뤄진다. 이 둘은 같을 수도 있지만 다를 수도 있는데 하나의 파드 안에는 여러 컨테이버(=이미지)가 있을 수 있기 때문이다.
디플로이먼트를 이용한 고가용성(HA) 구성
하나의 파드와 퍼시스턴트 볼륨을 사용하면 액티브 스탠바이(Active Standby: 상시 대기상태)한 고가용성(HA: High Availability)을 구성할 수 있다. 디플로이먼트는 안정적으로 동작되도록 설계되어 있어서 복구가 시작되지 전까지 5분이 소요되지만 유용한 기능이다. 파드는 어떤 노드에 있더라도 퍼시스턴트 볼륨을 마운트할 수 있다. 따라서 하나의 파드에 대해서 액티브 스탠바이 HA 구성이 가능하다. 클라우드 환경에서 HA를 구성할 때에는 퍼시스턴트 볼륨이 하나의 Zone에 있기 때문에 모든 노드가 같은 Zone에 있어야 한다.
=>AWS에서는 Region으로 이를 구성할 수 있다.
클라우드 보안에서는 on-premise한 private cloud(로컬 조직)에서 사용하던 보안 설정이 AWS와 같은 on-demand한 public cloud(상용 클라우드)에 100% 적용될 수 없기 때문에 문제가 많이 발생할 수 있다. 조직에서는 AWS에서 사용하는 모든 하드웨어와 소프트웨어 리소스에 대한 정보를 알 수 없기 때문이다(<=이를 Black Zone이라고 부른다).
그리고 클라우드는 수평적 개념이기 때문에 조직의 사용자가 일단 클라우드에 정상적으로 로그인하면 클라우드 안에서 자유롭게 IT 관리자의 간섭 없이도 여러 리소스를 사용할 수 있어서 보안/비용적 문제가 발생될 수 있다(<=Shadow IT라고 부른다).
MySQL 파드 서버를 매니페스트로 작성해서 배포한 뒤 외부의 퍼시스턴트 볼륨을 마운트해서 HA를 구성해보자. 클라이언트가 접근할 수 있도록 서비스 객체도 배포한다. 멀티 노드 환경이어야 한다.