[Kubernetes Volume] 2. 파드 내부 컨테이너간 데이터 공유(emptyDir, gitRepo)
목차
- empthDir
- emptyDir 볼륨이란?
- 파드 생성
- 실행 중인 파드 보기
- emptyDir을 사용을 위한 매체 지정
- gitRepo
- gitRepo에 파일 복제 및 서비스 실행
- 포크(fork)하다?
- 깃 리포지터리와 파일 동기화 여부 확인
- 사이드카 컨테이너
- 프라이빗 깃 리포지터리로 gitRepo 볼륨 사용
- gitRepo에 파일 복제 및 서비스 실행
emptyDir
emptyDir 볼륨이란?
가장 간단한 볼륨 유형은 emptyDir 볼륨으로 어떻게 파드에 볼륨을 정의하는지 살펴봅시다. 이름에서 알 수 있듯이 볼륨이 빈 디렉터리로 시작됩니다. 파드에 실행 중인 애플리케이션은 어떤 파일이든 볼륨에 쓸 수 있습니다. 볼륨의 라이프사이클이 파드에 묶여 있으므로 파드가 삭제되면 볼륨의 콘텐츠는 사라집니다.
emptyDir 볼륨은 동일 파드에서 실행 중인 컨테이너 간 파일을 공유할 때 유용합니다. 그러나 단일 컨테이너에서도 가용한 메모리에 넣기에 큰 데이터 세트의 정렬 작업을 수행하는 것과 같이 임시 데이터를 디스크에 쓰는 목적인 경우 사용할 수 있습니다. 데이터는 컨테이너 자체 파일 시스템에도 쓸 수 있지만 이 두가지 옵션에는 미묘한 차이가 있습니다. 컨테이너의 파일 시스템은 쓰기가 불가할 수도 있고 마운트된 볼륨에 쓰는 것이 유일한 옵션일 수 있습니다.
파드 생성
파드를 실행하기 위한 두 개의 이미지를 사용합니다. 하나는 이미 빌드되어 있는 luksa/fortune과 alpine 리눅스의 nginx입니다. 이제 파드 매니페스트를 생성해봅시다. 다음 예제의 내용을 포함한 YAML 파일을 생성합니다.
apiVersion: v1
kind: Pod
metadata:
name: fortune
spec:
containers:
- image: luksa/fortune > 첫 번째 컨테이너는 html-generator라고 이름 짓고luksa/fortune 이미지를 실행
name: html-generator
volumeMounts: > html이란 이름의 볼륨을 컨테이너의/var/htdocs에 마운트
- name: html
mountPath: /var/htdocs
- image: nginx:alpine > 두 번째 컨테이너는 web-server라고 이름 짓고 nginx:alpine 이미지를 실행
name: web-server
volumeMounts: > 위와 동일한 볼륨을 /usr/share/nginx/html에 읽기 전용으로 마운트
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes: > html이란 단일 emptyDir 볼륨을 위의 컨테이너 두 개에 마운트
- name: html
emptyDir: {}
파드는 컨테이너 두 개와 각 컨테이너에 각기 다른 경로로 마운트된 단일 볼륨을 갖습니다. html-generator 컨테이너가 시작하면 매 10초마다 fortune 명령의 결과를 /var/ htdocs/index.html에 쓰기 시작합니다. 볼륨이 /var/htdocs에 마운트됐으므로 index.html 파일은 컨테이너의 최상단 레이어가 아닌 볼륨에 쓰여집니다.
web-server 컨테이너가 시작 하자마자 컨테이너는 /usr/share/nginx/html 디렉터리(Nginx 서버가 서비스하는 기본 디렉터 리)의 HTML 파일을 서비스하기 시작합니다. 볼륨이 정확한 경로에 마운트됐으므로, Nginx 는 fortune 루프를 실행하는 컨테이너가 작성한 index.html 파일을 서비스합니다. 결과적으로 클라이언트가 파드의 포트 80으로 보낸 HTTP 요청은 fortune 메시지를 응답으로 받습니다.
실행 중인 파드 보기
Fortune 메시지를 보려면 파드의 접근을 활성화해야 합니다. 이 작업은 로컬 머신의 포트를 파드로 포워딩하면 됩니다.
명령어
kubectl port-forward fortune 8080:80
출력
Forwarding from 127.0.0.1:8080>80
Forwarding from [::1]:8080 -> 80
이제 로컬 머신의 포트 8080으로 Nginx 서버에 접근할 수 있습니다. 서버에 접근할 때는 curl 명령어를 사용합니다.
curl http://localhost:8080
몇 분을 기다린 뒤 다시 요청을 보내면 다른 메시지를 받을 것입니다. 이번 포스팅에서 여기까지의 과정은 컨테이너 두 개를 합쳐 어떻게 볼륨이 컨테이너 두 개를 결합시키고 각 컨테이너의 기능을 향상시키는지를 살펴보기 위해 간단한 애플리케이션을 생성한 것입니다.
emptyDir을 사용을 위한 매체 지정
볼륨으로 사용한 emptyDir은 파드를 호스팅하는 워커 노드의 실제 디스크에 생성되므로 노드 디스크가 어떤 유형인지에 따라 성능이 결정됐습니다. 반면 쿠버네티스에 emptyDir을 디스크가 아닌 메모리를 사용하는 tmpfs 파일시스템으로 생성하도록 요청할 수 있습니다. 이 작업을 위해 다음과 같이 emptyDir의 medium을 Memory로 지정합니다.
volumes:
- name: html
emptyDir:
medium: Memory > 이 emptyDir의 파일들은 메모리에 저장
emptyDir 볼륨은 가장 단순한 볼륨의 유형이지만 다른 유형들도 이 볼륨을 기반으로 합니다. 빈 디렉터리가 생성된 후 데이터로 채워집니다. 그런 볼륨 유형 중 하나가 gitRepo 볼륨 유형입니다.
gitRepo
gitRepo 볼륨의 특징은 생성된 후에는 참조하는 리포지터리와 동기화되지 않는다는 것입니다. 깃 리포지터리에 추가 커밋을 푸시해도 볼륨에 있는 파일은 변경되지 않습니다. 그러나 레플리케이션컨트롤러가 파드를 관리하는 경우 파드를 삭제하면 새 파드가 생성되는데 이 때 파드의 볼륨에는 최신 커밋을 포함하게 됩니다.
예를 들어 깃 리포지터리에 웹사이트의 정적 HTML 파일을 저장하고 gitRepo 볼륨과 웹 서버 컨테이너를 가진 파드를 생성할 수 있습니다. 매번 파드가 생성될 때 웹사이트의 최신 버전을 가져와 서비스할 것입니다. 단점은 gitRepo에 변경을 푸시할 때마다 웹사이트의 새 버전을 서비스하기 위해 파드를 삭제해줘야 한다는 점입니다.
gitRepo에 파일 복제 및 서비스 실행
파드를 생성하기 전에 HTML 파일이 있는 실제 깃 리포지터리가 필요합니다. 제가 공부하는 책의 저자는 예제를 위해 https://github.com/luksa/kubia-website-example.git에 깃허브 GitHub 리포지터리를 생성해 주었습니다. 나중에 변경 사항을 푸시하기 위해서 리포지터리를 포크해야 합니다. 깃허브에 리포지터리 복사본을 만드는 것도 방법입니다.
포크를 생성했으면 이제 파드를 생성할 차례입니다. 이번에는 파드에 Nginx 컨테이너 하 나와 gitRepo 볼륨 하나만 있으면 됩니다. gitRepo 볼륨이 예제 리포지터리를 포크한 여러분의 리포지터리를 가리키는지 확인을 한번 더 하면 좋습니다. 아무래도 주소를 직접 타이핑하게 되면 휴먼 리스크(오타)가 발생하기 때문이죠.
apiVersion: v1
kind: Pod
metadata:
name: gitrepo-volume-pod
spec:
containers:
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
containerPort: 80
protocol: TCP
volumes:
- name: html
gitRepo: > gitRepo 볼륨을생성
repository: https://github.com/luksa/kubia-website-example.git > 볼륨은 이 깃 리포지터리를 복제
revision: master > master 브랜치를 체크아웃
directory: . > 볼륨의 루트 디렉터리에리포지터리를 복제
파드를 생성하면 볼륨은 먼저 빈 디렉터리를 초기화한 다음 특정 깃 리포지터리를 복제 합니다. directory . (점)으로 지정하지 않으면 의도치 않게 리포지터리가 kubia-website- example 하위 디렉터리로 복제됐을 것입니다. 예제에서 리포지터리는 볼륨의 루트 디렉터리에 복제 돼야 하기 때문에 리포지터리를 지정함과 동시에 볼륨이 생성되는 시점에 쿠버네티스에게 master 브랜치가 가리키는 버전을 체크아웃하도록 지정했습니다.
파드가 실행되면 포트 포워딩, 서비스 또는 파드 내부(혹은 클러스터 내부의 또 다른 파드) 에서 curl 명령을 실행해 호출할 수 있습니다.
- 포크(fork)하다?
"리포지토리를 포크한다"는 것은 Git 및 GitHub, GitLab 및 Bitbucket과 같은 플랫폼에서 버전 제어 시스템의 맥락에서 사용됩니다. 리포지토리를 포크한다는 것은 자신의 계정 또는 네임스페이스에서 기존 리포지토리의 복사본을 만드는 것을 의미합니다. 이를 통해 원래 리포지토리에 영향을 주지 않고 코드베이스를 독립적으로 변경할 수 있습니다.
리포지토리를 포크하는 주된 이유는 오픈 소스 프로젝트에 기여하거나 기존 프로젝트를 작업의 시작점으로 사용하기 위해서입니다. 리포지토리를 포크하면 수정하거나 새로운 기능을 실험하거나 코드베이스의 버그를 수정할 수 있습니다. 포크된 리포지토리를 변경한 후에는 원본 리포지토리에 pull 요청(또는 merge 요청)을 제출하여 변경 사항을 기본 코드베이스에 병합할 것을 제안할 수 있습니다. 프로젝트 관리자는 변경 사항을 검토하고 피드백을 제공하며 기여를 수락할지 거부할지 결정할 수 있습니다.
깃 리포지터리와 파일 동기화 여부 확인
깃허브 리포지터리의 index.html 파일을 변경할 수 있습니다. 로컬에서 깃을 사용하지 않는 다면 깃허브에서 직접 파일을 수정도 가능합니다. 깃허브 리포지터리에서 파일을 클릭해 열고 연필 모양의 아이콘을 클릭하면 편집을 시작합니다. 텍스트를 변경하고 페이지의 맨 아래에 있는 버튼을 클릭해 변경 사항을 커밋합니다.
이제 깃 리포지터리의 master 브랜치에는 변경된 HTML 파일이 들어있습니다. gitRepo 볼륨은 깃 리포지터리와 동기화하지 않기 때문에 이 변경 사항이 Nginx 웹 서버에서는 보이지는 않습니다. 파드를 다시 호출해 확인해봅니다.
웹사이트의 새 버전을 보려면 파드를 삭제하고 다시 생성해야 합니다. 변경 사항이 있을 때마다 파드를 삭제하는 대신에 볼륨이 항상 깃 리포지터리와 동기화하도록 추가 프로세스를 실행할 수도 있습니다. 이 업계로 들어온다면 점차 깃허브와 친해질 것입니다. 때문에 자주 연습하고 친해지는 것이 좋습니다. 다음은 고려 해 볼 수 있는 사항들을 정리했습니다.
- 사이드카 컨테이너
깃 동기화 프로세스가 Nginx 웹 서버와 동일 컨테이너에서 실행되면 안 되며 두 번째 컨 테이너인 사이드카(sidecar) 컨테이너에서 실행돼야 합니다. 사이드카 컨테이너는 파드의 주 컨 테이너의 동작을 보완합니다. 새로운 로직을 메인 애플리케이션 코드에 밀어 넣어 복잡성을 더하고 재사용성을 떨어뜨리지만, 파드에 사이드카를 추가하면 기존 컨테이너 이미지를 사용도 있고 로직도 적용할 수 있습니다.
로컬 디렉터리를 깃 리포지터리와 동기화되도록 유지하는 기존의 컨테이너 이미지를 찾으려면 도커 허브로 가서 "git sync"로 검색해보면, 이런 동작을 하는 많은 이미지를 찾 을 수 있습니다. 예제의 파드에서 새 컨테이너에 그 이미지를 사용하고 기존 gitRepo 볼륨을 새 컨테이너에 마운트한 뒤, 깃 동기화 컨테이너가 깃 리포지터리와 파일 동기화를 유지하 도록 설정합니다. 모든 것이 올바르게 설정됐다면 웹 서버가 서비스하는 파일이 항상 깃허브 리포지터리와 동기화될 것입니다. - 프라이빗 깃 리포지터리로 gitRepo 볼륨 사용
깃 동기화 사이드카 컨테이너를 사용해야 하는 또 다른 이유가 있습니다. 프라이빗 깃 리포지터 리로 gitRepo 볼륨을 사용할 수 없습니다. 쿠버네티스 개발자들의 공통된 결론은 gitRepo 볼륨을 단순하게 유지하고 프라이빗 리포지터 리를 SSH 프로토콜을 통해 복제하는 방식의 지원을 추가하지 않은 것입니다. gitRepo 볼륨 에 추가 설정 옵션을 필요로 하기 때문입니다.
프라이빗 깃 리포지터리를 컨테이너에 복제하려면 깃 동기화 사이드카나 아니면 git Repo 볼륨을 대신하는 다른 유사 방법을 사용해야 합니다.
'Container > Kubernetes' 카테고리의 다른 글
[Kubernetes Volume] 4. 퍼시스턴트 스토리지(Persistent storage)와 사용법 (2) | 2023.04.14 |
---|---|
[Kubernetes Volume] 3. 워커노드 파일 시스템로 파일 접근(hostPath) (0) | 2023.04.13 |
[Kubernetes Volume] 1. 쿠버네티스 볼륨과 볼륨의 유형 (0) | 2023.04.12 |
[Kubernetes Service] 7. 헤드리스 서비스란? (0) | 2023.04.11 |
[Kubernetes Service] 6. 레디니스 프로브(readyness probe)로 수신 요청 (0) | 2023.04.11 |