原文地址https://my.oschina.net/ganity/blog/1616866html
Istio 是Service Mesh下一代微服務架構的一個完整的解決方案,本文在本地實驗環境中開發和部署了一個簡單的示例應用.node
本例子中使用了兩個應用,hello-node和hello-py. 調用關係以下python
應用調用關係git
使用Minikube的本地實驗環境, 系統爲centos7.0, 安裝參考https://yq.aliyun.com/articles/221687github
能夠參考https://istio.io/docs/setup/kubernetes/quick-start.htmldocker
curl -L https://git.io/getLatestIstio | sh -
json
cd istio-0.4.0
flask
export PATH=$PWD/bin:$PATH
bootstrap
kubectl apply -f install/kubernetes/istio.yaml
centos
kubectl apply -f install/kubernetes/istio-initializer.yaml
查看是否安裝正常,看istio-pilot
, istio-mixer
, istio-ingress
三個服務是否部署
kubectl get svc -n istio-system
kubectl get svc -n istio-system
查看pods
kubectl get pods -n istio-system
kubectl get pods -n istio-system
這樣istio就安裝完成了
本例子中使用了兩個應用,hello-node和hello-py. hello-node爲nodejs應用,提供一個接口返回一個JSON對象; hello-py爲python應用,調用hello-node提供的接口獲取JSON對象,簡單封裝後並返回到外部調用者(curl/瀏覽器或其餘)
參考的kubernetes官方文檔內容https://kubernetes.io/docs/tutorials/stateless-application/hello-minikube/#create-your-nodejs-application
建立一個目錄nodeserver
, 並建立一個server.js
文件內容以下
var http = require('http'); var handleRequest = function(request, response) { console.log('Received request for URL: ' + request.url); response.writeHead(200, {'Content-Type': 'application/json'}); var data = { "name":"nodejs-istio", "value":"Hello World!" }; response.end(JSON.stringify(data)); }; var www = http.createServer(handleRequest); www.listen(8080);
nodeserver
目錄下新建Dockerfile
,內容以下FROM node:6.9.2 EXPOSE 8080 COPY server.js . CMD node server.js
爲了使用Minikube的docker環境執行
eval $(minikube docker-env)
當再也不使用minikube環境時能夠使用eval $(minikube docker-env -u)
恢復
docker build -t hello-node:v1 .
參考istio官方GitHub中的bookinfo例子https://github.com/istio/istio/blob/master/samples/bookinfo/src/productpage/productpage.py
新建文件夾pythonserver
, 並新建文件productpage.py
,內容以下, 拿官方例子改的
#!/usr/bin/python from flask import Flask, request, render_template, redirect, url_for import simplejson as json import requests import sys from json2html import * import logging import requests # These two lines enable debugging at httplib level (requests->urllib3->http.client) # You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA. # The only thing missing will be the response.body which is not logged. try: import http.client as http_client except ImportError: # Python 2 import httplib as http_client http_client.HTTPConnection.debuglevel = 1 app = Flask(__name__) from flask_bootstrap import Bootstrap Bootstrap(app) def getForwardHeaders(request): headers = {} user_cookie = request.cookies.get("user") if user_cookie: headers['Cookie'] = 'user=' + user_cookie incoming_headers = [ 'x-request-id', 'x-b3-traceid', 'x-b3-spanid', 'x-b3-parentspanid', 'x-b3-sampled', 'x-b3-flags', 'x-ot-span-context' ] for ihdr in incoming_headers: val = request.headers.get(ihdr) if val is not None: headers[ihdr] = val #print "incoming: "+ihdr+":"+val return headers # The UI: @app.route('/') @app.route('/index.html') def index(): headers = getForwardHeaders(request) result = { "code": 200, "data": getProductDetails(headers), "author": "hello-py", "version": "1.0.0" } return json.dumps(result), 200, {'Content-Type': 'application/json'} # Data providers: def getProductDetails(headers): try: url = "http://hello-node:8080" res = requests.get(url, headers=headers, timeout=3.0) except: res = None if res and res.status_code == 200: return res.json() else: status = res.status_code if res is not None and res.status_code else 500 return {'error': 'Sorry, product details are currently unavailable for this book.'} if __name__ == '__main__': if len(sys.argv) < 2: print( "usage: %s port" % (sys.argv[0])) sys.exit(-1) p = int(sys.argv[1]) print( "start at port %s" % (p)) app.run(host='0.0.0.0', port=p, debug=True, threaded=True)
其中url = "http://hello-node:8080"
這裏指定該請求須要路由到hello-node
服務
pythonserver
目錄下新建requirements.txt
文件requests flask flask_json flask_bootstrap json2html simplejson gevent
pythonserver
目錄新建Dockerfile
FROM python:2.7-slim COPY requirements.txt ./ RUN pip install --no-cache-dir -r requirements.txt COPY productpage.py /opt/microservices/ COPY templates /opt/microservices/templates COPY requirements.txt /opt/microservices/ EXPOSE 9080 WORKDIR /opt/microservices CMD python productpage.py 9080
docker build -t hello-py:v1 .
完成後能夠經過docker images
查看是否成功
hello-istio.yaml
apiVersion: v1 kind: Service metadata: name: hello-node labels: app: hello-node spec: ports: - port: 8080 name: http selector: app: hello-node --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: hello-node-v1 spec: replicas: 1 template: metadata: labels: app: hello-node version: v1 spec: containers: - name: hello-node image: hello-node:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 --- ################################################################################################## # Productpage services ################################################################################################## apiVersion: v1 kind: Service metadata: name: hello-py labels: app: hello-py spec: ports: - port: 9080 name: http selector: app: hello-py --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: hello-py-v1 spec: replicas: 1 template: metadata: labels: app: hello-py version: v1 spec: containers: - name: hello-py image: hello-py:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 --- ########################################################################### # Ingress resource (gateway) ########################################################################## apiVersion: extensions/v1beta1 kind: Ingress metadata: name: gateway annotations: kubernetes.io/ingress.class: "istio" spec: rules: - http: paths: - path: / backend: serviceName: hello-py servicePort: 9080 ---
這裏定義了兩個service,一個網關
kubectl apply -f hello-istio.yaml
注: 若是沒有安裝Istio-Initializer ,須要手動注入sidecar
kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/kube/bookinfo.yaml)
完成後能夠查看看Pods
kubectl get pods
kubectl get pods
查看service
kubectl get svc
kubectl get svc
查看是否有istio-proxy
kubectl get pod hello-node-v1-5f8c79f65f-zb24c -o jsonpath='{.spec.containers[*].name}'
或者查看describe
kubectl describe po hello-node-v1-5f8c79f65f-zb24c
當pods中的STATUS
爲Running
狀態時,能夠訪問服務,因爲本地環境使用minikube因此須要以下命令獲取訪問地址
export GATEWAY_URL=$(kubectl get po -l istio=ingress -n istio-system -o 'jsonpath={.items[0].status.hostIP}'):$(kubectl get svc istio-ingress -n istio-system -o 'jsonpath={.spec.ports[0].nodePort}')
使用curl請求
curl $GATEWAY_URL
結果
輸入圖片說明
kubectl delete -f hello-istio.yaml
到此本地istio簡單示例的開發到發佈完成