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

Traefik Kubernetes Gateway

원문 보기 위키 갱신

출처: Traefik Kubernetes Gateway

본문

Traefik & Kubernetes with Gateway API

Kubernetes Gateway API 프로바이더를 사용하면 Traefik은 Gateway API Custom Resource Definitions(CRD)를 활용해 라우팅 구성을 얻어요. Gateway API 개념과 리소스에 대한 자세한 내용은 공식 문서를 참고하세요.

Kubernetes Gateway API 프로바이더는 사양의 v1.6.2 버전을 지원해요.

Standard 채널의 HTTPRoute 코어 기능 전부와 BackendTLSPolicy, GRPCRoute, TLSRoute 같은 일부 확장 기능, 그리고 Experimental 채널의 TCPRoute 를 완전히 지원해요.

자세한 내용은 적합성(conformance) 보고서를 확인하세요.

Gateway 배포하기

Gateway 는 Gateway API 사양의 핵심 리소스로, Kubernetes 클러스터로 들어오는 트래픽의 진입점을 정의해요. 이는 트래픽을 관리·처리하는 컨트롤러를 지정하는 GatewayClass 와 연결되어, 트래픽이 적절한 Kubernetes 백엔드 서비스로 전달되도록 보장해요.

GatewayClass 는 보통 인프라 프로바이더가 정의하는 클러스터 범위(cluster-scoped) 리소스예요. 다음 GatewayClass 는 여기에 연결된 게이트웨이가 Traefik 컨트롤러가 관리해야 함을 정의해요.

GatewayClass

---
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: traefik
spec:
  controllerName: traefik.io/gateway-controller

다음 Gateway 매니페스트는 실행 중인 Traefik 컨트롤러가 들어오는 트래픽을 처리하도록 구성해요.

리스너 포트

Gateway 리스너 포트는 Traefik 배포의 구성된 엔트리 포인트 포트와 일치해야 한다는 점에 유의하세요. 일치하지 않으면 ERROR 메시지가 기록되고 리소스 상태가 그에 따라 업데이트돼요.

Gateway

---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: traefik
  namespace: default
spec:
  gatewayClassName: traefik

  # Only Routes from the same namespace are allowed.
  listeners:
    - name: http
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: Same 

    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: secret-tls
            namespace: default

      allowedRoutes:
        namespaces:
          from: Same

    - name: tcp
      protocol: TCP
      port: 3000
      allowedRoutes:
        namespaces:
          from: Same

    - name: tls
      protocol: TLS
      port: 3443
      tls:
        mode: Terminate
        certificateRefs:
          - name: secret-tls
            namespace: default

      allowedRoutes:
        namespaces:
          from: Same

Secret

---
apiVersion: v1
kind: Secret
metadata:
  name: secret-tls
  namespace: default
