「시작하세요! 도커/쿠버네티스」 학습 정리 - 09장 ~ 10장.

toto9602·2024년 2월 4일
0

Docker 공부하기

목록 보기
9/10

용찬호. 「 시작하세요! 도커/쿠버네티스」. 위키북스 를 읽으며, 학습한 내용을 정리하는 글입니다.
→ 본문의 내용은 모두 책의 내용에 대한 직/간접적 인용임을 밝힙니다.

09. 퍼시스턴트 볼륨(PV)과 퍼시스턴트 볼륨 클레임(PVC)

  • 데이터베이스처럼, 포드 내부에서 특정 데이터를 보유해야 하는, stateful 애플리케이션의 경우 데이터 관리가 필요!
    • MySQL 디플로이먼트를 통해 포드를 생성해도, 데이터가 영속적이지 않다.
    • 디플로이먼트를 지우면 포드도 삭제되고, 그와 동시에 데이터도 삭제되기 때문.

→ 포드의 데이터를 영속적으로 저장하기 위한 방법이 필요!
→ 어느 노드에서도 접근해 사용할 수 있는 퍼시스턴트 볼륨(Persistent Volume)을 사용하는 것이 일반적!

[ 퍼시스턴트 볼륨 ]

  • 워커 노드들이 네트워크상에서 스토리지를 마운트해 영속적으로 데이터를 저장할 수 있는 볼륨
  • 포드에 장애가 생겨, 다른 노드로 옮겨가더라도 해당 노드에서 퍼시스턴트 볼륨에 네트워크로 연결해 데이터를 계속 사용 가능!
    • 네트워크로 연결해 사용 가능한 퍼시스턴트 볼륨의 예시로, NFS, AWS의 EBS, Ceph, GlusterFS 등이 있다.

9.1 로컬 볼륨 : hostPath, emptyDir

  • hostPath : 호스트와 볼륨을 공유하기 위해서 사용
  • emptyDir : 포드의 컨테이너 간에 볼륨을 공유하기 위해서 사용

9.1.1 워커 노드의 로컬 디렉토리를 볼륨으로 사용 : hostPath

  • 포드 데이터를 보존하는 가장 간단한 방법은, 호스트의 디렉터리를 포드와 공유해 데이터를 저장하는 것.
apiVersion: v1
kind: Pod
metadata:
	name: hostpath-pod
spec:
	containers:
    	- name: my-container
          image: busybox
          args: ["tail", "-f", "/dev/null" ]
          volumeMounts:
          - name: my-hostpath-volume
            mountPath: /etc/data
	volumes:
      - name: my-hostpath-volume
        hostPath:
           path: /tmp

→ 호스트의 /tmp를 포드의 /etc/data에 마운트

** 바람직한 방식은 아님!

  • 디플로이먼트의 포드에 장애가 생겨, 다른 노드로 포드가 옮겨갔을 경우, 이전 노드에 저장된 데이터를 사용할 수 없다.

9.1.2 포드 내의 컨테이너 간 임시 데이터 공유 : emptyDir

  • 포드의 데이터를 영속적으로 보존하기 위해 외부 볼륨을 스는 것이 아닌, 포드가 실행되는 도중에만 필요한 휘발생 데이터를 각 컨테이너가 함께 사용할 수 있도록 임시 저장 공간을 생성
  • emptyDir 이름처럼, 비어있는 상태로 생성되고, 포드가 삭제되면 emptyDir에 저장돼 있던 데이터도 함께 삭제
apiVersion: v1
kind: Pod
metadata:
	name: emptydir-pod
spec:
	containers:
    - name: content-creator
      image: alicek106/alpine-wget:latest
      args: ["tail", "-f", "/dev/null"]
      volumeMounts:
      - name: my-emptydir-volume
        mountPath: /data        # 1. 이 컨테이너가 /data에 파일을 생성하면
        
     - name: apache-webserver
       image: httpd:2
       volumeMounts: 
       - name: my-emptydir-volume
         mountPath: /usr/local/apache2/htdocs. # 2. 아파치 웹서버에서 접근 가능
	volumes:
      - name: my-emptydir-volume
        emptyDir: {}.                     # 포드 내에서 파일을 공유하는 emptyDir 

