태그 보관물: MySQL

3-Tier container environment configuration using Kubernetes (NginX/Tomcat/MySQL)

쿠버네티스를 활용한 3-Tier 컨테이너 환경 구성을 해보고자 한다. 구성은 도커와 동일하게 아래와 같이 간다.

3-Tier container environment configuration using Docker(NginX/Tomcat/MySQL)

이번에는 구성 시에 1-Container에 WEB/WAS/DB Pod를 각각 띄울 예정이다.

동일한 컨테이너에서 기동하기 때문에 서로에 대한 IP는 변하지 않을 것이고 IP Address는 localhost로 설정해주어야 한다.

그렇기 때문에!!

– WEB-WAS 사이의 연동 설정에서 IP를 localhost로 변경

– WAS-DB 사이의 연동 설정(어플리케이션 부분)에서 DB IP를 localhost로 변경

해주어야한다.. 그렇다면 이미지 부터 다시 말아보자.

1. WEB 구성

1-1. NginX의 WAS 연동 설정 파일에서 IP Address를 localhost로 변경 후 다시 이미지 생성

> $ vi /root/nginx-for-petclinic/nginx/conf

17 http {
18     upstream was-list {
19         #server tomcat-petclinic:8080;
20         server localhost:8080;
21     }
22
23     include       mime.types;
24     default_type  application/octet-stream;

1-2. Dockerfile을 이용하여 이미지 생성

root@master:~/nginx-for-petclinic# pwd
/root/nginx-for-petclinic
root@master:~/nginx-for-petclinic# docker build -t nginx-petclinic:2.0 .

# 이미지 생성 후, 확인

root@master:~/nginx-for-petclinic# docker images
REPOSITORY                               TAG       IMAGE ID       CREATED         SIZE
nginx-petclinic                          2.0       1f34b3ccac6d   5 seconds ago   133MB

1-3. 이미지를 Dockerhub에 저장

> 내가 생성한 이미지를 이따 yaml파일에서 로드할  수 있도록..

root@master:~# docker tag nginx-petclinic:2.0 ghkd5216/nginx-petclinic:2.0
root@master:~# docker push ghkd5216/nginx-petclinic:2.0

The push refers to repository [docker.io/ghkd5216/nginx-petclinic]
52efdeec58ec: Pushed
201e7ba1790a: Pushed
9959a332cf6e: Layer already exists
f7e00b807643: Layer already exists
f8e880dfc4ef: Layer already exists
788e89a4d186: Layer already exists
43f4e41372e4: Layer already exists
e81bff2725db: Layer already exists
2.0: digest: sha256:15cf195c6e6575d744fa0eb07b429d0db3d99f61

2. WAS 구성

2-1. WAS에서는 AP쪽에 DB 설정이 있기 때문에 소스 빌드 및 해당 소스가 디플로이된 이미지를 다시 생성해야 한다.

> $vi /root/spring-framework-for-petclinic/pom.xml

> 515번 라인과 같이 localhost로 변경해주면 된다.

509             <id>MySQL</id>
510             <properties>
511                 <db.script>mysql</db.script>
512                 <jpa.database>MYSQL</jpa.database>
513                 <jdbc.driverClassName>com.mysql.jdbc.Driver</jdbc.driverClassName>
514                 <!–<jdbc.url>jdbc:mysql://mysql-petclinic:3306/petclinic?useUnicode=true</jdbc.url>–>
515                 <jdbc.url>jdbc:mysql://localhost:3306/petclinic?useUnicode=true</jdbc.url>
516                 <jdbc.username>root</jdbc.username>
517                 <jdbc.password>petclinic</jdbc.password>
518             </properties>

2-2. 소스 빌드를 위한 자바 변경

> 자바 버전이 1.8이 되도록 수정

root@master:~/spring-framework-for-petclinic# sudo update-java-alternatives –jre-headless –jre –set java-1.8.0-openjdk-amd64

root@master:~/spring-framework-for-petclinic# java -version
openjdk version “1.8.0_292”
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)

2-3. 소스 빌드

> 소스를 빌드하고 나면, 현 디렉토리에 target 안에 petclinic.war라는 소스 파일이 빌드되어 있을 것이다.

root@master:~/spring-framework-for-petclinic# mvn clean package -Dmaven.test.skip=true -P MySQL

…(중략)

