单个网络网格中的虚拟机

此示例显示如何将 VM 或者本地裸机集成到 Kubernetes 上部署的单网络 Istio 网格中。

准备环境

  • 您已经在 Kubernetes 上部署了 Istio。如果尚未这样做,则可以在安装指南 中找到方法。

  • 虚拟机(VM)必须具有网格中 endpoint 的 IP 连接。这通常需要 VPC 或者 VPN,以及需要提供直接(没有 NAT 或者防火墙拒绝访问)路由到 endpoint 的容器网络。虚拟机不需要访问 Kubernetes 分配的集群 IP 地址。

  • VM 必须有权访问 DNS 服务, 将名称解析为集群 IP 地址。选项包括通过内部负载均衡器,使用 Core DNS 服务公开的 Kubernetes DNS 服务器,或者在可从 VM 中访问的任何其他 DNS 服务器中配置 IP。

具有以下说明:

  • 假设扩展 VM 运行在 GCE 上。
  • 使用 Google 平台的特定命令执行某些步骤。

安装步骤

安装并配置每个虚拟机,设置准备用于扩展的网格。

为虚拟机准备 Kubernetes 集群

当将非 Kubernetes 服务添加到 Istio 网格中时,首先配置 Istio 它自己的设施,并生成配置文件使 VM 连接网格。在具有集群管理员特权的计算机上,使用以下命令为 VM 准备集群:

  • 使用类似于以下的命令,为生成的 CA 证书创建 Kubernetes secret。请参阅证书办法机构 (CA) 证书 获取更多的详细信息。

样本目录中的 root 证书和中间证书已经大范围分发并被识别。不能 在生产环境中使用这些证书,否则您的集群容易受到安全漏洞和破坏的威胁。

ZipZipZipZip

  1. $ kubectl create namespace istio-system
  2. $ kubectl create secret generic cacerts -n istio-system \
  3. --from-file=@samples/certs/ca-cert.pem@ \
  4. --from-file=@samples/certs/ca-key.pem@ \
  5. --from-file=@samples/certs/root-cert.pem@ \
  6. --from-file=@samples/certs/cert-chain.pem@
  • 在集群中部署 Istio 控制平面:
  1. $ istioctl manifest apply \
  2. -f install/kubernetes/operator/examples/vm/values-istio-meshexpansion.yaml

