CloudNet 가시다님이 진행하시는 KANS 스터디 7주차 정리입니다.

 

5.4 Traffic Management

Traffic Management : 트래픽 컨트롤은 VirtualService와 DestinationRule 설정을 통해서 동작한다.

 

▶ 동작 소개 : 클라이언트 PC -> Istio ingressgateway 파드 -> (Gateway, VirtualService + DestinationRule) -> Cluster(Endpoint - 파드)

  • Gateway : 지정한 인그레스 게이트웨이로부터 트래픽이 인입, 프로토콜 및 포트, HOSTS, Proxy 등 설정 가능
  • VirtualService : 인입 처리할 hosts 설정, L7 PATH 별 라우팅, 목적지에 대한 정책 설정 가능 (envoy route config)
  • 사용 예시 : 헤더 매칭에 따라서, 각기 다른 destination으로 라우팅
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v3
  • VirtualService는 DestinationRule에서 설정된 서브넷(subset)을 사용하여 트래픽 컨트롤을 할 수 있다
  • hosts 필드 : 목적지 주소 - IP address, a DNS name (FQDN), 혹은 k8s svc 이름, wildcard("*") prefixes
  • Routing rules : HTTP 경우 - Match 필드(예, 헤더), Destination(istio/envoy에 등록된 대상, subnet에 DestinationRule 활용)
    • HTTPRoute : redierct, rewrite, fault(장애 주입), mirror(복제, 기본 100%), corsPolicy(CORS 삽입), headers(헤더 조작) 등
  • Routing rule precedence : Routing rules are evaluated in sequential order from top to bottom - 위에서 순차적으로 적용
  • DestinationRule : 실제 도착지(서비스와 1:1 연결)의 정교한 정책(부하분산, 연결 옵션, 서킷 브레이크, TLS 등)을 설정
  • 사용 예시 : 3개의 subsets for the my-svc destination service에 3개의 subnets이 있고, 이중 v1/v3은 RANDOM이고 v2는 ROUND_ROBIN
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-destination-rule
spec:
  host: my-svc
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
  - name: v3
    labels:
      version: v3
  • Load balancing options : Round robin(기본값), Random, Weighted, Least requests
    • Destination Rule : TrafficPolicy, Subset, ConnectionPoolSettings 등
    • 서브넷(subsets)을 정의할 수 있어 마이크로서비스 버전별로 라우팅할 때 사용한다

▶ Request Routing

  • 기본 DestinationRule 적용 : 각각의 파드에 subnet 지정

  • virtual-service-all-v1.yaml : 4개 서비스 모두 v1의 서브넷에 전송하는 정책 테스트

istio vs 확인
모든 마이크로서비스에 대해 v1의 서브넷에 전송되게 virtualservice 적용 후 확인

▶ Falut Injection (HTTP 결함 주입) - 의도적으로 지연(Latency)를 발생시키거나 중단

  • virtual-service-ratings-test-delay.yaml : end-user가 jason는 ratings v1에 7초 지연 발생, 그외 사용자는 ratings v1 정상 연결

7초 지연 발생
끊어짐 확인

  • virtual-service-ratings-test-abort.yaml : end-user가 jason는 ratings v1에 500 에러 리턴, 그 외 사용자는 ratings v1 정상 연결

로그상에서도 500 에러 확인

▶ Request Timeouts (타임아웃 제어)

kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: ratings
spec:
  hosts:
  - ratings
  http:
  - fault:
      delay:
        percent: 100
        fixedDelay: 2s
    route:
    - destination:
        host: ratings
        subset: v1
EOF

: 2초 지연 후 정상 접속

  • http timeout 0.5초 설정하지만, 응답 1초 걸리는 이유는, productpage 코드에 reviews 호출 시 timeout 되면 한번 더 재시도하게끔 하드 코딩되어 있음

▶ Envoy response flag

HTTP and TCP

  • UH : No healthy upstream hosts in upstream cluster in addition to 503 response code.
  • UF : Upstream connection failure in addition to 503 response code.
  • UO : Upstream overflow (circuit breaking) in addition to 503 response code.
  • NR : No route configured for a given request in addition to 404 response code, or no matching filter chain for a downstream connection.
  • URX : The request was rejected because the upstream retry limit (HTTP) or maximum connect attempts (TCP) was reached.
  • NC : Upstream cluster not found.
  • DT : When a request or connection exceeded max_connection_duration or max_downstream_connection_duration.
5.5 Security 보안

 

▶ 소개

[요구사항]

  • To defend against main-in-the-middle attacks, they need traffic encryption.
  • To provide flexible service access control, they need mutual TLS and fine-grained access policies.
  • To determine who did what at what time, they need auditing tools.

