Kubernetes Services
External access by configure Ingress
Firstly, install nginx ingress:
minikube addons enable ingress
kubectl get all -n ingress-nginx
NAME READY STATUS RESTARTS AGE
pod/ingress-nginx-admission-create--1-6rs7v 0/1 Completed 0 14m
pod/ingress-nginx-admission-patch--1-qf2zd 0/1 Completed 1 14m
pod/ingress-nginx-controller-5f66978484-wtpph 1/1 Running 0 14m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ingress-nginx-controller NodePort 10.104.234.97 <none> 80:31300/TCP,443:30830/TCP 14m
service/ingress-nginx-controller-admission ClusterIP 10.109.145.221 <none> 443/TCP 14m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ingress-nginx-controller 1/1 1 1 14m
NAME DESIRED CURRENT READY AGE
replicaset.apps/ingress-nginx-controller-5f66978484 1 1 1 14m
NAME COMPLETIONS DURATION AGE
job.batch/ingress-nginx-admission-create 1/1 4s 14m
job.batch/ingress-nginx-admission-patch 1/1 5s 14m
Create kubia application:
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia-deployment
labels:
app: kubia
spec:
replicas: 1
selector:
matchLabels:
app: kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: luksa/kubia:latest
ports:
- containerPort: 8080
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: kubia-internal-service
spec:
# type default is ClusterIP
selector:
app: kubia
ports:
- protocol: TCP
port: 8080
targetPort: 8080
kubectl apply -f kubia.yaml
Create ingress for kubia-internal-service:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kubia-ingress
spec:
rules:
- host: kubia.example.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: kubia-internal-service
port:
number: 8080
kubectl apply -f ingress.yaml
Now we can list of ingress:
kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
kubia-ingress nginx kubia.example.com localhost 80 94s
The ADDRESS is localhost, this is the url that kubernetes control plane is running. In this case is minikube ip: 192.168.49.2.
Edit /etc/hosts file:
127.0.0.1 localhost
127.0.1.1 jump-windows
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# k8s
192.168.49.2 kubia.example.com
Go to your browser or use curl, we can access service through ingress:
curl kubia.example.com
You've hit kubia-deployment-7b895464d7-h8448
Configure TLS for Ingress
Firstly, we create the RSA private key:
openssl genrsa -out tls.key 2048
Next we will use the RSA private key to generate the certificate:
openssl req -new -x509 -key tls.key -days 360 -subj "/CN=kubia" -out tls.crt
Perform base64 encode for tls.key and tls.crt, then fill to yaml file:
cat tls.crt | base64 | tr -d "\n"
cat tls.key | base64 | tr -d "\n"
Create tls-secret.yaml save secret TLS:
apiVersion: v1
kind: Secret
metadata:
name: secret-tls
type: kubernetes.io/tls
data:
# the data is abbreviated in this example
tls.crt: |
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURBVENDQWVtZ0F3SUJBZ0lVUWw2eitJOUY4MmgwQThjbzUxVmJ5K2Vjay9nd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0VERU9NQXdHQTFVRUF3d0ZhM1ZpYVdFd0hoY05Nakl3TkRFd01UWXlOek0wV2hjTk1qTXdOREExTVRZeQpOek0wV2pBUU1RNHdEQVlEVlFRRERBVnJkV0pwWVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDCkFRb0NnZ0VCQU1DNURMa3JXMHhJWkVEUFE4N1RYdlMxU3M3UkJKWk9wZGlTcnlaSTFHb0s4cndZRTZQZ2pwM1MKaUNlQ3FHbWRWNGV1aGhmbjk5WGlEQVFYSjRlS1R5TDlndTdvV2M5ZFg4d25KR0tXSjVnRE8zTzFnUWNjcGRhSwppSWRyUTlyMXBPTkIrSjZnR0t6NUtucXpZK2wvL0NSSDU2M0FuZ1h2TWlvODVWTWNOd3ZOV09nVjBpNlRjSk1kCmE4aWk2YXhLQWcwMjlaWjFRRFFPTVhYR3ZNeFFzRkhUM045ZUthbDFKYlZRL2ZFUy9hOHNNbXFYN01ncE0wdkUKV2xLSzF1TjlzeWYyamtKQzlhd0Fac3hveDQxbjd0WENPdTJ5alVqTlQvWGNyU0hPbUtScXRqL215T096N1Myawp0VE5QckVBVWk1U3FNbjBTbG43UXVjVEdtUVIrdDNrQ0F3RUFBYU5UTUZFd0hRWURWUjBPQkJZRUZMZTYvbERqCmZSNk8yOXptTHlLc3hZQmxmb0FMTUI4R0ExVWRJd1FZTUJhQUZMZTYvbERqZlI2TzI5em1MeUtzeFlCbGZvQUwKTUE4R0ExVWRFd0VCL3dRRk1BTUJBZjh3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUgyTDh6S0dLUmZrdkMxNgplbW9ESE1jT0MxOEpiWmIzNG5yRDB0MWlleHp4MHJLNTFVRU5TZlJYK2E4Y3Vma2xFREROc0hUNnRHV2xEYmFECkhPeXRUZDNKcXg5bFJNMG1LK1pXZk1ITGNXQVF2bXZWcUNGa3NDcUhHc3ZTb1Q3WVY0OHBqcytpL1VsZnJPcE8KcmlNYk5tbTdHNkdqLzA4VkluTDdIVUZaQnNLdEovNkJ5WXJrR01LUHoyNjB5aHQ2TDJxaUx1NlRIbUN3eGV1YwpNd1J3bWN1ajlzQmFtL3JQOWJoTHJYcThuSUxCSUlEZmlIWE5zYXBnL1I0WGVlcDZaaG8yUDJlSmlHRE1udHRDCkVyVUtnT29IOWdHZmlrR2FiWHNQK0c2dkFFZk1FQXR3L09wVmZHTHNSZnZ1U1RQT0JTVXdkaThvcldUTDFvOVAKMVFjSVRVTT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
tls.key: |
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcFFJQkFBS0NBUUVBd0xrTXVTdGJURWhrUU05RHp0TmU5TFZLenRFRWxrNmwySkt2SmtqVWFncnl2QmdUCm8rQ09uZEtJSjRLb2FaMVhoNjZHRitmMzFlSU1CQmNuaDRwUEl2MkM3dWhaejExZnpDY2tZcFlubUFNN2M3V0IKQnh5bDFvcUloMnREMnZXazQwSDRucUFZclBrcWVyTmo2WC84SkVmbnJjQ2VCZTh5S2p6bFV4dzNDODFZNkJYUwpMcE53a3gxcnlLTHByRW9DRFRiMWxuVkFOQTR4ZGNhOHpGQ3dVZFBjMzE0cHFYVWx0VkQ5OFJMOXJ5d3lhcGZzCnlDa3pTOFJhVW9yVzQzMnpKL2FPUWtMMXJBQm16R2pIaldmdTFjSTY3YktOU00xUDlkeXRJYzZZcEdxMlArYkkKNDdQdExhUzFNMCtzUUJTTGxLb3lmUktXZnRDNXhNYVpCSDYzZVFJREFRQUJBb0lCQURzdkdPY3NsMmIvdkRuaQo3TEh4VzNITzB1QmNkQW9zc09XbmRqNU5rMTNWYXVHMGl5T0NiSW12QTcwT2RPV3FPaDBpelc4OS8zQWhjUXM0CmlSMG9ybERTaFlrVXRhL212dXFWQXFsNzcwRFJqVXBsYlBCZ0xkV0t5WTY4dENQajEvVXFaMDFmWVBTTnVDdmkKTjBhWDFUalhGQ0RaekMyS1hWOTNQLzJiNXBPcXZMRHRiWDhDRkYrcmloYnhGOEk5ZkhmdXBTYzFwQXNYWkNBQQoxRnNXZG83Nmk2YVBuL3ZuRU9kRG1KK09ZN3p5K01hM3E3alF3ajhFMmRkUFdDQkp1UE9yNzEzRGt1TXJUc3RTCjFMRVptWlIzckFJcytxbDI4U0ZVbkdiWHZHZjhSNDBkWnhsNkpzR09hS3d1VjNwck9zN2hUbW9leUhSYlk1V0cKNkV5TXp6a0NnWUVBKzFlSjdoTVR6eFhDVTAxTU5sMjFmYjU1cEpaNm55ZmFPMWI1bUhUR295dndrWEN0NFRUcwovb1plN0tzVUtJZFVmWDZ1OCs0Nms0VzNkZjBwVDZWR2ZHODdwWlBNVVJaMk53SmUzc3FMMnBBNHRzZXQ2N3Q0ClVlaGswdlJYRXRQQXV3SVBlbXhHMXI0Q0FMNFZsMFJOK29UQ1B4YmJrRlRVZ1FsdzUrS29TWU1DZ1lFQXhFdG0KVml4eVluUUZROW0wZk4vWndUZTZVMzZ2S0s3WXF3NHRVelAyejRwQ1RkWEhsREgrWEhtMDR1aFd3dVg0V1hHMwpvNHV5NTFBZmpjS1VJcFVyckgxa3RMWkM4T3RZYzlVY0dUTUZEYzhmNzI0R2dNRXU1c3dYWTJHS1RvbkJOcm8wCktLYmhlTEFpeW9HMGM0OEppS3BtYTYrRVdvSDFNM1EvOS9hWjlsTUNnWUVBMURCeklhcTVibnJRTThOdU0vZW8KNFIrTlVvWTN2MlhGdDVNVjVMK3hjdEFGcU1PWUNDakdhNXJGU01pbG5CR2tJczV3cFQ3WjlQRk9rUzNKVXBRVgpqYmZhZzA3amp4R0hlNmxrcm5JUTM5UWlEUzFHaDEwZGx3aTdGZDF5SlZMZnd3RmFUK0JaYmJHN3Z5UzYxWm0wCnUycVpFdW9aTXlCcXh3VlJiSExONEVFQ2dZRUFuVmhuTnNvNEFrMUg3eVJ5ZGVxbHpTalRsWndsNGJHT0FrZkIKODBEakpXZUpVSVQ5andBb0NZNlJmWldKL242Qy9ZZVhFV1NveXB4Q1BzcnJIWEYvYWF1MTd0bHVmVm5aTkRodQpacENzQzI2dEJhcW5VY3dJd1g1MWZQY3grMVNXNlR5SEZOTDRSMXJBK0p6UnZoTzVLN0NUbXR3OWRxTlhucUFmCnFxOGtxUHNDZ1lFQWcxQng5TksyVVVkZTgyaDZmZmFlWXROVDdXa1RXM2dvandFV2p3WXhzZVBVQ0Q1MWloVUEKYVQ0QVhvaWxsRys1Wnd3Q3Z4V0NYNE1kWTl5SDlVMng5SGhjS1QreCszZnp3NjNPN0g1ampjcHRXYVJhdlZadApsdUlEM1crVnpaL3ZvYnV2WUdScVc5NUhLbThRN2FuU283SzB2TkswUXZzYXJySjZ4c01rcW1FPQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
kubectl apply -f tls-secret.yaml
Now create Ingress with TLS:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-kubia-ingress
spec:
tls:
- hosts:
- kubia.example.com
secretName: secret-tls
rules:
- host: kubia.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: kubia-internal-service
port:
number: 8080
kubectl apply -f tls-ingress.yaml
kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
tls-kubia-ingress nginx kubia.example.com localhost 80, 443 17s
We can see the PORTS is 80, 443. Let’s use HTTPS to access your service through the Ingress:
curl -k -v https://kubia.example.com/kubia
* Trying 192.168.49.2:443...
* Connected to kubia.example.com (192.168.49.2) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2
* Server certificate:
* subject: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
* start date: Apr 10 14:38:48 2022 GMT
* expire date: Apr 10 14:38:48 2023 GMT
* issuer: O=Acme Co; CN=Kubernetes Ingress Controller Fake Certificate
* SSL certificate verify result: self signed certificate (18), continuing anyway.
* Using HTTP2, server supports multiplexing
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x560b8745fb10)
> GET /kubia HTTP/2
> Host: kubia.example.com
> user-agent: curl/7.81.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 200
< date: Sun, 10 Apr 2022 16:51:41 GMT
<
You've hit kubia-deployment-7b895464d7-h8448
* Connection #0 to host kubia.example.com left intact
Configure headless service
apiVersion: v1
kind: Service
metadata:
name: kubia-headless
spec:
selector:
app: kubia
clusterIP: None
ports:
- port: 80
targetPort: 8080
A headless service is a service with a service IP but instead of load-balancing it will return the IPs of our associated Pods. This allows us to interact directly with the Pods instead of a proxy.
Let’s list of service:
kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 73d
kubia-headless ClusterIP None <none> 80/TCP 33m
kubia-internal-service ClusterIP 10.96.220.32 <none> 8080/TCP 3h1m
Because headless service is connected to Pod’s IPs without proxy. If we exec to the pod, we can interact with headless service:
kubectl get pods
NAME READY STATUS RESTARTS AGE
kubia-deployment-7b895464d7-h8448 1/1 Running 0 3h5m
kubectl exec -it kubia-deployment-7b895464d7-h8448 -- bash
root@kubia-deployment-7b895464d7-h8448:/# curl kubia-headless:8080
You've hit kubia-deployment-7b895464d7-h8448
root@kubia-deployment-7b895464d7-h8448:/# curl kubia-internal-service:8080
Istio Service Mesh
Configure Istio for Kubernetes cluster
Firstly, starting your minikube cluster:
$ minikube start --memory=8192 --cpus=4
...
Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
To build service mesh for kubernetes cluster, we can use istio, let’s download istio from https://github.com/istio/istio/releases/ and extracting:
$ wget https://github.com/istio/istio/releases/download/1.12.7/istio-1.12.7-linux-amd64.tar.gz
$ tar zvxf istio-1.12.7-linux-amd64.tar.gz
Checking the binary istio:
$ cd istio-1.12.7 && ls
bin LICENSE manifests manifest.yaml README.md samples tools
$ export PATH=$PWD/bin:$PATH
$ istioctl
Istio configuration command line utility for service operators to
debug and diagnose their Istio mesh.
Usage:
istioctl [command]
Available Commands:
...
Flags:
...
Additional help topics:
istioctl options Displays istioctl global options
Use "istioctl [command] --help" for more information about a command.
If you have not installed istio:
$ kubectl get ns
NAME STATUS AGE
default Active 8m47s
kube-node-lease Active 8m50s
kube-public Active 8m50s
kube-system Active 8m50s
$ kubectl get pods
No resources found in default namespace.
Let’s install istio service mesh:
$ istioctl install
This will install the Istio 1.12.7 default profile with ["Istio core" "Istiod" "Ingress gateways"] components into the cluster. Proceed? (y/N) y
✔ Istio core installed
✔ Istiod installed- Processing resources for Ingress gateways. Waiting for Deployment/istio-system/istio-ingressgateway
✔ Ingress gateways installed
✔ Installation complete
Making this installation the default for injection and validation.
Now listing pods and namespace in kubernetes cluster:
$ kubectl get ns
NAME STATUS AGE
default Active 10m
istio-system Active 62s
kube-node-lease Active 10m
kube-public Active 10m
kube-system Active 10m
$ kubectl get pods -n istio-system
NAME READY STATUS RESTARTS AGE
istio-ingressgateway-5744ff657c-cb6z2 1/1 Running 0 42s
istiod-76f7bb65df-tcfvj 1/1 Running 0 66s
$ kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m
istio-system istio-ingressgateway LoadBalancer 10.111.182.40 <pending> 15021:31549/TCP,80:30496/TCP,443:32456/TCP 61s
istio-system istiod ClusterIP 10.103.110.234 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 86s
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 10m
We can get a list of the ports available with the istio-ingressgateway service using:
$ kubectl get svc istio-ingressgateway -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.111.182.40 <pending> 15021:31549/TCP,80:30496/TCP,443:32456/TCP 10m
$ kubectl describe svc istio-ingressgateway -n istio-system
Name: istio-ingressgateway
Namespace: istio-system
Labels: app=istio-ingressgateway
install.operator.istio.io/owning-resource=unknown
install.operator.istio.io/owning-resource-namespace=istio-system
istio=ingressgateway
istio.io/rev=default
operator.istio.io/component=IngressGateways
operator.istio.io/managed=Reconcile
operator.istio.io/version=1.12.7
release=istio
Annotations: <none>
Selector: app=istio-ingressgateway,istio=ingressgateway
Type: LoadBalancer
IP Family Policy: SingleStack
IP Families: IPv4
IP: 10.111.182.40
IPs: 10.111.182.40
Port: status-port 15021/TCP
TargetPort: 15021/TCP
NodePort: status-port 31549/TCP
Endpoints: 172.17.0.4:15021
Port: http2 80/TCP
TargetPort: 8080/TCP
NodePort: http2 30496/TCP
Endpoints: 172.17.0.4:8080
Port: https 443/TCP
TargetPort: 8443/TCP
NodePort: https 32456/TCP
Endpoints: 172.17.0.4:8443
Session Affinity: None
External Traffic Policy: Cluster
Events: <none>
The output here shows that the istio-ingressgateway service is forwarding requests from port 80 to port 30496 (http2).
The load balancer listener is set to listen on HTTP port 80, which is the port for the NGINX web server application used in the virtual service in this example.
Step 1: Create the namespace my-namespace and enable automatic proxy sidecar injection.
$ kubectl create ns my-namespace
namespace/my-namespace created
$ kubectl label ns my-namespace istio-injection=enabled
namespace/my-namespace labeled
$ kubectl get ns --show-labels
NAME STATUS AGE LABELS
default Active 60m kubernetes.io/metadata.name=default
istio-system Active 51m kubernetes.io/metadata.name=istio-system
kube-node-lease Active 60m kubernetes.io/metadata.name=kube-node-lease
kube-public Active 60m kubernetes.io/metadata.name=kube-public
kube-system Active 60m kubernetes.io/metadata.name=kube-system
my-namespace Active 30m istio-injection=enabled,kubernetes.io/metadata.name=my-namespace
Step 2: Create the NGINX deployment and NGINX service by create the manifest file nginx.yaml.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webserver
name: my-nginx
namespace: my-namespace
spec:
replicas: 3
selector:
matchLabels:
app: webserver
template:
metadata:
labels:
app: webserver
spec:
containers:
- image: nginx
name: my-nginx
ports:
- containerPort: 80 # matched targetPort
---
apiVersion: v1
kind: Service
metadata:
labels:
app: my-nginx
name: webserver
namespace: my-namespace
spec:
ports:
- name: http
port: 80
protocol: TCP
targetPort: 80 # matched containerPort
selector:
app: webserver
type: ClusterIP
$ kubectl apply -f nginx.yaml
deployment.apps/my-nginx created
service/webserver created
$ kubectl get deploy,svc,po -n my-namespace
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-nginx 3/3 3 3 19s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/webserver ClusterIP 10.96.221.204 <none> 80/TCP 19s
NAME READY STATUS RESTARTS AGE
pod/my-nginx-856fb4777f-7s67q 2/2 Running 0 19s
pod/my-nginx-856fb4777f-8bhj2 2/2 Running 0 19s
pod/my-nginx-856fb4777f-d77fs 2/2 Running 0 19s
We can see 2/2 in READY column, means that the pods have deployed with sidecar proxy. To validate this, we describe one of the pods:
$ kubectl describe pods my-nginx-856fb4777f-7s67q -n my-namespace
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 46s default-scheduler Successfully assigned my-namespace/my-nginx-856fb4777f-7s67q to minikube
Normal Pulled 45s kubelet Container image "docker.io/istio/proxyv2:1.12.7" already present on machine
Normal Created 45s kubelet Created container istio-init
Normal Started 45s kubelet Started container istio-init
Normal Pulling 45s kubelet Pulling image "nginx"
Normal Pulled 41s kubelet Successfully pulled image "nginx" in 3.441922626s
Normal Created 41s kubelet Created container my-nginx
Normal Started 41s kubelet Started container my-nginx
Normal Pulled 41s kubelet Container image "docker.io/istio/proxyv2:1.12.7" already present on machine
Normal Created 41s kubelet Created container istio-proxy
Normal Started 41s kubelet Started container istio-proxy
Warning Unhealthy 38s (x3 over 40s) kubelet Readiness probe failed: Get "http://172.17.0.5:15021/healthz/ready": dial tcp 172.17.0.5:15021: connect: connection refused
Because my environment does not provide an external load balancer for the ingress gateway, the connection refused to 172.17.0.5:15021. But don’t worry about it, we can access the gateway using the service’s node port (30496).
Step 3: Create an ingress gateway for the NGINX service by create the manifest file nginx-gateway.yaml.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: my-nginx-gateway
namespace: my-namespace
spec:
selector:
istio: ingressgateway # get from labels when describe istio-ingressgateway service
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "mynginx.example.com"
$ kubectl apply -f nginx-gateway.yaml
gateway.networking.istio.io/my-nginx-gateway created
$ kubectl get gateways.networking.istio.io -n my-namespace
NAME AGE
my-nginx-gateway 14m
Step 4: Create a virtual service for the ingress gateway by create the manifest file nginx-virtualservice.yaml.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-nginx-virtualservice
namespace: my-namespace
spec:
hosts:
- "mynginx.example.com"
gateways:
- my-nginx-gateway
http:
- match:
- uri:
prefix: /
route:
- destination:
port:
number: 80
host: webserver # matched .metadata.name in Service
$ kubectl apply -f nginx-virtualservice.yaml
virtualservice.networking.istio.io/my-nginx-virtualservice created
$ kubectl get virtualservices.networking.istio.io -n my-namespace
NAME GATEWAYS HOSTS AGE
my-nginx-virtualservice ["my-nginx-gateway"] ["mynginx.example.com"] 17s
To confirm the ingress gateway is serving the application to the load balancer, use:
$ minikube ip
192.168.49.2
$ kubectl describe svc istio-ingressgateway -n istio-system | grep http2
Port: http2 80/TCP
NodePort: http2 30496/TCP
$ curl -I -HHost:mynginx.example.com 192.168.49.2:30496
HTTP/1.1 200 OK
server: istio-envoy
date: Sun, 22 May 2022 13:07:54 GMT
content-type: text/html
content-length: 615
last-modified: Tue, 25 Jan 2022 15:03:52 GMT
etag: "61f01158-267"
accept-ranges: bytes
x-envoy-upstream-service-time: 17
To monitoring and data visualization, we can use kiali - an observability console for Istio with service mesh configuration and validation capabilities.
Istio provides a basic sample installation to quickly get Kiali up and running:
$ kubectl apply -f prometheus.yaml
serviceaccount/prometheus created
configmap/prometheus created
clusterrole.rbac.authorization.k8s.io/prometheus created
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
service/prometheus created
deployment.apps/prometheus created
$ kubectl apply -f kiali.yaml
serviceaccount/kiali created
configmap/kiali created
clusterrole.rbac.authorization.k8s.io/kiali-viewer created
clusterrole.rbac.authorization.k8s.io/kiali created
clusterrolebinding.rbac.authorization.k8s.io/kiali created
role.rbac.authorization.k8s.io/kiali-controlplane created
rolebinding.rbac.authorization.k8s.io/kiali-controlplane created
service/kiali created
deployment.apps/kiali created
$ kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.111.182.40 <pending> 15021:31549/TCP,80:30496/TCP,443:32456/TCP 4h34m
istiod ClusterIP 10.103.110.234 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 4h34m
kiali ClusterIP 10.100.112.235 <none> 20001/TCP,9090/TCP 8s
prometheus ClusterIP 10.110.80.171 <none> 9090/TCP 54s
Instead expose kiali service, we can forward port from kiali service to localhost by command line:
$ kubectl port-forward svc/kiali -n istio-system 20001
Forwarding from 127.0.0.1:20001 -> 20001
Forwarding from [::1]:20001 -> 20001
Then, access Kiali by visiting http://127.0.0.1:20001 in your preferred web browser.
You can get full source code here: service, istio-service-mesh.