Istio起步

下载

  • Istio releases页面 可以找到对应操作系统和架构的安装包文件,也可以直接通过以下命令下载:

下载Istio最新release版本
curl -L https://istio.io/downloadIstio | sh -

如果要指定版本和架构,例如 ARM Atlas ,则使用如下下载案例:

下载Istio的release 1.18.2 ARM版本
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.18.2 TARGET_ARCH=arm64 sh -
  • 按照安装脚本提示执行:

按照安装脚本设置环境变量并执行预检查
# 按照安装脚本提示
# 添加环境变量
export PATH="$PATH:/root/istio-1.18.2/bin"

# 预检查
istioctl x precheck

如果顺利,则提示信息:

按照安装脚本设置环境变量并执行预检查,提示信息
 No issues found when checking the cluster. Istio is safe to install or upgrade!
  To get started, check out https://istio.io/latest/docs/setup/getting-started/

安装

Istio提供了多个 Istio configuration profile ,对于生产环境建议使用 default ,对于测试环境,建议使用 demo (两者的差异是 demo 增加了安装 istio-egressgateway 组件,并且安装了 Istio Bookinfo案例应用 方便学习研究)

执行 istioctl install 安装 profile=demo
istioctl install --set profile=demo -y
  • 添加一个namespace label让istio自动注入Envoy sidecar proxy:

在默认namespace上标记 istio-injection=enabled 方便后续部署应用自动注入Envoy sidecar
kubectl label namespace default istio-injection=enabled

部署案例应用

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

输出显示:

部署 Istio Bookinfo案例应用 输出显示
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
检查服务输出
kubectl get services
检查服务输出
NAME          TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.233.60.17    <none>        9080/TCP   2m39s
kubernetes    ClusterIP   10.233.0.1      <none>        443/TCP    57d
productpage   ClusterIP   10.233.28.23    <none>        9080/TCP   2m38s
ratings       ClusterIP   10.233.46.200   <none>        9080/TCP   2m39s
reviews       ClusterIP   10.233.35.53    <none>        9080/TCP   2m38s
检查pods
kubectl get pods
检查pods
NAME                              READY   STATUS      RESTARTS   AGE
details-v1-6997d94bb9-vx6x6       2/2     Running     0          4m33s
productpage-v1-58b4c9bff8-478vf   2/2     Running     0          4m31s
ratings-v1-b8f8fcf49-xkpb4        2/2     Running     0          4m32s
reviews-v1-5896f547f5-qmsnb       2/2     Running     0          4m32s
reviews-v2-5d99885bc9-gbbhm       2/2     Running     0          4m32s
reviews-v3-589cb4d56c-tcftw       2/2     Running     0          4m32s
  • 执行以下命令可以检查应用是否正确运行(实际上就是通过在容器内部检查curl页面):

检查应用运行
kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -sS productpage:9080/productpage | grep -o "<title>.*</title>"

输出显示:

检查应用运行输出
<title>Simple Bookstore App</title>

这里我们简单解析一下案例 samples/bookinfo/networking/bookinfo-gateway.yaml :

部署Ingress的 bookinfo-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  # The selector matches the ingress gateway pod labels.
  # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

可以看到这是一个类似 Nginx反向代理 的配置( VirtualService )

  • 创建Istio gateway:

执行创建 Istio gateway: gateway (相当于声明反向代理对外服务端口) 以及 virtualservice (相当于配置反向代理)
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml

此时提示输出

执行创建 Istio gateway 的输出信息
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created

检测Ingress的IP和端口

  • 执行检查 Ingress 服务:

检查上文创建的名为 istio-ingressgateway 的service(svc)
kubectl get svc istio-ingressgateway -n istio-system

输出显示:

检查上文创建的名为 istio-ingressgateway 的service(svc): 输出显示 EXTERNAL-IP 没有分配
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                                                                      AGE
istio-ingressgateway   LoadBalancer   10.233.8.166   <pending>     15021:31210/TCP,80:31659/TCP,443:30721/TCP,31400:32337/TCP,15443:30050/TCP   6h28m

可以看到 EXTERNAL-IP 始终是 pending 状态,表示没有分配外部访问IP地址

这个 EXTERNAL-IP 是云计算厂商提供的负载均衡,因为 Kubernetes 设计架构就是部署在云计算厂商的环境,直接调用云厂商的负载均衡(LoadBalancer)的API接口来获得负载均衡外部访问IP地址。

对于个人部署的 Barmetal 裸金属服务器,需要部署 Kubernetes MetalLB 负载均衡 来实现云厂商提供的外部负载均衡功能: 在 istio 上部署Metallb

安装和配置 Kubernetes MetalLB 负载均衡

  • 按照 安装MetalLB 步骤完成 MetalLB 安装(这里步骤不再复述)

  • 创建 MetalLB 的IP资源池来对外提供服务:

