EKS 클러스터에서 컨테이너를 동작시키기 위한 리소스 기본개념

2021-08-21

.

Data_Engineering_TIL(20210821)

[학습자료]

“클라우드 네이티브를 위한 쿠버네티스 실전 프로젝트” 책을 읽고 정리한 내용입니다.

** 동양북스, 아이자와 고지&사토 가즈히코 지음, 박상욱 옮김

참고자료 URL : https://github.com/dybooksIT/k8s-aws-book

“EKS 클러스터에 배치 어플리케이션 배포하기” 에 이어서 공부한 내용을 정리한 내용임

** URL : https://minman2115.github.io/DE_TIL259

[학습내용]

지난 실습에서 구현했던 쿠버네티스에서 클러스터 리소스 관점에서의 아키텍처

1

쿠버네티스에서 컨테이너를 동작시키기 위한 리소스

쿠버네티스는 여러가지 오브젝트로 표현됨

쿠버네티스의 장점은 프로그램을 동작시키는 구조를 추상화된 오브젝트로 표현하고 프로그램 추가&삭제 및 버전업그레이드와 같은 작업을 오브젝트에 대한 설정으로 표현함.

따라서 기존에 인프라 구축이나 애플리케이션 배포와 달리 ‘작업’이 아닌 ‘오브젝트 상태 선언’이라는 형태로 환경을 정의할 수 있다.

쿠버네티스에서 프로그램을 동작시키는 기본 단위 : Pod

쿠버네티스에서 프로그램을 동작시킬때 생성되는 오브젝트의 최소 단위는 컨테이너가 아닌 Pod다.

Pod는 서로 연관성이 있는 하나 이상의 컨테이너를 합쳐놓은 오브젝트이다.

  • 실습예시 - nginx 컨테이너 단독 구성

일전에 실습에서 쿠버네티스 클러스터를 구축한후 nginx를 배포하고 동작하는 것을 확인했었다.

이때 nginx 컨테이너 하나만 있는 파드를 정의하여 클러스터에 배포하였다. 이와 같이 컨테이너를 하나만 포함한 파드가 쿠버네티스에서 프로그램을 동작시키는 가장 단순한 형태다.

아래의 명령어는 kubectl이라는 쿠버네티스 관리도구를 이용해서 야믈파일 형태로 작성된 매니패스트를 클러스터에 적용(kubectl apply)하는 명령이다. 02_nginx_k8s.yaml라는 파일에 정의된 오브젝트가 쿠버네티스 위에 생성 된다(이미 생성된 경우 업데이트됨). 즉 매니페스트 파일에 pod가 정의된 것이다.

$ kubectl apply -f 02_nginx_k8s.yaml

쿠버네티스에서는 아래와 같이 오브젝트 정의를 나타내는 매니페스트 파일을 보통 YAML 형식으로 작성한다.

$ cat 02_nginx_k8s.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx-app
spec:
  containers:
  - name: nginx-container
    image: nginx
    ports:
    - containerPort: 80

1) apiVersion

v1은 매니페스트 파일에서 정의된 오브젝트가 준수해야하는 사양의 버전을 설정한다.

2) kind

pod는 이 매니페스트 파일이 파드라는 종류의 오브젝트를 의미한다.

3) metadata: 이후로는 파드 메타데이터를 정의한다.

4) name

nginx-pod는 파드 이름을 설정하는 것으로 nginx-pod라는 이름을 선언한다.

5) app

nginx-app는 labels 하위에 있는 내용으로 파드에 레이블을 설정한다. key value 형태로 app이라는 key에 대해 nginx-app이라는 값을 설정한다.

6) containers: 하위에는 컨테이너의 스팩을 정의한다.

7) name

nginx-container는 컨테이너의 이름이다.

8) image

nginx는 어떤 컨테이너 이미지를 사용할지를 설정한다 여기서는 nginx 컨테이너 이미지를 태그 없이 설정했다.