有关更多的详细信息和自定义选项,请参阅安装说明

  • 定义 VM 加入的命名空间。本示例使用 SERVICE_NAMESPACE环境变量存储命名空间。此变量的值必须与稍后在配置文件中使用的命名空间相匹配。
  1. $ export SERVICE_NAMESPACE="default"
  • 确定并存储 Istio 入口网关的 IP 地址,因为 VMs 通过此 IP 地址访问 CitadelPilot
  1. $ export GWIP=$(kubectl get -n istio-system service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  2. $ echo $GWIP
  3. 35.232.112.158
  • 在 VM 中生成 cluster.env 配置并部署。该文件包含 Kubernetes 集群 IP 地址范围,可通过 Envoy 进行拦截和重定向。当您安装 Kubernetes 时,可以指定 CIDR 的范围为 servicesIpv4Cidr。在安装后,按照以下示例的命令,使用适当的值替换 $MY_ZONE$MY_PROJECT,以获取 CIDR:
  1. $ ISTIO_SERVICE_CIDR=$(gcloud container clusters describe $K8S_CLUSTER --zone $MY_ZONE --project $MY_PROJECT --format "value(servicesIpv4Cidr)")
  2. $ echo -e "ISTIO_CP_AUTH=MUTUAL_TLS\nISTIO_SERVICE_CIDR=$ISTIO_SERVICE_CIDR\n" > cluster.env
  • 检查生成文件 cluster.env 的内容。其内容应该与以下示例类似:
  1. $ cat cluster.env
  2. ISTIO_CP_AUTH=MUTUAL_TLS
  3. ISTIO_SERVICE_CIDR=10.55.240.0/20
  • 如果 VM 仅在网格中调用服务,您可以跳过这2一步骤。否则,使用以下命令为 VM 新增公开端口到 cluster.env 文件下。如有必要,您可以稍后更改端口。
  1. $ echo "ISTIO_INBOUND_PORTS=3306,8080" >> cluster.env
  • 提取服务帐户需要在 VM 上使用的初始密钥。
  1. $ kubectl -n $SERVICE_NAMESPACE get secret istio.default \
  2. -o jsonpath='{.data.root-cert\.pem}' |base64 --decode > root-cert.pem
  3. $ kubectl -n $SERVICE_NAMESPACE get secret istio.default \
  4. -o jsonpath='{.data.key\.pem}' |base64 --decode > key.pem
  5. $ kubectl -n $SERVICE_NAMESPACE get secret istio.default \
  6. -o jsonpath='{.data.cert-chain\.pem}' |base64 --decode > cert-chain.pem

设置 VM

下一步,将要加入网格的每台机器上运行以下命令:

  • 将之前创建的 cluster.env*.pem 文件复制到 VM 中。例如:
  1. $ export GCE_NAME="your-gce-instance"
  2. $ gcloud compute scp --project=${MY_PROJECT} --zone=${MY_ZONE} {key.pem,cert-chain.pem,cluster.env,root-cert.pem} ${GCE_NAME}:~
  • 使用 Envoy sidecar 安装 Debian 软件包。
  1. $ gcloud compute ssh --project=${MY_PROJECT} --zone=${MY_ZONE} "${GCE_NAME}"
  2. $ curl -L https://storage.googleapis.com/istio-release/releases/1.5.0/deb/istio-sidecar.deb > istio-sidecar.deb
  3. $ sudo dpkg -i istio-sidecar.deb
  • 将 Istio 的网关 IP 地址添加到 /etc/hosts。重新访问 集群准备 部分以了解如何获取 IP 地址。以下示例使用 Istio 网关地址修改 /etc/hosts 文件:
  1. $ echo "35.232.112.158 istio-citadel istio-pilot istio-pilot.istio-system" | sudo tee -a /etc/hosts
  • /etc/certs/ 下安装 root-cert.pemkey.pemcert-chain.pem
  1. $ sudo mkdir -p /etc/certs
  2. $ sudo cp {root-cert.pem,cert-chain.pem,key.pem} /etc/certs
  • /var/lib/istio/envoy/ 下安装 cluster.env
  1. $ sudo cp cluster.env /var/lib/istio/envoy
  • /etc/certs//var/lib/istio/envoy/ 中文件的所有权转交给 Istio proxy。
  1. $ sudo chown -R istio-proxy /etc/certs /var/lib/istio/envoy
  • 验证节点上的 agent 是否正常工作:
  1. $ sudo node_agent
  2. ....
  3. CSR is approved successfully. Will renew cert in 1079h59m59.84568493s
  • 使用 systemctl 启动 Istio:
  1. $ sudo systemctl start istio-auth-node-agent
  2. $ sudo systemctl start istio

将来自 VM 工作负载的请求发送到 Kubernetes 服务

设置完后,机器可以访问运行在 Kubernetes 集群上的服务,或者其他的 VM。

以下示例展示了使用 /etc/hosts/ 如何从 VM 中访问 Kubernetes 集群上运行的服务,这里使用 Bookinfo 示例 中的服务。

  • 首先,在集群管理机器上获取服务的虚拟 IP 地址(clusterIP):
  1. $ kubectl get svc productpage -o jsonpath='{.spec.clusterIP}'
  2. 10.55.246.247
  • 然后在新增的 VM 上,将服务名称和地址添加到其 etc/hosts 文件下。然后您可以从 VM 连接到集群服务,如以下示例:
  1. $ echo "10.55.246.247 productpage.default.svc.cluster.local" | sudo tee -a /etc/hosts
  2. $ curl -v productpage.default.svc.cluster.local:9080
  3. < HTTP/1.1 200 OK
  4. < content-type: text/html; charset=utf-8
  5. < content-length: 1836
  6. < server: envoy
  7. ... html content ...

server: envoy 标头指示 sidecar 拦截了流量。

在添加的 VM 中运行服务

  • 在 VM 实例上设置 HTTP 服务,以在端口 8080 上提供 HTTP 通信:
  1. $ gcloud compute ssh ${GCE_NAME}
  2. $ python -m SimpleHTTPServer 8080
  • 定义 VM 实例的 IP 地址。例如,使用以下命令查找 GCE 实例的 IP 地址:
  1. $ export GCE_IP=$(gcloud --format="value(networkInterfaces[0].networkIP)" compute instances describe ${GCE_NAME})
  2. $ echo ${GCE_IP}
  • 将 VM 服务添加到网格
  1. $ istioctl experimental add-to-mesh external-service vmhttp ${VM_IP} http:8080 -n ${SERVICE_NAMESPACE}

按照下载页面中的说明,确保已经将 istioctl 客户端添加到您的路径中。

  • 在 Kubernetes 集群中部署一个 pod 运行 sleep 服务,然后等待其准备就绪:

Zip

  1. $ kubectl apply -f @samples/sleep/sleep.yaml@
  2. $ kubectl get pod
  3. NAME READY STATUS RESTARTS AGE
  4. sleep-88ddbcfdd-rm42k 2/2 Running 0 1s
  5. ...
  • 将 pod 中 sleep 服务的请求发送到 VM 的 HTTP 服务:
  1. $ kubectl exec -it sleep-88ddbcfdd-rm42k -c sleep -- curl vmhttp.${SERVICE_NAMESPACE}.svc.cluster.local:8080

您应该看到类似于以下输出的内容:

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><html>
  2. <title>Directory listing for /</title>
  3. <body>
  4. <h2>Directory listing for /</h2>
  5. <hr>
  6. <ul>
  7. <li><a href=".bashrc">.bashrc</a></li>
  8. <li><a href=".ssh/">.ssh/</a></li>
  9. ...
  10. </body>

恭喜你! 您已经成功的配置了一个服务,使其运行在集群中的 pod 上,将其流量发送给集群之外在 VM 上运行的服务,并测试了配置是否有效。

清理

运行以下命令,从网格的抽象模型中删除扩展 VM:

  1. $ istioctl experimental remove-from-mesh -n ${SERVICE_NAMESPACE} vmhttp
  2. Kubernetes Service "vmhttp.vm" has been deleted for external service "vmhttp"
  3. Service Entry "mesh-expansion-vmhttp" has been deleted for external service "vmhttp"

故障排除

以下是一些常见的 VM 相关问题的基本故障排除步骤。

  • 从 VM 向群集发出请求时,请确保不要以 root 或者 istio-proxy 用户的身份运行请求。默认情况下,Istio 将这两个用户都排除在拦截范围之外。

  • 验证计算机是否可以达到集群中运行的所有工作负载的 IP。例如:

  1. $ kubectl get endpoints productpage -o jsonpath='{.subsets[0].addresses[0].ip}'
  2. 10.52.39.13
  1. $ curl 10.52.39.13:9080
  2. html output
  • 检查节点 agent 和 sidecar 的状态:
  1. $ sudo systemctl status istio-auth-node-agent
  2. $ sudo systemctl status istio
  • 检查进程是否正在运行。在 VM 上,您应该看到以下示例的进程,如果您运行了ps 过滤 istio
  1. $ ps aux | grep istio
  2. root 6941 0.0 0.2 75392 16820 ? Ssl 21:32 0:00 /usr/local/istio/bin/node_agent --logtostderr
  3. root 6955 0.0 0.0 49344 3048 ? Ss 21:32 0:00 su -s /bin/bash -c INSTANCE_IP=10.150.0.5 POD_NAME=demo-vm-1 POD_NAMESPACE=default exec /usr/local/bin/pilot-agent proxy > /var/log/istio/istio.log istio-proxy
  4. istio-p+ 7016 0.0 0.1 215172 12096 ? Ssl 21:32 0:00 /usr/local/bin/pilot-agent proxy
  5. istio-p+ 7094 4.0 0.3 69540 24800 ? Sl 21:32 0:37 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev1.json --restart-epoch 1 --drain-time-s 2 --parent-shutdown-time-s 3 --service-cluster istio-proxy --service-node sidecar~10.150.0.5~demo-vm-1.default~default.svc.cluster.local
  • 检查 Envoy 访问和错误日志:
  1. $ tail /var/log/istio/istio.log
  2. $ tail /var/log/istio/istio.err.log

相关内容

多网络网格中的虚拟机

学习怎样添加运行在虚拟机上的服务到您的多网络 Istio 网格中。

DNS 证书管理

在 Istio 中配置和管理 DNS 证书。

安全管理 Webhook

一种更安全管理 Istio webhook 的方法。

揭开 Istio Sidecar 注入模型的神秘面纱

揭秘 Istio 是如何将其数据平面组件添加到现有 deployment。

Docker Desktop

在 Docker Desktop 中运行 Istio 的设置说明。

Google Kubernetes Engine

在两个 GKE 集群上设置多集群网格。