---
title: 배포 감지와 스팬이 담고 있어야 하는 것
description: >-
  sigiro는 배포에 대해 단 하나의 속성만 읽습니다 — 스팬 리소스의 service.version입니다. 이 페이지에서는 버전이 어떻게
  배포 이벤트가 되는지, sigiro가 어떻게 용의 배포를 선정하는지, 그리고 서비스가 버전을 전혀 전송하지 않을 때 무엇을 얻게 되는지
  설명합니다.
sidebar:
  order: 4
---
진단은 용의 배포를 지목할 수 있습니다: _'checkout' 서비스에서 14:30경 인시던트:
… ; 용의 배포: 버전 1.4.2가 14:29에 처음 관측됨_. 이는 강력한 주장이며,
읽는 사람이 그 근거를 묻는 것은 당연합니다.

그 근거는 한 곳에 있는 하나의 속성에서 나옵니다. 이 페이지에서는 그 속성을 명시하고,
sigiro가 배포와 정상 상태를 어떻게 구분하는지 설명하고, 하나의 배포가 어떻게 용의자가
되는지 설명하며, 그 속성이 없을 때 무엇을 얻게 되는지 알려 드립니다. 마지막 부분이
가장 중요한데, 그 부재는 아무런 신호 없이 조용히 일어나기 때문입니다.

## 하나의 속성, 하나의 위치

sigiro는 **스팬의 리소스 속성**에서 `service.version`을 읽습니다.

그것이 출처의 전부입니다. sigiro는 배포를 위해 다른 어떤 필드도 읽지 않습니다:

| 배포를 위해 읽지 않는 것 | 읽지 않는 이유 |
| --- | --- |
| `deployment.environment`, `deployment.*` | 어떤 쿼리도 이를 읽지 않습니다 |
| `git.commit.sha`, `vcs.*` | 어떤 쿼리도 이를 읽지 않습니다 |
| 로그, 메트릭 또는 프로파일의 `service.version` | sigiro는 `sigiro_spans`만 스캔합니다 |
| CI 웹훅, 배포 API, 릴리스 피드 | sigiro에는 OTLP 외의 인제스트 경로가 없습니다 |
| Kubernetes API 서버 | sigiro는 이에 절대 연결하지 않습니다 |

리소스 속성은 OTLP를 통해 도착하여 `sigiro_spans`의 `resource_attributes` 컬럼에
JSON 문자열로 그대로 저장됩니다. 세 개의 리소스 속성은 인제스트 시점에 자체 컬럼을
갖습니다 — `service.name`, `service.namespace`, `service.instance.id`입니다.
`service.version`은 그중 하나가 아니므로, sigiro는 매 쿼리마다 JSON에서 이 값을
다시 읽어 냅니다.

"스팬만"이라는 점에서 두 가지 결과가 따라옵니다. 로그는 내보내지만 스팬을 내보내지 않는
서비스는 로그가 아무리 훌륭하더라도 배포 이벤트를 생성하지 않습니다. 한 프로세스에서는
스팬을 내보내고 다른 프로세스에서는 내보내지 않는 서비스는 계측된 프로세스가 새 버전으로
재시작될 때만 배포를 보고합니다.

값 자체는 sigiro에게 불투명합니다. semver 문자열, git SHA, 빌드 번호, 날짜 모두
동일하게 동작하는데, sigiro는 두 문자열의 일치 여부만 비교하고 어느 쪽도 파싱하지
않기 때문입니다. sigiro는 버전에서 어떤 순서도 도출하지 않으므로, 업그레이드와 롤백을
구분할 수 없습니다.

## 배포란 베이스라인에 없었던 버전입니다

sigiro가 읽을 수 있는 배포 타임스탬프는 없으므로, 이를 도출합니다. 배포 이벤트란 진단
윈도우 내의 스팬에는 나타나고 베이스라인 윈도우 내의 **어떤** 스팬에도 나타나지 않는
`service.version` 값입니다.

베이스라인 윈도우는 진단 윈도우 길이의 네 배이며, 진단 윈도우가 시작되는 지점에서
끝납니다. 기본 진단 윈도우는 최근 15분이므로, 기본 베이스라인은 그 직전 1시간입니다.

각 배포 이벤트는 다음을 담고 있습니다:

