- 개발팀 전용 폴더 dev/ 생성 (standards, guides, quickstart, changes, deploys, data, history, dev_plans 이동) - 프론트엔드 전용 폴더 frontend/ 생성 (api/ → frontend/api-specs/) - 기획팀 폴더 requests/ 생성 - plans/ → dev/dev_plans/ 이름 변경 - README.md 신규 (사람용 안내), INDEX.md 재작성 (Claude Code용) - resources.md 신규 (노션 링크용, assets/brochure 이관 예정) - CURRENT_WORKS.md 삭제, TODO.md → dev/ 이동 - 전체 참조 경로 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
363 lines
8.7 KiB
Markdown
363 lines
8.7 KiB
Markdown
# 4. CI/CD 서비스 관리
|
|
|
|
[목차로 돌아가기](./README.md) | 서버: sam-cicd (110.10.147.46)
|
|
|
|
---
|
|
|
|
## Jenkins
|
|
|
|
**서비스 제어:**
|
|
|
|
```bash
|
|
sudo systemctl start jenkins
|
|
sudo systemctl stop jenkins
|
|
sudo systemctl restart jenkins
|
|
sudo systemctl status jenkins
|
|
```
|
|
|
|
**설정 파일:**
|
|
|
|
| 파일 | 용도 |
|
|
|------|------|
|
|
| /var/lib/jenkins/ | Jenkins 홈 (jobs, plugins, credentials) |
|
|
| /etc/systemd/system/jenkins.service.d/override.conf | JVM 메모리 설정 |
|
|
| /var/lib/jenkins/env-files/ | 배포 환경변수 (.env 파일) |
|
|
| /var/lib/jenkins-agent/ | Agent 워크스페이스 (빌드 실행 격리) |
|
|
| /etc/systemd/system/jenkins-agent.service | Agent systemd 서비스 |
|
|
|
|
**JVM 메모리 설정:**
|
|
|
|
```bash
|
|
# /etc/systemd/system/jenkins.service.d/override.conf
|
|
# Environment="JAVA_OPTS=-Xmx2048m -Xms512m -Djava.awt.headless=true"
|
|
|
|
# 변경 후 적용
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl restart jenkins
|
|
```
|
|
|
|
**로그:**
|
|
|
|
```bash
|
|
sudo journalctl -u jenkins -f
|
|
sudo journalctl -u jenkins --since "2 hours ago" --no-pager
|
|
```
|
|
|
|
**웹 UI:** https://ci.sam.it.kr (관리자: hskwon)
|
|
|
|
### Credential 관리
|
|
|
|
| Credential ID | 유형 | 용도 |
|
|
|--------------|------|------|
|
|
| deploy-ssh-key | SSH Username with private key | 운영/개발서버 SSH 배포 |
|
|
| gitea-api-token | Username with password | Gitea API 연동 (token을 username, 비밀번호 빈값) |
|
|
|
|
**Credential 위치:** Jenkins 관리 > Credentials > System > Global credentials
|
|
|
|
**SSH 키 경로:** /var/lib/jenkins/.ssh/id_ed25519
|
|
|
|
**환경변수 파일:**
|
|
|
|
```
|
|
/var/lib/jenkins/env-files/
|
|
react/
|
|
.env.develop # 개발서버용
|
|
.env.stage # Stage용
|
|
.env.main # 운영용
|
|
```
|
|
|
|
### 설치된 주요 플러그인
|
|
|
|
- Gitea Plugin -- Gitea Webhook 연동
|
|
- SSH Agent Plugin -- SSH 키 기반 배포
|
|
- Pipeline / Workflow Aggregator -- Jenkinsfile 지원
|
|
- Pipeline Stage View -- 파이프라인 시각화
|
|
- Blue Ocean -- 모던 UI
|
|
- NodeJS Plugin -- Node.js 도구 관리 (22.22.0)
|
|
|
|
플러그인 업데이트 후 Jenkins 재시작이 필요한 경우: `sudo systemctl restart jenkins`
|
|
|
|
### Build Agent (분산 빌드)
|
|
|
|
Built-in Node의 executor는 0으로 설정되어 있으며, 빌드는 로컬 Agent(`local-agent`)에서 실행된다.
|
|
|
|
| 항목 | 값 |
|
|
|------|-----|
|
|
| Agent 이름 | local-agent |
|
|
| Workspace | /var/lib/jenkins-agent/ |
|
|
| Executor 수 | 2 |
|
|
| 라벨 | build |
|
|
| 연결 방식 | WebSocket (Inbound) |
|
|
|
|
**서비스 제어:**
|
|
|
|
```bash
|
|
sudo systemctl start jenkins-agent
|
|
sudo systemctl stop jenkins-agent
|
|
sudo systemctl restart jenkins-agent
|
|
sudo systemctl status jenkins-agent
|
|
|
|
# Agent 로그
|
|
sudo journalctl -u jenkins-agent -f
|
|
```
|
|
|
|
> **참고**: Jenkins 마스터 재시작 시 Agent가 자동 재연결된다. Agent가 연결 실패하면 `sudo systemctl restart jenkins-agent`로 수동 재시작.
|
|
|
|
### Workspace 정리
|
|
|
|
```bash
|
|
# Agent workspace 용량 확인
|
|
sudo du -sh /var/lib/jenkins-agent/workspace/*
|
|
|
|
# 특정 workspace 삭제
|
|
sudo rm -rf /var/lib/jenkins-agent/workspace/<JOB_NAME>
|
|
|
|
# 전체 workspace 정리 (빌드 중이 아닌지 확인 후)
|
|
sudo rm -rf /var/lib/jenkins-agent/workspace/*
|
|
|
|
# 레거시 Built-in workspace (이전 빌드 잔존 시)
|
|
sudo du -sh /var/lib/jenkins/workspace/*
|
|
sudo rm -rf /var/lib/jenkins/workspace/*
|
|
|
|
# 임시 파일 정리
|
|
sudo find /tmp -name "jenkins*" -mtime +7 -delete
|
|
```
|
|
|
|
---
|
|
|
|
## Gitea
|
|
|
|
**서비스 제어:**
|
|
|
|
```bash
|
|
sudo systemctl start gitea
|
|
sudo systemctl stop gitea
|
|
sudo systemctl restart gitea
|
|
sudo systemctl status gitea
|
|
```
|
|
|
|
**설정 파일:**
|
|
|
|
| 파일 | 용도 |
|
|
|------|------|
|
|
| /etc/gitea/app.ini | 메인 설정 |
|
|
| /var/lib/gitea/data/repositories/ | Git 저장소 데이터 |
|
|
| /var/lib/gitea/log/ | Gitea 로그 |
|
|
| /var/lib/gitea/custom/ | 커스텀 설정 |
|
|
|
|
**주요 설정 (app.ini):**
|
|
|
|
```ini
|
|
[server]
|
|
DOMAIN = git.sam.it.kr
|
|
HTTP_PORT = 3000
|
|
ROOT_URL = https://git.sam.it.kr/
|
|
|
|
[service]
|
|
DISABLE_REGISTRATION = true # 회원가입 비활성화
|
|
REQUIRE_SIGNIN_VIEW = true # 로그인 필수
|
|
```
|
|
|
|
**로그:**
|
|
|
|
```bash
|
|
sudo journalctl -u gitea -f
|
|
sudo tail -f /var/lib/gitea/log/gitea.log
|
|
```
|
|
|
|
**웹 UI:** https://git.sam.it.kr (관리자: hskwon)
|
|
|
|
### 저장소 현황
|
|
|
|
| Organization | 저장소 | 설명 |
|
|
|-------------|--------|------|
|
|
| SamProject | sam-api | Laravel REST API |
|
|
| SamProject | sam-manage | Laravel Admin (mng) |
|
|
| SamProject | sam-react-prod | Next.js 프론트엔드 |
|
|
| SamProject | sam-sales | 영업자 사이트 (레거시) |
|
|
|
|
### 사용자/조직 관리
|
|
|
|
- 사이트 관리: https://git.sam.it.kr/-/admin
|
|
- 사용자 관리: https://git.sam.it.kr/-/admin/users
|
|
- 조직 관리: https://git.sam.it.kr/-/admin/orgs
|
|
|
|
**CLI로 사용자 추가:**
|
|
|
|
```bash
|
|
sudo -u git /usr/local/bin/gitea admin user create \
|
|
--config /etc/gitea/app.ini \
|
|
--username 사용자명 \
|
|
--password 비밀번호 \
|
|
--email 이메일 \
|
|
--admin # 관리자 권한 (선택)
|
|
```
|
|
|
|
### Webhook 설정
|
|
|
|
각 저장소에 Jenkins Webhook이 설정되어 있다.
|
|
|
|
| 항목 | 값 |
|
|
|------|-----|
|
|
| URL | https://ci.sam.it.kr/gitea-webhook/post |
|
|
| Content Type | application/json |
|
|
| Events | Push Events |
|
|
|
|
**Webhook 확인/테스트:** 저장소 > Settings > Webhooks
|
|
|
|
### 개발서버 동기화 (post-receive hook)
|
|
|
|
개발서버 Gitea에서 CI/CD Gitea로 자동 동기화:
|
|
|
|
**Hook 위치 (개발서버):** `/data/GIT/samproject/<repo>.git/hooks/post-receive.d/push-to-cicd`
|
|
|
|
**토큰 파일 (개발서버):** `/data/GIT/.cicd-env` (chmod 600, owner: git)
|
|
|
|
| 저장소 | 동기화 브랜치 | 비고 |
|
|
|--------|-------------|------|
|
|
| sam-react-prod | main, develop | post-update hook 비활성화 (CI/CD가 개발서버 배포 담당) |
|
|
| sam-api | main | develop은 기존 post-update hook 유지 |
|
|
| sam-sales | main | |
|
|
| sam-manage | main | 2026-02-24 hook 추가 |
|
|
|
|
> **참고:** react의 개발서버 배포는 Jenkins CI/CD 파이프라인이 처리한다.
|
|
> 기존 post-update hook의 git pull 방식(`pull_react.sh`)은 비활성화됨 (2026-02-24).
|
|
> 스크립트 위치: `/home/webservice/script/pull_react.sh`
|
|
|
|
**동기화 로그 확인:**
|
|
|
|
```bash
|
|
ssh sam-dev "tail -20 /home/webservice/logs/cicd_push_react-prod.log"
|
|
ssh sam-dev "tail -20 /home/webservice/logs/cicd_push_api.log"
|
|
ssh sam-dev "tail -20 /home/webservice/logs/cicd_push_sales.log"
|
|
ssh sam-dev "tail -20 /home/webservice/logs/cicd_push_manage.log"
|
|
```
|
|
|
|
---
|
|
|
|
## Prometheus
|
|
|
|
**서비스 제어:**
|
|
|
|
```bash
|
|
sudo systemctl start prometheus
|
|
sudo systemctl stop prometheus
|
|
sudo systemctl restart prometheus
|
|
sudo systemctl status prometheus
|
|
```
|
|
|
|
**설정 파일:**
|
|
|
|
| 파일 | 용도 |
|
|
|------|------|
|
|
| /etc/prometheus/prometheus.yml | 스크래핑 설정 |
|
|
| /var/lib/prometheus/ | 시계열 데이터 |
|
|
|
|
**바인딩:** 127.0.0.1:9090 (외부 접근 차단)
|
|
|
|
**데이터 보존:** 30일 (--storage.tsdb.retention.time=30d)
|
|
|
|
**설정 변경 후 적용:**
|
|
|
|
```bash
|
|
promtool check config /etc/prometheus/prometheus.yml # 문법 검사
|
|
sudo systemctl restart prometheus
|
|
# 또는 설정 리로드 (재시작 없이)
|
|
curl -X POST http://localhost:9090/-/reload
|
|
```
|
|
|
|
---
|
|
|
|
## Grafana
|
|
|
|
**서비스 제어:**
|
|
|
|
```bash
|
|
sudo systemctl start grafana-server
|
|
sudo systemctl stop grafana-server
|
|
sudo systemctl restart grafana-server
|
|
sudo systemctl status grafana-server
|
|
```
|
|
|
|
**설정 파일:**
|
|
|
|
| 파일 | 용도 |
|
|
|------|------|
|
|
| /etc/grafana/grafana.ini | 메인 설정 |
|
|
| /var/lib/grafana/ | 대시보드 데이터, 플러그인 |
|
|
|
|
**주요 설정:**
|
|
|
|
```ini
|
|
[server]
|
|
http_port = 3100
|
|
domain = monitor.sam.it.kr
|
|
|
|
[users]
|
|
allow_sign_up = false
|
|
```
|
|
|
|
**웹 UI:** https://monitor.sam.it.kr
|
|
|
|
---
|
|
|
|
## MySQL (CI/CD)
|
|
|
|
```bash
|
|
sudo systemctl status mysql
|
|
sudo systemctl restart mysql
|
|
|
|
# 접속
|
|
mysql # hskwon (auth_socket)
|
|
sudo mysql # root (auth_socket)
|
|
```
|
|
|
|
**주요 튜닝 설정:**
|
|
|
|
```ini
|
|
innodb_buffer_pool_size = 1536M
|
|
max_connections = 50
|
|
slow_query_log = 1
|
|
long_query_time = 2
|
|
```
|
|
|
|
**데이터베이스:** gitea (Gitea 데이터)
|
|
|
|
---
|
|
|
|
## Nginx (CI/CD)
|
|
|
|
```bash
|
|
sudo nginx -t && sudo systemctl reload nginx # 무중단 리로드
|
|
sudo systemctl restart nginx
|
|
sudo systemctl status nginx
|
|
```
|
|
|
|
**사이트 설정:**
|
|
|
|
| 파일 | 서비스 |
|
|
|------|--------|
|
|
| /etc/nginx/sites-available/git.sam.it.kr | Gitea 리버스 프록시 |
|
|
| /etc/nginx/sites-available/ci.sam.it.kr | Jenkins 리버스 프록시 |
|
|
| /etc/nginx/sites-available/monitor.sam.it.kr | Grafana 리버스 프록시 |
|
|
|
|
**git.sam.it.kr 주요 설정:**
|
|
|
|
```nginx
|
|
client_max_body_size 500M; # 대용량 Git push 허용
|
|
proxy_request_buffering off; # 스트리밍 전송 (413 방지)
|
|
```
|
|
|
|
---
|
|
|
|
## node_exporter / Certbot / fail2ban / UFW
|
|
|
|
운영서버와 동일한 명령어 체계. [운영서버 서비스 관리](./03-service-prod.md) 참조.
|
|
|
|
**UFW 규칙 (CI/CD):**
|
|
|
|
| 포트 | 프로토콜 | 용도 |
|
|
|------|---------|------|
|
|
| 22/tcp | ALLOW | SSH |
|
|
| 80/tcp | ALLOW | HTTP |
|
|
| 443/tcp | ALLOW | HTTPS | |