在本模組中,我們將瞭解如何將執行在虛擬機器器上的工作負載納入istio服務網格。
向istio服務網格中引入虛擬機器器的前提是已經安裝好了istio,關於istio的安裝部署,請檢視部落格《Istio(二):在Kubernetes(k8s)叢集上安裝部署istio1.14》https://www.cnblogs.com/renshengdezheli/p/16836404.html
伺服器版本 | docker軟體版本 | Kubernetes(k8s)叢集版本 | Istio軟體版本 | CPU架構 |
---|---|---|---|---|
CentOS Linux release 7.4.1708 (Core) | Docker version 20.10.12 | v1.21.9 | Istio1.14 | x86_64 |
Kubernetes叢集架構:k8scloude1作為master節點,k8scloude2,k8scloude3作為worker節點
伺服器 | 作業系統版本 | CPU架構 | 程序 | 功能描述 |
---|---|---|---|---|
k8scloude1/192.168.110.130 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kube-apiserver,etcd,kube-scheduler,kube-controller-manager,kubelet,kube-proxy,coredns,calico | k8s master節點 |
k8scloude2/192.168.110.129 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
k8scloude3/192.168.110.128 | CentOS Linux release 7.4.1708 (Core) | x86_64 | docker,kubelet,kube-proxy,calico | k8s worker節點 |
如果我們有在虛擬機器器上執行的工作負載,我們可以將它們連線到 Istio 服務網格,使其成為網格的一部分。
帶有虛擬機器器的 Istio 服務網格有兩種架構:單網路架構和多網路架構。
在這種情況下,有一個單一的網路。Kubernetes 叢集和在虛擬機器器上執行的工作負載都在同一個網路中,它們可以直接相互通訊。
控制平面的流量(設定更新、證書籤署)是通過 Gateway 傳送的。
虛擬機器器被設定了閘道器地址,所以它們在啟動時可以連線到控制平面。
多網路架構橫跨多個網路。Kubernetes 叢集在一個網路內,而虛擬機器器則在另一個網路內。這使得 Kubernetes 叢集中的 Pod 和虛擬機器器上的工作負載無法直接相互通訊。
所有的流量,控制平面和 pod 到工作負載的流量都流經閘道器,閘道器作為兩個網路之間的橋樑。
在 Istio 服務網格中,有兩種方式來表示虛擬機器器工作負載。
工作負載組(WorkloadGroup
資源)類似於 Kubernetes 中的部署(Deployment),它代表了共用共同屬性的虛擬機器器工作負載的邏輯組。
描述虛擬機器器工作負載的第二種方法是使用工作負載條目(WorkloadEntry
資源)。工作負載條目類似於 Pod,它代表了一個虛擬機器器工作負載的單一範例。
請注意,建立上述資源將不會提供或執行任何虛擬機器器工作負載範例。這些資源只是用來參照或指向虛擬機器器工作負載的。Istio 使用它們來了解如何適當地設定網格,將哪些服務新增到內部服務登入檔中,等等。
為了將虛擬機器器新增到網格中,我們需要建立一個工作負載組,作為模板。然後,當我們設定並將虛擬機器器新增到網格中時,控制平面會自動建立一個相應的 WorkloadEntry。
我們已經提到,WorkloadEntry 的作用類似於 Pod。在新增虛擬機器器時,會建立 WorkloadEntry 資源,而當虛擬機器器的工作負載從網格中移除時,該資源會被自動刪除。
除了 WorkloadEntry 資源外,我們還需要建立一個 Kubernetes 服務。建立一個 Kubernetes 服務給了我們一個穩定的主機名和 IP 地址,以便使用選擇器欄位存取虛擬機器器工作負載和 pod。這也使我們能夠通過 DestinationRule 和 VirtualService 資源使用 Istio 的路由功能。
在這個實驗中,我們將學習如何將虛擬機器器上執行的工作負載連線到 Kubernetes 叢集上執行的 Istio 服務網格。Kubernetes 叢集和虛擬機器器都將在谷歌雲平臺(GCP)上執行。我們將使用單一網路架構。
在我們建立了一個 Kubernetes 叢集後,我們可以下載、安裝和設定 Istio。
讓我們下載 Istio 1.10.3。
$ curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.10.3 sh -
下載了 Istio 後,我們可以使用 IstioOperator 來安裝它,它可以設定網格 ID、叢集名稱和網路名稱。網路名稱將是空的,因為我們要用單一網路架構。
讓我們來設定幾個環境變數,我們將在本實驗中使用這些變數。
export SERVICE_ACCOUNT="vm-sa"
export VM_APP="hello-vm"
export VM_NAMESPACE="vm-namespace"
export WORK_DIR="${HOME}/vmfiles"
export CLUSTER_NETWORK=""
export VM_NETWORK=""
export CLUSTER="Kubernetes"
我們還可以建立 $WORK_DIR
,在這裡我們將儲存證書和其他我們必須複製到虛擬機器器上的檔案。
mkdir -p $WORK_DIR
接下來,我們將初始化 Istio Operator 並安裝 Istio:
getmesh istioctl operator init
一旦 Operator 被初始化,我們就可以建立 IstioOperator 資源,指定網格 ID、叢集名稱和網路,並安裝 Istio:
cat <<EOF | kubectl apply -f -
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: istio
namespace: istio-system
spec:
values:
global:
meshID: mesh1
multiCluster:
clusterName: "${CLUSTER}"
network: "${CLUSTER_NETWORK}"
EOF
我們可以使用 kubectl get iop -n istio-system
命令來檢查 Istio 安裝狀態何時變為健康。
在下一步,我們將安裝東西向閘道器。這是控制平面用來與虛擬機器器工作負載對話的閘道器,反之亦然。
gen-eastwest-gateway.sh
指令碼是我們之前下載的 Istio 包的一部分。將資料夾改為 istio-1.10.3
(或你解壓 Istio 的資料夾)並執行以下命令:
samples/multicluster/gen-eastwest-gateway.sh --single-cluster | istioctl install -y -f -
gen-eastwest-gateway.sh
指令碼使用一個 IstioOperator 來部署一個額外的閘道器,名為 istio-eastwestgateway
,並設定了伺服器埠。
我們可以通過檢視 istio-system
名稱空間中的 Kubernetes 服務來檢查新閘道器。
最後,我們還需要設定閘道器,通過它來暴露控制平面(istiod)。我們可以通過部署 expose-istiod.yaml
檔案來做到這一點:
$ kubectl apply -n istio-system -f samples/multicluster/expose-istiod.yaml
gateway.networking.istio.io/istiod-gateway created
virtualservice.networking.istio.io/istiod-vs created
對於虛擬機器器工作負載,我們必須建立一個單獨的名稱空間來儲存 WorkloadEntry 資源和任何其他虛擬機器器工作負載相關的資源。此外,我們還必須匯出叢集環境檔案、令牌、證書和其他我們必須轉移到虛擬機器器上的檔案。
我們將把所有檔案存放在我們在實驗開始時建立的 $WORK_DIR
中。
讓我們在同一名稱空間中建立虛擬機器器名稱空間和我們將用於虛擬機器器工作負載的服務賬戶:
$ kubectl create ns "${VM_NAMESPACE}"
namespace/vm-namespace created
$ kubectl create serviceaccount "${SERVICE_ACCOUNT}" -n "${VM_NAMESPACE}"
serviceaccount/vm-sa created
現在我們可以建立一個 WorkloadGroup 資源並將其儲存到 workloadgroup.yaml
中:
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
虛擬機器器需要關於叢集和 Istio 的控制平面的資訊來連線到它。為了生成所需檔案,我們可以執行 getmesh istioctl x workload entry
命令。我們將所有生成的檔案儲存到 $WORK_DIR
中:
$ getmesh istioctl x workload entry configure -f workloadgroup.yaml -o "${WORK_DIR}" --clusterID "${CLUSTER}"
Warning: a security token for namespace "vm-namespace" and service account "vm-sa" has been generated and stored at "/vmfiles/istio-token"
configuration generation into directory /vmfiles was successful
現在是時候建立和設定一個虛擬機器器了。我在 GCP 中執行這個虛擬機器器,就像 Kubernetes 叢集一樣。虛擬機器器使用的是 Debian GNU/Linux 10(Buster)映象。確保你在防火牆部分勾選了 "允許 HTTP 流量",並且你有 SSH 存取該範例的許可權。
在這個例子中,我們在 80 埠執行一個簡單的 Python HTTP 伺服器。你可以在不同的埠上設定任何其他服務。只要確保你設定了相應的安全和防火牆規則。
$WORK_DIR
中的檔案複製到範例的主資料夾中。相應地替換 USERNAME
和 INSTANCE_IP
。 $ scp $WORK_DIR/* [USERNAME]@[INSTANCE_IP]:~
Enter passphrase for key '/Users/peterj/.ssh/id_rsa':
bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8)
cluster.env 100% 589 12.6KB/s 00:00
hosts 100% 38 0.8KB/s 00:00
istio-token 100% 906 19.4KB/s 00:00
mesh.yaml 100% 667 14.4KB/s 00:00
root-cert.pem 100% 1094 23.5KB/s 00:00
或者,你可以使用 gcloud
命令和範例名稱: gcloud compute scp --zone=us-west1-b ${WORK_DIR}/* [INSTANCE_NAME]:~
。
/etc/certs
: sudo mkdir -p /etc/certs
sudo cp root-cert.pem /etc/certs/root-cert.pem
istio-token
檔案到 /var/run/secrets/tokens
目錄: sudo mkdir -p /var/run/secrets/tokens
sudo cp istio-token /var/run/secrets/tokens/istio-token
curl -LO https://storage.googleapis.com/istio-release/releases/1.10.3/deb/istio-sidecar.deb
sudo dpkg -i istio-sidecar.deb
cluster.env
到 /var/lib/istio/envoy/
: sudo cp cluster.env /var/lib/istio/envoy/cluster.env
mesh.yaml
)新增到 /etc/istio/config/mesh
: sudo cp mesh.yaml /etc/istio/config/mesh
/etc/hosts
檔案中: sudo sh -c 'cat $(eval echo ~$SUDO_USER)/hosts >> /etc/hosts'
/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
以上都就緒後,就可以在虛擬機器器中啟動 Istio:
sudo systemctl start istio
此刻,虛擬機器器被設定為與 Kubernetes 叢集中 Istio 的控制平面通訊。
讓我們在 Kubernetes 叢集中部署一個 Hello world 應用程式。首先,我們需要在 default
名稱空間中啟用自動 sidecar 注入:
$ kubectl label namespace default istio-injection=enabled
namespace/default labeled
接下來,建立 Hello world 的部署和服務。
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
labels:
app: hello-world
spec:
replicas: 1
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- image: gcr.io/tetratelabs/hello-world:1.0.0
imagePullPolicy: Always
name: svc
ports:
- containerPort: 3000
---
kind: Service
apiVersion: v1
metadata:
name: hello-world
labels:
app: hello-world
spec:
selector:
app: hello-world
ports:
- port: 80
name: http
targetPort: 3000
將上述檔案儲存為 hello-world.yaml
,並使用 kubectl apply -f hello-world.yaml
進行部署。
等待 Pod 準備好,然後回到虛擬機器器上,嘗試存取 Kubernetes 服務:
$ curl http://hello-world.default
Hello World
你可以從虛擬機器器上存取在你的 Kubernetes 叢集內執行的任何服務。
我們也可以在虛擬機器器上執行一個工作負載。切換到範例上,執行一個簡單的 Python HTTP 伺服器:
$ sudo python3 -m http.server 80
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
如果你試圖直接 curl 到範例 IP,你會得到一個響應(目錄列表)。:
$ curl [INSTANCE_IP]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dt
d">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
...
但我們要做的是將工作負載(Python HTTP 服務)新增到網格中。出於這個原因,我們在前面建立了虛擬機器器名稱空間。所以讓我們建立一個代表虛擬機器器工作負載的 Kubernetes 服務。注意,名稱和標籤值等於我們之前設定的 VM_APP
環境變數的值。不要忘記將服務部署到 VM_NAMESPACE
。
apiVersion: v1
kind: Service
metadata:
name: hello-vm
labels:
app: hello-vm
spec:
ports:
- port: 80
name: http-vm
targetPort: 80
selector:
app: hello-vm
將上述檔案儲存為 hello-vm-service.yaml
,並使用 kubectl apply -f hello-vm-service.yaml -n vm-namespace
將其部署到 VM 名稱空間。
因為我們沒有使用實驗性的虛擬機器器自動註冊,它將自動建立 WorkloadEntry 資源,我們需要手動建立它們。
我們需要一個代表虛擬機器器工作負載的 WorkloadEntry 資源——該資源使用虛擬機器器服務賬戶(SERVICE_ACCOUNT
)和標籤中的應用程式名稱(VM_APP
)。
請注意,我們還需要獲得虛擬機器器的內部 IP 地址,這樣 Istio 就知道在哪裡可以到達虛擬機器器。讓我們把它儲存在另一個環境變數中(確保用你的值替換 INSTANCE_NAME
和 ZONE
)。
export VM_IP=$(gcloud compute instances describe [INSTANCE_NAME] --format='get(networkInterfaces[0].networkIP)' --zone=[ZONE])
我們現在可以建立 WorkloadEntry 資源:
cat <<EOF > workloadentry.yaml
apiVersion: networking.istio.io/v1alpha3
kind: WorkloadEntry
metadata:
name: ${VM_APP}
namespace: ${VM_NAMESPACE}
spec:
serviceAccount: ${SERVICE_ACCOUNT}
address: ${VM_IP}
labels:
app: ${VM_APP}
instance-id: vm1
EOF
將上述檔案儲存為 workloadentry.yaml
,然後在 $VM_NAMESPACE
名稱空間建立資源:
kubectl apply -n ${VM_NAMESPACE} -f workloadentry.yaml
為了把虛擬機器器的工作負載加入到網格內,我們還需要定義 ServiceEntry:
cat <<EOF > serviceentry.yaml
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: ${VM_APP}
spec:
hosts:
- ${VM_APP}
location: MESH_INTERNAL
ports:
- number: 80
name: http
protocol: HTTP
targetPort: 80
resolution: STATIC
workloadSelector:
labels:
app: ${VM_APP}
請注意,WorkloadEntry 和 ServiceEntry 在未來最終將自動建立。
在 $VM_NAMESPACE
中建立服務條目資源。
kubectl apply -n ${VM_NAMESPACE} -f serviceentry.yaml
我們現在可以使用 Kubernetes 服務名稱 hello-vm.vm-namespace
來存取虛擬機器器上的工作負載。讓我們在叢集內執行一個 Pod,並嘗試從那裡存取該服務:
$ kubectl run curl --image=radial/busyboxplus:curl -i --tty
If you don't see a command prompt, try pressing enter.
[ root@curl:/ ]$
在你得到 Pod 中的命令提示後,你可以執行 curl 並存取工作負載。你應該看到一個目錄列表的響應。同樣地,你會注意到在 HTTP 伺服器執行的範例上有一個紀錄檔條目:
[ root@curl:/ ]$ curl hello-vm.vm-namespace
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dt
d">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
...