Change:
What happened: When apiserver is using apiservice and service EXTERNAL-IP to access the external http service(a sample metric service),the "http request header Host" is still the apiserver's Host, causing the external http proxy services are failed to forward the request normally. The requested link is like this client -apiserver -external http proxy service -real http service(metric service) What you expected to happen: Many http proxy servers handle request forwarding through the http request header Host, such as nginxif the aggregator accesses an external http service, the original request header HOST should be request.URL.Host How to reproduce it (as minimally and precisely as possible): apiservice and ExternalName service a http proxy server() and print the "HTTP HEADER HOST" to nginx accesslog to change test-ext- DNS IP to the proxy server ip https://127.0.0.1:6443/apis/power.metrics.extender/v1alpha1/nodes nginx access log,the "HTTP HEADER HOST" is '127.0.0.1:6443' but not test-ext- The following is the configuration NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.254.0.1 <none443/TCP 2d power-metrics ExternalName <nonetest-ext- <none2d Name: Namespace: Labels: <noneAnnotations: <noneAPI Version: Kind: APIService Metadata: Creation Timestamp: 2018-11-30T07:54:23Z Resource Version: Self Link: UID: -f475-11e8-a76f- Spec: Group: power.metrics.extender Group Priority Minimum: 1000 Insecure Skip TLS Verify: true Service: Name: power-metrics Namespace: default Version: v1alpha1 Version Priority: 15 Status: Conditions: Last Transition Time: 2018-12-03T05:51:12Z Message: all checks passed Reason: Passed Status: True Type: Available Events: <noneAnything else we need to know?: Environment: Kubernetes version (use ): Client Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.1", GitCommit:"", GitTreeState:"clean", BuildDate:"2018-11-30T07:43:21Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"12+", GitVersion:"v1.12.0-alpha.0.2304+", GitCommit:"", GitTreeState:"clean", BuildDate:"2018-11-30T16:20:19Z", GoVersion:"go1.10.4", Compiler:"gc", Platform:"linux/amd64"} Cloud provider or hardware configuration: OS (e.g. from /etc/os-release): NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" IDLIKE="rhel fedora" VERSIONID="7" PRETTYNAME="CentOS Linux 7 (Core)" ANSICOLOR="0;31" CPENAME="cpe:/o:centos:centos:7" HOMEURL="" BUGREPORTURL="" CENTOSMANTISBTPROJECT="CentOS-7" CENTOSMANTISBTPROJECTVERSION="7" REDHATSUPPORTPRODUCT="centos" REDHATSUPPORTPRODUCTVERSION="7" Kernel (e.g. ): Linux 4.9.87-linuxkit-aufs SMP Wed Mar 14 15:12:16 UTC 2018 x8664 x8664 x86_64 GNU/Linux Install tools: Others: <!-- DO NOT EDIT BELOW THIS LINE --/kind bug
/sig api-machinery
/assign
so test-ext- is the proxy server, and from its access log, you see the req header is "127.0.0.1:6443", which is the apiserver's host. It seems that is working as expected. i.e, when apiserver sends the request to the proxy server, the req header should be apiserver's host. it cannot be the proxy server's host. Am I missing something here?
Thanks for your replyApiserver uses "test-ext-" to access proxy serverthe http req header's Host should be "test-ext-" but is "127.0.0.1:6443"this is not conform to IETF specification()
Yes, i see your point. I'll take a closer look at the code today or tomorrow.
Do you have any progress?
yes, i think the code is here: newReq.Header = utilnet.CloneHeader(req.Header) so the header is simply a clone of req.Header, though newReq.URL = location, and location.Host = rloc.Host, which has the correct resolved host for your case () Could you make a quick change to newReq.Header, and do a local build to check if it fixes the issue you encountered?
I think the problem code is here: copied Old 'req.Host' to New 'req.Host'then i add code:' ',Under line 144()it works for me. In additionI think the final request went out and passed this code this code Priority use 'req.Host' but not 'req.URL.Host'so apiserver needs to change req.Host externally before accessing external http services
I agree. Would you mind to make a PR?
ThanksI'll do it

Discussion:
newReq := req.WithContext(context.Background()) newReq.Header = utilnet.CloneHeader(req.Header) newReq.URL = location <ins> newReq.Host = location.Host </ins> if handlingInfo.proxyRoundTripper == nil { proxyError(w, req, "", http.StatusNotFound)

called  bool headers map[string][]string path    string <ins> host    string </ins> } func (d *targetHTTPHandler) Reset() { d.path = "" d.called = false d.headers = nil <ins> d.host = "" </ins> } func (d *targetHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { d.path = r.URL.Path d.called = true d.headers = r.Header <ins> d.host = r.Host </ins> w.WriteHeader(http.StatusOK) }

t.Errorf("%s: expected %v, got %v", name, e, a) return } <ins> if e, a := targetServer.Listener.Addr().String(), target.host; tc.expectedCalled && !reflect.DeepEqual(e, a) { t.Errorf("%s: expected %v, got %v", name, e, a) return } </ins> }() } }