9.2 네트워크 볼륨

  • 네트워크 볼륨은, 네트워크로 접근할 수만 있으면 쿠버네티스 클러스터 내부, 외부 어느 곳에 존재해도 상관없음!
  • 단, AWS EBS와 같은 클라우드에 종속적인 볼륨을 사용하려면 AWS에서 쿠버네티스 클러스터를 생성할 때 특정 클라우드를 위한 옵션이 별도 설정되어있어야 함.
    • kops를 통해 AWs에서 설치했다면 자동 설정!

9.3 PV, PVC를 이용한 볼륨 관리

9.3.1 퍼시스턴트 볼륨과 퍼시스턴트 볼륨 클레임을 사용하는 이유

  • 쿠버네티스에서 지원하는 대부분의 볼륨 타입은, 포드나 디플로이먼트의 YAML 파일에서 직접 정의해서 사용 가능
    • 그러나, 볼륨과 애플리케이션ㄴ의 정의가 서로 밀접하게 연관되어 분리할 수 없는 상황이 발생한다.
    • ex. MySQL 디플로이먼트의 YAML 파일에 네트워크 볼륨으로써 NFS를 명시했다면, 해당 YAML 파일로 MySQL을 생성하려면 반드시 NFS를 써야 한다.

→ 이러한 문제를 해결하기 위해, 퍼시스턴트 볼륨(PV)와, 퍼시스턴트 볼륨 클레임(PVC)를 사용!

  • 포드가 볼륨의 세부 사항을 몰라도 볼륨을 사용할 수 있도록 추상화해 준다.

  • 즉, 포드를 생성하는 YAML은 네트워크 볼륨이 NFS인지, AWS의 EBS인지 상관없이 볼륨 사용 가능!

  • 사용자는 디플로이먼트의 YAML 파일에 볼륨의 상세한 스펙을 정의하지 않는다.

    • '이 디플로이먼트는 볼륨을 마운트할 수 있어야 한다'는 의미의 퍼시스턴트 볼륨 클레임을 명시할 뿐이며, 실제로 마운트되는 볼륨이 무엇인지 알 필요가 없다.

9.3.2 퍼시스턴트 볼륨과 퍼시스턴트 볼륨 클레임 사용하기

[ AWS에서 EBS를 퍼시스턴트 볼륨으로 사용하기 ]
1. EBS 생성

export VOLUME_ID=$(aws ec2 create-volume --size 5 \
--region ap-northeast-2 \
--availability-zone ap-northeast-2a \ 
--volume-type gp2 \
--tag-specifications \
'ResourceType=volume, Tags=[{Key=KubernetesCluster, Value=mycluster.k8s.local}]' \
| jp '.VolumeId' -r)
  1. 생성한 EBS 볼륨을 통해 쿠버네티스의 퍼시스턴트 볼륨 생성
apiVersion: v1
kind: PersistentVolume
metadata:
	name: ebs-pv
spec:
	capacity:
    	storage: 5Gi   # 이 볼륨의 크기는 5G
    accessModes:
    	- ReadWriteOnce #하나의 포드(또는 인스턴스)에 의해서만 마운트될 수 있다. 
	awsElasticBlockStore:
    	fsType: ext4
        volumeID: <VOLUME_ID>

[ 퍼시스턴트 볼륨 클레임과 포드를 함께 생성 ]

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
	name: my-ebs-pvc #1. my-ebs-pvc라는 이름의 pvc를 생성
spec:	
	storageClassName: ""
    accessModes:
    	- ReadWriteOnce #2.1 속성이 ReadWriteOnce인 퍼시스턴트 볼륨과 연결
    resources:
    	requests:
        	storage: 5Gi. #2. 볼륨 크기가 최소 5Gi인 퍼시스턴트 볼륨과 연결
---
apiVersion: v1
kind: Pod
metadata:
	name: ebs-mount-container
spec:
	containers:
    	- name: ebs-mount-container
          image: busybox
          args: ["tail", "-f", "/dev/null" ] 
          volumeMounts:
          - name: ebs-volume
            mountPath: /mnt
	volumes:
    - name: ebs-volume
      persistentVolumeClaim:
      	claimName: my-ebs-pvc. # 3. my-ebs-pvc라는 이름의 pvc를 사용 

