이 글을 보는 사람은 도커와 쿠버네티스에 대한 기본적인 지식이 있다고 생각할 것입니다.

도커는 알겠는데 쿠버네티스는 처음이라면 아래 동영상을 보고 진행하시기 바랍니다.

https://www.youtube.com/watch?v=s_o8dwzRlu4&ab_channel=TechWorldwithNana

쿠버네티스 컨테이너에 외부에서 접속하는 과정은 일반적으로 다음과 같습니다.

외부 → nginx → minikube → ingress controller → service → pod

각각이 잘 동작하는지 확인하려면 거꾸로 구현해야 합니다.

여기서는 서비스와 파드를 구현해보고 외부에서 접속하는 과정은 ingress 대신 포트포워딩을 이용해 간단히 구현해볼 것입니다.

쿠버네티스에 스프링 프로젝트 배포하기

1. EC2에 Minicube 설치하기

1.1. EC2 생성하기

  • ARM 버전으로 진행하면 이슈가 많아서 x86으로 진행하는 것을 추천합니다.
  • 인스턴스는 미니큐브 조건 때문에 t2 미디엄을 사용합니다.
    • 프리티어 사용하면 미니큐브 설치 에러가 발생합니다.
  • SSH로 접속합니다.
  • 프리티어가 아니니까 주의하시기 바랍니다.

1.2. 도커 설치하기

  • 두 단계로 나누어서 설치할 것입니다.
  • docker info를 입력해서 잘 나오면 설치가 잘 된 것입니다.

1.3. 미니큐브 설치하기

  • 공식 홈페이지에서 환경에 맞춰서 설치할 것입니다.
  • minikube version을 입력해서 잘 나오면 설치가 잘 된 것입니다.

1.4. kubectl 설치하기

  • 환경에 맞춰서 설치할 것입니다.
  • kubectl version --short를 입력해서 잘 나오면 설치가 잘 된 것입니다.

2. 샘플 프로젝트 만들기

  • 테스트를 위해서는 Spring과 MySQL을 사용하는 샘플 프로젝트를 만들어야 합니다.
  • 이 부분을 뛰어넘고 싶은 분은 그냥 3번부터 시작하시면 됩니다. 제가 미리 만들어둔 프로젝트를 사용할 것입니다.
  • 참고로 제 프로젝트는 /으로 GET 요청을 받으면 HelloEntity라는 인스턴스를 만들어서 DB에 저장하고 결과를 반환해주는 단순한 것입니다.

3. 샘플 프로젝트 배포하기

3.1. ConfigMap 작성

https://kubernetes.io/docs/concepts/configuration/configmap/

vim config.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  # property-like keys; each key maps to a simple value
  mysql-url : mysql-service

  • 환경 변수에 세팅해줄 URL 주소를 입력합니다.
  • 아래 커맨드를 입력하고 잘 되면 된 것입니다.
kubectl apply -f config.yaml

  • kubectl describe configMap mysql-config을 입력하면 들어가 있는 값이 나옵니다.
[ec2-user@ip-172-31-42-29 spring-test]$ kubectl describe configMap mysql-config
Name:         mysql-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
mysql-url:
----
mysql-service

BinaryData
====

Events:  <none>

3.2. Secret 작성

  • 아이디와 비밀번호 등 민감한 정보는 config에 그대로 노출되면 안 됩니다.
    • 파일에 그대로 저장하면 위험합니다.
  • Secret은 암호화된 상태로 저장하기 때문에 털려도 그나마 괜찮습니다.
  • 그러나 설정하지 않으면 기본적으로 암호화 상태로 저장되지 않습니다.
  • 그래서 쿠버네티스에 배포할 수 있는 권한을 가진 사람이 간접적으로 접근 가능합니다.
  • 암호화하려면 따로 설정이 필요합니다.
  • 하지만 우리는 테스트니까 하지 않을 것입니다.

https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret

  • 아래 커맨드를 사용하시기 바랍니다.