[목표]

  • Security by default : no changes needed to application code and infrastructure
  • Defense in depth : integrate with existing security systems to provide multiple layers of defense
  • Zero-trust network : build security solutions on distrusted networks

[구성요소]

  • A Certificate Authority (CA) for key and certificate management
  • The configuration API server distributes to the proxies:
    • authentication policies
    • authorization policies
    • secure naming information
  • Sidecar and perimeter proxies work as Policy Enforcement Points(PEPs) to secure communication between clients and servers.
  • A set of Envoy proxy extensions to manage telemetry and auditing

[아키텍처]

  • The control plane handles configuration from the API server and configures the PEPs in the data plane.
  • The PEPs are implemented using Envoy. The following diagram shows the architecture.
제로트러스트(ZT:Zero Trust)
: "신뢰하지 않고 항상 확인"이라는 원칙을 바탕으로 하는 보안 모델이다.
어떤 사용자, 디바이스, 애플리케이션도 네트워크 내부에 있다는 이유만으로 신뢰하지 않고, 모든 접근 시도에 대해 엄격한 인증과 권한 확인 과정을 거치는 것을 의미한다.

제로트러스트의 주요 원칙
- 장치 액세스 제어 : 사용자 액세스에 대한 제어 외에도 Zero Trust는 장치 액세스에 대한 엄격한 제어를 요구한다.
- 최소 권한 : 사용자에게 필요한 최소한의 권한만 부여해야 한다.
- 내부망 이동 방지 : 공격자가 네트워크에 액세스한 후 네트워크 내에서 이동하는 것을 말한다.
- 마이크로 세분화 : 네트워크를 작은 단위로 세분화하여 공격의 영향을 최소화해야 한다.

제로트러스트 구현을 위한 기술
- ID 및 액세스 관리자(IAM) : 사용자와 디바이스를 정확하게 식별하고, 필요한 권한만 부여한다.
- 다중 요소 인증 (MFA) : 비밀번호 외에 추가적인 인증 요소를 요구하여 보안을 강화한다.
- 네트워크 마이크로 세분화 : 네트워크를 작은 단위로 나누어 공격의 영향을 최소화한다.
- SSL/TLS : 데이터 암호화를 통해 데이터 유출을 방지한다.
- 침입 탐지 및 예방 시스템(IDS/IPS) : 침입 시도를 탐지하고 차단한다.
- 로그 관리 및 분석 : 시스템 로그를 분석하여 이상 징후를 탐지한다.

 

▶ TLS vs mTLS - 서로를 인증하는 방식에 있어 차이점이 있다!

1. TLS(Transport Layer Security)

- 일방향 인증 : 서버가 클라이언트에게 자신의 신원을 증명한다. 클라이언트는 서버가 진짜임을 확인할 수 있지만, 서버는 클라이언트가 누구인지 알 수 없다.

- 주요 사용 사례 : 일반적인 웹 통신, 이메일 등

2. mTLS (Mutual TLS)

- 양방향 인증 : 서버와 클라이언트 모두 상대방의 신원을 증명한다. 서로가 서로를 신뢰할수 있는지 확인한다.

- 주요 사용 사례 : API 보안, IoT 기기, 내부 시스템, 금융 서비스

https://blog.cloudflare.com/protecting-the-origin-with-tls-authenticated-origin-pulls/

 

▶ SPIFFE : 워크로드 식별 표준 집합

  • 이기종 환경에서 서비스 ID를 발급할 수 있는 프레임워크
  • istio와 SPIFFE는 SVIC를 공유 -> 이를 통해 istio 서비스는 다른 SPIFFE 호환 시스템과 연결 설정 및 수락 가능

▶ Authentication, Authorizaion (Auto mutual TLS)

[ Identity and certificate management ]

Istio securely provisions strong identites to every workload 

Istio securely provisions strong identities to every workload with X.509 certificates. Istio agents, running alongside each Envoy proxy, work together with istiod to automate key and certificate rotation at scale. The following diagram shows the identity provisioning flow.

1. istiod offers a gRPC service to take certificate signing requests (CSRs).

2. When started, the Istio agent creates the private key and CSR, and then sends the CSR with its credentials to istiod for signing.

3. The CA in istiod validates the credentials carried in the CSR. Upon successful validation, it signs the CSR to generate the certificate.

4. When a workload is started, Envoy requests the certificate and key from the Istio agent in the same container via the Envoy secret discovery service (SDS) API.

5. The Istio agent sends the certificates received from istiod and the private key to Envoy via the Envoy SDS API.

6. Istio agent monitors the expiration of the workload certificate. The above process repeats periodically for certificate and key roatation.

 

