🌝

Istio 支持虚拟机集成实践

Posted at — Jan 29, 2022

Istio 支持 K8s 集群外的虚拟机及虚拟机运行的应用加入 Istio 服务网格。这允许老的应用以及不适合容器化部署的应用也能使用 Istio 服务网格。 在单网络下,Gateway 负责虚拟机访问允许在 K8s 上的 Istio 控制平面:

istio-virtual-machines-1

多网络下,Gateway 负责同时暴露 Istio 控制平面和服务网格内的服务:

istio-virtual-machines-2

虚拟机集成

Step 1. 环境准备

本文使用阿里云,在同一 VPC 下,部署一个 K8s 托管集群以及一个 ECS 实例,模拟单网络下集成虚拟机。在 K8s 节点机器上设置以下环境变量用于后续操作,并创建工作目录 mkdir -p "${WORK_DIR}"

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
VM_APP="demo"
VM_NAMESPACE="vm"
WORK_DIR="${HOME}/vmintegration"
SERVICE_ACCOUNT="vm"
# 多网络下,K8s 集群和虚拟机所在网络分别命名,如:
# CLUSTER_NETWORK="kube-network"
# VM_NETWORK="vm-network"
# 而 CLUSTER 值赋为 cluster1
CLUSTER_NETWORK=""
VM_NETWORK=""
CLUSTER="Kubernetes"

Step 2. 安装 Istio 控制平面

在 K8s 集群上安装 Istio(如果集群已安装则无须安装,但仍要暴露 Istio 控制平面):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
cat <<EOF > ./vm-cluster.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio
spec:
  values:
    global:
      meshID: mesh1
      multiCluster:
        clusterName: "${CLUSTER}"
      network: "${CLUSTER_NETWORK}"
EOF

istioctl install -f vm-cluster.yaml

Step 3. 安装 east-west gateway

通过 IstioOperator YAML 安装 east-west gateway:

1
samples/multicluster/gen-eastwest-gateway.sh --single-cluster | istioctl install -y -f -
 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
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: eastwest
spec:
  revision: ""
  profile: empty
  components:
    ingressGateways:
      - name: istio-eastwestgateway
        label:
          istio: eastwestgateway
          app: istio-eastwestgateway
        enabled: true
        k8s:
          service:
            ports:
              - name: status-port
                port: 15021
                targetPort: 15021
              - name: tls
                port: 15443
                targetPort: 15443
              - name: tls-istiod
                port: 15012
                targetPort: 15012
              - name: tls-webhook
                port: 15017
                targetPort: 15017
  values:
    gateways:
      istio-ingressgateway:
        injectionTemplate: gateway

Step 4. 暴露 Istio 控制平面

1
2
3
kubectl apply -n istio-system -f samples/multicluster/expose-istiod.yaml
# 多网络部署多以下步骤
# kubectl apply -n istio-system -f samples/multicluster/expose-services.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
42
43
44
45
46
47
48
49
50
51
52
53
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istiod-gateway
spec:
  selector:
    istio: eastwestgateway
  servers:
    - port:
        name: tls-istiod
        number: 15012
        protocol: tls
      tls:
        mode: PASSTHROUGH        
      hosts:
        - "*"
    - port:
        name: tls-istiodwebhook
        number: 15017
        protocol: tls
      tls:
        mode: PASSTHROUGH          
      hosts:
        - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: istiod-vs
spec:
  hosts:
  - "*"
  gateways:
  - istiod-gateway
  tls:
  - match:
    - port: 15012
      sniHosts:
      - "*"
    route:
    - destination:
        host: istiod.istio-system.svc.cluster.local
        port:
          number: 15012
  - match:
    - port: 15017
      sniHosts:
      - "*"
    route:
    - destination:
        host: istiod.istio-system.svc.cluster.local
        port:
          number: 443

Step 5. 创建虚拟机的命名空间

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

Step 6. 生成虚拟机应用的配置文件

