[운송장 정보보호 서비스] 인프라 세팅

신현식·2023년 5월 24일
0

캡스톤디자인

목록 보기
1/7
post-thumbnail

주제 선정

기본적으로 택배 운송장에 택배서비스를 이용하는 고객의 주소와 택배 물품의 운송장 번호가 기재되어 있으며 일부 택배는 이름이 가려져 있으나 택배회사마다 가려진 이름의 위치가 달라 택배서비스 이용자의 이름도 추측이 가능할 수 있으며, 일부 운송장에는 택배서비스 이용자의 전화번호 일부가 기재되어 있다.

위와 같은 사례들과 택배 운송장 사진과 같이 택배 서비스를 이용하는 고객들은 개인정보 노출에 대한 문제를 제기하고 택배 운송장 폐기 방법에 대한 관심도 또한 증가하고 있다. 하지만 현재의 택배 운송장들은 일부 정보만 가려지고 모든 정보들이 완벽하게 가려지지는 않는다.
이와 같은 문제 인식을 통해 택배운송장의 개인정보 노출을 차단하기 위해 QR코드로 이루어진 택배운송장을 개발해 인가된 사용자인 고객, 택배 기사, 관리자에게만 QR코드를 인식할 수 있는 권한을 부여해서 개인 정보노출을 막을 수 있는 택배운송장을 구현하고 여러 택배회사들의 택배서비스를 일괄적으로 관리, 운용해 편의성을 증진하려고 한다.

인프라 아키텍쳐

  • 이전에 사용해봤었던 AWS EKS를 사용하여 쿠버네티스로 서비스를 배포

  • 백엔드 서버 파드에 PVC를 부착하여 스토리지 클래스에 의해 동적으로 PV를 생성해 EBS스토리지에 연결시킨다. EBS 스토리지는 직접 연결 스토리지에 액세스하는 단일 EC2 인스턴스용으로 설계되었기 때문에 백엔드 파드들은 모든 같은 노드에 위치시킬 필요가 있다.
    따라서 affinity를 사용하여 백엔드 파드들이 모든 같은 노드에 있도록 설정할 것이다.

  • user와 deeliver 웹/앱의 도메인을 각각 생성하여 도메인 이름에 맞는 서비스로 라우팅 되도록 설계

  • 백엔드의 경우 로드밸런싱을 통해 프론트엔드에서 받아온 트래픽을 이중화가 된 백엔드 서버로 트래픽을 분산시킨다.

  • 장애 대비를 위해서 eks node그룹에 Auto Scaling Group을 지정하여 CPU 사용률 70%가 넘으면 Backend 서버를 자동 증설 및 삭제하도록 설정

  • 백엔드의 경우 user, admin, deliver 의 3가지 서비스를 독립적으로 개발할 것이고 내부적으로 통신이 가능하도록 설계할 것이다.

  • DBMS의 데이터베이스도 기능별로 분리해서 구축한 후 필요한 내용을 공유할때 kafka를 사용하여 실시간 통신에 이용

  • 고가용성을 위해 RDS 데이터베이스 사용, 인스턴스와 RDS는 보안을 위해 각각 프라이빗 서브넷에 배치

  • 이후 Github Action을 이용하여 각 서비스의 코드를 자동으로 빌드하는 CI/CD 구축

쿠버네티스 manifest 파일

EKS Cluster 파일

apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig

metadata:
  name: exqress
  region: ap-northeast-2
  version: "1.24"

# AZ
availabilityZones: ["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c"]

# IAM OIDC & Service Account
iam:
  withOIDC: true
  serviceAccounts:
    - metadata:
        name: aws-load-balancer-controller
        namespace: kube-system
      wellKnownPolicies:
        awsLoadBalancerController: true
    - metadata:
        name: ebs-csi-controller-sa
        namespace: kube-system
      wellKnownPolicies:
        ebsCSIController: true
    - metadata:
        name: cluster-autoscaler
        namespace: kube-system
      wellKnownPolicies:
        autoScaler: true

# Managed Node Groups
managedNodeGroups:
  # On-Demand Instance
  - name: mynodes
    instanceType: t3.medium
    minSize: 2
    desiredCapacity: 2
    maxSize: 3
    privateNetworking: true
    #ssh:
    #allow: true
    #publicKeyPath: ./keypair/myeks.pub
    availabilityZones: ["ap-northeast-2a", "ap-northeast-2b", "ap-northeast-2c"]
    iam:
      withAddonPolicies:
        imageBuilder: true # AWS ECR에 대한 권한 추가
        autoScaler: true
        albIngress: true
        cloudWatch: true
        ebs: true

# CloudWatch Logging
cloudWatch:
  clusterLogging:
    enableTypes: ["*"]
  • 이전에 작성한 인프라 아키텍처대로 두개의 워커노드(EC2인스턴스)를 생성한다.
  • 각 EC2인스턴스는 2a, 2b, 2c 가용영역에 분포된다.
  • ALB 인그레스, 오토스케일링 그룹, AWS ECR에 대한 권한, cloudWatch와 스토리지를 위한 애드온을 생성한다.