type: kubernetes.io/tls
data:
  # Self-signed certificate for the whoami.localhost domain.
  tls.crt: |
    LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUZWakNDQXo2Z0F3SUJBZ0lVZUUrZG94aTUrMTBMVi9DaUdTMkt2Q1dJR1dZd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1JERUxNQWtHQTFVRUJoTUNSbEl4RFRBTEJnTlZCQWNNQkV4NWIyNHhGVEFUQmdOVkJBb01ERlJ5WVdWbQphV3NnVEdGaWN6RVBNQTBHQTFVRUF3d0dWMmh2WVcxcE1DQVhEVEkwTURjeE1ERTFNRGt3TjFvWUR6SXhNalF3Ck5qRTJNVFV3T1RBM1dqQkVNUXN3Q1FZRFZRUUdFd0pHVWpFTk1Bc0dBMVVFQnd3RVRIbHZiakVWTUJNR0ExVUUKQ2d3TVZISmhaV1pwYXlCTVlXSnpNUTh3RFFZRFZRUUREQVpYYUc5aGJXa3dnZ0lpTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRJQ0R3QXdnZ0lLQW9JQ0FRQ1pNNm1WNUJkV2V0QzZtdnp0YVBobFNjZ0ljbnd6Z3NsOEFxendEMk05ClJWVkZwRUxBbTh2OTNlRWtMZEY2ZnNkY0FhUXQxWlFDSFdYby9mTHBRNVVrUHh1djZNUCt2NG1KMHY4ZEtGWjcKUjcwaTVud1lCMkVlVkw2RUNZaWlxNmZ6VEtsa3F6U0QvNW93elN3L3pqa0dUYTBJdy92SDlhc0g3NEhqM1d0QQo3RythenZjaVlhQTZxK1dWYlZxNlBIanF6em9obEFuMkh1ano2aERqYWllc3ZMbHdBL0IvcmhEc0FLaCtpMHI4CkFKUTFqM0JiTGJuYkJyWmZqYnBJUjNhYVh5amkwK3RQWENnVTkzQmU5dm1LZTZTY0dSNy82T25tYmtTc0xjZFcKaFpVNzcrL2c4WllsZGhwS01nczc4ekJYUlh4bHlzSThHRUtqU1hud3k5WmZNT2RJNEpBTWNtT0lOaVlBY21abgpJTUJIa0xacFl3aUl0eFdseXVJcWxoZFpkSHNrTFdNSjBSTHUxRmhTMnBFV0NOZTM3VDBiOWhtNFg0OXJ1QWJ6Ckl1M01xSmczcXFIdGRMNGRkZ1JZRHNjMXd0cDJrR2dBZGxDaXJIclF6K1l4MEJNT1ZsZEczaG1SUUh5ZHEySHIKWW0xeEFDNWpMZ3FvaVZhY09wd0xKY21PcGsrZWVNQkNZNVo0ekNYN1hXeXdhVmNtMnN2aGlPMThCZFIraDloWQpiMkRNZDFCendDbE95endQcUlvQy9uNGRURG96Ry9GT3NySzgvNEZ4dzY2Q1ZmM3E4MzBNUHdSd2xDSzFDQjdGCjNQK3lKWkpPelRuK05QZ2dGQW9NaGZUYXBQWTFhUGlWajBzVG9vQjBaOGNFV1RkTnJxQU5tUGs5aDNoQjJwbjgKSndJREFRQUJvejR3UERBYkJnTlZIUkVFRkRBU2doQjNhRzloYldrdWJHOWpZV3hvYjNOME1CMEdBMVVkRGdRVwpCQlNGSjF4N01xdG9zQ3UwQmFWbEs1U054K2djampBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQWdFQVdCOVc1eWkzClRpTWpmSThhSCtMZW1wZjc4clhyeWJ6UXJvSXdEazhqQXhnc3Nrc2V2ZEtIaXJIZGJMZ0RoS2krbkJLeEQ5S2QKNWM4RS9VL1VHWUhxaUowTVUzYkpoeTVNM3oyaklKd1hFa3FuVVhRd0dBNzVyU0QxWVBkOTlWeVpuNEJVRlEwdwpCT3loOU5DS3Z3ZTgycUVlOWZmeU5iem5JUEMrNS9pekhaYlNQMEpwRzdtNFQ5TXljdHV1OTlsaVhmSVlCMU1PCkRFRUdpamxhZ3JvdTliVlpsNmovR2xCaVZpU0JVQXhaRlNqdFErV2RFODJaZlFRUFVWdXQrUEY0SEl0N1dmYlgKaUpZbjRsMytJSVczNStvbUZ5QjR5WUJNdU9SVWRsZ3V5N1ZieEU5OTdPdHYzTnpDOGJYcGtaQVM0TkVzQVVFdwpJZ3lOcTFCdExsb3dZdjZXY05HbkJ5RE1NRUMzdUYzNEcxQkJCTzFDRHUrYXBVdW5NbVhUWmU5WlkrbXh4U2Z2CnBZclhHTHBoT2t4ZitQalpMbEpqQVFlcTNxblMvWWtLQmtYQi9zb282ZVVLTTlybyt5RTVMbnFrV20wZXpQWmwKc2Z5NGpqZ0lJUHlUMHhhZ0YyWExzUSs0M3N4aDRYTEhmc3Z3Zis2QnJVK2trTnoydmc2M3duLzJDQUNVVms3bgphSDdwZzZyZGt4T2pOTDJjUGd6ZzhWaExXbkVYYjhhUVJlVjY1WnlRc0xta21oOXBlSFRpYXBUb2xWa0d6TDIwCm9pdExZc3ZUcnhUR2NRd3Jpd3FaT1I3WjEvVEJLVnVoYnp0emxlRjFHRk9LdE52UmNSREVBeWVlbnJDRzRRMmgKMnFNNFh1RFFKcjJrR095OEV0dnlYTitENkNZUkg0ck5vZUk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K

  tls.key: |
    LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRQ1pNNm1WNUJkV2V0QzYKbXZ6dGFQaGxTY2dJY253emdzbDhBcXp3RDJNOVJWVkZwRUxBbTh2OTNlRWtMZEY2ZnNkY0FhUXQxWlFDSFdYbwovZkxwUTVVa1B4dXY2TVArdjRtSjB2OGRLRlo3UjcwaTVud1lCMkVlVkw2RUNZaWlxNmZ6VEtsa3F6U0QvNW93CnpTdy96amtHVGEwSXcvdkg5YXNINzRIajNXdEE3RythenZjaVlhQTZxK1dWYlZxNlBIanF6em9obEFuMkh1anoKNmhEamFpZXN2TGx3QS9CL3JoRHNBS2graTByOEFKUTFqM0JiTGJuYkJyWmZqYnBJUjNhYVh5amkwK3RQWENnVQo5M0JlOXZtS2U2U2NHUjcvNk9ubWJrU3NMY2RXaFpVNzcrL2c4WllsZGhwS01nczc4ekJYUlh4bHlzSThHRUtqClNYbnd5OVpmTU9kSTRKQU1jbU9JTmlZQWNtWm5JTUJIa0xacFl3aUl0eFdseXVJcWxoZFpkSHNrTFdNSjBSTHUKMUZoUzJwRVdDTmUzN1QwYjlobTRYNDlydUFiekl1M01xSmczcXFIdGRMNGRkZ1JZRHNjMXd0cDJrR2dBZGxDaQpySHJReitZeDBCTU9WbGRHM2htUlFIeWRxMkhyWW0xeEFDNWpMZ3FvaVZhY09wd0xKY21PcGsrZWVNQkNZNVo0CnpDWDdYV3l3YVZjbTJzdmhpTzE4QmRSK2g5aFliMkRNZDFCendDbE95endQcUlvQy9uNGRURG96Ry9GT3NySzgKLzRGeHc2NkNWZjNxODMwTVB3UndsQ0sxQ0I3RjNQK3lKWkpPelRuK05QZ2dGQW9NaGZUYXBQWTFhUGlWajBzVApvb0IwWjhjRVdUZE5ycUFObVBrOWgzaEIycG44SndJREFRQUJBb0lDQUVCa2dKRXA3ODAvamVBQktQSTR2cjhFCkJmblc5UEZKdFpwVUhaQkJSM3NIVzFJTU9xcHVVWTJBNXhLbjEzWmZOemdxMEhFYlpqeUZVc0pkaXU0VW8razYKUlU3b3pRaVVSU0VTK0h1dTZycWlhcEx5d1pIditCZ2hrbm80NzU4Lyt6VytNU3pJOFNmU0ZXTVJ1ZG1QdWxRMQo3ZGJUV1U2d3FaU0tUTlFUeXZMYzdnUHBuZUpybWtkTzNRNnppZ0RoVGdtVDFHRXNzZ3NxN3NzbXhMWnhkZithCnkyNlRtVkJ4UDFlUzV6OVpHTWxYRFBSK044RjdOTFVrMng3S21WT3NCZVBZdjN5bmlpNHZGQUhNQndWRFZadXAKWUlUajRpMjZIaVhtanlLM2t5T0F2anNWSElRMXh1QTBCZFROdC84WXRtYllJL005QitydVg0UDJiRFNUMktRKwo4TlN2Uk9wbVppcnBHZkY3bExMSGpJUjlTMFhCWDd6VDRoWnBRWnpqK3NEWnhDM2Y3TGIwRFlKYkp0TmlDYTQxCmNpTjhNUlNldzNneHZ0RVk0RzdnN3hjbkJNdjdNT3RwQTE3d2gvMHdLd0h0amYzSWh2TmIzdkZwT0k5d1FqSzYKSlRQMng4bENJV0tyalpObVN0UksreHJTN3hTOUZVdnBhSVlyclRLQkZWSmcyMURCYWI1L3hqRlBlQWxXejczSwpvVkhsa0hLdXNMSjZLczZzcXo0ZG9mbzg3dkFsUFJzTXRkZ1ZnZFIzNXhLTGtEWXNIbGxML3Z5dE9oSkNieXB5CkJqQm1TR0RMdzBDdWplaHVtU2czYjdSUGVTNk5rbHNqUEIrMVpzRjhpVGdCcjMyM1hvTmNha2dhWWVYQlg4NFAKaE1WZHUxWk1rbXJZMWhXTzEydnhBb0lCQVFEWU5Vb2xCMkhsdWlDcVFqdmU4UFNhV0YxRmhwNUlOMGJIZEppeApIdkhqMkplVHJ6V1pUZFlIdFNJR2RzalhTOTBESXo2bXJhMW9YZXFRYlgrODVlOUFQQkZnRTJmNU5uTzBCSVVJCk5hMXRiVGpIOUhjRGRzQmJKUkZwYnk1ODZUb3lhdFY3bS9zcjVpQUZlZFMyenFOTm1XUmZOdllZS2xselZoSEUKdUd4ZjZxMHJTWktVQUhja2s1bU5Yais3WFhZaTgyemErVEE3ZjBDVm5OamR3OXFpd3B2aTJKTFB2SnA0bWt6KwpyMEN1RW9yV2NhMUdTL2hTVWdXemw3NzhQdlRpZFI2RW4zMDB2ZlIyTE84aG1xRjhVL3Bpb2UrTDVjSllRNnNKCk1YMngrYThzWFFpZ3dwdG02aUNxQ2FuS3ExN3NUZS9RTmQ1czdwb3ZOaHVKOHd3dEFvSUJBUUMxWmM5ZktPUFgKVzZSN1VoaHRRcmhIc3htQnRIQ1BuNWRLbjN5MElNNWRBaEFSdFZDV1U0M0hOTHpCNW1LbjU2dnZrSVNFaXdBbAoxTGhuY2I3YXQ2cHpTSlZtMm5oTDhjeUZrdGQrNzVyL1FHNFlpNnZQbHNBODV5ZXZpZDhZcWswaHdaZXExY05xCmxETUN3NWsrV0drckM2VW5jZXNIc2FWbDJTUGdZV1c1L3I1NnVxUnBsaVFka1EyZmlEYWRyblVueU8ycHg3bFMKVG1HemZaNmtzTWh2MlZFR1NPRm05aUo0dWlPb0xyZVhoU1RQRmxTdjdZUTZSWWtSaGgwT0tqdXM5bXZacEIxWApjcytYN0UyVTNlM0RZelpCR0NFdmxxaFNWTFRScjdIN21pMWxUMEozR0RzbDdiUk9xOE50WVdQa3hhSlNCUnQ5Ck9TcTlkTm9CcGRvakFvSUJBQ2lQdnN3NW1WVW0yUS80QXhGdE5RWnJ3M3ZTcUlrMXpaS0h2a21rVzQ3NlNGMk4KaGttdmY1TE1tWWlLNmx6eHY1SGlIOVBYUzJ3RUNvaHo4bjMyeVM3TTFobW5LbDlucHNkRC9jMHZmTXpGcTl4ZgpjYUIxdTlxZGxxbW9FUm1nQzZuL3Z2TkVyUmRzUWQrbEhwSDVMRXZYbGl3Q3ZLS0Y5MmdhNHBSOFlPQ1J2MUVhCnFXUVl2a0ZmYTNSSkZUM0taK3BncnJCYUJZRnoreUxXWFIwbHJEUFN2TG9QRldQaHB6MHUvWGplV2cwT0wzdlIKc2NjNVkybldOM21jNDFpaFd3SE5KUitPYUVmbnh5QVFpQUJPNlRMUThtMWtvZk1sOUpMb2h3TGZoUXhKb21KNQpSYkFiTWxwWlhDMXFTSzliL1IvcDh5NmxuSWZsTDRuaDVjSzRsVFVDZ2dFQUpSSHVSQU1tTksrTXVJcjVaUEs2Cm1DUjR0UEg4QXMzWmJDMlZuWFlLMWlVQ3hhdXBFVjkzM05yaExEcjV0Rmg2NFpWR0Q1UWNicDYvSkp5eEpSOWQKblB1YlZJNlhBT1lrSnJQd2lBZE5SSmFWS1R6NTJvMXpNYjhIZEM4WHdZR2tDNTcxY0xzSW1YSTV6bm5NaWxvaworK0FBVzBSRGhLb0FKQVV3K0x6T3ZpamFJbGljR3R2TSs2SFdCK0VkVURJRHpTS1p0eFdTd01nMTNTbHh6elExCmNlNFdTZE9CQkxxT0p0L2JRNVp3ZkcyQUxUWGlEcVhhWE5JekJickRtMDUwTFkrYVVMcmlLQ25WVkxXODBReGQKZDQyQjIrR2pmb2NxVk5Ec3R1RlIzUm9QNXVGQXN2Zm50b09TVW5WMWxaZk9nMFVFUEFEQk1tRUpZL2hLU1FYcwp3d0tDQVFBNWQya2hFQ1c1V3QrMzRYWnl1b3NFTjZ4UDExbC96VDRBZjhGSWtQLzlkb0JXRnBhc28zbG1NcXZHCmhPeFErbnZBSjFhNzhZRjA4N3p1UC9DZkQ0UElOUTV4YzZHMDNQdG5JOVNVT0dpMDB4Zlg5MU5NMHBHYWJqb0QKZ0RqVzJxSkJDaVB5N0RIR1RlZkU5eUNUbkhrY1NBbWllVGc3aGFyeEZPOUREZTJKbzhKQXV2SHI1aGVxazVIcgpLYlgzTy9vNUMwcWVnYW1rWVRLcHZzV2VFdXhkY2l5LzFQd3NnV3BuV1JPWllQNENrSkJweEx1bDNVamVSY3dkCnRhcjBJYU52WlV2NFd4U0JZdWVHMDFyYUd2SDZtTTcyTEExR3MrMytwTnZwUVo3bGo2S09tcFlhQUlhemVxY2MKTjJjT2R5U1RqZmQ5OFlNVFAxbmIyK3N1Yy91VAotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==