[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time:  13.144 s
[INFO] Finished at: 2021-11-16T18:04:01+09:00
[INFO] ————————————————————————

2-4. WAS 이미지 생성

> 이제 만든 소스를 활용하여 tomcat 이미지를 만들어보도록 하자.

우선 이미지 생성을 위해 Dockerfile을 생성하고 위에서 만들었던 petclinic.war 파일을 Dockerfile 디렉토리에 위치시킨다.

root@master:/home/dockerfile/petclinic# pwd
/home/dockerfile/petclinic
root@master:/home/dockerfile/petclinic# ls -arlt
total 40644
drwxr-xr-x 5 root root     4096 11월  7 14:06 ..
-rw-r–r– 1 root root 41605349 11월  7 14:06 petclinic.war
-rw-r–r– 1 root root       64 11월  7 14:06 Dockerfile
drwxr-xr-x 2 root root     4096 11월  7 14:06 .

==================================================
하기는 Dockerfile 내용이다.
==================================================
root@master:/home/dockerfile/petclinic# cat Dockerfile
From tomcat:8-jre8
ADD petclinic.war /usr/local/tomcat/webapps/

위와 같이 준비가 되었다면 이제 해당 위치에서 이미지 빌드를 하면 된다.

커맨드는 아래와 같다.

root@master:/home/dockerfile/petclinic# docker build -t tomcat-petclinic:2.0 .
Sending build context to Docker daemon  41.61MB
Step 1/2 : From tomcat:8-jre8
—> cff25871f024
Step 2/2 : ADD petclinic.war /usr/local/tomcat/webapps/
—> 1c6d007012d5
Successfully built 1c6d007012d5
Successfully tagged tomcat-petclinic:2.0

2-5. 이미지를 Dockerhub에 저장

> 내가 생성한 이미지를 이따 yaml파일에서 로드할  수 있도록..

root@master:~# docker tag tomcat-petclinic:2.0 ghkd5216/tomcat-petclinic:2.0
root@master:~# docker push ghkd5216/tomcat-petclinic:2.0
The push refers to repository [docker.io/ghkd5216/tomcat-petclinic]
3fe16f1fe077: Pushed
7a1149e8d0d8: Layer already exists
f3d15ade5c54: Layer already exists
80ac7083a323: Layer already exists
01de28a83f3f: Layer already exists
74a293db1084: Layer already exists
68c1e7509c65: Layer already exists
6ccd0e6bdf7a: Layer already exists
9f9f651e9303: Layer already exists
0b3c02b5d746: Layer already exists
62a747bf1719: Layer already exists
2.0: digest: sha256:7ee8909691df00b211aa42f1605062019422b0d93d52053d4ad01034390e04a7 size: 2631

3. YAML 파일 생성

이제 이미지도 준비되었고, yaml 파일만 생성하여 기동해보면 된다.
도커와는 다르게 쿠버네티스의 경우에는 쿠버네티스 클러스터 내에서 동작하기 때문에 생성된 컨테이너의 IP 또한 클러스터 내의 CNI 네트워크 대역으로 할당된다.

그렇기 때문에 외부에서 해당 컨테이너에 접근하여 서비스를 호출하려면 Service를 통해 가능하다. AWS나 GCP같은 Public Cloud의 경우에는 Service에서 LoadBalnancer를 제공하여 외부로 노출할 IP를 할당 받지만, 우리가 테스트하는 방식과 같이 Baremetal(On-Premise) 환경에서는 LoadBalancer 기능이 없다. 그래서 LoadBalancer타입을 지원하게끔 하기 위해 MetalLB라는 놈을 사용해주어야 한다.

먼저 metalb을 설치해보면 아래와 같다.

root@master:~/yaml# kubectl apply -f  https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml

=================================
metallb.yaml 파일을 이용하여 파드와 기타 등등의 서비스를 실행한다.
이후, metallb-system 네임스페이스에 있는 리소스들을 조회해본다.
=================================

root@master:~/yaml# kc get all -n metallb-system

NAME                              READY   STATUS    RESTARTS   AGE
pod/controller-675d6c9976-d5k57   1/1     Running   0          9s
pod/speaker-h4l8n                 1/1     Running   0          9s
pod/speaker-rm54l                 1/1     Running   0          9s

NAME                     DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR                 AGE
daemonset.apps/speaker   2         2         2       2            2           beta.kubernetes.io/os=linux   9s

NAME                         READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/controller   1/1     1            1           9s

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/controller-675d6c9976   1         1         1       9s

이제 3-Tier환경의 컨테이너를 생성할 차례다.

yaml 파일의 경우 아래와 같다.

모든 항목들을 세세히 설명할 수는 없고 하나씩 찾아보면 기본적인 설정(포트/환경변수)만 되어있음을 볼 수 있다.

이 글에서는 가볍게 구성해보는 것이기 때문에 다음 글에서 좀 더 yaml 문법이나 파라미터 값을 공부해보아야 겠다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: petclinic-deployment
  namespace: default
  labels:
    app: petclinic-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
       app: petclinic-app
  template:
    metadata:
      labels:
        app: petclinic-app
    spec:
      containers:
      - image: mysql:5.7.8
        imagePullPolicy: Always
        name: mysql-petclinic
        ports:
        - containerPort: 3306
          protocol: TCP
        env:
        - name: MYSQL_ROOT_PASSWORD
          value: petclinic
        - name: MYSQL_DATABASE
          value: petclinic
      - image: docker.io/ghkd5216/nginx-petclinic:2.0
        imagePullPolicy: Always
        name: nginx-petclinic
        ports:
        - containerPort: 80
          protocol: TCP
      - image: docker.io/ghkd5216/tomcat-petclinic:2.0
        imagePullPolicy: Always
        name: tomcat-petclinic
        env:
        - name: JAVA_OPTS
          value: "-Xms512m -Xmx512m"
        ports:
        - containerPort: 8080
          protocol: TCP
      restartPolicy: Always

---

apiVersion: v1
kind: Service
metadata:
  name: petclinic-svc
spec:
  type: LoadBalancer
  selector:
    app: petclinic-app
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80


---

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.1.240-192.168.1.250

> 제일 하단에 metallb 관련 설정을 보면 addresses 범위 안에서 외부로 노출할 ExternalIP 대역을 설정할 수 있다.

이제 만든 yaml 파일을 실행하여 보자!!

4. Kubernetes를 통한 컨테이너 배포

root@master:~/yaml# kc apply -f petclinic-app.yaml
deployment.apps/petclinic-deployment created
service/petclinic-svc created
configmap/config created

root@master:~/yaml# kc get all
NAME                                        READY   STATUS    RESTARTS   AGE
pod/petclinic-deployment-86dc87794d-j69mm   3/3     Running   0          24s

NAME                    TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE
service/kubernetes      ClusterIP      10.96.0.1        <none>           443/TCP        13d
service/petclinic-svc   LoadBalancer   10.109.251.153   192.168.56.240   80:30560/TCP   24s

NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/petclinic-deployment   1/1     1            1           24s

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/petclinic-deployment-86dc87794d   1         1         1       24s

> 위와 같이 LoadBalancer 타입의 Service가 생성되어 External-IP를 할당하여 외부로 노출하는 것을 볼 수 있다.

이제 모든 준비가 끝났다.

실제로 외부의 웹 브라우저에서 클라이언트 입장으로 서비스를 호출해보자. 호출 url은 EXTERNAL_IP:[LB PORT]/petclinic 이다.

나의 경우에는 http://192.168.56.240:80/petclinic/으로 호출하면 된다.

5. 서비스 호출

 

 

> 외부 노출 IP로 정상적으로 접근 가능하다. 몇 가지 업무 테스트를 해보면,

 

 

정상적으로 데이터가 DB에 저장되는 것을 볼 수 있다.

3-Tier container environment configuration using Docker(NginX/Tomcat/MySQL)

이번 글에서는 Docker를 사용하여 간단한 3-Tier 컨테이너 환경을 구성해보고자 한다.

– WEB = NginX

– WAS = Tomcat

– DB = MySQL

구성은 WAS -> WEB -> DB 순으로 하도록 한다.

우선,  WAS 부터 구성해보도록 하자.

1. WAS 구성

1-1. Github에 올라가 있는 어플리케이션 소스 다운로드

> 소스를 다운받을 디렉토리 생성 후 Git 저장소에서 소스를 Pull 한다.

root@master:~# mkdir -p /home/src
root@master:~# cd /home/src
root@master:/home/src#

root@master:/home/src# git clone https://github.com/Hwang-sangyeon/spring-framework-for-petclinic.git
Cloning into ‘spring-framework-for-petclinic’…
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 1.89 MiB | 4.96 MiB/s, done.

1-2. JDK와 Maven 설치

> 소스를 컴파일 하기 위해 OpenJDK와 Maven을 설치한다.

root@master:~# sudo apt-get install openjdk-8-jdk maven

(중략)

update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/bin/unpack200 to provide /usr/bin/unpack200 (unpack200) in auto mode
update-alternatives: using /usr/lib/jvm/java-11-openjdk-amd64/lib/jexec to provide /usr/bin/jexec (jexec) in auto mode
Setting up libxdmcp-dev:amd64 (1:1.1.3-0ubuntu1) …
Setting up x11proto-core-dev (2019.2-1ubuntu1) …
Setting up libxcb1-dev:amd64 (1.14-2) …
Setting up libx11-dev:amd64 (2:1.6.9-2ubuntu1.2) …
Setting up libxt-dev:amd64 (1:1.1.5-1) …

1-3. JAVA_HOME 설정

> 현재 java -version으로 버전 확인 시 설치한 자바로 설정되어 있지 않기 때문에 아래와 같이 변경이 필요하다.

root@master:/home/src# sudo update-java-alternatives –list
java-1.11.0-openjdk-amd64      1111       /usr/lib/jvm/java-1.11.0-openjdk-amd64
java-1.8.0-openjdk-amd64       1081       /usr/lib/jvm/java-1.8.0-openjdk-amd64
root@master:/home/src#
root@master:/home/src#
root@master:~# sudo update-java-alternatives –jre-headless –jre –set java-1.8.0-openjdk-amd64

root@master:/home/src# java -version
openjdk version “1.8.0_292”
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)

