Ingress 구성

Ingress 구성 (Ingress Configuration)

Argo CD API 서버는 gRPC 서버(CLI가 사용)와 HTTP/HTTPS 서버(UI가 사용)를 모두 실행해요. 두 프로토콜 모두 argocd-server 서비스 객체에 의해 다음 포트로 노출돼요:

  • 443 - gRPC/HTTPS
  • 80 - HTTP (HTTPS로 리다이렉트)

Ingress를 구성하는 방법은 여러 가지가 있어요. 이 문서는 Ambassador, Contour, ingress-nginx, F5 NGINX, Traefik, AWS, Istio, Gateway API 등 다양한 인그레스 컨트롤러로 Argo CD를 노출하는 방법을 다뤄요.

출처: 문서

본문

Ambassador

Ambassador Edge Stack은 자동 TLS 종료와 CLI, UI 모두에 대한 라우팅 기능을 가진 Kubernetes ingress 컨트롤러로 사용할 수 있어요.

API 서버는 TLS를 비활성화한 상태로 실행되어야 해요. argocd-server deployment를 편집해 argocd-server 명령에 --insecure 플래그를 추가하거나, 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 간단히 server.insecure: "true"를 설정하세요. argocd CLI가 요청 host 헤더에 포트 번호를 포함하므로 두 개의 Mapping이 필요해요.

[!NOTE] gRPC-Web을 사용한다면 TLS를 비활성화할 필요가 없어요.

옵션 1: 호스트 기반 라우팅용 Mapping CRD (Option 1: Mapping CRD for Host-based Routing)

apiVersion: getambassador.io/v2
kind: Mapping
metadata:
  name: argocd-server-ui
  namespace: argocd
spec:
  host: argocd.example.com
  prefix: /
  service: https://argocd-server:443
---
apiVersion: getambassador.io/v2
kind: Mapping
metadata:
  name: argocd-server-cli
  namespace: argocd
spec:
  # NOTE: the port must be ignored if you have strip_matching_host_port enabled on envoy
  host: argocd.example.com:443
  prefix: /
  service: argocd-server:80
  regex_headers:
    Content-Type: "^application/grpc.*$"
  grpc: true

argocd CLI로 로그인:

argocd login <host>

옵션 2: 경로 기반 라우팅용 Mapping CRD (Option 2: Mapping CRD for Path-based Routing)

API 서버는 비-루트 경로(예: /argo-cd)에서 사용할 수 있도록 구성되어야 해요. argocd-server deployment를 편집해 argocd-server 명령에 --rootpath=/argo-cd 플래그를 추가하세요.

apiVersion: getambassador.io/v2
kind: Mapping
metadata:
  name: argocd-server
  namespace: argocd
spec:
  prefix: /argo-cd
  rewrite: /argo-cd
  service: https://argocd-server:443

argocd-cmd-params-cm configmap 예시:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cmd-params-cm
  namespace: argocd
  labels:
    app.kubernetes.io/name: argocd-cmd-params-cm
    app.kubernetes.io/part-of: argocd
data:
  ## Server properties
  # Value for base href in index.html. Used if Argo CD is running behind reverse proxy under subpath different from / (default "/")
  server.basehref: "/argo-cd"
  # Used if Argo CD is running behind reverse proxy under subpath different from /
  server.rootpath: "/argo-cd"

비-루트 경로에 대해 추가 --grpc-web-root-path 플래그를 사용해 argocd CLI로 로그인하세요.

argocd login <host>:<port> --grpc-web-root-path /argo-cd

Contour

Contour ingress 컨트롤러는 엣지에서 TLS 인그레스 트래픽을 종료할 수 있어요.

Argo CD API 서버는 TLS를 비활성화한 상태로 실행되어야 해요. argocd-server Deployment를 편집해 argocd-server 컨테이너 명령에 --insecure 플래그를 추가하거나, 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 간단히 server.insecure: "true"를 설정하세요.