- `event_type` — 리터럴 문자열 `deploy`
- `detected_at` — 해당 버전을 담고 있는 윈도우 내 가장 이른 스팬 타임스탬프로, 이는
  sigiro가 그 버전을 처음 _본_ 시점이며 배포가 시작된 시점이 아닙니다
- `description` — `version 1.4.2 first seen`

베이스라인과의 비교가 중요한 절반이며, 이는 실제 결함을 해결합니다. 이 비교가 없다면
"처음 관측됨"은 윈도우의 첫 행을 의미하게 되므로, 모든 정상 서비스의 모든 진단이
윈도우 시작 시점에 배포를 보고하게 됩니다. 그 이벤트는 항상 존재하고, 항상 시간상
인시던트 옆에 놓이며, 이를 읽는 에이전트는 그것을 원인으로 취급합니다. 영구적인 잘못된
단서는 단서가 없는 것보다 나쁘므로, 윈도우가 시작되기 전에 이미 실행되고 있던 버전은
정상 상태로 간주됩니다.

다음 다섯 가지 결과가 직접적으로 따라오며, 각각은 누군가를 놀라게 합니다:

- **고정된 버전은 아무것도 생성하지 않습니다.** 모든 빌드가
  `service.version=1.0.0`으로 출하된다면, sigiro는 배포 이벤트를 한 번 보고한 뒤
  다시는 보고하지 않습니다. 배포를 보이게 하려면 각 릴리스에 서로 다른 값을 부여하십시오.
- **여러 개의 새 버전은 여러 개의 이벤트를 생성합니다.** 쿼리가 버전별로 그룹화하므로,
  세 개의 새 버전이 있는 윈도우는 세 개의 배포 이벤트를 반환합니다.
- **롤백은 배포로 읽힙니다.** 이전 버전은 베이스라인 윈도우에 없으므로, 이 정의에
  따르면 새로운 것입니다.
- **텔레메트리의 공백은 배포로 읽힙니다.** 서비스가 베이스라인 윈도우에서 스팬을 전혀
  보내지 않았다면 베이스라인 집합은 비어 있고, 윈도우 내의 모든 버전이 새로운 것이
  됩니다. 서비스가 새로 생겼거나 조용했던 경우, 윈도우 시작 시점의 배포는 주의해서
  읽으십시오.
- **더 넓은 윈도우는 더 멀리 과거를 봅니다.** sigiro는 요청한 윈도우로부터 베이스라인을
  도출하므로, 6시간 진단은 이전 24시간과 비교합니다.

## Kubernetes 이벤트는 로그 텍스트에서 나옵니다

동일한 `events` 배열은 두 번째 이벤트 유형인 `k8s_event`도 담고 있으며, 이는 출처가
다릅니다.

sigiro는 윈도우 내 해당 서비스 로그의 `body` 컬럼에서 다섯 개의 고정된 부분 문자열을
스캔합니다: `OOMKilled`, `Unhealthy`, `BackOff`, `FailedScheduling`,
`ScalingReplicaSet`입니다. 매칭은 대소문자를 구분하며, 단순 부분 문자열 매칭입니다.
description은 로그 본문 전체이며, sigiro는 진단당 최대 20개를 반환합니다.

따라서 이것은 Kubernetes 통합이 아닙니다. sigiro는 API 서버와 절대 통신하지 않습니다.
이러한 이벤트는 무언가가 클러스터 이벤트를 진단 대상 서비스와 동일한 `service.name`
아래로 OTLP 로그에 전달할 때만 보입니다. 이벤트를 감시하여 로그로 내보내는 컬렉터가
일반적인 구성입니다. 아무것도 전달하지 않으면, 배열은 배포 이벤트만 담습니다.

`k8s_event`는 절대 용의자가 되지 않습니다. `deploy` 유형의 이벤트만 자격이 있습니다.

## 하나의 배포가 어떻게 용의자가 되는가

두 가지 규칙이 이를 결정하며, 둘 다 감지기 자체의 5분 버킷에서 비롯됩니다.

첫째, **인시던트**만 용의자를 갖습니다. 다른 어떤 변화와도 상관관계를 갖지 않는 단일
변화는 단일 신호 항목으로 남으며 배포 필드를 전혀 갖지 않습니다. 동일하거나 인접한
버킷의 두 개 이상의 변화는 하나의 인시던트로 병합되며, 그 항목만 배포를 찾습니다.
[대시보드가 아닌 증거에 대하여](/docs/explanation/evidence)에서 변화가 왜 그런 식으로
상관관계를 갖는지 설명합니다.

