istio 三日談之一,環境準備_Kubernetes中文社群
筆者嘗試在一個準生產環境下,利用 istio 來對執行在 Kubernetes 上的微服務進行管理。
這一篇是第一篇,將一些主要的坑和環境準備工作。
內容較多,因此無法寫成手把手教程,希望讀者有一定 Kubernetes 的操作基礎。
準備映象
初始執行需要的映象包括以下幾個:
- istio/mixer:0.1.6
- pilot:0.1.6
- proxy_debug:0.1.6
- istio-ca:0.1.6
首先要解決的自然還是映象的存放問題,官方在原始碼中提供了很方便的工具,用來根據模板生成在 Kubernetes 中執行 istio 的 YAML 檔案:
./updateVersion.sh \ -p 10.211.55.86:5000/istio,0.1.6 \ -c 10.211.55.86:5000/istio,0.1.6 \ -x 10.211.55.86:5000/istio,0.1.6
這一指令碼在原始碼的 install 目錄下。
Kubernetes 環境
這裡我們使用的叢集大概情況是:
- 1.7.1 版本的 Kubernetes
- 開啟了 RBAC
- 預備使用的名稱空間為:default
- PVC 自動供給
- 無網際網路連線
- 具有自己的私庫
啟動 istio
RBAC 相關
首先,install 目錄中提供的 rbac 檔案授權範圍不足,所以需要手工編輯istio-rbac-beta.yaml,把其中的幾個 RoleBinding,改為 ClusterRoleBinding。
kubectl create \ -f istio-rbac-beta.yaml
另外預設的 ClusterRole 中缺乏對
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1beta1 metadata: name: istio-pilot rules: - apiGroups: ["istio.io"] resources: ["istioconfigs", "istioconfigs.istio.io"] verbs: ["*"] - apiGroups: ["extensions"] resources: ["thirdpartyresources", "thirdpartyresources.extensions", "ingresses", "ingresses/status"] verbs: ["*"] - apiGroups: [""] resources: ["configmaps", "endpoints", "pods", "services"] verbs: ["*"] - apiGroups: [""] resources: ["namespaces", "nodes", "secrets"] verbs: ["get", "list", "watch"]
啟動 istio 元件
kubectl create \ -f istio.yaml \
建立 PVC
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: frontend-v1 spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
準備工作負載
這裡我們使用官方的 PHP + Apache 映象作為工作負載來進行下面的測試,例如我們準備好的 YAML 如下:
kind: Deployment apiVersion: extensions/v1beta1 metadata: name: frontend labels: name: frontend version: "1" spec: replicas: 1 template: metadata: labels: name: frontend version: "1" spec: containers: - name: php image: 10.211.55.86:5000/php:7.1.7-apache ports: - containerPort: 80 protocol: TCP volumeMounts: - name: wwwroot mountPath: /var/www/html env: - name: "SERVICE_VERSION" value: "1" volumes: - name: wwwroot persistentVolumeClaim: claimName: frontend-v1
服務定義:
kind: Service apiVersion: v1 metadata: name: svc-frontend labels: name: frontend version: "1" spec: type: NodePort ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 32010 selector: name: frontend
在 Web 目錄中我們隨便做了個index.php,用來展示當前所在 Pod 和環境變數中的服務版本號,備用。
Tips:一般這類測試,我都懶得重新做一個 Docker 映象,一般是另外用一個 Pod 掛載同一個 PVC,直接編輯頁面檔案,或者使用kubectl cp命令進行拷貝。
index.php
<?php header("Content-type: text/plain"); echo "From: ".gethostname()."\n"; echo "Version: ".$_ENV['SERVICE_VERSION']."\n";
delay.php
<?php header("Content-type: text/plain"); sleep(4); echo "\n-----------------------------\n"; echo "\nFrom: ".gethostname()."\n"; echo "Version: ".$_ENV['SERVICE_VERSION']."\n";
執行成功後,訪問該服務的 nodePort,會看到相應的輸出內容。
istio 的注入
首先用kubectl delete -f刪除上文的服務和 Deployment。
上面為了測試方便,給 Service 使用了 NodePort 型別,這裡我們去掉這一服務的 NodePort,用 ClusterIP 的形式執行:
spec: ports: - protocol: TCP port: 80 targetPort: 80 selector: name: frontend
接下來進行注入操作
istioctl kube-inject -f frontend-v1.yaml > frontend-v1-istio.yaml
觀察注入操作會發現,其中多了一個 Sidecar Container(下面的 Image 節內容已經被我修改為本地私庫):
env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP image: 10.211.55.86:5000/istio/proxy_debug:0.1.6 imagePullPolicy: Always name: proxy resources: {} securityContext: runAsUser: 1337
另外還在pod.beta.kubernetes.io/init-containers註解中進行了初始化:
[{ "args": ["-p", "15001", "-u", "1337"], "image": "10.211.55.86:5000/istio/init:0.1", "imagePullPolicy": "Always", "name": "init", "securityContext": { "capabilities": { "add": ["NET_ADMIN"] } } }, { "args": ["-c", "sysctl -w kernel.core_pattern=/tmp/core.%e.%p.%t \u0026\u0026 ulimit -c unlimited"], "command": ["/bin/sh"], "image": "10.211.55.86:5000/alpine", "imagePullPolicy": "Always", "name": "enable-core-dump", "securityContext": { "privileged": true } }]
可以看到上面一共涉及三個映象:
- docker.io/istio/proxy_debug:0.1
- docker.io/istio/init:0.1
- alpine
經過一番折騰:
- 原有 YAML
- 注入,生成新的 YAML
- 替換新 YAML 中的映象地址
就把原有的容器應用封裝成新的 istio 支援的微服務了。
準備測試素材
另外我們需要準備一個工具服務,用於在 shell 中進行測試:
kind: Deployment apiVersion: extensions/v1beta1 metadata: name: tool labels: name: tool version: "1" spec: replicas: 1 template: metadata: labels: name: tool version: "1" spec: containers: - name: tool image: 10.211.55.86:5000/php:7.1.7-apache ports: - containerPort: 80 protocol: TCP volumeMounts: - name: wwwroot mountPath: /var/www/html volumes: - name: wwwroot persistentVolumeClaim: claimName: frontend-v1 --- kind: Service apiVersion: v1 metadata: name: tool labels: name: tool spec: ports: - protocol: TCP port: 80 targetPort: 80 selector: name: tool
同樣的,這裡也需要執行istioctl kube-inject進行注入,執行之後,就得到一個運行於叢集內部的 Linux Shell,istio 中的路由策略經常是客戶端和伺服器協同完成的,因此上客戶和伺服器的 Deployment 都需要進行注入操作。