728x90

 

포드(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

 

 

 

 

 

 

 

 

 

 

728x90

+ Recent posts