여러 TLS 인증서

Traefik은 Gateway 리스너당 여러 개의 secret certificateRefs 를 지원해요. 인증서 중 하나가 유효하지 않거나 로드할 수 없으면 리스너가 유효하지 않은 것으로 간주되어 문제가 해결될 때까지 트래픽을 서비스하지 못해요.

예를 들어 다음 Gateway 리스너는 서로 다른 두 인증서를 참조해요:

---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: multi-cert-gateway
  namespace: default
spec:
  gatewayClassName: traefik
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: example-com-tls
          - name: example-org-tls
      allowedRoutes:
        namespaces:
          from: Same

Route 노출하기

Gateway 가 배포되면(Gateway 배포하기 참고) 일부 트래픽을 Kubernetes 백엔드 서비스로 전달하기 위해 HTTPRoute, TCPRoute, 또는 TLSRoute 리소스를 배포해야 해요.

Gateway에 연결하기

다음 예시에서 보듯 Route 리소스는 연결되어야 할 상위 Gateway 를 참조하는 ParentRefs 로 구성해야 해요.

HTTP/HTTPS

HTTPRoute 는 Gateway API 사양의 핵심 리소스로, Kubernetes 클러스터 내에서 HTTP 트래픽을 어떻게 라우팅할지 정의하도록 설계되었어요. HTTP 요청을 적절한 Kubernetes 백엔드 서비스로 안내하는 라우팅 규칙을 지정할 수 있게 해줘요.

