istio在虚拟机vm下的安装方法

建议参考官方文档 https://istio.io/latest/zh/docs/setup/install/virtual-machine/ ,这里提醒大家对于命令中文版部分命令与英文版不一致,请以 英文版 为准。

对于istio在vm上的安装教程主要分为三部分。首先是在k8s的master节点生成vm连接主节点的一些配置信息,其实是在vm上应用这些配置信息,最后也就是验证连接是否成功。

本篇主要介绍“单网络”的情况, 对于”多网络“请自行参考官方文档。

vm环境准备

生成vm通讯配置信息

这里主要介绍一些新手迷惑的部分。如环境变量设置及vm注册的方式

设置环境变量

在设置变量时,对于”单网络“来讲 CLUSTER_NETWORK 和 VM_NETWORK 保留空值即可。如我这里设置如下

$ VM_APP="myapp"
$ VM_NAMESPACE="vm"
$ WORK_DIR="/root/myapp"
$ SERVICE_ACCOUNT="vm-sa"
$ CLUSTER_NETWORK=""
$ VM_NETWORK=""
$ CLUSTER="Kubernetes"

每个环境变量的解释:
VM_APP 表示vm上应用的名称
VM_NAMESPACE 表示应用所在的namespace
WORK_DIR 生成vm配置信息保留的目录,任何位置即可
SERVICE_ACCOUNT 服务运行的账号 ,即yaml文件中的 ServiceAccount 字段
CLUSTER 集群名称,默认为 Kubernetes 即可。

安装 Istio 控制平面

1 为安装创建 IstioOperator 空间

cat <<EOF > ./vm-cluster.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio
spec:
  meshConfig:
    accessLogFile: /dev/stdout
    enableTracing: true
    enableEnvoyAccessLogService: true
    defaultConfig.envoyAccessLogService.address: skywalking-oap.istio-system:11800
  values:
    global:
      meshID: mesh1
      multiCluster:
        clusterName: "${CLUSTER}"
      network: "${CLUSTER_NETWORK}"
EOF

spec.meshConfig.accessLogFile 表示启用日志功能,这样如果有流量经过envoy将在日志 /var/log/istio/istio.log 中输出;其余三个是启用skywaling链路追踪服务所需要的配置,如果不启用将其删除即可。

2 安装 Istio

对于vm要注册到集群中的方法,分为”手动注册”和”自动注册”两种。其中”自动注册”方式目前还处于实验阶段,这里为了方便我们使用自动注册方式。

$ istioctl install -f vm-cluster.yaml --set values.pilot.env.PILOT_ENABLE_WORKLOAD_ENTRY_AUTOREGISTRATION=true --set values.pilot.env.PILOT_ENABLE_WORKLOAD_ENTRY_HEALTHCHECKS=true

3 部署东西向网关:(单网络)

$ samples/multicluster/gen-eastwest-gateway.sh --single-cluster | istioctl install -y -f -

4 使用东西向网关暴露集群内部服务:(单网络)

$ kubectl apply -n istio-system -f samples/multicluster/expose-istiod.yaml

5 配置虚拟主机的 namespace 和 ServiceAccount

$ kubectl create namespace "${VM_NAMESPACE}"
$ kubectl create serviceaccount "${SERVICE_ACCOUNT}" -n "${VM_NAMESPACE}"

创建vm运行配置文件

对于vm要注册到集群中,分手动注册和自动注册。其中自动注册目前还处于实验阶段,这里为了方便我们使用自动注册。当虚拟机连接到 Istiod 时,会自动创建一个 workloadEntry。 这使得虚拟机成为 service 的一部分,类似于 Kubernetes 中的 endpoint。
这里的 WorkloadEntry 和 WorkloadGroup 他们分别对应的是k8s中的 POD 和 Deployment。

1 创建 WorkloadGroup 配置文件

cat <<EOF > workloadgroup.yaml
apiVersion: networking.istio.io/v1alpha3
kind: WorkloadGroup
metadata:
  name: "${VM_APP}"
  namespace: "${VM_NAMESPACE}"
spec:
  metadata:
    labels:
      app: "${VM_APP}"
  template:
    serviceAccount: "${SERVICE_ACCOUNT}"
    network: "${VM_NETWORK}"