Authentication : 2가지 타입 인증 제공

  • Peer authentication : used for service-to-service authentication to verify the client making the connection. Istio offers mutual TLS as a full stack solution for transport authentication, which can be enabled without requiring service code changes. This solution:
    • Provides each service with a strong identity representing its role to enable interoperability across clusters and clouds.
    • Secures servcie-to-service communication.
    • Provides a key management system to automate key and certificate generation, distribution, and rotation.
  • Request authentication : Used for end-user authentication to verify the credential attached to the request. Istio enables request-level authentication with JSON Web Token (JWT) validation and a streamlined developer experience using a custom authentication provider or any OpenID Connect providers, for example : 
    • ORY Hydra, Keycloak, Auth0, Firebase Auth, Google Auth

Mutual TLS authentication

Istio tunnels service-to-service communication through the client- and service-side PEPs, which are implemented as Envoy proxies. When a workload sends a request to another workload using mutual TLS authentication, the request is handled as follows:

1. Istio re-routes the outbound traffic from a client to the client's local sidecar Envoy.

2.  The client side Envoy starts a mutual TLS handshake with the server side Envoy. During the handshake, the client side Envoy also does a secure naming check to verify that the service account presented in the server certificate is authorized to run the target service.

3. The client side Envoy and the server side Envoy establish a mutual TLS connection, and istio forwards the traffic from the client side Envoy to the server side Envoy.

4. The server side Envoy authorizes the request. If authorized, it forwards the traffic to the backend service through local TCP connections.

  • The URI that represnets the SPIFFE ID is formatted like this : spiffe://cluster-name/ns/namespace/sa/service-account-name
  • Peer authentication : PREMISSIVE(mTLS 사용/미사용 모두 허용), STRICT(반드시 mTLS 사용, 미사용 시 거부), DISABLE(mTLS미사용)

Authorization

Istio's authorization features provide mesh-, namespace-, and worklaod-wide access control for your workloads in the mesh. This level of control provides the following benefits:

  • Workload-to-workload and end-user-to-workload authorization.
  • A simple API : it includes a single AuthorizationPolicy CRD, which is easy to use and maintain.
  • Flexible semantics : operators can define custom conditions on Istio attributes, and use CUSTOM, DENY and ALLO actions.
  • High performance : Istio authorization (ALLOW and DENY) is enforced natively on Envoy.
  • High compatibility : supports gRPC, HTTP, HTTPS and HTTP/2 natively, as well as any plain TCP protocols.

 

▶ Authentication (Auto mutual TLS) 실습 : mTLS & PeerAuthentication

  • test 네임스페이스 생성 후 파드 생성(sidecar 미적용) 후 ratings 접속

test 네임스페이스 생성 후 ratings 접속 시도 - 성공
peer authentication 설정 변경
ratings 접속 시도 실패
로그 상에서 차단 확인

▶ AuthoriationPolicy & 실습

인가 기능

  • Workload-to-workload and end-user-workload authorization.
  • A simple API : it includes a single AuthorizationPolicy CRD, which is easy to used and maintain.
  • Flexible semantics : operators can define custom conditions on Istio attributes, and use CUSTOM, DENY and ALLOW actions.
  • High performance : Istio authorization (ALLOW and DENY) is enforced natively on Envoy.
  • High compatibility : supports gRPC, HTTP, HTTPS and HTTP/2 natively, as well as any plain TCP protocols.

Authorization architecture

  • 서버측의 Envoy proxy는 인바운드 트래픽에 대해서 액세스 제어

Implicit enablement

  • For workloads without authorization policies applied, Istio allows all requests => 인증 미적용 시 모든 요청이 허용
  • Authorization policies support ALLOW, DENY and CUSTOM actions => 권한 부여 정책은 '허용, 거부, 사용자 지정' 동작을 한다
  • Istio checks for matching policies in layers, in this order : CUSTOM, DENY and then ALLOW => 정책 적용 우선 순위
  • First, you configure a simple allow-noting policy that rejects all requests to the workload

로그 상에서도 확인

  • Run the following command to create a productpage-viewer policy to allow access with GET method to the productpage workload

productpage는 200 이지만, reviews/details는 403 에러

  • Run the following command to create the details-viewer policy to allow the productpage workload

  • Run the following command to create a policy reviews-viewer to allow the productpage workload

 

▶ JWT Token 접근제어 (JSON Web Token)

  • JWT는 X.509 Certificate와 마찬가지로 private key를 이용하여 토큰을 서명하고 public key를 이용하여 서명된 메세지를 검증합니다.
  • X.509 Certificate의 lightweight JSON 버전이라고 생각하면 편리합니다.
  • jwt는 JSON 형태로 토큰 형식을 정의한 스펙입니다. jwt는 쿠버네티스에서 뿐만 아니라 다양한 웹 사이트에서 인증, 권한 허가, 세션관리 등의 목적으로 사용합니다.
    • Header : 토큰 형식과 암호화 알고리즘을 선언합니다.
    • Payload : 전송하려는 데이터를 JSON 형식으로 기입합니다.
    • Signature:Header와 Payload의 변조 가능성을 검증합니다.
  • 각 파트는 base64 URL 인코딩이 되어서 . 으로 합쳐지게 됩니다.
