- k8s가 하는 것과 하지 않는 것을 구분하는 것은 중요함
- k8s가 하는 것
- pods 같은 객체를 생성하고 관리할 수 있음
- pods를 모니터링하고 교체하고 scale등 ... 을 할 수 있음
- k8s는 우리가 만들어 놓은 자원을 활용하고, 우리가 설정한 목표에 적용할거임
- k8s가 자원을 생성하는 것은 아님 (우리가 설정해줘야함)
- 우리가 설정해줘야하는 것
- 클러스터와 노드 인스턴스(worker + master nodes)를 만들어줘야함
- 노드마다 API 서버를 세팅해야함 (kubelet, 또 다른 k8s services..)
- cloud provider에서 Load balancer, file system 같은게 필요하다면 이것들도 설정을 해줘야함
Installation

- master node가 있는 클러스터는 여러 시스템에 분산되어있음
- master node에는 API 서버와 스케줄러 등..이 설치되야함
- 또한 하나 이상의 worker node와 services(software)가 필요함
- worker node에는 docker와 kubelete이 설치되어서 master node와 통신을 하게 만들어야함
- kubectl (kube-control)
- 클러스터에 명령을 내리는 도구임
- 즉, 클러스터는 기술 인프라이고, kubectl은 인프라와 통신을 하기위한 도구임
- kubectl을 master node와 API server와 혼동을 하면 안됨!!
- kubectl은 명령만 내리고, master node가 명령을 수행하는거임
- 로컬에서 클러스터 환경을 구축하기 위해 minikube를 활용할거임
먼저 kubectl을 설치 해볼거임
https://kubernetes.io/docs/tasks/tools/install-kubectl-macos/#before-you-begin
Install and Set Up kubectl on macOS
Before you begin You must use a kubectl version that is within one minor version difference of your cluster. For example, a v1.33 client can communicate with v1.32, v1.33, and v1.34 control planes. Using the latest compatible version of kubectl helps avoid
kubernetes.io
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl.sha256"
아래는 checksum file이 잘되었는지 확인 하는 명령어
echo "$(cat kubectl.sha256) kubectl" | shasum -a 256 --check

chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
sudo chown root: /usr/local/bin/kubectl
터미널에서 어느 위치(디렉토리)에서든 실행할 수 있도록 설정하는 명령어임
kubectl version --client --output=yaml
확인 한번 해주고
rm kubectl.sha256
정리해주면됨
minikube를 설치해볼거임
https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Farm64%2Fstable%2Fbinary+download
minikube start
minikube is local Kubernetes, focusing on making it easy to learn and develop for Kubernetes. All you need is Docker (or similarly compatible) container or a Virtual Machine environment, and Kubernetes is a single command away: minikube start What you’ll
minikube.sigs.k8s.io
curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-darwin-arm64
sudo install minikube-darwin-arm64 /usr/local/bin/minikube
minikube start
나는 Docker Desktop이 있기에, 드라이버를 virtual box 같은걸 지정안해줘도 docker위에 k8s가 올라가게 됨

만약 vritual machine을 사용하면 guest OS(우분투) 위에 minikube를 올려야하지만,
docker engine(경량화된 vm역할)을 통해 컨테이너에 바로 minikube를 올릴 수 있음
minikube status

minikube dashboard
대시보드에 드갈 수 있음
Understanding k8s Objects

Pod Objects

- 보통 pod하나당 컨테이너 하나가 들어가지만, 로그 수집 컨테이너 같은걸 붙일때 다중 컨테이너를 사용하기도 함
- volumes를 통해 pods들은 자원을 공유할 수 있음
- 클러스터 내부 IP주소를 가짐
- 즉, 한 Pod 내부에 있는 컨테이너들은 localhost (127.0.0.1) 주소를 통해 직접 통신할 수 있음
- 같은 네트워크 네임스페이스를 공유하여, 서로 네트워크 인터페이스가 겹치기 때문임
Deployments Object

