Published on

Microsoft Hyper-V Server - Cài đặt Istio service mesh trên K8s cluster

Ở bài viết trước mình đã triển trình bày cách mà mình thiết lập NGINX Ingress và MetalLB trên cluster. Bên cạnh đó, mình cũng đã cài đặt 1 Reverse Proxy trên host computer (Hyper-V Server) làm nhiệm vụ điều hướng request đến các dịch vụ khác nằm ngoài K8s cluster.

Trong viết này mình sẽ giới thiệu cách cài đặt Istio mesh server trên Kubernetes cluster.

HMicrosoft Hyper-V server

Cài đặt Istio service mesh

Invoke-WebRequest -Uri 'https://github.com/istio/istio/releases/download/1.11.1/istio-1.11.1-win.zip' -OutFile 'C:\istio.zip'
Expand-Archive -LiteralPath 'C:\istio.zip' -DestinationPath C:\
Remove-Item 'C:\istio.zip'

Thêm thư mục C:\istio-1.11.1\bin vào PATH environment để powershell có thể sử dụng command istioctl

$oldPath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
$newPath = "$oldPath;C:\istio-1.11.1\bin"
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")

Cài đặt Istio với profile demo

istioctl install --set profile=demo -y
kubectl label namespace default istio-injection=enabled

Cài đặt một số Dashboard dùng để quản lý Istio:

cd C:\istio-1.11.1
kubectl apply -f samples/addons

Thiết lập Nodeport services

Deploy NodePort service cho phép truy xuất vào các ứng dụng trong cluster. Dưới đây là nội dung file istio-services-node-port.yaml

#Grafana
apiVersion: v1
kind: Service
metadata:
  labels:
    app: grafana
    release: istio
  name: grafana-np
  namespace: istio-system
spec:
  ports:
    - name: http
      nodePort: 32493
      port: 3000
      protocol: TCP
      targetPort: 3000
  selector:
    app: grafana
  sessionAffinity: None
  type: NodePort
---
#prometheus
apiVersion: v1
kind: Service
metadata:
  labels:
    app: prometheus
    release: istio
  name: prometheus-np
  namespace: istio-system
spec:
  ports:
    - name: http
      nodePort: 32494
      port: 9090
      protocol: TCP
      targetPort: 9090
  selector:
    app: prometheus
  sessionAffinity: None
  type: NodePort
---
#jaeger
apiVersion: v1
kind: Service
metadata:
  labels:
    app: jaeger
    release: istio
  name: tracing-np
  namespace: istio-system
spec:
  ports:
    - name: http-tracing
      nodePort: 32495
      port: 80
      protocol: TCP
      targetPort: 16686
  selector:
    app: jaeger
  sessionAffinity: None
  type: NodePort
---
#kiali
apiVersion: v1
kind: Service
metadata:
  labels:
    app: kiali
    release: istio
  name: kiali-np
  namespace: istio-system
spec:
  ports:
    - name: http-kiali
      nodePort: 32496
      port: 20001
      protocol: TCP
      targetPort: 20001
  selector:
    app: kiali
  sessionAffinity: None
  type: NodePort
kubectl apply -f istio-services-node-port.yaml

Add NetNatStaticMapping, điều này cho phép truy cập đến NodePort server từ máy tính khác

Add-NetNatStaticMapping -ExternalIPAddress "0.0.0.0/24" -ExternalPort 32493 -Protocol TCP -InternalIPAddress "10.10.0.10" -InternalPort 32493 -NatName KubeNatNet
Add-NetNatStaticMapping -ExternalIPAddress "0.0.0.0/24" -ExternalPort 32494 -Protocol TCP -InternalIPAddress "10.10.0.10" -InternalPort 32494 -NatName KubeNatNet
Add-NetNatStaticMapping -ExternalIPAddress "0.0.0.0/24" -ExternalPort 32495 -Protocol TCP -InternalIPAddress "10.10.0.10" -InternalPort 32495 -NatName KubeNatNet
Add-NetNatStaticMapping -ExternalIPAddress "0.0.0.0/24" -ExternalPort 32496 -Protocol TCP -InternalIPAddress "10.10.0.10" -InternalPort 32496 -NatName KubeNatNet