둘째, 배포는 그 버킷이 인시던트 자체의 버킷 범위 안에 들어오거나, 첫 변화 직전의 한
버킷에 들어올 때 자격을 갖습니다. 그 추가 버킷은 허용 오차가 아니라 산술의 문제입니다:
14:29의 배포가 14:30 버킷에서 감지된 변화를 유발했다면, 구조상 한 버킷 앞선 것입니다.
여러 배포가 자격을 갖는 경우, 인시던트 시작 시점과 시간상 가장 가까운 것이 선택됩니다.

선정된 것은 두 번 나타납니다: 인시던트의 `deploy` 객체로, 그리고 항목 요약 끝의 절로
나타납니다. 다른 모든 배포 이벤트는 서비스의 `events` 배열에 남아 있으며, sigiro는
이를 시간순으로 정렬하고 절대 필터링하지 않습니다. 따라서 비교에서 밀려난 배포도
여전히 응답에 있으므로 읽어 볼 수 있습니다.

sigiro는 시간상의 상관관계만 주장하며 그 이상은 주장하지 않습니다. _용의(suspect)_ 라는
단어는 의도적인 선택입니다.

## 서비스가 버전을 설정하지 않을 때 일어나는 일

간단히 말해: 배포 이벤트를 얻지 못하며, sigiro는 그에 대해 아무것도 알려 주지 않습니다.

쿼리는 `service.version`이 null인 행을 버리므로, 이 속성을 전혀 설정하지 않는 서비스는
배포 이벤트를 제공하지 않습니다. 그러면 `events` 배열은 Kubernetes 이벤트만 담거나,
비어 있습니다. 모든 인시던트는 `deploy: null`을 갖게 되고, 요약은 용의자 절 없이
끝납니다.

어떤 항목도 경고하지 않습니다. sigiro는 `k8s.namespace.name`과 `k8s.deployment.name`이
없을 때 `missing_resource_attributes` 종류의 항목을 발생시키지만, 그 항목은
`service.version`에 대해서는 아무 말도 하지 않습니다. 버전에는 이에 상응하는 것이
없습니다. 이 성능 저하는 조용히 일어납니다.

이것이 응답에서 액면 그대로 읽을 수 없는 유일한 부분입니다. 배포 이벤트가 없는 윈도우는
매우 다른 두 상황에서 똑같이 보입니다: 배포가 일어나지 않은 경우, 그리고 어떤 프로세스도
`service.version`을 설정하지 않는 경우입니다. 응답은 이 둘을 구분하지 않습니다.

한 가지 쿼리는 이를 구분합니다:

```sql
SELECT DISTINCT resource_attributes::JSON->>'service.version' AS version
FROM sigiro_spans
WHERE service_name = 'checkout'
  AND timestamp > now() - INTERVAL '24 hours';
```

결과는 이렇게 읽으십시오:

- 한 행이고 그 값이 `NULL`인 경우 — 아무것도 이 속성을 설정하지 않습니다. sigiro는 이
  서비스에 대해 배포를 절대 보고할 수 없습니다.
- 값이 있는 한 행이고, 며칠 동안 변하지 않은 경우 — 무언가가 이 속성을 설정하지만, 그
  값이 절대 변하지 않습니다. sigiro는 그 값을 처음 본 시점에 배포를 보고했고, 그
  이후로는 보고하지 않습니다.
- 여러 행인 경우 — 이 서비스에 대해 배포 감지가 작동합니다.

서비스의 OpenTelemetry 리소스에 이 속성을 설정하고, 각 릴리스에 서로 다른 값을
부여하십시오. [에이전트로 코드 계측하기](/docs/how-to/install-with-ai)에서 리소스
설정 자체를 다룹니다.

## 다음에 읽을 내용

- [대시보드가 아닌 증거에 대하여](/docs/explanation/evidence) — 변화가 어떻게
  인시던트가 되는지, 그리고 모든 행이 왜 쿼리를 담고 있는지
- [테이블과 각 테이블이 설명하는 머신에 대하여](/docs/explanation/tables) —
  `resource_attributes`가 어디에 있는지, 그리고 어느 테이블이 어떤 질문에 답하는지
- [API 레퍼런스](/docs/reference) — `DerivedEvent`와 `Incident` 필드 전체
