본문 바로가기
WIKI 기술 지식 베이스

FAQ

원문 보기 위키 갱신

Flagger를 사용하면서 가장 자주 묻는 질문과 답변을 이 문서에서 알려드릴게요. 배포 전략, Kubernetes 서비스, 라벨 셀렉터, 메트릭, Istio 라우팅 등 주제별로 정리해 봅시다.

출처: 문서

본문

배포 전략 (Deployment Strategies)

Flagger가 지원하는 배포 전략은 무엇인가요?

Flagger는 다음 배포 전략을 구현합니다:

점진적 트래픽 전환 대신 A/B 테스트는 언제 사용해야 하나요?

세션 어피니티가 필요한 프론트엔드 앱의 경우 HTTP 헤더나 쿠키 매치 조건을 사용해 특정 사용자 집합이 canary 분석 기간 내내 같은 버전에 머무르도록 해야 합니다.

Flagger를 서비스 메시 밖에 있는 앱을 관리하는 데 사용할 수 있나요?

서비스 메시에 배포되지 않은 앱의 경우 Flagger는 Kubernetes L4 네트워킹으로 블루/그린 스타일 배포를 오케스트레이션할 수 있습니다.

트래픽 미러링은 언제 사용할 수 있나요?

트래픽 미러링은 블루/그린 배포 전략이나 canary 릴리스의 사전 단계(pre-stage)에 사용할 수 있습니다. 트래픽 미러링은 들어오는 각 요청을 복사해 primary로 하나, canary 서비스로 하나를 보냅니다. 미러링은 멱등성(idempotent) 이 있거나 두 번 처리할 수 있는(primary 한 번, canary 한 번) 요청에 사용해야 합니다.

실패한 릴리스를 재시도하려면 어떻게 하나요?

canary 분석은 다음 오브젝트 중 하나의 변경에 의해 트리거됩니다:

  • Deployment/DaemonSet PodSpec (metadata, container image, command, ports, env, resources 등)
  • 볼륨으로 마운트되거나 환경 변수에 매핑된 ConfigMaps
  • 볼륨으로 마운트되거나 환경 변수에 매핑된 Secrets

릴리스를 재시도하려면 pod 템플릿에 annotation을 추가하거나 변경하면 됩니다:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    metadata:
      annotations:
        timestamp: "2020-03-10T14:24:48+0000"

HPA를 사용하지 않을 때 deployment replicas를 바꾸려면 어떻게 하나요?

HPA를 사용하지 않을 때 deployment replicas를 바꾸려면 canary deployment를 원하는 replica 수로 업데이트하고 템플릿에 annotation을 달아 분석을 트리거해야 합니다. 분석이 끝나면 Flagger는 spec.replicas 변경사항을 primary deployment로 승격합니다.

예시:

apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 4  #update replicas
  template:
    metadata:
      annotations:
        timestamp: "2022-02-10T14:24:48+0000" #add annotation to trigger analysis

분석이 비활성화되었을 때 canary 초기화 과정 중 다운타임 창이 생기는 이유는 무엇인가요?

분석이 비활성화되었을 때 다운타임 창이 생기는 것은 의도된 동작입니다. 이는 즉시 롤백을 가능하게 하고 Kubernetes deployment 초기화가 동작하는 방식을 모방합니다. 이를 피하려면 분석을 활성화하고(skipAnalysis: false) 초기화가 끝날 때까지 기다린 뒤 다시 비활성화하면 됩니다(skipAnalysis: true).

크로스 네임스페이스 참조를 비활성화하려면 어떻게 하나요?

Flagger는 기본적으로 네임스페이스 전반의 리소스(AlertProivder, MetricProvider, Gloo Upsteream)에 접근할 수 있습니다. 멀티 테넌트 환경에 있고 이를 비활성화하려면 no-cross-namespace-refs 플래그로 할 수 있습니다.

flagger \
  -no-cross-namespace-refs=true \
  ...

