How to make Istio route custom HTTP methods?
$ curl -v -X MYMETHOD https://myapp.com
< HTTP/2 400
< content-length: 11
< content-type: text/plain
< date: Wed, 29 Dec 2021 08:24:36 GMT
< server: envoy
< x-envoy-upstream-service-time: 1
<
* Connection #0 to host myapp.com left intact
Bad Request
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp
spec:
gateways:
- gw
hosts:
- 'myapp.com'
http:
- name: myapp
route:
- destination:
host: myapp
port:
number: 8000
Kubernetes: 1.22.4
Istio: 1.12.1
Envoy does not support custom HTTP methods. Envoy implements the H/1 codec, which has a hardcoded list of HTTP methods it accepts (see RFC)
There is an open issue on the Envoy Github: https://github.com/envoyproxy/envoy/issues/18819
So you can't achieve what you want with an HTTP route. But you can make it work with a TCP/TLS route.
For this do the following:
Set the correct protocol on the service istio-ingressgateway:
ports:
- name: tcp
nodePort: 8000
port: 8000
protocol: TCP
Change the protocol on the gateway port
port:
name: tcp-gateway
number: 8000
protocol: TCP
Configure your Virtual Service for TCP traffic:
spec:
gateways:
- example-gateway
hosts:
- myapp.com
tcp:
- match:
- port: 8000
route:
- destination:
host: myapp.svc.cluster.local
port:
number: 8000
With a TCP endpoint, you have to take into account that you can't apply host/path-based routing. So make sure your myappp VirtualService is the only service that serves that port.
Related
I am trying to set up istio virtual service along with the gateway but somehow it's not working.
Here is my gateway configuration
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: nginx-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
name: admin
number: 9999
protocol: HTTP
hosts:
- nginx.example.com
Virtual service
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx-virtualservice
spec:
gateways:
- nginx-gateway
hosts:
- nginx.example.com
http:
- match:
- port: 9999
route:
- destination:
host: nginx
port:
number: 80
However it works only for port 80 and `443 but not for other ports.
Most likely, when you created the istio-ingressgateway, you used the default values, so only port 80 and 443 are opened.
Look at the ingressgateway service/deployment and open the port 9999, you can add it in the operator.
Right now you have the Gateway listening to the port 9999 but probably the traffic can't go through it.
I followed the example mentioned in Istio setup (in docker desktop)
here. I am not able to connect to service.
URL I am trying:
curl -s -I "http://localhost:80/status/200"
Below is the Virtual service and gateway for above example mentioned in link:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway # use Istio default gateway implementation
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "*"
gateways:
- httpbin-gateway
http:
- match:
- uri:
prefix: /status
route:
- destination:
port:
number: 8000
host: httpbin
>kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.110.230.106 localhost 15021:32117/TCP,80:32577/TCP,443:32202/TCP 5d15h
>curl -s -I "localhost:80/status/200" -v
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> HEAD /status/200 HTTP/1.1
> Host: localhost
> User-Agent: curl/7.55.1
> Accept: */*
>
* Empty reply from server
* Connection #0 to host localhost left intact
I've followed the entire subject of Using an External HTTPS Proxy that pointed out that it's a VIP based example not k8s service approach. But in my case Squid is accessible via k8s service and I would like to use FQDN not VIP address.
I've changed the config removing addresses part:
Squid Istio Service Entry:
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
name: proxy
spec:
hosts:
- squid.external.svc.cluster.local
location: MESH_EXTERNAL
exportTo:
- "."
ports:
- number: 3128
name: tcp
protocol: TCP
Mesh External Squid parts in external ns:
Squid Pod:
ports:
- containerPort: 3128
name: http
protocol: TCP
Squid k8s Service:
ports:
- name: http
port: 3128
protocol: TCP
targetPort: http
Curling from sleep cointaner:
HTTPS_PROXY=http://squid.external:3128 curl https://en.wikipedia.org/wiki/Main_Page
gives the result on the sleep sidecar:
[2021-07-21T06:46:23.938Z] "CONNECT - HTTP/1.1" 404 NR route_not_found - "-" 0 0 0 - "-" "curl/7.77.0-DEV" "424a0870-af92-4a59-a3af-c8dc91b31512" "en.wikipedia.org:443" "-" - - 192.168.101.185:3128 10.10.2.8:39744 - -
where 192.168.101.185 is the squid service IP.
Envoy error says that there is no route, but it found the service. What is missing and what is wrong? I appreciate any help or suggestion.
I've struggled with that until I found CONNECT - HTTP/1.1" 404 NR route_not_found. And finally I've solved that issue by bypassing istio sidecar for my outbound traffic on SQUID port:
Sample proxy client POD with istio sidecar:
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb
spec:
replicas: 1
selector:
matchLabels:
app: deb
template:
metadata:
labels:
app: deb
annotations:
traffic.sidecar.istio.io/excludeOutboundPorts: '3128' # A comma separated list of outbound ports to be excluded from redirection to Envoy.
spec:
terminationGracePeriodSeconds: 0
containers:
- name: debian
image: debian:buster
command: ["/bin/sleep", "3650d"]
imagePullPolicy: IfNotPresent
Now I can use my private k8s proxy without adding any ServiceEntry with IP addresses.
$ HTTPS_PROXY=squid.external:3128 curl https://something
Of course I cannot track my outbound traffic to that proxy in istio-sider.
Following this doc I got istio-ingressgateway running but using curl to test the URL I am facing this problem:
curl: (7) Failed to connect to httpbin.example.com port 31390: Connection refused
This is the Gateway:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mygateway
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: httpbin-credential # must be the same as secret
hosts:
- httpbin.example.com
and the virtual service:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- "httpbin.example.com"
gateways:
- mygateway
http:
- match:
- uri:
prefix: /status
- uri:
prefix: /delay
route:
- destination:
port:
number: 8000
host: httpbin
I am using istio 1.5.4.
This is the command that result in timeout:
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" --cacert example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
What Version of Istio and Kubernetes are you using, where did you get Istio from, Installation details
istioctl version
Version: 0.8.0
GitRevision: 6f9f420f0c7119ff4fa6a1966a6f6d89b1b4db84
User: root#48d5ddfd72da
Hub: docker.io/istio
GolangVersion: go1.10.1
BuildStatus: Clean
kubectl version
Client Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.7", GitCommit:"dd5e1a2978fd0b97d9b78e1564398aeea7e7fe92", GitTreeState:"clean", BuildDate:"2018-04-19T00:05:56Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"9", GitVersion:"v1.9.1", GitCommit:"3a1c9449a956b6026f075fa3134ff92f7d55f812", GitTreeState:"clean", BuildDate:"2018-01-04T11:40:06Z", GoVersion:"go1.9.2", Compiler
Is Istio Auth enabled or not ?
Auth is not enabled, I used istio-demo.yaml to install istio
What happened:
I tried to use the external example (ServiceEntry):
cat <<EOF | istioctl create -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-ext
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
EOF
cat <<EOF | istioctl create -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: google-ext
spec:
hosts:
- www.google.com
ports:
- number: 443
name: https
protocol: HTTPS
EOF
I keep getting errors when I try to curl from the sleep pod:
root#sleep-6ccf857cc6-b9jh4:/# curl http://httpbin.org/headers -I
HTTP/1.1 503 Service Unavailable
content-length: 19
content-type: text/plain
date: Thu, 14 Jun 2018 10:40:20 GMT
server: envoy
root#sleep-6ccf857cc6-b9jh4:/# curl -I https://www.google.com
curl: (35) Unknown SSL protocol error in connection to www.google.com:443
Some log output from the istio proxy sidecar of the sleep pod:
[2018-06-14 11:00:39.419][14][info][upstream] external/envoy/source/server/lds_api.cc:60] lds: add/update listener 'tcp_0.0.0.0_443'
[2018-06-14T11:00:37.373Z] "HEAD /headers HTTP/1.1" 503 UH 0 19 0 - "-" "curl/7.35.0" "d06828ed-7fd6-9383-adad-170177b00427" "httpbin.org" "-"
[2018-06-14 11:01:40.298][14][info][upstream] external/envoy/source/common/upstream/cluster_manager_impl.cc:388] add/update cluster out.www.google.com|https starting warming
[2018-06-14 11:01:40.299][14][info][upstream] external/envoy/source/common/upstream/cluster_manager_impl.cc:395] warming cluster out.www.google.com|https complete
Am running this on AWS, but was able to fix this with help from the istio/github/issues page...
Had to add RESOLUTION: DNS to the serviceentry
cat <<EOF | istioctl create -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: httpbin-ext
spec:
hosts:
- httpbin.org
ports:
- number: 80
name: http
protocol: HTTP
resolution: DNS
EOF
cat <<EOF | istioctl create -f -
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: google-ext
spec:
hosts:
- www.google.com
ports:
- number: 443
name: https
protocol: HTTPS
resolution: DNS
EOF
Link is:
https://github.com/istio/old_issues_repo/issues/392