Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .devcontainer/sre-agent-event-lab/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "Azure SRE Agent Event Lab",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu-24.04",
"features": {
"ghcr.io/devcontainers/features/azure-cli:1": {
"version": "latest",
"extensions": "log-analytics,containerapp"
},
"ghcr.io/devcontainers/features/github-cli:1": {
"version": "latest"
},
"ghcr.io/devcontainers/features/python:1": {
"version": "3.12",
"installTools": true,
"toolsToInstall": "uv"
},
"ghcr.io/azure/azure-dev/azd:0": {
"version": "latest"
}
},
"customizations": {
"vscode": {
"extensions": [
"ms-azuretools.vscode-azurecontainerapps",
"ms-azuretools.vscode-bicep",
"ms-python.python"
]
}
},
"postCreateCommand": "cd monitor/sre-agent-event-lab && ./scripts/setup-venv.sh",
"postAttachCommand": {
"next-steps": "echo 'Next: az login --use-device-code, then cd monitor/sre-agent-event-lab && source ./scripts/lab-env.sh'"
},
Comment thread
hellices marked this conversation as resolved.
"remoteUser": "vscode"
}
35 changes: 24 additions & 11 deletions monitor/sre-agent-event-lab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,54 @@ Azure Container Apps에 장애를 세 번 주입하고, Azure Monitor 경고를
- Storage 계정(Standard_LRS)
- 1분 주기 로그 검색 경고 규칙 3개(평가 주기가 짧을수록 규칙당 단가가 올라갑니다)