리소스와 개념에 대한 자세한 내용은 Kubernetes Gateway API 문서를 확인하세요.

예를 들어 다음 매니페스트는 whoami 백엔드와 그에 해당하는 HTTPRoute 를 구성해요. 배포된 Gateway 를 통해 http://whoami.localhost 주소로 접근할 수 있어요.

HTTPRoute

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
     - matches:
        - path:
            type: PathPrefix
            value: /

       backendRefs:
        - name: whoami
          namespace: default
          port: 80

Whoami 배포

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoami

  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    app: whoami

  ports:
    - port: 80

연결을 HTTPS로 보호하고 보안이 없는 요청을 보안 엔드포인트로 리다이렉트하기 위해, RequestRedirect 필터를 추가하도록 위 HTTPRoute 매니페스트를 업데이트하고, https Listener 에 바인딩되어 트래픽을 whoami 백엔드로 전달하는 새 HTTPRoute 를 추가할 거예요.

HTTPRoute (HTTP)

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - filters:
        - type: RequestRedirect
          requestRedirect:
            scheme: https

HTTPRoute (HTTPS)

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-https
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: https
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /

      backendRefs:
        - name: whoami
          namespace: default
          port: 80

모든 것이 배포되면 HTTP 및 HTTPS 엔드포인트에 GET 요청을 보냈을 때 다음 응답을 받을 수 있어요:

응답

$ curl -I http://whoami.localhost

HTTP/1.1 302 Found
Location: https://whoami.localhost/
Date: Thu, 11 Jul 2024 15:11:31 GMT
Content-Length: 5

$ curl -k https://whoami.localhost

Hostname: whoami-697f8c6cbc-2krl7
IP: 127.0.0.1
IP: ::1
IP: 10.42.1.5
IP: fe80::60ed:22ff:fe10:3ced
RemoteAddr: 10.42.2.4:44682
GET / HTTP/1.1
Host: whoami.localhost
User-Agent: curl/7.87.1-DEV
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.1.0
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: traefik-6b66d45748-ns8mt
X-Real-Ip: 10.42.1.0

HTTPRoute 필터로 Traefik 미들웨어 사용하기

HTTP 필터는 요청과 응답이 라우팅 인프라를 통과할 때 이를 수정할 수 있게 하는 HTTPRoute 구성 요소예요.

필터에는 세 가지 유형이 있어요:

  • Core: RequestHeaderModifier 와 RequestRedirect 같은 모든 Gateway 컨트롤러에 필수인 필터예요.

  • Extended: ResponseHeaderModifier 나 RequestMirror 처럼 일부 Gateway 컨트롤러에서만 제공하는 선택적 필터예요.

  • ExtensionRef: Gateway 컨트롤러가 제공하는 추가 필터예요. Traefik에서는 Middleware CRD를 통해 지원되는 HTTP 미들웨어들이 여기에 해당해요.

