반응형

개요

  • GPU 컴퓨팅 고도화
  • Model은 어떻게 관리해야 할까
  • 앞으로 해결해나가야 할 문제

이전 포스팅 

GPU 인스턴스 구성을 구성해보자 - 1

 


GPU 컴퓨팅 고도화

이전 p5 타입의 인스턴스에 gpu를 활성화까지 진행하고, 대체로 잘 동작하고 있었다.

하지만 이게 동작이 결국에 docker-compose 형태로 동작이 되고, 문제 시 Rollback 이나 CI/CD 구조내에서 많은 문제가 있었다.

그에따라 Devops 인원들이 붙어서 배포를 관리해주는 건 너무 비효율적이었다.

 

아무래도 바쁜데 이런것까지 잡아먹힐 수는 없으니, 어떻게 구성하는것이 좋을까 고민하던차에 ECS on EC2 형태가 어떨까... 싶었다.

 


GPU 타입의 ECS Cluster 생성

ECS Cluster 내에서 GPU 옵션이 붙어있는 EC2를 생성할 수 있었다.

원래는 EKS로 구축하려 했으나... 아직은 회사가 EKS를 받아들이기에는 시기상조

 

그리고 띄워봤는데, 띄우자 마자 gpu 활성화 없이 바로 gpu가 활성화 되어있네?

이전에 하루 다 날린 결과물이 허탈할 지경이었다.

이미 활성화 되어있는 gpu
ecs agent 까지 준비완료

좋아 목표는 아래와 같다

  • 기존 CD 구성형태로 ECS 배포 관리
  • ECS Agent를 활용하여 Self healing 구성
  • 배포 알림 시스템 구성

GPU ECS Task Definition

{
    "family": "<family name>",
    "containerDefinitions": [
        {
            "name": "<ecs name>",
            "image": "<image arn>",
            "cpu": 0,
            "memory": <memory>,
            "portMappings": [
                {
                    "name": "<server>",
                    "containerPort": <container port>,
                    "hostPort": 0,
                    "protocol": "tcp",
                    "appProtocol": "http"
                }
            ],
            "essential": true,
            "environment": [
                {
                    "name": "CUDA_VISIBLE_DEVICES",
                    "value": "0"
                },
                {
                    "name": "MKL_NUM_THREADS",
                    "value": "4"
                },
                {
                    "name": "TZ",
                    "value": "Asia/Seoul"
                },
                {
                    "name": "NUMEXPR_NUM_THREADS",
                    "value": "4"
                },
                {
                    "name": "GPU_SETTING",
                    "value": "0"
                },
                {
                    "name": "NUMEXPR_MAX_THREADS",
                    "value": "4"
                },
                {
                    "name": "NVIDIA_DRIVER_CAPABILITIES",
                    "value": "compute,utility"
                },
                {
                    "name": "OMP_NUM_THREADS",
                    "value": "4"
                }
            ],
            "environmentFiles": [],
            "mountPoints": [],
            "volumesFrom": [],
            "ulimits": [
                {
                    "name": "nofile",
                    "softLimit": 65536,
                    "hardLimit": 65536
                }
            ],
            "logConfiguration": {
                "logDriver": "awsfirelens",
                "options": {
                    "apikey": "<datadog api key>",
                    "compress": "gzip",
                    "provider": "ecs",
                    "dd_service": "<server>",
                    "Host": "http-intake.logs.datadoghq.com",
                    "TLS": "on",
                    "dd_source": "inference-server",
                    "dd_tags": "env:<environment>,team:<team>,role:server,app:<server>",
                    "Name": "datadog"
                },
                "secretOptions": []
            },
            "systemControls": [],
            "resourceRequirements": [
                {
                    "value": "1",
                    "type": "GPU"
                }
            ]
        },
        {
            "name": "datadog-agent",
            "image": "public.ecr.aws/datadog/agent:latest",
            "cpu": 0,
            "links": [],
            "portMappings": [
                {
                    "containerPort": 8126,
                    "hostPort": 8126,
                    "protocol": "tcp"
                }
            ],
            "essential": true,
            "entryPoint": [],
            "command": [],
            "environment": [
                {
                    "name": "ENVIRONMENT_NAME",
                    "value": "<environment>"
                },
                {
                    "name": "SERVICE_NAME",
                    "value": "<server>"
                },
                {
                    "name": "DD_API_KEY",
                    "value": "<datadog api key>"
                },
                {
                    "name": "ECS_FARGATE",
                    "value": "true"
                },
                {
                    "name": "DD_APM_ENABLED",
                    "value": "true"
                },
                {
                    "name": "DD_LOGS_ENABLED",
                    "value": "true"
                },
                {
                    "name": "APPLICATION_NAME",
                    "value": "<server>"
                }
            ],
            "mountPoints": [],
            "volumesFrom": [],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "<group>",
                    "awslogs-create-group": "true",
                    "awslogs-region": "ap-northeast-2",
                    "awslogs-stream-prefix": "ecs-service"
                }
            },
            "systemControls": []
        },
        {
            "name": "firelens_log_router",
            "image": "amazon/aws-for-fluent-bit:stable",
            "cpu": 0,
            "links": [],
            "portMappings": [],
            "essential": true,
            "entryPoint": [],
            "command": [],
            "environment": [
                {
                    "name": "SERVICE_NAME",
                    "value": "<server>"
                },
                {
                    "name": "ENVIRONMENT_NAME",
                    "value": "<environment>"
                },
                {
                    "name": "APPLICATION_NAME",
                    "value": "<server>"
                }
            ],
            "mountPoints": [],
            "volumesFrom": [],
            "user": "0",
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group": "<group>",
                    "awslogs-create-group": "true",
                    "awslogs-region": "ap-northeast-2",
                    "awslogs-stream-prefix": "ecs-service"
                },
                "secretOptions": []
            },
            "systemControls": [],
            "firelensConfiguration": {
                "type": "fluentbit",
                "options": {
                    "config-file-type": "file",
                    "config-file-value": "/fluent-bit/configs/parse-json.conf",
                    "enable-ecs-log-metadata": "true"
                }
            },
            "credentialSpecs": []
        }
    ],
    "executionRoleArn": "arn:aws:iam::<accountId>:role/ecsTaskExecutionRole",
    "networkMode": "bridge",
    "volumes": [],
    "placementConstraints": [],
    "requiresCompatibilities": [
        "EC2"
    ],
    "cpu": "8192",
    "memory": "24576",
    "runtimePlatform": {
        "cpuArchitecture": "X86_64",
        "operatingSystemFamily": "LINUX"
    },
    "enableFaultInjection": false
}
  • 기존 ECS Task Definition 과 동일하나 GPU 옵션이 몇몇 추가되었다.
  • 또한 DataDog 을 사용하는 만큼, 관련 SideCar도 추가하였다.