echo -n mysql-user | base64 # bXlzcWwtdXNlcg==
  • stringData 옵션을 사용하면 data 옵션을 대체할 수 있습니다. 하지만 특수문자를 포함한 문자열은 사용할 수 없습니다.
  • 저희는 stringData 옵션을 사용할 예정입니다.
  • 아래 커맨드를 입력하여 mysql-secret.yaml 파일을 적용합니다.
apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  password: mysql-password

  • kubectl describe secret secret-basic-auth 를 입력하면 아래와 같은 결과가 나타납니다.
Name:         secret-basic-auth
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/basic-auth

Data
====
password:  14 bytes

3.3 MySQL Deployment & Service 작성하기

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ 에서 예시를 확인할 수 있습니다.

apiVersion: apps/v1

kind: Deployment

metadata:

  name: nginx-deployment

  labels:

    app: nginx

spec:

  replicas: 3

  selector:

    matchLabels:

      app: nginx

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.14.2

        ports:

        - containerPort: 80

아래와 같이 수정해봅시다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deploy
  labels:
    app: mysql
    tier: database
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: 'mysql:8.0.26'
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: mysql
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306

이후 kubectl apply -f mysql-deployment.yaml 를 입력합니다.

kubectl get all 로 파드, 서비스, 배포 그리고 레플리카셋을 확인할 수 있습니다.

아래와 같이 파드가 잘 동작하면 성공입니다.

NAME                                READY   STATUS    RESTARTS   AGE
pod/mysql-deploy-847cd594ff-8hkkc   1/1     Running   0          5s

로그를 자세히 확인하려면 아래의 커맨드를 입력합니다.

kubectl logs -f pod/mysql-deploy-847cd594ff-8hkkc

아래와 같은 로그가 나타나면 준비가 완료된 상태입니다.

2023-02-22T04:59:55.553138Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.26'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

배시 쉘에서 직접 접속하려면 아래의 커맨드를 입력합니다.

kubectl exec -it pod/mysql-deploy-847cd594ff-8hkkc bash

패스워드는 아까 시크릿에서 명시한 mysql-password 입니다. exit 두 번 입력하여 콘솔로 나옵니다.

3.4 Spring 배포와 Service 작성하기

MySQL 배포와 형식이 비슷하기 때문에, 일단 아래와 같이 복사합니다.

cp mysql-deployment.yaml spring-deployment.yaml

그리고 수정을 좀 해줄 겁니다. 저희가 만든 테스트 프로젝트는 환경 변수가 3개이고, 사용자는 그냥 root를 넣고, 비밀번호는 시크릿, URL은 config를 참조할 겁니다.

  • MYSQL_USER
  • MYSQL_PWD
  • MYSQL_URL
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-demo-deploy # 이름을 바꿔줍니다.
  labels:
    app: spring-demo # 레이블을 바꿔줍니다.
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-demo # 당연히 바꿔줍니다.
  template:
    metadata:
      labels:
        app: spring-demo # 당연히 바꿔줍니다.
    spec:
      containers:
        - name: spring-demo # 당연히 바꿔줍니다.
          image: 'lee01042000/k8s-auto-deployment-test:main-2023-02-21T11-36-33'
          ports:
            - containerPort: 8080 # Spring은 8080 포트를 사용하므로 바꿔줍니다.
          env:
            - name: MYSQL_USER
              value: root
            - name: MYSQL_PWD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
            - name: MYSQL_URL
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-url

서비스도 추가해 줄 겁니다. 나중에 외부에서 이 파드에 접속하려면 서비스가 있어야 합니다.

apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

정갈한 버전은 아래와 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-demo-deploy
  labels:
    app: spring-demo
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-demo
  template:
    metadata:
      labels:
        app: spring-demo
    spec:
      containers:
        - name: spring-demo
          image: 'lee01042000/k8s-auto-deployment-test:main-2023-02-21T11-36-33'
          ports:
            - containerPort: 8080
          env:
            - name: MYSQL_USER
              value: root
            - name: MYSQL_PWD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
            - name: MYSQL_URL
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-url
---
apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

kubectl get all을 실행해 보세요. 아래와 같이 잘 나오면 성공입니다.

