240411 Kubernetes CNI와 어플리케이션 배포 과정 체험, pod 수명주기
Kubernetes CNI와 어플리케이션 배포 과정 체험
POD 배포 실습
일반적인 어플리케이션의 배포 절차
- 개발팀에 application 배포 일정이 잡힌다.
- Dockerfile을 생성하고 build 해서 이미지를 생성한다.
- docker run을 이용해 컨테이너를 테스트한다.
- docker hub 등의 레포지토리에 업로드한다.
- 올라간 이미지를 pod와 service를 생성해 연결한 뒤에 테스트한다.
- 테스트가 끝났다면 배포 파이프라인을 구축한다.
위 절차대로 실습해 봤다.
~ 폴더 하위에 nodeapp 폴더를 만든 뒤 app.js 파일을 생성했다.
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('deploy node app as pod on k8snode');
}).listen(3000);
app.js는 위와 같다.
app.js를 실행하기 위해 노드 환경이 필요하다.
node 이미지를 pull해왔다.
1) node:21-slim 컨테이너를 3000번 포트로 생성한다.
2) app.js 파일을 컨테이너 내부로 보낸다.
3) 노드가 잘 실행되고 있는지 확인한다.
4) app.js를 실행한다.
위와 같은 순서대로 실행 시 에러 없이 포그라운드 형식으로 잘 실행되었다.
컨테이너에 대해 도커 측 ip를 확인했다.
또 다른 master 노드의 터미널 창을 열어 curl로 3000번 포트에 접근해 봤다.
위처럼 app.js에 작성한 글이 출력된다면 어플리케이션의 동작에는 문제가 없다는 뜻이다.
이제 pod로 쓸 수 있도록 이미지화할 것이다.
실행 중인 node-app 컨테이너를 종료, 삭제한다.
이미지화를 위해 Dockerfile을 작성 후 이미지를 빌드한다.
FROM node:21-slim
EXPOSE 3000
COPY app.js .
CMD node app.js
도커파일 내용은 위와 같다.
생성한 이미지로 curl 테스트를 해보니 잘 동작했다.
그다음으로는 이 이미지를 docker hub에 올린 다음 pod화 할 것이다.
먼저 선언형 yaml 파일인 nodeapp.yaml을 생성한다.
apiVersion: v1
kind: Pod
metadata:
name: nodeapp-pod
labels:
app: test-nodeapp
spec:
containers:
- name: node-container
image: dockerhubID/nodeapp:1.0
ports:
- containerPort: 3000
nodeapp.yaml은 위와 같다.
실행 중인 컨테이너를 종료, 삭제한 뒤
pod 형식으로 띄웠다.
만약 바로 Running 상태가 되지 않고 오류가 난다면 터미널창에서 dockerhub에 로그인을 한 뒤 다시 시도하면 된다.
pod는 kubectl의 제어를 받기 때문에 사용자가 요청한 pod 상태와 실제 pod 상태를 controller manager가 계속 체크한다.
따라서 따로 조치를 취하지 않아도 알아서 Running 상태로 업로드가 된다.
위에서 확인한 ip로 curl 하면 접속이 잘 된다.
pod에 할당된 ip가 쿠버네티스 내부방으로 간주하기 때문에 powershell에서는 접속되지 않는다.
pod를 노출시키기 위해 service 객체를 생성해야 한다.
서비스의 목적
: selector에 적힌 label명을 가진 pod를 찾아서 적힌 스펙대로 외부에 노출시켜 주는 것
따라서 서비스의 selector과 파드의 label을 모두 test-nodeapp으로 일치시킨다.
apiVersion: v1
kind: Service
metadata:
name: nodeapp-svc
spec:
selector:
app: test-nodeapp
ports:
- port: 10001
targetPort: 3000
externalIPs:
- 2번노드주소
nodeapp-svc.yaml 파일의 내용은 위와 같다.
마지막 externalIPs는 해당 pod가 배정된 인스턴스의 내부주소로 작성해야 한다.
나는 2번 노드에 배정되어 있다.
그러면 2번노드주소:10001 접속 시 pod 컨테이너의 3000번 포트로 연결된다.
그러고 나서 kubectl로 해당 object들을 검색해 보면
위와 같이 nodeapp-pod와 nodeapp-svc가 함께 돌고 있다.
pod의 자체 주소는 첫 줄에 있는 ip
service의 자체 주소는 두 번째 줄에서 첫 번째로 출력된 ip
그리고 2번 노드 주소의 10001번 포트 접속 시 서비스가 pod로 연결해 준다는 것을 알 수 있다.
이제 powershell에서도 접속이 가능해졌다.
호스트 pc의 브라우저에서도 접속 가능하다.
할당된 pod와 svc를 삭제하는 명령어는 위와 같다.
pod 수명주기
kubectl api-resources
: 사용 가능한 object 출력
shortnames
: 호출 시 단축어로 조회가능한 명령어
yaml코드에 기술한 내용을 kubectl을 이용해 실행하면 해당 내용은 api서버가 전달받고
그 이후에는 스케줄러와 echd 등을 거쳐 object로 등록되고 실행된다.
선언적 명령을 위한 yaml 파일의 구조
apiVersion: v1등...
kind: 만드려는 object의 종류
metadata:
name: 만드려는 object의 이름
namespace: 소속 namespace
label: 구분을 위해 붙이는 별명
spec:
기타 상세 정보들...
yaml파일에서는 보통 apiVersion, kind, metadata, spec 4개의 옵션은 필수적으로 작성한다.
apiVersion에 쓸 수 있는 요소들은 위 명령어로 확인 가능하다.
보통 완성된 pod에는 대부분 v1을 쓴다.
kind
- pod, service 등 특정 단위의 object를 작성한다.
metadata
- object가 가지는 고유한 설명에 대해 작성한다.
name
- 작성해 주는 것이 기본이지만 작성하지 않아도 디폴트 값이 들어간다.
spec
- object가 가지는 고유한 설정 및 정의에 대해서 기술한다.
- 사용자가 의도한 상태를 가지도록 하기 위해서 spec을 작성한다.
특정 object에 대한 세부사항을 확인하고 싶다면
kubectl explain pods
명령어를 사용한다.
fileds에 따르면 yaml 코드로 선언할 시에 pod는
apiVersion, kind, metadata, spec, staus를 1차적인 정보로 가질 수 있다고 나온다.
pod 하위의 spec은 위와 같이 . 로 계층을 구분해서 조회할 수 있다.
한 번에 모든 계층구조를 확인하고 싶다면
재귀호출(--recursive) 옵션을 붙여주면 된다.
yaml 검증 및 작성 툴
vscode에서 .yaml으로 파일을 생성하면 형식을 바로 지원해 준다.
yaml 코드 검증 사이트로 구조가 어떤지,
검증 사이트로 계층이 깨진 곳이 있는지 확인할 수 있다.
YAMLlint - The YAML Validator
www.yamllint.com
pod를 관리하는 단위들
pod
: 컨테이너를 생성하고 싶을 때 만들 수 있는 가장 작은 단위
2개 이상의 같은 컨테이너를 병렬형식으로 배치해야 하는 경우에는
replicaSet(레플리카셋)을 사용한다.
replicaSet의 특징
- pod개수를 무조건 복사본으로 정의한 개수만큼 유지한다.
- 중간에 컨테이너 하나가 죽어버리면 그 즉시 새로운 pod를 생성해 사용자의 요구와 시스템 상의 배포상태를 맞춰준다.
Deployment
- replicaSet을 그룹으로 가질 수 있다.
- replicaSet의 소속으로만 기능하는 것이 아니라 배포 시 롤링 무중단 배포를 한다던지 여러 관리 옵션을 걸 수 있다.