Envoy Proxy
クラウドネイティブ高性能プロキシ。サービスメッシュ、API Gateway、ロードバランサー機能。observability、動的設定、gRPC対応。
サーバー
Envoy Proxy
概要
Envoy Proxyは、クラウドネイティブ環境とマイクロサービスアーキテクチャのために設計された高性能エッジプロキシ・サービスメッシュ用プロキシです。C++で開発され、毎秒数十万のリクエストを処理できる高いパフォーマンスを誇ります。動的設定管理(xDS API)、豊富な可観測性機能、多様なプロトコルサポート(HTTP/1.1、HTTP/2、HTTP/3、gRPC)により、現代のマイクロサービス環境で広く採用されています。IstioやAWS App Meshなどの主要サービスメッシュソリューションの基盤として使用されており、CNCF(Cloud Native Computing Foundation)卒業プロジェクトとして信頼性が確立されています。
詳細
Envoy Proxyは2016年にLyft社で開発開始され、2017年にオープンソース化されました。現在のバージョン1.31では、HTTP/3(QUIC)、WebAssembly(WASM)フィルター、OAuth2認証、外部処理フィルター等の先進的な機能を提供しています。イベント駆動型の非同期アーキテクチャとマルチスレッド設計により、極めて高いスループットと低いレイテンシを実現します。プラグアブルなフィルターチェーンアーキテクチャにより、HTTPフィルター、ネットワークフィルター、リスナーフィルターを組み合わせた柔軟な拡張が可能です。
主な特徴
- 動的設定管理: xDS API(LDS、CDS、RDS、EDS)による設定の動的更新
- 高度な負荷分散: サブセット負荷分散、地域加重負荷分散、カスタムポリシー対応
- 包括的可観測性: 分散トレーシング、メトリクス収集、アクセスログ機能
- モダンプロトコル対応: HTTP/2、HTTP/3、gRPC、WebSocketの完全サポート
- 拡張性: フィルターチェーンとWebAssemblyによる柔軟なカスタマイズ
- セキュリティ機能: mTLS、OAuth2、JWTバリデーション、レート制限
メリット・デメリット
メリット
- Kubernetesとサービスメッシュのデファクトスタンダードプロキシ
- 極めて高いパフォーマンスとリソース効率性
- 豊富な可観測性機能により運用負荷を大幅に軽減
- 動的設定により無停止での設定変更が可能
- 主要クラウドプロバイダーとサービスメッシュソリューションでサポート
- 活発な開発コミュニティとCNCFによる長期サポート保証
デメリット
- 学習コストが高く、設定の複雑性が初期導入の障壁となる
- YAML設定ファイルが大規模環境では非常に複雑になる傾向
- デバッグ時に多層フィルターチェーンの問題特定が困難
- メモリ使用量がやや多く、リソース制約環境では注意が必要
- 従来のシンプルなロードバランサーと比較してオーバーヘッドが存在
- プロダクション運用には専門的なサービスメッシュ知識が必要
参考ページ
書き方の例
基本設定とHTTPプロキシ
# envoy.yaml
admin:
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: service_backend
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: service_backend
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: backend.example.com
port_value: 80
負荷分散とヘルスチェック設定
# 高度な負荷分散設定
clusters:
- name: web_service
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: LEAST_REQUEST
health_checks:
- timeout: 1s
interval: 5s
unhealthy_threshold: 3
healthy_threshold: 2
http_health_check:
path: "/health"
expected_statuses:
- start: 200
end: 299
load_assignment:
cluster_name: web_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: web1.example.com
port_value: 8080
health_check_config:
port_value: 8080
- endpoint:
address:
socket_address:
address: web2.example.com
port_value: 8080
- endpoint:
address:
socket_address:
address: web3.example.com
port_value: 8080
# サブセット負荷分散
- name: api_service
connect_timeout: 0.25s
type: EDS
eds_cluster_config:
eds_config:
path: "./eds.yaml"
lb_policy: LEAST_REQUEST
lb_subset_config:
fallback_policy: ANY_ENDPOINT
subset_selectors:
- keys: ["version"]
- keys: ["stage", "version"]
SSL/TLS終端と高度なセキュリティ設定
# TLS設定
listeners:
- name: https_listener
address:
socket_address:
address: 0.0.0.0
port_value: 443
filter_chains:
- transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain:
filename: "/etc/ssl/certs/server.crt"
private_key:
filename: "/etc/ssl/private/server.key"
validation_context:
trusted_ca:
filename: "/etc/ssl/certs/ca.crt"
alpn_protocols: ["h2", "http/1.1"]
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_https
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: secure_service
domains: ["secure.example.com"]
routes:
- match:
prefix: "/"
route:
cluster: secure_backend
http_filters:
# JWT認証フィルター
- name: envoy.filters.http.jwt_authn
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
providers:
auth0:
issuer: "https://your-domain.auth0.com/"
audiences:
- "your-api-audience"
remote_jwks:
http_uri:
uri: "https://your-domain.auth0.com/.well-known/jwks.json"
cluster: jwks_cluster
timeout: 5s
rules:
- match:
prefix: "/api/"
requires:
provider_name: "auth0"
# レート制限フィルター
- name: envoy.filters.http.local_ratelimit
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
stat_prefix: http_local_rate_limit
token_bucket:
max_tokens: 1000
tokens_per_fill: 1000
fill_interval: 1s
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
可観測性とトレーシング設定
# 分散トレーシング設定
tracing:
http:
name: envoy.tracers.zipkin
typed_config:
"@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
collector_cluster: zipkin
collector_endpoint: "/api/v2/spans"
shared_span_context: false
# メトリクス設定
stats_sinks:
- name: envoy.stat_sinks.statsd
typed_config:
"@type": type.googleapis.com/envoy.config.core.v3.StatsdSink
address:
socket_address:
address: statsd.example.com
port_value: 8125
- name: envoy.stat_sinks.metrics_service
typed_config:
"@type": type.googleapis.com/envoy.config.core.v3.MetricsServiceConfig
grpc_service:
envoy_grpc:
cluster_name: metrics_service
# アクセスログ設定
http_connection_manager:
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/var/log/envoy/access.log"
format: |
[%START_TIME%] "%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%"
%RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT%
%DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% "%REQ(X-FORWARDED-FOR)%"
"%REQ(USER-AGENT)%" "%REQ(X-REQUEST-ID)%" "%REQ(:AUTHORITY)%" "%UPSTREAM_HOST%"
- name: envoy.access_loggers.grpc
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.grpc.v3.HttpGrpcAccessLogConfig
common_config:
grpc_service:
envoy_grpc:
cluster_name: access_log_service
log_name: "envoy-access-log"
動的設定(xDS)とサービスディスカバリ
# 動的設定管理
dynamic_resources:
# リスナーディスカバリサービス
lds_config:
api_config_source:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
set_node_on_first_message_only: true
# クラスターディスカバリサービス
cds_config:
api_config_source:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
set_node_on_first_message_only: true
# ノード情報
node:
cluster: service_cluster
id: service_node_1
metadata:
zone: us-east-1a
region: us-east-1
version: "1.0"
static_resources:
clusters:
# xDS管理サーバー
- name: xds_cluster
connect_timeout: 0.25s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options:
connection_keepalive:
interval: 30s
timeout: 5s
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: control-plane.example.com
port_value: 18000
WebAssembly拡張とカスタムフィルター
# WebAssemblyフィルター
http_filters:
- name: envoy.filters.http.wasm
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
config:
name: "custom_auth_filter"
root_id: "custom_auth"
configuration:
"@type": type.googleapis.com/google.protobuf.StringValue
value: |
{
"api_endpoint": "https://auth.example.com/validate",
"timeout_ms": 1000
}
vm_config:
vm_id: "custom_auth"
runtime: "envoy.wasm.runtime.v8"
code:
local:
inline_string: |
class CustomAuth {
constructor(rootContext) {
this.rootContext = rootContext;
}
onRequestHeaders() {
const authHeader = this.getRequestHeader("authorization");
if (!authHeader) {
this.sendLocalResponse(401, "Unauthorized", "Missing authorization header", []);
return FilterHeadersStatus.StopIteration;
}
return FilterHeadersStatus.Continue;
}
}
# Luaフィルター(軽量スクリプト)
- name: envoy.filters.http.lua
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
inline_code: |
function envoy_on_request(request_handle)
-- カスタムヘッダーの追加
request_handle:headers():add("x-custom-header", "added-by-lua")
-- リクエストログ
request_handle:logInfo("Processing request: " .. request_handle:headers():get(":path"))
end
function envoy_on_response(response_handle)
-- レスポンス時間の追加
local start_time = response_handle:headers():get("x-request-start")
if start_time then
local duration = os.time() - tonumber(start_time)
response_handle:headers():add("x-response-time", tostring(duration) .. "ms")
end
end
TCPプロキシとマルチプロトコル対応
# TCPプロキシ設定
listeners:
- name: tcp_proxy
address:
socket_address:
address: 0.0.0.0
port_value: 3306
filter_chains:
- filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
stat_prefix: tcp_mysql
cluster: mysql_cluster
access_log:
- name: envoy.access_loggers.file
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
path: "/var/log/envoy/tcp_access.log"
# Redis Proxy
- name: redis_proxy
address:
socket_address:
address: 0.0.0.0
port_value: 6379
filter_chains:
- filters:
- name: envoy.filters.network.redis_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.redis_proxy.v3.RedisProxy
stat_prefix: redis_stats
prefix_routes:
routes:
- prefix: "user:"
cluster: redis_user_cluster
- prefix: "session:"
cluster: redis_session_cluster
catch_all_route:
cluster: redis_default_cluster
settings:
op_timeout: 5s
enable_redirection: true
# gRPCプロキシ設定
- name: grpc_proxy
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: grpc_ingress
codec_type: AUTO
route_config:
name: grpc_route
virtual_hosts:
- name: grpc_service
domains: ["grpc.example.com"]
routes:
- match:
prefix: "/api.UserService/"
route:
cluster: grpc_backend
timeout: 30s
http_filters:
- name: envoy.filters.http.grpc_web
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router