[쿠버네티스] RabbitMQ와 디플로이먼트를 이용한 msa 아키텍처

최동혁·2023년 4월 27일
0

쿠버네티스

목록 보기
4/7

RabbitMQ 설정

컨피그맵

apiVersion: v1
kind: ConfigMap
metadata:
  name: rabbitmq-cm
data:
  RABBITMQ_DEFAULT_VHOST: "my_vhost"
  RABBITMQ_DEFAULT_USER: "user"
  RABBITMQ_DEFAULT_PASS: "qwer1234"

디플로이먼트

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rabbitmq-deployment
spec:
  selector:
    matchLabels:
      type: rabbitmq
  replicas: 1
  template:
    metadata:
      labels:
        type: rabbitmq
    spec:
      containers:
      - name: rabbitmq
        image: rabbitmq:latest
        envFrom:
        - configMapRef:
            name: rabbitmq-cm
  • 해당 디플로이먼트로 파드를 생성 후 파드 터미널로 이동
  • rabbitmq-plugins enable rabbitmq_management
  • 위의 명령어로 rabbitmq 실행

서비스

apiVersion: v1
kind: Service
metadata:
  name: rabbitmq-svc
spec:
  selector:
    type: rabbitmq
  ports:
  - port: 5672
    name: message-que
    targetPort: 5672
  - port: 15672
    name: dashboard
    targetPort: 15672
  type: LoadBalancer
  • rabbitmq 대시보드에 들어가기 위해 로드밸런서를 이용해 외부 ip 할당
  • 그 후, 로드밸런서가 발급받은 외부 ip:15672로 접속하면 rabbitmq의 로그인창이 뜬다.
  • 컨피그맵에서 설정해준 user와 pass를 이용해 로그인

Admin 마이크로 서비스

코드 다운

admin의 admin/settings.py

  • 컨피그맵에서 환경변수를 설정해줄 것이기 때문에, db 관련 정보와 rabbitmq url을 설정해줘야한다.
ALLOWED_HOSTS = ['*',]
...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ['DBNAME'],
        'USER': os.environ['DBUSER'],
        'PASSWORD': os.environ['DBPASS'],
        'HOST': os.environ['DBHOST'],
        'PORT': os.environ['DBPORT'],
    }
}
  • host는 전부를 허용해줘서, 외부 ip에서 접속이 가능하게 해주는 것이다.
  • db의 정보는 이렇게 바꿔준다.
  • 물론 import os를 해줘야한다.
  • 그러면 configmap에서 해당 이름으로 선언해준 변수를 가져와서 쓸 수 있다.

admin의 consumer.py

params = pika.URLParameters(os.environ['RABBITMQURL'])
  • rabbitmqurl을 쓰는 곳의 코드도 위의 코드로 바꿔준다.
  • 물론 import os는 필수

admin의 admin/producer.py

params = pika.URLParameters(os.environ['RABBITMQURL'])
  • 위의 파일에서도 위의 코드와 같이 바꿔주고 os import 확인

컨테이너 구축

파일 이동

  • 우리는 admin-app이라는 폴더를 볼륨으로 사용할 것이다.
  • 그렇기에 mkdir /admin-app 을 이용해 가장 상위에 만들어준다.

  • 위의 그림과 같이 dbdata를 제외한 admin 폴더 내부의 폴더들을 admin-app 디렉토리에 옮겨준다.

DB 컨피그맵

apiVersion: v1
kind: ConfigMap
metadata:
  name: admin-db-cm
data:
  MYSQL_ROOT_PASSWORD: 'qwer1234'
  MYSQL_DATABASE: 'admin-db'
  • MYSQL_DATABASE는 admin-db라는 데이터베이스를 생성해주는 코드이다.

장고, 컨슈머 컨피그맵

apiVersion: v1
kind: ConfigMap
metadata:
  name: admin-cm
data:
  DBNAME: "admin-db"
  DBUSER: "root"
  DBPASS: "qwer1234"
  DBHOST: "127.0.0.1"
  DBPORT: "3306"
  RABBITMQURL: "amqp://user:qwer1234@rabbitmq-svc/my_vhost"
  • 앞에서 os.environ~~ 을 이용해 불러오는 환경변수를 해당 컨피그맵에 넣어서 불러오는 것이다.
  • rabbitmq의 url은 위와 같은 형식이다.
  • 앞에는 user이름, 뒤에는 비밀번호 그리고 @ rabbitmq의 서비스 이름, 그리고 rabbitmq 컨피그맵에서 설정해준 VHOST의 이름순서다.
  • 그리고 왜 DBHOST가 127.0.0.1이냐면, 한 파드내에서는 같은 ip를 사용한다.
  • 그 파드 내에, 디플로이먼트로 장고, 컨슈머, db 총 3개의 컨테이너를 생성해놓았다. 그렇기 때문에 한 파드 내에서 각자 격리된 컨테이너를 사용하는 것이여서, 파드의 ip를 공유한다.
  • port따라 어느 컨테이너로 갈지 결정하는 것이다.

