본문 바로가기

Cloud

(Kubernetes) - cluster상에서 WAS-DB 연결

반응형

🍳머리말

K8s cluster에서 Provisioned WAS(tomcat)와 DB(mysql)를 연결하는 예제 {}로 감싸진 부분은 직접 입력해야하는 부분입니다.


📕 Prerequisite

📔 Docker

📔 CNI가 설치된 k8s cluster.

📔 Docker Hub 계정


📕 DB(mysql) 준비

📔 namespace 생성

논리적 격리를 위해 namespace를 생성해줍니다. 

kubectl create namespace [이름]

 

제 경우는 제 이름을 따서 mskim이라는 namespace를 생성해줬습니다.

kubectl create namespace mskim

 

📔 replicaset 생성

제 namespace로 replicaset을 생성해줍니다. mysql latest image를 사용했습니다. label은 mysql로 사용할 것입니다.

 

mysql-deployment.yaml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: myweb-mysql
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
        containers:
        - image: docker.io/mysql
          imagePullPolicy: Never  #Do not use remote mirror
          name: mysql
          ports:
          - containerPort: 3306
          env:
          - name: MYSQL_ROOT_PASSWORD
            value: "password"

mysql의 password는 password로 설정했습니다.

 

📔 service 생성

cluster 내에서만 통신할 수 있도록 service객체를 ClusterIP type으로 만들어 deployment를 여기로 노출시킵니다.

 

mysql-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: mysql
spec:
  ports:
  - name: mysql-svc
    port: 3306
    targetPort: 3306
  selector:
    app: mysql
  type: ClusterIP

 

확인

kubectl -n [namespace명] get svc

 

teminal 출력

 

 

📔 예제 database, table, data생성

📑 pod 이름 확인

kubectl -n [namespace명] get pods

다음과 같이 myweb-mysql-랜덤5글자 형태로 running 중이라면 성공입니다.

 

📑 해당 pod에 접속

형식은 아래와 같습니다.

kubectl -n [namespace명] exec -it [pod명] bash

 

제 경우는 이런 명령어를 입력했습니다.

kubectl -n mskim exec -it myweb-mysql-fg9rw bash

 

입력후에는 이런식으로 접속됩니다.

📑 MySQL 접속

형식은 다음과 같습니다.

mysql -u[user명] -p[password]

 

제 경우 user는 root, password는 password로 설정했으므로 다음과 같은 명령어로 접속합니다.

 mysql -uroot -ppassword

 

접속 후 해당화면입니다.

📑 MySQL server에 data생성

다음과 같은 sql문들을 실행해줍니다. database, table, row들을 추가하는 sql문입니다.

create database testDB;
use testDB;
create table testTable(
    id int(11) not null auto_increment,
    name varchar(20) not null,
    constraint testTable_pk primary key(id)
);

insert into testTable(name) values("hi");
insert into testTable(name) values("mskim");
insert into testTable(name) values("hello");
insert into testTable(name) values("James");
insert into testTable(name) values("JIN");

 

아래와 같이 Query Ok message가 출력된다면 된 것입니다.

 


📕 WAS(tomcat) 준비

📔 JDBC driver 설치

Tomcat official image에는 JDBC driver가 없습니다. 따라서 필요한 sql에 따른 driver를 jar형태로 image의 file system에 포함시켜야 합니다.

 

아래 url에서 jar를 설치해주도록 합니다. mysql version에 따른 connector는 고려하지 않았습니다. 필요한 경우 호환되는 version을 알고있다는 가정하에 진행하겠습니다.

https://dev.mysql.com/downloads/connector/j/

 

MySQL :: Download Connector/J

MySQL Connector/J 8.0 is highly recommended for use with MySQL Server 8.0, 5.7 and 5.6. Please upgrade to MySQL Connector/J 8.0.

dev.mysql.com

 

받은 jar file은 jvm상에서 실행할 수 있는 압축 file입니다. 

 

