-
[서비스메시] Istio, EnvoyDevOps, 클라우드/Service Mesh 2024. 7. 13. 18:24
서비스 메시, Istio와 Envoy
서비스 메시는 주로 분산 아키텍처에서 각 소프트웨어 컴포넌트 간의 네트워킹을 관리한다.
- 특히 쿠버네티스 환경에서 마이크로서비스 간의 상호 연결을 관리하고, 그에 대한 가시성을 제공한다.
- 기본 쿠버네티스 기능만으로는 어렵다.
- 서비스 메시를 사용하면 네트워크 트래픽을 경유하는 다양한 로직을 구성할 수 있다.
- 이를 통해 원격 측정, 보안, 트래픽 관리 등 여러 기능을 구현 가능하다.
Istio는 각 파드에 프록시 컨테이너를 주입하여 네트워크 요청을 관리한다.
- 프록시는 네트워크 호출을 가로채어 서비스 메시의 로직을 적용하고, 이를 대상 컨테이너로 전달한다.
- 이 과정에서 Istio는 원격 측정 데이터를 수집하고, 호출 체인을 추적한다.
Istio의 구성 요소는 크게 데이터 플레인과 컨트롤 플레인으로 나뉜다.
- 데이터 플레인은 각 파드에 주입되는 프록시를 포함하며, 컨트롤 플레인은 Istio 시스템 자체를 실행하는 파드들로 구성된다.
- 최신 버전의 Istio에서는 Istio Daemon 파드가 대부분의 기능 담당한다.
Istio는 여러 서비스 메시 구현 중 하나로, 프록시를 이용하여 서비스 간 통신을 관리하는 역할을 한다.
- Istio는 Envoy 프록시를 기본 사이드카 컨테이너로서 구현하여, 특정 컨테이너가 클러스터 내 다른 컨테이너를 호출할 때 이를 프록시를 통해 라우팅한다.
- Istio는 Kubernetes의 커스텀 리소스 정의를 통해 Envoy를 설정하고 관리하며, 사용자는 일반적인 Kubernetes YAML을 사용하여 Istio를 구성할 수 있다.
- Istio를 사용하는 주된 이유는, Envoy를 직접 다루는 것보다 훨씬 편리하고 추상화된 서비스 메시 기능을 제공하기 때문이다.
Envoy Demo 구성 파일
admin: access_log_path: /tmp/admin_access.log address: socket_address: protocol: TCP address: 0.0.0.0 port_value: 9901 # Admin Endpoint Port static_resources: listeners: - name: listener_0 address: socket_address: protocol: TCP address: 0.0.0.0 port_value: 10000 # 임의의 Envoy Listener Port(http) filter_chains: - filters: - name: envoy.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager stat_prefix: ingress_http route_config: name: api_and_internal_split_routing virtual_hosts: - name: backend domains: ["*"] routes: - match: prefix: "/api" route: cluster: service_api prefix_rewrite: "/" host_rewrite: "www.google.com" http_filters: - name: envoy.router clusters: # grouping 된 타겟, K8s Cluster가 아님 - name: service_api connect_timeout: 10s type: STRICT_DNS # Comment out the following line to test on v6 networks dns_lookup_family: V4_ONLY lb_policy: ROUND_ROBIN load_assignment: cluster_name: service_api endpoints: - lb_endpoints: - endpoint: address: socket_address: address: www.google.com port_value: 443 tls_context: sni: www.google.com
- envoy 내장 필터 체인으로 envoy.http_connection_manager 를 사용한다.
- 이 필터 체인의 proto 스키마는 다음과 같다.
envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
- 해당 필터는 envoy 내장 TCP 필터이며 http에 대한 스펙을 정의하고 있다.
- 가상 호스트로 prefix-matching을 사용하고 있으며 reverse-proxy로 들어온 요청을 rewrite 하고 있다.
- 그래서 위 리버스 프록시에서 /api 로 접근하는 http 요청에 대해서 호스트를 www.google.com으로 라우팅해준다.
- 어드민 페이지는 요렇게 정의한 9901 포트로 접근해 확인할 수 있다.
Envoy v2와 v3 스펙 차이
1.16.x 버전까지의 envoy는 필터 체인에서 v2의 내장 tcp(http) 스키마를 사용할 수 있다.
- 데모에서 제공하는 http_connection_manager 가 v2의 구현체다.
- 근데, 1.17 부터는 v3를 extension 형태로 지원한다.
v2 정적 리소스 스펙
{ "codec_type": "...", "stat_prefix": "...", "rds": "{...}", "route_config": "{...}", "scoped_routes": "{...}", "http_filters": [], "add_user_agent": "{...}", "tracing": "{...}", "common_http_protocol_options": "{...}", "http_protocol_options": "{...}", "http2_protocol_options": "{...}", "server_name": "...", "server_header_transformation": "...", "max_request_headers_kb": "{...}", "idle_timeout": "{...}", "stream_idle_timeout": "{...}", "request_timeout": "{...}", "drain_timeout": "{...}", "delayed_close_timeout": "{...}", "access_log": [], "use_remote_address": "{...}", "xff_num_trusted_hops": "...", "internal_address_config": "{...}", "skip_xff_append": "...", "via": "...", "generate_request_id": "{...}", "preserve_external_request_id": "...", "forward_client_cert_details": "...", "set_current_client_cert_details": "{...}", "proxy_100_continue": "...", "upgrade_configs": [], "normalize_path": "{...}", "merge_slashes": "...", "request_id_extension": "{...}" }
v3 정적 리소스 스펙
{ "codec_type": ..., "stat_prefix": ..., "rds": {...}, "route_config": {...}, "scoped_routes": {...}, "http_filters": [], "add_user_agent": {...}, "tracing": {...}, "common_http_protocol_options": {...}, "http_protocol_options": {...}, "http2_protocol_options": {...}, "server_name": ..., "server_header_transformation": ..., "scheme_header_transformation": {...}, "max_request_headers_kb": {...}, "stream_idle_timeout": {...}, "request_timeout": {...}, "request_headers_timeout": {...}, "drain_timeout": {...}, "delayed_close_timeout": {...}, "access_log": [], "access_log_flush_interval": {...}, "flush_access_log_on_new_request": ..., "access_log_options": {...}, "use_remote_address": {...}, "xff_num_trusted_hops": ..., "original_ip_detection_extensions": [], "early_header_mutation_extensions": [], "internal_address_config": {...}, "skip_xff_append": ..., "via": ..., "generate_request_id": {...}, "preserve_external_request_id": ..., "always_set_request_id_in_response": ..., "forward_client_cert_details": ..., "set_current_client_cert_details": {...}, "proxy_100_continue": ..., "upgrade_configs": [], "normalize_path": {...}, "merge_slashes": ..., "path_with_escaped_slashes_action": ..., "request_id_extension": {...}, "local_reply_config": {...}, "strip_matching_host_port": ..., "strip_any_host_port": ..., "stream_error_on_invalid_http_message": {...}, "strip_trailing_host_dot": ..., "proxy_status_config": {...}, "append_x_forwarded_port": ..., "append_local_overload": ..., "add_proxy_protocol_connection_state": {...} }
v2 http 라우터와 v3 http 라우터에는 차이가 존재한다.
우선 공식 docs에서 제공하는 v2 라우팅 스펙과 v3 라우팅 스펙를 보면 필터 설정에 대한 차이를 볼 수 있다.
v2: envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager
v3: envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagertyped_config: "@type": type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager stat_prefix: ingress_http route_config: name: api_and_internal_split_routing virtual_hosts: - name: backend domains: ["*"] routes: - match: prefix: "/api" route: cluster: service_api prefix_rewrite: "/" host_rewrite: "www.google.com"
앞서 작성한 demo config에서의 차이를 보자.
v2 route-config에서는 host_rewite 를 통해서 라우팅할 호스트를 지정하고 있다.
이에 대한 공식 docs를 보면 다음과 같은 설명이 있다.
host_rewrite
(string) Indicates that during forwarding, the host header will be swapped with this value. Only one of host_rewrite, auto_host_rewrite, auto_host_rewrite_header may be set.그니까… host_rewrite, auto_host_rewrite, auto_host_rewrite_header 중 하나의 필드를 통해서 호스트를 필수적으로 지정해야 한다.
그런데 v3 route-config에서는 host_rewrite 를 지원하지 않는다.
host_rewrite를 대체 할 수 있는 필드는 host_rewrite_literal, auto_host_rewrite, host_rewrite_header, host_rewrite_path_regex 뿐이다.host_rewrite_literal
(string) Indicates that during forwarding, the host header will be swapped with this value. Using this option will append the x-forwarded-host header if append_x_forwarded_host is set. Only one of host_rewrite_literal, auto_host_rewrite, host_rewrite_header, host_rewrite_path_regex may be set.라우팅 스펙이 변경되면서 내장된 필터 스펙도 변경된다.
우리는 아래의 처럼 envoy의 내장 router를 바로 사용했었다.
그렇지만, v3에서는 filter에 내장된 tcp 라우터 중 http 라우터를 선택하고 그 구현체를 직접 정의해야 한다.# v2 http_filters: - name: envoy.router
# v3 http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
클러스터 스펙도 함께 확인해보자.
- 마찬가지로 tls_contex 에서 단순하게 Server Name Indication만 정의했던 v2다.
- 그렇지만, v3에서는 transport_socket 레벨에서 그 구현체를 정의하도록 변경되었다.
# v2 clusters: # grouping 된 타겟, K8s Cluster가 아님 - name: service_api connect_timeout: 10s type: STRICT_DNS # Comment out the following line to test on v6 networks dns_lookup_family: V4_ONLY lb_policy: ROUND_ROBIN load_assignment: cluster_name: service_api endpoints: - lb_endpoints: - endpoint: address: socket_address: address: www.google.com port_value: 443 tls_context: sni: www.google.com
# v3 transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext sni: www.google.com
결론
컨테이너 오케스트레이션을 접하다보면 늘 서비스 디스커버리, 서비스 메시, 프록시가 함께 따라다니더라.
이번에 서비스 메시가 좀 궁금해져서 제일 많이 노출되는 Istio를 공부해보기 시작했다.
간단한 개념과 프록시 설정법만 확인해봤는데 버전 별 스펙이 다른데 설정할 값도 많아서 좀 신경써서 구축해야겠다 싶다.
'DevOps, 클라우드 > Service Mesh' 카테고리의 다른 글
[서비스메시] Istio로 트래픽 관리하기 (1) 2024.10.05 [서비스메시] Ambient Mesh에 대해서 (1) 2024.08.05 [서비스메시] 변수명은 중요하다. (0) 2024.07.28