결과는? -> 잘 동작함 

이참에 이렇게 할걸 ... 약간 후회


Model은 어떻게 관리해야 할까?

EC2 on ECS 로 구성을 하고, 나서 큰 문제는 없었으나 아래와 같은 이슈가 발생하였다.


모델 추가 변경의 건 - 첫번째 시도 (Git LFS)

Dev : 모델업데이트를 해야되는데 어떻하죠?

Devops : 모델은 VCS에 못올리나요?

Dev : 모델자체가 크기가 커서 에러가 납니다.

Devops : Git LFS로 올려야될것 같네요. 확인해보겠습니다.

 

모델을 생각못한건 아니지만, 아니 솔직히 생각못하긴 했다.

그래서 모델을 Git LFS를 사용하기로 했다.

git lfs install

git lfs track "~~.pt"
git lfs track "~~.lib"
git lfs track "~~.dll"

>> 산출물

## .gitattributes

* text = auto
~~.pt filter=lts diff=lfs merge=lfs -text
~~.lib filter=lts diff=lfs merge=lfs -text
~~.dll filter=lts diff=lfs merge=lfs -text

근데, 이걸 설정하고 CD를 진행하려 보니 문득 이런생각이 들었다.

 

LFS 사용한다면?

  • Git LFS를 설정 -> Git Storage 비용 발생 -> CD 내에서 LFS 관련 옵션 설정 -> 어차피 CD 할때마다 Pull / Push 함...

S3 사용한다면? 

  • 필요 모델 S3에 올림 -> S3 비용발생 -> CD 내에서 S3 파일다운받아서 해제 
Devops : ~~님, 혹시 모델 변경이 잦을까요?

Dev : 아뇨, 잦지는 않을 것 같습니다. 현재는 개발중이라 수정이 될텐데
추후에는 한달에 한번정도만 수정 될 것 같아요

Devops : OK

모델 추가 변경의 건 - 두번째 시도 ( S3 사용하자)

 

S3로 선택한 건, 더 편하고 비용친화적이고 관리하기 더 편할것같아서 

머리아픈 LFS 보다는 S3를 선택하기로 했다.

 

CD 단에서 S3 데이터를 풀어서 Dockerizing 하면 끝이라고 생각했다.

## action 내에서 발췌

- name: Pull Models
  run: |
   aws s3 cp s3://<S3 Bucket>/models.zip .
      
- name: Unzip Models
  run: |
   unzip -o models.zip

 

오... 잘 동작하는데?


앞으로 해결해나가야 할 문제

  • GPU 인스턴스 내 배포문제
    • 현재 p5.xlarge, p5.2xlarge 타입을 사용하고 있는데
    • 각각 사용할 수 있는 GPU는 1개씩이다.
    • 이 얘기는 배포 시, Rolling Update가 안된다.

이 문제의 대해서는 일단 최소 인스턴스를 2개 운영하는 방식으로 구성하기로 했다.

물론 개발환경만 DeploymentConfiguration 을 조절해서 Recreate 방식으로 수정했다.

운영은 다운타임이 발생해서 일단 좋은방법이 나타날때까지 GPU 인스턴스를 2개 운영하는것으로 대체...

 

  • 운영환경 내 비용효율화 문제
    • 일단 개발환경은 SPOT 인스턴스로 대체하여, 어느정도의 비용은 낮췄다.
    • 그외 더 좋은 방법이 없을까 고민했지만 -> 애초에 GPU 옵션을 사용하는 서비스에서 비용효율화... 가능할까?
  • 더 좋은 방법 없을까?
    • SageMaker를 고려중이다.
    • 이건 좀더 공부해봐야 할 것 같다.
반응형
반응형
  • 모델 소스코드가 파일크기가 너무커서... 자체 GitLab을 만들기로 했다 (LFS용)

 

Resource Name / Desc
OS amazon-linux 2 (ARM64)
Computing t4g.medium
Storage gp3 ( 100GB ) 

 

Gitlab Install

sudo yum update -y

sudo yum install curl \
policycoreutils-python \
openssh-server \
openssh-clients \
perl \
posfix -y

sudo systemctl enable sshd
sudo systemctl start sshd

sudo systemctl enable postfix
sudo systemctl start postfix

## 필요한 경우 (X)
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash

## 실제 도메인으로 변경 (domain 로 구성) - gitlab 설치
sudo EXTERNAL_URL="http://domain..." yum install -y gitlab-ce

 

Gitlab 설정

sudo vi /etc/gitlab/gitlab.rb
# 다음 설정들을 필요에 따라 수정:
# external_url 'http://Domain...'
# gitlab_rails['gitlab_shell_ssh_port'] = 22
# postgresql['shared_buffers'] = "256MB" # RAM에 따라 조정

# 설정 적용
sudo gitlab-ctl reconfigure
# 8GB swap memory 설정
sudo dd if=/dev/zero of=/swapfile bs=1M count=8192
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 부팅시 자동 마운트
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# 백업 디렉토리 생성
sudo mkdir -p /var/opt/gitlab/backups
sudo chmod 700 /var/opt/gitlab/backups

# 백업 설정 (gitlab.rb에 추가)
sudo vi /etc/gitlab/gitlab.rb

# 다음 라인 추가:
# gitlab_rails['backup_path'] = "/var/opt/gitlab/backups"
# gitlab_rails['backup_keep_time'] = 604800 # 7일

# 설정 적용
sudo gitlab-ctl reconfigure
sudo cat /etc/gitlab/initial_root_password ## 초기설정 시 비밀번호 확인

# /etc/gitlab/gitlab.rb에 추가
postgresql['shared_buffers'] = "2GB"  # RAM의 25%
nginx['worker_processes'] = 4         # CPU 코어 수만큼
nginx['worker_connections'] = 2048

# /etc/gitlab/gitlab.rb에 추가
gitlab_rails['env'] = {
  'MALLOC_ARENA_MAX' => 2
}

 

Gitlab SMTP + AWS SES 설정

// /etc/gitlab/gitlab.rb
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "email-smtp.ap-northeast-2.amazonaws.com"
gitlab_rails['smtp_port'] = 465
gitlab_rails['smtp_user_name'] = "SES에서 생성한 SMTP 사용자 이름"
gitlab_rails['smtp_password'] = "SES에서 생성한 SMTP 비밀번호"
gitlab_rails['smtp_domain'] = "SES에서 설정한 도메인"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_tls'] = true
gitlab_rails['smtp_force_ssl'] = true