Azure SRE Agent는 이 실습이 만들지 않습니다. 미리 만들어 둔 Agent를 사용하며 [별도로 과금](https://azure.microsoft.com/pricing/details/sre-agent/)됩니다.

안전 경계는 스크립트가 강제합니다.
Azure SRE Agent는 이 실습이 만들지 않습니다. 미리 만들어 둔 Agent를 사용하며 [별도로 과금](https://azure.microsoft.com/pricing/details/sre-agent/)됩니다. 안전 경계는 스크립트가 강제합니다.

- 현재 azd 환경이 가리키는 구독과 `az account show`의 활성 구독이 다르면 실행을 거부합니다.
- 리소스 그룹에 `purpose=sre-agent-event-lab`과 `azd-env-name=<현재 environment>` 태그가 모두 없으면 거부합니다.
- 한 번에 한 시나리오만 실행하며, 이전 시나리오가 복구·캡처될 때까지 다음 시나리오를 막습니다.
- 응답 계획은 모두 `Review` 모드로 두어 Agent가 승인 없이 변경하지 못하게 합니다.
- `evidence/`에는 비밀 값, 연결 문자열, 액세스 토큰을 저장하지 않습니다.

## 시작하기: fork와 Codespaces

이 실습은 **본인 fork에서** 진행합니다. Agent에 저장소를 연결하면 조사 결과 이슈가 그 저장소에 생성되므로, 원본을 연결하면 참가자 전원의 이슈가 한곳에 쌓이고 쓰기 권한도 없습니다.

1. 이 저장소를 본인 계정으로 fork합니다.
2. fork에서 **Code > Codespaces > New with options**를 열고 dev container로 `Azure SRE Agent Event Lab`을 고릅니다. `az`, `azd`, `gh`, Python, `uv`가 설치되고 `postCreateCommand`가 `setup-venv.sh`를 실행해 `app/.venv`까지 만듭니다.
3. 터미널에서 로그인한 뒤 환경을 한 번 읽습니다.

```bash
az login --use-device-code
azd auth login

source ./monitor/sre-agent-event-lab/scripts/lab-env.sh
```

`lab-env.sh`는 `azd`가 게시한 배포 출력만 읽어 리소스 그룹·구독·Container App·Storage 범위 등을 현재 셸에 export하고, 값이 하나라도 없으면 `LAB_READY=0`으로 알려 줍니다. 이후 가이드의 명령은 이 값들을 그대로 사용하므로 단계마다 다시 조회하지 않습니다. 비밀 값은 읽지도 출력하지도 않습니다.

로컬에서 진행한다면 아래 사전 조건을 직접 갖춘 뒤 같은 `source` 한 줄로 시작합니다. Codespaces에서는 dev container가 이미 갖춰 줍니다.

## 사전 조건

- `az`, `azd`, `jq`, `curl`, `python3`
- `az`, `azd`, `jq`, `curl`, `python3`, [`uv`](https://docs.astral.sh/uv/getting-started/installation/) — `uv`는 `app/.venv`를 만드는 `scripts/setup-venv.sh`가 쓰는 유일한 도구이며, 사내 프록시로 구성된 인덱스 설정을 그대로 씁니다(공개 PyPI `pip` 폴백 없음).
- `az extension add --name log-analytics` (`az monitor log-analytics query` 제공)
- `az login`과 `azd auth login` — 두 CLI는 자격 증명을 따로 관리합니다.
- 구독 Contributor, 역할 할당을 위한 Owner 또는 User Access Administrator
- Azure SRE Agent를 만들 수 있는 [지원 지역](https://learn.microsoft.com/azure/sre-agent/supported-regions) 접근 권한
- 브라우저에서 `https://sre.azure.com` 및 `*.azuresre.ai` 접근
- Agent에 연결할 GitHub 저장소 권한
- [`uv`](https://docs.astral.sh/uv/getting-started/installation/) — `app/.venv`를 만드는 `scripts/setup-venv.sh`가 이 도구만 사용하며, 사내 프록시로 구성된 `uv`의 인덱스 설정을 그대로 씁니다. 공개 PyPI로 우회하는 `pip` 폴백은 없습니다.
- Agent에 연결할 GitHub 저장소 권한 — 본인 fork처럼 이슈를 만들 수 있는 저장소여야 합니다

이 실습의 모든 명령은 아래에서 한 번만 진입하는 이 디렉터리를 기준으로 합니다.

```bash
cd monitor/sre-agent-event-lab
```

로컬 검증만 먼저 해 보려면 다음을 실행합니다.
로컬 검증만 먼저 해 보려면 다음을 실행합니다. Codespaces에서는 `setup-venv.sh`가 이미 실행된 상태입니다.

```bash
./scripts/setup-venv.sh
app/.venv/bin/python -m pytest app -q

bash -n scripts/*.sh
az bicep build --file infra/main.bicep --stdout >/dev/null
```
Expand All @@ -65,9 +80,7 @@ az bicep build --file infra/main.bicep --stdout >/dev/null
azd env new sre-event-lab --location koreacentral
```

`--subscription`을 생략하면 azd가 로그인된 계정의 구독 목록에서 고르게 합니다. 특정 구독을 고정하려면 `--subscription <YOUR_SUBSCRIPTION_ID>`를 붙이세요. 리소스 그룹 이름은 지정하지 않으면 `rg-<environment 이름>`이 됩니다.

`.env.example`은 스크립트가 읽는 설정 이름과 허용 기본값만 적어 둔 참고 파일입니다. 값을 바꾸려면 `azd env set <NAME> <VALUE>`로 현재 azd 환경에 저장합니다.
`--subscription`을 생략하면 azd가 로그인된 계정의 구독 목록에서 고르게 합니다. 특정 구독을 고정하려면 `--subscription <YOUR_SUBSCRIPTION_ID>`를 붙이세요. 리소스 그룹 이름은 지정하지 않으면 `rg-<environment 이름>`이 됩니다. `.env.example`은 스크립트가 읽는 설정 이름과 허용 기본값만 적어 둔 참고 파일이며, 값을 바꾸려면 `azd env set <NAME> <VALUE>`로 현재 azd 환경에 저장합니다.

## 배포

Expand Down
21 changes: 16 additions & 5 deletions monitor/sre-agent-event-lab/guides/01-agent-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,19 @@

## 시작 조건

- **이 저장소를 본인 계정으로 fork했습니다.** Agent에 연결하는 저장소는 fork여야 합니다. 아래 "연결할 원본"에서 설명하듯 조사 결과 이슈가 연결된 저장소에 생성되므로, 원본 저장소를 연결하면 참가자 전원의 이슈가 한곳에 쌓입니다.
- [README](../README.md)의 `azd up`이 성공했고 `/healthz`가 HTTP 200을 반환합니다.
- `https://sre.azure.com`에 로그인할 수 있고, 대상 구독에 Azure SRE Agent가 **Running** 상태로 하나 있습니다.
- 역할을 만들 수 있는 권한(Owner 또는 User Access Administrator)이 있습니다.
- 아래 값을 손에 들고 시작합니다.

```bash
cd monitor/sre-agent-event-lab
azd env get-value AZURE_SUBSCRIPTION_ID
azd env get-value AZURE_RESOURCE_GROUP
source ./scripts/lab-env.sh
```

`lab-env.sh`는 구독 ID, 리소스 그룹, 그리고 `origin` 원격에서 유추한 저장소 URL을 출력합니다. fork를 열었는지까지 확인하지는 않으므로, `Repository` 줄이 **본인 계정의 저장소**인지 직접 확인하세요. 원본 저장소가 찍혀 있다면 fork를 clone해 다시 시작합니다.

## 설정 페이지 열기

Agent를 열면 위쪽 상태 표시줄이 아직 연결하지 않은 데이터 원본 수를 보여 줍니다. 오른쪽 **Complete setup**을 누르면 설정 페이지로 이동합니다.
Expand All @@ -33,13 +35,15 @@ Agent를 열면 위쪽 상태 표시줄이 아직 연결하지 않은 데이터

| 원본 | 이 실습에서 넣는 값 | 왜 필요한가 |
|---|---|---|
| Code | 이 저장소(`hellices/devguidesample`)와 브랜치 | 조사 결론이 코드와 최근 변경을 짚게 합니다 |
| Azure resources | `azd env get-value AZURE_RESOURCE_GROUP`이 출력한 리소스 그룹 | 메트릭·리소스 상태·Activity Log를 읽습니다 |
| Code | **본인이 fork한 저장소**와 브랜치 (`source ./scripts/lab-env.sh`가 출력한 `Repository` 값) | 조사 결론이 코드와 최근 변경을 짚게 합니다 |
| Azure resources | `lab-env.sh`가 출력한 `Resource group` 값 | 메트릭·리소스 상태·Activity Log를 읽습니다 |
| Knowledge files | [runbooks/incident-response.md](../runbooks/incident-response.md) | 조사 순서와 금지 사항을 팀 규칙으로 강제합니다 |
| Incidents | Azure Monitor | 경고를 자동으로 받아 조사 스레드를 엽니다 |

저장소는 [Connect source code](https://learn.microsoft.com/azure/sre-agent/connect-source-code)로 연결합니다. 이슈·PR 조작까지 맡기려면 [GitHub connector](https://learn.microsoft.com/azure/sre-agent/setup-github-connector)를 추가로 설정하되, 토큰 값은 포털 입력창에만 넣고 이 저장소의 어떤 파일에도 남기지 않습니다.

**연결 대상은 반드시 본인 fork여야 합니다.** GitHub connector를 붙이면 Agent가 조사 결과를 **이슈로 생성**하는데, 그 이슈는 연결된 저장소에 만들어집니다. 원본 저장소를 연결하면 본인 실습의 장애 이슈가 원본에 쌓이고, 원본에 쓰기 권한이 없으면 연결 자체가 실패합니다.

## 역할 부여

Agent가 실습 리소스를 읽고 구독의 경고를 훑을 수 있어야 합니다. 범위를 넓히지 마세요.
Expand Down Expand Up @@ -134,11 +138,18 @@ UAMI_MONITORING_CONTRIBUTOR_ASSIGNMENT_ID="$(az role assignment create \
```bash
azd env set SRE_AGENT_NAME "<포털에 보이는 Agent 이름>"
azd env set SRE_AGENT_RESOURCE_ID "<az resource list로 확인한 Agent 리소스 ID>"
azd env set SRE_REPOSITORY_URL "https://github.com/<owner>/<repo>"
azd env set SRE_REPOSITORY_BRANCH "main"
azd env set SRE_KNOWLEDGE_PATH "runbooks/incident-response.md"

if [[ -n "${SRE_REPOSITORY_URL}" ]]; then
azd env set SRE_REPOSITORY_URL "${SRE_REPOSITORY_URL}"
else
echo "저장소 URL을 직접 지정하세요: azd env set SRE_REPOSITORY_URL \"https://github.com/<본인 계정>/<저장소>\"" >&2
fi
```

`SRE_REPOSITORY_URL`은 `source ./scripts/lab-env.sh`가 `origin`에서 유추한 값입니다. 원격 URL에 자격 증명이 들어 있으면 `lab-env.sh`가 값을 비워 두므로, 위 분기가 직접 지정하라고 알려 줍니다. 어느 경우든 **본인이 이슈를 만들 수 있는 저장소**여야 합니다.

토큰, 연결 문자열, 클라이언트 비밀은 azd 환경에도 저장하지 않습니다. 인증은 Agent의 관리 ID와 포털 OAuth 흐름이 처리합니다.

## 근거 파일 만들기
Expand Down
23 changes: 10 additions & 13 deletions monitor/sre-agent-event-lab/guides/02-scenario-s1.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,29 @@

이 절의 명령을 순서대로 실행하면 스크립트 없이 시나리오 하나를 끝까지 진행할 수 있습니다. 무엇이 Azure에 적용되는지 명령 그대로 보이는 것이 목적입니다. 각 블록은 앞 단계가 성공했는지 플래그로 확인하고 진행합니다.

먼저 이번 실행에서 계속 쓸 값을 셸 변수로 읽습니다. 아래 블록부터 마지막 `record-capture`까지는 같은 셸에서 실행합니다.
Codespaces에서 이 저장소를 열었다면 `az login`을 마친 뒤 아래 한 줄로 이번 실습에 필요한 값이 모두 셸에 준비됩니다. 여기서부터 마지막 `record-capture`까지는 같은 셸에서 실행합니다.

```bash
cd monitor/sre-agent-event-lab
LAB_READY=1
source ./scripts/lab-env.sh
```

`lab-env.sh`는 `azd`가 게시한 배포 출력만 읽어 `RESOURCE_GROUP`, `SUBSCRIPTION_ID`, `APP_NAME`, `APP_FQDN`, `WORKLOAD_PRINCIPAL_ID`, `STORAGE_CONTAINER_SCOPE`, `BLOB_ROLE_ASSIGNMENT_NAME`을 export하고, 하나라도 읽지 못하면 `LAB_READY=0`으로 알려 줍니다. 비밀 값은 읽지도 출력하지도 않습니다.

RESOURCE_GROUP="$(azd env get-value AZURE_RESOURCE_GROUP 2>/dev/null)" || LAB_READY=0
SUBSCRIPTION_ID="$(azd env get-value AZURE_SUBSCRIPTION_ID 2>/dev/null)" || LAB_READY=0
APP_NAME="$(azd env get-value AZURE_CONTAINER_APP_NAME 2>/dev/null)" || LAB_READY=0
APP_FQDN="$(azd env get-value AZURE_CONTAINER_APP_FQDN 2>/dev/null)" || LAB_READY=0
이번 시나리오에서만 쓰는 값을 정하고 시도를 기록합니다.

```bash
ALERT_RULE_NAME="alert-sre-lab-s1-http500"
EVIDENCE_DIR="${PWD}/evidence/s1-$(date -u +%Y%m%dT%H%M%SZ)"

for value in "${RESOURCE_GROUP}" "${SUBSCRIPTION_ID}" "${APP_NAME}" "${APP_FQDN}"; do
[[ -n "${value// /}" ]] || LAB_READY=0
done

if (( LAB_READY )); then
mkdir -p "${EVIDENCE_DIR}"
python3 scripts/lab_state.py begin-run s1 "${EVIDENCE_DIR}" || LAB_READY=0
else
echo "azd 환경 값을 읽지 못했습니다. 먼저 azd provision을 실행하세요." >&2
fi
(( LAB_READY )) || echo "준비되지 않았습니다. 아래 단계는 모두 건너뜁니다." >&2
```

`azd env get-value`는 실패해도 오류 문장을 표준 출력으로 내보내므로 위 검사가 필요합니다. `begin-run`은 이번 시도를 기록하면서 순서·중복 실행 게이트도 함께 적용하고, 거부되면 `LAB_READY`가 0이 되어 이후 단계가 모두 건너뜁니다. 근거 디렉터리를 절대 경로로 두는 이유는 채점기와 캡처 도구가 기록된 경로를 실행 위치와 무관하게 다시 열기 때문입니다.
`begin-run`은 이번 시도를 기록하면서 순서·중복 실행 게이트도 함께 적용하고, 거부되면 `LAB_READY`가 0이 되어 이후 단계가 모두 건너뜁니다. 근거 디렉터리를 절대 경로로 두는 이유는 채점기와 캡처 도구가 기록된 경로를 실행 위치와 무관하게 다시 열기 때문입니다.

### 1. 장애 주입

Expand All @@ -58,6 +53,7 @@ if (( LAB_READY )); then
--query properties.latestRevisionName -o tsv)"

az containerapp update \
--subscription "${SUBSCRIPTION_ID}" \
--resource-group "${RESOURCE_GROUP}" \
--name "${APP_NAME}" \
--set-env-vars FAILURE_MODE=http500 \
Expand Down Expand Up @@ -150,6 +146,7 @@ RECOVERY_OLD_REVISION="$(az containerapp show \
--query properties.latestRevisionName -o tsv)"

az containerapp update \
--subscription "${SUBSCRIPTION_ID}" \
--resource-group "${RESOURCE_GROUP}" \
--name "${APP_NAME}" \
--set-env-vars FAILURE_MODE=none \
Expand Down
25 changes: 12 additions & 13 deletions monitor/sre-agent-event-lab/guides/03-scenario-s2.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,31 @@

## 수동 실행

S1과 같은 구조이며, 바뀌는 것은 주입 값과 부하 조건뿐입니다. 아래 블록부터 마지막 `record-capture`까지 같은 셸에서 실행합니다.
S1과 같은 구조이며, 바뀌는 것은 주입 값과 부하 조건뿐입니다.

Codespaces에서 이 저장소를 열었다면 `az login`을 마친 뒤 아래 한 줄로 이번 실습에 필요한 값이 모두 셸에 준비됩니다. 여기서부터 마지막 `record-capture`까지는 같은 셸에서 실행합니다.

```bash
cd monitor/sre-agent-event-lab
LAB_READY=1
source ./scripts/lab-env.sh
```

RESOURCE_GROUP="$(azd env get-value AZURE_RESOURCE_GROUP 2>/dev/null)" || LAB_READY=0
SUBSCRIPTION_ID="$(azd env get-value AZURE_SUBSCRIPTION_ID 2>/dev/null)" || LAB_READY=0
APP_NAME="$(azd env get-value AZURE_CONTAINER_APP_NAME 2>/dev/null)" || LAB_READY=0
APP_FQDN="$(azd env get-value AZURE_CONTAINER_APP_FQDN 2>/dev/null)" || LAB_READY=0
`lab-env.sh`는 `azd`가 게시한 배포 출력만 읽어 `RESOURCE_GROUP`, `SUBSCRIPTION_ID`, `APP_NAME`, `APP_FQDN`, `WORKLOAD_PRINCIPAL_ID`, `STORAGE_CONTAINER_SCOPE`, `BLOB_ROLE_ASSIGNMENT_NAME`을 export하고, 하나라도 읽지 못하면 `LAB_READY=0`으로 알려 줍니다. 비밀 값은 읽지도 출력하지도 않습니다.

이번 시나리오에서만 쓰는 값을 정하고 시도를 기록합니다.

```bash
ALERT_RULE_NAME="alert-sre-lab-s2-latency"
EVIDENCE_DIR="${PWD}/evidence/s2-$(date -u +%Y%m%dT%H%M%SZ)"

for value in "${RESOURCE_GROUP}" "${SUBSCRIPTION_ID}" "${APP_NAME}" "${APP_FQDN}"; do
[[ -n "${value// /}" ]] || LAB_READY=0
done

if (( LAB_READY )); then
mkdir -p "${EVIDENCE_DIR}"
python3 scripts/lab_state.py begin-run s2 "${EVIDENCE_DIR}" || LAB_READY=0
else
echo "azd 환경 값을 읽지 못했습니다. 먼저 azd provision을 실행하세요." >&2
fi
(( LAB_READY )) || echo "준비되지 않았습니다. 아래 단계는 모두 건너뜁니다." >&2
```

`azd env get-value`는 실패해도 오류 문장을 표준 출력으로 내보내므로 위 검사가 필요합니다. `begin-run`은 이번 시도를 기록하면서 순서·중복 실행 게이트도 함께 적용하고, 거부되면 `LAB_READY`가 0이 되어 이후 단계가 모두 건너뜁니다. 근거 디렉터리를 절대 경로로 두는 이유는 채점기와 캡처 도구가 기록된 경로를 실행 위치와 무관하게 다시 열기 때문입니다.
`begin-run`은 이번 시도를 기록하면서 순서·중복 실행 게이트도 함께 적용하고, 거부되면 `LAB_READY`가 0이 되어 이후 단계가 모두 건너뜁니다.

### 1. 지연 주입

Expand All @@ -52,6 +49,7 @@ if (( LAB_READY )); then
--query properties.latestRevisionName -o tsv)"

az containerapp update \
--subscription "${SUBSCRIPTION_ID}" \
--resource-group "${RESOURCE_GROUP}" \
--name "${APP_NAME}" \
--set-env-vars ORDER_DELAY_MS=4000 \
Expand Down Expand Up @@ -141,6 +139,7 @@ RECOVERY_OLD_REVISION="$(az containerapp show \
--query properties.latestRevisionName -o tsv)"

az containerapp update \
--subscription "${SUBSCRIPTION_ID}" \
--resource-group "${RESOURCE_GROUP}" \
--name "${APP_NAME}" \
--set-env-vars ORDER_DELAY_MS=0 \
Expand Down
Loading