EnvoyFilter 활용하기

EnvoyFIlter는 Istio Pilot에서 생성된 Envoy 구성을 사용자 정의하는 메커니즘을 제공한다.

EnvoyFIlter를 사용하여 특정 필드의 값을 수정하고, 특정 필터를 추가하거나, 완전히 새로운 리스너, 클러스터 등을 추가할 수 있다. 

참고1) API의 일부 측면은 Istio 네트워킹 하위 시스템의 내부 구현과 Envoy의 XDS API에 깊이 연결되어 있다. EnvoyFilter API 자체는 이전 버전과의 호환성을 유지하지만 이 메커니즘을 통해 제공되는 모든 Envoy 구성은 Istio 프록시 버전 업그레이드에서 주의 깊게 모니터링하여 사용되지 않은 필드가 제거되고 적절하게 대체되어야 한다.

참고2) 주어진 네임스페이스에서 여러 EnvoyFilter가 동일한 작업 부하에 바인딩되는 경우 모든 패치는 생성 시간 순서대로 순차적으로 처리된다. 여러 EnvoyFilter 구성이 서로 충돌하는 경우 동작은 정의되지 않는다.

참고3) 시스템의 모든 우크로드(사이드카 및 게이트웨이)에 EnvoyFilter 리소스를 적용하려면 Workloadselector 없이 config 루트 네임스페이스에서 리소스를 정의한다.

 

모니터링

▶ Grafana(그라파나) & Prometheus

[ Grafana ]

  • 오픈소스 메트릭 데이터 시각화 도구
  • 현재는 40여개의 DB source 타입을 지원
  • 대시보드들을 손쉽게 공유하고 다운 받아 사용
  • Grafana Labs에서 개발 중. Loki, cortex 등을 오픈소스로 개발하고 있는 회사

[Prometheus]

  • Golang으로 개발된 TSDB
  • SoundCloud 사에서 시작한 오픈소스 모니터링 시스템
  • 시계열 데이터 수집
  • 다차원 데이터 모델을 활용한 유연한 쿼리 PromQL(사용자가 실시간으로 시계열 데이터를 선택하고 집계할 수 있는 쿼리)

▶ 프로메테우스와 메트릭

[프로메테우스 메트릭]

  • 메트릭 타입 : Counter, Gauge, Histogram, Summary
  • Counter : 가장 많이 수집되는 유형, 증가하는 이벤트의 누적갯수 또는 크기, 리셋 시 제로 Ex)초당 요청 갯수
  • Gauge : 간단한 수로 표현됨, 증가할수도 있고 감소할수도 있음 ex)메모리 할당량, 장비 온도
  • Histogram : 특정 버킷에 속하는 값의 관찰빈도 측정, 다소 복잡한 유형이며 istio metric에서 항상 이슈가 많음. Quantiles는 분위기 계산 시 유용
  • Summary : Histogram과 유사

▶ 분산 트레이싱 개요

목적 : 하나의 큰 요청에 여러 개의 이어지는 요청으로 동작시, 어떤 곳이 문제인지 알기 쉽게 추적 가능하게 해줌

Trace context propagationi

  • x-request-id
  • x-b3-traceid
  • x-b3-spanid
  • x-b3-parentspanid
  • x-b3-sampled
  • x-b3-flags
  • x-ot-span-context

▶ 실무에서 사용하는 tracing tip

  • 랜덤샘플링 퍼센트 : 100%(몽땅, 주의하자) -> 보통 5~10% 설정
  • Jaeger UI : x-request-id, X-b3-traceid 검색 확인
  • Kiali : Traces에서 확

▶ Istio config_dump

> Envoy 배운대로 나눠서 쿼리하고 json으로 뽑아보기 : istioctl pc (lstneres, clusters, route)

 

 

6. Istio 트래픽 흐름

▶ Istio 통신 : 호스트의 tcp/ip와 iptables과 파드 내에 iptables와 envoy를 경유

  • 달리기에 비유하자면, Istio가 없을 경우를 운동장 한바퀴라면, istio 사용 시 대략 운동장 세바퀴
  • Istio 사용 시 장점도 있지만, 없을 경우 대비 비용(지연 추가, 프로세싱 추가, 복잡한 구조 등)이 추가

 

 