# 발신자명을 설정하고 싶다면 다음을 추가
gitlab_rails['gitlab_email_from'] = '발신자 이메일 도메인'

// 저장 후 설정 - 재부팅
sudo gitlab-ctl reconfigure

 

Gitlab Status 확인

sudo gitlab-ctl status | cat
반응형
반응형

개요

  • ECS가 뭔데?
  • Kubernetest가 정답인가?
  • 그럼에도 왜 ECS Fargate를 사용하는가?
  • ECS Fargate 를 잘 활용하는 방법

 


ECS 가 뭔데?

 

간단하다. ECS ( Elastic Container Service )

Container 기반 서비스를 AWS 내 쉽게 띄우기 위한 하나의 시스템이다.

어쩌면 Docker 기반의 구성된 서비스를 굉장히 쉽게 만들어서 Cloud 시스템에 구축할 수 있겠는가? -> 그게 바로 ECS라고 생각한다

 


ECS를 사용하면 뭐가 좋은가?

보통 ECS를 얘기하면, 매번 나오는게 EKS와 비교하게 된다.

하지만 그전에 간단하게 Docker 기반 시스템을 구축하기 위한 서비스를 어느정도 나열해보면 아래와 같다.

 

Layer로 나눠본 Container 기반 시스템 구성


Layer 1. Docker를 쓴다 - EC2에 올려서 쓴다

뭐... 굉장히 심플하다

Dockerfile을 구성하든, docker-compose를 구성하든 그 자체로 EC2에 올려서 서비스를 한다.

정말 간단하다는 말 외에는 따로 할 말이 없다

하지만 그 간단함 때문에 -> 많은 부분들이 고민이 되는 부분이다

모니터링, 로그, 배포, Self Healing, Rollback 모든 부분에서 손수 수작업을 진행해야 한다.


 Layer 2. Orchestration Tool을 사용하되, EC2를 사용한다

보통 production 즉, 회사내에서 서비스를 운영하는 단계라면 Layer 2 에서 시작하는 것 같다.

기본적인 Orchestration 을 사용하되, ECS , EKS 를 EC2를 host로 사용한다.

물론 나쁘진 않다. 하지만 나는 Serverless 더 선호한다. ( 비용 및 효율성 측면에서 어쩔 땐 EC2 기반이 좋을 때가 존재함 )


Layer 3. Serverless 형태로 사용한다

Serverless...

마법의 단어다. 대부분의 고민거리를 해결해준다.

물론 Serverless 가 모든 고민거리, 기술적 이슈들을 해결해주진 않는다.

Serverless 이기에 겪는 문제도 있고, 여전히 손수 수작업으로 해줘야 할 부분도 존재한다.

그럼에도 불구하고 관리하기 편하기때문에 Devosp Engineer 입장에서는 업무 시간에 다른부분을 더 강화할 시간을 벌게된다.

 


Kubernetes가 정답인가?

대부분의 회사에서 사용하는 스택이나, 개발자 취업 사이트를 보면 Kubernetes를 사용한다. 

거의 무조건 사용하고, 사용 / 활용할 수 있는 사람을 뽑는다.

왜 그럴까? ECS 보다 Kubernets가 더 좋은 점은 무엇일까? (경험기반...)

 


EKS는 자유롭다

EKS 만큼 자유로운 시스템은 또 없다.

여기서 자유롭다라는 뜻은, 따로 vendor에 구애 받지 않는다는 얘기다.

 

K8S 는 GCP, AWS, Azure Multi Cloud내에 GKE, EKS, AKE 여러개로 불리기도하고, 온프레미스에서도

동작방식이 같아 흔히 Cloud Lock In 현상을 줄일 수 있다.

 

ECS만 봐도 AWS에서만 사용가능하고,

GCP에서는 Cloud Run, App Engine 같은 기능을 써야하기 때문에 그것의 비해서는 자유롭다.

 


배포 전략이 자유롭다 (CNCF)

ECS는 기본적인 Rolling Update, Code Deploy를 사용해서 Blue/Green, Canary 배포방식을 사용할 수 있다.

하지만 좀더 트래픽을 세밀하게 조절해서 배포하는 방안들의 대해서는 굉장히 많은 노력이 필요하다.

 

그에 반해, K8s 같은 경우에는 Traffic Splitting 같은 배포전략을 Istio로 한다거나, ArgoCD 같은 Tool로 굉장히 

다양한 방법의 배포 / Rollback 기능을 활용할 수 있다.

 


AutoScaling 시, 세부적으로 Control 이 가능하다

ECS도 이건 가능하다. 불가능하지는 않다.

간단하게 CPU, Memory 기반으로도 AutoScaling 가능하고

CloudWatch를 연동해서 SQS, SNS, ALB의 지표등을 확인해서 다양한 AutoScaling 전략을 사용할 수 있다.

 

하지만 K8s 같은 경우에는 더 세밀하게 조정이 가능한데 HPA & VPA 을 사용하면 CPU, Memory 기반으로 자동확장이 더 유연하다.

그리고 애초에 Node , Pod 기반으로 동작하기 때문에 당연한 얘기기도 하다

 

추가적으로 Karpenter 이놈을 쓰면 굉장히 도움이 많이 때문에 좀 부럽긴하다.

나중에 Kaprenter 기능을 Deep 하게 공부해서 글써보면 도움이 많이 될지도...

 


Addons가 너무 훌륭하다 (CNCF)

사실 이 부분은 넘사벽이라고 생각하는데,

ECS도 AWS 내부서비스와 조합은 훌륭하다.

하지만 K8s는 CNCF 내 오픈소스와 다양한 툴링이 가능하다.

 

어떤것이 좋다. 어떤것이 있다. 하나하나 세부적으로 얘기하지 않아도 

정말 좋은 오픈소스나 툴이 있다고 하면 대부분 K8S 를 기반으로 만들어져 있다.

 


그럼에도 왜 ECS Fargate 를 사용하는가?

간단하다...

쉽다...

아주 적은 인원으로, 여러개의 서비스를 구축할 때 이만한건 없는 것 같다.

내가 생각했을 때 굉장히 좋은 시스템이고 Lock In이 걸렸다면 어쩔수 없지만...

당분간 AWS 만 쓸건데, Lock In 정도야 ... 큰 문제일까 싶다.

 


그래도 나름대로 비용 효율성

AWS내에서 K8s를 사용하려면 EKS 옵션이 있는데,