Đến đây có thể truy cập các dashboar lần lượt các địa chỉ: http://Hyper-V-local-ip:32493, http://Hyper-V-local-ip:32494, http://Hyper-V-local-ip:32495, http://Hyper-V-local-ip:32496

Hiện tại thì NGINX của host đang quản lý các request HTTP(s) đến cluster cũng như các service khác, điều này mình đã thực hiện ở các bài viết trước. Bây giờ mình sử dụng Istio để quản lý các request đến cluster, nên NGINX cần bàn giao lại cho Istio bằng cách dừng service đang chạy và xóa Firewall rule dành cho nó.

net stop nginx 2>&1 | % { $_.ToString() }
Remove-NetFirewallRule -DisplayName "Allow HTTP and HTTPs over Nginx"

Sau đó thêm Firewall rule để Istio quản lý các HTTP(s) request đến cluster

$INGRESS_HOST = (kubectl -n istio-system get service istio-ingressgateway -o json | ConvertFrom-Json).status.loadBalancer.ingress[0].ip
$INGRESS_PORT = ((kubectl -n istio-system get service istio-ingressgateway -o json | ConvertFrom-Json).spec.ports | where {
 $_.name -eq "http2" }).port
$SECURE_INGRESS_PORT = ((kubectl -n istio-system get service istio-ingressgateway -o json | ConvertFrom-Json).spec.ports | where {
 $_.name -eq "https" }).port
Add-NetNatStaticMapping -ExternalIPAddress "0.0.0.0/24" -ExternalPort 80 -Protocol TCP -InternalIPAddress "$INGRESS_HOST" -InternalPort $INGRESS_PORT -NatName KubeNatNet
Add-NetNatStaticMapping -ExternalIPAddress "0.0.0.0/24" -ExternalPort 443 -Protocol TCP -InternalIPAddress "$INGRESS_HOST" -InternalPort $SECURE_INGRESS_PORT -NatName KubeNatNet

Istio traffic split sample

Trong ví dụ này Istio sẽ điều phối các request tới 1 endpoint, 50% request sẽ điều hướng tới app apple, 50% request còn lại sẽ điều hướng tới app banana. Tỷ lệ này mình có thể cài đặt tùy ý.

apple.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apple-app
  labels:
    app: fruit
    name: apple
spec:
  selector:
    matchLabels:
      app: fruit
      name: apple
  template:
    metadata:
      labels:
        app: fruit
        name: apple
    spec:
      containers:
        - name: apple-app
          image: hashicorp/http-echo
          args:
            - '-text=apple'
          imagePullPolicy: Always
          ports:
            - containerPort: 5678

banana.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: banana-app
  labels:
    app: fruit
    name: banana
spec:
  selector:
    matchLabels:
      app: fruit
      name: banana
  template:
    metadata:
      labels:
        app: fruit
        name: banana
    spec:
      containers:
        - name: banana-app
          image: hashicorp/http-echo
          args:
            - '-text=banana'
          imagePullPolicy: Always
          ports:
            - containerPort: 5678

istio.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: fruit-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - 'fruits.adtsolutions.com.vn'
---
apiVersion: v1
kind: Service
metadata:
  name: fruit-service
  labels:
    app: fruit
spec:
  ports:
    - port: 5678
  selector:
    app: fruit
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: fruit-rule
spec:
  host: fruit-service
  subsets:
    - name: fruit-apple
      labels:
        name: apple
    - name: fruit-banana
      labels:
        name: banana
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: fruit-virtualservice
spec:
  hosts:
    - 'fruits.adtsolutions.com.vn'
  gateways:
    - fruit-gateway
  http:
    - match:
        - uri:
            prefix: /
      route:
        - destination:
            host: fruit-service #Name of the service
            subset: fruit-apple
          weight: 50
        - destination:
            host: fruit-service #Name of the service
            subset: fruit-banana
          weight: 50

Chạy các lệnh sau để deploy các resources:

kubectl create namespace example
kubectl label namespace example istio-injection=enabled
kubectl -n example apply -f apple.yaml
kubectl -n example apply -f banana.yaml
kubectl -n example apply -f istio.yaml

Chi tiết có thể theo dõi trong video này