9) containerPort : 80

이 컨테이너를 공개할 포트를 설정한다. 여기서는 컨테이너 내부의 80 포트를 그대로 80으로 공개한다.

쿠버네티스의 레이블

위에 야믈파일에서 파드에 app: nginx-app (app이라는 키에 nginx-app 이라는 값을 설정한다는 의미) 라는 레이블을 설정했다.

이 레이블은 왜 설정하는 것일까?

쿠버네티스에서 디플로이먼트나 서비스 같은 다양한 리소스를 식별하기 위해 레이블을 사용한다.

즉, 리소스들이 대상으로 하는 파드를 특정짓기 위해 레이블을 이용한다.

컨테이너를 여러개 포함한 pod

pod 하나에 컨테이너 여러개를 올리는 상황은 언제일까.

일반적으로는 컨테이너 여러개가 모여 하나의 통합된 서비스를 제공하는 경우이다.

pod 하나에 포함되는 컨테이너는 다음과 같은 특징이 있다.

1) localhost로 서로 통신이 가능

2) 스토리지(볼륨) 공유가능

그리고 이 컨테이너들은 반드시 함께 동작하고 함께 정지된다.

이는 어떤 컨테이너가 다른 컨테이너와 네트워크나 스토리지를 공유하여 밀접하게 처리해야 하는 작업이 있고, 컨테이너끼리 1대1로 대응해야 한다면 컨테이너들이 파드 하나에 포함되어야 한다.

예를들면 아래와 같은 경우가 있다.

1) 메인처리를 실행하는 컨테이너가 출력한 로그를 다른 컨테이너가 읽어들여 로그수집 서버나 메트릭 수집서버에 전송

2) 메인처리를 실행하는 컨테이너가 외부 시스템에 접속할 경우, 또 다른 컨테이너가 프록시로 되어 목적지를 할당하거나 요청이 제대로 처리되지 않았을때 재시도 수행

이처럼 메인처리를 실행하는 컨테이너 옆에 보조 역할을 하는 컨테이너를 배치하는 구성을 사이드카 패턴이라고 한다.

2번처럼 파드 외부와의 통신구조 사이에 프록시가 배치되어 통신에 대한 보조적인 역할을 하는 구성을 앰버서더 패턴이라고 한다.

2

디플로이먼트

파드의 다중화, 버전 업데이터, 롤백 등을 구현하는 오브젝트라고 할 수 있다.

파드를 이용하면 쿠버네티스 클러스터에 프로그램을 동작시킬 수 있다. 하지만 웹 어플리케이션의 경우 일반적으로는 파드를 직접배포하지는 않는다. 지난번에 실습할때도 예제 API 어플리케이션을 배포할때도 직접 파드를 배포하지 않고 Deployment라는 오브젝트를 만들어 간접적으로 파드를 배포했다.

클러스터에서 어플리케이션을 동작시킬 경우에는 요청량과 처리 부하에 따라 파드수를 늘리고 줄이면서 대응해가는 것이 일반적이다. 또 파드가 비정상 종료된 경우 별도의 파드를 생성해 유효한 파드수를 유지한다. Deployment를 이용하여 어플리케이션을 배포하면 이런 처리를 쿠버네티스가 자동으로 해준다. 또한 생성한 디플로이먼트에 구성할 파드 버전(컨테이너 이미지 태그)를 변경하도록 명령하면 자동으로 새로운 버전의 컨테이너 이미지를 확인하고 동작중인 파드를 다음 버전으로 변경한다.

이처럼 디플로이먼트를 사용해 직접 파드를 배포하면 어떤 기능으로 구현할 수 없는 다양한 처리를 쿠버네티스 구조로 구현할 수 있다. 이는 쿠버네티스와 같은 컨테이너 오케스트레이션 도구의 큰 장점이다. 그래서 쿠버네티스 클러스터에 어플리케이션을 배포하는 경우 일반적으로 파드를 직접 설정하지 않고 디플로이 형태를 사용한다.