이건 Cluster 비용이 별도로 나간다. 큰 비용은 아니지만 월에 $ 70 ~ 80 발생한다.

하지만 ECS는 Cluster를 여러개 만들어도 공짜이기 때문에 짱짱맨이다.

 


나는 인프라 이런거 모르고 그냥 개발에만 집중할래

딱 이런 사람들에게는 최적의 솔루션이 아닌가 싶다.

ECS Fargate 를 사용하면 정말 많은것을 해준다.

Self Healing도 해주고, Auto Scaling도 너무 쉽고, ALB나 Event Bridge pipe를 사용해서 여러 서비스와 조합도 가능하다.

그리고 Scale-up 하는것도 굉장히 옵션이 다양하기 때문에 GPU 기반이나 LLM을 크게 돌릴것이 아니라면 더할나위 없다.

 

 

ECS Fargate 를 잘 활용하는 방법

솔직히 개인적인 경험으로는 기존 ECS Fargate를 사용해도 큰 문제는 없지만

몇몇 더 잘 사용하면 기존보다 2~3배 가량 더 잘 사용할 수 있다고 생각한다.

 


비용 효율화 (SPOT 인스턴스)

ECS Fargate OS System은 총 2가지로 나뉜다

  • ARM
  • x86_64

이때 x86_64를 사용하게되면 SPOT 인스턴스를 사용할 수 있다.

물론 SPOT 인스턴스 자체가 동작하는 원리는 AWS 내 노는 컴퓨팅을 잠시 빌려써서 다시 임대하는 형식이기 때문에,

가끔은 죽을 수도 있다.

 

그렇기에 개발 / 스테이징 / 데이터 배치 같은 가끔은 죽어도 되는 애들은 SPOT 인스턴스를 고려해보는것도 좋은것같다.


ECS Fargate 가 아닌, EC2 on ECS도 고려해보자

너무 위에서 ECS Fargate 만 얘기했지만,

EC2에 ECS 사용하는 옵션도 굉장히 좋다.

 

GPU, 그외 다른 성격을 가진 Computing 유형도 ECS를 사용해서 편하게 배포하고 구성하고를 사용할 수 있다 (ecs agent)

추가적으로 보통 ECS Fargate 에서는 서비스 당 ENI를 하나씩 가지게된다 (network mode)

 

하지만 EC2 on ECS는 다양한 network mode를 선택 할 수 있다.

network mode 설명
bridge - EC2 내부에 Docker bridge 사용
- Container 간 NAT 통신
host - 컨테이너나 EC2의 네트워크를 직접사용 (IP공유)
- EC2에 바인딩 된 포트 그대로 사용
- 보안이슈가 존재

 

그래서 고성능 네트워크가 필요하다거나, 특정 포트를 컨테이너 내에서 직접 노출한다거나,

로드밸런서가 아닌 EIP로 바로 트래픽을 받는 어느정도 특수한 환경일 경우, 위와같이 처리할 수 있다.

 

결론

정말 대규모의 시스템이나 비용효율적인 방안들을 검토해서 구성을 해야한다면 K8S 가 정답일 수도 있다고 생각한다.

하지만 본인 내지, 회사의 도메인과 서비스를 이해하고 현재 어느수준에 있는지를 파악한다면 어떤 솔루션이 적합한지 한번쯤은 더 생각해볼수 있지 않을까 생각한다.

 

물론 나도 K8S를 하고싶지만, 현재 ECS 를 사용하면서도 회사의 비즈니스는 정말 잘 굴러간다.

그렇다고 ECS -> K8S 갈아탄다고 해서 서비스 안정성이 올라가냐?, 트래픽이 올라가냐? 그건 아니다.

 

하지만 K8S로 마이그레이션하거나 진행해야 할때는 있을거다.

그때를 위해서 공부는 꾸준히 해놓자...

 

 

반응형

'Architecture > Computing' 카테고리의 다른 글

self hosted 로 gitlab 설치하기  (0) 2025.03.27
python 앱 빌드시간 단축  (0) 2025.01.12
반응형

개요

  • GPU 인스턴스를 구축해보자
  • GPU 활성화 하기
  • Docker 내에서는 왜 안되지?
  • Docker 에서도 GPU 활성되게 하기

GPU 인스턴스를 구축해보자

최근 추론모델을 학습하기 위해서, GPU를 사용하는 인스턴스가 필요했다.

가만보자...

gpu 가 있는 인스턴스

현재 회사에서 알맞은 스펙은 Amazon EC2 g5로 진행하기로 했다.

테스트하고, 비교한 결과는 내부적인 자료라서 공유하기는 애매하고....

많은 테스트를 통해서 g5.2xlarge 를 사용하기로 하였다.

 

 

가격은 시간 당 $ 1.212

하루에 1.212 * 24 = $ 29

한달에 30 * 29 = $ 872  (매우 비싸다...)


 

GPU 활성화하기

EC2 기본적인 스펙은 아래와 같다.

운영체제 Computing Storage
ubuntu g5.2xlarge 150 GB (gp3)

 

사실 처음에 gpu 인스턴스를 구축하면, 자동으로 gpu가 있는건 줄 알았는데, 

driver를 직접 설치하고 구성을 해야 하더라...

이것도 모르고 왜 느리지?... 했었따.

 


기본적인 Ubuntu 환경 세팅

sudo apt-get update -y
sudo apt install gcc -y

sudo apt-get install linux-headers-$(uname -r)
sudo apt install ubuntu-drivers-common -y

ubuntu-drivers devices

 

ubuntu-drivers devices를 하게되면 아래 화면이 나타난다.

 

ubuntu nvidia driver

여기서 그냥 아무것도 모르고 driver 낮은 버전설치했다가 -> 호환이 안되서 시간만 엄청 잡아먹었다.

왠만하면 recommended 로 된걸로 설치하자 (2025.3.24일 기준 - nvidia-driver-550)

 


gpu driver 설치

sudo apt-get install nvidia-driver-550
sudo reboot ## 재부팅 후에 적용 완료 됨
nvidia-smi

 

오우 여기까지 나왔다면, 

nvidia gpu가 설치가 된거다 (스크린샷은 470으로 찍힘)

 


Docker 내에서는 왜 안되지?

docker 서비스를 gpu 인스턴스에 띄워놓고, 테스트를 해보니... 추론모델이 cpu 만 사용하였다.

 

아... 뭐가 문제지

알고보니, container내에서 gpu를 사용하기 위해선 자체적인 toolkit 을 설치해야 한다. (이걸 알아차리기까지 2시간 가까이 소요됨)

 