- k8s는 deployment object라고 봐도 무방함
- 사용자가 원하는걸 지정하면 그에 맞게 실행을 함
- Deployment가 Pod의 직접 생성·제거, 유지관리, 자동 스케일링, 롤백까지 관리함
- pod를 직접 생성하지는 않지만, 우리가 원하는걸 반영하고 관리해주는 역할임
실습을 해보자
- 앱을 내 클러스터에서 실행을 해볼려고함
app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send(`
<h1>Hello from this NodeJS app!</h1>
<p>Try sending a request to /error and see what happens</p>
`);
});
app.get('/error', (req, res) => {
process.exit(1);
});
app.listen(8080);
- app.listen(8080): 이 앱을 포트 8080번에서 HTTP 요청을 받을 수 있도록 서버를 시작
Dockerfile
FROM node:14-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "node", "app.js" ]
- EXPOSE 8080: 컨테이너가 내부적으로 8080 포트를 사용한다는 것을 명시함
- CMD: 컨테이너가 시작될 때 기본으로 실행할 명령어
package.json
{
"name": "first-run",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Maximilian Schwarzmüller / Academind GmbH",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"body-parser": "^1.19.0"
}
}
- Node.js 프로젝트에 필요한 패키지 정보가 들어있음
.dockerignore
node_modules
Dockerfile
이제 터미널에서 아래와 같이 실행을 해보자
docker build -t kub-first-app .
- 이미지에 kub-first-app이라는 tag를 붙여서 실행할거임
- 이제 kubectl을 이용해 이미지를 k8s로 보내는 과정을 해볼거임
먼저 dockerhub를 쓰지 않고 바로 보낼 경우 error가 발생함
kubectl create deployment first-app --image=kub-first-app
- kubectl 명령어는 로컬 시스템에서 k8s 클러스터로 보낼때 항상 사용함

kubectl get deployments 명령어를 통해 확인해보면
- READY 부분에 0(current state)/1(target state)이 나오는데 1개중에 0개인 상태이므로 실패했다는 거임

kubectl get pods 명령어를 통해 확인해봐도 Err가 나온것을 확인할 수 있음
- k8s는 pod를 생성할 때, 지정된 이미지를 클러스터(노드) 머신에서 받아와야 함
- --image=kub-first-app라고 하면, k8s는 도커 허브같은 곳에서 kub-first-app이라는 이미지를 찾으려 시도함
- 현재 이미지는 로컬 머신에만 있으면 ErrImagePull이 발생하게 된 것임
- 즉, 쿠버네티스 클러스터/노드 내부의 로컬 도커 저장소에 동일한 이름의 이미지가 없으면,
- 노드들은 기본적으로 외부(도커 허브 등)에서 이미지를 찾으려고 하기에
- Dockerhub에 이미지를 올리고 다운 받는 과정이 필요한거임
kubectl delete deployment first-app
다시 삭제하고 docker hub에 먼저 보내보자
docker-hub에서 Create Repository에서 kube-first-app을 등록해주면됨
docker tag kub-first-app <devminii/kube-first-app 자기 계정 이름 적어주면됨>
docker push devminii/kube-first-app
도커허브에 올리고 다시 아래 명령을 실행하면 이미지는 원격 이미지를 가리키게됨
kubectl create deployment first-app --image=devminii/kube-first-app

정상적인것을 확인할 수 있음
대시보드에서도 확인할 수 있음

Service Object

- 포드와 그 안의 컨테이너에 도달할려면 Service가 필요함
- Pods는 기본적으로 내부 IP를 가지고 있음

- 내부 IP에는 외부에서 접근을 못하고, pod교체시 매번 내부 IP가 변경되는 문제가 있음
- 즉, service는 pod를 함께 그룹화하고 변경되지 않는 공유 IP주소를 제공함
service에 대해 실습을 해보자
kubectl expose deployment first-app --type=LoadBalancer --port=8080
- expose: Deployment와 연결된 Pod들을 Service(고정 IP)라는 네트워크 진입점으로 노출하는 명령어임
- first-app이라는 이름의 Deployment를 tag함
- 생성하는 서비스 타입을 LoadBalancer로 지정
- 이 서비스에 대한 고유 주소를 생성함
- 클라우드 환경에서는 외부에 IP를 할당하여, 외부에서 직접 접근할 수 있는 로드밸런서를 생성함
- --port=8080: 서비스가 외부로 노출할 포트 번호가 8080
kubectl get services
상태를 확인할 수 있음