일전에 실습할때 아래와 같은 명령어로 API 어플리케이션을 배포했다.

[ec2-user@ip-10-0-1-104 eks-env]$ ECR_HOST=xxxxxxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com envsubst < 22_deployment_backend-app_k8s.yaml.template | kubectl apply -f -
deployment.apps/backend-app created

[ec2-user@ip-10-0-1-104 eks-env]$ cat 22_deployment_backend-app_k8s.yaml.template
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-app
  labels:
    app: backend-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend-app
  template:
    metadata:
      labels:
        app: backend-app
    spec:
      containers:
      - name: backend-app
        image: ${ECR_HOST}/k8sbook/backend-app:1.0.0
        imagePullPolicy: Always
        ports:
        - containerPort: 8080
        env:
        - name: DB_URL
          valueFrom:
            secretKeyRef:
              key: db-url
              name: db-config
        - name: DB_USERNAME
          valueFrom:
            secretKeyRef:
              key: db-username
              name: db-config
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              key: db-password
              name: db-config
        readinessProbe:
          httpGet:
            port: 8080
            path: /health
          initialDelaySeconds: 15
          periodSeconds: 30
        livenessProbe:
          httpGet:
            port: 8080
            path: /health
          initialDelaySeconds: 30
          periodSeconds: 30
        resources:
          requests:
            cpu: 100m
            memory: 512Mi
          limits:
            cpu: 250m
            memory: 768Mi
        lifecycle:
          preStop:
            exec:
              command: ["/bin/sh", "-c", "sleep 2"]

1) replicas: 2

디플로이먼트를 통해 클러스터 내부에 배포된 파드 수를 설정하는 것이다. 따라서 이 디플로이먼트를 쿠버네티스 클러스터에 생성하면 클러스터 전체에 파드 2개가 생성된다.

2) template:

디플로이먼트를 통해 배포할 파드의 정의를 설정하는 부분으로 pod template라고도 부른다.

3) resources:

파드가 사용할 메모리나 CPU 등의 리소스양에 대한 정의

디플로이먼트를 배포하고 아래 명령어를 이용해서 디플로이먼트 목록을 확인할 수 있다.

일전에 실습할때는 kubectl get all 명령어로 쿠버네티스의 리소스를 체크했었는데 아래와 같이 kubectl get deployment를 날리게 되면 쿠버네티스에서 디플로이라는 특정한 리소스만 체크도 가능하다.

[ec2-user@ip-10-0-1-104 eks-env]$ kubectl get deployment
NAME                      READY                 UP-TO-DATE        AVAILABLE               AGE
backend-app               2/2                   2                 2                       127m

NAME : 디플로이먼트 이름

READY : 디플로이먼트에서 설정한 파드 수와 실제 동작하고 있는 파드수가 분수형태로 표시

UP-TO-DATE : 디플로이먼트에서 정의된 상태(파드에서 사용할 컨테이너 버전, 리소스 제약 상태 등)를 만족하는 파드 수

AVAILABLE : 실제 사용가능한 파드 수

AGE : 디플로이먼트가 생성된 이후의 경과시간

디플로이먼트 하위에서 생성되는 리플리카셋

어플리케이션의 배포는 디플로이먼트를 이용하는데 디플로이먼트가 직접 파드를 배포하지 않고 그 중간에 Replicaset이라는 다른 오브젝트를 생성해 배포한다. 디플로이먼트는 파드 수 증감과 파드에 장애가 발생했을때 자동 재시작을 해주는데 실질적으로는 리플리카 셋이라는 것이 이를 담당한다.

아래와 같이 명령어를 실행하면 리플리카셋 상태를 확인할 수 있다.

[ec2-user@ip-10-0-1-104 eks-env]$ kubectl get replicaset
NAME                          DESIRED                  CURRENT             READY             AGE
backend-app-abc2129aakdnb     2                        2                   2                 127m

