본문 바로가기 대메뉴 바로가기

테크니컬 스토리

아이티마야의 새로운 기술 뉴스를 만나보세요.
기술자료
비용과 UI로 관리가 쉬운 오픈소스 메시지 브로커를 알아보자. RabbitMQ(Massage System)를 구축해 보자. 비용과 UI로 관리가 쉬운 오픈소스 메시지 브로커를 알아보자. RabbitMQ란. RabbitMQ는 가장 널리 퍼져있는 오픈소스 메시지 브로커 방식입니다. 즉, 메시지 브로커 방식이란, 응용프로그램, 서비스 및 시스템이 정보를 통신하고 교환할 수 있도록 하는 소프트웨어 모듈입니다. 사용하는 이유. 이와 같은 Massage System을 사용하는 이유는, 독립된 애플리케이션을 RabbitMQ라는 메시지 시스템을 통해 실시간으로 데이터를 주고받음으로써, 데이터 교환 엔드포인트를 하나로 통합해 비용이 들지 않으며, 관리가 수월해집니다. RabbitMQ 특징. RabbitMQ의 장점을 정리해 보면, 라우팅, 클러스터링, 관리 UI와 가벼운 오픈소스입니다. RabbitMQ는 kafka와 비슷한 방식이지만, 대용량 데이터를 사용하지 않는다면, 가벼운 RabbitMQ를 사용하는 것이 좋습니다. RabbitMQ는 서버가 죽는 경우 메모리에 저장돼 있던 메시지들은 모두 사라지지만, MessageDurability라는 옵션으로 디스크에도 저장이 되게 하여, 메시지 손실을 막아줍니다. (하지만, 디스크에 저장될 때 서버가 죽는 경우 손실을 막을 순 없습니다. 따라서, RabbitMQ의 환경 구축을 해보겠습니다. 구축환경은 아래와 같습니다. OS:(VM) Ubuntu22.04 GUI (GDM3) CPU:8 core RAM:4GB (tip) RabbitMQ(Massage System)을 구축하기 전, 손쉬운 모니터링을 위해 GUI를 설치하는 것이 좋습니다. 1. 우선 최신버전 설치를 위해, 업데이트를 진행해 줍니다. #sudo apt-get update 2. 그 후, rabbitmq를 설치해 줍니다. #sudo apt-get install rabbitmq-server 3. 재부팅 후에도, 서비스가 동작하도록 하기 위해 아래와 같은 명령어를 입력해 줍니다. #sudo systemctl restart rabbitmq-server #sudo rabbitmq-plugins enable rabbitmq_management 4. 아래 명령어로 플러그인이 켜졌는지 확인이 가능합니다.(그림 참고) #sudo rabbitmp-plugins list 4. rabbitmq 계정 생성(기본적으로 rabbitmq는 gui모드에서 기본계정이 ID,PW:guest로 생성되지만, 이 계정으로는 외부에서 접속이 불가능 함으로, 계정을 따로 생성해 줍니다.) #sudo rabbitmqctl add_user (id)(pw) (예시) sudo rabbitmqctl add_user test test #sudo rabbitmqctl set_user_tags (id) administrator (예시) sudo rabbitmqctl set_user_tags test administrator 저는 예시와 같이 #sudo rabbitmqctl add_user test test 로 id,pw 둘다 test계정으로 생성했습니다. 5. Rabbitmq는 기본 포트가 5672, GUI는 15672입니다. 저는 GUI로, 아래 그림과 같이 localhost:15672로 접속할 수 있습니다. 로그인 후, 아래처럼 웹으로 잘 접속되는 것을 확인할 수 있습니다. 그 외, 포트 변경 방법입니다. (아래 그림 참고) #sudo vi /etc/rabbitmq/rabbitmq-env.conf #NODE_PROT=5672 의 주석을 해제후, 원하는 포트 번호를 적어주세요. 아래의 명령어로 rabbitmq를 재시작 해주세요. #sudo systemctl restart rabbitmq-server Rabbitmq service가 동작하지 않을시. 만약, 아래 그림과 같이 Rabbitmq에 (e)라고 적혀있지 않다면 서비스가 실행 중이지 않다는 겁니다. 다시 한번 아래와 같은 명령어를 입력해 주시면 됩니다. #sudo systemctl restart rabbitmq-server #sudo rabbitmq-plugins enable rabbitmq_manageme 아래와 같이 [e]또는 [E]라고 되어있으면 정상적으로 실행 중입니다. 2023.06.16
100 Gbps OPA(Omni-Path Express Accelerated) 장치 설정 (Ubuntu) 가성비로 구성하는 서버 간 100 Gbps 구성 100 Gbps OPA(Omni-Path Express Accelerated) 장치 설정 (Ubuntu) 서버 간 고속 통신 OPA(Omni-Path Express Accelerated)는 몇 년 전까지 인텔에서 HPC를 대상으로 세일즈 하던 Mellanox EDR과 비교되던 서버 간 고속 통신망입니다. 지금은 OPA가 CORNELIS로 인수되어 지속되고 있습니다. 최근 Nvidia에 인수된 Mellanox의 인피니밴드 제품이 2023년 1분기 기준 제품수급에 문제가 있어 발주 후 오랜 시간을 대기해야만 하고, 가격도 많이 비싸 가성비로 OPA로 선택하시는 경우가 많습니다. OPA는 100 Gbps 구성까지 제공하며 기본구성으로 48 포트 스위치와 서버에 장착되는 인터페이스카드만 있으면 사용 가능합니다. OS 지원 OPA의 OS 제공은 Redhat 계열을 위주로 업데이트되고 있습니다. 하지만 최근 AI사용자의 Ubuntu 사용이 많아지며 Ubuntu에서 사용하는 방법에 대해 정리하였습니다. ● 테스트된 OS ○ Ubuntu 20.04 ○ Ubuntu 22.04 Ubuntu repo에서는 OPA관련 패키지를 제공하여 매우 간단하게 구성할 수 있습니다. 테스트는 스위치 1개에 6대의 서버를 OPA HCA를 통해 연결하고 테스트했습니다. 장치 구성 $ sudo apt install opa-fastfabric rdma-core OPA 정보 로드 $ sudo opainfo $ sudo opareport $ lspci | grep Omni $ lshw -C network issue#1. OPA 장치명 할당 이슈 장치 드라이버 설치 후, 장치는 정상 인식되지만 장치명이 할당되지 않는다면, modprobe.d 에서 nouveau를 차단했는지 확인해야 합니다. 만약 차단했다면 차단을 하지 않아야 정상 할당 됩니다. # cd / etc/modprobe.d nouveau 차단 내용 모두 삭제 issue#2. ipoib 등 모듈 자동 로드 이슈 인피니밴드 장치에 ip를 할당하기 위해 ipoib를 포함한 몇몇 모듈이 실행되어야 하는데, 모듈이 자동으로 로드되지 않습니다. rdma-core 패키지를 설치하면 opa-fastfabric과 함께 설치된 모듈도 자동으로 로드되도록 등록해야 합니다. issue#3. OPA 장치 활성화 이슈 초기 구성시 opainfo 명령어로 확인했을 때 PortState 값이 Init으로 출력됩니다. 이는 정상 인식이 되지 않은 경우이며, subnet manager 가 구성되지 않으면 이런 증상이 나타납니다. 모든 서버 중 반드시 서버 1대에는 opa-fm을 설치해야 합니다. opa-fm 패키지를 설치하면 PortState 값이 Active로 변경되고, OS에서 제공하는 netplan이나 network-manager 등에서 IP할당이 정상적으로 가능합니다. 서브넷 매니저는 1개 네트워크에 1개 서버에만 설치되면 된다. 중복 설치되면 문제가 됩니다. opa-fm 이 설치된 서버가 다운된다면, opa 링크 연결에도 영향을 줄 수 있습니다. $ sudo apt install opa-fm OPA 장, 단점 OPA구성은 이더넷과 같은 네트워크 통신이 아닙니다. IP 등을 할당하여 사용하는 환경은 동일하게 제공하지만, 이를 이더넷 통신으로 사용할 수 없습니다. 서버 간 고속 통신만 제공합니다. HPC에서는 상당한 시장 점유율이 있는 제품인 만큼, 구성에 대한 래퍼런스를 많이 찾아볼 수 있습니다. 가격이 상대적으로 저렴한 게 가장 큰 장점입니다. 아쉬운 점은 HPC 외의 환경에서 많은 래퍼런스가 없다는 점과 100 Gbps 이후 후속모델이 아직 출시되지 않고 있다는 게 많이 아쉬운 점입니다. 하지만 OPA는 서버 간 고속통신을 고려한다면 꼭 비교대상에 올려놓아야 하는 제품입니다. 2023.05.17
Kubeflow 설치 및 활용 오픈소스 MLOps 중 가장 많이 사용하는 Kubeflow 설치 및 활용 방안 Kubeflow 설치 및 활용 Kubeflow 사용 이유 Kubeflow는 오픈소스로 구성된 MLOps 제품입니다. 분석/트레이닝/서빙을 모두 처리할 수 있고, 사용방법이 쉽습니다. 전제 조건 1.kubenetes (1개 노드 이상 구성) 2.Default Storage Class 3.(선택) Master Node kustomize 설치 snap repo에서 설치하는 kustomize 5.0.1 버전은 호환 문제가 있어, kustomize는 아래 방식으로 구성합니다. $ sudo snap remove kustomize $ curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash $ sudo mv kustomize /usr/local/bin/ kubeflow manifest 다운로드 1.6.1 버전으로 구성 시 기본 istio-gateway 구성이 NodePort로 되어 있어 외부 접속이 가능한 상태로 구성됩니다. SSL 인증도 마찬가지로 외부 접속이 가능한 상태로 구성되어 별도의 수정이 필요 없습니다. 그 외 모든 버전은 istio 기본 구성이 ClusterIP입니다. $ cd ~ $ git clone -b v1.6.1 https://github.com/kubeflow/manifests.git kustomize 설치 $ cd ~/manifests $ while ! kustomize build example | awk '!/well-defined/' | kubectl apply -f -; do echo "Retrying to apply resources"; sleep 10; done 구성 확인 $ kubectl get pod -A pod 초기화 및 컨테이너 생성에 상당한 시간이 소요됩니다. 만약 pod 생성 중 에러가 나거나, imagepull 이 되지 않는다면, pod 생성 순서가 잘못되어 있을 수 있습니다. 설치 스크립트를 다시 실행하면 재구성됩니다. dashboard 접근 istio gateway 가 nodeport 서비스로 변경되고, 80포트와 연결된 포트를 확인합니다. $ kubectl get svc istio-ingressgateway -n istio-system dex 기본 계정 계정 : user@example.com 비번 : 12341234 K8s Dashboard 설치 $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml K8s Dashboard NodePort 변경 $ kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard selector:   k8s-app: kubernetes-dashboard  sessionAffinity: None  type: NodePort ###########변경 status:  loadBalancer: {} K8s Dashboard Role 추가 $ vi kuebernetes-dashboard-service-account.yaml apiVersion: v1 kind: ServiceAccount metadata:   name: admin-user   namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata:   name: admin-user roleRef:   apiGroup: rbac.authorization.k8s.io kind: ClusterRole   name: cluster-admin subjects: - kind: ServiceAccount   name: admin-user   namespace: kube-system $ kubectl apply -f kuebernetes-dashboard-service-account.yaml 토큰확인 $ kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}') K8s 대시보드 접근 443 포트와 포워딩된 포트로 사용합니다. (https://IPaddress로 접속) $ kubectl get svc kubernetes-dashboard -n kubernetes-dashboard 2023.05.16
분산 스토리지 클러스터 선택의 이유 가성비 MLOps 스토리지 분산 스토리지 클러스터 선택의 이유 최근 MLOps 환경에서 가장 중요한 이슈는 단연 GPU와 스토리지입니다. GPU는 가격과 성능에 대한 테이블이 존재하지만, 스토리지는 여러 업체가 많은 이슈를 겪고 있습니다. SAN Storage 기존 전통적인 대용량 스토리지를 사용하자니 IOPS로 인한 전체 MLOps의 학습 속도 저하가 발생하고, 전통적인 스토리지에서 개선된 All Flash 스토리지를 사용하자니 용량 대비 가격이 만만치 않습니다. SAN 스토리지 구성은 정형 데이터 활용에서 많이 사용합니다. 스토리지는 2000 IOPS 정도의 성능으로 구성되며, 서버당 필요 IOPS는 1000을 넘지 않습니다. 많은 IOPS를 필요로 한다면 All Flash 스토리지로 구성하며, All Flash 스토리지는 1,000,000 IOPS 수준의 성능으로 구성되지만, 용량 대비 비용이 높습니다. 분산 스토리지 클러스터 MLOps 분야에서 가장 많이 선택하고 있는 분야는 소프트웨어 정의 스토리지입니다. 대표적인 오픈소스로 Ceph, GlusterFS, Hadoop 등이 있고, 여러 대의 파일서버를 하나의 스토리지 클러스터로 묶어 데이터를 분산처리하여 성능 및 안정성을 확보할 수 있습니다. MLOps 환경에서는 각각 GPU의 IOPS 요구량이 매우 많습니다. 학습 이미지 크기가 작다면(100k 미만) GPU마다 수천 번의 IOPS가 필요하며, 이미지 크기가 비교적 큰 편 (10m 미만)이라면 수백 번의 IOPS가 필요합니다. MLOps 환경에서는 스토리지의 성능이 전체 학습 성능에 큰 영향을 줍니다. 만약 연결 인터페이스를 InfiniBand로 구성한다면 NVIDIA GPU Direct를 사용할 수도 있습니다. 스토리지 스케일 아웃 분산 스토리지는 노드를 추가하여 추후 용량 증설 및 성능 향상이 용이합니다. 최근 여러 고객사는 예상치 않은 분야에서 많은 데이터를 획득합니다. MLOps에서도 초기 학습 데이터양을 정해두지만, 예상치 않은 데이터를 획득하고 이를 활용하여 새로운 학습모델과 시장을 발견하기도 합니다. 데이터 분석 및 AI 고객은 데이터를 삭제보다는 아카이빙에 초점을 두고, 스토리지의 용량 및 성능을 지속적으로 늘릴 수 있는 스토리지가 필요합니다. 스토리지의 용량 및 성능 스케일아웃은 MLOps 시장에서는 필수적인 요소입니다. 분산 스토리지 클러스터는 MLOps 환경에서 가장 적합한 스토리지 선택입니다. 2023.05.03
K8s내에 Ceph Storage Cluster 구성 (Multi Node) 오픈소스 스토리지 클러스터를 K8s내에 구성하기 K8s내에 Ceph Storage Cluster 구성 Kubernetes는 여러 스토리지 선택지가 있지만, 그중 온프레미스 환경에서 관리가 쉽고 강력한 성능을 내는 Ceph이 있습니다. Ceph Storage Cluster는 안정적이며, 높은 성능과 Block, File, Object 스토리지로 다양하게 사용이 가능합니다. 본 포스팅은 Kubernetes Cluster내에 Ceph Storage Cluster를 구성하여 이를 PVC로 사용하는 방법에 대해 설명합니다. 사전 설치 요구 ●k8s 구성 (3 node 이상) ●노드당 빈 디스크 1개 이상 ●노드당 8 core 이상 ●노드당 20GB 메모리 이상 ●Metal LB k8s구성 환경 본 테스트에서는 k8s는 4개 노드로 구성했습니다. 서버 스펙은 아래와 같습니다. k8s-mgmt : 8core / 24GB / 100GB x1 / 30GB x1 k8s-worker1 : 8core / 24GB / 100GB x1 / 30GB x1 k8s-worker2 : 8core / 24GB / 100GB x1 / 30GB x1 k8s-worker2 : 8core / 24GB / 100GB x1 / 30GB x1 100GB 디스크는 k8s 구성을 위해 사용된 OS 디스크이고, 30GB 디스크는 Ceph에서 사용할 디스크입니다. 디스크 1개당 OSD1개로 구성되며, 디스크는 각 노드에 포맷 및 마운트가 되지 않은 상태여야 합니다. Ceph 클러스터를 위해 2개의 MGR / 3개의 MON / 디스크 수만큼의 OSD 데몬이 실행되어야 합니다. 각 데몬마다 최소 Core/Memory 가 정해져 있습니다.(수정가능) 성능을 위해 코어와 메모리를 많이 할당하여 테스트했습니다. Rook 예제 및 소스파일 다운로드 Rook 예제 파일은 거의 모든 환경에서 대응할 수 있는 예제코드를 제공합니다. $ git clone https://github.com/rook/rook.git/ helm 활용 rook 오퍼레이터 구성 helm 으로 간단하게 rook-ceph 구성해 보겠습니다. (repo 추가) $ helm repo add rook-release https://charts.rook.io/release $ helm search repo rook-ceph (rook 오퍼레이터 설치) $ kubectl create namespace rook-ceph (repo 추가) $ helm install --namespace rook-ceph rook-ceph rook-release/rook-ceph $ kubectl get all -n rook-ceph Ceph 클러스터 구성 rook/deploy/examples/ 에 여러 예제 파일이 존재합니다. helm chart 기본 구성으로 설치합니다. 기본으로 구성할 경우, 2개의 MGR / 3개의 MON / 빈디스크 수만큼의 OSD 데몬이 생성됩니다. 최소 3개 노드이상일 경우 기본구성으로 설치하면 적당합니다. 아래 설치하기 전에 위에 구성한 오퍼레이터가 꼭 동작하고 있어야 합니다. 만약 오퍼레이터가 설치 중이라면 설치완료 후 진행합니다. $ helm install --namespace rook-ceph rook-ceph-cluster --set operatorNamespace=rook-ceph rook-release/rook-ceph-cluster $ kubectl get all -n rook-ceph 기본으로 구성하면, 스토리지 클래스에 Ceph-Block, Ceph-Bucket, Ceph-File system 이 모두 생성됩니다. 필요한 것만 설치한다면 예제파일 참고하여 구성할 수 있습니다. Toolbox 설치 rook/deploy/examples/ 에 toolbox.yaml 파일을 사용하여 구성합니다. toolbox를 통해 ceph cli를 사용할 수 있습니다. $ kubectl apply -f toolbox.yaml $ kubectl get deploy rook-ceph-tools -n rook-ceph $ kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath='{.items[0].metadata.name}') bash (toolbox)$ ceph -s (toolbox)$ ceph osd status Dashboard 사용 Ceph-Cluster관련 서비스가 모두 작동한다면, Dashboard 서비스가 동작중인 것을 확인할 수 있습니다. Dashboard는 기본 ClusterIP 서비스로 동작합니다. 외부에서 접속이 가능하게, LoadBalancer로 변경하여 사용합니다. (k8s에 LoadBalancer 서비스가 설치되어 있어야 합니다.) 먼저, CephCluster의 Dashboard 서비스를 ssl을 사용하지 않도록 변경하고, 기본 url을 변경합니다. $ kubectl get svc -n rook-ceph $ kubectl edit CephCluster rook-ceph -n rook-ceph (수정전) dashboard : enabled : true ssl : true (수정후) dashboard : enabled : true ssl : false urlPrefix : /ceph-dashboard 대시보드가 ssl을 사용한다면 8443 포트이지만, 우리는 ssl을 사용하지 않도록 구성하니 7000 포트로 고정됩니다. rook-ceph 예제파일 중 dashboard-loadbalancer.yaml 파일을 수정하고 적용합니다. $ vi dashboard-loadbalancer.yaml (수정전) port : 8443 targetPort : 8443 (수정후) port : 7000 targetPort : 7000 $ kubectl apply -f dashboard-loadbalancer.yaml 이제 rook-ceph-mgr-dashboard-loadbalancer라는 서비스가 LoadBalancer 타입으로 만들어지고 외부 IP가 확인됩니다. $ kubectl get svc -n rook-ceph NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE rook-ceph-mgr ClusterIP 10.233.49.224 9283/TCP 157m rook-ceph-mgr-dashboard ClusterIP 10.233.27.231 7000/TCP 157m rook-ceph-mgr-dashboard-loadbalancer LoadBalancer 10.233.23.189 192.168.0.170 000:31460/TCP 7m54s rook-ceph-mon-a ClusterIP 10.233.60.101 6789/TCP,3300/TCP 159m rook-ceph-mon-b ClusterIP 10.233.32.79 6789/TCP,3300/TCP 158m rook-ceph-mon-c ClusterIP 10.233.1.9 6789/TCP,3300/TCP 158m rook-ceph- rgw-ceph-objectstore ClusterIP 10.233.40.192 80/TCP 브라우저에서 http://192.168.0.170:7000/ceph-dashboard/ 경로로 접속할 수 있습니다. 계정은 admin이고 패스워드는 아래 명령으로 확인할 수 있습니다. # 패스워드 확인 $ kubectl get secret rook-ceph-dashboard-password -n rook-ceph -o yaml | grep "password:" | awk '{print $2}' | base64 --decode (Ceph-filesystem) PVC 생성 PVC를 생성하면 자동으로 PV도 함께 생성되고 연결됩니다. PVC 생성 예제 파일도 마찬가지로 ceph-csi/example/ 에서 확인할 수 있습니다. $ vi cephfs-pvc01.yaml --- apiVersion : v1 kind : PersistentVolumeClaim metadata : name : cephfs-pvc01 spec : accessModes : -ReadWriteMany resources : requests : storage : 5Gi     storageClassName : ceph-filesystem $ kubectl apply -f cephfs-pvc01.yaml $ kubectl get pvc (ceph-block) PVC 생성 CephFS와 가장 큰 차이점은 PVC 생성 시 accessModes값을 ReadWriteOnce로 구성했다는 것입니다. RBD는 ReadWriteMany로 구성할 수 없습니다. $ vi cephblock-pvc01.yaml --- apiVersion : v1 kind : PersistentVolumeClaim metadata : name : rbd-pvc spec : accessModes : -ReadWriteOnce resources : requests : storage : 10Gi     storageClassName : ceph-block $ kubectl apply -f cephblock-pvc01.yaml $ kubectl get pvc Test pod 생성 및 확인 ceph-filesystem PVC와 ceph-block PVC가 생성되었고 pvc 정보가 bound로 출력되는 것을 확인할 수 있습니다. pod를 만들어 마운트가 되는지 테스트해봅니다. $ vi ceph-test-pod.yaml --- apiVersion : v1 kind : Pod metadata : name : ceph-test-pod spec : containers : - name : web-server image : nginx volumeMounts : - name : ceph-filesystem-01 mountPath : /data1 - name : ceph-block-01 mountPath : /data2 volumes : - name : ceph-filesystem-01 persistentVolumeClaim : claimName : rbd-pvc readOnly : false - name : ceph-block-01 mountPath : /data2 - name : ceph-block-01 persistentVolumeClaim : claimName : rbd-pvc readOnly : false $ kubectl apply -f ceph-test-pod.yaml (확인) $ kubectl exec -ti ceph-test-pod /bin/bash rdb-test-pod01>df -h Filesystem Size Used Avail Use% Mounted on overlay 49G 17G 30G 37% / tmpfs 64M 0 64M 0% /dev tmpfs 14G 0 14G 0% /sys/fs/cgroup 10.233.1.9:6789,10.233.60.101:6789--- 5.0G 0 5.0G 0% /data1 /dev/rbd0 9.8G 24K 9.8G 1% /data2 /dev/mapper/ubuntu --vg-ubuntu--lv 49G 17G 30G 37% /etc/hosts shm 64M 0 64M 0% /dev/shm tmpfs 28G 12K 28G 1% /run/secrets /kubernetes.io/serviceaccount tmpfs 14G 0 14G 0% /proc/acpi tmpfs 14G 0 14G 0% /proc/scsi tmpfs 14G 0 14G 0% /sys/firmware 2023.02.14
아파치 카프카 (Apache Kafka) 오픈소스 분산형 스트리밍 플랫폼 - Apache Kafka 아파치 카프카 (Apache Kafka) Apache Kafka 란? Apache Kafka는 오픈소스 분산 스트리밍 플랫폼이며 주로 데이터 파이프 라인을 만들 때 사용되는 솔루션입니다. Apache Kafka 용어 설명 1. 브로커 (Broker) : 카프카가 설치되어 있는 서버 혹은 노드 등을 브로커라고 합니다. 브로커는 프로듀서에게서 전달받은 메시지를 수집, 전달 역할을 합니다. 2. 프로듀서 (producer) : 프로듀서 API를 통해 메시지를 브로커에게 보내는역할을 합니다. 3. 컨슈머 (consumer) : 컨슈머 API를 통해 브로커에서 메시지를 받는 역할을 합니다. 4. 주키퍼 (Zookeeper) : 다수의 카프카 클러스터를 관리하기 위한 관리도구입니다. 5. 토픽 (topic) : 카프카는 메시지를 토픽에 따라 분리할 수 있고 프로듀서와 컨슈머는 특정 토픽의 메시지를 송수신할 수 있습니다. 카프카의 특징 : ● 카프카는 Producer와 Consumer를 분리하며, 단일 Producer, Consumer 가 아닌 멀티 Producer와 멀티 Consumer로 구성이 가능합니다. ● 카프카 클러스터는 주키퍼와 연동하여 사용합니다, 주키퍼에는 리더, 팔로워라는 개념이 있고 주키퍼 서버에서 브로커 파티션의 리더를 정해주고 리더 파티션의 장애가 발생했을 시 주키퍼에서 다른 브로커의 파티션을 리더를 위임해 정상적으로 운영될 수 있게끔 합니다. ● 주키퍼는 홀수의 서버로 동작합니다. 카프카 클러스로 운영시 최소 3대 이상의 주키퍼 서버로 구성하길 권장합니다. 그 이유는 분산 코디네이션 환경에서 예상치 못한 장애가 발생하더라도 분산 시스템의 일관성을 유지시키기 위해서 사용합니다. [ Apache Kafka에서 Kafka 4.0 이후부터 주키퍼를 제거할 계획이라고 합니다 ] 안정성 : ● 다른 메시지 시스템과는 다르게 카프카는 메시지를 디스크에 순차적으로 저장합니다. 이로 인해 서버에 장애가 발생해도 디스크에 메시지를 저장하기 때문에 유실될 걱정이 없습니다. ● 카프카에서 replication 동작으로 브로커 하나가 종료되더라도 운영에 차질이 없습니다. 카프카를 사용하는 이유 : ● 카프카는 클러스터로도 운영되기 때문에 확장이 편리하고 장애에 대한 대처가 쉽습니다. ● 메시지를 디스크에 저장하기 때문에 유실될 걱정이 없는 안정성이 있습니다. ● 카프카는 메시지를 병렬로 처리하기 때문에 데이터를 더 효과적으로 저장할 수 있습니다. 설치 서버 스펙 - 환경 : VM - CPU : 8 Core - Memory : 8GB - OS : ubuntu 22.04 싱글노드 설치 예제 사전 설치 kafka 구성 전 java를 설치해 줍니다. $ apt install default-jre $ java --version 명령어를 통해 java 버전을 확인 $ apt install default-jdk $ javac -version 명령어를 통해 javac 버전 확인 kafka용 유저 생성 sudo 권한을 가진 kafka용 유저를 생성해 줍니다 $ sudo adduser kafka $ sudo adduser kafka sudo kafka 바이너리 다운로드 및 추출 $ sudo mkdir ~/Downloads $ sudo curl "https://downloads.apache.org/kafka/3.3.2/kafka_2.13-3.3.2.tgz" -o ~/Downloads/kafka.tgz $ mkdir ~/kafka && cd ~/kafka $ tar -xvzf ~/Downloads/kafka.tgz --strip 1 - 압축풀때 현재 kafka디렉토리에 위치하고 있는지 확인하고 풀어줍니다. kafka 서버 구성 $ vi ~/kafka/config/server.properties 맨 밑에 delete.topic.enable = true 추가해 주고 kafka 로그가 저장되는 디렉토리를 변경해 줍니다. log.dirs=/home/kafka/logs zookeeper, kafka 서비스를 보다 쉽게 실행 및 중지할 수 있도록 systemd에 파일 생성 $ vi /etc/systemd/system/zookeeper.service [Unit] Requires=network.target remote-fs.target After=network.target remote-fs.target [Service] Type=simple User=kafka ExecStart=/home/kafka/kafka/bin/zookeeper-server-start.sh /home/kafka/kafka/config/zookeeper.properties ExecStop=/home/kafka/kafka/bin/zookeeper-server-stop.sh Restart=on-abnormal [Install] WantedBy=multi-user.target $ vi /etc/systemd/system/kafka.service [Unit] Requires=zookeeper.service After=zookeeper.service [Service] Type=simple User=kafka ExecStart=/bin/sh -c '/home/kafka/kafka/bin/kafka-server-start.sh /home/kafka/kafka/config/server.properties > /home/kafka/kafka/kafka.log 2>&1' ExecStop=/home/kafka/kafka/bin/kafka-server-stop.sh Restart=on-abnormal [Install] WantedBy=multi-user.target 서비스 시작 및 확인 $ systemctl start kafka $ systemctl status kafka $ systemctl enable kafka $ systemctl start zookeeper $ systemctl status zookeeper $ systemctl enable zookeeper 카프카 모니터링 툴 UI for Apache Kafka라는 카프카 클러스터를 모니터링하고 관리하는 무료 오픈소스 웹 UI가 있습니다. Dashboard를 통해 브로커, 토픽, 파티션과 같은 카프카 클러스터의 현황을 확인할 수 있습니다. UI를 실행하려면 Docker 이미지를 사용하여 실행할 수 있습니다. 도커 이미지 : hub.docker.com/r/provectuslabs/kafka-ui 백그라운드에서 Docker 컨테이너를 시작합니다. docker run -p 8080:8080 \ -e KAFKA_CLUSTERS_0_NAME=local \ -e KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:9092 \ -d provectuslabs/kafka-ui:latest 이후 http://localhost:8080에서 웹 UI에 접속합니다. 환경변수를 이용해 추가구성이 가능합니다. Kafka 서버를 구성 후 재부팅을 했을 때 서비스가 제대로 실행되지 않는다면 /home/kafka/logs/meta.properties cluster.id 부분을 주석처리하고 서비스를 재시작하면 작동이 되는 걸 확인할 수 있습니다. 2023.02.13
k8s에서 외부 Ceph Storage Cluster를 기본 StorageClass로 사용하기 다른 용도로 사용 중인 Ceph Storage를 Kubernetes에서도 이어 사용할 수 있습니다. k8s에서 외부 Ceph Storage Cluster를 기본 StorageClass로 사용하기 Kubernetes에서 스토리지 클래스로 사용할 수 있는 스토리지 종류는 다양합니다. Local, AWS EBS, AzureFile, AzureDisk, CephFS, CephRBD, NFS, iSCSI, Glusterfs 등을 제공하고, 나열된 방식 외에도 많은 볼륨 플러그인을 사용할 수 있습니다. 본 포스팅은 별도로 구성된 Ceph 클러스터를 k8s에서 StorageClass로 사용하는 방법을 다루고 있습니다. Ceph Storage를 여러 목적으로 다양하게 사용하는 구성으로 적합합니다. Ceph-csi 설치 전에는 Ceph 을 k8s에서 사용하기 위해, 별도의 provisioner를 복잡하게 구성해야 했습니다. 최근 k8s의 정책 변화로 권장하고 있는 ceph-csi를 통해 간단하게 구성할 수 있습니다. ceph-csi는 git에서 제공하는 yaml 파일로도 구성할 수 있지만, 여기서는 helm을 통해 구성하겠습니다. chart 설정 파일 예제와, storage class, pod 등등 생성 시 참고 example은 git에서 다운로드할 수 있습니다. $ git clone https://github.com/ceph/ceph-csi.git (CephFS) CephFS를 스토리지 클래스로 사용 CephFS는 Ceph에서 제공하는 파일 스토리지입니다. ReadWriteMany 특성의 PVC를 생성할 수 있습니다. 공용 볼륨으로 쓰거나, 데이터 셋 저장 후 공유 목적으로 사용하기에 적합합니다. (CephFS) 환경 설정 파일 구성 설치 전에, 설정 파일을 구성합니다. 여기서는 csiConfig, secret, StorageClass 관련 설정만 미리 넣어 구성합니다. 미리 넣지 않고 추후 구성도 가능합니다. 설정 파일은 /ceph-csi/charts/ 경로의 values.yaml 파일을 참고할 수 있습니다.Ceph의 mon 정보와 keyring 정보는 이전 ceph 구성 포스팅을 참고하시면 됩니다. (k8s master) $ vi values.yaml csiConfig: - clusterID: "test-cephfs" monitors: - "192.168.0.138:6789" - "192.168.0.138:6789" - "192.168.0.141:6789" secret: create: true name: "ceph-fs-secret" adminID: "admin" adminKey: "AQD81LRjujj5ERAASy7HgGX92yusPCYDiJIOjg==" storageClass: create: true name: ceph-fs-sc annotations: storageclass.beta.kubernetes.io/is-default-class: "true" storageclass.kubesphere.io/supported-access-modes: '["ReadWriteOnce","ReadOnlyMany","ReadWriteMany"]' clusterID: "test-cephfs" fsName: "chunvol1" pool: "cephfs.chunvol1.data" provisionerSecret: ceph-fs-secret provisionerSecretNamespace: ceph-fs controllerExpandSecret: ceph-fs-secret controllerExpandSecretNamespace: ceph-fs nodeStageSecret: ceph-fs-secret nodeStageSecretNamespace: ceph-fs reclaimPolicy: Delete allowVolumeExpansion: true mountOptions: - discard 위 구성 파일에서는 3가지 구성을 포함하고 있습니다. helm 구성 시 csiConfig만 구성하고, secret과 storageclass는 추후 구성해도 상관없습니다. 1. csiConfig : ceph 클러스터의 서버 정보 (mon 서버 정보) 2. secret : ceph 클러스터의 연결 계정 정보 (keyring) 3. storageClass : k8s에 생성될 storageclass 정보 (CephFS) ceph-csi 차트 설치 및 제거 (k8s-master) ceph-csi-chart - helm repo 추가 $ helm repo add ceph-csi https://ceph.github.io/csi-charts $ helm search repo ceph-csi cephfs csi 설치 및 확인 $ kubectl create namespace "ceph-fs" $ helm install --namespace "ceph-fs" "ceph-fs-sc" ceph-csi/ceph-csi-cephfs -f values.yaml $ helm status "ceph-fs-sc" -n "ceph-fs" cephfs csi 제거 $ helm uninstall "ceph-fs-sc" --namespace "ceph-fs" $ kubectl delete namespace "ceph-fs" (CephFS) PVC 생성 PVC를 생성하면 자동으로 PV도 함께 생성되고 연결됩니다. PVC 생성 예제 파일도 마찬가지로 ceph-csi/example/에서 확인할 수 있습니다. $ vi cephfs-pvc01.yaml --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: cephfs-pvc01 spec: accessModes: - ReadWriteMany resources: requests: storage:5Gi storageClassName: csi-fs-sc $ kubectl apply -f cephfs-pvc01.yaml $ kubectl get pvc (CephFS) pod 생성 아래와 같이 Pod 생성 시 PVC를 연결할 수 있습니다. 관련 예제 파일은 ceph-csi/example/에서 확인할 수 있습니다. $ vi cephfs-pod01.yaml --- apiVersion: v1 kind:Pod metadata: name:csi-cephfs-test-pod spec: containers: - name: test-pod01 image: nginx volumeMounts: - name: test-pvc01 mountPath: /data volumes: - name: test-pvc01 persistentVolumeClaim: claimName: cephfs-pvc01 readOnly: false $ kubectl apply -f cephfs-pod01.yaml $ kubectl get pod -n default (CephFS) PVC IO 성능 테스트 1만개의 4k 파일 $ time cp -r /olddata /data/ real 0m2.608s user 0m0.055s sys 0m0.259s 1개의 4.4GB 파일 $ time cp -r /bigsize /data/ real 0m18.652s user 0m0.000s sys 0m3.515s (RBD) Ceph RBD를 스토리지 클래스로 사용 RBD는 Ceph에서 제공하는 블록 스토리지입니다. ReadWriteOnce 특성의 PVC를 생성할 수 있습니다. 대체적으로 CephFS 보다 성능이 높지만, 볼륨 공유가 안되는 블록 스토리지입니다. (RBD) Configmap 구성 파일 생성 CephFS 와 마찬가지로 helm 을 통해 csi-rbd 프로비저너를 설치합니다. 이번에는 구성 파일을 csiConfig, secret, storageClass 각각 별개로 구성하도록 하겠습니다. $ vi csiconfig.yaml csiConfig: - clusterID: "test-ceph-rbd" monitors: - "192.168.0.138:6789" - "192.168.0.140:6789" - "192.168.0.141:6789" (RBD) ceph-csi-rbd 설치 (k8s-master) ceph-csi-chart - helm repo 추가 $ helm repo add ceph-csi https://ceph.github.io/csi-charts $ helm search repo ceph-csi RBD 설치 및 확인 $ kubectl create namespace "ceph-rbd" $ helm install --namespace "ceph-rbd" "ceph-rbd-sc" ceph-csi/ceph-csi-rbd -f csiconfig.yaml $ helm status "ceph-rbd-sc" -n "ceph-rbd" RBD csi 제거 $ kubectl create namespace "ceph-rbd" $ helm uninstall "ceph-rbd-sc" --namespace "ceph-rbd" $ kubectl delete namespace "ceph-rbd" (RBD) RBD Secret 추가 $ vi secret.yaml apiVersion: v1 kind: Secret metadata: name: ceph-rbd-secret namespace: ceph-rbd stringData: userID: admin userKey: "AQD81LRjujj5ERAASy7HgGX92yusPCYDiJIOjg==" --- $ kubectl apply -f secret.yaml (RBD) StorageClass 추가 StorageCalss를 추가할 때 가장 중요한 건, csiConfigmap 구성 시 ClusterID가 같아야 하고, ceph에서 RBD 풀로 초기화한 Pool 정보가 정확해야 합니다. 그리고, 바로 위에서 생성한 secret 이름과 namespace도 매우 중요합니다. StorageClass는 관련 정보가 잘못되어도 생성됩니다. StorageClass가 생성되었는데도 불구하고, PVC 생성이 안된다면 StorageClass 정보 값이 잘못된 경우가 많습니다. $ vi storageclass.yaml apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: rbd annotations: storageclass.beta.kubernetes.io/is-default-class: "true" storageclass.kubesphere.io/supported-access-modes: '["ReadWriteOnce","ReadOnlyMany","ReadWriteMany"]' provisioner: rbd.csi.ceph.com parameters: clusterID: "test-ceph-rbd" pool: "rbdvol1" imageFeatures: layering csi.storage.k8s.io/provisioner-secret-name: ceph-rbd-secret csi.storage.k8s.io/provisioner-secret-namespace: ceph-rbd csi.storage.k8s.io/controller-expand-secret-name: ceph-rbd-secret csi.storage.k8s.io/controller-expand-secret-namespace: ceph-rbd csi.storage.k8s.io/node-stage-secret-name: ceph-rbd-secret csi.storage.k8s.io/node-stage-secret-namespace: ceph-rbd csi.storage.k8s.io/fstype: ext4 reclaimPolicy: Delete >allowVolumeExpansion: true mountOptions: - discard $ kubectl apply -f storageclass.yaml (RBD) PVC 생성 CephFS와 가장 큰 차이점은 PVC 생성 시 accessModes 값을 ReadWriteOnce로 구성했다는 것입니다. RBD는 ReadWriteMany로 구성할 수 없습니다. $ vi pvc.yaml --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: rbd-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: rbd $ kubectl apply -f pvc.yaml $ kubectl get pvc (RBD) pod 생성 및 확인 PVC까지 정상적으로 생성되었고, PVC의 상태가 bound로 확인된다면, Pod와 연결할 수 있습니다. RBD로 구성된 PVC는 1개의 Pod와 연결됩니다. $ vi pod.yaml --- apiVersion: v1 kind: Pod metadata: name: rbd-test-pod01 spec: containers: - name: web-server image: nginx volumeMounts: - name: rbd1 mountPath: /data volumes: - name: rbd1 persistentVolumeClaim: claimName: rbd-pvc readOnly: false $ kubectl apply -f pod.yaml $ kubectl exec -ti rbd-test-pod01 /bin/bash rdb-test-pod01> df -h (RBD) pod 생성 및 확인 PVC까지 정상적으로 생성되었고, PVC의 상태가 bound로 확인된다면, Pod와 연결할 수 있습니다. RBD로 구성된 PVC는 1개의 Pod와 연결됩니다. $ vi pod.yaml --- apiVersion: v1 kind: Pod metadata: name: rbd-test-pod01 spec: containers: - name: web-server image: nginx volumeMounts: - name: rbd1 mountPath: /data volumes: - name: rbd1 persistentVolumeClaim: claimName: rbd-pvc readOnly: false $ kubectl apply -f pod.yaml $ kubectl exec -ti rbd-test-pod01 /bin/bash rdb-test-pod01> df -h (RBD) Ceph 노드에서 이미지 생성 여부 확인 PVC 생성이 잘 되었다면, Ceph 노드에서 RBD 이미지가 생성된 것을 확인할 수 있습니다. 물론, Ceph Dashboard에서도 해당 내용 확인이 가능합니다. Ceph에서는 RBD 이미지이지만, 사용하는 클라이언트에서는 물리 디스크로 인식하게 됩니다. (ceph Bootstrap) $ rbd list rbdvol1 (RBD) RBD IO 성능 테스트 1만개의 4k 파일 $ time cp -r /olddata /data/ real 0m0.223s user 0m0.016s sys 0m0.198s 1개의 4.4GB 파일 $ time cp -r /bigsize /data/ real 0m15.778s user 0m0.007s sys 0m4.481s 2023.01.27
Kubernetes LoadBalancer 사용 (MetalLB) K8s LoadBalancer 사용을 위한 MetalLB Kubernetes LoadBalancer 사용 (MetalLB) k8s는 대다수의 서비스를 함께 배포하지만, 일부 서비스는 외부 서비스를 사용해야 합니다. 그중 대표적인게 네트워크 서비스 중 하나인 LoadBalancer입니다. k8s에서 제공하는 네트워크 모드는 clusterIP, NodePort, LoadBalancer 3가지입니다. 이 포스팅에서는 LoadBalancer 사용을 위해 MetalLB를 구성합니다. ARP 모드 활성화 Metal LB 사용을 위해 ARP 모드를 활성화합니다. $ kubectl edit configmap -n kube-system kube - proxy (수정전)strictARP : false (수정후)strictARP : true Metal LB 설치 Metal LB는 설치용 yaml 파일을 제공합니다. 매우 간단하게 설치할 수 있습니다. $ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml $ kubectl get all -n metallb-system Metal LB 구성 여기서는 IPAddressPool 을 2개 생성하고, L2 네트워크에 IPAddressPool을 등록하여 구성합니다. L2 네트워크에 직접 IP Pool을 구성하여 사용할 수도 있습니다. # IP풀 (ip-pool-01) 생성 $ vi ip-pool-01.yaml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ip-pool-01 namespace: metallb-system spec: addresses: - 192.168.0.70-192.168.0.79 # IP풀 (ip-pool-01) 생성 $ vi ip-pool-02.yaml apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: ip-pool-02 namespace: metallb-system spec: addresses: - 192.168.1.180-192.168.1.189 # L2네트워크 생성 $ vi network-l2-lb-01.yaml apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name:network-l2-lb-01 namespace: metallb-system spec: ipAddressPools: - ip-pool-01 - ip-pool-02 #적용 $ kubectl apply -f ip-pool-01.yaml $ kubectl apply -f ip-pool-02.yaml kubectl apply -f network-l2-lb-01.yaml (Test) nginx-deploy 생성 Metal LB가 구성되었으니 테스트해 보겠습니다. nginx deployment를 생성하고 replicas를 3개로 구성합니다. $ vi test-nginx-deploy.yaml apiVersion: apps/v1 kind:Deployment metadata: name: test-nginx-deploy labels: app:nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: test-nginx aimage: nginx ports: - containerPort:80 $ kubectl apply -f test-nginx-deploy.yaml (Test) nginx-svc 생성 생성한 deploy의 서비스를 생성합니다. 서비스 타입을 LoadBalancer로 구성합니다. $ vi test-nginx-svc.yaml apiVersion: v1 kind:Service metadata: name: est-nginx-svc labels: app:nginx spec: ports: selector: - port:8080 targetPort: 80 protocol: TCP selector: app: nginx type: LoadBalancer $ kubectl apply -f test-nginx-svc.yaml (Test) svc 확인 서비스가 생성되면 서비스 목록에서 [CLUSTER-IP]와 [EXTERNAL-IP]가 둘 다 생성되는 것을 확인할 수 있습니다. [EXTERNAL-IP]는 위에서 생성한 IP 풀 내에서 할당되고, 외부에서 접속이 가능합니다. $ kubectl get svc -n default 기존 서비스 수정 기존 서비스의 경우 kubectl edit를 이용하여 [type: ClusterIP]를 [type: LoadBalancer]로 수정하면 적용됩니다. 2023.01.27
WSL을 이용하여 도커 사용 WSL을 이용하여 도커 사용 WSL 활용 방법 WSL(Windows Subsystem for Linux)의 정의 · Windows 환경에서도 리눅스를 사용할 수 있다. 기존에 사용하였던 듀얼 부팅. VM 등 리눅스를 설치해서 사용을 하였는 때 불편한 점들을 개선하여 더 효율적으로 사용이 가능하다. · WSL(Windows subsystem for Linux)은 windows 하위 시스템으로써 다음 설정으로 Linux을 사용할 수 있다. 필요한 요구 사항 Windows 10 버전 2004 이상(빌드 19041 이상) 또는 Windows 11을 실행해야 합니다. WSL 설치하기 PowerShell을 관리자로 실행합니다. WSL을 설치합니다. wsl --install ※참고 위의 명령은 WSL이 전혀 설치되지 않은 경우에만 작동합니다. wsl --install을 실행하고 WSL 도움말 텍스트를 보는 경우 wsl --list --online을 실행하여 사용 가능한 배포판 목록을 확인하고wsl --install -d < DistroName >을 실행하여 배포판을 설치해 보세요. WSL을 제거하려면 WSL의 레거시 버전 제거 또는 Linux 배포판 등록 취소 또는 제거를 참조하세요. 출처: https://learn.microsoft.com/ko-kr/windows/wsl/install Windows Terminal 설치 Microsoft Store에서 Windows Terminal을 검색하여 설치하시면 됩니다. WSL을 사용하여 Docker 설치 터미널에서 Docker 관련 패키지를 설치합니다. sudo apt-get install \ apt-transport-https \ curl \ gnupg \ lsb-release Docker 공식 GPG key를 추가합니다. curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudogpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg repository를 설정합니다. echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null Docker 최신 버전으로 설치합니다. sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin Docker 실행 sudo service docker start 컨테이너 실행하기 docker run [옵션] [이미지] [명령] [매개 변수] 옵션 설명 -d detached mode 흔히 말하는 백그라운드 모드 -p 호스트와 컨테이너의 포트를 연결 (포워딩) -v 호스트와 컨테이너의 디렉터리를 연결 (마운트) -e 컨테이너 내에서 사용할 환경 변수 설정 -name 컨테이너 이름 설정 -rm 프로세스 종료 시 컨테이너 자동 제거 -it -i와 -t를 동시에 사용한 것으로 터미널 입력을 위한 옵션 -link 컨테이너 연결 [컨테이너명:별칭] docker에 ubuntu 설치하기 sudo docker search ubuntu NAME DESCRIPTION STARS OFFICIAL AUTOMATED ubuntu Ubuntu is a Debian-based Linux operating sys… 15430 [OK] websphere-liberty WebSphere Liberty multi-architecture images… 291 [OK] ubuntu-upstart DEPRECATED, as is Upstart (find other proces… 112 [OK] neurodebian NeuroDebian provides neuroscience research s… 98 [OK] ubuntu/nginx Nginx, a high-performance reverse proxy & we… 73 open-liberty Open Liberty multi-architecture images based… 56 [OK] ubuntu/apache2 Apache, a secure & extensible open-source HT… 51 ubuntu-debootstrap DEPRECATED; use"ubuntu" instead 50 [OK] ubuntu/squid Squid is a caching proxy for the Web. Long-t… 49 ubuntu/mysql MySQL open source fast, stable, multi-thread… 41 ubuntu/bind9 BIND 9 is a very flexible, full-featured DNS… 41 ubuntu/prometheus Prometheus is a systems and service monitori… 34 ubuntu/postgres PostgreSQL is an open source object-relation… 23 ubuntu/kafka Apache Kafka, a distributed event streaming… 19 ubuntu/redis Redis, an open source key-value store. Long-… 16 ubuntu/prometheus-alertmanager Alertmanager handles client alerts from Prom… 8 ubuntu/grafana Grafana, a feature rich metrics dashboard & … 6 ubuntu/memcached Memcached, in-memory keyvalue store for smal… 5 ubuntu/zookeeper ZooKeeper maintains configuration informatio… 5 ubuntu/dotnet-runtime Chiselled Ubuntu runtime image for .NET apps… 5 ubuntu/dotnet-deps Chiselled Ubuntu for self-contained .NET & A… 5 ubuntu/telegraf Telegraf collects, processes, aggregates & w… 4 ubuntu/cortex Cortex provides storage for Prometheus. Long… 3 ubuntu/dotnet-aspnet Chiselled Ubuntu runtime imagefor ASP.NET a… 3 ubuntu/cassandra Cassandra, an open source NoSQL distributed … 2 ubuntu 이미지 받기 sudo docker pull ubuntu docker 이미지 확인 sudo docker images 컨테이너 생성 docker create --name ubuntu ubuntu_test ※ 이처럼 Windows 환경에서도 WSL을 이용하여 리눅스를 사용할 수 있고 딥러닝 및 개발 환경도 구성하여 이용할 수 있다. 2023.01.12
의료 데이터 분석/설계를 위한 OHDSI CDM 기반의 의료 데이터 분석/설계 오픈소스 OHDSI Atlas 의료 데이터 분석/설계를 위한 OHDSI OHDSI? CDM? OHDSI는 OMOP CDM 기반의 분산 연구망을 표준 및 관련 소프트웨어 도구를 만들고 유지 관리하는 국제적인 비영리 단체입니다. CDM 기반의 오픈소스를 운영하고 있습니다. OHDSI와 누적된 의료 데이터를 활용하여 여러 분석 설계 및 실행을 진행할 수 있습니다. OHDSI Atlas 사용 환경 구성을 위해 OHDSI에서 제공하는 컨테이너를 활용하여 구성하였고, 이를 공유합니다. DB는 PostgreSQL로 구성하였고, 사용자를 위한 Jupyter와 R 등의 분석 컨테이너를 포함하였습니다. 필요 패키지 ●OHDSI WEBAPI ●OHDSI Atlas ●OHDSI Achilles ●R ●PostgreSQL ●Jupyter ●Docker OS 설치 CentOS 7.9 (최소설치) 방화벽 해제 (local)$ systemctl disable firewalld (local)$ systemctl stop firewalld Docker 설치 (local)$ yum -y update (local)$ yum install yum-utils device-mapper-persistent-data lvm2 (local)$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo (local)$ yum install docker-ce (local)$ systemctl start docker&&systemctl enable docker 작업 폴더 생성 (local)$ mkdir /sourcedata (local)$ mkdir /sourcedata/data (local)$ mkdir /workspace1 (local)$ mkdir /workspace2 (local)$ mkdir /db1 (local)$ mkdir /db2 docker-compose 설치 (local)$ curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose (local)$ chmod +x /usr/local/bin/docker-compose (local)$ ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose SQL 테이블 데이터 다운로드 (local)$ yum install -y git (local)$ cd /sourcedata (local)$ git clone -b v5.3.2 https://github.com/OHDSI/CommonDataModel.git ATLAS webtool compose 파일 다운로드 (local)$ cd /sourcedata (local)$ git clone https://github.com/OHDSI/Broadsea.git PostgreSQL 컨테이너 생성 (local)$ docker run --name postgres1 -d --restart unless-stopped --shm-size=1g \ -p 1040:5432 -e POSTGRES_PASSWORD=Itmaya2009! \ -v /db1:/var/lib/postgresql/data \ -v /sourcedata:/sourcedata \ -v /workspace1:/workspace postgres **--shm-size-=1g 옵션을 실 서버에 구성할때는 32g로 구성하여 성능 확보 필요함 PostgreSQL DB 구성 (local)$ docker exec -ti postgres1 bash (postgres1)$ psql -U postgres (postgres1 #)# CREATE USER atlas PASSWORD 'Itmaya2009!' SUPERUSER; (postgres1 #)# CREATE DATABASE atlasdb OWNER atlas; (postgres1 #)# \c atlasdb (postgres1 #DB)# CREATE SCHEMA cdm; (postgres1 #DB)# CREATE SCHEMA ohdsi; (postgres1 #DB)# CREATE SCHEMA results; (postgres1 #DB)# exit DB 테이블 생성 및 데이터 복사 (local)$ docker exec -ti postgres1 bash 테이블 쿼리 생성 (postgres1)$ cd /sourcedata/CommonDataModel/inst/ddl/5.3/postgresql/ (postgres1)$ echo 'SET search_path to cdm;' | cat - OMOPCDM_postgresql_5.3_ddl.sql > 1.sql (postgres1)$ echo 'SET search_path to cdm;' | cat - OMOPCDM_postgresql_5.3_primary_keys.sql > 2.sql (postgres1)$ echo 'SET search_path to cdm;' | cat - OMOPCDM_postgresql_5.3_constraints.sql > 3.sql (postgres1)$ echo 'SET search_path to cdm;' | cat - OMOPCDM_postgresql_5.3_indices.sql > 4.sql (postgres1)$ sed -i 's/\@cdmDatabaseSchema/cdm/g' /sourcedata/CommonDataModel/inst/ddl/5.3/postgresql/1.sql (postgres1)$ sed -i 's/\@cdmDatabaseSchema/cdm/g' /sourcedata/CommonDataModel/inst/ddl/5.3/postgresql/2.sql (postgres1)$ sed -i 's/\@cdmDatabaseSchema/cdm/g' /sourcedata/CommonDataModel/inst/ddl/5.3/postgresql/3.sql (postgres1)$ sed -i 's/\@cdmDatabaseSchema/cdm/g' /sourcedata/CommonDataModel/inst/ddl/5.3/postgresql/4.sql 테이블 생성 (1.sql) (postgres1)$ psql -U atlas -d atlasdb -a -f 1.sql 권한 변경 (2.sql) (postgres1)$ psql -U atlas -d atlasdb -a -f 2.sql 권한 변경 (3.sql) (postgres1)$ psql -U atlas -d atlasdb -a -f 3.sql 테이블 인덱스 생성 (4.sql) (postgres1)$ psql -U atlas -d atlasdb -a -f 4.sql (postgres1)$ exit webtools, atlas, rstudio 컨테이너 생성 docker compose 구성 (local)$ echo "version: '2' services: broadsea-methods-library: image: ohdsi/broadsea-methodslibrary container_name: achilles1 ports: - "1020:8787" - "1050:6311" - "1060:1444" volumes: - /workspace1:/workspace environment: -PASSWORD=Itmaya2009! broadsea-webtools: image: ohdsi/broadsea-webtools container_name: atlas1 ports: - "1010:8080" volumes: - .:/tmp/drivers/:ro - /workspace1:/workspace - /sourcedata/Broadsea/config-local.js:/usr/local/tomcat/webapps/atlas/js/config-local.js:ro environment: -WEBAPI_URL=http://192.168.0.249:1010 - env=webapi-postgresql - security_enabled=false - security_origin=* - datasource_driverClassName=org.postgresql.Driver - datasource_url=jdbc:postgresql://192.168.0.249:1040/atlasdb - datasource.cdm.schema=cdm - datasource.ohdsi.schema=ohdsi - datasource_username=atlas - datasource_password=Itmaya2009! - spring.jpa.properties.hibernate.default_schema=ohdsi - spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect - spring.batch.repository.tableprefix=ohdsi.BATCH_ - flyway_datasource_driverClassName=org.postgresql.Driver - flyway_datasource_url=jdbc:postgresql://192.168.0.249:1040/atlasdb - flyway_schemas=ohdsi - flyway.placeholders.ohdsiSchema=ohdsi - flyway_datasource_username=atlas - flyway_datasource_password=Itmaya2009! - flyway.locations=classpath:db/migration/postgresql" > /sourcedata/Broadsea/postgresql/docker-compose.yml (local)$ cd /sourcedata/Broadsea/postgresql/ (local)$ docker-compose up -d achilles 컨테이너 ssh 구성 (local)$ docker exec -ti achilles1 bash (achilles1)$ apt update (achilles1)$ apt install -y openssh-server vim (achilles1)$ sed -i 's/\#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config (achilles1)$ sed -i 's/\#Port 22/Port 1444/g' /etc/ssh/sshd_config (achilles1)$ passwd root (achilles1)> 패스워드 입력 (Itmaya2009!) (achilles1)$ service ssh start (achilles1)$ exit atlas DB 연동 (local)$ echo "ALTER TABLE ohdsi.source ALTER COLUMN is_cache_enabled SET DEFAULT true; truncate ohdsi.source; truncate ohdsi.source_daimon; INSERT INTO ohdsi.source( source_id, source_name, source_key, source_connection, source_dialect) VALUES (1, 'OHDSI CDM V5 Database', 'OHDSI-CDMV5', 'jdbc:postgresql://192.168.0.249:1040/atlasdb?user=atlas&password=Itmaya2009!', 'postgresql'); INSERT INTO ohdsi.source_daimon( source_daimon_id, source_id, daimon_type, table_qualifier, priority) VALUES (1, 1, 0, 'cdm', 2); INSERT INTO ohdsi.source_daimon( source_daimon_id, source_id, daimon_type, table_qualifier, priority) VALUES (2, 1, 1, 'cdm', 2); INSERT INTO ohdsi.source_daimon( source_daimon_id, source_id, daimon_type, table_qualifier, priority) VALUES (3, 1, 2, 'results', 2); INSERT INTO ohdsi.source_daimon( source_daimon_id, source_id, daimon_type, table_qualifier, priority) VALUES (4, 1, 3, 'cdm', 2);" > /sourcedata/CommonDataModel/inst/ddl/5.3/postgresql/5.sql (local)$ docker exec -ti postgres1 bash (postgres1)$ psql -U atlas -d atlasdb -a -f /sourcedata/CommonDataModel/inst/ddl/5.3/postgresql/5.sql (postgres1)$ exit Atlas 컨테이너 재시작 (local)$ docker restart atlas1 Achilles 버전 변경 (local)$ docker exec -ti achilles1 bash (achilles1)$ R (achilles1)> remotes::install_github('OHDSI/OhdsiRTools@v2.0.2') (achilles1)>> skip Enter (achilles1)> remotes::install_github('OHDSI/Achilles@v1.7.0') (achilles1)>> skip Enter *** 분석 결과 테이블 생성 (데이터 부재로 오류 발생함. 데이터 없이는 진행하지 말 것) (achilles1)> library(Achilles) (achilles1)> connectionDetails achilles(connectionDetails, cdmDatabaseSchema = "cdm", resultsDatabaseSchema="results", cdmVersion = "5.3.2") (achilles1)> quit() (achilles1)$ exit Jupyter Notebook 구성 jupyter 컨테이너 생성 (local)$ docker run -v /sourcedata:/sourcedata -v /workspace1:/workspace --name=jupyter1 -e GRANT_SUDO=yes --user root -p 1030:8888 -d jupyter/datascience-notebook 패스워드 로그인 설정 (local)$ docker exec -ti jupyter1 bash (jupyter1)$ apt update (jupyter1)$ apt install -y vim (jupyter1)$ ipython (jupyter1)> from notebook.auth import passwd (jupyter1)> passwd() (jupyter1)> Itmaya2009! (jupyter1)> Itmaya2009! (jupyter1)> exit (출력되는 password 보안키를 복사) (jupyter1)$ echo "c.NotebookApp.password_required = True" >> ~/.jupyter/jupyter_notebook_config.py (jupyter1)$ echo "c.NotebookApp.password = '복사한 보안키'" >> ~/.jupyter/jupyter_notebook_config.py (보안키 잘 들어갔는지 vi 로 ~/.jupyter/jupyter_notebook_config.py 파일 마지막줄 확인) (jupyter1)$ exit (local)$ docker restart jupyter1 서비스 인프라 확인 Port 22 : Server Local (CentOS 7.9 Base) ( user:root / password:Itmaya2009! ) atlas config #1 공용볼륨 : /workspace1:/workspace Port 1010 : Atlas (atlas1 container) Port 1020 : R studio (achilles1 container) ( user:rstudio / password:Itmaya2009! ) Port 1030 : Jupyter Notebook (jupyter1 container) ( password:Itmaya2009! ) Port 1040 : PostgreSQL (postgres1 container) ( DB:atlasdb / user:atlas / password:Itmaya2009! ) - schema (cdm, ohdsi, results) Port 1050 : R Serve (achilles1 container) Port 1060 : Dev SSH (achilles1 container) ( user:root / password:Itmaya2009! ) atlas config #2 공용볼륨 : /workspace2:/workspace Port 2010 : Atlas (atlas2 container) Port 2020 : R studio (achilles2 container) ( user:rstudio / password:Itmaya2009! ) Port 2030 : Jupyter Notebook (jupyter2 container) ( password:Itmaya2009! ) Port 2040 : PostgreSQL (postgres2 container) ( DB:atlasdb / user:atlas / password:Itmaya2009! ) - schema (cdm, ohdsi, results) Port 2050 : R Serve (achilles1 container) Port 2060 : Dev SSH (achilles1 container) ( user:root / password:Itmaya2009! ) 서비스 동작 확인 WebAPI : http://192.168.0.249:1010/WebAPI/source/sources atlas : http://192.168.0.249:1010/atlas rStudio : http://192.168.0.249:1020/ ( user:rstudio / password:Itmaya2009! ) Jupyter : http://192.168.0.249:1030/ ( password:Itmaya2009! ) SSH : ssh root@192.168.0.249 -p 1060 ( user:root / password:Itmaya2009! ) DB : jdbc:postgresql://192.168.0.249:1040/atlasdb ( user:atlas / password:Itmaya2009! ) - schema (cdm, ohdsi, results) 2022.12.20
PLEASE WAIT WHILE LOADING...