container toolkit 설치 (docker가 설치가 이미 되어있다는 가정)

# NVIDIA GPG 키와 리포지토리 추가
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

# NVIDIA Container Toolkit 설치
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

docker run --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi

## docker deamon을 재구성
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

docker run --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi

 


과연 잘 구성이 되었을까?

docker info | grep Runtimes

이렇게 나와야 함 - 1

docker exec -it [container-id] /bin/sh
nvidia-smi ## nvidia 사용현황이 나와야 함

이렇게 나와야 함 - 2

 


 

Docker 에서도 GPU 활성되게 하기

자 그럼 Container 내에서, 잘 동작되는지 확인이 되었으니 명령어에 gpu를 사용한다고 명시해보자...

 


docker run 명령어에 gpu 옵션 추가

docker run --gpus all [이미지명] [명령어]

 


docker-compose 에 gpu 옵션 추가

version: '3.8'
services:
  [추론모델]:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: [추론모델]
    ports:
      - "8888:8888"
    restart: unless-stopped
    volumes:
      - ./logs:/app/logs
    environment:
      - TZ=Asia/Seoul
    deploy:                             ## 이 부분 부터 추가
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8888/ping"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

gpu를 잘 쓰고있다.

 

서버상태를 보니 기존 3초정도 걸렸던 작업이 -> 0.2 ~ 0.5 초로 줄었다.

결국 happy ending

 

앞으로 해야할 일

  • gpu 인스턴스를 EC2 로 구성하였다 -> AutoScaling, 모니터링, Disk 관련 부분들을 다시한번 점검해봐야 한다
  • 현재 Service Code 모델로 인해 10~20GB 정도된다. 현재는 어쩔수 없이 S3로 주고받으나 다른방법을 모색해봐야 한다
    • Github Submodule...
    • Github Self hosted...
  • CI/CD CD 구성은 아직 안했는데, main push 되면 ssm Run Command가 EC2에 명령을 질의하게끔 하면 되지 않을까?

 

나처럼 많이 헤멜것 같은 분들에게 한줄기 희망이 되길...

한 12번 포기할뻔 했는데 다행이 해냈다.

반응형
반응형

개요

  • 현재 CD 는 어떤 구성으로 되어있는가?
  • 잘 돌아가나? 
  • 문제점 파악 및 효율적인 방안 고민
  • CodeBuild + Github Action 구성 방안
  • 현재는?

 

현재 회사에서는 Github Action을 Self Hosted 로 사용하고있다 (2024.8 ~ 현재까지)

조금은 특이? 하게 사용하고 있다.

원래의 Action을 Self Hosted로 사용하는 대부분의 활용예제는 EC2 Computing 1대 = Action 방식으로 사용하고 있었고,

내가 생각했을때는 좀 비효율적인 방식이라고 생각하여, Computing Spec 하나에 Github Action Image를 여러개 둬서 병렬 처리로 하는 방식을 활용했다.

 


현재 CD는 어떤구성으로 되어있는가?

 

 

대략적인 구조도는 이런 형태로 되어있다. 순서대로 CD 구성을 보면

  1. 개발자는 Git Repository에 Merge / Tag 배포를 진행하게 된다.
  2. 자체 Action 내에서 Lambda를 호출하고 해당 Lambda 함수는 Self Hosted로 된 EC2를 (Stopping -> Running) 상태로 변경한다.
  3. 이 후 Running 상태의 EC2는 각각의 action 이미지를 빌드하여 CD를 진행하게 된다.

잘 돌아가나?

6~7 개월 사용하다보니, 잘 돌아가긴 하지만 살짝살짝 애매한 부분이 하나씩 들어났다.

 

1. 동작의 불확실 성

아무래도 람다 - EC2 형태로 구성하다보니, 가끔 Ec2가 안뜨거나, Lambda 함수가 호출이 안되는 등 

꽤 여러문제가 발생하였다. 사실 비용문제때문에 Action이 안돌때는 저렇게 한건데....

 

저 형태를 떼어내려 하니, 결국 사용하지 않을때는 EC2는 Stop 형태로 만들어야 한다 이런 결론이 나왔다.

2. EC2 관리

Self hosted로 된 EC2를 관리하다보니, 처음 EC2 + Action로 관리를 하니 아래파일들을 만들게되었다.

파일이름 내용
Dockerfile Docker 환경에서 Action runner 실행을 위한 파일
runner-install.sh Github Action Runner 추가 스크립트
runner-remove.sh Github Action Runner 삭제 스크립트
runner-docker-up.sh 람다에서 호출하는 Action Runner 추가 스크립트
runner-docker-down.sh 람다에서 호출하는 Action Runner 제거 스크립트
runner-instance-update.sh EC2 최신상태 유지 (리눅스 패키니, Action Runner, Image)
relaim-disk-space.sh 오래된 리소스 정리 (Disk, Docker System, Volume...)
slack-noti-sh Slack Noti

 

사실 이런 문제 말고도, EC2를 관리하는 유지보수는 적지 않았다.

Multi Account로 관리하고 있는 만큼 환경 별로 EC2를 1개씩 둬야 했고,

그에따라 디스크 정리 및 여러부분을 관리하였다 (cron이나 여러부분에서 자동화를 하더라도... 문제는 존재함)

 


문제점 파악 및 효율적인 방안 고민

그럼 총 2가지 측면에서 고려해봐야 한다고 생각했다.

  1. 동작의 불확실성을 최대한 피하고, 사용할때만 CD 구성이 필요함
  2. EC2 자체의 관리를 최소화 하며, 설치 및 유지보수 비용이 간단해야 한다.

그 과정에서 고민한 결과들을 보면 하나로 대락적으로 모아졌다. -> Serverless

 


CodeBuild + Github Action 구성

언젠가 본적이 있었다 (2024년 인가...)

그 당시에는 굉장히 experiment 한 기능으로 생각했는데, 어쩌면 우리가 찾는 기능일지 몰라 테스트를 진행하고

관련해서 정말 간단하게 구성해보자고 팀원들과 PoC를 진행하였다.

 

PoC 및 실제 환경에 적용하기 위한 단계를 만들었는데 아래와 같다.

  • CodeBuild 구성을 어떻게 관리할 것인가?
  • 각 환경별로 Action 호출을 어떻게 할 것 인가?
  • Action 스크립트는 어떻게 관리할 것 인가?

CodeBuild 구성을 어떻게 관리할 것인가?

이건 꽤 간단하였다.

우리 우리팀은 Terraform으로 대부분의 AWS 인프라를 관리하고 있었고,