创建 y-k8s-ip-pool.yaml 设置对外提供负载均衡服务的IP地址池
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: y-k8s-ip-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.8.151-192.168.8.198
  • 然后执行创建:

创建名为 y-k8s-ip-pool 的MetalLB地址池
kubectl create -f y-k8s-ip-pool.yaml
  • 一旦完成 MetalLB 的负载均衡服务的IP地址池,再次检查 Ingress 服务:

再次检查 istio-ingressgateway 的service(svc)
kubectl get svc istio-ingressgateway -n istio-system

Binggo ,现在可以看到对外服务的IP地址已经分配:

可以看到完成 MetalLB 地址池配置后, istio-ingressgateway 的service(svc) 正确获得了对外服务负载均衡IP
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)                                                                      AGE
istio-ingressgateway   LoadBalancer   10.233.8.166   192.168.8.151   15021:31210/TCP,80:31659/TCP,443:30721/TCP,31400:32337/TCP,15443:30050/TCP   24h

获得访问URL

  • 执行以下命令获得访问URL:

获取Ingress的IP和Port,拼接出访问URL
# 对于其他云环境,参考原文 https://istio.io/latest/docs/setup/getting-started/#determining-the-ingress-ip-and-ports

# Ingress host:
export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
# Ingress port:
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')

# 获得实际访问GATEWAY URL
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo "$GATEWAY_URL" 

按照上文实践,我获得的URL输出如下:

获取Ingress的IP和Port,拼接出访问URL
192.168.8.151:80

备注

上述访问URL是我部署 zcloud 的内部网络IP地址池,所以对外 public 网段不能直接访问。有两种简便方式:

  • 方法一: 通过 iptables 端口转发:

通过 iptables 端口转发实现访问内网 Kubernetes 的 Kubernetes MetalLB 负载均衡 输出入口
# 假设public接口IP地址是 10.10.1.111 (模拟对internet提供服务)
local_host=10.10.1.111
bookinfo_port=80

istio_bookinfo_host=192.168.8.151
istio_bookinfo_port=80

sudo iptables -t nat -D PREROUTING -p tcp --dport ${bookinfo_port} -j DNAT --to-destination ${istio_bookinfo_host}:${istio_bookinfo_port}
sudo iptables -t nat -D POSTROUTING -p tcp -d ${istio_bookinfo_host} --dport ${istio_bookinfo_port} -j SNAT --to-source ${local_host}

Dashboard

Istio提供了一个Dashboard来实现可观测性

  • 默认 kiali 采用了 ClusterIP ,所以外部无法访问,官方采用了 istioctl dashboard kiali 方式在 127.0.0.1 上开启 20001 端口访问(但是我是在服务器上部署,所以转换为 LoadBalancer 模式,结合 Kubernetes MetalLB 负载均衡 就非常容易实现访问)

  • 修改 kubectl -n istio-system edit svc kiali

    type: ClusterIP
    

改为:

type: LoadBalancer

此时 svc 从如下:

kiali                  ClusterIP      10.233.63.114   <none>          20001/TCP,9090/TCP                                                           15m

自动修改成:

kiali                  LoadBalancer   10.233.63.114   192.168.8.152   20001:32561/TCP,9090:32408/TCP                                               20m
  • 再次创建一个简单的端口转发脚本 iptables_port_forwarding_kiali :

通过 iptables 端口转发实现访问 kiali
local_host=10.1.1.111

kiali_port=20001

istio_kiali_host=192.168.8.152
istio_kiali_port=20001

sudo iptables -t nat -A PREROUTING -p tcp -d ${local_host} --dport ${kiali_port} -j DNAT --to-destination ${istio_kiali_host}:${istio_kiali_port}
sudo iptables -t nat -A POSTROUTING -p tcp -d ${istio_kiali_host} --dport ${istio_kiali_port} -j SNAT --to-source ${local_host}

则可以通过访问 http://10.1.1.111:20001/kiali 来访问 kiali 服务

此时就可以看到 kiali Dashboard:

../../_images/kiali_dashboard.png

简单使用

  • 点击 Graph 导航图标,然后在终端执行以下压测命令:

    for i in $(seq 1 10000); do curl -s -o /dev/null "http://$GATEWAY_URL/productpage"; done
    
  • 此时在 Graph 页面就会看到图形化流量演示:

../../_images/istio_graph_1.png

此时点击 Namespace Layout 2 kiali-breathfirst 按钮就会看到监控组件关系(注意需要选择 default namespace)

../../_images/istio_graph_2.png

此外点击某个链路还能看到详细流量分析

../../_images/istio_graph_3.png

备注

目前仅仅完成搭建,还有很多需要学习实践

参考