NAME : backend-app-abc2129aakdnb 라고 명시되어 있다. 디플로이먼트의 이름인 backend-app 뒤에 랜덤으로 난수가 붙게 된다. 리플리카셋의 이름에 랜덤 문자열이 부여되는 것은 디플로이먼트 하나에 리플리카셋 여러개가 생성될 수 있기 때문이다.

DESIRED : 레플리카셋에서 설정한 파드수

CURRENT : 현재 동작하고 있는 파드수

READY : 완료상태인 파드수

AGE : 레플리카셋이 생성된 이후 경과시간

컨테이너 이미지 버전과 리소스 제약 등 디플로이먼트 정의를 변경한 경우에는 내부적으로 새로운 디플로이먼트 정의에 맞는 리플리카셋이 생성되고, 새로운 리플리카셋의 파드가 생성되면 이전 리플리카셋의 파드를 정지시키게 된다.

리플리카셋으로 생성된 파드

아래와 같이 명령어를 실행하면 파드 상태를 확인할 수 있다.

[ec2-user@ip-10-0-1-104 eks-env]$ kubectl get pod
NAME                          READY                  STATUS             RESTARTS             AGE
backend-app-asdcaqwceqweq     1/1                    Running            0                    155m
backend-app-cqwecqwecqeqw     1/1                    Running            0                    155m
batch-app-1602916928-qwenj    0/1                    Completed          0                    11m
batch-app-1602912828-qcas     0/1                    Completed          0                    6m52s
batch-app-1602913192-qwcn     0/1                    Completed          0                    113s

디플로이먼트 –> 리플리카셋 –> 파드 순서는 디플로이먼트 선언(매니페스트 야믈파일을 생성하고 kubectl apply 명령을 실행)하면 그 뒤에 리플리카셋이 생성되고 또 그 뒤에 리플리카셋이 파드를 생성하는 흐름으로 이어진다.

디플로이먼트에서 리플리카셋, 파드가 생성되는 흐름은 아래와 같다.

3

Kubectl describe 명령어로 상세정보 조회하기

$ kubectl describe <리소스 종류> <오브젝트 이름> 명령어를 사용하면 리소스종류에 따른 상세정보 조회가 가능하다.

# 예시
$ kubectl describe pod batch-app-1629116700-mw5cd
Name:         batch-app-1629116700-mw5cd
Namespace:    eks-work

...

Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  81s   default-scheduler  Successfully assigned eks-work/batch-app-xxxxxx-mw5cd to ip-192-168-1-116.ap-northeast-2.compute.internal
  Normal  Pulling    80s   kubelet            Pulling image "xxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com/k8sbook/batch-app:1.0.0"
  Normal  Pulled     72s   kubelet            Successfully pulled image "xxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com/k8sbook/batch-app:1.0.0" in 7.440966617s
  Normal  Created    72s   kubelet            Created container batch-app
  Normal  Started    72s   kubelet            Started container batch-app

일전에 실습했던 크론잡 스케쥴은 어떻게 동작하는가

일전에 EKS 클러스터에서 크론잡을 생성할때 명령은 아래와 같다.

ECR 주소를 envsubst 명령어로 치환한 매니페스트를 kubectl apply 명령으로 적용한다.

[ec2-user@ip-10-10-1-181 eks-env]$ ECR_HOST=xxxxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com | envsubst < 43_cronjob_k8s.yaml.template | kubectl apply -f -
cronjob.batch/batch-app created

