1 VM에 개발 환경 구축하기
- Project: Agent Platform PoC 환경 구축
- 조건: Azure VM(Ubuntu 24.04)에서의 개발환경
- Azure Portal에서 Ubuntu 24.04 LTS VM을 생성한 후 git, conda, pyenv, poetry를 설치하는 과정에서 마주칠 수 있는 문제들과 해결 방법을 정리
1.1 구축할 개발환경 모식도
1.1.1 작업 환경 구조
┌─────────────────────────────────────┐
│ 로컬 PC (Windows) │
│ PowerShell Terminal │
└──────────────────┬──────────────────┘
│ SSH
↓
┌─────────────────────────────────────┐
│ Azure VM (Ubuntu 24.04) │
│ azureuser@test-agent │
│ - git │
│ - conda |
│ - pyenv │
│ - poetry │
│ - 개발 작업 환경 │
└─────────────────────────────────────┘
1.1.2 중요 개념
| 개념 | 설명 |
|---|---|
| VM (Virtual Machine) | 클라우드에서 실행되는 가상 컴퓨터 |
| Image | VM의 운영체제 템플릿 (Docker와 다름) |
| SSH | 원격 서버에 안전하게 접속하는 프로토콜 |
| Private Key | SSH 접속 인증용 파일 |
| 웹 콘솔 | Azure Portal의 브라우저 기반 터미널 (제약이 있음) |
1.2 초기 상황
1.2.1 생성한 VM 스펙
- VM명: test-agent
- OS: Ubuntu 24.04 LTS (Canonical official image)
- 크기: Standard D8as v5 (8vCPUs, 32GB RAM)
- 접속 방식:
- 웹 브라우저 콘솔 (Azure Portal 내 터미널) - sudo 제약 있음
- SSH (원격 접속) - 권장 방식
- 웹 브라우저 콘솔 (Azure Portal 내 터미널) - sudo 제약 있음
1.2.2 설치 목표
- git: source code 버전 관리
- Miniconda (conda): DL/ML/Stat dependency 관리
- pyenv: python interpreter 버전 관리
- Poetry: Python 개발관련 dependency 관리
1.3 발생한 문제들과 해결 방법
1.3.1 웹 브라우저 콘솔에서 sudo 권한 제약
- 증상
kmkim [ ~ ]$ sudo apt update
sudo: The "no new privileges" flag is set, which prevents sudo from running as root.
sudo: If sudo is running in a container, you may need to adjust the container configuration to disable the flag. - 원인
- 웹 브라우저 콘솔 = Azure Portal의 웹 화면 내에 내장된 터미널 창 (Cloud Shell이 아닌 경우)
- Azure Portal의 웹 브라우저 콘솔은 보안상
no-new-privileges플래그가 설정되어 있어서 sudo 권한 상승이 불가능
- 이는 컨테이너 환경의 제약이 아니라 웹 콘솔 자체의 보안 제한
- 왜 이런 제한이 필요한가?
- 웹 브라우저는 악성 JavaScript나 공격으로 조작될 수 있음
- 브라우저 콘솔을 통해 root 권한을 얻을 수 있다면, 전체 VM을 장악당할 위험 증가
no-new-privileges플래그는 이미 실행 중인 프로세스가 권한을 상승시키는 것을 막음 (기존 권한 유지는 가능)
- 따라서 웹 콘솔로 일반 사용자(azureuser) 작업은 가능하지만, sudo로 root 권한이 필요한 작업은 차단
- 웹 브라우저는 악성 JavaScript나 공격으로 조작될 수 있음
- 웹 브라우저 콘솔 = Azure Portal의 웹 화면 내에 내장된 터미널 창 (Cloud Shell이 아닌 경우)
- 해결책
- 웹 브라우저 콘솔대신 local cmd prompt (power shell)에서 SSH로 직접 접속
1.3.2 Local에서 SSH 접속 방법
- 증상
- 웹 콘솔의 sudo 제약으로 인해 패키지 설치가 불가능한 상황
- 웹 콘솔의 sudo 제약으로 인해 패키지 설치가 불가능한 상황
- SSH란?
- SSH (Secure Shell) = 인터넷을 통해 원격 컴퓨터에 안전하게 접속하는 프로토콜
- 자세한 내용은 SSH 개요 블로그 참조
- SSH (Secure Shell) = 인터넷을 통해 원격 컴퓨터에 안전하게 접속하는 프로토콜
- 장점
- 웹 콘솔의 제약이 없음
- sudo 권한이 정상 작동
- 웹 콘솔보다 더 안정적이고 빠름
- 로컬에서 언제든 접속 가능
- 웹 콘솔의 제약이 없음
- 웹 브라우저 콘솔 vs SSH의 차이:
| 항목 | 웹 브라우저 콘솔 | SSH |
|---|---|---|
| 접속 방식 | Azure Portal 웹 페이지 내 | 암호화된 네트워크 연결 |
| 보안 | 웹 브라우저 보안 정책 적용 (제약 많음) | 공개키 암호화 (매우 강력) |
| 권한 | no-new-privileges 플래그로 sudo 차단 |
일반 사용자이지만 sudo 가능 |
| 통신 | 평문 또는 약한 암호화 | 모든 데이터 암호화 (AES-256 등) |
| 인증 | Azure Portal 로그인 | Private Key 파일 기반 |
| 안정성 | 브라우저 다운시 연결 끊김 | 네트워크만 안정하면 지속 연결 |
- SSH 접속 단계
1단계: Private Key 파일 준비
- VM 생성 시 Azure가 생성한
test-agent_key.pem파일을 다운로드
- 보통 Downloads 폴더에 저장됨
- VM 생성 시 Azure가 생성한
2단계: 로컬 PowerShell(Windows) 또는 Terminal(macOS/Linux)에서 접속
ssh -i C:\Users\kmkim\Downloads\test-agent_key.pem azureuser@20.196.144.16
-i옵션은 Identity file(신원 확인 파일)을 지정하는 옵션
3단계: 첫 접속 시 호스트 인증
The authenticity of host '20.196.144.16' can't be established. Are you sure you want to continue connecting (yes/no)?→
yes입력4단계: 접속 완료
azureuser@test-agent:~$
1.3.3 Conda 설치 시 권한 부족
- 증상
azureuser@test-agent:~$ bash Miniconda3-latest-Linux-x86_64.sh -b -p /opt/conda
mkdir: cannot create directory '/opt/conda': Permission denied
ERROR: Could not create directory: '/opt/conda'. - 원인
/opt디렉토리는 root 권한이 필요
- azureuser는 일반 사용자이므로 직접 접근 불가.
- 해결책
1.3.4 Conda 초기화 실패
- 증상
azureuser@test-agent:~$ sudo /opt/conda/bin/conda init bash
no change /root/.bashrc
No action taken. - 원인
sudo로 실행하면 root의.bashrc가 수정되지만, azureuser로 로그인하면/home/azureuser/.bashrc를 사용
- 해결책
- sudo 없이 실행하거나, 수동으로 초기화 코드를 추가
# sudo 없이 실행. conda가 자동으로 .bashrc를 수정
/opt/conda/bin/conda init bash
# 실행 결과: .bashrc에 다음과 같은 긴 초기화 블록이 자동 추가됨
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/opt/conda/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
eval "$__conda_setup"
else
if [ -f "/opt/conda/etc/profile.d/conda.sh" ]; then
. "/opt/conda/etc/profile.d/conda.sh"
else
export PATH="/opt/conda/bin:$PATH"
fi
fi
unset __conda_setup
# <<< conda initialize <<< # 수동으로 초기화: conda shell.bash hook를 실행하여 초기화에 필요한 최소한의 코드만 생성
# eval로 그 코드를 실행하도록 .bashrc에 추가
# 자동 초기화와 동일한 효과
echo 'eval "$(/opt/conda/bin/conda shell.bash hook)"' >> ~/.bashrc
source ~/.bashrc - Conda 설치 확인
1.3.5 Pyenv 설치
1.3.5.1 Python 개발 환경 구축
- conda와 pyenv는 python interpreter의 버전을 독립적으로 관리한다.
- conda는 deep learning, machine learning, statistics 관련 패키지들과 더불어 java, c++과 같은 python외 개발 관련 가상환경을 관리한다.
- pyenv는 오로지 python으로만 개발이 될 프로젝트용으로 사용되며 python version만 관리하고 후에 설치할 poetry와 맞물려 사용된다.
- conda는 deep learning, machine learning, statistics 관련 패키지들과 더불어 java, c++과 같은 python외 개발 관련 가상환경을 관리한다.
- 사실, conda는 순서에 상관없이 나중에 설치해도 되지만 python개발환경 구축시엔 git이 편의성에 있어서 필요할 수 있다.
- pyenv는 Python을 설치하고 버전을 관리하는 도구이다
- Poetry는 Python 위에서 실행되므로, Python이 먼저 설치되어야 한다.
- python 개발 환경 구축 순서는 다음의 단계를 따라야한다.
- pyenv 설치 (Python 버전 관리자)
- Python 3.11 설치 (프로그래밍 언어로 pyenv로 설치해야함)
- Poetry 설치 (Python 패키지 관리자, Python 3.11 기반으로 설치)
- pyenv 설치 (Python 버전 관리자)
- Pyenv 설치
# 방법1
curl https://pyenv.io/install.sh | bash # 회사 네트워크 방화벽때문에 pyenv.io 네트워크 접근 불가 → GitHub clone으로 해결
# 방법2: GitHub에서 직접 clone (권장)
git clone https://github.com/pyenv/pyenv.git ~/.pyenv 설치 후 PATH 설정
- pyenv를 Shell 환경에 영구 등록
- heredoc(히어닥) 문법: 여러 줄의 텍스트를 파일에 추가하는 방식
cat >> ~/.bashrc << 'EOF'
[여기에 작성된 내용들]
EOF
cat >> ~/.bashrc << 'EOF'
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
EOF
source ~/.bashrc 코드 설명
1. cat >> ~/.bashrc
* cat: 텍스트를 출력하는 명령어
* >>: 파일 끝에 추가(append)하라는 의미 (> 하나만 쓰면 덮어쓰기)
* ~/.bashrc: 현재 사용자의 홈 디렉토리(~)에 있는 .bashrc 파일
2. << ‘EOF’
* <<: heredoc 시작을 의미 (여러 줄 입력 시작)
* ‘EOF’: 입력 종료 마커 (End Of File)
* 작은따옴표(’)로 감싸면 → 변수 치환 안 함 (문자 그대로 저장)
* 큰따옴표(“) 또는 따옴표 없으면 → 변수 치환 함
3. export PYENV_ROOT=”\(HOME/.pyenv"
* export: 환경 변수를 설정하고 자식 프로세스도 사용 가능하게 만듦
* PYENV_ROOT: pyenv가 설치된 위치를 저장하는 변수
* "\)HOME/.pyenv”: /home/azureuser/.pyenv (사용자 홈 폴더의 .pyenv 디렉토리)
4. export PATH=“\(PYENV_ROOT/bin:\)PATH”
* PATH: Shell이 명령어를 찾는 경로 목록
* \(PYENV_ROOT/bin: pyenv 실행 파일이 있는 폴더를 PATH 맨 앞에 추가
* :\)PATH: 기존 PATH 내용은 뒤에 유지
* 왜 맨 앞에? → 같은 이름의 명령어가 있으면 pyenv 버전을 우선 실행
5. eval “$(pyenv init -)”
* pyenv init -: pyenv 초기화 스크립트 생성 (실제로는 긴 Shell 코드 출력)
* \((): 명령어 치환 - 괄호 안 명령어를 실행하고 결과를 반환
* eval: 문자열을 Shell 명령어로 실행
* 실제 동작: pyenv가 출력한 초기화 코드를 즉시 실행
6. eval "\)(pyenv virtualenv-init -)”
* pyenv-virtualenv 플러그인 초기화 (가상 환경 관리 기능)
* 위와 동일한 방식으로 초기화 코드 실행
7. EOF
* heredoc 종료 마커 (여기까지가 추가할 내용)
8. source ~/.bashrc
* .bashrc 파일을 즉시 재실행 → 현재 Shell에 바로 적용
* 안 하면? → 다음 로그인이나 새 터미널을 열어야 적용됨
- Pyenv 설치 확인:
pyenv --version
1.3.5.2 python 설치
ubuntu에 python이 설치되어 있지 않아 다음 메세지가 뜰 것.
pyenv: python: command not found
The `python' command exists in these Python versions:
3.11.10
Note: See 'pyenv help global' for tips on allowing both
python2 and python3 to be found. - 시스템이 인식할 python버전을 설정
# 시스템 전체의 기본 Python 버전을 3.11.10으로 설정 (OS의 python 설치 유무와 버전을 신경쓸필요없어짐)
azureuser@test-agent:~$ pyenv global 3.11.10
# global 설정하면 pyenv가 관리하는 경로로 고정 되게됨
azureuser@test-agent:~$ which python
# 또는 python의 특정 버전의 최신 버전을 찾으려면 다음의 명령어를 입력하여 확인하여 설치
pyenv install --list | grep "3.11" | tail -1
# python 설치 확인
azureuser@test-agent:~$ python --version 1.3.5.3 Poetry 설치
- pip install poetry = 간편 설치
- pip(Python 패키지 관리자)를 사용
- 가장 간단하고 빠름
- pyenv로 설치한 Python 환경에 직접 설치
- 하지만 Poetry 공식 문서는 이 방법을 권장하지 않음
- pip(Python 패키지 관리자)를 사용
- curl 방식 = 공식 권장 설치 (독립 설치)
- Poetry 설치 스크립트를 다운받아 실행
- Poetry를 시스템 Python과 분리하여 독립 환경에 설치
~/.local/bin에 독립 설치
- 독립 환경이라 충돌 없음
- 더 깨끗하고 안전함
- Poetry 공식 문서의 표준 방법
- Poetry 설치 스크립트를 다운받아 실행
# 방법 2: 공식 설치 스크립트 (권장)
curl -ssl https://install.python-poetry.org | python3 -
export PATH="$HOME/.local/bin:$PATH"
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
poetry --version # 확인 - 발생 가능한 귀찮은 문제
- pip 방식의 문제
# Python 3.11에서 poetry 설치
pyenv global 3.11.10
pip install poetry
# 나중에 Python 3.12로 변경
pyenv global 3.12.5
# poetry가 사라짐!
poetry --version
# bash: poetry: command not found - curl 방식은 안전
1.4 VM 종료 및 관리
1.4.1 VM 중지 (비용 절감)
또는 Azure Portal에서 Virtual Machines → test-agent → Stop 클릭
- Stop: 비용 청구 안 됨, 나중에 재시작 가능
- Delete: 주의! VM 완전 삭제 (복구 불가)
1.4.2 VM 재시작
1.5 편의성 개선 (선택사항)
1.5.1 PowerShell에 SSH Alias 설정
PowerShell 프로필 편집:
다음 추가:
Set-Alias -Name ssh-vm -Value 'ssh -i C:\Users\kmkim\Downloads\test-agent_key.pem azureuser@20.196.144.16' 이후 접속:
1.6 SSH Key 관리 (여러 VM/서버 사용할 때)
- Key가 여러 개일 때 관리 방법
- Azure VM, AWS EC2, GitHub, GitLab 등 여러 서비스를 사용하면 SSH Key가 점점 많아진다.
- Azure VM, AWS EC2, GitHub, GitLab 등 여러 서비스를 사용하면 SSH Key가 점점 많아진다.
- SSH Key 관리 전략
- Key 저장소 통일 (
.ssh폴더)
- Key 저장소 통일 (
# Windows의 .ssh 폴더 (자동 생성됨)
C:\Users\kmkim\.ssh\
# Key 파일들을 모두 여기에 정리
C:\Users\kmkim\.ssh\
├── azure-vm-test-agent.pem # Azure VM용
├── aws-ec2-dev.pem # AWS EC2용
├── github-personal # GitHub용 (확장자 없음)
├── gitlab-work # GitLab용
├── id_rsa # 기본 key (old format)
└── id_ed25519 # 최신 key format - SSH Config 파일로 Host 별칭 관리
SSH config 파일 생성:
다음 내용 추가:
# Azure VM - test-agent
Host azure-test
HostName 20.196.144.16
User azureuser
IdentityFile C:\Users\kmkim\.ssh\azure-vm-test-agent.pem
Port 22
# AWS EC2 - Development Server
Host aws-dev
HostName ec2-1-2-3-4.compute-1.amazonaws.com
User ec2-user
IdentityFile C:\Users\kmkim\.ssh\aws-ec2-dev.pem
Port 22
# GitHub
Host github.com
HostName github.com
User git
IdentityFile C:\Users\kmkim\.ssh\github-personal
# GitLab
Host gitlab.com
HostName gitlab.com
User git
IdentityFile C:\Users\kmkim\.ssh\gitlab-work
- 간단한 접속 명령
* SSH config를 설정하면 긴 명령을 단축
Before (설정 전):
After (설정 후):
- Key 권한 설정 (Windows)
* SSH Key는 신중하게 보관
* Windows에서는:
# .ssh 폴더 우클릭 → 속성 → 보안 → 고급
# 현재 사용자만 읽기/쓰기 권한 허용
# 다른 사용자는 접근 차단
# 또는 PowerShell로:
icacls "C:\Users\kmkim\.ssh" /inheritance:r /grant:r "$env:USERNAME`:(F)" - SSH Key 명명 규칙 (권장)
<서비스>-<용도>-<환경>.pem
예:
- azure-vm-dev.pem
- aws-ec2-prod.pem
- github-personal
- gitlab-work-deploy