6.1 클라이언트(요청) -> 파드(인입)

[트래픽 흐름]

  • 외부 클라이언트 PC에서 k8s 클러스터 내부의 웹 서버 파드로 인입 시 트래픽 흐름입니다.
  • 기존 패킷 내용 중 변경 전과 변경 후으로 표현

[파드 내 IPTables 적용 흐름] : 아래 (1)~(8) 까지의 과정 먼저 설명

 

6.1.1 Client PC -> Istio IngressGateway 파드 구간

▶ 외부 클라이언트 PC(192.168.10.254)에서 웹 서버 파드로 접속 시도

접속 확인

6.1.2 Istio IngressGateway 파드 -> 노드 인입

▶ Istio IngressGateway(envoy) 파드를 경유하여 웹 서버 파드가 있는 노드로 인입

  • Istio IngressGateway(envoy) 파드는 클라이언트 PC의 IP를 HTTP XFF(X-Forwarded-for) 헤더에 담아서 전달합니다.
  • Istio IngressGateway(envoy) 파드 x-envoy-Y 헤더를 추가해서 전달합니다.
6.1.3 [파드 내부] IP Tables 적용 -> Istio-proxy 컨테이너 인입

▶ 'PAUSE 컨테이너'가 파드 네트워크 네임스페이스를 생성하여 제공하며, 'Init 컨테이너'는 Istio-proxy가 트래픽을 가로챌 수 있게 파드 내에 iptables rules 설정을 완료

2024-10-17T04:38:30.035473Z     info    Running iptables restore with: iptables-restore and the following input:
* nat
-N ISTIO_INBOUND
-N ISTIO_REDIRECT
-N ISTIO_IN_REDIRECT
-N ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp --dport 15008 -j RETURN
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A ISTIO_INBOUND -p tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_OUTPUT -o lo -s 127.0.0.6/32 -j RETURN
-A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -p tcp ! --dport 15008 -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -o lo ! -d 127.0.0.1/32 -p tcp ! --dport 15008 -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
COMMIT
2024-10-17T04:38:30.035534Z     info    Running command (with wait lock): iptables-restore --noflush --wait=30
2024-10-17T04:38:30.037620Z     info    Running iptables restore with: ip6tables-restore and the following input:

2024-10-17T04:38:30.037701Z     info    Running command (with wait lock): ip6tables-restore --noflush --wait=30
2024-10-17T04:38:30.038741Z     info    Running command (without lock): iptables-save 
2024-10-17T04:38:30.040944Z     info    Command output: 
# Generated by iptables-save v1.8.10 on Thu Oct 17 04:38:30 2024
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:ISTIO_INBOUND - [0:0]
:ISTIO_IN_REDIRECT - [0:0]
:ISTIO_OUTPUT - [0:0]
:ISTIO_REDIRECT - [0:0]
-A PREROUTING -p tcp -j ISTIO_INBOUND
-A OUTPUT -p tcp -j ISTIO_OUTPUT
-A ISTIO_INBOUND -p tcp -m tcp --dport 15008 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15090 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15021 -j RETURN
-A ISTIO_INBOUND -p tcp -m tcp --dport 15020 -j RETURN
-A ISTIO_INBOUND -p tcp -j ISTIO_IN_REDIRECT
-A ISTIO_IN_REDIRECT -p tcp -j REDIRECT --to-ports 15006
-A ISTIO_OUTPUT -s 127.0.0.6/32 -o lo -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -p tcp -m tcp ! --dport 15008 -m owner --uid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --uid-owner 1337 -j RETURN
-A ISTIO_OUTPUT ! -d 127.0.0.1/32 -o lo -p tcp -m tcp ! --dport 15008 -m owner --gid-owner 1337 -j ISTIO_IN_REDIRECT
-A ISTIO_OUTPUT -o lo -m owner ! --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -m owner --gid-owner 1337 -j RETURN
-A ISTIO_OUTPUT -d 127.0.0.1/32 -j RETURN
-A ISTIO_OUTPUT -j ISTIO_REDIRECT
-A ISTIO_REDIRECT -p tcp -j REDIRECT --to-ports 15001
COMMIT
# Completed on Thu Oct 17 04:38:30 2024

 

▶ 파드 내 IPTables Chains/Rules 적용(NAT 테이블) -> 'Istio-proxy 컨테이너'로 인입

  • PREROUTING -> ISTIO_INBOUND -> ISTIO_IN_REDIRECT (redir ports 15006)

▶ 'Istio-proxy 컨테이너'의 15006 Listener 확인

