포드(pod)
컨테이너 애플리케이션의 기본 단위
1개 이상의 컨테이너로 구성된 컨테이너 집합
여러 개의 컨테이너를 추상화해서 하나의 애플리케이션으로 동작하도록 만드는 컨테이너 묶음
사이드카 패턴
웹 서버 컨테이너와 최신 컨텐츠를 깃헙에서 가져오는 컨테이너를 하나의 파드 묶음

#1 깃허브에서 정기적으로 컨텐츠를 다운받는 쉘을 작성
c:\cloud\sidecar\contents-cloner
#!/bin/bash
# CONTENTS_SOURCE_URL 환경변수가 설정되어 있는지 확인
# 없는 경우 에러 종료
if [ -z $CONTENTS_SOURCE_URL ]; then
exit 1
fi
# 처음에는 git clone을 통해서 컨텐츠를 가져옮
git clone $CONTENTS_SOURCE_URL /data
# 이후부터는 60초 마다 깃헙에서 컨텐츠를 가져옮
cd /data
while true
do
date
sleep 60
git pull
done
#2 깃허브에서 정기적으로 컨텐츠를 다운받는 컨테이너 이미지 작성을 위한 Dockerfile을 작성
c:\cloud\sidecar\Dockerfile
FROM ubuntu:16.04
RUN apt-get update && apt-get install -y git
COPY ./contents-cloner /contents-cloner
RUN chmod a+x /contents-cloner
WORKDIR /
CMD [ "/contents-cloner" ]
#3 이미지 빌드 후 레지스트리(도커허브)에 등록
PS c:\cloud\sidecar> docker build --tag mhee4321/c-cloner:0.1 .
#4 깃헙 레포지터리 생성
mhee4321/web-contents
#5 사이드카 패턴의 포드를 생성하는 매니페스트(yaml) 파일 작성
[vagrant@master sidecar]$ vi webserver.yaml
apiVersion: v1
kind: Pod
metadata:
name: webserver
spec:
containers:
- name: nginx # 주기능을 수행하는 컨테이너
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html # nginx 웹 루트 디렉터리
name: contents-vol
readOnly: true
- name: cloner # 보조 기능을 수행하는 컨테이너 ⇐ 사이드카 컨테이너
image: myanjini/c-cloner:0.1
env:
- name: CONTENTS_SOURCE_URL # github 저장소 주소
value: "https://github.com/mhee4321/web-contents"
volumeMounts:
- mountPath: /data # github에서 가져온 데이터가 쌓이는 곳
name: contents-vol
volumes:
- name: contents-vol
emptyDir: {}
#6 포드를 생성
[root@master sidecar]# kubectl apply -f webserver.yaml
[root@master sidecar]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hello-pod 1/1 Running 2 3d16h 192.168.166.138 node1 <none> <none>
my-nginx-pod 2/2 Terminating 0 18h 192.168.104.9 node2 <none> <none>
nginx-test 1/1 Running 3 3d23h 192.168.166.137 node1 <none> <none>
webserver 2/2 Running 0 30s 192.168.166.140 node1 <none> <none>
[root@master sidecar]# kubectl logs webserver -c cloner
Cloning into '/data'...
Tue Feb 23 00:43:10 UTC 2021
Already up-to-date.
Tue Feb 23 00:44:11 UTC 2021
Already up-to-date.
Tue Feb 23 00:45:12 UTC 2021
Already up-to-date.
Tue Feb 23 00:46:13 UTC 2021
Already up-to-date.
Tue Feb 23 00:47:13 UTC 2021
#7 대화형 포드를 기동해서 포드의 초기 컨텐츠를 출력
[root@master sidecar]# kubectl run busybox --image=busybox --restart=Never --rm -it sh
(한번쓰고 버릴 포드 -> 웹서버 코드에 있는 nginx쪽으로 보냈을 때 응답이 어떤지 보기 위함)
/ # wget -q -O - http://192.168.166.140
<!----github에 있는 내용------>
<!DOCTYPE html>
<html>
<head>
<title>사이드카 패턴</title>
</head>
<body>
<h1>사이드카 패턴</h1>
</body>
</html>
#8 github에 컨텐츠 내용을 변경 후 다시 요청
web-contents/index.html
<!DOCTYPE html>
<html>
<head>
<title>사이드카 패턴</title>
</head>
<body>
<h1>사이드카 패턴</h1>
<a>새로운 내용 추가</a>
</body>
</html>
/ # wget -q -O - http://192.168.166.140
<!DOCTYPE html>
<html>
<head>
<title>사이드카 패턴</title>
</head>
<body>
<h1>사이드카 패턴</h1>
<a>새로운 내용 추가</a>
</body>
</html>
포드의 헬스 체크 기능
헬스 체크 ⇒ 포드의 컨테이너에는 어플리케이션이 정상적으로 동작하고 있는지 확인하는 기능
→ 헬스 체크 결과, 이상이 감지되는 경우에는 컨테이너를 강제 종료하고 재시작할 수 있음
→ kubelet이 컨테이너의 헬스 체크를 담당
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
활성 프로브(Liveness Probe)
-
컨테이너의 어플리케이션이 정상적으로 실행 중인 것을 검사
-
검사에 실패하면 포드상의 컨테이너를 강제로 종료하고 재시작
-
매니페스트에 명시적으로 설정해야 사용할 수 있음
준비 상태 프로브(Readiness Probe)
-
컨테이너의 어플리케이션이 요청을 받을 준비가 되었는지 검사
-
검사에 실패하면 서비스에 의한 요청 트래픽 전송을 중비
-
포드가 기동되고 나서 준비가 될 때까지 요청이 전송되지 않도록 하기 위해 사용
-
매니페스트에 명시적으로 설정해야 사용할 수 있음
#1 작업 디렉터리 생성 후 매니페스트 파일(YAML) 작성
**매니페스트 파일 : 작업 내용을 기술해 놓은 파일
[root@master ~]# mkdir hc-probe
[root@master ~]# cd hc-probe/
[root@master hc-probe]# vi webapl-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: webapl
spec:
containers:
- name: webapl
image: myanjini/webapl:0.1 # 핸들러를 구현한 어플리케이션
livenessProbe: # 어플리케이션이 동작하지 여부를 확인
httpGet: # 지정된 포트와 경로로 HTTP GET 요청을 주기적으로 실행
path: /healthz # 확인 경로
port: 3000 # 확인 포트
initialDelaySeconds: 3 # 검사 개시 대시 시간
periodSeconds: 5 # 검사 주기
readinessProbe: # 어플리케이션이 준비되었는지 확인
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 15
periodSeconds: 6
#2 컨테이너 이미지를 생성
[root@master hc-probe]# vi Dockerfile
FROM alpine:latest
RUN apk update && apk add --no-cache nodejs npm
WORKDIR /
ADD ./package.json /
RUN npm install
ADD ./webapl.js /
CMD node /webapl.js
[root@master hc-probe]# vi package.json
{
"name": "webapl",
"version": "1.0.0",
"description": "",
"main": "webapl.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.3"
}
}
[root@master hc-probe]# vi webapl.js
// web application
const express = require('express')
const app = express()
var start = Date.now() //어플리케이션이 시작된 시간
// http://CONTAINER_IP:3000/healthz 형식으로 요청이 들어왔을 때 수행하는 기능을 정의하는 함수
app.get('/healthz', function(request, response) {
var msec = Date.now() - start //어플리케이션이 시작된 후 경과된 시간
var code = 200
if (msec > 40000 ) { //경과된 시간이 40000 밀리세컨드 보다 작으면 200, 크면 500 반환
code = 500
}
console.log('GET /healthz ' + code)
response.status(code).send('OK')
})
// http://CONTAINER_IP:3000/ready 형식으로 요청이 들어왔을 때 수행하는 기능을 정의하는 함수
app.get('/ready', function(request, response) {
var msec = Date.now() - start
var code = 500
if (msec > 20000 ) {
code = 200
}
console.log('GET /ready ' + code)
response.status(code).send('OK')
})
app.get('/', function(request, response) {
console.log('GET /')
response.send('Hello from Node.js')
})
app.listen(3000);
#3 컨테이너 이미지 생성 후 도커허브에 등록
[root@master hc-probe]# docker build --tag mhee4321/webapl:0.1 .
[root@master hc-probe]# docker push mhee4321/webapl:0.1
[root@master hc-probe]# kubectl apply -f webapl-pod.yaml
[root@master hc-probe]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d19h
my-nginx-pod 2/2 Running 2 21h
nginx-test 1/1 Running 4 4d2h
pod-1 2/2 Running 6 3d21h
webapl 0/1 ContainerCreating 0 3s
webserver 2/2 Running 0 3h6m
[vagrant@master hc-probe]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d19h
my-nginx-pod 2/2 Running 2 21h
nginx-test 1/1 Running 4 4d2h
pod-1 2/2 Running 6 3d21h
webapl 0/1 Running 0 6s
|
+------------------------------- ⇐ readinessProbe가 아직 성공하지 못해 READY 상태가 아닌 것으로 판정
webserver 2/2 Running 0 3h6m
:
[vagrant@master hc-probe]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d19h
my-nginx-pod 2/2 Running 2 21h
nginx-test 1/1 Running 4 4d2h
pod-1 2/2 Running 6 3d21h
webapl 1/1 Running 0 30s
webserver 2/2 Running 0 3h7m
[root@master hc-probe]# kubectl logs webapl
GET /healthz 200
GET /healthz 200
GET /healthz 200
GET /ready 500 15 + 6초
GET /healthz 200 20초
GET /ready 200 15 + 12초 → 20초 초과 ⇒ READY 상태 1/1가 설정
GET /healthz 200
GET /ready 200
GET /healthz 200
GET /healthz 200
GET /ready 200
GET /healthz 200 40초
GET /ready 200
GET /healthz 500 45초
GET /ready 200
GET /healthz 500
GET /ready 200
GET /healthz 500
GET /ready 200
GET /ready 200
GET /ready 200
GET /ready 200
[root@master hc-probe]# kubectl describe pods webapl
Name: webapl
Namespace: default
Priority: 0
Node: node2/192.168.56.12
Start Time: Tue, 23 Feb 2021 04:41:15 +0000
Labels: <none>
Annotations: cni.projectcalico.org/podIP: 192.168.104.22/32
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"webapl","namespace":"default"},"spec":{"containers":[{"image":"myanji...
Status: Running
IP: 192.168.104.22
Containers:
webapl:
Container ID: docker://50e33d3ae2a2de2c79b5f039ef0d17d874817dc9996a5ed457ca345b81ffd4d2
Image: myanjini/webapl:0.1
Image ID: docker-pullable://myanjini/webapl@sha256:fde38c453b96f5dcc418bf903f234caebb2c9f0e4a479035da4caeedceaa3a46
Port: <none>
Host Port: <none>
State: Running
Started: Tue, 23 Feb 2021 04:41:17 +0000
Ready: True ⇐ ReadinessProbe가 성공한 경우 True로 설정
Restart Count: 0
Liveness: http-get http://:3000/healthz delay=3s timeout=1s period=5s #success=1 #failure=3
Readiness: http-get http://:3000/ready delay=15s timeout=1s period=6s #success=1 #failure=3
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-mmbs5 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-mmbs5:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-mmbs5
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 49s default-scheduler Successfully assigned default/webapl to node2
Normal Pulled 47s kubelet, node2 Container image "myanjini/webapl:0.1" already present on machine
Normal Created 47s kubelet, node2 Created container webapl
Normal Started 47s kubelet, node2 Started container webapl
Warning Unhealthy 31s kubelet, node2 Readiness probe failed: HTTP probe failed with statuscode: 500
Warning Unhealthy 3s kubelet, node2 Liveness probe failed: HTTP probe failed with statuscode: 500
레플리카셋(Replica Set)
정해진 수의 동일한 포드가 항상 실행되도록 관리
노드 장애 등의 이유로 포드를 사용할 수 없다면 다른 노드에서 포드를 다시 생성
레플리카셋 생성 및 삭제
#1 기존에 생성한 리소스를 정리
[vagrant@master hc-probe]$ kubectl delete -f webapl-pod.yaml
pod "webapl" deleted
[vagrant@master hc-probe]$ cd ..
[vagrant@master ~]$ kubectl delete -f nginx-pod-with-ubuntu.yaml
pod "my-nginx-pod" deleted
[vagrant@master ~]$ cd sidecar
[vagrant@master sidecar]$ kubectl delete -f webserver.yaml
pod "webserver" deleted
**파드 안지워질 때 강제삭제
[root@master ~]# kubectl delete pods my-nginx-pod --grace-period=0 --force
#2 nginx 컨테이너 두 개를 실행하는 포드를 정의
apiVersion: v1
kind: Pod
metadata:
name: my-nginx-pod-a
spec:
containers:
- name: my-nginx-container
image: nginx
ports:
- containerPort: 80
protocol: TCP
---
apiVersion: v1
kind: Pod
metadata:
name: my-nginx-pod-b
spec:
containers:
- name: my-nginx-container
image: nginx
ports:
- containerPort: 80
protocol: TCP
⇒ 동일한 포드를 일일이 정의하는 것은 매우 비효율적인 작업이다.
⇒ 포드가 삭제되거나, 포드가 위치한 노드에 장애가 발생해서 포드에 접근할 수 없는 경우에는 관리자가 직접 포드를 삭제하고 다시 생성해야는 문제가 있다.
#3 레플리카셋을 정의
[vagrant@master ~]$ vi replicaset-nginx.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-nginx
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx-pods-label
template: ⇐ 포드 스펙, 포드 템플릿 → 생성할 포드를 명시
metadata:
name: my-nginx-pod
labels:
app: my-nginx-pods-label
spec:
containers:
- name: my-nginx-container
image: nginx:latest
ports:
- containerPort: 80
protocol: TCP
#4 레플리카셋을 생성 및 확인
[vagrant@master ~]$ kubectl apply -f replicaset-nginx.yaml
replicaset.apps/replicaset-nginx created
[vagrant@master ~]$ kubectl get pods,replicaset
NAME READY STATUS RESTARTS AGE
pod/hello-pod 1/1 Running 3 3d20h
pod/my-nginx-pod 2/2 Terminating 0 23h
pod/nginx-test 1/1 Running 4 4d4h
pod/replicaset-nginx-8c8gs 1/1 Running 0 23s
pod/replicaset-nginx-x4drl 1/1 Running 0 23s
pod/replicaset-nginx-zxdzq 1/1 Running 0 23s
NAME DESIRED CURRENT READY AGE
replicaset.apps/replicaset-nginx 3 3 3 23s
#5 포드 개수를 증가시킨 후 실행
[vagrant@master ~]$ cp replicaset-nginx.yaml replicaset-nginx-4pods.yaml
[vagrant@master ~]$ vi replicaset-nginx-4pods.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-nginx
spec:
replicas: 4
selector:
:
[vagrant@master ~]$ kubectl apply -f replicaset-nginx-4pods.yaml
replicaset.apps/replicaset-nginx configured ⇐ 기존 리소스를 수정 (포드 개수를 3개에서 4개로 조정)
[root@master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 3 3d21h
my-nginx-pod 2/2 Terminating 0 23h
nginx-test 1/1 Running 4 4d4h
replicaset-nginx-8c8gs 1/1 Running 0 33m
replicaset-nginx-wdgsn 1/1 Running 0 14s
replicaset-nginx-x4drl 1/1 Running 0 33m
replicaset-nginx-zxdzq 1/1 Running 0 33m
#6 레플리카셋을 삭제
[vagrant@master ~]$ kubectl delete rs replicaset-nginx
replicaset.extensions "replicaset-nginx" deleted
[vagrant@master ~]$ kubectl get pods ⇐ 레플리카셋으로 생성한 포드도 함께 삭제
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d21h
nginx-test 1/1 Running 4 4d4h
pod-1 2/2 Running 6 3d22h
[vagrant@master ~]$ kubectl apply -f replicaset-nginx-4pods.yaml
replicaset.apps/replicaset-nginx created
[vagrant@master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d21h
nginx-test 1/1 Running 4 4d4h
pod-1 2/2 Running 6 3d22h
replicaset-nginx-44lvg 1/1 Running 0 10s
replicaset-nginx-9hmrz 1/1 Running 0 10s
replicaset-nginx-9s8w2 1/1 Running 0 10s
replicaset-nginx-xt9bs 1/1 Running 0 10s
[vagrant@master ~]$ kubectl delete -f replicaset-nginx-4pods.yaml ⇐ YAML 파일을 이용해서 일괄 삭제도 가능
replicaset.apps "replicaset-nginx" deleted
레플리카셋 동작원리
#1 app: my-nginx-pods-label 라벨을 가지는 포드를 생성
[vagrant@master ~]$ vi nginx-pod-without-rs.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-nginx-pod
labels:
app: my-nginx-pods-label
spec:
containers:
- name: my-nginx-container
image: nginx:latest
ports:
- containerPort: 80
[vagrant@master ~]$ kubectl apply -f nginx-pod-without-rs.yaml
pod/my-nginx-pod created
[vagrant@master ~]$ kubectl get pods --show-labels ⇐ 라벨을 함께 출력
NAME READY STATUS RESTARTS AGE LABELS
hello-pod 1/1 Running 2 3d21h app=hello
my-nginx-pod 1/1 Running 0 14s app=my-nginx-pods-label
nginx-test 1/1 Running 4 4d4h run=nginx-test
pod-1 2/2 Running 6 3d22h <none>
#2 app: my-nginx-pods-label 라벨을 가지는 포드를 3개 생성하는 레플리카셋을 정의 후 생성
[vagrant@master ~]$ cat replicaset-nginx.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-nginx
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx-pods-label
template:
metadata:
name: my-nginx-pod
labels:
app: my-nginx-pods-label
spec:
containers:
- name: my-nginx-container
image: nginx:latest
ports:
- containerPort: 80
protocol: TCP
[vagrant@master ~]$ kubectl apply -f replicaset-nginx.yaml
replicaset.apps/replicaset-nginx created
[vagrant@master ~]$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
hello-pod 1/1 Running 2 3d21h app=hello
my-nginx-pod 1/1 Running 0 6m16s app=my-nginx-pods-label
nginx-test 1/1 Running 4 4d4h run=nginx-test
pod-1 2/2 Running 6 3d22h <none>
replicaset-nginx-d2fw8 1/1 Running 0 11s app=my-nginx-pods-label ⇐ 2개의 포드만 새로 생성
replicaset-nginx-d9np5 1/1 Running 0 11s app=my-nginx-pods-label
[vagrant@master ~]$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
replicaset-nginx 3 3 3 2m18s
#3 #1에서 수동으로 생성한 포드를 삭제
[vagrant@master ~]$ kubectl delete pods my-nginx-pod
pod "my-nginx-pod" deleted
[vagrant@master ~]$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
hello-pod 1/1 Running 2 3d21h app=hello
nginx-test 1/1 Running 4 4d4h run=nginx-test
pod-1 2/2 Running 6 3d22h <none>
replicaset-nginx-d2fw8 1/1 Running 0 4m28s app=my-nginx-pods-label
replicaset-nginx-d9np5 1/1 Running 0 4m28s app=my-nginx-pods-label
replicaset-nginx-m4kx2 1/1 Running 0 16s app=my-nginx-pods-label
#4 레플리카셋이 생성한 포드의 라벨을 변경 후 포드 정보를 조회
[vagrant@master ~]$ kubectl edit pods replicaset-nginx-d2fw8
아래 두 부분을 주석 처리 후 저장
# labels:
# app: my-nginx-pods-label
[vagrant@master ~]$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
hello-pod 1/1 Running 2 3d21h app=hello
nginx-test 1/1 Running 4 4d4h run=nginx-test
pod-1 2/2 Running 6 3d22h <none>
replicaset-nginx-4ljt7 1/1 Running 0 3m24s app=my-nginx-pods-label ⇐ 새로운 포드가 생성
replicaset-nginx-d2fw8 1/1 Running 0 12m <none> ⇐ 관리 대상으로 간주하지 않음
replicaset-nginx-d9np5 1/1 Running 0 12m app=my-nginx-pods-label
replicaset-nginx-m4kx2 1/1 Running 0 8m23s app=my-nginx-pods-label
[vagrant@master ~]$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
replicaset-nginx 3 3 3 14m
#5 레플리카셋을 삭제
[vagrant@master ~]$ kubectl delete replicaset replicaset-nginx
replicaset.extensions "replicaset-nginx" deleted
[vagrant@master ~]$ kubectl get replicaset
No resources found.
[vagrant@master ~]$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
hello-pod 1/1 Running 2 3d21h app=hello
nginx-test 1/1 Running 4 4d4h run=nginx-test
pod-1 2/2 Running 6 3d23h <none>
replicaset-nginx-d2fw8 1/1 Running 0 15m <none> ⇐ 라벨이 삭제된 포드는 레플리카셋에 의해 삭제되지 않음
#6 라벨이 삭제된 포드는 직접 삭제
[vagrant@master ~]$ kubectl delete pods replicaset-nginx-d2fw8
pod "replicaset-nginx-d2fw8" deleted
[vagrant@master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d21h
nginx-test 1/1 Running 4 4d4h
pod-1 2/2 Running 6 3d23h
디플로이먼트(Deployment)
레플리카셋, 포드의 배포, 업데이트 등을 관리
디플로이먼트 생성, 삭제
#1 디플로이먼트 정의 및 생성
[vagrant@master ~]$ vi deployment-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx
template:
metadata:
name: my-nginx-pod
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
[root@master ~]# kubectl apply -f deployment-nginx.yaml
deployment.apps/my-nginx-deployment created
[root@master ~]# kubectl get deployment,replicaset,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-nginx-deployment 3/3 3 3 46s
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-nginx-deployment-7484748b57 3 3 3 46s
NAME READY STATUS RESTARTS AGE
pod/hello-pod 1/1 Running 3 3d22h
pod/my-nginx-deployment-7484748b57-7tprl 1/1 Running 0 46s
pod/my-nginx-deployment-7484748b57-9n2lh 1/1 Running 0 46s
pod/my-nginx-deployment-7484748b57-wv6rz 1/1 Running 0 46s
pod/nginx-test 1/1 Running 4 4d5h
#2 디플로이먼트 삭제 → 레플리카셋, 포드도 함께 삭제되는 것을 확인
[vagrant@master ~]$ kubectl delete deployment my-nginx-deployment
deployment.extensions "my-nginx-deployment" deleted
[vagrant@master ~]$ kubectl get deployment
No resources found.
[vagrant@master ~]$ kubectl get replicaset
No resources found.
[vagrant@master ~]$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d22h
nginx-test 1/1 Running 4 4d5h
pod-1 2/2 Running 6 3d23h
디플로이먼트를 사용하는 이유
어플리케이션의 업데이트와 배포를 편하게 만들기 위해서 사용
#1 --record 옵션을 추가해 디플로이먼트를 생성
[vagrant@master ~]$ kubectl apply -f deployment-nginx.yaml --record
deployment.apps/my-nginx-deployment created
[vagrant@master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d22h
my-nginx-deployment-9b5988dd-24cp8 1/1 Running 0 12s
my-nginx-deployment-9b5988dd-8g557 1/1 Running 0 12s
my-nginx-deployment-9b5988dd-jh4d9 1/1 Running 0 12s
nginx-test 1/1 Running 4 4d5h
pod-1 2/2 Running 6 3d23h
#2 kubectl set image 명령으로 포드의 이미지를 변경
[vagrant@master ~]$ kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record
deployment.extensions/my-nginx-deployment image updated
[vagrant@master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d22h
my-nginx-deployment-9b5988dd-24cp8 0/1 Terminating 0 3m32s ⇐ 1.10 버전은 종료
my-nginx-deployment-9b5988dd-8g557 1/1 Running 0 3m32s
my-nginx-deployment-9b5988dd-jh4d9 1/1 Running 0 3m32s
my-nginx-deployment-d4659856c-qxflc 1/1 Running 0 16s
my-nginx-deployment-d4659856c-rjt94 0/1 ContainerCreating 0 5s ⇐ 1.11 버전은 생성
nginx-test 1/1 Running 4 4d5h
pod-1 2/2 Running 6 3d23h
[vagrant@master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d22h
my-nginx-deployment-d4659856c-fw2ct 1/1 Running 0 12s
my-nginx-deployment-d4659856c-qxflc 1/1 Running 0 35s
my-nginx-deployment-d4659856c-rjt94 1/1 Running 0 24s
nginx-test 1/1 Running 4 4d5h
pod-1 2/2 Running 6 3d23h
[vagrant@master ~]$ kubectl get replicaset
NAME DESIRED CURRENT READY AGE
my-nginx-deployment-9b5988dd 0 0 0 9m46s ⇐ 처음에 생성했던 레플리카셋
my-nginx-deployment-d4659856c 3 3 3 6m29s ⇐ 새롭게 생성된 레플리카셋
#3 리버전 정보 확인
[vagrant@master ~]$ kubectl rollout history deployment my-nginx-deployment
deployment.extensions/my-nginx-deployment
REVISION CHANGE-CAUSE
1 kubectl apply --filename=deployment-nginx.yaml --record=true
2 kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record=true
#4 이전 버전의 레플리카셋으로 롤백
[vagrant@master ~]$ kubectl rollout undo deployment my-nginx-deployment --to-revision=1
deployment.extensions/my-nginx-deployment rolled back
[vagrant@master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d22h
my-nginx-deployment-9b5988dd-5kgfz 1/1 Running 0 7s
my-nginx-deployment-9b5988dd-bcz5x 1/1 Running 0 10s
my-nginx-deployment-9b5988dd-lrzbj 1/1 Running 0 13s
my-nginx-deployment-d4659856c-qxflc 0/1 Terminating 0 14m
my-nginx-deployment-d4659856c-rjt94 0/1 Terminating 0 14m
nginx-test 1/1 Running 4 4d5h
pod-1 2/2 Running 6 4d
[vagrant@master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
hello-pod 1/1 Running 2 3d22h
my-nginx-deployment-9b5988dd-5kgfz 1/1 Running 0 17s
my-nginx-deployment-9b5988dd-bcz5x 1/1 Running 0 20s
my-nginx-deployment-9b5988dd-lrzbj 1/1 Running 0 23s
nginx-test 1/1 Running 4 4d5h
pod-1 2/2 Running 6 4d
[vagrant@master ~]$ kubectl get replicasets
NAME DESIRED CURRENT READY AGE
my-nginx-deployment-9b5988dd 3 3 3 19m
my-nginx-deployment-d4659856c 0 0 0 16m
[vagrant@master ~]$ kubectl rollout history deployment my-nginx-deployment
deployment.extensions/my-nginx-deployment
REVISION CHANGE-CAUSE
2 kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record=true
3 kubectl apply --filename=deployment-nginx.yaml --record=true
#5 디플로이먼트 상세 정보를 출력
[vagrant@master ~]$ kubectl describe deployment my-nginx-deployment
Name: my-nginx-deployment
Namespace: default
CreationTimestamp: Tue, 23 Feb 2021 07:06:13 +0000
Labels: app=my-nginx
Annotations: deployment.kubernetes.io/revision: 3
kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{"kubernetes.io/change-cause":"kubectl apply --filename=deployment-n...
kubernetes.io/change-cause: kubectl apply --filename=deployment-nginx.yaml --record=true
Selector: app=my-nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=my-nginx
Containers:
nginx:
Image: nginx:1.10
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: my-nginx-deployment-9b5988dd (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 22m deployment-controller Scaled up replica set my-nginx-deployment-d4659856c to 1
Normal ScalingReplicaSet 21m deployment-controller Scaled down replica set my-nginx-deployment-9b5988dd to 2
Normal ScalingReplicaSet 21m deployment-controller Scaled up replica set my-nginx-deployment-d4659856c to 2
Normal ScalingReplicaSet 21m deployment-controller Scaled down replica set my-nginx-deployment-9b5988dd to 1
Normal ScalingReplicaSet 21m deployment-controller Scaled up replica set my-nginx-deployment-d4659856c to 3
Normal ScalingReplicaSet 21m deployment-controller Scaled down replica set my-nginx-deployment-9b5988dd to 0
Normal ScalingReplicaSet 7m25s deployment-controller Scaled up replica set my-nginx-deployment-9b5988dd to 1
Normal ScalingReplicaSet 7m22s deployment-controller Scaled down replica set my-nginx-deployment-d4659856c to 2
Normal ScalingReplicaSet 7m22s deployment-controller Scaled up replica set my-nginx-deployment-9b5988dd to 2
Normal ScalingReplicaSet 7m19s (x2 over 25m) deployment-controller Scaled up replica set my-nginx-deployment-9b5988dd to 3
Normal ScalingReplicaSet 7m19s deployment-controller Scaled down replica set my-nginx-deployment-d4659856c to 1
Normal ScalingReplicaSet 7m17s deployment-controller Scaled down replica set my-nginx-deployment-d4659856c to 0
#6 모든 리소소를 삭제
[vagrant@master ~]$ kubectl delete deployment,replicaset,pod --all
서비스(service)
포드를 연결하고 외부에 노출
YAML 파일에 containerPort 항목을 정의했다고 해서 해당 포트가 바로 외부에 노출되는 것은 아님
해당 포트로 사용자가 접근하거나, 다른 디플로이먼트의 포드들이 내부적으로 접근하려면 서비스(service) 객체가 필요
서비스의 기능
-
여러 개의 포드에 쉽게 접근할 수 있도록 고유한 도메인 이름을 부여
-
여러 개의 포드에 접근할 때, 요청을 분산하는 로드 밸런서 기능을 수행
-
클라우드 플랫폼의 로드 벨런서, 클러스터 노드의 포트 등을 통해 포드를 외부에 노출
서비스의 종류(type)
ClusterIP 타입
-
쿠버네티스 내부에서만 포드들에 접근할 때 사용
-
외부로 포드를 노출하지 않기 때문에 쿠버네티스 클러스터 내부에서만 사용되는 포드에 적합
NodePort 타입
-
포드에 접근할 수 있는 포트를 클러스터의 모든 노드에 동일하게 개방
-
외부에서 포드에 접근할 수 있는 서비스 타입
-
접근할 수 있는 포트는 랜덤으로 정해지지만, 특정 포트로 접근하도록 설정할 수 있음
LoadBalancer 타입
-
클라우드 플랫폼에서 제공하는 로드 벨러서를 동적으로 프로비저닝해 포드에 연결
-
NodePort 타입과 마찬가지로 외부에서 포드에 접근할 수 있는 서비스 타입
-
일반적으로 AWS, GCP 과 같은 클라우드 플랫폼 환경에서 사용
디플로이먼트를 생성
#1 디플로이먼트 정의, 생성, 확인
[root@master ~]# vi deployment-hostname.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostname-deployment
spec:
replicas: 3
selector:
matchLabels:
app: webserver
template:
metadata:
name: my-webserver
labels:
app: webserver
spec:
containers:
- name: my-webserver
image: alicek106/rr-test:echo-hostname # <= pod의 hostname을 반환하는 웹서버이미지
ports:
- containerPort: 80
[root@master ~]# kubectl apply -f deployment-hostname.yaml
deployment.apps/hostname-deployment created
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
hostname-deployment-7dfd748479-6vjnx 1/1 Running 0 51s 192.168.166.160 node1 <none> <none>
hostname-deployment-7dfd748479-gkf6p 1/1 Running 0 51s 192.168.166.162 node1 <none> <none>
hostname-deployment-7dfd748479-jrvbw 1/1 Running 0 51s 192.168.166.161 node1 <none> <none>
#2 클러스터 노드 중 하나에 접속해서 curl을 이용해 포드에 접근
[root@master ~]# kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never curl 192.168.166.160 | grep Hello
<p>Hello, hostname-deployment-7dfd748479-6vjnx</p> </blockquote>
ClusterIP 타입의 서비스 - 쿠버네티스 클러스터 내부에서만 포드에 접근
#1 hostname-svc-clusterip.yaml 파일을 생성
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-clusterip
spec:
ports:
- name: web-port
port: 8080 <= service IP에 접근할 때 사용할 포트
targetPort: 80 <= selector 항목에서 정의한 라벨의 포드의 내부에서 사용하고 있는 포트
selector: <= 접근 허용할 포드의 라벨을 정의
app: webserver
type: ClusterIP <= 서비스 타입
#2 서비스 생성 및 확인
[root@master ~]# kubectl apply -f hostname-svc-clusterip.yaml
service/hostname-svc-clusterip created
[root@master ~]# kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-service NodePort 10.103.0.239 <none> 8001:31757/TCP 3d23h
hostname-svc-clusterip ClusterIP 10.96.50.8 <none> 8080/TCP 10s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 7d4h<= kubernetes API에 접근하기 위한 서비스
nginx-test NodePort 10.111.201.195 <none> 80:32185/TCP 4d7h
#3 임시 포드를 생성해서 서비스로 요청
[root@master ~]# kubectl run -it --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
If you don't see a command prompt, try pressing enter.
root@debug:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default
link/ether 5e:35:6e:a6:f3:44 brd ff:ff:ff:ff:ff:ff
inet 192.168.166.164/32 scope global eth0
valid_lft forever preferred_lft forever
--로드밸런싱 -> 요청이 들어오면 여유있는 노드로 분배해줌
-> 서비스와 연결된 포드에 로드밸런싱을 수행
root@debug:/# curl 10.96.50.8:8080 --silent | grep Hello
<p>Hello, hostname-deployment-7dfd748479-jrvbw</p> </blockquote>
root@debug:/# curl 10.96.50.8:8080 --silent | grep Hello
<p>Hello, hostname-deployment-7dfd748479-gkf6p</p> </blockquote>
root@debug:/# curl 10.96.50.8:8080 --silent | grep Hello
<p>Hello, hostname-deployment-7dfd748479-6vjnx</p> </blockquote>
#4 서비스 이름으로 접근
root@debug:/# curl hostname-svc-clusterip:8080 --silent | grep Hello
<p>Hello, hostname-deployment-7dfd748479-6vjnx</p> </blockquote>
root@debug:/# curl 10.96.50.8:8080 --silent | grep Hello
<p>Hello, hostname-deployment-7dfd748479-gkf6p</p> </blockquote>
root@debug:/# curl 10.96.50.8:8080 --silent | grep Hello
<p>Hello, hostname-deployment-7dfd748479-6vjnx</p> </blockquote>
⇒ 쿠버네티스는 어플리케이션이 서비스나 포드를 쉽게 찾을 수 있도록 내부 DNS를 구동
#5 서비스 삭제
root@debug:/# exit
exit
pod "debug" deleted
[root@master ~]# kubectl delete service hostname-svc-clusterip
service "hostname-svc-clusterip" deleted
'CLOUD > Docker' 카테고리의 다른 글
2/25 - 도커/쿠버네티스 활용 컨테이너 개발 12차시 (0) | 2021.02.25 |
---|---|
2/24 - 도커/쿠버네티스 활용 컨테이너 개발 11차시 (0) | 2021.02.24 |
2/22 - 도커/쿠버네티스 활용 컨테이너 개발 9차시 (0) | 2021.02.22 |
2/19 - 도커/쿠버네티스 활용 컨테이너 개발 8차시 (0) | 2021.02.19 |
2/16 - 도커/쿠버네티스 활용 컨테이너 개발 7차시 (0) | 2021.02.16 |