Sidecar 的配置分两次到来
一句话总结
sidecar 容器启动的不是 Envoy,而是 pilot-agent。pilot-agent 汇集容器参数、环境变量和网格配置,写出一份 bootstrap,这份 bootstrap 中只有两样东西:这个代理是谁(node)和从哪里获取配置(xds-grpc)。其余的一切都从 istiod 获取。
为什么需要它
Envoy 只需一份配置文件就能启动。但不可能为网格中的数千个代理预先生成各不相同的配置文件。每个 Pod 的 IP 和名称都不同,而且每当服务增加,就要重写所有文件。所以 Istio 把配置拆成了两部分:Pod 启动时确定的小型 bootstrap,以及启动之后从 istiod 获取的其余全部内容。
这样拆分之后,就出现了新的故障类型。bootstrap 有误,代理就根本启动不起来(CrashLoop);bootstrap 是对的,但连不上 istiod,代理虽然在运行,却没有就绪(Ready 0/2)。要区分这两种症状,就必须知道 bootstrap 是在哪里、用什么生成的。
工作原理
注入产物中的 istio-proxy 以 proxy sidecar --domain $(POD_NAMESPACE).svc.cluster.local … 开头。$(POD_NAMESPACE) 不是 shell 语法,而是 kubelet 用同名环境变量替换进去的 Kubernetes 语法。环境变量有两类。一类是 CA_ADDR、TRUST_DOMAIN 这样在注入时就已确定的值,另一类是 Pod 名称、命名空间、服务账号这样必须等 Pod 启动才能知道、因而通过 fieldRef 获取的值。
pilot-agent 把这些汇集起来,生成 bootstrap。
| bootstrap 位置 | 材料 |
|---|---|
node.id |
角色(sidecar)、Pod IP、<파드이름>.<네임스페이스>、<네임스페이스>.svc.cluster.local(占位符依次为 Pod 名称与命名空间、命名空间)四个字段,用波浪号连接而成 |
node.cluster |
<워크로드>.<네임스페이스>(占位符依次为工作负载与命名空间) |
node.metadata |
去掉 ISTIO_META_* 变量前缀后的内容(CLUSTER_ID、MESH_ID、WORKLOAD_NAME 等) |
static_resources.clusters |
只有一个 xds-grpc。即网格配置中的 discoveryAddress(默认 istiod.istio-system.svc:15012) |
dynamic_resources |
通过 ADS 接收 CDS、LDS,并一直等到第一个响应(initial_fetch_timeout: 0s) |
istiod 既是配置服务器,又是证书签发机构。所以在默认安装中,CA_ADDR 和 discoveryAddress 指向同一个 15012。身份证明始于两个卷。audience 被限定为 istio-ca 的投射服务账号令牌,证明“我是这个服务账号”;istio-ca-root-cert ConfigMap 中的根证书,则用来确认对方是不是真正的 istiod。
在现场相遇的样子
只有 sidecar 处于 CrashLoopBackOff。用自定义 bootstrap(sidecar.istio.io/bootstrapOverride)或 EnvoyFilter 改动了集群名称时,常会遇到这种情况。日志第一行如果是 Unknown gRPC client cluster,就说明 ADS 所指向的名称和静态集群名称对不上。这类问题可以在部署之前用 --mode validate 筛出来。
Pod 停在 1/2 Ready。代理在运行,但 15021 返回 503。如果 Envoy 停留在 PRE_INITIALIZING,说明没有从 istiod 收到第一份配置——可能是网络策略阻断了 15012,也可能是令牌的 audience 不符导致无法获得证书,或者是 istiod 已经下线。管理端口在这种状态下也是开放的,所以先看 control_plane.connected_state。
多集群中配置混在一起。如果 CLUSTER_ID 在两个集群中相同,istiod 就无法区分这两个代理,端点会混杂。标识就是选择配置的键。
官方文档:pilot-agent · Debugging Envoy and Istiod · Envoy bootstrap
下一项实验要做什么
从注入产物中提取参数、环境变量和卷,亲手编写同样形态的 bootstrap 并进行筛查。观察只写错一个集群名称,Envoy 就在启动之前拒绝的情形,并用管理端口确认在没有 istiod 的 Pod 中,代理无法就绪、只能等待的情形。