NAME                                     READY   STATUS    RESTARTS   AGE
pod/mysql-deploy-847cd594ff-8hkkc        1/1     Running   0          52m
pod/spring-demo-deploy-c9798b78d-bs5c7   1/1     Running   0          4s

로그를 찍어 보세요.

kubectl logs -f pod/spring-demo-deploy-c9798b78d-bs5c7

로그가 잘 찍히면 실행된 것입니다. 굿굿!

3. 요청해보기

모든 파드와 서비스는 미니큐브 안에 있으므로, 현재는 ec2 로컬에서 요청할 수 없습니다. 스프링 서비스를 미니큐브 바깥으로 연결해야 합니다. 이를 위해서는 로드밸런서나 노드포트를 이용해서 구현할 수 있습니다. 이전에 작성한 서비스를 수정해 봅시다.

apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  type: NodePort #스펙에 노드포트 추가
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30007 # 미니큐브 바깥으로 연결할 포트번호 미니큐프ip:30007로 서비스에 연결가능

기존 파일을 수정한 코드는 아래와 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-demo-deploy
  labels:
    app: spring-demo
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-demo
  template:
    metadata:
      labels:
        app: spring-demo
    spec:
      containers:
        - name: spring-demo
          image: 'lee01042000/k8s-auto-deployment-test:main-2023-02-21T11-36-33'
          ports:
            - containerPort: 8080
          env:
            - name: MYSQL_USER
              value: root
            - name: MYSQL_PWD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
            - name: MYSQL_URL
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-url
---
apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  type: NodePort
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30007

명령어를 실행한 결과를 확인해 봅시다.

kubectl get svc

위 명령어를 실행한 결과가 아래와 같으면 성공입니다.

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP          103m
mysql-service    ClusterIP   10.110.69.196   <none>        3306/TCP         7m19s
spring-service   NodePort    10.104.52.108   <none>        8080:30007/TCP   5m37s

이제 콘솔에서 minikube ip를 입력하면, 미니큐브에 할당된 로컬 아이피가 나옵니다. curl 192.168.49.2:30007을 입력하면, 아래와 같이 응답을 받을 수 있습니다.

HelloEntity(id=0, name=Hello)

데이터베이스에 데이터가 잘 저장되어 있는지 확인해 봅시다. MySQL에 접속하고 데이터베이스들을 확인합니다.

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| k8s_test           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

데이터베이스가 생성되어 있습니다. use k8s_test;로 데이터베이스를 선택하고, show tables;로 테이블을 확인합니다.

mysql> show tables;
+--------------------+
| Tables_in_k8s_test |
+--------------------+
| hello_entity       |
+--------------------+
1 row in set (0.00 sec)

테이블도 잘 생성되어 있습니다. select * from hello_entity;를 실행하면, 데이터가 잘 저장되어 있는 것을 확인할 수 있습니다.

mysql> select * from hello_entity;
+----+-------+
| id | name  |
+----+-------+
|  0 | Hello |
+----+-------+
1 row in set (0.00 sec)

4. 외부와 연결하기

이제 minikube ip 를 외부에서 들어오는 요청과 매핑해야 합니다.

포트포워딩 방법은 여러 가지가 있습니다. kubectl에서는 다음과 같은 명령어를 사용하여 포트포워딩이 가능합니다.

kubectl port-forward --address 0.0.0.0 service/spring-service 8080:8080

위와 같이 포워딩이 수행되면 다음과 같은 메시지가 출력됩니다.

Forwarding from 0.0.0.0:8080 -> 8080
Handling connection for 8080
Handling connection for 8080

이제 웹 페이지에서 EC2 인스턴스로 요청하면 결과를 잘 받을 수 있습니다.

쿠버네틱스 외부 연결

이 글을 보는 사람은 도커와 쿠버네티스에 대한 기본적인 지식이 있다고 생각할 것입니다.

도커는 알겠는데 쿠버네티스는 처음이라면 아래 동영상을 보고 진행하시기 바랍니다.

https://www.youtube.com/watch?v=s_o8dwzRlu4&ab_channel=TechWorldwithNana