1-4. 소스 Build

> 이제 소스와 컴파일 할 JDK와 maven도 준비되었기 때문에 Compile을 해보도록 하자

소스 경로에 들어가 압축을 풀고 아래와 같이 빌드를 진행해준다.

빌드 전에 잠시 소스 수정이 필요하다.
pom.xml에 mysql 연동 부분에 localhost:3306을 mysql-petclinic:3306으로 수정하자.
was와 db가 다른 컨테이너로 기동되기 때문에 localhost를 인식할 수 없다.
그러나 mysql-petclinic은 컨테이너 명으로 link가 걸려 통신이 가능하다..

root@master:/home/src/spring-framework-for-petclinic/spring-framework-for-petclinic# mvn clean package -Dmaven.test.skip=true -P MySQL

…(중략)

[INFO] ————————————————————————
[INFO] BUILD SUCCESS
[INFO] ————————————————————————
[INFO] Total time:  16.802 s
[INFO] Finished at: 2021-11-07T13:54:37+09:00
[INFO] ————————————————————————

=========================================================================
빌드를 하고 나면, 소스 경로 하위의 target 디렉토리에 petclinic.war 소스 파일이 생성된다.

root@master:/home/src/spring-framework-for-petclinic/spring-framework-for-petclinic/target# ls -arlt|grep petclinic.war
-rw-r–r– 1 root root 41605349 11월  7 13:54 petclinic.war

1-5. WAS 이미지 생성

> 이제 만든 소스를 활용하여 tomcat 이미지를 만들어보도록 하자.

우선 이미지 생성을 위해 Dockerfile을 생성하고 이전에 만들었던 petclinic.war 파일을 같은 디렉토리에 위치시킨다.

root@master:/home/dockerfile/petclinic# pwd
/home/dockerfile/petclinic
root@master:/home/dockerfile/petclinic# ls -arlt
total 40644
drwxr-xr-x 5 root root     4096 11월  7 14:06 ..
-rw-r–r– 1 root root 41605349 11월  7 14:06 petclinic.war
-rw-r–r– 1 root root       64 11월  7 14:06 Dockerfile
drwxr-xr-x 2 root root     4096 11월  7 14:06 .