[ec2-user@ip-10-10-1-181 eks-env]$ cat 43_cronjob_k8s.yaml.template
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: batch-app
spec:
  schedule: "*/5 * * * *" # min hour day-of-month month day-of-week
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: batch-app
            image: ${ECR_HOST}/k8sbook/batch-app:1.0.0
            imagePullPolicy: Always
            env:
            - name: DB_URL
              valueFrom:
                secretKeyRef:
                  key: db-url
                  name: db-config
            - name: DB_USERNAME
              valueFrom:
                secretKeyRef:
                  key: db-username
                  name: db-config
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  key: db-password
                  name: db-config
            - name: CLOUD_AWS_CREDENTIALS_ACCESSKEY
              valueFrom:
                secretKeyRef:
                  key: aws-accesskey
                  name: batch-secret-config
            - name: CLOUD_AWS_CREDENTIALS_SECRETKEY
              valueFrom:
                secretKeyRef:
                  key: aws-secretkey
                  name: batch-secret-config
            - name: CLOUD_AWS_REGION_STATIC
              valueFrom:
                configMapKeyRef:
                  key: aws-region
                  name: batch-app-config
            - name: SAMPLE_APP_BATCH_BUCKET_NAME
              valueFrom:
                configMapKeyRef:
                  key: bucket-name
                  name: batch-app-config
            - name: SAMPLE_APP_BATCH_FOLDER_NAME
              valueFrom:
                configMapKeyRef:
                  key: folder-name
                  name: batch-app-config
            - name: SAMPLE_APP_BATCH_RUN
              valueFrom:
                configMapKeyRef:
                  key: batch-run
                  name: batch-app-config
          restartPolicy: OnFailure

1) kind: CronJob

리소스 타입이 크론잡이라는 것을 알 수 있다. 디플로이먼트 처럼 리소스 타입이 정의된 것이다.

2) containers:

실행할 컨테이너에 대한 정의로 컨테이너 이름, 이미지, 실행할때 설정할 환경변수와 값의 저장소 등을 설정한다.

그러나 env:의 환경변수는 디플로이먼트 때와 달리 여러개의 시크릿과 컨피그맵에서 값을 가져온다.

API 어플리케이션의 경우 디플로이먼트를 쿠버네티스에 등록하면 그 다음에 리플리카셋이 생성되고 리플리카셋에서 파드가 생성되어 파드안에서 컨테이너가 동작하는 구조로 되어 있었다. 그러면 크론잡은 어떻게 동작하는가

크론잡을 쿠버네티스 클러스터에 등록한 경우 설정한 실행 스케쥴이 되면 내부적으로 잡이라는 리소스가 생성된다. 그리고 잡 안에서 파드가 생성된다. 파드에서 컨테이너가 동작하는 것은 디플로이먼트의 경우와 같다.

4

잡 리소스란

잡은 일정한 처리를 수행하고 완료하는 테스크를 실행하기 위한 리소스다.

앞에서 설명한 배치 어플리케이션은 S3에 저장된 파일을 읽어 들인 후 그 내용을 데이터베이스에 등록하는 것이다. 이 프로그램은 S3에 저장된 모든 파일의 처리가 끝나면 처리 완료하고 종료해도 된다. API 어플리케이션과 비교해보면 API 어플리케이션은 명시적으로 종료를 시키는 경우를 제외하고는 계속 동작하도록 설정이 되어 있으며 내부에서 동작하는 프로그램도 비정상 종료의 경우를 제외하면 종료되는 일이 없이 계속 동작한다.

디플로이먼트 –> 리플리카셋 –> 파드라는 흐름은 계속적으로 동작한다는 것을 기대할때 사용한다. 그와 반대로 잡 –> 파드 라는 흐름은 일정한 처리가 끝나면 프로그램을 종료하고 테스크로도 Completed 상태가 되기를 원하는 경우에 사용한다.

  • 그러면 잡 리소스로 실행되는게 어떻게 동작하는지 알아보자.

1) 잡 실행 수

잡 리소스에서 설정내용에 따라 여러개의 처리를 병렬로 실행할 수 있다. 잡의 실행 수를 규정하는 파라미터에는 잡 정의와 관련된 .spec.completions.spec.parallelism이 있다.

.spec.completions : 그 잡이 완료될때까지 실행 종료해야 하는 파드수를 의미함. 디폴트값은 1이기 때문에 명시적으로 설정하지 않으면 파드 하나가 정상 종료되면 그 잡은 완료됨을 의미한다.