📔 Sample.war 설치

apache tomcat 공식으로 제공하는 Sample Application인 Sample.war를 받아줍니다. tomcat image의 filesystem으로 넣어주면 자동으로 압축을 해제해 실행해줍니다.

https://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/

 

Sample Application

Sample Application The example app has been packaged as a war file and can be downloaded here (Note: make sure your browser doesn't change file extension or append a new one). The easiest way to run this application is simply to move the war file to your C

tomcat.apache.org

📔 Docker hub 접속

 1. docker hub에 login해줍니다. 

 2. 하기와 같이 새로운 repository를 생성해줍니다. 이름을 was로 설정한 후 create button을 click하면 됩니다.

 

생성된 결과는 다음과 같습니다.

 

📔 Tomcat Image Build

 

docker daemon을 실행해주시고 다음 명령어로 작성한 Dockerfile을 이용, jdbc.jar, sample.war과 함께 tomcat을 docker hub에서 받아와 image를 build해줍니다. 이를 위해서 작업한 dir경로의 terminal에서 하기와 같은 명령어를 실행합니다.

 

Dockerfile 예시

제 경우는 base continer를 openjdk 10을 사용했고 tomcat 10 mysql-connedtor-java는 mysql 8에 맞춰 download받아 image build했습니다.

FROM openjdk:10-jdk
MAINTAINER jyson

# 환경 변수 및 작업 경로
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
RUN mkdir -p "$CATALINA_HOME"
WORKDIR ${CATALINA_HOME}

# 톰캣 설치 파일 다운로드 실행 및 압축해제            
RUN wget http://apache.mirror.cdnetworks.com/tomcat/tomcat-10/v10.0.20/bin/apache-tomcat-10.0.20.tar.gz;
RUN tar -xf apache-tomcat-10.0.20.tar.gz  --strip-components=1;

# war 파일 복사
COPY ./sample.war $CATALINA_HOME/webapps

# jdbc driver jar 복사
COPY ./mysql-connector-java.jar ../openjdk-10/lib
COPY ./mysql-connector-java.jar /usr/local/tomcat/lib/

# 컨테이너에서 사용할 포트
EXPOSE 8080

# 설정 완료 후 실행
CMD ["catalina.sh", "run"]

 

작성 후에는 다음과 같은 명령어로 image build 해줍니다.

docker build -t [dockerhub ID]/[repo명]:[tag명] .

 

제 경우 docker ID는 xhdxhl, repo명은 was, tag명은 0.1이므로 다음과 같이 작성했습니다.

docker build -t xhdxhl/was:0.1 .

명령어 입력시 아래와 같이 나옵니다.

 

📔 Tomcat Image Push

local환경에서 build 명령어로 image를 말았으니 원격 repo에 push를 해야합니다.

아까 build했을 때 설정한 값들로 push 명령어를 입력해줍니다.

 

docker push [docker ID]/[repo명]:[tag명]

 

 

제 경우 입력한 명령어는 다음과 같습니다.

 

docker push [docker ID]/[repo명]:[tag명]

 

명령어를 입력하면 다음과 같이 뜹니다.

입력했을 때 뜨는 화면
push된 결과 나오는 화면

push 후에는 docker hub에 다음과 같이 tag 0.1의 image가 목록으로 browser에 출력됩니다.

📔 Tomcat Secret 생성

db의 credential정보는 secret으로 관리하는 것이 좋습니다. 비록 예제이나 서비스를 운영하는 것처럼 보이기 위해 secret을 생성해 deployment로 주입할 예정입니다.

 

tomcat-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: tomcat-secret
stringData:
  DB_URL: "jdbc:mysql://mysql/testDB"
  DB_USER: "root"
  DB_PASSWORD: "password"

📔 Tomcat Deployment 생성

이제 dockerhub의 원격 repo로 push된 image를 pull해서 deployment를 생성해줍니다.

 

tomcat-deployment.yaml

apiVersion: apps/v1      
kind: ReplicaSet    
metadata:     
  name: myweb-tomcat
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      containers:
      - image: docker.io/xhdxhl/was:0.1
        imagePullPolicy: Always
        name: myweb
        resources:
          limits:
            cpu: "0.5"
            memory: 1Gi
        ports:
        - containerPort: 8080         
        env:
        - name: db_url
          valueFrom:
            secretKeyRef:
              name: tomcat-secret
              key: DB_URL
        - name: db_user
          valueFrom:
            secretKeyRef:
              name: tomcat-secret
              key: DB_USER
        - name: db_password
          valueFrom:
            secretKeyRef:
              name: tomcat-secret
              key: DB_PASSWORD

📔 Tomcat Service 생성

tomcat-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: myweb
spec:
  ports:
  - name: myweb-svc
    port: 8080 #Port number of the Service
    targetPort: 8080  #Port number of container exposed
    nodePort: 30001  #The real port number of the node
  selector:
    app: myweb   #Service selected pod with tag app: myweb
  type: NodePort

 

확인

kubectl -n [namespace명] get svc

 

출력결과

 

pod 확인 명령어

kubectl -n [namespace명] get pods

 

출력결과

📔 Tomcat 외부노출 확인

크롬창에서 http://[cluster가 구성된 node의 ip]:[nodeport로 노출된 tomcat service의 port번호]로 접속합니다.nodeport 번호는 30001번으로 지정했으니 url은 예시로 http://192.168.9.199:30001 가 됩니다.

다음처럼 tomcat이 원활히 배포되었고 sample.war의 압축을 자동으로 해제해 다음 html을 출력하는 화면을 볼 수 있습니다.


📕 WAS-DB사이 connection 확인

📔 jsp file 작성

db와의 연결이 제대로 이루어졌을 확인하기 위해 작성합니다. db와 연결 후에 간단한 query문을 실행하는 sql문 입니다.

 

📑 dbtest.jsp

<%@ page import="java.sql.*" contentType="text/html; charset=UTF-8" %>
<%@ page import="javax.naming.*" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%
	String DB_URL = System.getenv("db_url");
	String DB_USER = System.getenv("db_user");
	String DB_PASSWORD= System.getenv("db_password");
	Connection conn;
	Statement stmt;
	ResultSet rs;

	try
	{
		out.println("START TRY!!");
		out.println("<br/>");
		conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
		out.println("getConnection success");
		out.println("<br/>");
		stmt = conn.createStatement();
		out.println("createStatement success");
		out.println("<br/>");
     	out.println("MySQL Connection Success!");
		out.println("<br/>");

		String sql = "select * from testTable";
		rs = stmt.executeQuery(sql);
		
		while(rs.next()) {
			out.println("id - " +rs.getString("id")+ " |");
			out.println("NAME - " +rs.getString("name")+ " |");
			out.println("<hr>");
		}
		stmt.close();
		conn.close();
	}
	catch(Exception e)
	{
		e.printStackTrace();
	}
%>
 
</body>
</html>

 

📔 .jsp를 tomcat container안으로 옮기기

kubectl은 기본적으로 cp명령어를 지원합니다.

kubectl -n [namespace명] cp [옮길 file 경로] [pod명]:[pod내부 container의 목적지 경로]

 

제 경우 다음과 같은 명령어를 입력했습니다.

kubectl -n [namespace명] cp ./dbtest.jsp myweb-tomcat-cm6g6:./webapps/ROOT

 

📔 web에서 연결 확인


자 이제 접속이 되었으니 .jsp가 적용됐는지 확인해 봅시다.

/[jsp file명]로 구분해 접속해볼 수 있습니다. dbtest.jsp를 넣어놓았으니 url은 다음과 같습니다.

http://192.168.9.199:30001/dbtest.jsp

연결이 잘 되었고 testTable의 row들을 성공적으로 출력하고 있습니다.