또한 Contour 인스턴스 두 개를 배포해 내부 전용 인그레스 경로와 외부 전용 인그레스 경로를 제공할 수도 있어요. 하나는 private-subnet LoadBalancer 서비스 뒤에, 하나는 public-subnet LoadBalancer 서비스 뒤에 배포하면 돼요. private Contour deployment는 kubernetes.io/ingress.class: contour-internal로 어노테이션된 Ingress를 선택하고, public Contour deployment는 kubernetes.io/ingress.class: contour-external로 어노테이션된 Ingress를 선택해요.

이렇게 하면 Argo CD UI를 비공개로 배포하면서도 SSO 콜백이 성공하도록 허용할 수 있어요.

BYO 인증서와 함께하는 여러 Ingress 객체를 사용한 비공개 Argo CD UI (Private Argo CD UI with Multiple Ingress Objects and BYO Certificate)

Contour Ingress는 Ingress 객체당 단일 프로토콜만 지원하므로, Ingress 객체 세 개를 정의하세요. 하나는 비공개 HTTP/HTTPS용, 하나는 비공개 gRPC용, 하나는 공개 HTTPS SSO 콜백용이에요.

내부 HTTP/HTTPS Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-http
  annotations:
    kubernetes.io/ingress.class: contour-internal
    ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  rules:
  - host: internal.path.to.argocd.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: http
  tls:
  - hosts:
    - internal.path.to.argocd.io
    secretName: your-certificate-name

내부 gRPC Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-grpc
  annotations:
    kubernetes.io/ingress.class: contour-internal
spec:
  rules:
  - host: grpc-internal.path.to.argocd.io
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
  tls:
  - hosts:
    - grpc-internal.path.to.argocd.io
    secretName: your-certificate-name

외부 HTTPS SSO 콜백 Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-external-callback-http
  annotations:
    kubernetes.io/ingress.class: contour-external
    ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  rules:
  - host: external.path.to.argocd.io
    http:
      paths:
      - path: /api/dex/callback
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: http
  tls:
  - hosts:
    - external.path.to.argocd.io
    secretName: your-certificate-name

gRPC 프로토콜 프록싱을 연결하려면 argocd-server Service에 projectcontour.io/upstream-protocol.h2c: "https,443"로 어노테이션해야 해요.

그런 다음 API 서버는 TLS를 비활성화한 상태로 실행되어야 해요. argocd-server deployment를 편집해 --insecure 플래그를 argocd-server 명령에 추가하거나, 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 간단히 server.insecure: "true"를 설정하세요.

Contour httpproxy CRD:

Contour httpproxy CRD를 사용하면 GRPC와 REST api에 같은 호스트 이름을 사용할 수 있어요.

apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
  name: argocd-server
  namespace: argocd
spec:
  ingressClassName: contour
  virtualhost:
    fqdn: path.to.argocd.io
    tls:
      secretName: wildcard-tls
  routes:
    - conditions:
        - prefix: /
        - header:
            name: Content-Type
            contains: application/grpc
      services:
        - name: argocd-server
          port: 80
          protocol: h2c # allows for unencrypted http2 connections
      timeoutPolicy:
        response: 1h
        idle: 600s
        idleConnection: 600s
    - conditions:
        - prefix: /
      services:
        - name: argocd-server
          port: 80

kubernetes/ingress-nginx (DEPRECATED)

ingress-nginx는 2026년 3월 24일에 은퇴하고 보관되었어요. 이 섹션은 여전히 다른 Ingress Controller의 참고용으로 사용할 수 있어요.

옵션 1: SSL-Passthrough

Argo CD는 같은 포트(443)에서 여러 프로토콜(gRPC/HTTPS)을 제공해요. 이것은 argocd-service에 대해 단일 nginx ingress 객체와 규칙을 정의하려 할 때 문제가 돼요. nginx.ingress.kubernetes.io/backend-protocol 어노테이션이 백엔드 프로토콜(예: HTTP, HTTPS, GRPC, GRPCS)에 대해 단일 값만 받기 때문이에요.

단일 ingress 규칙과 호스트 이름으로 Argo CD API 서버를 노출하려면 nginx.ingress.kubernetes.io/ssl-passthrough 어노테이션을 사용해 TLS 연결을 통과시키고 Argo CD API 서버에서 TLS를 종료해야 해요.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https

