istio 三日談之一,環境準備
筆者嘗試在一個準生產環境下,利用 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 中缺乏對 Namespace 的許可權,新版本已經修正,目前版本仍需新增:
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:1template: 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:1template: 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 都需要進行注入操作。