ExtensionRef 필터

Traefik 미들웨어를 ExtensionRef 필터로 사용하려면 문서에 설명된 대로 정적 구성에서 Kubernetes CRD 프로바이더를 활성화해야 해요.

예를 들어 다음 매니페스트는 Traefik AddPrefix 미들웨어를 사용하는 HTTPRoute 를 구성해요. 배포된 Gateway 를 통해 http://whoami.localhost 주소로 접근할 수 있어요:

HTTRoute

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - backendRefs:
        - name: whoami
          namespace: default
          port: 80

      filters:
        - type: ExtensionRef
          extensionRef:
            group: traefik.io
            kind: Middleware
            name: add-prefix

AddPrefix 미들웨어

---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: add-prefix
  namespace: default
spec:
  addPrefix:
    prefix: /prefix

Whoami 배포

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoami

  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: traefik/whoami

---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    app: whoami
  ports:
    - port: 80

Once everything is deployed, sending a GET request should return the following response:

응답

$ curl http://whoami.localhost

Hostname: whoami-697f8c6cbc-kw954
IP: 127.0.0.1
IP: ::1
IP: 10.42.2.6
IP: fe80::a460:ecff:feb6:3a56
RemoteAddr: 10.42.2.4:54758
GET /prefix/ HTTP/1.1
Host: whoami.localhost
User-Agent: curl/7.87.1-DEV
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.2.1
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-6b66d45748-ns8mt
X-Real-Ip: 10.42.2.1

백엔드 레벨 필터

경로 레벨 필터 외에도 Gateway API는 backendRefs[].filters 필드를 통해 개별 백엔드에 직접 필터를 적용하는 것도 지원해요. 이를 통해 특정 백엔드에 요청 수정을 적용할 수 있어 HTTPRouteBackendRequestHeaderModification 확장 기능을 사용할 수 있어요.

지원되는 필터 유형

백엔드 레벨 필터는 경로 레벨 필터와 동일한 필터 유형을 지원해요:

  • RequestHeaderModifier: 백엔드로 전달하기 전에 HTTP 요청 헤더를 추가, 설정, 제거해요.

  • 응답HeaderModifier: Add, set, or remove HTTP response headers.

  • RequestRedirect: 요청을 다른 URL로 리다이렉트해요.

  • URLRewrite: 요청 URL 경로 및/또는 호스트 이름을 다시 작성해요.

  • ExtensionRef: Traefik Middleware 리소스를 참조해요.

미들웨어 실행 순서

경로 레벨과 백엔드 레벨 필터가 모두 구성되면 경로 레벨 필터가 먼저 적용되고 그 다음 백엔드 레벨 필터가 적용돼요.

서비스 레벨 미들웨어에 대한 자세한 내용은 서비스 미들웨어를 참고하세요.

백엔드에서 RequestHeaderModifier 사용하기

HTTPRoute

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /

      backendRefs:
        - name: whoami
          namespace: default
          port: 80
          filters:
            - type: RequestHeaderModifier
              requestHeaderModifier:
                set:
                  - name: X-Backend-Header
                    value: "backend-filter"