EOF

2 将 WorkloadGroup 信息注册到集群中

$ kubectl --namespace "${VM_NAMESPACE}" apply -f workloadgroup.yaml

注意在配置 WorkloadGroup 的时候,不要使用探针这个例子,否则会导致通讯连接失败。

3 生成vm配置信息

$ istioctl x workload entry configure -f workloadgroup.yaml -o "${WORK_DIR}" --clusterID "${CLUSTER}" --autoregister

此时生成的vm配置信息将保存到环境变量 WORK_DIR 设置的目录。

建议了解一下生成的每一个配置文件内容,最好先看一下他们的内容,官方已对它们做了介绍。

这里需要提醒一下,你当前k8s集群没有使用 LoadBalancer 的话,则生成的 hosts 文件内容可能为空值,否则就需要手动添加一条域名解析记录。

$ cat /root/myapp/hosts
192.168.111.201 istiod.istio-system.svc

$ kubectl get svc -A

域名 istiod.istio-system.svc 中的 istiod 为服务名称, istio-system 是服务所属的namespace, 后面的 svc 代表服务类型。如果对k8s比较熟悉的话,这个很容易理解。

不过我们仍然可用kubectl 进行端口映射,以向外提供服务.
先找到 istiod 对应的pod,然后再将pod的端口遇到外面,参考 https://istio.io/latest/zh/docs/setup/getting-started/

$ kubectl get -n istio-system pod -l app=istiod
NAME                      READY   STATUS    RESTARTS   AGE
istiod-6445d59578-g6m45   1/1     Running   15         7d3h

$ kubectl port-forward -n istio-system pod/istiod-6445d59578-g6m45 --address=0.0.0.0 15012:15012
Forwarding from 0.0.0.0:15012 -> 15012

4 将生成的vm配置信息通过scp命令上传到vm

$ scp -r myapp sxf@192.168.111.133:/home/sxf/
sxf@192.168.111.133's password: 

虚拟机配置

刚刚我们已经将生成的配置信息上传到了虚拟机vm,存储目录为 /home/sxf/myapp,下面我们开始应用配置信息。

1 进入存储目录

cd /home/sxf/myapp

2 将根证书安装到目录 /etc/certs:

sudo mkdir -p /etc/certs
sudo cp root-cert.pem /etc/certs/root-cert.pem

3 将令牌安装到目录 /var/run/secrets/tokens:

sudo mkdir -p /var/run/secrets/tokens
sudo cp istio-token /var/run/secrets/tokens/istio-token

4 安装包含 Istio 虚拟机集成运行时(runtime)的包:

ubuntu:

$ curl -LO https://storage.googleapis.com/istio-release/releases/1.11.1/deb/istio-sidecar.deb
$ sudo dpkg -i istio-sidecar.deb
正在选中未选择的软件包 istio-sidecar。
(正在读取数据库 ... 系统当前共安装有 213866 个文件和目录。)
正准备解包 istio-sidecar.deb  ...
正在解包 istio-sidecar (1.11.2) ...
正在设置 istio-sidecar (1.11.2) ...

centos:

$ curl -LO https://storage.googleapis.com/istio-release/releases/1.11.2/rpm/istio-sidecar.rpm
$ sudo rpm -i istio-sidecar.rpm

对于centos系统,目前官方声称只运行centos8(截止istio1.11.2),但经过测试发现 centos7.6 .1801 也可以支持,只是需要安装一个glibc 扩展包即可。

如果重复安装的话,会提示以下信息