위 규칙은 Argo CD API 서버에서 TLS를 종료하고, 서버가 사용 중인 프로토콜을 감지해 적절히 응답해요. nginx.ingress.kubernetes.io/ssl-passthrough 어노테이션은 nginx-ingress-controller의 커맨드라인 인자에 --enable-ssl-passthrough 플래그가 추가되어야 한다는 점을 참고하세요.

cert-manager와 Let's Encrypt를 사용한 SSL-Passthrough

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-ingress
  namespace: argocd
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/ssl-passthrough: "true"
    # If you encounter a redirect loop or are getting a 307 response code
    # then you need to force the nginx ingress to connect to the backend using HTTPS.
    #
    nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
spec:
  ingressClassName: nginx
  rules:
  - host: argocd.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-server-tls # as expected by argocd-server

옵션 2: Ingress Controller에서 SSL 종료 (SSL Termination at Ingress Controller)

대안적인 접근 방식은 Ingress에서 SSL 종료를 수행하는 것이에요. ingress-nginx Ingress는 Ingress 객체당 단일 프로토콜만 지원하므로, nginx.ingress.kubernetes.io/backend-protocol 어노테이션을 사용해 두 개의 Ingress 객체를 정의해야 해요. 하나는 HTTP/HTTPS용, 다른 하나는 gRPC용이에요.

각 인그레스는 다른 도메인(argocd.example.comgrpc.argocd.example.com)을 위한 거예요. 이렇게 하려면 예상치 못한 동작을 피하기 위해 Ingress 리소스가 서로 다른 TLS secretName을 사용해야 해요.

HTTP/HTTPS Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-http-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: http
    host: argocd.example.com
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-ingress-http

gRPC Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-grpc-ingress
  namespace: argocd
  annotations:
    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
    host: grpc.argocd.example.com
  tls:
  - hosts:
    - grpc.argocd.example.com
    secretName: argocd-ingress-grpc

그런 다음 API 서버는 TLS를 비활성화한 상태로 실행되어야 해요. argocd-server deployment를 편집해 --insecure 플래그를 argocd-server 명령에 추가하거나, 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 간단히 server.insecure: "true"를 설정하세요.

이 접근 방식의 명백한 단점은 API 서버에 두 개의 별도 호스트 이름이 필요하다는 것이에요. 하나는 gRPC용, 다른 하나는 HTTP/HTTPS용이에요. 하지만 ingress 컨트롤러에서 TLS 종료가 일어나도록 허용해요.

F5 NGINX Ingress Controller

ArgoCD를 제대로 지원하려면 이 Ingress Controller가 ConfigMap을 통해 HTTP/2 지원으로 구성되어야 해요.

그 구성을 가진 후에는 Ingress에서 SSL을 종료하고 서로 다른 도메인으로 HTTP용과 GRPC용 두 개의 인그레스를 가질 수 있어요:

HTTP/HTTPS Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-http-ingress
  namespace: argocd
  annotations:
    nginx.org/redirect-to-https: "true"
spec:
  ingressClassName: f5-nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: http
    host: argocd.example.com
  tls:
  - hosts:
    - argocd.example.com
    secretName: argocd-ingress-http

gRPC Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-server-grpc-ingress
  namespace: argocd
  annotations:
    nginx.org/grpc-services: argocd-server
spec:
  ingressClassName: f5-nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              name: https
    host: grpc.argocd.example.com
  tls:
  - hosts:
    - grpc.argocd.example.com
    secretName: argocd-ingress-grpc

그런 다음 API 서버는 TLS를 비활성화한 상태로 실행되어야 해요. argocd-server deployment를 편집해 --insecure 플래그를 argocd-server 명령에 추가하거나, 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 간단히 server.insecure: "true"를 설정하세요.

Traefik (v3.0)

Traefik은 엣지 라우터로 사용할 수 있으며 같은 배포 안에서 TLS 종료를 제공해요.

현재 NGINX보다 유리한 점은 TCP와 HTTP 연결을 같은 포트에서 종료할 수 있다는 것이에요. 즉 여러 호스트나 경로가 필요하지 않아요.

API 서버를 TLS 비활성화 상태로 실행하세요. argocd-server deployment를 편집해 --insecure 플래그를 argocd-server 명령에 추가하거나 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 server.insecure: "true"를 설정하세요.