쿠버네티스 컨테이너에 외부에서 접속하는 과정은 다음과 같습니다.

외부 → nginx → minikube → ingress controller → service → pod

각각이 잘 동작하는지 확인하려면 거꾸로 구현해야 합니다.

여기서는 서비스와 파드를 구현해 볼 것입니다.

쿠버네티스에 스프링 프로젝트 배포하기

1. EC2에 Minicube 설치하기

1.1. EC2 생성하기

  • ARM 버전으로 진행하면 이슈가 많아서 x86으로 진행하는 것을 추천합니다.
  • 인스턴스는 미니큐브 조건 때문에 t2 미디엄을 사용합니다.
    • 프리티어 사용하면 미니큐브 설치 에러가 발생합니다.
  • SSH로 접속합니다.
  • 프리티어가 아니니까 주의하시기 바랍니다.
    • 제가 회사 계정이라서 괜찮았습니다.

1.2. 도커 설치하기

  • 두 단계로 나누어서 설치할 것입니다.
  • docker info를 입력해서 잘 나오면 설치가 잘 된 것입니다.

1.3. 미니큐브 설치하기

  • 공식 홈페이지에서 환경에 맞춰서 설치할 것입니다.
  • minikube version을 입력해서 잘 나오면 설치가 잘 된 것입니다.

1.4. kubectl 설치하기

  • 환경에 맞춰서 설치할 것입니다.
  • kubectl version --short를 입력해서 잘 나오면 설치가 잘 된 것입니다.

2. 샘플 프로젝트 만들기

  • MySQL과 연결되는 샘플 프로젝트를 만들 것입니다.
  • 이 부분을 뛰어넘고 싶은 분은 그냥 3번부터 시작하시면 됩니다. 제가 미리 만들어둔 프로젝트를 사용할 것입니다.
  • 참고로 제 프로젝트는 /으로 GET 요청을 받으면 HelloEntity라는 인스턴스를 만들어서 DB에 저장하고 결과를 반환해주는 단순한 것입니다.
  • 코드 블라블라

3. 샘플 프로젝트 배포하기

3.1. ConfigMap 작성

https://kubernetes.io/docs/concepts/configuration/configmap/

vim config.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql-config
data:
  # property-like keys; each key maps to a simple value
  mysql-url : mysql-service

  • 환경 변수에 세팅해줄 URL 주소를 입력합니다.
  • 아래 커맨드를 입력하고 잘 되면 된 것입니다.
kubectl apply -f config.yaml

  • kubectl describe configMap mysql-config을 입력하면 들어가 있는 값이 나옵니다.
[ec2-user@ip-172-31-42-29 spring-test]$ kubectl describe configMap mysql-config
Name:         mysql-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
mysql-url:
----
mysql-service

BinaryData
====

Events:  <none>

3.2. Secret 작성

  • 아이디와 비밀번호 등 민감한 정보는 config에 그대로 노출되면 안 됩니다.
    • 파일에 그대로 저장하면 위험합니다.
  • Secret은 암호화된 상태로 저장하기 때문에 털려도 그나마 괜찮습니다.
  • 그러나 설정하지 않으면 암호화 상태로 저장되지 않습니다.
  • 그래서 쿠버네티스에 배포할 수 있는 권한을 가진 사람이 간접적으로 접근 가능합니다.
  • 암호화하려면 따로 설정이 필요합니다.
  • 하지만 우리는 테스트니까 하지 않을 것입니다.

https://kubernetes.io/docs/concepts/configuration/secret/#basic-authentication-secret

  • 아래 커맨드를 사용하시기 바랍니다.
echo -n mysql-user | base64 # bXlzcWwtdXNlcg==
  • stringData 옵션을 사용하면 data 옵션을 대체할 수 있습니다. 하지만 특수문자를 포함한 문자열은 사용할 수 없습니다.
  • 저희는 stringData 옵션을 사용할 예정입니다.
  • 아래 커맨드를 입력하여 mysql-secret.yaml 파일을 적용합니다.
apiVersion: v1
kind: Secret
metadata:
  name: secret-basic-auth