root@k8s-w2:~# c1 ss -tpnl '( dport = :15006 or sport = :15006 )'
State      Recv-Q      Send-Q           Local Address:Port            Peer Address:Port     Process
LISTEN     0           4096                   0.0.0.0:15006                0.0.0.0:*         users:(("envoy",pid=3928,fd=37))
LISTEN     0           4096                   0.0.0.0:15006                0.0.0.0:*         users:(("envoy",pid=3928,fd=36))

 

  nginx 파드 내에서 istio-proxy 컨테이너와 nginx 컨테이너 정보 확인

istio-proxy 컨테이너
nginx-container

 

 

6.1.4 [파드 내부] Istio-proxy 컨테이너 - IPTables 적용

▶ 'Istio-proxy 컨테이너'는 대리인(Proxy) 역할로, 출발지IP를 127.0.06으로 변경하여 'Nginx 컨테이너'와 연결을 한다

  • 'Istio-proxy 컨테이너'의 로그 확인

  • 파드 내에서 패킷 덤프 후 확인 : 출발지 IP가 127.0.0.6으로 변경

 

6.1.5 [파드 내부] IPTables 적용 -> Nginx 컨테이너 인입

▶ 파드 내에 IPTables는 전역으로 적용되므로, 'Istio-proxy'의 인/아웃 시 트래픽 구별이 중요

  • 'Istio-proxy'를 빠져나올때는 출발지 IP가 127.0.0.6이므로 ISTIO_OUTPUT에 적용되어 리턴되어 POSTROUTING를 통해 nginx로 도착한다
  • IPTables 확인 : istio-proxy -> OUTPUT -> ISTIO_OUTOUT(맨 상단 Rule 매칭으로 Return) -> POSTROUTING -> NGINX 컨테이너

▶ 최종적으로 nginx 컨테이너에 클라이언트의 요청 트래픽이 도착한다.

 

6.2 파드(리턴 트래픽) -> 클라이언트
  • nginx(웹 서버) 컨테이너에서 리턴 트래픽(응답, 200 ok)를 클라이언트에 전달합니다.
  • IPTables CT(Connection Table)에 정보를 참고해서 역변환 등이 적용되어 전달된다.
6.3 파드(요청) -> 외부 웹서버

[트래픽 흐름]

  • 파드에서 업데이트 나 패치 다운로드 처럼 외부 웹서버나 인터넷 연결 과정에서의 트래픽의 흐름

[파드 내 IPTables 적용 흐름] : 아래 (9)~(15)까지의 과정을 먼저 설명

 

6.3.1 [파드 내부] ClientPC -> Istio IngressGateway 파드 구간

 

▶ 'nginx 컨테이너'에서 외부 웹 서버 요청을 한다.

root@k8s-w2:~# c1 conntrack -L --dst-nat
tcp      6 0 TIME_WAIT src=172.16.46.11 dst=34.117.59.81 sport=59010 dport=80 src=127.0.0.1 dst=172.16.46.11 sport=15001 dport=59010 [ASSURED] mark=0 use=1
conntrack v1.4.5 (conntrack-tools): 1 flow entries have been shown.
 src=172.16.46.11 dst=34.117.59.81 sport=59010 dport=80     # 최초 요청 트래픽 정보
 src=127.0.0.1    dst=172.16.46.11 sport=15001 dport=59010  # 리턴 트래픽에서 IP/Port 정보를 보면, 출발지 포트가 15001 으로, 'istio-proxy' 경유를 했음을 알 수 있다

 

6.3.2 [파드 내부] IPTables -> Istio-proxy 컨테이너 인입

▶ 파드 내 IPTables Chains/Rules 적용 (NAT 테이블) -> 'Istio-proxy 컨테이너'로 인입

  • OUTPUT -> ISTIO_OUTPUT -> ISTIO_REDIRECT (redir ports 15001)
6.3.3 [파드 내부] Istio-proxy 컨테이너 -> 노드의 호스트 네임스페이스

▶ 'Istio-proxy 컨테이너'는 대리인(Proxy) 역할로, 출발지 포트를 변경(+2) 후 외부 웹서버에 연결

▶ 파드를 빠져나가기 전, 다시 한번 더 IPTables 적용 => 이때, 이전 트래픽과 매칭되는 Rule이 다른 것은 UID 1337 때문

 

6.3.4 노드 -> 외부

노드에 SNAT(masquerading) 설정이 되어 있을 경우, 출발지 IP를 노드의 NIC IP로 변환하여 외부 웹서버에 요청을 전달

 

6.4 외부 웹서버(리턴 트래픽)-> 파드

웹 서버에서 리턴 트래픽이 파드에 돌아오는 과정은 1.2에서 알아본 흐름과 유사합니다.

다만, 파드 내로 인입 시 목적지 포트(+2)이므로, 'Nginx 컨테이너'로 바로 가지 않고, 'Istio-proxy 컨테이너'로 먼저 가게 됩니다.

 

 