IngressRoute CRD

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: argocd-server
  namespace: argocd
spec:
  entryPoints:
    - websecure
  routes:
    - kind: Rule
      match: Host(`argocd.example.com`)
      priority: 10
      services:
        - name: argocd-server
          port: 80
    - kind: Rule
      match: Host(`argocd.example.com`) && Header(`Content-Type`, `application/grpc`)
      priority: 11
      services:
        - name: argocd-server
          port: 80
          scheme: h2c
  tls:
    certResolver: default

AWS Application Load Balancers (ALBs) 그리고 Classic ELB (HTTP Mode)

AWS ALB는 UI와 gRPC 트래픽 모두에 대한 L7 Load Balancer로 사용할 수 있으며, Classic ELB와 NLB는 둘 모두에 대한 L4 Load Balancer로 사용할 수 있어요.

ALB를 사용할 때는 argocd-server용 두 번째 서비스를 만들고 싶을 거예요. 백엔드 프로토콜이 HTTP1이 아닌 HTTP2이므로 GRPC 트래픽을 UI 트래픽과 다른 대상 그룹으로 보내도록 ALB에 알려야 하기 때문에 이 작업이 필요해요.

apiVersion: v1
kind: Service
metadata:
  annotations:
    alb.ingress.kubernetes.io/backend-protocol-version: GRPC # This tells AWS to send traffic from the ALB using GRPC. Plain HTTP2 can be used, but the health checks won't be available because argo currently downgrades non-grpc calls to HTTP1
  labels:
    app: argogrpc
  name: argogrpc
  namespace: argocd
spec:
  ports:
  - name: "443"
    port: 443
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-server
  sessionAffinity: None
  type: NodePort

이 서비스를 만든 후에는 아래처럼 alb.ingress.kubernetes.io/conditions 어노테이션을 사용해 모든 application/grpc 트래픽을 새 HTTP2 백엔드로 조건부로 라우팅하도록 Ingress를 구성할 수 있어요. 참고: 조건 어노테이션에서 . 뒤의 값은 트래픽을 라우팅하려는 서비스와 같은 이름이어야 하며, serviceName이 일치하는 모든 경로에 적용돼요.

또한 헬스 체크 경로를 /grpc.health.v1.Health/Check로 설정해 헬스 체크가 argocd-server에서 gRPC 헬스 상태 코드 OK - 0을 반환하도록 구성할 수 있다는 점도 참고하세요. 기본적으로 ALB의 gRPC 헬스 체크는 헬스 체크 경로 /AWS.ALB/healthcheck에서 상태 코드 UNIMPLEMENTED - 12를 반환해요.

  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    annotations:
      alb.ingress.kubernetes.io/backend-protocol: HTTPS
      # Use this annotation (which must match a service name) to route traffic to HTTP2 backends.
      alb.ingress.kubernetes.io/conditions.argogrpc: |
        [{"field":"http-header","httpHeaderConfig":{"httpHeaderName": "Content-Type", "values":["application/grpc"]}}]
      alb.ingress.kubernetes.io/listen-ports: '[{"HTTPS":443}]'
      # Use this annotation to receive OK - 0 instead of UNIMPLEMENTED - 12 for gRPC health check.
      alb.ingress.kubernetes.io/healthcheck-path: /grpc.health.v1.Health/Check
      alb.ingress.kubernetes.io/success-codes: '0'
    name: argocd
    namespace: argocd
  spec:
    rules:
    - host: argocd.argoproj.io
      http:
        paths:
        - path: /
          backend:
            service:
              name: argogrpc # The grpc service must be placed before the argocd-server for the listening rules to be created in the correct order
              port:
                number: 443
          pathType: Prefix
        - path: /
          backend:
            service:
              name: argocd-server
              port:
                number: 443
          pathType: Prefix
    tls:
    - hosts:
      - argocd.argoproj.io

Istio

다음 구성을 사용해 Argo CD를 Istio 뒤에 둘 수 있어요. 이 예시는 Argo CD를 Istio 뒤에 제공하고 서브패스(예: /argocd)를 사용해요.

