동적 프로비저닝은 쿠버네티스에서 퍼시스턴트 볼륨 요청(PVC)을 했을 때 동적으로 퍼시스턴트 볼륨(PV)를 생성하고 해당 스토리지를 요청한 프로세스에 연결해 주는 방식이다. 이러한 방식은 높은 유연성과 자동화된 할당 정책, 배포 편리성 등의 까닭으로 클라우드 관리 시 자주 사용된다. 동적 프로비저닝 시 퍼시스턴트 볼륨은 기본으로 지정된 스토리지 클래스 범위에서 자동으로 할당된다. 이러한 까닭에, 스토리지 클래스가 이미 충분한 저장 공간을 가지고 있지 않고, 자동으로 설정된 경우, 많은 서비스가 해당 스토리지 클래스에 몰리게 된다.
정적 프로비저닝은 세밀하고 직접적인 정책 관리와 배포 흐름에 대한 선후관계가 엄격하기 때문에 명확한 워크플로우를 추구하거나 엄격한 보안 규칙이 적용되는 경우 사용된다.
하지만 일반적인 클라우드 실습의 경우에는 일일이 PV, PVC를 생성하는 것을 가정하지 않고, 동적 프로비저닝이 활성화되어 있다는 가정 하에 진행된다. 그리고, 깃랩과 같은 소규모 배포를 벗어난 서비스를 사용할 경우 퍼시스턴스가 복잡하게 설정되어 있으므로 이러한 기능이 있다면 유용하다.
그러나 클라우드 컴퓨팅의 장점 중 하나는 리소스의 유연한 공유이다. 따라서 많은 경우 스토리지 볼륨을 제공하는 노드와 컴퓨팅 노드를 분리하고, 개인 실습용 로컬 클러스터 구축 시에도 보통은 이러한 전략을 사용할 것이다. 그럼, 노드 1개에 NFS를 설정하고, 설정된 파일시스템을 마운트하여 스토리지 클래스로 설정하는 과정을 알아보자.
간단하게 모든 사용자가 모든 작업을 할 수 있는 파일시스템을 만들어 보자. 노드가 외부로 노출되어서 서비스되는 등 보안이 취약해질 수 있는 경우 접근 권한 등은 알아서 수정하도록 하자.
NFS를 설정할 노드에 접속하여 아래와 같은 파일을 만든다.
#!/bin/bash
echo "Setting up NFS storage..."
apt install -y nfs-kernel-server ## 이 부분은 배포판에 따라 수정해야 함
mkdir -p /mnt/k8s-storage-class
chown nobody:nogroup /mnt/k8s-storage-class #폴더 소유자 부재 상태로 전환
chmod 777 /mnt/k8s-storage-class #모든 사용자가 파일시스템 접근 권한이 있음.
echo "/mnt/k8s-storage-class 192.168.0.*/24(rw,sync,no_subtree_check,no_root_squash)" >> /etc/exports #클라이언트에서 서브디렉토리, 루트 권한 취득 허가
systemctl restart nfs-server
exportfs -arv #export fs
echo """
#################################################
## IF YOU ARE USING FIREWALLD: #
## firewall-cmd --permanent --add-service=nfs #
## firewall-cmd --reload #
#################################################
## IF YOU ARE USING UFW: ##
## ufw allow nfs ##
#################################################
"""
이렇게 되면 폴더는 자연스레 사용자의 소유권에 따라 맞춰질 것이다.
하지만, 이대로는 NFS가 설정되었을 뿐이지 쿠버네티스 스토리지 클래스에서 NFS를 저장공간으로 쓰지도 않고, 여전히 PVC는 대기 상태에서 걸려 있을 수밖에 없다.
바로 노드의 IP를 기억 후에 아래로 내려가자. kubectl로 확인해도 좋고, ip addr
로 확인해도 좋다.
그렇다면, 다음으로 StorageClass를 생성해 보자. 다행인 것은, NFS 스토리지를 저장공간으로 쓰는 스토리지 클래스는 헬름 차트로 손쉽게 생성 가능하다. 역시 빠르게 스크립트부터 보자.
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner
helm update
helm install nfs-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--set nfs.server=$YOUR_NFS_SERVER_IP \
--set nfs.path=/mnt/k8s-storage-class \
--set storageClass.defaultClass=true \
--set storageClass.reclaimPolicy=Delete
sudo apt install -y nfs-common
export 등으로 YOUR_NFS_IP를 정의해야 하고, 이것은 노드 주소로 설정해야 한다.
그 후 생성한 스크립트를 실행하면 배포가 완료되고 kubectl get storageclass
를 하면 (default) 태그로 스토리지클래스가 설정이 되어 있을 것이다.
이제, 테스트 삼아 GitLab을 배포해 보자.
#!/bin/bash
export YOUR_DOMAIN=example.com
export YOUR_EMAIL=me@example.com
export YOUR_PUBLIC_IP=10.10.10.10
이것과 같이 자신의 정보에 맞게 스크립트를 만들어 주자. 그러나, PUBLIC IP로 바로 체결되지 않은 경우 그냥 ““로 비워두자.
이제 export
명령을 실행해 보면 메일 등의 주소가 환경 변수로 설정된 것을 볼 수 있다.
그럼, 깃랩 설치를 위한 스크립트도 짜 보자. 아주 간단하다. 명령어에서 요구하는 것 역시 모두 환경변수에 있다.
#!/bin/bash
helm repo add gitlab https://charts.gitlab.io/
helm repo update
kubectl create ns gitlab
helm upgrade --install gitlab gitlab/gitlab \
--timeout 600s \
--set global.hosts.domain=$YOUR_DOMAIN \
--set global.hosts.externalIP=$YOUR_PUBLIC_IP \
--set certmanager-issuer.email=$YOUR_EMAIL \
--set gitlab.gitlab-rails.initialRootEmail=$YOUR_EMAIL \
--namespace gitlab
이 때, 공인 IP를 쓰지 않고 비워둔 경우 kubectl get svc -n gitlab
를 해 보자.
gitlab-nginx-ingress-controller은 LoadBalancer
타입으로 생성되어 있고, IP는 할당되지 않고 대기 상태일 것이다.
이렇다면, MetalLB를 설정 후, 서비스를 수정해야 한다.
kubectl edit configmap -n kube-system kube-proxy
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.9/config/manifests/metallb-native.yaml
MetalLB가 설정되었다. 하지만 할당하기 위한 IP 범위를 설정하지 않았다. 이를 설정하도록 하자.
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: gitlab-metallb-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.200-192.168.1.250
autoAssign: true
편하게 192.168.1.200 - 192.168.1.250으로 하고, yaml을 kubectl apply
로 적용하자.
이제 IP 대역이 설정되었다. 실제로 같은 네트워크 레벨에서 IP를 할당하기 위해 L2 Advertiser를 설정하자.
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: gitlab-l2-advertisement
namespace: metallb-system
spec:
ipAddressPools:
- gitlab-metallb-pool
마찬가지로 적용해 준다.
kubectl edit svc gitlab-nginx-ingress-controller -n gitlab
을 해 보자.
만약 실수로 공인 IP를 기입했다면 열린 서비스 YAML에서 공인 IP를 삭제하자.
이후 조금 기다리면 192.168.1.200으로 첫 IP가 MetalLB를 통해 할당된다.
다시 kubectl get svc -n gitlab
하고 노출 포트에 따라 적절히 포워딩한 후 웹 UI로 접속하자.
root의 비밀번호를 몰라서 로그인이 안 될 것이다.
이것은 GitLab의 Base64 인코딩된 시크릿을 읽어서 확인하면 된다.
kubectl get secret gitlab-gitlab-initial-root-password -ojsonpath='{.data.password}' -n gitlab | base64 --decode; echo
다음으로 확인한 비밀번호로 접속하면 관리자로 로그인된다.