개발 / 스테이징 / 운영 별로 하나하나씩 만들되 구성 자체는 Terraform 으로 관리하는 것을 목표로 하였다.

또한 CodeBuild의 경우 buildspec 을 Update를 해줘야 하는데, 그 부분도 Terraform 으로 관리하는것으로 진행하였다.

 

version: 0.2

env:
  parameter-store:
    DOCKERHUB_PASS: /common/DOCKERHUB_PWD
    DOCKERHUB_USERNAME: /common/DOCKERHUB_USERNAME

phases:
  install:
    commands:
      - echo $CODEBUILD_BUILD_ID
      - echo "Installing AWS Copilot CLI for ARM64..."
      - aws s3 cp s3://[s3-bucket]/ssm ssm
      - chmod +x ssm
      - sudo mv ssm /usr/local/bin/ssm

  pre_build:
    commands:
      - docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASS

  post_build:
    commands:
      - export CODEBUILD_PROJECT_NAME=$(echo $CODEBUILD_BUILD_ID | cut -d":" -f1)
      - S3_ARTIFACT_FILE="s3://codebuild-${CODEBUILD_PROJECT_NAME}/results/failure_build_${CODEBUILD_BUILD_ID}.txt"
      - export CODEBUILD_BUILD_SUCCEEDING=2
      - aws s3 ls "$S3_ARTIFACT_FILE" > /dev/null 2>&1 || (echo "No error artifacts."; export CODEBUILD_BUILD_SUCCEEDING=1;)
      - if [ "${CODEBUILD_BUILD_SUCCEEDING}" -ne 1 ]; then
          aws s3 cp "$S3_ARTIFACT_FILE" "build-status.txt";
          if grep -q "BUILD_FAILED=true" ./build-status.txt; then
            echo "Build failed in GitHub Actions.";
            export CODEBUILD_BUILD_SUCCEEDING=0;
          else
            echo "Build succeeded in GitHub Actions.";
          fi
        fi
      - if [ "${CODEBUILD_BUILD_SUCCEEDING}" -eq 0 ]; then exit 1; fi

 

 

각 환경별로 Action 호출을 어떻게 관리할 것 인가?

개발 / 스테이징 / 운영별로 Action을 만들고 러너의 대한 호출은 Action에 Workflow 이름 패턴으로 구분하였다.

code build 에서는 필터그룹을 활용하여, 실제 부합하는 조건에 Action만 호출할 수 있다.

  • ^(action.*dev-deploy)$
  • ^(action.*stg-deploy)$
  • ^(action.*prd-deploy)$

 

Action 스크립트는 어떻게 관리할 것인가?

 

기본적으로 CD 구성은 Service Repository 와 CI/CD 에필요한 파일들은 구분해놨기 때문에,

해당 부분은 아래 그림과 같이 구성하였다. (그림으로 대체)

 

name: action-[service]-dev-deploy
on:
  push:
    tags:
      - '[service]-dev-20[2-3][0-9][0-1][0-9][0-3][0-9]-[0-9][0-9]'
  workflow_dispatch:

## [Required] 
env:
  ENVIRONMENT: dev
  SERVICE_NAME: [service]
  SLACK_CHANNEL: [slack-channel]
  S3_BUCKET: [s3-bucket]
  DOCKERFILE_PATH: [dockerfile-path]

## [Require Change runs-on]
jobs:
  build:
    runs-on:
      - [codebuild-name]-${{ github.run_id }}-${{ github.run_attempt }}
      - buildspec-override:true
    strategy:
      matrix:
        node-version: [20.x]

    steps:
      - name: Checkout tag
        uses: actions/checkout@v4
        with:
          ref: ${{ github.ref }}

      - name: Get package version
        run: |
          echo "CURRENT_TAG=$(node -p "require('./apps/[service]/package.json').version")" >> $GITHUB_ENV
          echo tag $CURRENT_TAG
      - name: Noti Workflow start
        uses: 8398a7/action-slack@v3
        with:
          icon_emoji: ":fire:"
          channel: ${{ env.SLACK_CHANNEL }}
          status: ${{ job.status }}
          author_name: "[Devops] ${{ env.SERVICE_NAME }}-${{ env.ENVIRONMENT }}"
          fields: repo,message,commit,author,action
          text: "(1 / 2) Action Start - Tag: ${{ env.CURRENT_TAG }}"
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DEVOPS_NOTI }}
        if: always()

      # [Require Change] ref ... 
      - name: Checkout build script repository
        uses: actions/checkout@v4
        with:
          repository: [build repostiroy name]
          token: ${{ secrets.ACCESS_TOKEN }}
          path: devops-repo
          ref: main

      - name: Run build script
        run: |
          $SHELL devops-repo/repository/${{ github.repository }}/${{ env.SERVICE_NAME }}/build-deploy.sh $SERVICE_NAME $ENVIRONMENT $CURRENT_TAG $S3_BUCKET $DOCKERFILE_PATH
      - name: Get and upload failed build status
        if: ${{ failure() }}
        run: |
          CODEBUILD_PROJECT_NAME=$(echo $CODEBUILD_BUILD_ID | cut -d":" -f1)
          echo "BUILD_FAILED=true" > build-status.txt
          aws s3 cp build-status.txt s3://codebuild-${CODEBUILD_PROJECT_NAME}/results/failure_build_${CODEBUILD_BUILD_ID}.txt
      
      ## Action Success
      - name: Noti Workflow Success
        if: success()
        uses: 8398a7/action-slack@v3
        with:
          icon_emoji: ":white_check_mark:"
          channel: ${{ env.SLACK_CHANNEL }}
          status: ${{ job.status }}
          author_name: "[Devops] ${{ env.SERVICE_NAME }}-${{ env.ENVIRONMENT }}"
          fields: repo,message,commit,author,action
          text: "(2 / 2) ✅  *Action* - Tag: ${{ env.CURRENT_TAG }}"
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_DEVOPS_NOTI }}

 


현재는? 잘 돌아가나...

아직까진 문제는 없었다.

기본적으로 Serverless 형태로 돌아가 문제로 삼았던 부분은 해결되었다.

BootStrapping 시간도 1~2분 대에 끝나기 때문에 Build 시간이 문제가 되진 않았다.

캐시같은 경우에는 Local Cache가 아닌, --cache-from 로 해결하였다.

 

반응형
반응형