Kubernetes 서비스 (Kubernetes services)

클러스터 안에서 앱은 어떻게 노출되나요?

앱 이름이 podinfo라고 가정하면 다음과 같이 canary를 정의할 수 있습니다:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: podinfo
  namespace: test
spec:
  targetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: podinfo
  service:
    # service name (optional)
    name: podinfo
    # ClusterIP port number (required)
    port: 9898
    # container port name or number
    targetPort: http
    # port name can be http or grpc (default http)
    portName: http

service.name을 지정하지 않으면 targetRef.name이 apex 도메인과 canary/primary 서비스 이름 접두사로 사용됩니다. 서비스 이름은 불변(immutable) 필드로 취급해야 합니다. 변경하면 라우팅 충돌이 발생할 수 있습니다.

canary 스펙 서비스를 바탕으로 Flagger는 다음 Kubernetes ClusterIP 서비스를 생성합니다:

  • <service.name>.<namespace>.svc.cluster.local

    selector app=<name>-primary

  • <service.name>-primary.<namespace>.svc.cluster.local

    selector app=<name>-primary

  • <service.name>-canary.<namespace>.svc.cluster.local

    selector app=<name>

이로써 메시 밖 네임스페이스에서 podinfo.test:9898으로 들어오는 트래픽이 앱의 최신 안정 릴리스로 라우팅되도록 보장합니다.

apiVersion: v1
kind: Service
metadata:
  name: podinfo
spec:
  type: ClusterIP
  selector:
    app: podinfo-primary
  ports:
  - name: http
    port: 9898
    protocol: TCP
    targetPort: http
---
apiVersion: v1
kind: Service
metadata:
  name: podinfo-primary
spec:
  type: ClusterIP
  selector:
    app: podinfo-primary
  ports:
  - name: http
    port: 9898
    protocol: TCP
    targetPort: http
---
apiVersion: v1
kind: Service
metadata:
  name: podinfo-canary
spec:
  type: ClusterIP
  selector:
    app: podinfo
  ports:
  - name: http
    port: 9898
    protocol: TCP
    targetPort: http

podinfo-canary.test:9898 주소는 canary 분석 중에만 사용할 수 있으며, 적합성(conformance) 테스트나 부하 테스트에 사용할 수 있습니다.

다중 포트 (Multiple ports)

내 앱이 여러 포트에서 수신 대기합니다. 클러스터 안에서 어떻게 노출할 수 있나요?

포트 발견(port discovery)이 활성화되면 Flagger는 deployment 스펙을 스캔해 canary 서비스에 지정된 포트와 Envoy 사이드카 포트를 제외한 컨테이너 포트를 추출합니다. 이 포트들은 ClusterIP 서비스를 생성할 때 사용됩니다.

두 개의 포트를 노출하는 deployment의 경우:

apiVersion: apps/v1
kind: Deployment
spec:
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9899"
    spec:
      containers:
      - name: app
        ports:
        - containerPort: 8080
        - containerPort: 9090

Prometheus가 mTLS를 통해 포트 9090에 도달할 수 있도록 포트 발견을 활성화할 수 있습니다:

apiVersion: flagger.app/v1beta1
kind: Canary
spec:
  service:
    # container port used for canary analysis
    port: 8080
    # port name can be http or grpc (default http)
    portName: http
    # add all the other container ports
    # to the ClusterIP services (default false)
    portDiscovery: true
    trafficPolicy:
      tls:
        mode: ISTIO_MUTUAL

포트 8080과 9090 모두 ClusterIP 서비스에 추가됩니다.

라벨 셀렉터 (Label selectors)

Flagger가 지원하는 라벨 셀렉터는 무엇인가요?

대상 deployment는 app: <DEPLOYMENT-NAME> 형식의 단일 라벨 셀렉터를 가져야 합니다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo

app 외에도 Flagger는 name과 app.kubernetes.io/name 셀렉터를 지원합니다. 다른 규칙을 사용한다면 -selector-labels 플래그로 자신의 라벨을 지정할 수 있습니다. 예를 들어:

flagger \
  -selector-labels=service,name,app.kubernetes.io/name \
  ...

pod 어피니티와 안티 어피니티가 지원되나요?

Flagger는 대상 deployment의 pod 안티 어피니티와 토폴로지 분산 제약 조건에 정의된 각 match expression의 첫 번째 값을 다시 씁니다(rewrite). primary deployment를 생성하거나 업데이트할 때 다음 두 요구 사항을 충족해야 합니다:

  • match expression의 키는 selector-labels 파라미터로 지정된 라벨 중 하나여야 합니다. 기본 라벨은 app,name,app.kubernetes.io/name입니다.
  • 값은 대상 deployment의 이름과 일치해야 합니다.

이런 경우 Flagger의 rewrite는 값에 -primary 접미사를 붙입니다. 이 rewrite는 canary와 primary deployment가 만든 pod를 서로 다른 가용 영역에 분산하는 데 사용할 수 있습니다.

대상 deployment 예시:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  selector:
    matchLabels:
      app: podinfo
  template:
    metadata:
      labels:
        app: podinfo
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                    - podinfo
              topologyKey: topology.kubernetes.io/zone

생성된 primary deployment 예시:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo-primary
spec:
  selector:
    matchLabels:
      app: podinfo-primary
  template:
    metadata:
      labels:
        app: podinfo-primary
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                    - podinfo-primary
              topologyKey: topology.kubernetes.io/zone

app, name, app.kubernetes.io/name 외에 다른 라벨을 사용하는 것도 가능합니다.

안티 어피니티 예시(다른 라벨 사용):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: podinfo
spec:
  selector:
    matchLabels:
      app: podinfo
      affinity: podinfo
  template:
    metadata:
      labels:
        app: podinfo
        affinity: podinfo
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  affinity: podinfo
              topologyKey: topology.kubernetes.io/zone

메트릭 (Metrics)

Flagger는 요청 성공률과 지속 시간을 어떻게 측정하나요?

기본적으로 Flagger는 Prometheus 쿼리를 사용해 요청 성공률과 지속 시간을 측정합니다.

HTTP 요청 성공률 백분율

스펙:

  analysis:
    metrics:
    - name: request-success-rate
      # minimum req success rate (non 5xx responses)
      # percentage (0-100)
      thresholdRange:
        min: 99
      interval: 1m

Istio 쿼리:

sum(
    rate(
        istio_requests_total{
          reporter="destination",
          destination_workload_namespace=~"{{ namespace }}",
          destination_workload=~"{{ target }}",
          response_code!~"5.*"
        }[{{ interval }}]
    )
)
/
sum(
    rate(
        istio_requests_total{
          reporter="destination",
          destination_workload_namespace=~"{{ namespace }}",
          destination_workload=~"{{ target }}"
        }[{{ interval }}]
    )
)

Envoy 쿼리 (App Mesh):

sum(
    rate(
        envoy_cluster_upstream_rq{
          kubernetes_namespace="{{ namespace }}",
          kubernetes_pod_name=~"{{ target }}",
          envoy_response_code!~"5.*"
        }[{{ interval }}]
    )
)
/
sum(
    rate(
        envoy_cluster_upstream_rq{
          kubernetes_namespace="{{ namespace }}",
          kubernetes_pod_name=~"{{ target }}"
        }[{{ interval }}]
    )
)

Envoy 쿼리 (Contour and Gloo):

sum(
    rate(
        envoy_cluster_upstream_rq{
            envoy_cluster_name=~"{{ namespace }}-{{ target }}",
            envoy_response_code!~"5.*"
        }[{{ interval }}]
    )
)
/
sum(
    rate(
        envoy_cluster_upstream_rq{
            envoy_cluster_name=~"{{ namespace }}-{{ target }}",
        }[{{ interval }}]
    )
)