$ sudo dpkg -i istio-sidecar.deb
Selecting previously unselected package istio-sidecar.
(Reading database ... 192947 files and directories currently installed.)
Preparing to unpack istio-sidecar.deb ...
Unpacking istio-sidecar (1.11.1) ...
Setting up istio-sidecar (1.11.1) ...
Adding group `istio-proxy' (GID 134) ...
Done.
Warning: The home dir /var/lib/istio you specified already exists.
Adding system user `istio-proxy' (UID 128) ...
Adding new user `istio-proxy' (UID 128) with group `istio-proxy' ...
The home directory `/var/lib/istio' already exists.  Not copying from `/etc/skel'.
adduser: Warning: The home directory `/var/lib/istio' does not belong to the user you are currently creating.

此时会创建一个 istio-proxy 用户,和一些配置目录,如 /var/lib/istio

查看生成的目录结构

$ tree /var/lib/istio
/var/lib/istio
├── config
│   └── mesh
├── envoy
│   ├── envoy_bootstrap_tmpl.json
│   └── sidecar.env
├── extensions
│   ├── metadata-exchange-filter.compiled.wasm
│   ├── metadata-exchange-filter.wasm
│   ├── stats-filter.compiled.wasm
│   └── stats-filter.wasm
└── proxy

5 将 cluster.env 安装到目录 /var/lib/istio/envoy/ 中

sudo cp cluster.env /var/lib/istio/envoy/cluster.env

6 将网格配置文件 Mesh Config 安装到目录 /etc/istio/config/mesh

sudo cp mesh.yaml /etc/istio/config/mesh

7 将 istiod 主机添加到 /etc/hosts

$ sudo sh -c 'cat hosts >> /etc/hosts'

$ cat /etc/hosts
192.168.111.201 istiod.istio-system.svc

这时会将一个域名解析记录写入本机hosts文件,此域名至关重要,它是实现一切服务发现 xDS 的地址

8 把文件 /etc/certs/ 和 /var/lib/istio/envoy/ 的所有权转移给 Istio proxy

sudo mkdir -p /etc/istio/proxy
sudo chown -R istio-proxy /var/lib/istio /etc/certs /etc/istio/proxy /etc/istio/config /var/run/secrets /etc/certs/root-cert.pem

此时我们再看一下相关目录结构

$ tree /var/lib/istio /etc/certs /etc/istio/proxy /etc/istio/config /var/run/secrets
/var/lib/istio
├── config
│   └── mesh
├── envoy
│   ├── cluster.env
│   ├── envoy_bootstrap_tmpl.json
│   └── sidecar.env
├── extensions
│   ├── metadata-exchange-filter.compiled.wasm
│   ├── metadata-exchange-filter.wasm
│   ├── stats-filter.compiled.wasm
│   └── stats-filter.wasm
└── proxy
/etc/certs
└── root-cert.pem
/etc/istio/proxy
/etc/istio/config
└── mesh
/var/run/secrets
└── tokens
    └── istio-token


5 directories, 11 files

启动 istio 服务

1 在vm虚拟机上启用服务

$ systemctl start istio

2 查看istio日志

root@vm1:/home/sxf/myapp# tail -f /var/log/istio/istio.log
2021-09-06T07:27:43.891160Z	info	cache	generated new workload certificate	latency=969.387861ms ttl=23h59m59.108862154s
2021-09-06T07:27:43.891238Z	info	cache	Root cert has changed, start rotating root cert
2021-09-06T07:27:43.891265Z	info	ads	XDS: Incremental Pushing:0 ConnectedEndpoints:0 Version:
2021-09-06T07:27:43.892535Z	info	cache	returned workload trust anchor from cache	ttl=23h59m59.107482619s
2021-09-06T07:27:46.875262Z	info	ads	ADS: new connection for node:vm1.vm-1
2021-09-06T07:27:46.875301Z	info	ads	ADS: new connection for node:vm1.vm-2
2021-09-06T07:27:46.875490Z	info	cache	returned workload trust anchor from cache	ttl=23h59m56.124527456s
2021-09-06T07:27:46.875722Z	info	cache	returned workload certificate from cache	ttl=23h59m56.124293167s
2021-09-06T07:27:46.876267Z	info	ads	SDS: PUSH for node:vm1.vm resources:1 size:1.1kB resource:ROOTCA
2021-09-06T07:27:46.876305Z	info	ads	SDS: PUSH for node:vm1.vm resources:1 size:4.0kB resource:default

如果看到类似的输出,则表示服务成功。 其中 node:vm1.vm 中的vm1表示当前主机名,vm表示命名空间

也可以查看错误日志

$ tail -f /var/log/istio/istio.err.log

为了防止服务器重启导致的 istio 服务无法自动重启的问题,建议设置为随机启动。

$ systemctl enable istio

可以通过 systemctl is-enabled istio.service 查看服务是否为随机启动状态。

验证vm是否联机成功

在k8s控制面 master 节点执行查看命令

$ istioctl proxy-status
vm1.vm      SYNCED     SYNCED     SYNCED     SYNCED       istiod-6445d59578-g6m45     1.11.0

当看到类似信息即表示通讯成功!更多用法通过命令 istioctl --help 查看

另外我们也可以查看前面注册的 WorkloadGroup 和 WorkloadEntry

$ kubectl get wg -A
$ kubectl get we -A

常见问题

  1. 如果遇到 failed to warm certificate 之类的错误,一般是由于token 失效引起的,此时可以通过在 master 节点重新生成vm配置信息,并将 token 的内容复制过来再重试。
  2. 如果遇到一些ca之类的信息,可以试着执行以下命令
$ sudo unlink /etc/istio/proxy/SDS && sudo unlink /etc/istio/proxy/XDS
  1. 有时候服务停止后,存在envoy未退出的情况,虽然官方声称解决了这个问题,但在不同的版本中仍出现此问题。这个错误信息出现在 /var/log/istio/istio.err.log 日志文件
2021-09-09T01:34:29.634762Z     critical        envoy main      error initializing configuration 'etc/istio/proxy/envoy-rev0.json': cannot bind '127.0.0.1:15000': Address already in use

此时可能需要手动 kill -9 PID 将envoy进程结束掉,再重启istio服务

4. 如果按照istio官方文档的istio步骤,会发现通过 vm 请求服务时

$ curl helloworld.sample.svc:5000/hello

是无法正常通讯的。

此时需要先检查一下域名路由问题,使用 traceroute 或 ping 命令均可。

$ traceroute helloworld.sample.svc

此时需要手动添加一条路由规则才可以。

$ route add -net 10.244.0.0 gw 192.168.3.58 netmask 255.255.0.0

这里向所以来自ip段 10.244.0.0 的请求通过网关 192.168.3.58 进行转发。这里的 10.244.0.0 是指安装k8s时指定的 Pod CIDR网格段(参考), 192.168.3.58 是指安装k8s master 节点的IP地址。

5. 如果vm重启的话,会发现 /var/run/secrets/tokens/istio-token 自动丢失,如果只是短暂断开的话,则需要先删除目录 /etc/certs/ 下自动生成的 .pem 文件,再将原来的配置文件重新复制过去, 再次启用istio即可。如果是长时间断开的话,就没有好的解决办法了,只有重新生成vm连接配置(istioctl x workload entry configure -f workloadgroup.yaml -o “${WORK_DIR}” –clusterID “${CLUSTER}” –autoregister),将生成的 istio-token 复制到vm上(issue)。这一点感觉不太好,虽然token是用来引导vm连接,唯了安全性,但维护成本有些大,毕竟vm断开的情况是无法避免的。注意token内容共一行,如果在终端复制的话可能变为多行。

# 停止服务
systemctl stop istio
killall envoy

# 清理旧内容
rm -rf /etc/certs/
unlink /var/lib/istio/proxy/XDS 
unlink /var/lib/istio/proxy/SDS
unlink /etc/istio/proxy/SDS
unlink /etc/istio/proxy/XDS

# 复制新生成的 istio-token
sudo mkdir -p /etc/certs
sudo cp root-cert.pem /etc/certs/root-cert.pem
sudo mkdir -p /var/run/secrets/tokens
sudo cp istio-token /var/run/secrets/tokens/istio-token

# 当前目录结构
tree /var/lib/istio /etc/certs /etc/istio/proxy /etc/istio/config /var/run/secrets
/var/lib/istio
├── config
│   └── mesh
├── envoy
│   ├── cluster.env
│   ├── envoy_bootstrap_tmpl.json
│   └── sidecar.env
├── extensions
│   ├── metadata-exchange-filter.compiled.wasm
│   ├── metadata-exchange-filter.wasm
│   ├── stats-filter.compiled.wasm
│   └── stats-filter.wasm
└── proxy
/etc/certs
└── root-cert.pem
/etc/istio/proxy
└── envoy-rev0.json
/etc/istio/config
└── mesh
/var/run/secrets
└── tokens
    └── istio-token

# 重启服务验证
systemctl start istio
tail -f /var/log/istio/istio.log