백엔드에서 ExtensionRef (Traefik 미들웨어) 사용하기

HTTPRoute

---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami-http
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - backendRefs:
        - name: whoami
          namespace: default
          port: 80
          filters:
            - type: ExtensionRef
              extensionRef:
                group: traefik.io
                kind: Middleware
                name: add-prefix

AddPrefix 미들웨어

---
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: add-prefix
  namespace: default
spec:
  addPrefix:
    prefix: /api

GRPC

GRPCRoute 는 Gateway API 사양의 확장 리소스로, Kubernetes 클러스터 내에서 GRPC 트래픽을 어떻게 라우팅할지 정의하도록 설계되었어요. GRPC 요청을 적절한 Kubernetes 백엔드 서비스로 안내하는 라우팅 규칙을 지정할 수 있게 해줘요.

리소스와 개념에 대한 자세한 내용은 Kubernetes Gateway API 문서를 확인하세요.

예를 들어 다음 매니페스트는 echo 백엔드와 그에 해당하는 GRPCRoute 를 구성해요. 배포된 Gateway 를 통해 echo.localhost:80 주소로 접근할 수 있어요.

GRPCRoute

---
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: echo
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: http
      kind: Gateway

  hostnames:
    - echo.localhost

  rules:
    - matches:
        - method:
            type: Exact
            service: grpc.reflection.v1alpha.ServerReflection

        - method:
            type: Exact
            service: gateway_api_conformance.echo_basic.grpcecho.GrpcEcho
            method: Echo

      backendRefs:
        - name: echo
          namespace: default
          port: 3000

Echo 배포

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echo
  namespace: default
spec:
  selector:
    matchLabels:
      app: echo

  template:
    metadata:
      labels:
        app: echo
    spec:
      containers:
        - name: echo-basic
          image: gcr.io/k8s-staging-gateway-api/echo-basic
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
            - name: GRPC_ECHO_SERVER
              value: "1"

---
apiVersion: v1
kind: Service
metadata:
  name: echo
  namespace: default
spec:
  selector:
    app: echo

  ports:
    - port: 3000

Once everything is deployed, sending a GRPC request to the HTTP endpoint should return the following response:

응답

$ grpcurl -plaintext echo.localhost:80 gateway_api_conformance.echo_basic.grpcecho.GrpcEcho/Echo

{
  "assertions": {
    "fullyQualifiedMethod": "/gateway_api_conformance.echo_basic.grpcecho.GrpcEcho/Echo",
    "headers": [
      {
        "key": "x-real-ip",
        "value": "10.42.2.0"
      },
      {
        "key": "x-forwarded-server",
        "value": "traefik-74b4cf85d8-nkqqf"
      },
      {
        "key": "x-forwarded-port",
        "value": "80"
      },
      {
        "key": "x-forwarded-for",
        "value": "10.42.2.0"
      },
      {
        "key": "grpc-accept-encoding",
        "value": "gzip"
      },
      {
        "key": "user-agent",
        "value": "grpcurl/1.9.1 grpc-go/1.61.0"
      },
      {
        "key": "content-type",
        "value": "application/grpc"
      },
      {
        "key": "x-forwarded-host",
        "value": "echo.localhost:80"
      },
      {
        "key": ":authority",
        "value": "echo.localhost:80"
      },
      {
        "key": "accept-encoding",
        "value": "gzip"
      },
      {
        "key": "x-forwarded-proto",
        "value": "http"
      }
    ],
    "authority": "echo.localhost:80",
    "context": {
      "namespace": "default",
      "pod": "echo-78f76675cf-9k7rf"
    }
  }
}

TCP

Experimental 채널

아래에서 설명하는 TCPRoute 리소스는 현재 Gateway API 사양의 Experimental 채널에서만 사용할 수 있어요. 이 리소스를 사용하려면 Traefik 배포에서 experimentalChannel 구성 옵션을 활성화해야 해요.

TCPRoute 는 Gateway API 사양의 리소스로, Kubernetes 클러스터 내에서 TCP 트래픽을 어떻게 라우팅할지 정의하도록 설계되었어요.

리소스와 개념에 대한 자세한 내용은 Kubernetes Gateway API 문서를 확인하세요.

For example, the following manifests configure a whoami backend and its corresponding TCPRoute, reachable through the deployed Gateway at the localhost:3000 address.

