Bug Report
Please answer these questions before submitting your issue. Thanks!
- What did you do?
On a control machine behind an HTTP proxy (needed to reach the component mirror), with the cluster on an internal network excluded via NO_PROXY:
export HTTP_PROXY=http://internal-proxy:3128
export HTTPS_PROXY=http://internal-proxy:3128
export NO_PROXY=10.0.0.0/8,.internal.example.com,localhost,127.0.0.1
tiup cluster reload <cluster> -R tikv
- What did you expect to see?
NO_PROXY honored: internal hosts (PD, TiKV) reached directly; only the external component mirror goes through the proxy — the standard HTTP_PROXY/NO_PROXY contract.
- What did you see instead?
Every request is forced through HTTP_PROXY regardless of NO_PROXY, so the internal API calls fail. It surfaces in two stages of reload:
- PD API —
error requesting http://pd-1.internal.example.com:2379/pd/api/v1/config, ... code 403 (the proxy rejects the internal request).
- After fixing that, TiKV status scrape —
Error: failed to get leader count ...: metric tikv_raftstore_region_count{type="leader"} not found. tiup scrapes http://tikv-1.internal.example.com:20180/metrics to count leaders before restart; that request also goes through the proxy and returns the proxy's error page, so the metric can't be parsed.
(Conversely, without a proxy, InitConfig fails to fetch /timestamp.json from the mirror — there is no single configuration that works.)
- What version of TiUP are you using (
tiup --version)?
v1.16.5 (also reproduced on master).
Root cause
Two HTTP clients set tr.Proxy to a fixed http.ProxyURL (applied to every destination, ignoring NO_PROXY) instead of http.ProxyFromEnvironment:
pkg/utils/http_client.go → NewHTTPClient — used by the PD API client (pkg/cluster/api/pdapi.go).
pkg/cluster/spec/tikv.go → makeTransport — used by genLeaderCounter to scrape the TiKV status port.
httpProxy := os.Getenv("TIUP_INNER_HTTP_PROXY")
if len(httpProxy) == 0 {
httpProxy = os.Getenv("HTTP_PROXY")
}
if len(httpProxy) > 0 {
if proxyURL, err := url.Parse(httpProxy); err == nil {
tr.Proxy = http.ProxyURL(proxyURL) // ignores NO_PROXY
}
}
Proposed fix (backward compatible)
Resolve the proxy with golang.org/x/net/http/httpproxy so NO_PROXY is honored, keeping the TIUP_INNER_HTTP_PROXY override, in both clients:
import "golang.org/x/net/http/httpproxy"
proxyCfg := httpproxy.FromEnvironment() // HTTP(S)_PROXY + NO_PROXY
if inner := os.Getenv("TIUP_INNER_HTTP_PROXY"); len(inner) > 0 {
proxyCfg.HTTPProxy, proxyCfg.HTTPSProxy = inner, inner
}
proxyFunc := proxyCfg.ProxyFunc()
tr.Proxy = func(req *http.Request) (*url.URL, error) {
return proxyFunc(req.URL)
}
Bug Report
Please answer these questions before submitting your issue. Thanks!
On a control machine behind an HTTP proxy (needed to reach the component mirror), with the cluster on an internal network excluded via
NO_PROXY:NO_PROXYhonored: internal hosts (PD, TiKV) reached directly; only the external component mirror goes through the proxy — the standardHTTP_PROXY/NO_PROXYcontract.Every request is forced through
HTTP_PROXYregardless ofNO_PROXY, so the internal API calls fail. It surfaces in two stages ofreload:error requesting http://pd-1.internal.example.com:2379/pd/api/v1/config, ... code 403(the proxy rejects the internal request).Error: failed to get leader count ...: metric tikv_raftstore_region_count{type="leader"} not found. tiup scrapeshttp://tikv-1.internal.example.com:20180/metricsto count leaders before restart; that request also goes through the proxy and returns the proxy's error page, so the metric can't be parsed.(Conversely, without a proxy,
InitConfigfails to fetch/timestamp.jsonfrom the mirror — there is no single configuration that works.)tiup --version)?v1.16.5 (also reproduced on
master).Root cause
Two HTTP clients set
tr.Proxyto a fixedhttp.ProxyURL(applied to every destination, ignoringNO_PROXY) instead ofhttp.ProxyFromEnvironment:pkg/utils/http_client.go→NewHTTPClient— used by the PD API client (pkg/cluster/api/pdapi.go).pkg/cluster/spec/tikv.go→makeTransport— used bygenLeaderCounterto scrape the TiKV status port.Proposed fix (backward compatible)
Resolve the proxy with
golang.org/x/net/http/httpproxysoNO_PROXYis honored, keeping theTIUP_INNER_HTTP_PROXYoverride, in both clients: