I am trying to understand the Istio traffic routing. I installed Istio in demo mode and got to playing around with the samples. The samples have you install a few gateways (I did bookinfo-gateway and httpbin-gateway.
But it seems all my traffic goes through the "http2" port defined in istio-ingressgateway in the istio-system namespace.
The documentation makes reference to this:
Istio provides some preconfigured gateway proxy deployments (istio-ingressgateway and istio-egressgateway) that you can use - both are deployed if you use our demo installation
But when I run: kubectl -n istio-system get service istio-ingressgateway -o yaml the result shows kind: Service.
The other gateways the demos had me made show kind: Gateway.
So I am left confused...
Is there a difference between a service and a gateway?
How would I use the sample application gateways instead of the istio-ingressgateway (that is really a service).
How does istio connect my VirtualService to the istio-ingressgateway. Is it just looking for all VirtualServices?
Is there a difference between a service and a gateway?
Yes.
The istio-ingressgateway is a kubernetes service of type LoadBalancer (or NodePort, depending on your setup) that serves as the entry point into your cluster. The ingressgateway is the ingress controller of istio and it is completely optional.
The gateway is a custom resource of istio, that serves as an entry into your mesh. It is bound to an ingressgateway by the selector, eg see https://github.com/istio/istio/blob/master/samples/httpbin/httpbin-gateway.yaml
kind: Gateway
[...]
spec:
selector:
istio: ingressgateway
How would I use the sample application gateways instead of the istio-ingressgateway (that is really a service).
You need both (or another form of ingress controller and route all traffic through the mesh gateway, more on that see below).
How does istio connect my VirtualService to the istio-ingressgateway. Is it just looking for all VirtualServices?
See this yaml file again: https://github.com/istio/istio/blob/master/samples/httpbin/httpbin-gateway.yaml
The gateway is bound to the ingressgateway.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway
[...]
A VirtualService like the one in the file is bound to a gateway.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
gateways:
- httpbin-gateway
[...]
So if the traffic uses your gateway the VirtualService is considered.
Beside the gateways you configure, there is always the mesh gateway. So if you want your internal cluster traffic to use the istio configuration, you need to either add the mesh gateway to your virutal service:
gateways:
- httpbin-gateway
- mesh
or create a separat virutal service for that. If you don't set any gateway, mesh gateway will be used, since it is the default.
See: https://istio.io/latest/docs/reference/config/networking/virtual-service/#VirtualService -> the gateways entry
Related
I deployed Istio using the operator and added a custom ingress gateway which is only accessible from a certain source range (our VPN).
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
namespace: istio-system
name: ground-zero-ingressgateway
spec:
profile: empty
components:
ingressGateways:
- name: istio-ingressgateway
enabled: true
- name: istio-vpn-ingressgateway
label:
app: istio-vpn-ingressgateway
istio: vpn-ingressgateway
enabled: true
k8s:
serviceAnnotations:
...
service:
loadBalancerSourceRanges:
- "x.x.x.x/x"
Now I want to configure Istio to expose a service outside of the service mesh cluster, using the Kubernetes Ingress resource. I use the kubernetes.io/ingress.class annotation to tell the Istio gateway controller that it should handle this Ingress.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
annotations:
kubernetes.io/ingress.class: istio
spec:
...
Kubernetes version (EKS): 1.19
Istio version: 1.10.3
Which ingress gateway controller is now used (istio-ingressgateway or istio-vpn-ingressgateway)? Is there a way to specify which one should be used?
P.S. I know that I could create a VirtualService and specify the correct gateway but we want to write a manifest that also works without Istio by specifying the correct ingress controller with an annotation.
You can create an ingress class that references the ingress controller that is deployed by default in the istio-system namespace. This configuration with ingress will work, however to my current knowledge, this is only used for backwards compatibility. If you want to use istio ingress controller functionality, you should use istio gateway and virtual service instead:
Using the Istio Gateway, rather than Ingress, is recommended to make use of the full feature set that Istio offers, such as rich traffic management and security features.
If this solution is not optimal for you, you should use e.g. nginx ingress controller and you can still bind it with annotations (deprecated) or using IngressClass. To my present knowledge it is not possible to bind this ingress class with an additional ingress controller. If you need an explanation, documentation, you should create an issue on github.
Summary: The recommended option is to use the gateway with virtual service. Another possibility is to use nginx alone ingress with different classes and an ingress resource for them.
I am defining canary routes in mesh-virtual-service and wondering whether I can make it applicable for ingress traffic (with ingress-virtual-service) as well. With something like below, but it does not work (all traffic from ingress is going to non-canary version)
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-deployment-app
namespace: test-ns
spec:
gateways:
- mesh
hosts:
- test-deployment-app.test-ns.svc.cluster.local
http:
- name: canary
match:
- headers:
x-canary:
exact: "true"
- port: 8080
headers:
response:
set:
x-canary: "true"
route:
- destination:
host: test-deployment-app-canary.test-ns.svc.cluster.local
port:
number: 8080
weight: 100
- name: stable
route:
- destination:
host: test-deployment-app.test-ns.svc.cluster.local
port:
number: 8080
weight: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: test-deployment-app-internal
namespace: test-ns
spec:
gateways:
- istio-system/default-gateway
hosts:
- myapp.dev.bla
http:
- name: default
route:
- destination:
host: test-deployment-app.test-ns.svc.cluster.local
port:
number: 8080
weight: 100
So I am expecting x-canary:true response header when I call myapp.dev.bla but I don't see that.
Well the answer is only partially inside the link you included. I think the essential thing to realize when working with Istio 'what even is Istio Service Mesh'. Service mesh is every pod with Istio envoy-proxy sidecar + all the gateways (gateway is standalone envoy-proxy). They all know about each other because of IstioD so they can cooperate.
Any pod without Istio sidecar (including ingress pods or i.e. kube-system pods) in your k8s cluster doesn't know anything about Istio or Service Mesh. If such pod wants to send traffic to Service Mesh (to apply some Traffic Management rules like you have) must send it through Istio Gateway. Gateway is object that creates standard deployment + service. Pods in the deployment consist standalone envoy-proxy container.
Gateway object is a very similar concept to k8s ingress. But it doesn't have to listen on nodePort necessarily. You can use it also as an 'internal' gateway. Gateway serves as entry point into your service mesh. Either for external or even internal traffic.
If you're using i.e. Nginx as the Ingress solution you must reconfigure the Ingress rule to send traffic to one of the gateways instead of the target service. Most likely to your mesh gateway. It's nothing else than k8s Service inside istio-gateway or istio-system namespace
Alternatively you can configure Istio Gateway as 'new' Ingress. As I'm not sure if some default Istio Gateway listens on nodePort you need to check it (again in istio-gateway or istio-system namespace. Alternatively you can create new Gateway just for your application and apply VirtualService to the new gateway as well.
As I understand, Istio VirtualService is kind of abstract thing, which tries to add an interface to the actual implementation like the service in Kubernetes or something similar in Consul.
When use Kubernetes as the underlying platform for Istio, is there any difference between Istio VirtualService and Kubernetes Service or are they the same?
Kubernetes service
Kubernetes service manage a pod's networking. It specifies whether your pods are exposed internally (ClusterIP), externally (NodePort or LoadBalancer) or as a CNAME of other DNS entries (externalName).
As an example this foo-service will expose the pods with label app: foo. Any requests sent to the node on port 30007 will be forwarded to the pod on port 80.
apiVersion: v1
kind: Service
metadata:
name: foo-service
spec:
type: NodePort
selector:
app: foo
ports:
- port: 80
targetPort: 80
nodePort: 30007
Istio virtualservice
Istio virtualservice is one level higher than Kuberenetes service. It can be used to apply traffic routing, fault injection, retries and many other configurations to services.
As an example this foo-retry-virtualservice will retry 3 times with a timeout 2s each for failed requests to foo.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: foo-retry-virtualservice
spec:
hosts:
- foo
http:
- route:
- destination:
host: foo
retries:
attempts: 3
perTryTimeout: 2s
Another example of this foo-delay-virtualservice will apply a 0.5s delay to 0.1% of requests to foo.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: foo-delay-virtualservice
spec:
hosts:
- foo
http:
- fault:
delay:
percentage:
value: 0.1
fixedDelay: 5s
route:
- destination:
host: foo
Ref
https://kubernetes.io/docs/concepts/services-networking/service/
https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/
https://istio.io/latest/docs/reference/config/networking/virtual-service/
https://istio.io/latest/docs/concepts/traffic-management/#virtual-services
Istio's VirtualServices provides, as every Istio's extensions, some additionals features such as external traffic routing/management (Pod to external communication, HTTPS external communication, routing, url rewriting...).
Take a look at this doc about it for more details : https://istio.io/docs/reference/config/networking/virtual-service
They can be both useful, as you need "classic" Services to manage ingress traffic or service-to-service communication.
Virtual Service:
It defines a set of traffic routing rules to apply to a kubernetes service or subset of service based on the matching criteria. This is something similar to kubernetes Ingress object. It plays a key role on Istio's traffic management flexible and powerful.
Kubernetes Service:
It can be a logical set of pods and defined as an abstraction on top of pods which provides single DNS name or IP.
I have configured istio ingress with lets encrypt certificate.
I am able to access different service on https which are running on different port by using gateways and virtualservice.
But kubernetes-dashboard run on 443 port in kube-system namespace and with its own certificate, How i can expose it through istio gateways and virtualservice.
I have defined sub domain for dashboard and created gateways,virtualservice and it was directing 443 trafic to kuberentes dashboard service , but its not working.
for https virtual service config i have taken reference from for istio doc
It sounds like you want to configure an ingress gateway to perform SNI passthrough instead of TLS termination. You can do this by setting the tls mode in your Gateway configuration to PASSTHROUGH something like this:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: dashboard
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 443
name: https-dashboard
protocol: HTTPS
tls:
mode: PASSTHROUGH
hosts:
- dashboard.example.com
A complete passthrough example can be found here.
I have a setup of kubernetes on a coreos baremetal.
For now I did the connection from outside world to service with a nginx reverse-proxy.
I'm trying the new Ingress resource.
for now I have added a simple ingress:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kube-ui
spec:
backend:
serviceName: kube-ui
servicePort: 80
that starts like this:
INGRESS
NAME RULE BACKEND ADDRESS
kube-ui - kube-ui:80
My question is how to connect from the outside internet to that ingress point as this resource have no ADDRESS ... ?
POSTing this to the API server will have no effect if you have not configured an Ingress controller. You need to choose the ingress controller implementation that is the best fit for your cluster, or implement one. Examples and instructions can be found here.
check this gist
This is for the ingress-nginx, not kubernetes-ingress
Pre-requirement
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml
Exposing hostNetwork (hope you know what you are doing. As documented, other than this, you can use nodePort or loadbalancer.)
kubectl edit deployment.apps/nginx-ingress-controller -n ingress-nginx
add
template:
spec:
hostNetwork: true
port forwarding
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-services
namespace: ingress-nginx
data:
9000: "default/example-go:8080"
Also, you can use ingress object to expose the service