7. Istio Ambient Mesh

 

 

k3s 환경에 설치 시 아래 파라미터 설정 필요

  • When using k3s and one of its bundled CNIs, you must append some values to your installation command, as K3s uses nonstandard locations for CNI configuration and binaries.
  • These nonstandard locations may be overridden as well, according to k3s documentation. If you are using k3s with a custom, non-bundled CNI, you must use the correct paths for those CNIs, e.g. /etc/cni/net.d
# istioctl
istioctl install --set profile=ambient --set values.cni.cniConfDir=/var/lib/rancher/k3s/agent/etc/cni/net.d --set values.cni.cniBinDir=/var/lib/rancher/k3s/data/current/bin/

# helm
helm install istio-cni istio/cni -n istio-system --set profile=ambient --wait --set cniConfDir=/var/lib/rancher/k3s/agent/etc/cni/net.d --set cniBinDir=/var/lib/rancher/k3s/data/current/bin/

 

Introducing Kmesh : Revolutionizing Service Mesh Data Planes With Kernel-Native Technology

 

 

Istio와 Sidecar

Istio 아키텍처의 특징 중 하나는 Sidecar를 사용하는 것이다. Sidecar는 애플리케이션 컨테이너와 함께 배포되는 프로그래밍 가능한 프록시이다. 

https://istio.io/latest/blog/2022/introducing-ambient-mesh/

 

애플리케이션과 Istio 데이터 플레인을 완벽하게 분리하지 못해 몇가지 제한이 발생

  • 침습성 - Sidecar는 Kubernetes pod 사양을 수정하고 pod 내 트래픽을 리디렉션하여 애플리케이션에 "주입"해야 한다. 결과적으로 Sidecar를 설치하거나 업그레이드하려면 애플리케이션 pod를 다시 시작해야 하며, 이는 워크로드에 방해가 될수 있다.
  • 리소스의 과소 활용 - Sidecar proxy는 연관된 작업 부하에 전념하기 때문에 CPU 및 메모리 리소스는 각 개별 pod의 최악의 사용에 대비하여 프로비저닝되어야 한다. 이는 클러스터 전체에서 리소스의 과소 활용으로 이어질 수 있는 대규모 예약으로 이어진다.
  • 트래픽 중단 - Istio의 Sidecar에서 일반적으로 수행되는 트래픽 캡처 및 HTTP 처리에는 컴퓨팅 비용이 많이 들고 HTTP 구현에 적합하지 않은 일부 애플리케이션이 중단될 수 있다.
Slicing the layers

Istio는 기본 암호화에서 고급 L7 정책에 이르기까지 모든 데이터 플레인 기능을 단일 아키텍처 구성 요소인 Sidecar에 구현한다. Workload에 간단한 전송 보안만 필요한 경우에도 관리자는 여전히 sidecar를 배포하고 유지 관리하는 운영 비용을 지불해야 한다. 

 

Ambient Mesh는 다른 접근 방식을 가지고 있다. Istio의 기능을 두 개의 별도 계층으로 분할한다. 기본에는 라우팅을 처리하는 보안 오버레이와 트래픽에 대란 제로 트러스트 보안이 있다. 그 위에는 필요한 경우 사용자가 L7 처리를 활성화하여 Istio 기능의 전체 범위에 액세스할 수 있다. L7 처리 모드는 보안 오버레이보다 무겁지만 여전히 인프라의 Ambient 구성 요소로 실행되므로 애플리케이션 pod를 수정할 필요가 없다.

https://istio.io/latest/blog/2022/introducing-ambient-mesh/

이 계층적 접근 방식을 통해 사용자는 Istio를 더 점진적으로 채택하여 필요에 따라 네임스페이스별로 메시 없음에서 보안 오버레이, 전체 L7 처리로 원활하게 전활할 수 있다. 또한 다양한 Ambient 모드 또는 Sidecar로 실행되는 워크로드는 우너활하게 상호 운용되므로 사용자는 시간이 지남에 따라 변경되는 특정 요구 사항에 따라 기능을 혼합하고 일치시킬 수 있다.

 

Ambient Mesh 구축

쿠버네티스 클러스터의 각 노드에서 실행되는 공유 에이전트를 사용한다. 이 에이전트는 제로 트러스트 터널(또는 ztunnel)이며, 주요 책임은 메시 내의 요소를 안전하게 연결하고 인증하는 것이다. 노드의 네트워킹 스택은 로컬 ztunnel 에이전트를 통해 참여하는 워크로드의 모든 트래픽을 리디렉션한다. 이를 통해 Istio의 데이터 플레인과 애플리케이션의 우려 사항을 완전히 분리하여 궁극적으로 운영자가 애플리케이션을 방해하지 않고 데이터 플레인을 활성화, 비활성화, 확장 및 업그레이드할 수 있습니다. ztunnel은 워크로드 트래픽에 L7 처리를 수행하지 않으므로 사이드카보다 상당히 간소하다. 복잡성과 관련 리소스 비용이 크게 감소하여 공유 인프라로 제공하기에 적합하다.

 

