Administration interface和Layered Runtime
管理接口admin
Envoy内建了一个管理服务(administration server),它支持查询和修改操作,甚至有可能暴露私有数据(例如统计数据、集群名称和证书信息等),因此非常有必要精心编排其访问控制机制以避免非授权访问;
admin:
access_log: [] # 访问日志协议的相关配置,通常需要指定日志过滤器及日志配置等;
access_log_path: ... # 管理接口的访问日志文件路径,无须记录访问日志时使用/dev/null;
profile_path: ... # cpu profiler的输出路径,默认为/var/log/envoy/envoy.prof;
address: # 监听的套接字;
socket_address:
protocol: ...
address: ...
port_value: ...
下面是一个简单的配置示例
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 }
# 提示:此处 仅为出于方便测试的目的,才设定其监听于对外通信的任意IP地址;安全起见,应该使用127.0.0.1;
为Envoy添加Admin Interface
以前面一节中配置的“L7 Front Proxy”添加管理接口的方法,仅需要在其用到的envoy.yaml
配置文件中添加相关的配置信息即可;
下面给出的简单的测试命令
admin:
access_log_path: /tmp/admin_access.log
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: 80 }
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
……
clusters:
- name: local_cluster
connect_timeout: 0.25s
type: STATIC
……
~$ curl 172.31.5.2:9901/listeners
listener_0::0.0.0.0:80
~$ curl 172.31.5.2:9901/ready
LIVE
~$ curl 172.31.5.2:9901/config_dump
{
"configs": [ {
"@type":
"type.googleapis.com/envoy.admin.v3.BootstrapConfigDump",
"bootstrap": {
"node": {
"hidden_envoy_deprecated_build_version":
"98c1c9e9a40804b93b074badad1cdf284b47d58b/1.18.3/Clean/RELEAS
E/BoringSSL",
"user_agent_name": "envoy",
"user_agent_build_version": {
"version": {
"major_number": 1,
"minor_number": 18,
"patch": 3
},
……
}
管理接口admin速览
admin接口内置了多个/path,不同的path可能会分别接受不同的GET或POST请求;
admin commands are:
/: Admin home page # GET
/ready:Outputs a string and error code reflecting the state of the server. # GET,返回envoy服务当前的状态;
/certs: print certs on machine # GET,列出已加载的所有TLS证书及相关的信息;
/clusters: upstream cluster status # GET,额外支持使用“GET /clusters?format=json”
/config_dump: dump current Envoy configs # GET,打印Envoy加载的各类配置信息;支持include_eds、master和resource等查询参数;
/contention: dump current Envoy mutex contention stats (if enabled) # GET,互斥跟踪
/cpuprofiler: enable/disable the CPU profiler # POST,启用或禁用cpuprofiler
/healthcheck/fail: cause the server to fail health checks # POST,强制设定HTTP健康状态检查为失败;
/healthcheck/ok: cause the server to pass health checks # POST,强制设定HTTP健康状态检查为成功;
/heapprofiler: enable/disable the heap profiler # POST,启用或禁用heapprofiler;
/help: print out list of admin commands
/hot_restart_version: print the hot restart compatibility version # GET,打印热重启相关的信息;
/listeners: print listener addresses # GET,列出所有侦听器,支持使用“GET /listeners?format=json”
/drain_listeners:Drains all listeners. # POST,驱逐所有的listener,支持使用inboundonly(仅入站侦听器)和graceful(优雅关闭)等查询参数;
/logging: query/change logging levels # POST,启用或禁用不同子组件上的不同日志记录级别
/memory: print current allocation/heap usage # POST,打印当前内在分配信息,以字节为单位;
/quitquitquit: exit the server # POST,干净退出服务器;
/reset_counters: reset all counters to zero # POST,重围所有计数器;
/tap:This endpoint is used for configuring an active tap session. # POST,用于配置活动的带标签的session;
//reopen_logs:Triggers reopen of all access logs. Behavior is similar to SIGUSR1 handling. # POST,重新打开所有的日志,功能类似于SIGUSR1信号;
/runtime: print runtime values # GET,以json格式输出所有运行时相关值;
/runtime_modify: modify runtime values # POST /runtime_modify?key1=value1&key2=value2,添加或修改在查询参数中传递的运行时值
/server_info: print server version/status information # GET,打印当前Envoy Server的相关信息;
/stats: print server stats # 按需输出统计数据,例如GET /stats?filter=regex,另外还支持json和prometheus两种输出格式;
/stats/prometheus: print server stats in prometheus format # 输出prometheus格式的统计信息;
管理接口
几个示例输出
◼ GET /clusters:列出所有已配置的集群,包括每个集群中发现的所有上游主机以及每个主机的统计信息;支持输出为json格式;
◆ 集群管理器信息:“version_info string”,无CDS时,则显示为“version_info::static”
◆ 集群相关的信息:断路器、异常点检测和用于表示是否通过CDS添加的标识“add_via_api”
◆ 每个主机的统计信息:包括总连接数、活动连接数、总请求数和主机的健康状态等;不健康的原因通常有以下三种
-
failed_active_hc:未通过主动健康状态检测;
-
failed_eds_health:被EDS标记为不健康;
-
failed_outlier_check:未通过异常检测机制的检查;
◼ GET /listeners:列出所有已配置的侦听器,包括侦听器的名称以及监听的地址;支持输出为json格式;
◼ POST /reset_counters:将所有计数器重围为0;不过,它只会影响Server本地的输出,对于已经发送到
外部存储系统的统计数据无效;
◼ GET /config_dump:以json格式打印当前从Envoy的各种组件加载的配置信息;
◼ GET /ready:获取Server就绪与否的状态,LIVE状态为200,否则为503;
集群统计信息中主机的状态说明
Envoy 运行时配置概述
相较于静态资源配置来说,xDS API的动态配置机制使得Envoy的配置系统极具弹性;
◼ 但有时候配置的变动仅需要修改个别的功能特性,若通过xDS接口完成未免有些动静过大,Runtime便是面向这种场景的配置接口;
◼ Runtime就是一个虚拟文件系统树,可通过一至多个本地文件系统目录、静态资源、RTDS动态发现和Admin Interface进行定义和配置;
◆ 每个配置称为一个Layer,因而也称为“Layered Runtime”,这些Layer最终叠加生效;
换句话说,Runtime是与Envoy一起部署的外置实时配置系统,用于支持更改配置设置而无需重启Envoy或更改主配置;
◼ 运行时配置相关的运行时参数也称为“功能标志(feature flags)”或“决策者(decider)”;
◼ 通过运行时参数更改配置将实时生效;
运行时配置的实现也称为运行时配置供应者;
◼ Envoy当前支持的运行时配置的实现是由多个层级组成的虚拟文件系统
◆ Envoy在配置的目录中监视符号链接的交换空间,并在发生交换时重新加载文件树;
◼ 但Envoy会使用默认运行时值和“null”提供给程序以确保其正确运行,因此,运行时配置系统并不必不可少;
配置Envoy运行时环境
启用Envoy的运行时配置机制需要在Bootstrap文件中予以启用和配置
◼定义在bootstrap配置文件中的layered_runtime顶级字段之下
◼ 一旦在bootstrap中给出layered_runtime字段,则至少要定义出一个layer;
layered_runtime: # 配置运行配置供应者,未指定时则使用null供应者,即所有参数均加载其默认值;
layers: # 运行时的层级列表,后面的层将覆盖先前层上的配置;
- name: ... # 运行时的层级名称,仅用于“GET /runtime”时的输出;
static_layer: {...} # 静态运行时层级,遵循运行时probobuf JSON表示编码格式;不同于静态的xDS资源,静态运行时层一样可被后面的层所覆盖;
# 此项配置,以及后面三个层级类型彼此互斥,因此一个列表项中仅可定义一层;
disk_layer: {...} # 基于本地磁盘的运行时层级;
symlink_root: ... # 通过符号链接访问的文件系统树;
subdirectory: ... # 指定要在根目录中加载的子目录;
append_service_cluster: ... # 是否将服务集群附加至符号链接根目录下的子路径上;
admin_layer: {...} # 管理控制台运行时层级,即通过/runtime管理端点查看,通过/runtime_modify管理端点修改的配置方式;
rtds_layer: {...} # 运行时发现服务(runtime discovery service)层级,即通过xDS API中的RTDS API动态发现相关的层级配置;
name: ... # 在rtds_config上为RTDS层订阅的资源;
rtds_config:RTDS的ConfigSource;
Front Proxy and TlS
Front proxy
在Envoy Mesh中,作为Front Proxy的Envoy通常是独立运行的进程,它将客户端请求代理至Mesh中的各Service,而这些Service中的每个应用实例都会隐藏于一个Sidecar Proxy模式的envoy
实例背后;
◼ 我们这里仍然以docker-compose为编排工具,以便于将更多的精力集中于Envoy及Mesh之上
TLS
Envoy Mesh 中的TLS模式大体有如下几种常用场景
Front Proxy面向下游客户端提供https服务,但Front Proxy、Mesh内部的各服务间依然使用http协议
◆ https → http
◼ Front Proxy面向下游客户端提供https服务,而且Front Proxy、Mesh内部的各服务间也使用https协议
◆ https → https
◆ 但是内部各Service间的通信也有如下两种情形
-
仅客户端验证服务端证书
-
客户端与服务端之间互相验证彼此的证书(mTLS)
◆ 注意:对于容器化的动态环境来说,证书预配和管理将成为显著难题
◼ Front Proxy直接以TCP Proxy的代理模式,在下游客户端与上游服务端之间透传tls协议;
◆ https-passthrough
◆ 集群内部的东西向流量同样工作于https协议模型
TLS Front Proxy
仅需要配置Listener面向下游客户端提供tls通信,下面是Front Proxy Envoy的配置示例
static_resources:
listeners:
- name: listener_http
address:
socket_address: { address: 0.0.0.0, port_value: 8443 }
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: web_service_01
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: web_cluster_01 }
http_filters:
- name: envoy.filters.http.router
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:
# The following self-signed certificate pair is generated using:
# $ openssl req -x509 -newkey rsa:2048 -keyout front-proxy.key -out front-proxy.crt -days 3650 -nodes -subj '/CN=www.magedu.com'
- certificate_chain:
filename: "/etc/envoy/certs/front-proxy.crt"
private_key:
filename: "/etc/envoy/certs/front-proxy.key“
Upstream and downstream TLS
除了Listener中面向下游提供tls通信,Front Proxy还要以tls协议与Envoy Mesh中的各Service建
立tls连接;
◼ 下面左侧是Envoy Mesh中的某Service的Sidecar Proxy Envoy的配置示例,右则是Front Proxy Envoy
中的Cluster面向上游通信的配置示例
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 443 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
……
http_filters: - name: envoy.filters.http.router
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/envoy/certs/webserver.crt"
private_key:
filename: "/etc/envoy/certs/webserver.key"
clusters:
- name: web_cluster_01
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: web_cluster_01
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.31.8.11, port_value: 443 }
- endpoint:
address:
socket_address: { address: 172.31.8.12, port_value: 443 }
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
Front Proxy https passthrough
TLS passthrough模式的Front Proxy需要使用TCP Proxy类型的Listener,Cluster的相关配置中也无需再指定transport_socket相关的配置;
◼ 但Envoy Mesh中各Service需要基于tls提供服务
static_resources:
listeners:
- name: listener_http
address:
socket_address: { address: 0.0.0.0, port_value: 8443 }
filter_chains:
- filters:
- name: envoy.filters.network.tcp_proxy
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
cluster: web_cluster_01
stat_prefix: https_passthrough
clusters:
- name: web_cluster_01
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: web_cluster_01
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.31.9.11, port_value: 443 }
- endpoint:
address:
socket_address: { address: 172.31.9.12, port_value: 443 }