1. 程式人生 > >istio 三日談之一,環境準備_Kubernetes中文社群

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 中缺乏對

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: 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

經過一番折騰:

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