# Deployment 기본 정보 metadata: name: mysql-deployment # Deployment 이름
# Deployment 세부 정보 spec: replicas: 1 # 생성할 파드의 복제본 개수 selector: matchLabels: app: mysql-db # 아래에서 정의한 Pod 중 'app: backend-app'이라는 값을 가진 파드를 선택
# 배포할 Pod 정의 template: metadata: labels: # 레이블 (= 카테고리) app: mysql-db spec: containers: - name: mysql-container # 컨테이너 이름 image: mysql # 컨테이너를 생성할 때 사용할 이미지 ports: - containerPort: 3306 # 컨테이너에서 사용하는 포트를 명시적으로 표현 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: mysql-root-password - name: MYSQL_DATABASE valueFrom: configMapKeyRef: name: mysql-config key: mysql-database # 컨테이너 내에서 어떤 경로를 볼륨으로 사용할 지 지정 volumeMounts: - name: mysql-persistent-storage # 밑에서 설정할 volumes.name과 값이 같아야 함 mountPath: /var/lib/mysql # mysql 컨테이너 내부에 있는 경로 # 파드가 사용할 볼륨을 지정 volumes: - name: mysql-persistent-storage # 위에서 설정할 volumeMounts.name과 일치해야 함 persistentVolumeClaim: claimName: mysql-pvc # 연결시킬 PVC의 name과 동일해야 함
mysql-secret.yaml
apiVersion: v1 kind: Secret
# Secret 기본 정보 metadata: name: mysql-secret # Secret 이름
# Key, Value 형식으로 값 저장 stringData: mysql-root-password: password123
mysql-config.yaml
apiVersion: v1 kind: ConfigMap
# ConfigMap 기본 정보 metadata: name: mysql-config # ConfigMap 이름
# Key, Value 형식으로 설정값 저장 data: mysql-database: kub-practice
mysql-service.yaml
apiVersion: v1 kind: Service
# Service 기본 정보 metadata: name: mysql-service # Service 이름
# Service 세부 정보 spec: type: NodePort # Service의 종류 selector: app: mysql-db # 실행되고 있는 파드 중 'app: mysql-db'이라는 값을 가진 파드와 서비스를 연결 ports: - protocol: TCP # 서비스에 접속하기 위한 프로토콜 port: 3306 # 쿠버네티스 내부에서 Service에 접속하기 위한 포트 번호 targetPort: 3306 # 매핑하기 위한 파드의 포트 번호 nodePort: 30002 # 외부에서 사용자들이 접근하게 될 포트 번호
mysql-pv.yaml
apiVersion: v1 kind: PersistentVolume
# PersistentVolume 기본 정보 metadata: name: mysql-pv # PersistentVolume 이름
# PersistentVolume 세부 정보 spec: storageClassName: my-storage # PV와 PVC의 storageClassName이 같다면 볼륨이 연결된다. capacity: storage: 1Gi # 볼륨이 사용할 용량을 설정 accessModes: - ReadWriteOnce # 아래 hostPath 타입 활용 시 이 옵션만 사용 가능 hostPath: # hostPath 타입을 활용 (hostPath : 쿠버네티스 내부 공간을 활용) path: "/mnt/data" # 쿠버네티스 내부의 공간에서 /mnt/data의 경로를 볼륨으로 사용
mysql-pvc.yaml
apiVersion: v1 kind: PersistentVolumeClaim
# PersistentVolumeClaim 기본 정보 metadata: name: mysql-pvc # PersistentVolumeClaim 이름
# PersistentVolumeClaim 세부 정보 spec: storageClassName: my-storage # PV와 PVC의 storageClassName이 같다면 볼륨이 연결된다. accessModes: - ReadWriteOnce # 볼륨에 접근할 때의 권한 resources: # PVC가 PV에 요청하는 리소스의 양을 정의 requests: # 필요한 최소 리소스 storage: 1Gi # PVC가 PV에 요청하는 스토리지 양 (PV가 최소 1Gi 이상은 되어야 한다.)
# ConfigMap 기본 정보 metadata: name: spring-config # ConfigMap 이름
# Key, Value 형식으로 설정값 저장 data: db-host: mysql-service db-port: "3306" db-name: kub-practice
spring-deployment.yaml
apiVersion: apps/v1 kind: Deployment
# Deployment 기본 정보 metadata: name: spring-deployment # Deployment 이름
# Deployment 세부 정보 spec: replicas: 3 # 생성할 파드의 복제본 개수 selector: matchLabels: app: backend-app # 아래에서 정의한 Pod 중 'app: backend-app'이라는 값을 가진 파드를 선택
# 배포할 Pod 정의 template: metadata: labels: # 레이블 (= 카테고리) app: backend-app spec: containers: - name: spring-container # 컨테이너 이름 image: spring-server # 컨테이너를 생성할 때 사용할 이미지 imagePullPolicy: IfNotPresent # 로컬에서 이미지를 먼저 가져온다. 없으면 레지스트리에서 가져온다. ports: - containerPort: 8080 # 컨테이너에서 사용하는 포트를 명시적으로 표현 env: - name: DB_HOST valueFrom: configMapKeyRef: name: spring-config key: db-host - name: DB_PORT valueFrom: configMapKeyRef: name: spring-config key: db-port - name: DB_NAME valueFrom: configMapKeyRef: name: spring-config key: db-name - name: DB_USERNAME valueFrom: secretKeyRef: name: spring-secret key: db-username - name: DB_PASSWORD valueFrom: secretKeyRef: name: spring-secret key: db-password
spring-secret.yaml
apiVersion: v1 kind: Secret
# Secret 기본 정보 metadata: name: spring-secret # Secret 이름
# Key, Value 형식으로 값 저장 stringData: db-username: root db-password: password123
spring-service.yaml
apiVersion: v1 kind: Service
# Service 기본 정보 metadata: name: spring-service
# Service 세부 정보 spec: type: NodePort # Service의 종류 selector: app: backend-app # 실행되고 있는 파드 중 'app: backend-app'이라는 값을 가진 파드와 서비스를 연결 ports: - protocol: TCP # 서비스에 접속하기 위한 프로토콜 port: 8080 # 쿠버네티스 내부에서 Service에 접속하기 위한 포트 번호 (Service targetPort: 8080 # 매핑하기 위한 파드의 포트 번호 nodePort: 30000 # 외부에서 사용자들이 접근하게 될 포트 번호
30002번 포트로 MySQL에 직접적으로 접근할 수 있게끔 보안이 설정되어 있다는 점이다.
Service의 NodePort를 활용해 30002번 포트를 외부로 오픈해서 MySQL에 아무나 접근할 수 있게 만들었다.
보안적인 문제점 해결을 위해 Service의 종류 중 NodePort를 사용하지 않고 ClusterIP를 활용해야 한다. ClusterIP를 활용함으로써 외부에서 아무나 MySQL에 접근하지 못하게 막아야 한다.
Service 종류 - NodePort : 쿠버네티스 내부에서 해당 서비스에 접속하기 위한 포트를 열고 외부에서 접속 가능하도록 한다. - ClusterIP : 쿠버네티스 내부에서만 통신할 수 있는 IP 주소를 부여. 외부에서는 요청할 수 없다. - LoadBalancer : 외부의 로드밸런서(AWS의 로드밸런서 등)를 활용해 외부에서 접속할 수 있도록 연결한다.
mysql-service.yaml
apiVersion: v1 kind: Service
# Service 기본 정보 metadata: name: mysql-service # Service 이름
# Service 세부 정보 spec: type: ClusterIP # Service의 종류 selector: app: mysql-db # 실행되고 있는 파드 중 'app: mysql-db'이라는 값을 가진 파드와 서비스를 연결 ports: - protocol: TCP # 서비스에 접속하기 위한 프로토콜 port: 3306 # 쿠버네티스 내부에서 Service에 접속하기 위한 포트 번호 targetPort: 3306 # 매핑하기 위한 파드의 포트 번호 nodePort: 30002 # 외부에서 사용자들이 접근하게 될 포트 번호 -> 이 부분을 지운다.
서비스 오브젝트 변경사항 반영
kubectl apply -f mysql-service.yaml
이렇게 설정했다면 아래와 같은 아키텍쳐가 된 것이다.
DB를 관리하기 위해 접속해야 할 때는 쿠버네티스의 포트 포워딩을 활용해서 접속하면 된다.
아래 포트 포워딩 명령어를 사용하면 내 로컬 컴퓨터에서만 해당 파드와 연결을 허용시킬 수 있게 된다.
kubectl port-forward pod/[MySQL 파드명] 3306:3306
포트 설정 주의
이미 로컬에서 3306번 포트로 실행중이라면 접속에 실패할 수 있다. 따라서 아래와 같이 로컬에서는 13306번 포트로 접속해야한다.