먼저 Argo CD를 서브패스(즉 /argocd)로 실행할 수 있는지 확인해야 해요. 이를 위해 argocd 프로젝트의 install.yaml을 그대로 사용했어요

curl -kLs -o install.yaml https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

다음 파일을 kustomization.yaml로 저장하세요:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./install.yaml

patches:
- path: ./patch.yml

그리고 다음 줄을 patch.yml로:

# Use --insecure so Ingress can send traffic with HTTP
# --basehref /argocd is the subpath like https://IP/argocd
# env was added because of https://github.com/argoproj/argo-cd/issues/3572 error
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: argocd-server
spec:
 template:
   spec:
     containers:
     - args:
       - /usr/local/bin/argocd-server
       - --staticassets
       - /shared/app
       - --redis
       - argocd-redis:6379
       - --insecure
       - --basehref
       - /argocd
       - --rootpath
       - /argocd
       name: argocd-server
       env:
       - name: ARGOCD_MAX_CONCURRENT_LOGIN_REQUESTS_COUNT
         value: "0"

Argo CD를 설치하세요(현재 디렉터리에 위에 정의된 세 개의 YAML 파일만 있어야 해요):

kubectl apply -k ./ -n argocd --wait=true

Istio용 secret을 만들어야 합니다(우리 경우 secretname은 argocd Namespace의 argocd-server-tls). 그 후 Istio 리소스를 만듭니다

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: argocd-gateway
  namespace: argocd
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
    tls:
     httpsRedirect: true
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - "*"
    tls:
      credentialName: argocd-server-tls
      maxProtocolVersion: TLSV1_3
      minProtocolVersion: TLSV1_2
      mode: SIMPLE
      cipherSuites:
        - ECDHE-ECDSA-AES128-GCM-SHA256
        - ECDHE-RSA-AES128-GCM-SHA256
        - ECDHE-ECDSA-AES128-SHA
        - AES128-GCM-SHA256
        - AES128-SHA
        - ECDHE-ECDSA-AES256-GCM-SHA384
        - ECDHE-RSA-AES256-GCM-SHA384
        - ECDHE-ECDSA-AES256-SHA
        - AES256-GCM-SHA384
        - AES256-SHA
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: argocd-virtualservice
  namespace: argocd
spec:
  hosts:
  - "*"
  gateways:
  - argocd-gateway
  http:
  - match:
    - uri:
        prefix: /argocd
    route:
    - destination:
        host: argocd-server
        port:
          number: 80

이제 http://<IP>/argocd로 이동할 수 있어요(HTTPS로 리다이렉트될 거예요).

Kubernetes Ingress가 있는 Google Cloud 로드 밸런서 (Google Cloud load balancers with Kubernetes Ingress)

Kubernetes 객체만 사용해 Load Balancer를 배포하려면 GKE와 Google Cloud의 통합을 활용할 수 있어요.

이를 위해 다섯 개의 객체가 필요해요:

  • Service
  • BackendConfig
  • FrontendConfig
  • SSL 인증서가 있는 secret
  • GKE용 Ingress

이 Google 통합에 사용할 수 있는 모든 옵션에 대한 세부 정보가 필요하면 Ingress 기능 구성에 대한 Google 문서를 확인할 수 있어요.

내부 TLS 비활성화 (Disable internal TLS)

먼저 HTTP에서 HTTPS로의 내부 리다이렉션 루프를 피하려면 API 서버를 TLS 비활성화 상태로 실행해야 해요.

argocd-server deployment의 argocd-server 명령에서 --insecure 플래그를 편집하거나, 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 간단히 server.insecure: "true"를 설정하세요.

Service 만들기 (Creating a service)

이제 외부에서 접근 가능한 서비스가 필요해요. 이것은 실질적으로 Argo CD가 가진 내부 서비스와 같지만 Google Cloud 어노테이션이 있어요. 이 서비스는 kube-proxy 없이 로드 밸런서가 파드에 직접 트래픽을 보낼 수 있도록 Network Endpoint Group (NEG)을 사용하도록 어노테이션되어 있다는 점을 참고하세요. 원하지 않는다면 neg 어노테이션을 제거하세요.

서비스:

apiVersion: v1
kind: Service
metadata:
  name: argocd-server
  namespace: argocd
  annotations:
    cloud.google.com/neg: '{"ingress": true}'
    cloud.google.com/backend-config: '{"ports": {"http":"argocd-backend-config"}}'
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 8080
  selector:
    app.kubernetes.io/name: argocd-server

BackendConfig 만들기 (Creating a BackendConfig)

이전 서비스가 argocd-backend-config라는 백엔드 config를 참조하는 것 보이나요? 이 YAML로 배포하세요:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: argocd-backend-config
  namespace: argocd
spec:
  healthCheck:
    checkIntervalSec: 30
    timeoutSec: 5
    healthyThreshold: 1
    unhealthyThreshold: 2
    type: HTTP
    requestPath: /healthz
    port: 8080

파드와 같은 헬스 체크를 사용해요.

FrontendConfig 만들기 (Creating a FrontendConfig)

이제 HTTP에서 HTTPS로의 리다이렉트가 있는 프론트엔드 config를 배포할 수 있어요:

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: argocd-frontend-config
  namespace: argocd
spec:
  redirectToHttps:
    enabled: true

[!NOTE] 다음 두 단계(인증서 secret과 Ingress)는 인증서를 직접 관리하고, 그 인증서와 키 파일이 있다고 가정하고 설명해요. 인증서가 Google-managed인 경우 Google-managed SSL 인증서 사용 가이드를 사용해 다음 두 단계를 수정하세요.


인증서 secret 만들기 (Creating a certificate secret)

이제 로드 밸런서에 원하는 SSL 인증서가 있는 secret을 만들어야 해요. 인증서 키가 저장된 경로에서 이 명령을 실행하기만 하면 돼요:

kubectl -n argocd create secret tls secret-yourdomain-com \
  --cert cert-file.crt --key key-file.key

Ingress 만들기 (Creating an Ingress)

그리고 마지막으로, 그 모든 것을 마무리할 우리의 Ingress가 있어요. 프론트엔드 config, 서비스, 인증서 secret에 대한 참조를 참고하세요.


[!NOTE] 1.21.3-gke.1600보다 이전 버전을 실행하는 GKE 클러스터의 경우, pathType 필드에 대해 지원되는 유일한 값ImplementationSpecific이에요. 따라서 GKE 클러스터 버전을 확인해야 해요. 버전에 따라 다른 YAML을 사용해야 해요.


1.21.3-gke.1600보다 이전 버전을 사용한다면 다음 Ingress 리소스를 사용해야 해요:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd
  namespace: argocd
  annotations:
    networking.gke.io/v1beta1.FrontendConfig: argocd-frontend-config
spec:
  tls:
    - secretName: secret-example-com
  rules:
    - host: argocd.example.com
      http:
        paths:
        - pathType: ImplementationSpecific
          path: "/*"   # "*" is needed. Without this, the UI Javascript and CSS will not load properly
          backend:
            service:
              name: argocd-server
              port:
                number: 80

1.21.3-gke.1600 이상 버전을 사용한다면 다음 Ingress 리소스를 사용해야 해요:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd
  namespace: argocd
  annotations:
    networking.gke.io/v1beta1.FrontendConfig: argocd-frontend-config
spec:
  tls:
    - secretName: secret-example-com
  rules:
    - host: argocd.example.com
      http:
        paths:
        - pathType: Prefix
          path: "/"
          backend:
            service:
              name: argocd-server
              port:
                number: 80

이미 알고 있듯이 로드 밸런서를 배포하고 연결을 받을 준비가 되기까지 몇 분이 걸릴 수 있어요. 준비되면 Load Balancer의 공개 IP 주소를 얻고, DNS 서버(Google 또는 타사)로 가서 도메인 또는 서브도메인(즉 argocd.example.com)을 그 IP 주소로 지정하세요.

그 IP 주소는 다음과 같이 Ingress 객체를 describe해 얻을 수 있어요:

kubectl -n argocd describe ingresses argocd | grep Address

DNS 변경이 전파되면 Google Cloud Load Balancer로 Argo를 사용할 준비가 된 거예요