9.3.3 퍼시스턴트 볼륨을 선택하기 위한 조건 명시

  • 퍼시스턴트 볼륨 클레임을 사용하면, 실제로 볼륨이 어떠한 스펙을 가졌는지는 알 필요가 없지만, 사용하려는 볼륨이 애플리케이션에 필요한 최소 조건을 맞출 필요는 있다.
    • AccessMode, 볼륨의 크기 등이 이러한 조건에 해당!
      - 퍼시스턴트 볼륨과 퍼시스턴트 볼륨 클레임의 accessMode 및 볼륨 크기 속성이 부합해야, 쿠버네티스는 두 리소스를 매칭해 바인드한다.
  • accessMode, 볼륨 크기, 스토리지 클래스, 라벨 셀렉터 등이 주로 볼륨 조건으로 사용된다.

9.3.4 퍼시스턴트 볼륨와 라이프사이클과 Reclaim Policy

[ 퍼시스턴트 볼륨의 STATUS ]

  • Available : 퍼시스턴트 볼륨이 사용 가능한 상태
  • Bound : 퍼시스턴트 볼륨 클레임을 새로 생성해, 바인드.
    • 이미 바인드되어, 다른 퍼시스턴트 볼륨 클레임과 연결이 불가
  • Released: 퍼시스턴트 볼륨과 연결된 퍼시스턴트 볼륨 클레임 삭제 상황
    • 해당 퍼시스턴트 볼륨의 사용이 끝났음을 의미
    • Released 상태의 퍼시스턴트 볼륨을 다시 사용할 수 없음.

[ Reclaim Policy ]

  • 퍼시스턴트 볼륨 클레임 삭제 시, 퍼시스턴트 볼륨의 데이터를 어떻게 처리할지 정의 가능
    • 퍼시스턴트 볼륨의 사용이 끝났을 때 해당 볼륨을 어떻게 초기화할지 설정하는 것을 Reclaim Policy 라고 한다.

< Reclaim Policy의 종류 >

  • Retain : 연결된 퍼시스턴트 볼륨 클레임 삭제 후에 Released 전환, 실제 데이터는 보존
  • Delete : 퍼시스턴트 볼륨 사용 종료 이후 자동적으로 삭제됨
  • Recycle : 퍼시스턴트 볼륨 클레임 삭제시, 퍼시스턴트 볼륨의 모든 데이터를 삭제 후 Available 로 전환
    • Deprecated 된 기능.

9.3.5 StorageClass와 Dynamic Provisioning

  • 다이나믹 프로비저닝은, 퍼시스턴트 볼륨 클레임이 요구하는 조건과 일치하는 퍼시스턴트 볼륨이 존재하지 않는다면, 자동으로 퍼시스턴트 볼륨과 외부 스토리지를 함께 프로비저닝하는 것.

10. 보안을 위한 인증과 인가 : ServiceAccount와 RBAC

  • 쿠버네티스가 보안 측면에서 제공하는 기능 중, 가장 자주 사용되는 것은 RBAC(Role Based Access Control)를 기반으로 하는 서비스 어카운트(Service Account) 기능!
  • 서비스 어카운트는 사용자 또는 애플리케이션 하나에 해당하며, RBAC라는 기능을 통해 특정 명령을 실행할 수 있는 권한을 서비스 어카운트에 부여
    • 권한을 부여받은 서비스 어카운트는 해당 권한에 해당하는 기능만 사용 가능

10.1 쿠버네티스의 권한 인증 과정

[ kubectl 명령어를 사용해 쿠버네티스 기능 실행 시, 일어나는 일들 ]
1. HTTP 핸들러 : kubectl 명령어가 쿠버네티스 API 서버의 HTTP 핸들러에 요청을 전송
2. Authentication & Authorization : API 서버는 해당 클라이언트가 쿠버네티스의 사용자가 맞는지 (인증), 해당 기능을 실행할 권한이 있는지 (인가) 확인
3. 어드미션 컨트롤러 단계를 거친 뒤, 요청받은 기능을 수행

→ kubectl 사용시, 이런 과정을 신경쓰지 않았던 것은
설치 도구가 자동으로 kubectl이 관리자 권한을 갖도록 설정하기 때문
→ ~/.kube/config 파일에서 확인!

10.2 서비스 어카운트와 롤(Role), 클러스터 롤(Cluster Role)

  • 서비스 어카운트는, 체계적으로 권한을 관리하기 위한 쿠버네티스 오브젝트이다.
  • 한 명의 사용자나, 애플리케이션에 해당한다고 이해하면 쉽다-!
  • 쿠버네티스에서 권한 부여하는 방법은, Role을 사용하거나 Cluster Role을 사용하는 두 가지로 구분!