AWS팀의 내부 Devops Tools

  • Source -> Build -> Package (패키징) 작업
  • Gamma (Staging) 에 Push
    • Gamma 구간에서는 끊임없이 테스트를 진행
    • 테스트 진행에서 알람 / 에러가 발생한다면 바로 Rollback (자동롤백)
  • Wave 라는 개념은 -> AWS는 N개의 리전이 존재하기에 Wave로 구역을 배분하여 차례대로 Push / 배포
  • Gamma -> WaveN 의 단계에서는 계속해서 Integration test를 진행하고, 그에따라 자동으로 Rollback 된다

Stage 마다 사용하는 AWS tool

소스코드를 관리 / 배포하는 방식

소스코드를 관리할때는 안전하고, 팀에 고품질을 제공할 수 있는 방식으로 배포하고 팀은 빠르게 운용할 수 있어야 한다

AWS AppConfig

  • 애플리케이션의 설정 및 구성을 중앙에서 관리 / 동적으로 업데이트 할 수 있도록 지원
  • 개발자는 애플리케이션을 재배포하거나, 다시 컴파일 하지 않아도 설정을 변경할 수 있음 -> 변경사항을 안전하게 배포
  • 장점
    • 기능 플래그 관리 -> 새 기능을, 일부 사용자에게 적용... ( A / B 테스트 가능 )
    • 기능 플래그 관리 -> AppConfig 의 설정갑을 바꿔서 특정사용자에게만 적용 가능
    • 긴급 설정 변경 -> 서버 부하가 높아지는 경우, 특정 API 요청수를 제한 하는 기능 제공
    • 긴급 설정 변경 -> 특정 값을 변경하고 싶은 경우 -> 실시간 반영
    • AppConfig를 활용하여 -> 환경별로 설정값을 분리하여 관리가능
반응형
반응형

개요

  • 폐쇄망에서 요구하는것들
  • 기존 Architecture 에서 불가능한 부분
  • 요구사항을 만족하려면?

폐쇄망에서 요구하는 것들

최근 몇몇 핀테크 회사와 제휴를 맺으면서 아래와같은 요청이 들어왔다.

 

  1. 폐쇄망회사에서 회사 제품을 호출하기위해서 등록이 필요한데 Domain이나 IP 주소좀 보내달라고 하는 경우
  2. 폐쇄망회사에서 API 통신을 하기위해서 IP를 알려달라고 하는경우

자... 대충 그림을 그리면서 이해를 해보자

 

Architecture에서 불가능한 부분

ALB IP를 전달 해주면 안됨

ALB IP 들은 고정 IP 가 아니다. 바뀐다.

만약에 ALB IP를 굳이 등록해야 한다면 ....

아래 문서를 방화벽 담당자에게 전달해주고 등록해달라고 하자 (바로 전화옴)

https://docs.aws.amazon.com/ko_kr/vpc/latest/userguide/aws-ip-ranges.html 

 

만약 WAS를 Public Subnet 에서 구성했다면?

WAS를 Public Subnet에 구성했다면 IP 주소를 줘도 좋다. 하지만 변수가 존재한다.

EIP - EC2 조합은 큰 문제가 없지만, ECS / EKS를 사용하는 경우 Public IP가 배포할때마다 변한다.

그러면 배포 후에 한 2~3분후 제휴회사에서 전화가 올수도 있다. 

만약 그렇게되면 큰일이 났다고 보면 된다...

 

 

요구사항을 만족하려면?

 

폐쇄망회사에서 회사 제품을 호출하기위해서 등록이 필요한데 Domain이나 IP 주소좀 보내달라고 하는 경우

 

제일 간단한건, Domain 자체를 등록해달라고 하면된다.

하지만 만약 방화벽에 최신것이 아닌 옛날 거라면, IP를 알려줘야 한다.

 

만약 IP가 ALB같은 동적으로 바뀐다면 AWS Global Accelerator를 고려해보자

Global Accelerator Architecture

GA (Global Accelerator)를 사용하면 각 AZ에 ENI가 생긴다.

쉽게 생각하면 해당 ALB용 EIP가 생긴다고 생각하면 좋을듯?

 

폐쇄망회사에서 API 통신을 하기위해서 IP를 알려달라고 하는경우

위에서도 언급했듯이, WAS가 Public Subnet 에 존재한다면 Private Subnet 으로 옮기자...

그리고 NAT IP를 알려주면 된다.

결국 RouteTable에도 기재했듯이, 모든 Outbound는 NAT IP를 통해서 우회하기때문에 해당 IP를 알려주면 된다.

 

 

결론

반응형

'Architecture > Network' 카테고리의 다른 글

Databricks Backend 내부망 Network 구조  (0) 2024.10.27
반응형

Backend 개발과 Devops를 거쳐 Platform Enginnering 으로

요즘 들어 내 업에 대해 많은 고민을 하고 있다.
"더 잘할 수 있을까?" 혹은 "내가 잘하고 있는 걸까?" 같은 생존에 대한 불안이 아닌,
"어떻게 일하는 것이 좋을까?" 그리고 "어떻게 하면 더 즐겁고 의미 있게 일할 수 있을까?"에 대한 고민이다.

 

그 고민의 연장선에서, 지금까지 경험한 회사와 역할들을 돌아보며 내가 해온 DevOps 업무를 플랫폼 엔지니어링 관점에서 정리해보려 한다. 규모와 투자단계를 명시하는 이유는, 각 조직의 상황에 따라 DevOps 업무가 어떤 형태로 변모해왔는지를 보여주기 위함이다.

 


 

20명 규모의 A 시리즈 스타트업 - Backend Engineer

 

이 시기의 나는 백엔드 개발자로 커리어를 시작했다.
빠르게 움직이는 작은 조직 특성상 단순히 서버 개발만으로는 역할을 다 할 수 없었고,

자연스럽게 인프라, 이벤트 기획, 데이터 분석 등 다양한 역할을 겸하게 되었다.

 

주요 업무

  • 서버 개발
  • 인프라 구성
  • 새로운 제품 개발 
  • 구매 이벤트 도출하여 비즈니스 파악

작은 회사에서는 각자 업무 외에도 제품개발부터 데이터 도출, 비즈니스 방향성 파악까지 빠르게 돌아가는

사이클 속에서 다양한 역할을 병행해야 한다. 이 과정에서 신속한 실행력 효율적인 업무처리 가 핵심이었던 것 같다.

 

당시 내가 바라본 개발자 업무는 아래와 같이 정의하였다.

  • 기한 내 서비스를 출시하기 위한 빠른 인프라 구성
  • 수동 작업을 자동화하여 빠르게 릴리즈하기
  • 서버 개발자의 연장선상에서 이뤄지는 작업 ( 인프라 구성, Devops )

말 그대로 "기술을 적용하는 것" 자체가 Devops 업무라고 생각했다.