여러 계층의 인증 리버스 프록시를 통한 인증 (Authenticating through multiple layers of authenticating reverse proxies)

Argo CD 엔드포인트는 하나 이상의 리버스 프록시 계층으로 보호될 수 있어요. 이 경우 argocd CLI의 --header 파라미터로 추가 헤더를 제공해 그 계층들을 통해 인증할 수 있어요.

$ argocd login <host>:<port> --header 'x-token1:foo' --header 'x-token2:bar' # can be repeated multiple times
$ argocd login <host>:<port> --header 'x-token1:foo,x-token2:bar' # headers can also be comma separated

Argo CD 서버와 UI 루트 경로 (Argo CD server and UI root path) (v1.5.3)

Argo CD 서버와 UI는 비-루트 경로(예: /argo-cd)에서 사용할 수 있도록 구성할 수 있어요. 이렇게 하려면 argocd-server deployment 명령에 --rootpath 플래그를 추가하세요:

spec:
  template:
    spec:
      name: argocd-server
      containers:
      - command:
        - /argocd-server
        - --repo-server
        - argocd-repo-server:8081
        - --rootpath
        - /argo-cd

참고: --rootpath 플래그는 API 서버와 UI base URL을 모두 변경해요. nginx.conf 예시:

worker_processes 1;

events { worker_connections 1024; }

http {

    sendfile on;

    server {
        listen 443;

        location /argo-cd/ {
            proxy_pass         https://localhost:8080/argo-cd/;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            # buffering should be disabled for api/v1/stream/applications to support chunked response
            proxy_buffering off;
        }
    }
}

--grpc-web-root-path 플래그는 비-루트 경로(예: /argo-cd)를 제공하는 데 사용돼요

$ argocd login <host>:<port> --grpc-web-root-path /argo-cd

UI 기본 경로 (UI Base Path)

Argo CD UI가 비-루트 경로(예: / 대신 /argo-cd)에서 사용 가능하다면 UI 경로를 API 서버에 구성해야 해요. UI 경로를 구성하려면 argocd-server deployment 명령에 --basehref 플래그를 추가하세요:

spec:
  template:
    spec:
      name: argocd-server
      containers:
      - command:
        - /argocd-server
        - --repo-server
        - argocd-repo-server:8081
        - --basehref
        - /argo-cd

참고: --basehref 플래그는 UI base URL만 변경해요. API 서버는 계속 / 경로를 사용하므로 프록시 config에 URL 재작성 규칙을 추가해야 해요. URL 재작성이 있는 nginx.conf 예시:

worker_processes 1;

events { worker_connections 1024; }

http {

    sendfile on;

    server {
        listen 443;

        location /argo-cd {
            rewrite /argo-cd/(.*) /$1  break;
            proxy_pass         https://localhost:8080;
            proxy_redirect     off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            # buffering should be disabled for api/v1/stream/applications to support chunked response
            proxy_buffering off;
        }
    }
}

Gateway API 예시 (Gateway API Example)

이 섹션은 Gateway API를 사용해 다양한 TLS 구성에서 Argo CD 서버를 노출하는 방법을 다루며, HTTP와 gRPC 트래픽을 모두 수용하고 가능하면 HTTP/2를 사용해요.

Gateway에서 TLS 종료 (TLS termination at the Gateway)

같은 네임스페이스의 Secret에 저장된 인증서로 TLS 연결을 종료하는 다음 클러스터 전역 Gateway 리소스를 가정하세요:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: cluster-gateway
  namespace: gateway
spec:
  gatewayClassName: example
  listeners:
    - protocol: HTTPS
      port: 443
      name: https
      hostname: "*.local.example.com"
      allowedRoutes:
        namespaces:
          from: All
      tls:
        mode: Terminate
        certificateRefs:
          - name: cluster-gateway-tls
            kind: Secret
            group: ""

인증서 관리를 자동화하기 위해 cert-managergateway 어노테이션을 지원해요.

Argo CD와 gateway 사이의 트래픽 보안 (Securing traffic between Argo CD and the gateway)