하기는 Dockerfile 내용이다.
root@master:/home/dockerfile/petclinic# cat Dockerfile
From tomcat:8-jre8
ADD petclinic.war /usr/local/tomcat/webapps/

위와 같이 준비가 되었다면 이제 해당 위치에서 이미지 빌드를 하면 된다.

커맨드는 아래와 같다.

root@master:~/docker/tomcat-test# docker build -t tomcat-petclinic .
Sending build context to Docker daemon  41.61MB
Step 1/2 : From tomcat:8-jre8
8-jre8: Pulling from library/tomcat
bb7d5a84853b: Pull complete
f02b617c6a8c: Pull complete
d32e17419b7e: Pull complete
ab18cfab55f9: Pull complete
793716e93ecb: Pull complete
3b9b14f7678b: Pull complete
4dc2d594b57d: Pull complete
3f275ee15a3d: Pull complete
15b0db619216: Pull complete
c0aa838e7a3a: Pull complete
Digest: sha256:47165dabe7c092c61ef2726a7fdc70dda0ce9dea07ca68bda0aea6ecfaba2873
Status: Downloaded newer image for tomcat:8-jre8
—> cff25871f024
Step 2/2 : ADD petclinic.war /usr/local/tomcat/webapps/
—> f27039d77fc4
Successfully built f27039d77fc4
Successfully tagged tomcat-petclinic:latest

2. WEB 구성

2-1. NginX 리소스 다운로드

> Git에 올라가 있는 NginX 리소스를 다운받는다.

root@master:/home/src# git clone https://github.com/Hwang-sangyeon/nginx-for-petclinic.git
Cloning into ‘nginx-for-petclinic’…

리소스 다운로드 후,

nginx.conf 파일에서 was 연동 포트 확인 및 nginx listen-port를 확인한다.

2-2. 이미지 생성

> Dockerfile이 있는 디렉토리에서 이미지를 빌드한다.

root@master:/home/src/nginx-for-petclinic/nginx-for-petclinic# docker build -t nginx-petclinic .
Sending build context to Docker daemon  6.656kB

2-3. WEB/WAS 이미지 확인

root@master:/home/src/nginx-for-petclinic/nginx-for-petclinic# docker images|grep petclinic
nginx-petclinic                          latest    952aff9083ee   19 seconds ago   133MB
tomcat-petclinic                         latest    39e56a91e5e7   9 minutes ago    334MB

3. 컨테이너 기동

이제부터는 필요한 이미지가 준비되었기 때문에 WEB/WAS/DB 컨테이너를 기동하여 3-Tier를 구성을 해보려고 한다.

여기서 중요한 점은 WAS가 기동되기 전에 (소스 빌드) DB가 먼저 떠있어야 하기 때문에 DB 컨테이너를 반드시 먼저 기동시켜야 한다는 것이다.

3-1. DB 컨테이너 기동

> mysql-petclinic 컨테이너 명으로 mysql 이미지를 바로 받아 컨테이너를 실행한다.

docker run --name mysql-petclinic -e MYSQL_ROOT_PASSWORD=petclinic -e MYSQL_DATABASE=petclinic -p 3306:3306 mysql:5.7.8

Initializing database 이후 docker container ps로 확인

root@master:~# docker container ps | grep mysql
d286f5c59a6c   mysql:5.7.8            “/entrypoint.sh mysq…”   57 seconds ago      Up 56 seconds      0.0.0.0:3306->3306/tcp, :::3306->3306/tcp   mysql-petclinic

3-2. WAS 컨테이너 기동

docker run -it --rm -p 8080:8080 --name tomcat-petclinic --link mysql-petclinic:mysql-petclinic tomcat-petclinic

> tomcat 컨테이너에서 mysql 컨테이너의 ip로 접속할 수 있겠지만, static ip가 아니기 때문에 mysql 컨테이너의 이름으로 접속을 해야 할 필요가 있다. 이럴 경우 link 옵션을 통해 컨테이너를 구동하면 tomcat 컨테이너에서 mysql 컨테이너로 이름으로 접속할 수 있다. link 옵션으로 구동하면 톰캣 컨테이너 안의 /etc/hosts에 링크된 mysql 컨테이너 hostname과 ip가 들어간다.

3-3. WEB 컨테이너 기동

docker run -it --rm -p 80:80 --name nginx-petclinic --link tomcat-petclinic:tomcat-petclinic nginx-petclinic

4. 서비스 호출

 

192.168.56.200은 VM의 IP

 

이상 도커를 활용하여 3-Tier 컨테이너 환경을 구성해보았다..

[Docker] docker-compose 를 이용해 ELK 구축하기 ( + mySql, Nori)

1. ELK ?

Elasticsearch, Logstash, Kibana 오픈 소스 프로젝트 3개를 합쳐서 ELK 라고 한다. Elasticsearch 는 검색 및 분석 엔진으로 무료버전으로도 기본적인 기능은 충분히 사용가능하다. Logstash는 여러 소스에서 동시에 데이터를 수집하여 변환한 후 Elasticsearch 와 같은 곳에 ‘stash’로 전송하는 서버 사이드 데이터 처리 파이프라인을 말한다. Kibana 는 사용자가 Elasticsearch 를 시각화하여 사용할수 있는 툴이다.

여기서는 이미 사용하고 있는 docker 기반 mySql 을 Elasticsearch 에 logstash 를 이용해 동기화 하고, 검색하는 부분만 포스팅할 예정이다.

 