type: kubernetes.io/basic-auth
stringData:
  password: mysql-password

  • kubectl describe secret secret-basic-auth 를 입력하면 아래와 같은 결과가 나타납니다.
Name:         secret-basic-auth
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/basic-auth

Data
====
password:  14 bytes

3.3 MySQL Deployment & Service 작성하기

https://kubernetes.io/docs/concepts/workloads/controllers/deployment/ 에서 예시를 확인할 수 있습니다.

apiVersion: apps/v1

kind: Deployment

metadata:

  name: nginx-deployment

  labels:

    app: nginx

spec:

  replicas: 3

  selector:

    matchLabels:

      app: nginx

  template:

    metadata:

      labels:

        app: nginx

    spec:

      containers:

      - name: nginx

        image: nginx:1.14.2

        ports:

        - containerPort: 80

아래와 같이 수정해봅시다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-deploy
  labels:
    app: mysql
    tier: database
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: 'mysql:8.0.26'
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
spec:
  selector:
    app: mysql
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306

이후 kubectl apply -f mysql-deployment.yaml 를 입력합니다.

kubectl get all 로 파드, 서비스, 배포 그리고 레플리카셋을 확인할 수 있습니다.

아래와 같이 파드가 잘 동작하면 성공입니다.

NAME                                READY   STATUS    RESTARTS   AGE
pod/mysql-deploy-847cd594ff-8hkkc   1/1     Running   0          5s

로그를 자세히 확인하려면 아래의 커맨드를 입력합니다.

kubectl logs -f pod/mysql-deploy-847cd594ff-8hkkc

아래와 같은 로그가 나타나면 준비가 완료된 상태입니다.

2023-02-22T04:59:55.553138Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.26'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.

배시 쉘에서 직접 접속하려면 아래의 커맨드를 입력합니다.

kubectl exec -it pod/mysql-deploy-847cd594ff-8hkkc bash

패스워드는 아까 시크릿에서 명시한 mysql-password 입니다. exit 두 번 입력하여 콘솔로 나옵니다.

3.4 Spring 배포와 Service 작성하기

MySQL 배포와 형식이 비슷하기 때문에, 일단 아래와 같이 복사합니다.

cp mysql-deployment.yaml spring-deployment.yaml

그리고 수정을 좀 해줄 겁니다. 저희가 만든 테스트 프로젝트는 환경 변수가 3개이고, 사용자는 그냥 root를 넣고, 비밀번호는 시크릿, URL은 config를 참조할 겁니다.

  • MYSQL_USER
  • MYSQL_PWD
  • MYSQL_URL
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-demo-deploy # 이름을 바꿔줍니다.
  labels:
    app: spring-demo # 레이블을 바꿔줍니다.
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-demo # 당연히 바꿔줍니다.
  template:
    metadata:
      labels:
        app: spring-demo # 당연히 바꿔줍니다.
    spec:
      containers:
        - name: spring-demo # 당연히 바꿔줍니다.
          image: 'lee01042000/k8s-auto-deployment-test:main-2023-02-21T11-36-33'
          ports:
            - containerPort: 8080 # Spring은 8080 포트를 사용하므로 바꿔줍니다.
          env:
            - name: MYSQL_USER
              value: root
            - name: MYSQL_PWD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
            - name: MYSQL_URL
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-url

서비스도 추가해 줄 겁니다. 나중에 외부에서 이 파드에 접속하려면 서비스가 있어야 합니다.

apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

정갈한 버전은 아래와 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-demo-deploy
  labels:
    app: spring-demo
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-demo
  template:
    metadata:
      labels:
        app: spring-demo
    spec:
      containers:
        - name: spring-demo
          image: 'lee01042000/k8s-auto-deployment-test:main-2023-02-21T11-36-33'
          ports:
            - containerPort: 8080
          env:
            - name: MYSQL_USER
              value: root
            - name: MYSQL_PWD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
            - name: MYSQL_URL
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-url
---
apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080

kubectl get all을 실행해 보세요. 아래와 같이 잘 나오면 성공입니다.