장고, 컨슈머, db 디플로이먼트

apiVersion: apps/v1
kind: Deployment
metadata:
  name: admin-deployment
spec:
  selector:
    matchLabels:
      type: admin
  replicas: 1
  template:
    metadata:
      labels:
        type: admin
    spec:
      nodeSelector:
        kubernetes.io/hostname: node1
      containers:
      - name: admin-db
        image: mysql:8.0.32-debian
        volumeMounts:
        - name: admin-db
          mountPath: /var/lib/mysql
        envFrom:
        - configMapRef:
            name: admin-db-cm
      - name: admin
        image: ddarahakit2023/admin:1.0
        startupProbe:
          tcpSocket:
            port: 8000
          initialDelaySeconds: 10
          periodSeconds: 10
        command: ["/bin/sh", "-ec", "python manage.py makemigrations && python manage.py migrate && python manage.py runserver 0.0.0.0:8000"]
        volumeMounts:
        - name: admin-path
          mountPath: /app
        envFrom:
        - configMapRef:
            name: admin-cm
      - name: admin-consumer
        image: ddarahakit2023/admin:1.0
        command: ["python", "-u", "consumer.py"]
        volumeMounts:
        - name: admin-path
          mountPath: /app
        envFrom:
        - configMapRef:
            name: admin-cm
      volumes:
      - name : admin-path
        hostPath:
          path: /admin-app
          type: DirectoryOrCreate
      - name : admin-db
        hostPath:
          path: /admin-db
          type: DirectoryOrCreate
  • 쿠버네티스에는 coredns라는게 이름 풀이를 해서 각 파드들끼리 이름으로 통신이 가능하다.
  • 여기서 주의 깊게 봐야하는 것은, nodeSelector이다.
  • 쿠버네티스를 동작시키는데, master와 worker1, 2가 기본적으로 돌아가고 있을것이다.
  • 여기에 어떤 worker를 사용해서 파드를 올릴지 정하는 것인데, 자신이 worker의 hostname을 어떤식으로 설정했냐에 따라서 설정해줘야한다.
  • 필자는 node1이라는 hostname으로 설정해놓아서 node1로 바꾸었다.
  • 그리고 db는 데이터들을 /var/lib/mysql에 놓는데, 컨테이너는 한번 내려가면 전부 지워진다. 그렇기에 master 노드에 마운트를 시켜서 컨테이너가 꺼지더라도 정보가 날아가지 않게 해줄것이다.
  • 가장 아랫줄에 보면 admin-db라는 path를 hostpath로 쓴다는 코드가 있다. 만약 없으면 직접 만들어주고, db에 대한 정보들이 저장될 것이다.
  • startupprobe는 해당 명령어를 수행해서 컨테이너를 만드는데, 만약 오류가 뜨면 계속해서 오류가 안나올때까지 실행을 시켜준다. 이걸 왜 하냐면, db, 장고, 컨슈머 순서로 만들어지면 상관없는데, 장고가 먼저 만들어진 후, db를 만들면 장고가 db와 연동이 안되서 컨테이너가 오류가 난다. 그렇기 때문에 db가 다 만들어지고 장고와 연결이 될 때까지 계속해서 재생성을 해준다.
  • command는 쉘로 접속해서 쉘 명령어로 장고의 model과 db를 연동시키는 명령어 makemigrations와 migrate를 진행하고, runserver로 서버를 구동시켜주는 것이다.

서비스(로드밸런서)

apiVersion: v1
kind: Service
metadata:
  name: admin-svc
spec:
  selector:
    type: admin
  ports:
  - port: 8000
    targetPort: 8000
  type: LoadBalancer
  • 외부에서 접속하기 위한 ip를 받고, 8000번 포트로 포워딩을 해준다.

  • 그 후, 로드밸런서에서 발급해준 ip에 8000번 포트로 접속해서 api/products로 가보면 drf UI가 나오게 된다.

  • drf는 JSON 형식으로 통신하기 때문에, 데이터를 집어넣기 위해서는 JSON 형식으로 데이터를 직접 작성해서 넣어준다.

  • 예를 들어

{
  "title" : "hi1",
  "image" : "img01"
}
  • 이런식의 json으로 여러개를 집어넣어보면

  • 이렇게 나오는 것을 볼 수 있다.

결론

  • 우리는 하나의 파드 안에 3개의 컨테이너를 집어넣었다.
  • 장고 프로젝트, 컨슈머, db 총 3개를 집어넣었는데, 이런식으로 전부 격리해서 하나의 api로 쪼개는 것이 msa의 핵심이다.

profile
항상 성장하는 개발자 최동혁입니다.

0개의 댓글