2. Nori ?

한글 검색을 올바르게 수행하기 위해서는 형태소 분석기 plug-in 을 Elasticsearch 에 따로 설치해주어야 하는데, 다른 다양한 형태소 분석기들도 많지만 필자는 Elasticsearch 공식문서를 보면서 작업하기 수월하기 위해 Nori 형태소 분석기를 사용하기로 하였다. nori는 elasticsearch 가 실행된 상태에서 해당 bash 에 접속해 설치하면 된다.

$ docker exec -it elasticsearch /bin/bash 
$ bin/elasticsearch-plugin install analysis-nori #elasticsearch container 에서 명령

nori를 이용한 검색을 해야하는 데이터 컬럼에 대해서는 반드시 mapping analyzer 셋팅을 해주어야 한다. 예를들어 ‘name’이라는 column 에 형태소 분석을 이용한 한글검색이 가능하게 하고자 한다면 mapping 은 다음과 같은 형태일 수 있다.

 "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          },
          "analyzer":"nori_analyzer"
        }

 

3. docker-compose

version: '3.2'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.6.1 #기본 이미지 사용
    container_name: elasticsearch
    environment:
      ES_JAVA_OPTS: "-Xmx256m -Xms256m"
      discovery.type: single-node #간단한 local 테스트를 위해 single-node로 구성
    volumes:
      - /usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elk
  logstash:
    container_name: logstash
    image: docker.elastic.co/logstash/logstash:7.6.1
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    volumes:
      - type: bind
        source: ./config/logstash/config/logstash.yml
        target: /usr/share/logstash/config/logstash.yml
        read_only: true
      - type: bind
        source: ./config/logstash/pipeline
        target: /usr/share/logstash/pipeline
        read_only: true
      - ./jar/mysql-connector-java-8.0.18.jar:/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-8.0.18.jar #mysql 사용을 위한 jdbc-connector 다운
    networks:
      - elk
    depends_on:
      - elasticsearch #elasticsearch 가 실행된 이후 logstash 실행되도록 depends_on 설정
  kibana:
    container_name: kibana
    image: docker.elastic.co/kibana/kibana:7.6.1
    ports:
      - 5601:5601
    networks:
      - elk
    depends_on:
      - elasticsearch #elasticsearch 가 실행된 이후 kibana 실행되도록 depends_on 설정
    
networks:
 elk:
  external:
    name: mysql-network #이미 사용하고 있는 db와 연결을 위해 mysql-docker network 와 연결이 되도록 external 설정을 따로 해주었다. 

volumes:
 elasticsearch: #volume container 사용
    

 

이미 떠있는 mysql container 와의 연결을 위해 external network 설정을 따로 해주었으나, 만약 elk 구축과 함께 database 를 실행한다면 external 연결은 해줄필요가 없다. 기본적인 ELK 설정을 거이 따르고 있으며 여기서는 mysql 연결을 위한 부분과 single-node 사용하는 부분만 수정하였다.

4. mysql 과 동기화 작업 설정

동기화 하고 싶은 데이터가 있다면 logstash.conf 파일에서 설정해주면 된다. 여기서는 crontab 과 수정일을 이용하여 마지막 데이터를 동기화해 가지고 오도록 작업하였다.

input {
  jdbc {
    jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-8.0.18.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://[mysql-container-name]:[mysql-container-host]/allpal?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul&autoReconnect=true"
    jdbc_user => "[mysql-id]"
    jdbc_password => "[mysql-password]"

    columns_charset => {
      "[한글데이터를 가지고 있는 column 명]" => "UTF-8"
    }

    statement => "SELECT *, UNIX_TIMESTAMP(modification_time) as unix_ts_in_secs FROM [table name] WHERE 
    (UNIX_TIMESTAMP(modification_time) > :sql_last_value AND modification_time < NOW())"

    jdbc_paging_enabled => true
    use_column_value => true
    tracking_column => "unix_ts_in_secs"
    tracking_column_type => "numeric"
    clean_run => true
    schedule => "*/5 * * * * *"  # crontab 표기법의 스케쥴 설정
  }
}

output {
  elasticsearch {
    hosts => "elasticsearch:9200"
    index => "[index명]"
    document_id => "%{_id}"
  }
  stdout {
    codec => rubydebug
  }
}

[대괄호]안에 있는 부분들은 해당 상황에 맞게 입력하면 되는 값이며, 여기서는 위에서 언급한것처럼 modification_time 이라는 수정일 컬럼을 이용하여 동기화하였다. 새로 추가되거나, 수정/삭제 된 경우에도 데이터가 자동으로 동기화 되기 위해서 다음과 같이 작업을 진행하였다.

 

각 환경에 맞게 수정한 docker-compose.yml 파일과 logstash.conf 등 설정파일들 준비가 완료되었다면 docker-compose.yml 파일이 있는 디렉토리에서 docker-compose up 을 통해 해당 파일이 실행되는것을 확인할 수 있으며, localhost:5601 에 접속하여 kibana 에서 편하게 실제 index가 들어간 모습과, mapping 등을 확인할 수 있다.

MariaDB Connect engine JDBC 연결 사용하기

MariaDB에서 이기종 데이터베이스를 사용하기 위해서 Connect 엔진을 사용합니다.

connect 엔진에 대한 MariaDB의 웹페이지는 아래를 참고하시면 됩니다.

https://mariadb.com/kb/en/library/connect/

connect 엔진을 이용해서 이기종 데이터 베이스를 연결할때 ODBC를 사용을 했습니다.