front-user-deploy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: front-user-deploy
spec:
  selector:
    matchLabels:
      tier: front-user
  replicas: 1
  template:
    metadata:
      labels:
        tier: front-user
    spec:
      containers:
        - name: front-user
          image: <사용자 ID>.dkr.ecr.ap-northeast-2.amazonaws.com/front-user:27
          ports:
            - containerPort: 80
              protocol: TCP

현재 적용되어 있는 이미지는 개발한 코드를 도커 이미지로 만들어 ECR에 저장시켜둔 파일을 가져온 것이다.
이미지를 만드는 방법은 나중에 적어두겠다.

front-user-svc

apiVersion: v1
kind: Service
metadata:
  name: front-user-svc
spec:
  selector:
    tier: front-user
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 31113

front-deliver-deploy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: front-delivery-deploy
spec:
  selector:
    matchLabels:
      tier: front-delivery
  replicas: 1
  template:
    metadata:
      labels:
        tier: front-delivery
    spec:
      containers:
        - name: front-delivery
          image: <사용자 ID>.dkr.ecr.ap-northeast-2.amazonaws.com/front-delivery:53
          ports:
            - containerPort: 80
              protocol: TCP

front-deliver-svc

apiVersion: v1
kind: Service
metadata:
  name: front-delivery-svc
spec:
  selector:
    tier: front-delivery
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 31112

front-ing

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: front-ing
  annotations: # AWS에서 ALB로 사용할수 있게 함
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: instance
    alb.ingress.kubernetes.io/certificate-arn: <exqress.com 용 인증값>, <exqress-deliver.com 용 인증값>
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]'
    alb.ingress.kubernetes.io/ssl-redirect: "443"

spec:
  rules:
    - host: exqress-deliver.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: front-delivery-svc
                port:
                  number: 80
    - host: exqress.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: front-user-svc
                port:
                  number: 80

각 호스트마다 인그레스를 설정해두어서 exqress.com은 front-user-svc로 포워딩 시켜두었고 exqress-deliver.com은 front-deliver-svc로 포워딩하도록 설정해두었다.
또한 이전에 https 리다이렉트를 진행할 때 tls-redirect를 사용했었는데 이 방식으로 진행했을때는 웹에서 접속했을 땐 https가 제대로 적용이 되었다. 하지만 우리 프로젝트는 PWA 이기때문에 핸드폰으로 모바일 접속을 했을 경우에도 https로 리다이렉트가 되어야 하지만 적용되지 않았다.

관련 내용을 찾아보니 'alb.ingress.kubernetes.io/ssl-redirect: "443"' 이 어노테이션을 사용해줘야지 웹과 앱에서 모두 https로 리다이렉트되는 것을 확인할 수 있었다.

📢 sst/tls 차이 비교

back-user-deploy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: back-user-deploy
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 0
  selector:
    matchLabels:
      tier: back-user
  replicas: 1
  template:
    metadata:
      labels:
        tier: back-user
    spec:
      containers:
        - name: back-user
          image: <사용자 ID>.dkr.ecr.ap-northeast-2.amazonaws.com/back-user:26
          ports:
            - containerPort: 4002
              protocol: TCP
          volumeMounts:
            - name: ebs-volume
              mountPath: /data
          resources:
            requests:
              cpu: 200m
              memory: 200M
      volumes:
        - name: ebs-volume
          persistentVolumeClaim:
            claimName: ebs-pvc
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: tier
                    operator: In
                    values:
                      - back-delivery
              topologyKey: "kubernetes.io/hostname"
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: tier
                    operator: In
                    values:
                      - back-user
              topologyKey: "kubernetes.io/hostname"
  • 파드 어피니티를 설정하여 같은 레이블을 가지고 있는 파드들은 배척시키고 tier: back-user라는 레이블을 가지고 있는 파드와 같은 노드에 위치하도록 설정해주었다. 이는 ebs 볼륨을 사용하고 있기 때문에 백엔드 파드들을 모두 같은 노드에 위치시켜야 하기 때문이다.

back-user-svc

apiVersion: v1
kind: Service
metadata:
  name: back-user-svc
spec:
  selector:
    tier: back-user
  type: NodePort
  ports:
    - port: 80
      targetPort: 4002
      nodePort: 31118

back-user-ing

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: back-user-ing
  annotations: # AWS에서 ALB로 사용할수 있게 함
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: instance
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: back-user-svc
                port:
                  number: 80

