docker desktop之Istio初体验中完成集群内部基础组件部署之后,我们有了大概的认知。其中关于如何将服务对外暴露并没有明细说明太多,此篇补充下如何对外开放应用服务

对外开放应用程序

此时我们查看如下:

1
2
3
4
5
6
7
8
9
10
11
~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  kubectl get pods                                                ✔  18:28:42
NAME READY STATUS RESTARTS AGE
details-v1-79c697d759-smfhp 2/2 Running 0 5m56s
productpage-v1-65576bb7bf-k6797 2/2 Running 0 5m54s
ratings-v1-7d99676f7f-xjr74 2/2 Running 0 5m55s
reviews-v1-987d495c-2hqcg 2/2 Running 0 5m55s
reviews-v2-6c5bf657cf-s4db5 2/2 Running 0 5m56s
reviews-v3-5f7b9f4f77-7rt5t 2/2 Running 0 5m55s
~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  kubectl exec "$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')" -c ratings -- curl -s productpage:9080/productpage | grep -o "<title>.*</title>"

<title>Simple Bookstore App</title>

确保服务状态都是正常的。

此时,BookInfo 应用已经部署,但还不能被外界访问。 要开放访问,你需要创建 Istio 入站网关(Ingress Gateway, 它会在网格边缘把一个路径映射到路由。

如对基础概念还不清楚的,可以参考Istio-文档-概念

  1. 把应用关联到Istio网关:
    先看下 bookinfo-gateway.yaml 中内容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
    name: bookinfo-gateway
    spec:
    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
    1
    2
    3
     ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml 
    gateway.networking.istio.io/bookinfo-gateway created
    virtualservice.networking.istio.io/bookinfo created
  2. 确保配置文件没有问题:
    1
    2
     ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  istioctl analyze                                                ✔  18:43:44
    ✔ No validation issues found when analyzing namespace: default.

    确定入站 IP 和端口

    为访问网关设置两个变量:INGRESS_HOSTINGRESS_PORT。*由于我的环境是Mac,通过docker desktop部署的k8s*,所以如下的为此环境的处理方式。

执行下面命令进行判断:你的 Kubernetes 集群环境是否支持外部负载均衡:

1
2
3
4
 ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  kubectl get svc istio-ingressgateway -n istio-system                                                   ✔  18:50:32

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.106.247.46 localhost 15021:30307/TCP,80:30353/TCP,443:30695/TCP,31400:30328/TCP,15443:32035/TCP 28m

设置 EXTERNAL-IP 的值之后, 你的环境就有了一个外部的负载均衡,可以用它做入站网关。 但如果 EXTERNAL-IP 的值为 <none> (或者一直是 <pending> 状态), 则你的环境则没有提供可作为入站流量网关的外部负载均衡。 这个情况,你还可以用服务(Service)的 节点端口 访问网关。

  • 由于我的环境中确实存在外部的负载均衡,那么继续往下走。
    设置入站 IP 地址和端口

    1
    2
    3
    4
    5
    ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 

    ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')

    ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')

    在某些环境中,负载均衡除了 IP 地址,还可以用主机名访问。 在这种情况下,入站流量网关的EXTERNAL-IP 值不是 IP 地址,而是一个主机名, 那上面设置 INGRESS_HOST 环境变量的操作会失败。 使用下面命令纠正 INGRESS_HOST 的值。我的环境是出现这样的情况

    1
    >$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
  • 如果没有负载均衡,那就选择一个节点端口来代替
    设置入站的端口:

    1
    2
    $ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
    $ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')

GKE:

1
$ export INGRESS_HOST=workerNodeAddress

你需要创建一个防火墙规则,放行发往 ingressgatewayTCP 流量。 再运行下面的命令,单独放行发往 HTTP 端口或 HTTPS 端口的流量,或者都放行。

1
2
$ gcloud compute firewall-rules create allow-gateway-http --allow "tcp:$INGRESS_PORT"
$ gcloud compute firewall-rules create allow-gateway-https --allow "tcp:$SECURE_INGRESS_PORT"

IBM Cloud Kubernetes Service:

1
2
$ ibmcloud ks workers --cluster cluster-name-or-id
$ export INGRESS_HOST=public-IP-of-one-of-the-worker-nodes

Docker For Desktop:

1
$ export INGRESS_HOST=127.0.0.1

Other environments:

1
$ export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
  1. 设置环境变量 GATEWAY_URL
    1
    ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT                                                         ✔  18:54:31
  2. 确保 IP地址和端口均成功的赋值给了环境变量:
    1
    2
     ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  echo $GATEWAY_URL                                                                                      ✔  19:03:53
    localhost:80

    验证外部访问

    用浏览器查看 Bookinfo 应用的产品页面,验证 Bookinfo 已经实现了外部访问。
  3. 运行下面命令,获取 Bookinfo 应用的外部访问地址。
    1
    2
     ~/Documents/Opts/k8s/addons/istio-1.8.1/v1.8.1  echo "http://$GATEWAY_URL/productpage"                                                                 ✔  19:03:58
    http://localhost:80/productpage
  4. 把上面命令的输出地址复制粘贴到浏览器并访问,确认 Bookinfo 应用的产品页面是否可以打开。
    bookinfo

至此结束,后续继续更新Istio相关文章。

参考入门