JDBC를 사용하기 위해서는 10.2.2 / 10.1.17 / 10.0.27 이상의 버전을설치하면 됩니다.

JDBC를 사용하는 방법은 아래 웹페이지를 참고합니다.

https://mariadb.com/kb/en/library/connect-jdbc-table-type-accessing-tables-from-another-dbms/

해당 웹페이지만으로 실제 사용하기에는 쉽지 않아서 아래 테스트를 한 내용을 정리해 봅니다.

먼저 MariaDB JDBC connector를 이용해서 같은 서버의 MariaDB를 JDBC로 연결해서 사용하는 방법은 아래와 같습니다.

  • JRE 설치
  • my.cnf 설정 : connect_jvm_path, connect_class_path
  • mariadb start
  • connect 엔진 global variables 확인
  • create table

# apt-get install default-jre

# vi my.cnf
##### connect engine
connect_jvm_path="/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server"
connect_class_path="/ohnew/mariadb/connect/mariadb-java-client-2.2.3.jar"

# systemctl start mariadb

MariaDB> show global variables like 'conn%path';

MariaDB> create table jt_t1 engine=connect table_type=jdbc tabname=t1 connection='jdbc:mariadb://localhost:3306/ohnew' option_list="User=root,Password=";

아래는 다른 서버에 있는 oracle 데이터베이스를 JDBC로 연결해서 사용하는 방법입니다.

  • my.cnf 설정 : connect_jvm_path, connect_class_path
  • mariadb start
  • create server
  • create table

# vi my.cnf
##### connect engine
connect_jvm_path="/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server"
connect_class_path="/ohnew/mariadb/connect/ojdbc6.jar"

# systemctl start mariadb

MariaDB> create server 'oracle' foreign data wrapper 'oracle' options (
HOST 'jdbc:oracle:thin:@192.168.100.101:1521:orcl',
DATABASE 'ORCL',
USER 'system',
PASSWORD 'manager',
PORT 0,
SOCKET '',
OWNER 'SYSTEM');

MariaDB> create table jt_ora_t1 engine=connect table_type=JDBC connection='oracle/ohnew.t1' SRCDEF='select c1 from ohnew.t1';

CONNECT Storage Engine Oracle연동 (My-SQL에 Oracle db 연결)

Oracle DB가 아닌 MSSQL , Postgre 등의 연결도 해당 DB에서 제공하는 Driver 들을 설치 설정하면 크게 다르지 않다.

예를 들어

가입자(회원) 정보는 Oracle DB에 있고 실제 단위 서비스에 대해서는 MariaDB or MySQL를 사용하는 경우

회원 정보 1,2명의 데이터를 처리가 아니라 수백 수천만명의 데이터를 처리 해야 하는 경우…

이럴때..

MariaDB(MySQL)에서 제공하는 CONNECT Storage Engine을 통해서

MariaDB(MySQL) –> Oracle DB로 직접 억세스 해보자.

Connect engine 구성 방법 및 순서

  1.  연결하고자 하는 대상  DB의 ODBC Driver 설치
  2.  ODBC 설치및 설정
  3.  연결테스트(ODBC-Oracle)
  4.  MariaDB(MySQL) Connected Engine Plugin 설치 및 설정 
  5.  연동 테스트(MariaDB or MySQL – Oracle) 

1. Oracle DB ODBC Driver 설치 (Oracle client 설치)

Oracle db ODBC Driver 설치를위해 OracleClient 를 설치 한다.

Oracle Client(http://www.oracle.com/technetwork/database/enterprise-edition/downloads/oracle12c-linux-12201-3608234.html) 에서 OS 및 적절한 버전의 client를 다운받는다

요즘은 이런 드라이버 하나 받으려는데 로그인이 필요하다. 불편해 죽겠다…


rpm -ivh oracleclient/oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
rpm -ivh oracleclient/oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm
rpm -ivh oracleclient/oracle-instantclient12.1-odbc-12.1.0.2.0-1.x86_64.rpm

단순하게 rpm Package를 받아 설치 한다. (우리가 필요한것은 basic, odbc 이지만 혹시 모르니 모두 설치 한다.)

참고로 zip 파일로 내려 받아 압축을 풀어 사용 할 수도 있다.

기본 설치시 Oracle client 는 /usr/lib/oracle/{version}/client64/lib/ 에 설치된다.

현재 최신 버전은 12.1 이다.  테스트 한 바로는 12.1버전을 사용시, 11 버전과 호환에 큰 문제는 없었다.

일단, 설치가 되었다면 오라클 클라이언트 Path 를 환경 변수에 잡아주자


$ vi ~/.bash_profile

$ export ORACLE_HOME=/usr/lib/oracle/12.1/client64
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME/lib


// 저장후 이를 적용 하기 위하여 
$ source ~/.bash_profile

//환경변수 확인

$ env
LD_LIBRARY_PATH=/usr/lib/oracle/12.1/client64/lib/:/usr/lib/oracle/12.1/client64/lib/:

2. ODBC 설치및 설정(연결테스트)

*. Windows 환경의 ODBC 설정은 “Windows Oracle ODBC 설정” 글 참조

위의 그림에도 나와 있듯이 MariaDB(MySQL)에서 제공하는 CONNECT Storage Engine 은 ODBC를 사용 하므로 Odbc를 설치 한다. (ubuntu 는 당연히 apt-get install)


[root@TESTDB ~] yum install unixODBC
[root@TESTDB ~] yum install unixODBC-devel

[수동 설치]

unixODBC 소스를 내려 받아 압축을 풀고 compile 하여 설치


$ ./configure
$ make
$ make install

설치시 기본 설치 경로는 /usr/local 이며 별도의 설치 경로를 주고자 하는 경우 컴파일시 다음 조건을 준다

예) ./configure –prefix=/usr/local/unixODBC