HTTP 요청 P99 지속 시간

스펙:

  analysis:
    metrics:
    - name: request-duration
      # maximum req duration P99
      # milliseconds
      thresholdRange:
        max: 500
      interval: 1m

Istio 쿼리:

histogram_quantile(0.99,
  sum(
    irate(
      istio_request_duration_milliseconds_bucket{
        reporter="destination",
        destination_workload=~"{{ target }}",
        destination_workload_namespace=~"{{ namespace }}"
      }[{{ interval }}]
    )
  ) by (le)
)

Envoy 쿼리 (App Mesh, Contour and Gloo):

histogram_quantile(0.99,
  sum(
    irate(
      envoy_cluster_upstream_rq_time_bucket{
        kubernetes_pod_name=~"{{ target }}",
        kubernetes_namespace=~"{{ namespace }}"
      }[{{ interval }}]
    )
  ) by (le)
)

참고 메트릭 간격은 컨트롤 루프 간격보다 작거나 같아야 합니다.

커스텀 메트릭을 사용할 수 있나요?

분석은 Prometheus, Datadog, AWS CloudWatch, New Relic, Graphite에서 제공하는 메트릭으로 확장할 수 있습니다. 커스텀 메트릭 사용 방법에 대한 자세한 내용은 메트릭 문서를 읽어보세요.

Istio Gateway API

Istio를 Gateway API와 함께 사용한다면 Prometheus 쿼리에 reporter="source"를 포함해야 합니다. 예를 들어 HTTP 요청 오류 백분율을 계산하려면 쿼리는 다음과 같을 것입니다:

100 - sum(
    rate(
        istio_requests_total{
          reporter="source",
          destination_workload_namespace=~"{{ namespace }}",
          destination_workload=~"{{ target }}",
          response_code!~"5.*"
        }[{{ interval }}]
    )
)
/
sum(
    rate(
        istio_requests_total{
          reporter="source",
          destination_workload_namespace=~"{{ namespace }}",
          destination_workload=~"{{ target }}"
        }[{{ interval }}]
    )
) * 100

Istio 라우팅 (Istio routing)

Flagger는 Istio와 어떻게 상호작용하나요?

Flagger는 Canary 서비스 스펙을 바탕으로 Istio Virtual Service와 Destination Rule을 생성합니다. 서비스 구성으로 앱을 메시 안이나 밖에 노출할 수 있습니다. 또한 트래픽 정책, HTTP 매치 조건, URI rewrite 규칙, CORS 정책, 타임아웃, 재시도를 정의할 수 있습니다.

아래 스펙은 frontend 워크로드를 메시 안 frontend.test.svc.cluster.local:9898와 메시 밖 frontend.example.com에 노출합니다. 외부 호스트에는 Istio ingress gateway를 지정해야 합니다.

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: frontend
  namespace: test
spec:
  service:
    # container port
    port: 9898
    # service port name (optional, will default to "http")
    portName: http-frontend
    # Istio gateways (optional)
    gateways:
    - istio-system/public-gateway
    - mesh
    # Istio virtual service host names (optional)
    hosts:
    - frontend.example.com
    # Istio traffic policy
    trafficPolicy:
      tls:
        # use ISTIO_MUTUAL when mTLS is enabled
        mode: DISABLE
    # HTTP match conditions (optional)
    match:
      - uri:
          prefix: /
    # HTTP rewrite (optional)
    rewrite:
      uri: /
    # Istio retry policy (optional)
    retries:
      attempts: 3
      perTryTimeout: 1s
      retryOn: "gateway-error,connect-failure,refused-stream"
    # Add headers (optional)
    headers:
      request:
        add:
          x-some-header: "value"
    # cross-origin resource sharing policy (optional)
    corsPolicy:
      allowOrigin:
        - example.com
      allowMethods:
        - GET
      allowCredentials: false
      allowHeaders:
        - x-some-header
      maxAge: 24h