NAME                                     READY   STATUS    RESTARTS   AGE
pod/mysql-deploy-847cd594ff-8hkkc        1/1     Running   0          52m
pod/spring-demo-deploy-c9798b78d-bs5c7   1/1     Running   0          4s

로그를 찍어 보세요.

kubectl logs -f pod/spring-demo-deploy-c9798b78d-bs5c7

로그가 잘 찍히면 실행된 것입니다. 굿굿!

3. 요청해보기

모든 파드와 서비스는 미니큐브 안에 있으므로, 현재는 ec2 로컬에서 요청할 수 없습니다. 스프링 서비스를 미니큐브 바깥으로 연결해야 합니다. 이를 위해서는 로드밸런서나 노드포트를 이용해서 구현할 수 있습니다. 이전에 작성한 서비스를 수정해 봅시다.

apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  type: NodePort #스펙에 노드포트 추가
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30007 # 미니큐브 바깥으로 연결할 포트번호 미니큐프ip:30007로 서비스에 연결가능

기존 파일을 수정한 코드는 아래와 같습니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-demo-deploy
  labels:
    app: spring-demo
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: spring-demo
  template:
    metadata:
      labels:
        app: spring-demo
    spec:
      containers:
        - name: spring-demo
          image: 'lee01042000/k8s-auto-deployment-test:main-2023-02-21T11-36-33'
          ports:
            - containerPort: 8080
          env:
            - name: MYSQL_USER
              value: root
            - name: MYSQL_PWD
              valueFrom:
                secretKeyRef:
                  name: secret-basic-auth
                  key: password
            - name: MYSQL_URL
              valueFrom:
                configMapKeyRef:
                  name: mysql-config
                  key: mysql-url
---
apiVersion: v1
kind: Service
metadata:
  name: spring-service
spec:
  type: NodePort
  selector:
    app: spring-demo
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
      nodePort: 30007

명령어를 실행한 결과를 확인해 봅시다.

kubectl get svc

위 명령어를 실행한 결과가 아래와 같으면 성공입니다.

NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes       ClusterIP   10.96.0.1       <none>        443/TCP          103m
mysql-service    ClusterIP   10.110.69.196   <none>        3306/TCP         7m19s
spring-service   NodePort    10.104.52.108   <none>        8080:30007/TCP   5m37s

이제 콘솔에서 minikube ip를 입력하면, 미니큐브에 할당된 로컬 아이피가 나옵니다. curl 192.168.49.2:30007을 입력하면, 아래와 같이 응답을 받을 수 있습니다.

HelloEntity(id=0, name=Hello)

데이터베이스에 데이터가 잘 저장되어 있는지 확인해 봅시다. MySQL에 접속하고 데이터베이스들을 확인합니다.

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| k8s_test           |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

데이터베이스가 생성되어 있습니다. use k8s_test;로 데이터베이스를 선택하고, show tables;로 테이블을 확인합니다.

mysql> show tables;
+--------------------+
| Tables_in_k8s_test |
+--------------------+
| hello_entity       |
+--------------------+
1 row in set (0.00 sec)

테이블도 잘 생성되어 있습니다. select * from hello_entity;를 실행하면, 데이터가 잘 저장되어 있는 것을 확인할 수 있습니다.

mysql> select * from hello_entity;
+----+-------+
| id | name  |
+----+-------+
|  0 | Hello |
+----+-------+
1 row in set (0.00 sec)

4. 외부와 연결하기

이제 minikube ip 를 외부에서 들어오는 요청과 매핑해야 합니다.

포트포워딩 방법은 여러 가지가 있습니다. kubectl에서는 다음과 같은 명령어를 사용하여 포트포워딩이 가능합니다.

kubectl port-forward --address 0.0.0.0 service/spring-service 8080:8080

위와 같이 포워딩이 수행되면 다음과 같은 메시지가 출력됩니다.

Forwarding from 0.0.0.0:8080 -> 8080
Handling connection for 8080
Handling connection for 8080

이제 웹 페이지에서 EC2 인스턴스로 요청하면 결과를 잘 받을 수 있습니다.

+ Recent posts