보안 요구사항이 허용한다면 Argo CD API 서버는 TLS 비활성화 상태로 실행할 수 있어요: argocd-server 명령에 --insecure 플래그를 전달하거나, 여기에 설명된 대로 argocd-cmd-params-cm ConfigMap에 server.insecure: "true"를 설정하세요.

BackendTLSPolicy를 사용해 TLS를 유지하고 gateway와 Argo CD API 서버 사이의 트래픽을 암호화하는 것도 가능해요. 자세한 내용은 Upstream TLS 문서를 참고하세요.

apiVersion: gateway.networking.k8s.io/v1
kind: BackendTLSPolicy
metadata:
  name: tls-upstream-auth
  namespace: argocd
spec:
  targetRefs:
    - kind: Service
      name: argocd-server
      group: ""
  validation:
    caCertificateRefs:
      - kind: ConfigMap
        name: argocd-server-ca-cert
        group: ""
    hostname: argocd-server.argocd.svc.cluster.local

HTTP 요청 라우팅 (Routing HTTP requests)

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: argocd-http-route
  namespace: argocd
spec:
  parentRefs:
    - name: cluster-gateway
      namespace: gateway
      sectionName: https
  hostnames:
    - "argocd.local.example.com"
  rules:
    - backendRefs:
        - name: argocd-server
          port: 80
      matches:
        - path:
            type: PathPrefix
            value: /

gRPC 요청 라우팅 (Routing gRPC requests)

argocd CLI는 HTTP/2 위의 gRPC로 API 서버와 통신할 때 전체 기능으로 동작하며, HTTP/1.1로 폴백해요. (--grpc-web 플래그).

gRPC는 GRPCRoute를 사용해 구성할 수 있고, argocd-server 서비스에서 애플리케이션 프로토콜로 HTTP/2를 요청할 수 있어요:

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: argocd-grpc-route
  namespace: argocd
spec:
  parentRefs:
    - name: cluster-gateway
      namespace: gateway
      sectionName: https
  hostnames:
    - "grpc.argocd.local.example.com"
  rules:
    - backendRefs:
        - name: argocd-server
          port: 443

그리고 Argo CD의 values.yaml(또는 직접 서비스 매니페스트)에서:

server:
  service:
    # Enable gRPC over HTTP/2
    servicePortHttpsAppProtocol: kubernetes.io/h2c
같은 도메인으로 gRPC와 HTTP 라우팅 (Routing gRPC and HTTP through the same domain)

공식적으로는 권장되지 않지만, HTTPRouteGRPCRoute를 같은 도메인에 연결하는 것은 일부 구현에서 지원될 수 있어요. 아래와 같이 대상의 모호함을 없애기 위해 요청 헤더 매칭이 필요해집니다:

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: argocd-grpc-route
  namespace: argocd
spec:
  parentRefs:
    - name: cluster-gateway
      namespace: gateway
  hostnames:
    - "grpc.argocd.local.example.com"
  rules:
    - backendRefs:
        - name: argocd-server
          port: 443
      matches:
        - headers:
            - name: Content-Type
              type: RegularExpression
              value: "^application/grpc.*$"

TLS passthrough

TLS는 Argo CD API 서버에서 종료되도록 구성할 수도 있어요.

이렇게 하려면 Experimental Gateway API CRD의 일부인 TLSRoute를 gateway에 연결해야 해요.

kind: Gateway
metadata:
  name: cluster-gateway
  namespace: gateway
spec:
  gatewayClassName: example
  listeners:
  - name: tls
    port: 443
    protocol: TLS
    hostname: "argocd.example.com"
    allowedRoutes:
      namespaces:
        from: All
      kinds:
        - kind: TLSRoute
    tls:
      mode: Passthrough
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  namespace: argocd
  name: argocd-server-tlsroute
spec:
  parentRefs:
  - name: cluster-gateway
    namespace: gateway
    sectionName: tls
  hostnames:
  - argocd.example.com
  rules:
  - backendRefs:
    - name: argocd-server
      port: 443

TLS 인증서는 여기에서 암시적이며, Argo CD 서버가 argocd-server-tls secret에서 찾아요.

cert-manager는 passthrough gateway 리스너에 대한 인증서 생성을 지원하지 않는다는 점을 참고하세요.

더 알아보기 (Learn more)