TCPRoute

---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: whoami-tcp
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: tcp
      kind: Gateway

  rules:
     - backendRefs:
        - name: whoamitcp
          namespace: default
          port: 3000

Whoami 배포

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoamitcp

  template:
    metadata:
      labels:
        app: whoamitcp
    spec:
      containers:
        - name: whoami
          image: traefik/whoamitcp
          args:
            - --port=:3000

---
apiVersion: v1
kind: Service
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    app: whoamitcp
  ports:
    - port: 3000

Once everything is deployed, sending the WHO command should return the following response:

응답

$ nc localhost 3000

WHO
Hostname: whoamitcp-85d644bfc-ktzv4
IP: 127.0.0.1
IP: ::1
IP: 10.42.1.4
IP: fe80::b89e:85ff:fec2:7d21

TLS

TLSRoute 는 Gateway API 사양의 리소스로, Kubernetes 클러스터 내에서 TLS(Transport Layer Security) 트래픽을 어떻게 라우팅할지 정의하도록 설계되었어요. 들어오는 연결의 SNI(Server Name Indication)를 기반으로 TLS 연결을 적절한 백엔드 서비스로 안내하는 라우팅 규칙을 지정해요.

리소스와 개념에 대한 자세한 내용은 Kubernetes Gateway API 문서를 확인하세요.

For example, the following manifests configure a whoami backend and its corresponding TLSRoute, reachable through the deployed Gateway at the localhost:3443 address via a secure connection with the whoami.localhost SNI.

TLSRoute

---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
  name: whoami-tls
  namespace: default
spec:
  parentRefs:
    - name: traefik
      sectionName: tls
      kind: Gateway

  hostnames:
    - whoami.localhost

  rules:
    - backendRefs:
        - name: whoamitcp
          namespace: default
          port: 3000

Whoami 배포

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    matchLabels:
      app: whoamitcp

  template:
    metadata:
      labels:
        app: whoamitcp
    spec:
      containers:
        - name: whoami
          image: traefik/whoamitcp
          args:
            - --port=:3000

---
apiVersion: v1
kind: Service
metadata:
  name: whoamitcp
  namespace: default
spec:
  selector:
    app: whoamitcp
  ports:
    - port: 3000

Once everything is deployed, sending the WHO command should return the following response:

응답

$ openssl s_client -quiet -connect localhost:3443 -servername whoami.localhost
Connecting to ::1
depth=0 C=FR, L=Lyon, O=Traefik Labs, CN=Whoami
verify error:num=18:self-signed certificate
verify return:1
depth=0 C=FR, L=Lyon, O=Traefik Labs, CN=Whoami
verify return:1

WHO
Hostname: whoamitcp-85d644bfc-hnmdz
IP: 127.0.0.1
IP: ::1
IP: 10.42.2.4
IP: fe80::d873:20ff:fef5:be86

네이티브 로드 밸런싱

기본적으로 Traefik은 성능을 위해 트래픽을 pod IP로 직접 보내고 백엔드에 이미 수립된 연결을 재사용해요.

이 동작을 재정의하고 Traefik이 트래픽을 서비스 IP로 보내도록 구성할 수 있어요. pod에 대한 로드 밸런싱은 Kubernetes 서비스 자체가 수행해요. 백엔드 Service 에 traefik.io/service.nativelb 주석으로 설정할 수 있어요.

기본적으로 NativeLB는 false 예요.

기본값

프로바이더 레벨의 nativeLBByDefault 옵션으로 기본값을 재정의할 수 있다는 점에 유의하세요.

apiVersion: v1
kind: Service
metadata:
  name: myservice
  namespace: default
  annotations:
    traefik.io/service.nativelb: "true"
spec:
  ports:
    - name: web
      port: 80

프로덕션에서 Traefik OSS를 사용 중인가요?

업무에서 Traefik을 사용하고 있다면 엔터프라이즈급 API 게이트웨이 기능이나 Traefik OSS에 대한 상용 지원을 추가하는 것을 고려해 보세요.

  • API 게이트웨이 데모 영상 보기

  • 24/7/365 OSS 지원 요청하기

Traefik OSS에 API 게이트웨이 기능을 추가하는 것은 빠르고 매끄러워요. 교체(rip and replace)가 필요 없고 모든 구성이 그대로 유지돼요. 짧은 영상으로 직접 확인해 보세요.

더 알아보기 (Learn more)