위 스펙에 대해 Flagger는 다음 virtual service를 생성합니다:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: frontend
  namespace: test
  ownerReferences:
    - apiVersion: flagger.app/v1beta1
      blockOwnerDeletion: true
      controller: true
      kind: Canary
      name: podinfo
      uid: 3a4a40dd-3875-11e9-8e1d-42010a9c0fd1
spec:
  gateways:
    - istio-system/public-gateway
    - mesh
  hosts:
    - frontend.example.com
    - frontend
  http:
  - corsPolicy:
      allowHeaders:
      - x-some-header
      allowMethods:
      - GET
      allowOrigin:
      - example.com
      maxAge: 24h
    headers:
      request:
        add:
          x-some-header: "value"
    match:
    - uri:
        prefix: /
    rewrite:
      uri: /
    route:
    - destination:
        host: podinfo-primary
      weight: 100
    - destination:
        host: podinfo-canary
      weight: 0
    retries:
      attempts: 3
      perTryTimeout: 1s
      retryOn: "gateway-error,connect-failure,refused-stream"

virtual service의 각 목적지에 대해 규칙이 생성됩니다:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: frontend-primary
  namespace: test
spec:
  host: frontend-primary
  trafficPolicy:
    tls:
      mode: DISABLE
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: frontend-canary
  namespace: test
spec:
  host: frontend-canary
  trafficPolicy:
    tls:
      mode: DISABLE

Flagger는 virtual service와 destination rule을 canary 서비스 스펙과 동기화해 둡니다. virtual service 스펙을 직접 수정하면 덮어써집니다.

메시 안 http://backend.test.svc.cluster.local:9898에 워크로드를 노출하려면 서비스 스펙에 컨테이너 포트와 트래픽 정책만 포함하면 됩니다:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: backend
  namespace: test
spec:
  service:
    port: 9898
    trafficPolicy:
      tls:
        mode: DISABLE

위 스펙을 바탕으로 Flagger는 다음과 같은 여러 ClusterIP 서비스를 생성합니다:

apiVersion: v1
kind: Service
metadata:
  name: backend-primary
  ownerReferences:
  - apiVersion: flagger.app/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: Canary
    name: backend
    uid: 2ca1a9c7-2ef6-11e9-bd01-42010a9c0145
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 9898
    protocol: TCP
    targetPort: 9898
  selector:
    app: backend-primary

Flagger는 ingress gateway를 통해 클러스터 밖에 노출되는 사용자 대면 앱과 메시 안에서만 접근 가능한 백엔드 HTTP API 모두에 동작합니다.

Delegation이 활성화되면 Flagger는 hosts와 gateway 없이 Istio VirtualService를 생성해 서비스가 Istio 위임과 호환되도록 합니다.

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: backend
  namespace: test
spec:
  service:
    delegation: true
    port: 9898
  targetRef:
    apiVersion: v1
    kind: Deployment
    name: podinfo
  analysis:
    interval: 15s
    threshold: 15
    maxWeight: 30
    stepWeight: 10

위 스펙을 바탕으로 Flagger는 다음 virtual service를 생성합니다:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: backend
  namespace: test
  ownerReferences:
  - apiVersion: flagger.app/v1beta1
    blockOwnerDeletion: true
    controller: true
    kind: Canary
    name: backend
    uid: 58562662-5e10-4512-b269-2b789c1b30fe
spec:
  http:
  - route:
    - destination:
        host: podinfo-primary
      weight: 100
    - destination:
        host: podinfo-canary
      weight: 0

따라서 다음 virtual service는 위의 delegate VirtualService로 트래픽을 /podinfo로 전달합니다.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: frontend
  namespace: test
spec:
  gateways:
    - istio-system/public-gateway
    - mesh
  hosts:
    - frontend.example.com
    - frontend
  http:
  - match:
    - uri:
        prefix: /podinfo
    rewrite:
      uri: /
    delegate:
      name: backend
      namespace: test