ODBC설정 파일(odbc.ini, odbcinst.ini)의 경로는  {prefix}/etc 에 존재 하며,

이를 변경 하고자 하는 경우  –sysconfdir 옵션을 이용 할 수 있다.

예) ./configure –sysconfdir=/etc

odbc 설정

odbc설정은 2개의 파일을 편집하여 설정 합니다.(odbc.ini, odbcinst.ini)

yum or apt-get을 이용하여 설치 한 경우 odbc.ini, odbcinst.ini 파일은 /etc 디렉토리에 있습니다.

[odbcinst.ini편집]


$ sudo vi /etc/odbcinst.ini

[Oracle]
Description = Oracle ODBC driver for Oracle
Driver = /usr/lib/oracle/12.1/client64/lib/libsqora.so.12.1

Driver = oracle odbc client driver path

Driver = 오라클 client가 인스톨된 위치의 정확한 파일명을 주어야 합니다.

[odbc.ini편집]


$ sudo vi /etc/odbc.ini

[Oracle]
Driver = Oracle-12.1
ServerName = //192.168.0.2:1521/ORCL
UserName = system
Password = manager
Trace = yes
TraceFile = /tmp/odbc_oracle.log

Driver = Oracle (odbcinst.ini 에서 동일한 이름 사용)

ServerName = //192.168.0.2:1521/ORCL

serverName 은 oracle DB 의 정보를 정확하게 기입 합니다.

3. 연결테스트(ODBC-Oracle)

odbc 에서 제공 하는 isql툴을 이용해서 접속을 확인 합니다.


$ isql Oracle
+---------------------------------------+
| Connected!                      |
|                                 |
| sql-statement                    |
| help [tablename]                 |
| quit                             |
|                                 |
+---------------------------------------+
SQL>
SQL> select * from emp;
+-------+-----------+----------+-------+--------------------+----------
| EMPNO | ENAME     | JOB      | MGR   | HIREDATE           | SAL
+-------+-----------+----------+-------+--------------------+----------
| 7369  | SMITH     | CLERK    | 7902  | 1980-12-17 00:00:00| 800
…
+-------+-----------+----------+-------+--------------------+----------
SQLRowCount returns -1
15 rows fetched
SQL>

테이블 및 데이터 테스트 쿼리 사용 작동 확인 중 에러가 발생 하는 경우 isql –v Oracle 으로 에러메세지를 출력 하여 확인

4. MariaDB(MySQL) Connected Engine Plugin 설치 및 설정

mariadb connected engine 설치 및 활성화 Connected Engine은 mariaDB에서 plug in 형태로 제공되며, 버전 10.2 이상 상위 버전에서 지원 합니다. (10.0 이하 버전은 지원이 중단) root database 접속 후 플러그인 되어 있는 엔진 중 connect engine이 설치 되어 있고 활성화 되어 있는지 확인


$ mysql -uroot -p

MariaDB [(none)]>show engines;

+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
  | Engine             | Support | Comment                                                                    | Transactions | XA   | Savepoints |
  +--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+
  | CONNECT            | YES     | Management of External Data (SQL/MED), including many file formats         | NO           | NO   | NO         |

CONNECT Engine plug-in이 설치 되어 있는지 확인한다.

CONNECT Engine plug-in이 설치 되어 있지 않을 경우 connect-engine을 설치 합니다.


//connect-engine 인스톨 후, 엔진 추가 및 확인
$ yum install mariadb-connect-engine

$ mysql -uroot -p

MariaDB [(none)]> INSTALL SONAME 'ha_connect';
MariaDB [(none)]> show engines;
+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+

| Engine             | Support | Comment                                                                    | Transactions | XA   | Savepoints |

+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+

| CSV                | YES     | CSV storage engine                                                         | NO           | NO   | NO         |

| MRG_MyISAM         | YES     | Collection of identical MyISAM tables                                      | NO           | NO   | NO         |

| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables                  | NO           | NO   | NO         |

| BLACKHOLE          | NO      | /dev/null storage engine (anything you write to it disappears)             | NULL         | NULL | NULL       |

| MyISAM             | YES     | MyISAM storage engine                                                      | NO           | NO   | NO         |

| CONNECT            | YES     | Management of External Data (SQL/MED), including many file formats         | NO           | NO   | NO         |

| InnoDB             | DEFAULT | Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES          | YES  | YES        |

| ARCHIVE            | NO      | Archive storage engine                                                     | NULL         | NULL | NULL       |

| FEDERATED          | YES     | FederatedX pluggable storage engine                                        | YES          | NO   | YES        |

| PERFORMANCE_SCHEMA | YES     | Performance Schema                                                         | NO           | NO   | NO         |

| Aria               | YES     | Crash-safe tables with MyISAM heritage                                     | NO           | NO   | NO         |

+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+

11 rows in set (0.01 sec)

7. 연동 테스트(MariaDB or MySQL – Oracle)

이제  MariaDB에서 Oracle로 직접 연결해 보자.

MariaDB [testdb]> CREATE TABLE emp_oracle ENGINE=CONNECT CONNECTION='DSN=ORCL;UID=system;PWD=manager' `TABLE_TYPE`=ODBC `tabname`='emp' ;

Query OK, 0 rows affected (0.04 sec)


