웹훅 구성
웹훅 구성 (Webhook Configuration)
Argo CD는 Git/OCI/Helm 리포지토리를 3분마다 폴링해서 매니페스트의 변경을 감지해요. 이 폴링 지연을 없애려면 API 서버가 웹훅 이벤트를 수신하도록 구성할 수 있답니다.
출처: 문서
본문
개요 (Overview)
Argo CD는 3분마다 Git/OCI/Helm 리포지토리를 폴링해서 매니페스트의 변경을 감지해요. 폴링에서 오는 이 지연을 없애려면 API 서버가 웹훅 이벤트를 수신하도록 구성할 수 있어요.
Git 웹훅 (Git Webhooks)
Argo CD는 GitHub, GitLab, Bitbucket, Bitbucket Server, Azure DevOps, Gogs의 Git 웹훅 알림을 지원해요. 다음은 GitHub용 Git 웹훅을 구성하는 방법을 설명하지만, 같은 과정이 다른 제공자에도 적용될 거예요.
OCI 레지스트리 웹훅 (OCI Registry Webhooks)
Argo CD는 OCI 호환 컨테이너 레지스트리의 웹훅도 지원해서, 새 OCI 아티팩트가 push되면 애플리케이션 새로고침을 트리거해요. 자세한 내용은 OCI 호환 레지스트리용 웹훅 구성을 참고하세요.
Application Sets는 애플리케이션 생성에 별도의 웹훅 구성을 사용해요. Git 생성기의 웹훅 지원은 여기에서 찾을 수 있어요.
[!NOTE] 웹훅 핸들러는 브랜치 이름과 태그 이름이 같은 경우 브랜치 이벤트와 태그 이벤트를 구분하지 않아요. 브랜치
x로의 push에 대한 hook 이벤트는targetRevision: refs/tags/x를 가진 같은 repo를 가리키는 앱의 새로고침도 트리거해요.
1. Git 제공자에서 웹훅 만들기 (Create The WebHook In The Git Provider)
Git 제공자에서 웹훅을 구성할 수 있는 설정 페이지로 이동하세요. Git 제공자에서 구성된 payload URL은 Argo CD 인스턴스의 /api/webhook 엔드포인트를 사용해야 해요 (예: https://argocd.example.com/api/webhook). 공유 시크릿을 사용하려면 시크릿에 임의의 값을 입력하세요. 이 값은 다음 단계에서 웹훅을 구성할 때 사용돼요.
인증되지 않은 웹훅 이벤트로 인한 DDoS 공격(/api/webhook 엔드포인트에는 현재 레이트 리밋 보호가 없음)을 막으려면 payload 크기를 제한하는 것이 좋아요. argocd-cm ConfigMap의 webhook.maxPayloadSizeMB 속성으로 이를 구성할 수 있어요. 기본값은 50MB예요.
Github
[!NOTE] GitHub에서 웹훅을 만들 때 "Content type"을 "application/json"으로 설정해야 해요. 기본값 "application/x-www-form-urlencoded"는 hook을 처리하는 라이브러리에서 지원되지 않아요.
Azure DevOps
Azure DevOps는 선택적으로 basic authentication으로 웹훅을 보호하는 것을 지원해요. 사용하려면 웹훅 구성에서 username과 password를 지정하고, argocd-secret Kubernetes secret의 webhook.azuredevops.username과 webhook.azuredevops.password 키에 같은 username/password를 구성하세요.
2. 웹훅 시크릿으로 Argo CD 구성 (Configure Argo CD With The WebHook Secret) (선택)
웹훅 공유 시크릿 구성은 선택사항이에요. 인증되지 않은 웹훅 이벤트가 와도 Argo CD는 Git 리포지토리와 관련된 애플리케이션을 계속 새로고침하니까요. 웹훅 payload의 내용은 신뢰할 수 없는 것으로 간주되며, 애플리케이션의 새로고침(3분 간격으로 이미 발생하는 과정)만 초래하므로 이렇게 하는 것은 안전해요. Argo CD가 공개적으로 접근 가능하다면 DDoS 공격을 막기 위해 웹훅 시크릿을 구성하는 것이 권장돼요.
argocd-secret Kubernetes secret에서 1단계에서 구성한 Git 제공자의 웹훅 시크릿과 함께 다음 키 중 하나를 구성하세요.
| 제공자 | K8s Secret 키 |
|---|---|
| GitHub | webhook.github.secret |
| GitLab | webhook.gitlab.secret |
| BitBucket | webhook.bitbucket.uuid |
| BitBucketServer | webhook.bitbucketserver.secret |
| Gogs | webhook.gogs.secret |
| Azure DevOps | webhook.azuredevops.username |
webhook.azuredevops.password |
Argo CD Kubernetes secret을 편집하세요:
kubectl edit secret argocd-secret -n argocd
TIP: 시크릿 입력을 쉽게 하기 위해 Kubernetes는 stringData 필드에 시크릿 입력을 지원하므로, 값을 base64 인코딩해서 data 필드에 복사하는 번거로움을 덜어줘요. 1단계에서 만든 공유 웹훅 시크릿을 stringData 필드의 해당 GitHub/GitLab/BitBucket 키에 복사하기만 하면 돼요:
apiVersion: v1
kind: Secret
metadata:
name: argocd-secret
namespace: argocd
type: Opaque
data:
...
stringData:
# github webhook secret
webhook.github.secret: shhhh! it's a GitHub secret
# gitlab webhook secret
webhook.gitlab.secret: shhhh! it's a GitLab secret
# bitbucket webhook secret
webhook.bitbucket.uuid: your-bitbucket-uuid
# bitbucket server webhook secret
webhook.bitbucketserver.secret: shhhh! it's a Bitbucket server secret
# gogs server webhook secret
webhook.gogs.secret: shhhh! it's a gogs server secret
# azuredevops username and password
webhook.azuredevops.username: admin
webhook.azuredevops.password: secret-password
저장하면 변경 사항이 자동으로 적용돼요.
대안 (Alternative)
argocd-secret 대신 다른 Kubernetes Secret에 웹훅 데이터를 저장하고 싶다면, data 아래의 키가 $로 시작하고 그 뒤에 Kubernetes Secret 이름과 :(콜론)이 오는지 ArgoCD가 확인한다는 점을 이용할 수 있어요.
문법: $<k8s_secret_name>:<a_key_in_that_k8s_secret>
[!NOTE] Secret에는
app.kubernetes.io/part-of: argocd라벨이 있어야 해요.
자세한 내용은 사용자 관리 문서의 해당 섹션을 참고하세요.
BitBucket Cloud 특별 처리 (Special handling for BitBucket Cloud)
BitBucket은 웹훅 request body에 변경된 파일 목록을 포함하지 않아요. 이로 인해 Manifest Paths 어노테이션 기능이 BitBucket Cloud에 호스팅된 리포지토리에서 동작하지 않아요. BitBucket은 두 커밋 사이의 변경된 파일 목록을 결정하는 diffstat API를 제공해요. 웹훅에 없는 변경된 파일 목록을 처리하기 위해 Argo CD 웹훅 핸들러는 원본 서버에 API 콜백을 해요. SSRF(Server-side request forgery) 공격을 막기 위해 Argo CD 서버는 암호화된 웹훅 요청에 대해서만 콜백 메커니즘을 지원해요. 들어오는 웹훅은 X-Hook-UUID request header를 포함해야 해요. 검증을 위해 해당 UUID를 argocd-secret의 webhook.bitbucket.uuid로 제공해야 해요. 콜백 메커니즘은 BitBucket Cloud의 공개 및 비공개 리포지토리를 모두 지원해요. 공개 리포지토리의 경우 Argo CD 웹훅 핸들러는 API 콜백에 no-auth 클라이언트를 사용해요. 비공개 리포지토리의 경우 Argo CD 웹훅 핸들러는 HTTP/HTTPS URL에 대한 유효한 리포지토리 OAuth 토큰을 검색해요. 웹훅 핸들러는 이 OAuth 토큰을 사용해 원본 서버에 API 요청을 해요. Argo CD 웹훅 핸들러가 일치하는 리포지토리 자격 증명을 찾지 못하면 변경된 파일 목록은 비어 있게 돼요. 콜백 중에 오류가 발생하면 변경된 파일 목록은 비게 돼요.
3. OCI 호환 레지스트리용 웹훅 구성 (Webhook Configuration for OCI-Compliant Registries)
Git 웹훅 외에도 Argo CD는 OCI 호환 컨테이너 레지스트리의 웹훅을 지원해요. 이는 새 아티팩트가 push될 때 즉시 애플리케이션을 새로고침해서 폴링의 지연을 없애줘요.
GitHub Container Registry (GHCR)
웹훅은 GHCR 이미지 리포지토리에 직접 등록할 수 없어요. 대신 package 이벤트가 연결된 GitHub 리포지토리에서 전달돼요.
[!NOTE] GHCR 이미지 리포지토리가 아직 GitHub 리포지토리에 연결되지 않았다면 리포지토리를 패키지에 연결을 참고하세요.
웹훅 구성 (Configure the Webhook)
- GitHub 리포지토리의 Settings → Webhooks → Add webhook로 이동하세요
- Payload URL을
https://<argocd-server>/api/webhook으로 설정하세요 - Content type을
application/json으로 설정하세요 - Secret을 안전한 값으로 설정하세요
- Events 아래에서 Let me select individual events를 선택하고 Packages를 활성화하세요
[!NOTE]
container패키지 유형에 대한published이벤트만 새로고침을 트리거해요. 다른 패키지 유형(npm, maven 등)과 동작은 무시돼요.
[!WARNING] GitHub는 알 수 없는 미디어 유형을 가진 아티팩트에 대해
package웹훅 이벤트를 보내지 않아요. OCI 아티팩트가 커스텀이나 비표준 미디어 유형을 사용하면 웹훅이 트리거되지 않아요. GitHub의 지원 패키지 유형 문서를 참고하세요.
웹훅 시크릿 구성 (Configure the Webhook Secret)
GHCR 웹훅은 GitHub Git 웹훅과 같은 시크릿(webhook.github.secret)을 사용해요:
apiVersion: v1
kind: Secret
metadata:
name: argocd-secret
namespace: argocd
type: Opaque
stringData:
webhook.github.secret: <your-webhook-secret>
예시 애플리케이션 (Example Application)
알려진 미디어 유형의 OCI 아티팩트가 GHCR에 push되면 Argo CD는 일치하는 repoURL과 targetRevision을 가진 Applications를 새로고침해요:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
spec:
source:
repoURL: oci://ghcr.io/myorg/myimage
targetRevision: v1.0.0
chart: mychart
destination:
server: https://kubernetes.default.svc
namespace: default
targetRevision 필드는 정확한 태그와 semver 제약을 지원해요:
| 제약 | 다음이 push될 때 웹훅 트리거 |
|---|---|
1.0.0 |
1.0.0만 |
^1.2.0 |
>=1.2.0 그리고 <2.0.0 (예: 1.2.1, 1.9.0) |
~1.2.0 |
>=1.2.0 그리고 <1.3.0 (예: 1.2.1, 1.2.9) |
>=1.0.0 |
>=1.0.0인 모든 버전 |
URL 매칭 (URL Matching)
Argo CD는 일관된 매칭을 보장하기 위해 비교 전에 OCI 리포지토리 URL을 정규화해요:
예를 들어, 이 repoURL 값들은 모두 ghcr.io/myorg/myimage에 대한 웹훅 이벤트와 매칭돼요:
oci://ghcr.io/myorg/myimageoci://GHCR.IO/MyOrg/MyImageoci://ghcr.io/myorg/myimage/