.spec.parallelism : 그 잡을 실행할때 병렬로 수행하는 파드수를 의미한다. 이 또한 기본값은 1이며 명시적으로 설정하지 않으면 병렬실행을 수행하지 않는다는 것을 의미한다.

2) 잡 실행 패턴

패턴 1. 단일파드를 실행하는 패턴

.spec.completions.spec.parallelism를 모두 디폴트값으로 사용하는 경우, 잡 리소스 1에 대해 파드 하나가 생성되며 그 파드가 정상 종료되면 잡이 완료된다.

우리가 실습했던 패턴은 패턴 1이라고 할 수 있다.

패턴 2. 완료해야할 파드수를 설정하는 실행 패턴

.spec.completions를 설정한 경우 .spec.completions로 설정한 수의 파드가 정상 종료되면 그 잡은 완료된다. 이때 .spec.parallelism은 필수가 아니지만 설정한 수만큼 파드가 병렬로 실행된다.(설정하지 않을 경우 동시에 파드 여러개가 실행되지 않고 하나씩 실행된다.)

패턴 3. 작업 큐형 실행 패턴

동시에 파드 여러개를 실행하고 작업 큐를 순차적으로 처리하는 패턴이다. 작업 큐를 사용하는 경우는 큐, 데이터베이스, 파일 등 무엇이든 상관없이 외부 처리 대상을 유지하고 그것을 순차적으로 처리한다. 처리 대상이 없어지면 완료 처리가 된다. .spec.completions는 설정하지 않고 .spec.parallelism를 설정하여 실행한다.

3) 잡 재시도 횟수

.spec.backoffLimit이라는 것도 알아야 한다. 잡에서 생성된 파드가 비정상 종료한 경우 몇번을 재실행할지 설정하는 것이다. 디폴트값은 6이다.

exponential back-off(지수 백오프 지연)이라는 것도 있는데 이거는 처리를 여러번 재실행할때 횟수가 증가함에 따라 재실행을 다시 할때까지 대기시간을 지수 함수적으로 증가시킨다는 것이다. 지수 백오프 상한이 6분으로 되어 있고, 이는 최대 6분간격으로 재실행한다는 것이다.

4) 크론잡 설정값

.spec.schedule : 원하는 크론 스케쥴링 값을 넣어주면 된다.

** EKS의 경우 타임존으로 UTC를 사용하므로 주의해야 한다.

5) 동시 실행 제어

.spec.concurrencyPolicy : 이전에 스케쥴링된 잡 실행이 미완료인 상태에서 다음 스케쥴에 도달했을때 어떻게 동작할지를 설정함.

설정가능한 값은 Allow, Forbid, Replace이며 기본값은 Allow이다.

Allow - 디폴트값으로 동시실행을 허가한다.

Forbid - 실행중인 잡을 남기고 신규 잡 생성은 건너뛴다.

Replace - 실행중인 잡을 종료하고 신규 잡을 생성한다.

EKS 클러스터에서 컨테이너를 동작시키기 위한 기타 리소스

1) 노드 각각에 반드시 파드 하나를 동작시키는 ‘데몬셋’

쿠버네티스에 데몬셋을 등록하면 그 안에 정의된 파드가 클러스터에 속한 워커 노드별로 하나씩 동작하게 된다.

로그수집용 에이전트를 노드 각각에 배포해야 하는 상황이 있는데 이럴때 사용하면 된다. 데몬셋은 일반적인 어플리케이션 개발에 사용하는 것이지 컨테이너를 동작시키기 위한 리소스는 아니다. 클러스터 내부에서 공통으로 사용하는 기능을 구현하기 위한 리소스라고 생각하면 된다.

2) 영구 데이터를 다루기 위한 ‘스테이트풀셋’

