• Google Kubernetes Engine
    • 开始之前
    • 创建 GKE 集群
    • 创建 Google Cloud 防火墙规则
    • 安装 Istio 控制平面
    • 生成远程集群的安装文件
    • 安装远程集群
    • 为 Istio pilot 创建远程集群的 kubeconfig 文件
    • 配置 Istio 控制平面,以发现远程集群
    • 部署跨集群的 Bookinfo 示例
    • 卸载

    Google Kubernetes Engine

    本例中展示了如何在两个 Google Kubernetes Engine 集群的基础上,配置一个单一控制平面的多集群网格。

    开始之前

    在安装 Istio 的先决条件之外,本示例还需要如下安装步骤:

    • 这个例子需要一个有效的 Google Platform 项目

    • 此示例需要启用结算的有效 Google Cloud Platform 项目。

      • 如果你还没有建立 GCP 用户,那么还可以申请 300 美元的免费试用额度。

      • 创建一个 Google Cloud Project 来运行你的 GKE 集群。

    • 安装并初始化 Google Cloud SDK

    创建 GKE 集群

    • gcloud 创建缺省项目以进行后续操作。
    1. $ gcloud config set project myProject
    2. $ proj=$(gcloud config list --format='value(core.project)')
    • 创建两个 GKE 集群以便尝试多集群功能。

    注意:为了使用跨集群的直接 Pod 间通信,需要启用 —enable-ip-aliaszone 的值要从 GCP zones 中进行选择。

    1. $ zone="us-east1-b"
    2. $ cluster="cluster-1"
    3. $ gcloud container clusters create $cluster --zone $zone --username "admin" \
    4. --cluster-version "1.9.6-gke.1" --machine-type "n1-standard-2" --image-type "COS" --disk-size "100" \
    5. --scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.read_only",\
    6. "https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring",\
    7. "https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly",\
    8. "https://www.googleapis.com/auth/trace.append" \
    9. --num-nodes "4" --network "default" --enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias --async
    10. $ cluster="cluster-2"
    11. $ gcloud container clusters create $cluster --zone $zone --username "admin" \
    12. --cluster-version "1.9.6-gke.1" --machine-type "n1-standard-2" --image-type "COS" --disk-size "100" \
    13. --scopes "https://www.googleapis.com/auth/compute","https://www.googleapis.com/auth/devstorage.read_only",\
    14. "https://www.googleapis.com/auth/logging.write","https://www.googleapis.com/auth/monitoring",\
    15. "https://www.googleapis.com/auth/servicecontrol","https://www.googleapis.com/auth/service.management.readonly",\
    16. "https://www.googleapis.com/auth/trace.append" \
    17. --num-nodes "4" --network "default" --enable-cloud-logging --enable-cloud-monitoring --enable-ip-alias --async
    • 反复执行下面的命令,等待集群进入 RUNNING 状态:
    1. $ gcloud container clusters list
    • 获取集群凭据(命令详情):
    1. $ gcloud container clusters get-credentials cluster-1 --zone $zone
    2. $ gcloud container clusters get-credentials cluster-2 --zone $zone
    • 使用 kubectl 访问各个集群:

      • 检查 cluster-1
    1. $ kubectl config use-context "gke_${proj}_${zone}_cluster-1"
    2. $ kubectl get pods --all-namespaces
    • 检查 cluster-2
    1. $ kubectl config use-context "gke_${proj}_${zone}_cluster-2"
    2. $ kubectl get pods --all-namespaces
    • 为当前 GPC 用户的 Kubernetes 凭据创建一个 cluster-admin 角色绑定。

    注意:使用你的 Google Cloud 账号绑定的邮箱替换下面的 mygcp@gmail.com

    1. $ KUBE_USER="mygcp@gmail.com"
    2. $ kubectl create clusterrolebinding gke-cluster-admin-binding \
    3. --clusterrole=cluster-admin \
    4. --user="${KUBE_USER}"

    创建 Google Cloud 防火墙规则

    为了允许每个集群中的 Pod 能够直接通信,创建如下规则:

    1. $ function join_by { local IFS="$1"; shift; echo "$*"; }
    2. $ ALL_CLUSTER_CIDRS=$(gcloud container clusters list --format='value(clusterIpv4Cidr)' | sort | uniq)
    3. $ ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}"))
    4. $ ALL_CLUSTER_NETTAGS=$(gcloud compute instances list --format='value(tags.items.[0])' | sort | uniq)
    5. $ ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
    6. $ gcloud compute firewall-rules create istio-multicluster-test-pods \
    7. --allow=tcp,udp,icmp,esp,ah,sctp \
    8. --direction=INGRESS \
    9. --priority=900 \
    10. --source-ranges="${ALL_CLUSTER_CIDRS}" \
    11. --target-tags="${ALL_CLUSTER_NETTAGS}" --quiet

    安装 Istio 控制平面

    接下来生成一个 Istio 安装文件、安装,并在 default 命名空间中启用 Sidecar 的自动注入:

    1. $ kubectl config use-context "gke_${proj}_${zone}_cluster-1"
    2. $ helm template install/kubernetes/helm/istio --name istio --namespace istio-system > $HOME/istio_master.yaml
    3. $ kubectl create ns istio-system
    4. $ kubectl apply -f $HOME/istio_master.yaml
    5. $ kubectl label namespace default istio-injection=enabled

    执行下面的命令,等待 Pod 启动:

    1. $ kubectl get pods -n istio-system

    生成远程集群的安装文件

    • 获取控制平面 Pod 的 IP 地址:
    1. $ export PILOT_POD_IP=$(kubectl -n istio-system get pod -l istio=pilot -o jsonpath='{.items[0].status.podIP}')
    2. $ export POLICY_POD_IP=$(kubectl -n istio-system get pod -l istio=mixer -o jsonpath='{.items[0].status.podIP}')
    3. $ export TELEMETRY_POD_IP=$(kubectl -n istio-system get pod -l istio-mixer-type=telemetry -o jsonpath='{.items[0].status.podIP}')
    • 生成远程集群的安装文件:
    1. $ helm template install/kubernetes/helm/istio-remote --namespace istio-system \
    2. --name istio-remote \
    3. --set global.remotePilotAddress=${PILOT_POD_IP} \
    4. --set global.remotePolicyAddress=${POLICY_POD_IP} \
    5. --set global.remoteTelemetryAddress=${TELEMETRY_POD_IP} > $HOME/istio-remote.yaml

    安装远程集群

    下面的步骤会安装一个最精简的 Istio 组件集合,并为远端集群 default 命名空间启用 Sidecar 的自动注入:

    1. $ kubectl config use-context "gke_${proj}_${zone}_cluster-2"
    2. $ kubectl create ns istio-system
    3. $ kubectl apply -f $HOME/istio-remote.yaml
    4. $ kubectl label namespace default istio-injection=enabled

    为 Istio pilot 创建远程集群的 kubeconfig 文件

    istio-remote Helm chart 会给 Istio pilot discovery 创建一个最小化权限的 Service account。

    • 在给 Service account istio-multi 创建 kubeconfig 文件之前,首先要准备环境变量:
    1. $ export WORK_DIR=$(pwd)
    2. $ CLUSTER_NAME=$(kubectl config view --minify=true -o "jsonpath={.clusters[].name}")
    3. $ CLUSTER_NAME="${CLUSTER_NAME##*_}"
    4. $ export KUBECFG_FILE=${WORK_DIR}/${CLUSTER_NAME}
    5. $ SERVER=$(kubectl config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
    6. $ NAMESPACE=istio-system
    7. $ SERVICE_ACCOUNT=istio-multi
    8. $ SECRET_NAME=$(kubectl get sa ${SERVICE_ACCOUNT} -n ${NAMESPACE} -o jsonpath='{.secrets[].name}')
    9. $ CA_DATA=$(kubectl get secret ${SECRET_NAME} -n ${NAMESPACE} -o "jsonpath={.data['ca\.crt']}")
    10. $ TOKEN=$(kubectl get secret ${SECRET_NAME} -n ${NAMESPACE} -o "jsonpath={.data['token']}" | base64 --decode)

    注意:在很多系统中都可以使用 openssl enc -d -base64 -A 来替代 base64 —decode

    • 在工作目录中为 Service account istio-multi 创建一个 kubeconfig 文件:
    1. $ cat <<EOF > ${KUBECFG_FILE}
    2. apiVersion: v1
    3. clusters:
    4. - cluster:
    5. certificate-authority-data: ${CA_DATA}
    6. server: ${SERVER}
    7. name: ${CLUSTER_NAME}
    8. contexts:
    9. - context:
    10. cluster: ${CLUSTER_NAME}
    11. user: ${CLUSTER_NAME}
    12. name: ${CLUSTER_NAME}
    13. current-context: ${CLUSTER_NAME}
    14. kind: Config
    15. preferences: {}
    16. users:
    17. - name: ${CLUSTER_NAME}
    18. user:
    19. token: ${TOKEN}
    20. EOF

    至此,远程集群的 kubeconfig 就已经创建好并保存到了 ${WORK_DIR} 目录之中了,文件名称和原始的 kubeconfig 文件中的集群名称一致。

    配置 Istio 控制平面,以发现远程集群

    为每个远程集群创建 Secret 并用标签进行标记:

    1. $ kubectl config use-context "gke_${proj}_${zone}_cluster-1"
    2. $ kubectl create secret generic ${CLUSTER_NAME} --from-file ${KUBECFG_FILE} -n ${NAMESPACE}
    3. $ kubectl label secret ${CLUSTER_NAME} istio/multiCluster=true -n ${NAMESPACE}

    部署跨集群的 Bookinfo 示例

    • 在第一个集群上安装 Bookinfo,然后删除 reviews-v3Deployment,以便在远程集群进行部署:

    ZipZip

    1. $ kubectl config use-context "gke_${proj}_${zone}_cluster-1"
    2. $ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo.yaml@
    3. $ kubectl apply -f @samples/bookinfo/networking/bookinfo-gateway.yaml@
    4. $ kubectl delete deployment reviews-v3
    • 为远端集群创建 reviews-v3.yaml 文件,准备部署:
    1. ---
    2. ##################################################################################################
    3. # Ratings service
    4. ##################################################################################################
    5. apiVersion: v1
    6. kind: Service
    7. metadata:
    8. name: ratings
    9. labels:
    10. app: ratings
    11. spec:
    12. ports:
    13. - port: 9080
    14. name: http
    15. ---
    16. ##################################################################################################
    17. # Reviews service
    18. ##################################################################################################
    19. apiVersion: v1
    20. kind: Service
    21. metadata:
    22. name: reviews
    23. labels:
    24. app: reviews
    25. spec:
    26. ports:
    27. - port: 9080
    28. name: http
    29. selector:
    30. app: reviews
    31. ---
    32. apiVersion: extensions/v1beta1
    33. kind: Deployment
    34. metadata:
    35. name: reviews-v3
    36. spec:
    37. replicas: 1
    38. template:
    39. metadata:
    40. labels:
    41. app: reviews
    42. version: v3
    43. spec:
    44. containers:
    45. - name: reviews
    46. image: istio/examples-bookinfo-reviews-v3:1.5.0
    47. imagePullPolicy: IfNotPresent
    48. ports:
    49. - containerPort: 9080
    50. EOF

    注意ratings 服务定义也被加入远程集群,其原因是 reviews-v3ratings 的客户端,创建了服务对象,就创建了 DNS 条目。reivews-v3 中的 Sidecar 会在 DNS 解析到服务地址之后来确定正确的 ratings 服务端点。如果使用的是多集群 DNS 方案,例如在 Kubernetes 联邦集群之中,这一步骤就不必执行了。

    • 在远端部署 reviews-v3
    1. $ kubectl config use-context "gke_${proj}_${zone}_cluster-2"
    2. $ kubectl apply -f $HOME/reviews-v3.yaml
    • 获取 istio-ingressgateway 服务的外部 IP,以便发起对 bookinfo 页面的访问,来验证 Istio 是否已经在 reviews 服务的负载均衡中包含了远端集群的 reviews-v3 实例:
    1. $ kubectl get svc istio-ingressgateway -n istio-system

    重复访问 http://<GATEWAY_IP>/productpage,每个版本的 reviews 服务应该会以同样几率做出响应,其中包含了远端集群的 reviews-v3(红色)。可能需要多次访问才能看到预期效果。

    卸载

    除了按照基于 VPN 的多集群卸载操作之外,还应该执行以下步骤:

    • 删除 Google Cloud 防火墙规则:
    1. $ gcloud compute firewall-rules delete istio-multicluster-test-pods --quiet
    • 从不再用于 Istio 的每个集群中删除 cluster-admin 角色绑定:
    1. $ kubectl delete clusterrolebinding gke-cluster-admin-binding
    • 删除不再使用的任何 GKE 集群。以下是远程集群 cluster-2 的示例 delete 命令:
    1. $ gcloud container clusters delete cluster-2 --zone $zone