pilot 환경 변수 PILOT_ENABLE_VIRTUAL_SERVICE_DELEGATE도 설정해야 합니다. Istio Delegation 사용에 대해서는 Virtual Service와 pilot 환경 변수 문서를 참고할 수 있습니다.

Istio Ingress Gateway

같은 외부 도메인에 여러 canary를 어떻게 노출할 수 있나요?

두 앱(하나는 메인 웹사이트를, 하나는 REST API를 서비스하는 앱)이 있다고 가정하면 각 앱에 대해 다음과 같이 canary 오브젝트를 정의할 수 있습니다:

apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: website
spec:
  service:
    port: 8080
    gateways:
    - istio-system/public-gateway
    hosts:
    - my-site.com
    match:
      - uri:
          prefix: /
    rewrite:
      uri: /
---
apiVersion: flagger.app/v1beta1
kind: Canary
metadata:
  name: webapi
spec:
  service:
    port: 8080
    gateways:
    - istio-system/public-gateway
    hosts:
    - my-site.com
    match:
      - uri:
          prefix: /api
    rewrite:
      uri: /

위 구성에 따라 Flagger는 같은 ingress gateway와 외부 호스트에 바인딩된 두 개의 virtual service를 생성합니다. Istio Pilot은 두 서비스를 병합하고 website 규칙은 병합된 구성의 목록 끝으로 이동합니다.

호스트 병합은 canary가 mesh gateway가 아닌 다른 ingress gateway에 바인딩된 경우에만 동작한다는 점을 참고하세요.

Istio 상호 TLS (Istio Mutual TLS)

canary에 mTLS를 어떻게 활성화하나요?

글로벌 mTLS가 활성화된 Istio를 배포할 때는 TLS 모드를 ISTIO_MUTUAL로 설정해야 합니다:

apiVersion: flagger.app/v1beta1
kind: Canary
spec:
  service:
    trafficPolicy:
      tls:
        mode: ISTIO_MUTUAL

Istio를 permissive 모드로 실행한다면 TLS를 비활성화할 수 있습니다:

apiVersion: flagger.app/v1beta1
kind: Canary
spec:
  service:
    trafficPolicy:
      tls:
        mode: DISABLE

Flagger가 메시 밖에 있다면 부하 테스트를 어떻게 시작할 수 있나요?

Flagger가 메시 밖에서 부하 테스터 서비스를 호출할 수 있으려면 mTLS를 비활성화해야 합니다:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: flagger-loadtester
  namespace: test
spec:
  host: "flagger-loadtester.test.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: DISABLE
---
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: flagger-loadtester
  namespace: test
spec:
  selector:
    matchLabels:
      app: flagger-loadtester
  mtls:
    mode: DISABLE

ExternalDNS

annotation을 사용할 수 있나요?

Flagger는 annotation(과 라벨)을 생성된 모든 apex, primary, canary 오브젝트에 전파합니다. 이를 통해 external-dns annotation을 사용할 수 있습니다.

Flagger가 annotation을 설정하도록 구성할 수 있습니다:

spec:
  service:
    apex:
      annotations:
        external-dns.alpha.kubernetes.io/hostname: "mydomain.com"
    primary:
      annotations:
        external-dns.alpha.kubernetes.io/hostname: "primary.mydomain.com"
    canary:
      annotations:
        external-dns.alpha.kubernetes.io/hostname: "canary.mydomain.com"

다중 소스와 Istio

/!\\ apex annotation은 생성된 Kubernetes Services와 생성된 Istio VirtualServices 오브젝트 양쪽에 추가됩니다. external-dns를 두 소스 모두 사용하도록 구성했다면 이는 충돌을 만들 것입니다!

    spec:
      containers:
        args:
        - --source=service              # choose only one
        - --source=istio-virtualservice # of these two

ExternalDNS 문서 확인하기

더 알아보기 (Learn more)