[ Role 사용하기 ]

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
	namespace: default
    name: service-reader
rules:
- apiGroups: [""]  #1. 대상이 될 오브젝트의 API 그룹
  resources: ["services"]  #2. 대상이 될 오브젝트의 이름 
  verbs: ["get", "list"]  #3. 어떠한 동작을 허용할 것인지 명시
  • apiGroups : 어떠한 API 그룹에 속하는 오브젝트에 대해 권한을 지정할지 설정. API 그룹은 쿠버네티스의 오브젝트가 가지는 목적에 따라 분류되는, 일종의 카테고리
  • resources : 어떠한 쿠버네티스 오브젝트에 대해 권한을 정의할 것인지 입력
  • verbs : 이 롤을 부여받은 대상이 resources에 지정된 오브젝트들에 대해 어떤 동작을 수행할 수 있는지 정의

코어 API 그룹("")에 속하는 서비스 리소스에 대해 get과 list를 실행할 수 있다.

  • 롤은 특정 기능에 대한 권한을 정의하는 오브젝트이므로, 롤을 생성하는 것만으로 서비스 어카툰트나 사용자에게 권한이 부여되지 않는다.
    • 롤 바인딩(Role Binding)이라는 오브젝트를 통해 특정 대상과 롤을 연결해야 함!

[ ex. 서비스 어카운트에 롤에 정의된 권한 부여하기 ]

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
	name: service-reader-rolebinding
    namespace: default
subjects:
- kind: ServiceAccount # 권한을 부여할 대상이 ServiceAccount
  name: alicek106 # alicek106이라는 이름의 서비스 어카운트에 권한을 부여
  namespace: default
roleRef:
	kind: Role #Role에 정의된 권한을 부여합니다.
    name: service-reader # service-reader라는 이름의 Role을 대상(subjects)에 연결
    apiGroup: rbac.authorization.k8s.io

→ 롤 바인딩과 롤, 서비스 어카운트는 모두 1 : 1 관계가 아님!
→ 하나의 롤은 여러 개의 롤 바인딩에 의해 참조될 수 있고, 하나의 서비스 어카운트는 여러 개의 롤 바인딩에 의해 권한을 부여받을 수 있다.

롤은 권한을 부여하기 위한 일종의 템플릿, 롤 바인딩은 롤과 서비스 어카운트를 연결하기 위한 중간 다리

[ 클러스터 롤 ]

  • 클러스터 롤은 클러스터 단위의 리소스에 대한 권한을 정의하기 위해 사용
  • 클러스터 롤을 특정 대상에게 연결하려면 클러스터 롤 바인딩이라는 쿠버네티스 오브젝트를 사용한다.

10.3 쿠버네티스 API 서버에 접근

10.3.2 클러스터 내부에서 kubernetes 서비스를 통해 API 서버에 접근

쿠버네티스 클러스터 내부 애플리케이션은 어떻게 API 서버에 접근하고 인증을 수행하는가?

  • 가령, Nginx 인그레스 컨트롤러는 인그레스의 생성을 동적으로 감지해 Nginx의 라우팅 규칙을 업데이트
    • 이를 위해, Nginx 인그레스 컨트롤러는 인그레스 규칙이 생성, 삭제될 때마다 알림을 받을 수 있도록 쿠버네티스 API 서버에 Watch API를 걸어둬야 하고, 해당 API 사용을 위한 적절한 권한을 부여받아야 한다.

→ 이를 위해 쿠버네티스는 클러스터 내부에서 API 서버에 접근할 수 있는 서비스 리소스를 미리 생성!
→ 기본적으로 존재하는 kubernetes 서비스가 그것이다.

쿠버네티스는 포드를 생성할 때 자동으로 서비스 어카운트의 시크릿을 포드 내부에 마운트한다.

  • 기본적으로 포드의 /var/run/secrets/kubernetes.io/serviceaccount 경로에 마운트

10.6 유저(User)와 그룹(Group)의 개념

  • 유저는 실제 사용자를, 그룹은 여러 유저들을 모아 놓은 집합을 의미
  • 롤 바인딩이나 클러스터 롤 바인딩을 정의하는 YAML 파일의 Kind 값에 ServiceAccount 대신 UserGroup 도 사용 가능!
profile
주니어 백엔드 개발자입니다! 조용한 시간에 읽고 쓰는 것을 좋아합니다 :)

0개의 댓글