Ztunnels는 서비스 메시의 핵심 기능인 제로 트러스트를 가능하게 한다. 네임스페이스에 대해 Ambient가 활성화 되면 보안 오버레이가 생성된다. HTTP를 종료하거나 구문 분석하지 않고도 mTLS, 원격 측정, 인증 및 L4 권한 부여를 통해 워크로드를 제공한다.

https://istio.io/latest/blog/2022/introducing-ambient-mesh/

 

주변 메시가 활성화되고 보안 오버레이가 생성되면 L7 기능을 활용하도록 네임스페이스를 구성할 수 있다.이를 통해 네임스페이스는 Virtual Service API , L7 원격 측정 및 L7 권한 부여 정책을 포함한 Istio 기능의 전체 세트를 구현할 수 있다 .이 모드에서 작동하는 네임스페이스는 하나 이상의 Envoy 기반 웨이포인트 프록시를 사용하여 해당 네임스페이스의 워크로드에 대한 L7 처리를 처리한다. Istio의 제어 평면은 클러스터의 ztunnel을 구성하여 L7 처리가 필요한 모든 트래픽을 웨이포인트 프록시를 통해 전달한다. 중요한 점은 Kubernetes 관점에서 웨이포인트 프록시는 다른 Kubernetes 배포와 마찬가지로 자동 확장이 가능한 일반 포드일 뿐이라는 것이다. 웨이포인트 프록시는 제공하는 네임스페이스의 실시간 트래픽 수요에 맞게 자동 확장될 수 있으므로 사용자에게 상당한 리소스 절감 효과가 있을 것으로 예상한다. 최악의 경우 최대 부하 운영자가 예상하는 것이 아니다.

 

https://istio.io/latest/blog/2022/introducing-ambient-mesh/

 

HBONE(HTTP 기반 오버레이 네트워크 환경) - Ambient mesh는 mTLS를 통한 HTTP CONNECT를 사용하여 보안 터널을 구현하고 경로에 웨이포인트 프록시를 삽입

HBONE은 일반적인 로드 밸런서 인프라와의 상호 운용성을 가능하게 하는 동시에 TLS 자체보다 트래픽을 더 깔끔하게 캡슐화한다.  FIPS 빌드는 기본적으로 사용되어 규정 준수 요구 사항을 충족한다. HBONE, 표준 기반 접근 방식, UDP 및 기타 비 TCP 프로토콜에 대한 계획에 대한 자세한 내용은 향후 블로그에서 제공될 예정이다.

단일 메시에서 사이드카와 앰비언트를 혼합해도 시스템의 기능이나 보안 속성에 제한이 생기지 않는다. Istio 제어 평면은 선택한 배포 모델에 관계없이 정책이 적절하게 시행되도록 보장한다. 앰비언트는 단순히 더 나은 인체공학과 더 많은 유연성을 갖춘 옵션을 도입한다.

 

로컬 노드에서 L7 처리가 없는 이유?

Ambient Mesh는 노드에서 공유 ztunnel 에이전트를 사용하여 메시의 제로 트러스트 측면을 처리하는 반면, L7 처리가 별도로 예약된 포드의 웨이포인트 프록시에서 발생한다. 간접적으로 신경 쓰고 노드에서 공유 전체 L7 프록시를 사용하지 않는 이유는 무엇인가?

  • Envoy는 본질적으로 멀티 테넌트가 아니다. 그 결과, 공유 인스턴스에서 여러 제약 없는 테넌트의 L7 트래픽에 대한 복잡한 처리 규칙을 혼합하는 데 보안 문제가 있다. L4 처리로 엄격하게 제한함으로써 취약성 표면 영역을 크게 줄인다.
  • ztunnel에서 제공하는 mTLS 및 L4 기능은 웨이포인트 프록시에서 필요한 L7 처리와 비교했을 때 훨씬 더 작은 CPU 및 메모리 풋프린트가 필요하다. 웨이포인트 프록시를 공유 네임스페이스 리소스로 실행하면 해당 네임스페이스의 필요에 따라 독립적으로 확장할 수 있으며, 관련 없는 테넌트에 비용이 불공평하게 분배되지 않는다.
  • ztunnel의 범위를 줄이면 잘 정의된 상호 운용성 계약을 충족할 수 있는 다른 보안 터널 구현으로 대체할 수 있다.