WatchOperation
WatchOperation (리소스 변경 감지 Operations)
이 기능은 v2에서 도입되었습니다. 자세한 내용은 Crossplane 기능 생명주기 문서를 참고하세요.
출처: 문서
본문
WatchOperation은 감시 중인 Kubernetes 리소스가 변경될 때 Operations를 생성합니다. 데이터베이스를 삭제하기 전에 백업하거나, 업데이트 후 구성을 검증하거나, 리소스 실패 시 알림을 트리거하는 등 반응형 운영 워크플로에 WatchOperations를 사용하세요.
WatchOperations는 어떻게 동작하나요? (How WatchOperations work)
WatchOperations는 특정 Kubernetes 리소스를 감시하며, 해당 리소스가 변경될 때마다 새 Operations를 생성합니다. 변경된 리소스는 함수가 처리할 수 있도록 Operation에 자동으로 주입됩니다.
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: config-validator
spec:
watch:
apiVersion: v1
kind: ConfigMap
matchLabels:
validate: "true"
concurrencyPolicy: Allow
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: validate
functionRef:
name: function-config-validator
input:
apiVersion: fn.crossplane.io/v1beta1
kind: ConfigValidatorInput
rules:
- required: ["database.url", "database.port"]
- format: "email"
field: "notification.email"
- step: notify
functionRef:
name: function-slack-notifier
input:
apiVersion: fn.crossplane.io/v1beta1
kind: SlackNotifierInput
channel: "#alerts"
severity: "warning"
⚠️ 중요: WatchOperations는 alpha 기능입니다. Crossplane 인자에
--enable-operations를 추가해서 Operations를 반드시 활성화해야 해요.
주요 특징 (Key features)
- 모든 Kubernetes 리소스 유형 감시 - Crossplane 리소스로 제한되지 않음
- 네임스페이스와 라벨 필터링 지원 - 특정 리소스 대상 지정
- 변경된 리소스 자동 주입 - 함수가 트리거 리소스를 받음
- 구성 가능한 동시성 정책 - Operation 생성 제어
리소스 감시 (Resource watching)
WatchOperations는 유연한 필터링으로 어떤 Kubernetes 리소스든 감시할 수 있습니다.
특정 유형의 모든 리소스 감시
spec:
watch:
apiVersion: apps/v1
kind: Deployment
특정 네임스페이스의 리소스 감시
spec:
watch:
apiVersion: v1
kind: ConfigMap
namespace: production
특정 라벨이 있는 리소스 감시
spec:
watch:
apiVersion: example.org/v1
kind: Database
matchLabels:
backup: "enabled"
environment: "production"
클러스터 범위 리소스 감시
spec:
watch:
apiVersion: v1
kind: Node
matchLabels:
node-role.kubernetes.io/worker: ""
리소스 주입 (Resource injection)
WatchOperation이 Operation을 생성할 때, 특별한 요구사항 이름 ops.crossplane.io/watched-resource로 변경된 리소스를 자동으로 주입합니다. 함수는 명시적으로 요청하지 않아도 이 리소스에 접근할 수 있어요.
예를 들어, 라벨이 validate: "true"인 ConfigMap이 변경되면 WatchOperation은 이런 Operation을 생성합니다.
apiVersion: ops.crossplane.io/v1alpha1
kind: Operation
metadata:
name: config-validator-abc123
spec:
mode: Pipeline
pipeline:
- step: validate
functionRef:
name: function-config-validator
requirements:
requiredResources:
- requirementName: ops.crossplane.io/watched-resource
apiVersion: v1
kind: ConfigMap
name: my-config
namespace: default
# ... other pipeline steps from operationTemplate
감시된 리소스는 함수의 req.required_resources에서 특별한 이름 ops.crossplane.io/watched-resource 아래 자동으로 사용 가능합니다.
동시성 정책 (Concurrency policies)
WatchOperations는 CronOperations와 동일한 동시성 정책을 지원합니다.
- Allow (기본값): 여러 Operations가 동시에 실행될 수 있음. 서로 간섭하지 않는 작업에 사용하세요.
- Forbid: 이전 작업이 아직 실행 중이면 새 Operations가 시작되지 않음. 동시에 실행할 수 없는 작업에 사용하세요.
- Replace: 새 Operations가 시작하기 전에 실행 중인 작업을 중지함. 항상 최신 작업을 실행하려 할 때 사용하세요.
일반적인 사용 사례 (Common use cases)
📝 참고: 아래 예제는 설명을 위한 가상의 함수를 사용합니다. 출시 시점에는
function-python만 operations를 지원해요.
구성 검증 (Configuration validation)
ConfigMap이 변경될 때 검증하세요.
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: config-validator
spec:
watch:
apiVersion: v1
kind: ConfigMap
matchLabels:
validate: "true"
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: validate-config
functionRef:
name: function-config-validator
input:
apiVersion: fn.crossplane.io/v1beta1
kind: ConfigValidatorInput
rules:
- required: ["database.host", "database.port"]
- format: "email"
field: "notification.email"
삭제 시 데이터베이스 백업 (Database backup on deletion)
데이터베이스가 삭제되기 전에 백업하세요.
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: backup-on-deletion
spec:
watch:
apiVersion: rds.aws.m.upbound.io/v1beta1
kind: Instance
# Note: Watching for deletion requires function logic
# to check deletion timestamp
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: create-backup
functionRef:
name: function-rds-backup
input:
apiVersion: fn.crossplane.io/v1beta1
kind: RDSBackupInput
retentionDays: 30
리소스 실패 알림 (Resource failure alerting)
리소스가 실패 상태에 들어가면 알림을 보내세요.
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: failure-alerts
spec:
watch:
apiVersion: example.org/v1
kind: App
matchLabels:
alert: "enabled"
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: check-status
functionRef:
name: function-status-checker
input:
apiVersion: fn.crossplane.io/v1beta1
kind: StatusCheckerInput
alertConditions:
- type: "Ready"
status: "False"
- step: send-alert
functionRef:
name: function-alertmanager
input:
apiVersion: fn.crossplane.io/v1beta1
kind: AlertInput
severity: "critical"
고급 구성 (Advanced configuration)
고급 감시 패턴 (Advanced watch patterns)
여러 조건이 있는 복잡한 리소스 감시입니다.
# Watch Deployments in specific namespaces with multiple label conditions
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: multi-condition-watcher
spec:
watch:
apiVersion: apps/v1
kind: Deployment
namespace: production # Only production namespace
matchLabels:
app.kubernetes.io/managed-by: "crossplane"
environment: "prod"
backup-required: "true"
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: backup-deployment
functionRef:
name: function-deployment-backup
# Watch custom resources across all namespaces
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: database-lifecycle-manager
spec:
watch:
apiVersion: database.example.io/v1
kind: PostgreSQLInstance
# No namespace specified = watch all namespaces
matchLabels:
lifecycle-management: "enabled"
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: lifecycle-check
functionRef:
name: function-database-lifecycle
input:
apiVersion: fn.crossplane.io/v1beta1
kind: DatabaseLifecycleInput
checkDeletionTimestamp: true
autoBackup: true
교차 리소스 워크플로 (Cross-resource workflows)
WatchOperations는 하나의 리소스 유형을 감시하면서 관련 리소스를 동적으로 가져올 수 있습니다. Ingress를 감시하고 인증서를 관리하는 WatchOperation 예입니다.
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: ingress-certificate-manager
spec:
watch:
apiVersion: networking.k8s.io/v1
kind: Ingress
matchLabels:
auto-cert: "enabled"
operationTemplate:
spec:
mode: Pipeline
pipeline:
- step: manage-certificates
functionRef:
name: function-cert-manager
input:
apiVersion: fn.crossplane.io/v1beta1
kind: CertManagerInput
issuer: "letsencrypt-prod"
renewBefore: "720h" # 30 days
함수는 감시된 Ingress를 검사하고 관련 리소스를 동적으로 요청합니다.
from crossplane.function import request, response
def operate(req, rsp):
# Access the watched Ingress resource
ingress = request.get_required_resource(req, "ops.crossplane.io/watched-resource")
if not ingress:
response.fatal(rsp, "No watched resource found")
return
# Extract the service name from the Ingress backend
rules = ingress.get("spec", {}).get("rules", [])
if not rules:
response.fatal(rsp, "Could not extract service name from ingress")
return
backend = rules[0].get("http", {}).get("paths", [{}])[0].get("backend", {})
service_name = backend.get("service", {}).get("name")
if not service_name:
response.fatal(rsp, "Could not extract service name from ingress")
return
ingress_namespace = ingress.get("metadata", {}).get("namespace", "default")
# CRITICAL: Always request the same resources to ensure requirement
# stabilization. Crossplane calls the function repeatedly until
# requirements don't change.
response.require_resources(
rsp,
name="related-service",
api_version="v1",
kind="Service",
match_name=service_name,
namespace=ingress_namespace
)
# Check if the service is available and process accordingly
service = request.get_required_resource(req, "related-service")
if service:
# Success: Both resources available
response.set_output(rsp, {
"status": "success",
"message": "Certificate management completed",
"ingress_host": ingress.get("spec", {}).get("rules", [{}])[0].get("host"),
"service_name": service.get("metadata", {}).get("name")
})
return
# Waiting: Service not available yet
response.set_output(rsp, {
"status": "waiting",
"message": f"Waiting for service '{service_name}' to be available"
})
⚠️ 중요: 핵심 리소스 안정화 패턴입니다. 함수는 완료를 알리기 위해 매 반복마다 동일한 요구사항을 반환해야 해요. 앞의 예제 함수는 서비스 존재 여부와 무관하게 항상
response.require_resources()를 호출합니다. 이렇게 해야 Crossplane이 언제 함수 호출을 멈출지 알 수 있어요.
흔한 실수: 리소스가 없을 때만 요청하면 안정화 계약이 깨져서 시간 초과 오류가 발생합니다.
이 패턴을 통해 함수는 다음을 할 수 있습니다.
- 감시된 리소스 검사 (자동 주입됨)
- 함수가 필요로 하는 다른 리소스를 동적으로 결정
response.require_resources()로 해당 리소스를 일관되게 요청- 사용 가능할 때 모든 리소스를 처리하거나, 대기 중이면 상태 제공
상태와 모니터링 (Status and monitoring)
WatchOperations는 감시에 대한 상태 정보를 제공합니다.
status:
conditions:
- type: Synced
status: "True"
reason: ReconcileSuccess
- type: Watching
status: "True"
reason: WatchActive
watchingResources: 12
runningOperationRefs:
- name: config-validator-anjda
- name: config-validator-f0d92
주요 상태 필드:
Conditions: 표준 Crossplane 조건(Synced)과 WatchOperation 고유 조건.Watching: WatchOperation이 리소스를 적극적으로 감시하면 True, 일시 중지되거나 실패하면 False.watchingResources: 감시 중인 리소스 수.runningOperationRefs: 이 WatchOperation이 만든 실행 중인 Operations.
이벤트 (Events)
WatchOperations는 중요한 활동에 대해 이벤트를 발생시킵니다.
EstablishWatched(Warning) - 감시 설정 실패TerminateWatched(Warning) - 감시 종료 실패GarbageCollectOperations(Warning) - Operation 정리 실패CreateOperation(Warning) - Operation 생성 실패ReplaceRunningOperation(Warning) - Operation 교체 실패
모니터링 (Monitoring)
다음을 사용해 WatchOperations를 모니터링하세요.
# Check WatchOperation status
$ kubectl get watchoperation my-watchop
# View recent Operations created by the WatchOperation
$ kubectl get operations -l crossplane.io/watchoperation=my-watchop
# Check watched resource count
$ kubectl describe watchoperation my-watchop
# Check events
$ kubectl get events --field-selector involvedObject.name=my-watchop
베스트 프랙틱스 (Best practices)
리소스 선택
- 특정 라벨 셀렉터 사용: 정밀한 필터링으로 불필요한 Operations 방지.
- 자주 변경되는 리소스 피하기: 빈번하게 변경되는 리소스를 감시할 때는 주의.
- 작게 시작: 좁은 셀렉터로 시작해 필요에 따라 확장.
이벤트 처리
- 이벤트 필터링 구현: 불필요한 변경을 처리하지 않도록 generation, 삭제 타임스탬프, 상태 조건을 확인.
- Operation 볼륨 모니터링: 인기 있는 리소스는 많은 Operations를 만들 수 있음.
동시성 정책
- 적절한 동시성 정책 선택: 병렬로 실행할 수 있는 독립 처리에는
Allow. - 새 변경을 처리하기 전에 완료해야 하는 작업에는
Forbid. - 최신 상태만 중요한 상태 확인이나 모니터링에는
Replace.
히스토리 관리 (History management)
CronOperations처럼, WatchOperations도 완료된 Operations를 자동으로 정리합니다.
apiVersion: ops.crossplane.io/v1alpha1
kind: WatchOperation
metadata:
name: config-validator
spec:
watch:
apiVersion: v1
kind: ConfigMap
successfulHistoryLimit: 10 # Keep 10 successful Operations (default: 3)
failedHistoryLimit: 5 # Keep 5 failed Operations (default: 1)
operationTemplate:
# Operation template here
감시 리소스 주입 (Watched resource injection)
WatchOperations는 특별한 요구사항 이름 ops.crossplane.io/watched-resource를 사용해 변경된 리소스를 생성된 Operation에 자동으로 주입합니다.
from crossplane.function import request, response
def operate(req, rsp):
# Access the resource that triggered this Operation
watched_resource = request.get_required_resource(req, "ops.crossplane.io/watched-resource")
if not watched_resource:
response.set_output(rsp, {"error": "No watched resource found"})
return
# Process based on the watched resource
if watched_resource["kind"] == "ConfigMap":
config_data = watched_resource["data"]
# Validate configuration...
감시된 리소스는 Operation 템플릿에 선언할 필요 없이 함수의 required_resources 맵에서 사용 가능합니다.
함수 개발과 운영 고려 사항을 포함한 일반적인 Operations 베스트 프랙틱스는 Operation 베스트 프랙틱스를 참고하세요.
트러블슈팅 (Troubleshooting)
WatchOperation이 Operations를 생성하지 않음
- WatchOperation이
Watching=True조건을 갖는지 확인. - 감시된 리소스가 존재하고 셀렉터와 일치하는지 확인.
- 리소스가 실제로 변경되고 있는지 확인.
- 감시 설정 실패를 나타내는 이벤트를 찾아보세요.
너무 많은 Operations 생성됨
- 라벨 셀렉터를 더 적은 리소스와 일치하도록 정제.
- Forbid 또는 Replace 동시성 정책 사용 고려.
- 리소스가 예상보다 더 자주 변경되는지 확인.
- 함수 로직이 리소스 업데이트를 유발하지 않는지 검토.
감시 리소스를 처리하지 못하는 Operations
- 함수 능력에 operation이 포함되는지 확인.
- 함수가
ops.crossplane.io/watched-resource를 처리하는지 확인. - 처리 오류에 대한 함수 로그를 검토.
- 함수가 감시 중인 특정 리소스 유형을 처리할 수 있는지 확인.
다음 단계 (Next steps)
- Operation - 일회성 운영 작업 알아보기
- CronOperation - 예약된 Operations 알아보기
- Operations 시작하기 - 첫 번째 반응형 Operation 만들기
더 알아보기 (Learn more)
- CronOperation - cron 일정으로 작업 예약하기
- Operation - 한 번 완료까지 실행되는 작업