back-deliver-deploy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: back-delivery-deploy
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 0
  selector:
    matchLabels:
      tier: back-delivery
  replicas: 1
  template:
    metadata:
      labels:
        tier: back-delivery
    spec:
      containers:
        - name: back-delivery
          image: <사용자 ID>.dkr.ecr.ap-northeast-2.amazonaws.com/back-delivery:34
          ports:
            - containerPort: 4001
              protocol: TCP
          volumeMounts:
            - name: ebs-volume
              mountPath: /data
          resources:
            requests:
              cpu: 200m
              memory: 200M
      volumes:
        - name: ebs-volume
          persistentVolumeClaim:
            claimName: ebs-pvc
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: tier
                    operator: In
                    values:
                      - back-delivery
              topologyKey: "kubernetes.io/hostname"
  • 어피니티 설정에서 이 부분은 따로 같이 있어야 하는 파드를 지정해두지 않았기 때문에 제일 먼저 생성이 된다. 이후 다른 백엔드 파드들이 delivery 파드의 위치를 보고 알맞는 노드에 위치할 것이다.

back-deliver-svc

apiVersion: v1
kind: Service
metadata:
  name: back-delivery-svc
spec:
  selector:
    tier: back-delivery
  type: NodePort
  ports:
    - port: 80
      targetPort: 4001
      nodePort: 31117

back-deliver-ing

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: back-delivery-ing
  annotations: # AWS에서 ALB로 사용할수 있게 함
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: instance
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: back-delivery-svc
                port:
                  number: 80

back-admin-deploy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: back-admin-deploy
spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 0
  selector:
    matchLabels:
      tier: back-admin
  replicas: 1
  template:
    metadata:
      labels:
        tier: back-admin
    spec:
      containers:
        - name: back-admin
          image: <사용자 ID>.dkr.ecr.ap-northeast-2.amazonaws.com/back-admin:4
          ports:
            - containerPort: 8000
              protocol: TCP
          volumeMounts:
            - name: ebs-volume
              mountPath: /data
          resources:
            requests:
              cpu: 200m
              memory: 200M
      volumes:
        - name: ebs-volume
          persistentVolumeClaim:
            claimName: ebs-pvc
      affinity:
        podAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: tier
                    operator: In
                    values:
                      - back-delivery
              topologyKey: "kubernetes.io/hostname"
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: tier
                    operator: In
                    values:
                      - back-admin
              topologyKey: "kubernetes.io/hostname"

back-admin-svc

apiVersion: v1
kind: Service
metadata:
  name: back-admin-svc
spec:
  selector:
    tier: back-admin
  type: NodePort
  ports:
    - port: 80
      targetPort: 8000
      nodePort: 31115

back-admin-ing

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: back-admin-ing
  annotations: # AWS에서 ALB로 사용할수 있게 함
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: instance
spec:
  rules:
    - http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: back-admin-svc
                port:
                  number: 80

애드온 세팅

온프레미스에서 사용했던 내용들을 AWS에서도 똑같이 사용할 수 있도록 구성하기 위해
Amazon EKS의 애플리케이션 로드 밸런싱, EBS CSI Provisioner, Metric-Server 설치, Cluster AutoscalerController, CloudWatch & Container Insights 의 애드온을 설치해준다. 이를 안해주면 ingress 나 ebs 볼륨등을 사용할 수 없기에 다음 내용을 참조하여 설치해주면 된다. 📢 eks 애드온 설치

ebs 스토리지

원래는 efs 스토리지를 사용하여 여러 가용영역에 거쳐 활용하려고 하였는데 우리가 하는 프로젝트에서 딱히 efs 스토리지를 사용하는 이점이 없었다. 그래서 ebs 스토리지를 사용하기로 결정하였는데 이는 하나의 노드에서 사용이 가능하기 때문에 위에서 파드들의 위치를 모두 한곳으로 모아두었다.

  • gp3 타입의 스토리지클래스 생성
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3
provisioner: ebs.csi.aws.com
volumeBindingMode: WaitForFirstConsumer
reclaimPolicy: Delete
parameters:
  type: gp3
  csi.storage.k8s.io/fstype: ext4
  • ebs-pvc 생성
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ebs-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: gp3

ArgoCD로 쿠버네티스 자동 배포 설정

만들어둔 yaml파일들을 git 저장소에 저장시키고 이 저장소의 url를 argocd와 연결시켜 자동으로 쿠버네티스 manifest파일들을 배포하도록 설정할 것이다.

# Argo CD 설치
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml


# 로드밸런서로 바꿈
kubectl patch svc argocd-server -n argocd -p '{"spec": {"type": "LoadBalancer"}}'

# 패스워드 찾기 
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo      

argocd에 접속하여 비밀번호는 내가 원하는 값으로 변경하고 새로운 app을 만든다.
앱생성시에 default 위치에 만들고 원격 저장소의 url로 쿠버네티스 manifest 파일들이 저장되어있는 git 저장소의 url을 입력하고 밑의 값들을 main / . 으로 바꿔준다. 그후 생성하면 자동으로 서비스들이 배포되는 것을 볼 수 있다.

profile
전공 소개

0개의 댓글