MariaDB [testdb]> select * from emp_oracle;
+-------+-----------+----------+-------+--------------------+----------
| EMPNO | ENAME     | JOB      | MGR   | HIREDATE           | SAL
+-------+-----------+----------+-------+--------------------+----------
| 7369  | SMITH     | CLERK    | 7902  | 1980-12-17 00:00:00| 800
…
+-------+-----------+----------+-------+--------------------+----------
15 rows in set (0.11 sec)

MariaDB [testdb]>

위 처럼 oracle DB의  emp Table을 직접 조회 할수 있다.  접속 유저의 권한이 있다면 Insert, Update 역시 가능하다.

한계점은 당욘히 존재 한다.

Blob/Text 등의 data Type은 지원하지 못한다.

또한, Oracle, MySQL등에서 지원하는 LinkDB , LinkedServer처럼 한번 연결로 모든 테이블 억세스는 되지 않는다.  테이블당 링크 테이블을 생성해 이용해야 한다. (이 부분은 필요한 Oracle에 view를 생성하고 이 View Table를 이용하는 편법을 이용할 수 있다)

[참고] 

테스트를 하면서 LD_LIBRARY 문제가 발생했다. 이유는 MariaDB(MySQL) 의 구동이 MySQL Damon에 의해서 실행되는데 MySQL User에 LD_LIBRARY Path 설정이 되지 않아서 발생하는 오류 였다.

이럴경우 아래와 같이 LD_LIBRARY 를 추가 할 수 있다.

[Oracle library 추가 방법]


/etc/ld.so.conf.d/ 디렉토리에 파일(*.conf)을 만들어 추가

cd  /etc/ld.so.conf.d/
vi oracle.conf
/usr/lib/oracle/12.2/client64/lib

프로젝트 중

고객에게 문자 발송 데이터를 만들어 문자 발송 시스템으로 데이터를 넣어 주어야 하는 프로젝트가 있었다,

고객 정보는 Oracle DB에 있었고,

문자 발송 대상 고객리스트는 엑셀로 전달되었다.

여러가지 문제로 해당 시스템은 MariaDB로 구성되어 있어서 엑셀로 전달되는 대상 고객 정보를 고객 DB(Oracle)에서 얻어와야 하는데 한번에 전달되는 엑셀의 고객수가 100만건이 넘었다.

고객정보 소스는 엑셀이고, 고객 ID를 이용해서 필요한 고객정보(Oracle DB)를 얻어와야 하는데  100만건이 넘는 데이터를 프로그램에서 loop 를 돌면서 처리 하기에는 속도의 문제가 있었으나 Connected engine을 이용해 query 한번으로 처리 할수 있었다…

MySQL DB-Link 구현을 위한 FEDERATED 엔진 활성화 및 테이블 생성

Oracle 과 MSSQL에 있는 DB Link 서비스를 MySQL에서 지원하는 FEDERATED 엔진을 이용하여 구현하는 방법 입니다.

1. 설치되어 있는 엔진 확인

– CentOS에서 yum 으로 설치했을때 기본적으로 사용 가능한 엔지들의 목록 입니다.

2. 엔진을 사용할 수 있도록 설치

 

3. FEDERATED 엔진의 설치여부 확인

– FEDERATED 엔진이 목록에 표시되지만 사용 가능하지 않은 상태 입니다.

4. 엔진 사용 가능 하도록 my.cnf 수정

– [mysqld] 하위에  federated 항목을 추가 합니다.

5. 엔진의 상태를 확인 합니다.

– FEDERATED 엔진의 Support 상태가 YES 로 변경 되었습니다.

—————————– FEDERATED 엔진을 사용하여 테이블을 생성하여 원격지 테이블과 연결 ————————-

1. 원격지에 테이블을 생성 합니다.

CREATE TABLE `cityholic_db`.`cart_product` (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘아이디’,

`users_id` bigint(20) unsigned NOT NULL COMMENT ‘고객아이디’,

`product_id` bigint(20) NOT NULL COMMENT ‘상품아이디’,

`option_code` varchar(50) NOT NULL COMMENT ‘상품옵션코드’,

`quantity` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘상품 개수’,

PRIMARY KEY (`users_id`,`product_id`,`option_code `),

UNIQUE KEY `id_UNIQUE` (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=’카트에 담긴 상품’;

2. 로컬에 테이블을 생성 합니다.

CREATE TABLE `cityholic_db`.`cart_product` (

`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT ‘아이디’,

`users_id` bigint(20) unsigned NOT NULL COMMENT ‘고객아이디’,

`product_id` bigint(20) NOT NULL COMMENT ‘상품아이디’,

`option_code` varchar(50) NOT NULL COMMENT ‘상품옵션코드’,

`quantity` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘상품 개수’,

PRIMARY KEY (`users_id`,`product_id`,`option_code `),

UNIQUE KEY `id_UNIQUE` (`id`)

) ENGINE=FEDERATED DEFAULT CHARSET=utf8 COMMENT=’카트에 담긴 상품’

CONNECTION=’mysql://root:dldusrn1@10.3.0.27:3306/cityholic_db/cart_product’;

– 원격지 테이블 Create 문에서 ENGINE  수정, CONNECTION 옵션 추가  작업만 수행 합니다.

– CONNECTION 옵션의 구성은 다음과 같습니다.  ‘mysql://[계정]:[비밀번호]@[서버ip]:[port]/[원격지DB명]/[원격지 테이블명]’

3. 이상 모든 설정을 완료 했다면 로컬에서 원격지의 Table을 로컬 테이블 처럼 사용 가능합니다. select, insert, update, delete 모두 가능 합니다.