1. 程式人生 > >istio 三日談之一,環境準備

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

經過一番折騰:

  1. 原有 YAML
  2. 注入,生成新的 YAML
  3. 替換新 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 都需要進行注入操作。