通过 istioctl x workload entry 命令生成虚拟机应用(workload instance)的配置文件。该命令会生成五个文件:

  1. cluster.env:包含一些元信息,如:流量入口的端口号、虚拟机对应的 serviceaccount 和 namespace;
  2. istio-token:JWT token,用于从 CA 获取证书;
  3. mesh.yaml
  4. root-cert.pem:用于认证的根证书;
  5. hosts:包含 Istiod 的地址。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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

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

cluster.env 的内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
CANONICAL_REVISION='latest'
CANONICAL_SERVICE='demo'
ISTIO_INBOUND_PORTS='*'
ISTIO_LOCAL_EXCLUDE_PORTS='15090,15021,15020'
ISTIO_METAJSON_LABELS='{"app":"demo","service.istio.io/canonical-name":"demo","service.istio.io/canonical-revision":"latest"}'
ISTIO_META_CLUSTER_ID='Kubernetes'
ISTIO_META_DNS_CAPTURE='true'
ISTIO_META_MESH_ID='mesh1'
ISTIO_META_NETWORK=''
ISTIO_META_WORKLOAD_NAME='demo'
ISTIO_NAMESPACE='vm'
ISTIO_SERVICE='demo.vm'
ISTIO_SERVICE_CIDR='*'
POD_NAMESPACE='vm'
SERVICE_ACCOUNT='vm'
TRUST_DOMAIN='cluster.local'

mesh.yaml 的内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
defaultConfig:
  discoveryAddress: istiod.istio-system.svc:15012
  meshId: mesh1
  proxyMetadata:
    CANONICAL_REVISION: latest
    CANONICAL_SERVICE: demo
    ISTIO_META_CLUSTER_ID: Kubernetes
    ISTIO_META_DNS_CAPTURE: "true"
    ISTIO_META_MESH_ID: mesh1
    ISTIO_META_NETWORK: ""
    ISTIO_META_WORKLOAD_NAME: demo
    ISTIO_METAJSON_LABELS: '{"app":"demo","service.istio.io/canonical-name":"demo","service.istio.io/canonical-revision":"latest"}'
    POD_NAMESPACE: vm
    SERVICE_ACCOUNT: vm
    TRUST_DOMAIN: cluster.local
  tracing:
    zipkin:
      address: zipkin.istio-system:9411

hosts 包含 Istiod 的地址:

1
8.134.<xxx>.<xxx> istiod.istio-system.svc

Step 6. 配置虚拟机

将前面生成的配置,从 K8s 集群节点机器上,传输到要加入服务网格的虚拟机上。然后依次将配置文件安装到虚拟机上:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# 首先,将根证书安装到 /etc/certs 目录下
mkdir -p /etc/certs
cp root-cert.pem /etc/certs/root-cert.pem

# 接着,将 istio-token 安装到 /var/run/secrets/tokens 目录下
mkdir -p /var/run/secrets/tokens
cp istio-token /var/run/secrets/tokens/istio-token

# 然后,将 cluster.env 安装到 /var/lib/istio/envoy/ 目录下
cp cluster.env /var/lib/istio/envoy/cluster.env

# 将 mesh 配置文件安装到 /etc/istio/config/ 目录下,并重命名为 mesh
cp mesh.yaml /etc/istio/config/mesh

# 最后,更新 hosts 文件
cat hosts >> /etc/hosts

并将 /etc/certs/ 等目录的所有者设置为 istio-proxy:

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

Step 7. 安装 Istio 虚拟机集成运行时:

因阿里云 ECS 的操作系统 Alibaba Cloud Linux 是基于 CentOS 的,因此选择 CentOS 8 的安装包:

1
2
curl -LO https://storage.googleapis.com/istio-release/releases/1.12.2/rpm/istio-sidecar.rpm
rpm -i istio-sidecar.rpm

运行 Istio agent:

1
systemctl start istio

检查是否安装成功 cat /var/log/istio/istio.log,日志中无 failed 字样。至此,可以访问 K8s 服务网格中的 Service,如:curl helloworld.sample.svc:5000/hello