500명 규모의 B 시리즈 게임 회사 - Devops Engineer

 

조직 규모가 커지고 분업화가 이뤄진 환경에서 DevOps에 온전히 집중할 수 있게 되었다.

이 시기부터는 기술을 '어떻게 적용할 것인가' 보다, '왜 적용해야 하는가'에 대한 고민이 더 깊어졌다

 

좀 큰 회사를 가니, 이전 스타트업 과는 다르게 아래 업무? 의사결정? 의사소통? 이 추가되었다

 

얼떨결에 추가된 사항들

  • 업무는 많지만, 각각 조직이 세분화 되어있어, 뭔가를 하기전에 협의를 진행해야 함
  • 본부 / 팀 / 파트끼리는 많은 회의와 의사결정 과정에서 일정이 결정됨 
  • 회의 / 논의 / 커피챗 때문에 일하는 시간이 가끔 적어짐 ( 해당 회사 특징일 수 있음 )

주요 업무

  • 시키는일 잘 하기 ( Director 님 지시)
  • CI/CD 파이프라인 구성 및 개선
  • AWS 기반 인프라 설계 및 운영 (Network, Computing, Database)
  • 모니터링 / Observability 구성
  • ISMS 대응 및 보안정책 설계
  • 새로운 기술 PoC 수행

해당 회사내 본부에서는 Devops 업무를 하는사람은 Director님과 나 밖에 없었기에,

거의 대부분의 구성업무는 혼자서 진행했던 것 같다. 하지만

 

첫회사와 비교해봤을 때, 업무자체는 굉장히 Specialized 해졌다.

이때의 나는 Devops Engineer 업무는 아래와 같이 정의하였다.

  • 개발자가 안정적으로 배포하고 모니터링할 수 있는 환경을 만드는 사람
  • 서비스 품질을 높이는 자동화와 효율성을 인프라 구성 설계

뭔가... 이전에는 계속만들고 적용하고 했다면

해당 회사를 다니면서 적용하기전에 많은 고민을 하고 진행했던 것 같다.

그 과정에서 계속 인프라를 구성하고 그것을 고도화하기 위한 방안 및 검토를 많이 했던 것 같다.


100명 규모 B 시리즈 핀테크 회사 - Devops Team Lead

 

현재 회사를 다니면서 팔자에도 없는 팀장를 맡게되었다.

굉장히 Long Story 이긴하지만, 입사할때만 해도 팀원이었고 우여곡절을 겪어 팀장대리를 달고

업무를 진행하면서 본격적으로 입사 5개월차에 팀장을 맡게되었다. 

 

전체적인 인원과 팀의 규모는 이전과는 적어졌지만,

직급에서 오는 특이점으로 인해서 업무를 진행하는 시야가 달라졌다 -> ( 시야가 달라져야 했다 )

 

주요 업무

  • DevOps 팀의 업무 조율 및 목표 설정
  • 모니터링 및 장애 대응 (SRE 관점에서...)
  • 인프라 안정성 유지 및 보안 업무 병행
  • 반복되는 수동 작업 자동화
  • 신기술 도입 및 사내 확산 전략 수립

이 시점에 SRE나, Platform Engineering 과 같은 직무를 있다는 것을 알게되었고 

해당 직무들이 기존 내가 경험하고 알고있던 Devops Engineer와 다른점이 뭔지 천천히 공부하게 되었다.

 

이 시점에서 나의 고민은 기술적 효율성, 구성 이런것들 보다 아래 물음의 대한 고민들을 많이 하게되었다.

  • 어떻게 하면 누구나 쉽게 인프라를 다룰 수 있을까?
  • 어떻게 하면 효율적으로 수동적인 업무를 자동화할 수 있을까?
  • 어떤 방식으로 구성해야 개발자 UX 를 높이면서 업무 효율성을 추구할 수 있을까?

자 그럼, 어떻게 해야 누구나 쉽게 인프라를 다루고, 수동적인 업무를 자동화하고, 업무 효율성을 추구할 수 있을까?

해당 회사를 다니면서 위 2개의 회사와 크게 차이점이 있었다.

  • 이미 인프라는 어느정도 구축이 되어있음
  • 대대적인 인프라 구조 변경은 필요하지 않음 (단, K8s 도입등은 예외)
  • 오히려 보안과 관리체계, 내부 운영 프로세스 개선이 주요 포인트
  • 그리고 수동적인 업무가 과도하게 많음

자... 수동적인 업무가 뭘까? ( 이걸로 시간이 꽤 많이 뺏김 )

  • 신규 인프라 구성 요청
  • 환경변수 등록 및 변경 요청
  • 모니터링 설정 및 알람 확인 / 등록 
  • AWS 사용관련 질문 및 지원 요청

수동적인 업무들이 보통 Devops 관련 업무들이긴 하지만,

저런 업무들로 조금씩 시간을 뺏기다 보니 정작 고도화된 업무들을 할때 나름 시간이 부족하다고 생각했다.

 


그래서 어떻게 해결한 것인가? -> Platform Engineering

 

Service Catalog 기반으로 Self 서비스 구조 만들기

  • Terraform Cloud 를 활용해 팀/서비스 단위로 IaC 템플릿을 관리
  • AWS Service Catalog 또는 Port.io 같은 도구를 도입하여 GUI 기반의 셀프 프로비저닝 제공
  • 표준화된 인프라 템플릿을 통해 개발자가 직접 필요한 리소스를 생성하고 관리할 수 있도록 유도
  • 구성된 리소스는 팀 단위 대시보드로 가시화하여 관리 편의성 향상

 

Internal Developer Platform (IDP) 도입

  • Backstage / Budibase 기반의 IDP를 구성하여 서비스 생성, 인프라 요청, 환경변수 설정 등을 통합
  • GitOps 기반으로 모든 요청이 코드로 기록되고, 추적 가능하도록 구성
  • Slack 등 협업툴과 연동하여 요청 → 승인 → 실행 → 결과 피드백 루프를 자동화

 

AIOps 도입으로 모니터링 고도화

  • 기존 임계값 기반의 경보 시스템은 False Positive 발생이 잦고, 실질적인 문제 탐지가 어려움
  • 머신러닝 기반의 이상탐지 모델을 도입하여 패턴 기반 탐지 (SageMaker , Datadog Anomaly Detection...)

결론

현재 지금은 Service Catalog와 IDP 툴을 적용해서 구성해 볼 예정이다.

관련해서 시간이 난다면 블로그에 글을 기재해보겠지만, 많은 우여곡절이 있을 것 같다.

아자아자 화이팅

반응형

+ Recent posts