리플리카셋을 사용하면 파드가 비정상 종료된 경우에도 자동으로 파드를 재시작하거나 다른 노드에 재생성하여 특정 파드 수를 유지할 수 있는 구조로 되어 있다. 여기서 유의해야할 점은 레플리카셋에서 파드가 재생성된 경우 그 파드는 매번 초기화된 상태로 동작한다는 것이다.

컨테이너는 동작할때 매번 컨테이너 이미지를 이용하여 생성되기 때문에 기본적으로 초기화 된 상태로 만들어진다고 생각해야 한다. 그러나 디비와 같이 저장해서 유지해야 할 데이터가 필요한 경우 파드를 재시작하면 데이터가 초기화되어 문제가 발생할 수 있다. 그래서 쿠버네티스는 파드 외부에 볼륨 형태로 데이터를 저장한 후 파드가 재시작하더라도 그때까지 사용했던 볼륨을 계속 사용할 수 있는 구조로 되어 있다. 스테이트풀셋은 이런 동작을 지원하는 리소스다.

리플리카셋과 디플로이먼트에서 동작시킨 파드처럼 고유의 상태를 갖지 않고, 모든 파드가 같은 상태를 갖는 것은 Stateless라고 하며, 데이터베이스처럼 파드 별로 고유의 상태를 갖는 것을 Stateful이라고 한다. 스테이트풀셋이란 스테이트풀한 어플리케이션을 동작시키기 위한 리소스다.

일반적으로는 쿠버네티스에서 스테이트풀 어플리케이션을 동작시키는 것은 운영적인 측면에서 추천하지는 않는 방법이다. 현재 스테이트풀 어플리케이션이 필요한 경우 쿠버네티스 클러스터 외부에서 구성하는 것이 무난하다.

네임스페이스

네임스페이스는 컨테이너를 동작시키기 위한 리소스는 아니지만 컨테이너가 동작하는 클러스터를 논리적으로 사용하기 위한 리소스다.

쿠버네티스에는 네임스페이스 3개가 존재한다.

1) default : 명시적으로 네임스페이스를 설정하지 않았을 경우에 사용되는 네임스페이스

2) kube-system : 쿠버네티스에 의해 생성하는 오브젝트가 사용하는 네임스페이스. kube-system는 쿠버네티스가 사용하는 것이며 일반적으로는 어플리케이션 리소스를 여기에 생성해서 사용하지 않는다.

3) kube-public : 미인증 사용자를 포함하는 모든 사용자가 참조할 수 있는 네임스페이스. 어떤 이유에서 리소스를 외부로 공개할때 사용하는 네임스페이스.

우리가 실습했을때 예제 어플리케이션에서 사용한 네임스페이스

실습했을때 eks-work라는 네임스페이스를 생성했고, 예제 어플리케이션용 디플로이먼트와 크론잡을 비롯한 리소스를 이 네임스페이스에 생성했다.

네임스페이스를 이용한 클러스터 리소스 제한

네임스페이스는 단순히 리소스를 배치하는 논리적인 구분 외에도 리소스 쿼터나 네트워크 정책과 같은 리소스 또는 RBAC(Role-Based Access Control)의 구조가 있다. 이를 함께 사용하면 리소스 사용량과 네트워크 통신 제한 또는 클러스터에 대한 권한 제어를 실행할 수 있다. 본격적으로 쿠버네티스 클러스터를 여러 사용자 또는 그룹에서 공용으로 사용할 경우 네임스페이스를 이용해 여러가지 제약을 설정해야 하며 운영상에 중요한 역할을 담당하고 있다.

네임스페이스를 정의할 매니페스트 파일 예시

실습할때 예제 어플리케이션을 구축하면서 사용한 네임스페이스 생성용 매니패스트 파일은 아래와 같다.

Kind에 네임스페이스를 설정하고 이 매니패스트 파일이 네임스페이스 정의임을 나타낸다.

$ cat eks-env/20_create_namespace_k8s.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: eks-work