외부 IP는 아직 확인할 수 없음
minikube service first-app

이 URL을 통해 외부에 접근하면 됨

- /error 주소를 주게되면 k8s는 스스로 재시작을 할려고 할것임
- kubectl get pods를 통해 확인이 가능함
kubectl scale deployment/first-app --replicas=3
- first-app이라는 이름의 Deployment의 Replica 수를 3개로 조정 (명령어로 scale을 관리할 수 있음, 자동은 아님)

- error가 발생해도 다른 pod에 의해 계속 실행되고, error가 발생한 pod는 자동으로 재시작되면서 복구됨
kubectl scale deployment/first-app --replicas=1
- 이렇게하면 다시 replica가 1로 돌아가서 pod가 하나만 남는것을 확인할 수 있음
코드를 변경하고 원할 경우에 대해 실습을 해보자
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send(`
<h1>Hello from this NodeJS app!</h1>
<p>Try sending a request to /error and see what happens</p>
<p>Try Try Try Try</p>
`);
});
app.get('/error', (req, res) => {
process.exit(1);
});
app.listen(8080);
- 코드를 잠시 고치고 해보자
- 코드를 바꾸고 나서 이미지는 다시 빌드해줘야함
docker build -t devminii/kube-first-app .
- 업데이트된 이미지를 반영하여 새로운 배포로 업데이트할려함
- 먼저 배포가 존재하는지 확인함
kubectl get deployments
다시 docker hub에 올리고 이미지를 변경할거임
docker push devminii/kube-first-app
kubectl set image deployment/first-app kube-first-app=devminii/kube-first-app
- fisrt-app이라는 Deployment 내의 kube-first-app 컨테이너의 이미지를
- devminii/kube-first-app으로 update하라는 뜻
- 이렇게 하면 반영이 안되게 나옴
- 그래서 아래와 같이 할거임
docker build -t devminii/kube-first-app:2 .
- ‘devminii/kube-first-app:2’ 버전 도커 이미지를 새로 만들어서 저장함
docker push devminii/kube-first-app:2
kubectl set image deployment/first-app kube-first-app=devminii/kube-first-app:2
- k8s가 2가 붙은 이미지를 이전에 사용된거와 다른 태그로 인식하고
- 다시 다운받아 이를 기반으로 컨테이너를 다시 시작하도록함
kubectl rollout status deployment/first-app
- rollout된 것을 확인하는 명령어


Rollbacks & History
- first-app:3로 실제 존재하지 않는 이미지를 실행시켜볼거임
kubectl set image deployment/first-app kube-first-app=devminii/kube-first-app:3
- roll out 진행상황을 아래 명령어를 통해 검사해볼거임
kubectl rollout status deployment/first-app

- 방금 3을 배포했는데 업데이트가 아직되지 않았으며, 이전 pod가 끝나기를 기다리고있는 상태임
- 왜냐하면 3은 없는 이미지이기에 기존에있는 pod가 종료할 필요가 없기 때문인거임
- 즉, 업데이트를 롤백해야함

kubectl rollout undo deployment/first-app

- 더 오래전으로 돌아가고 싶으면 history를 봐야함
kubectl rollout history deployment/first-app --revision=1
- revision=1, 2, 3...원하는 번호를 선택해서 정해주면됨

- 처음에 했던걸로 돌아가볼려고 함
kubectl rollout undo deployment/first-app --to-revision=1
이렇게 하면 처음에 했던게 나오게 됨
'클라우드 > Docker & Kubernetes' 카테고리의 다른 글
| Virtualization (0) | 2025.08.19 |
|---|---|
| k8s-Deployment (AWS EKS) (0) | 2025.08.11 |
| Managing Data & Volumes with k8s (0) | 2025.08.08 |
| k8s core concepts & setup (2) (0) | 2025.08.07 |
| Kubernetes Concepts (0) | 2025.08.06 |