├── .flaskenv
├── .idea
├── microFaultInjection.iml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── Dockerfile
├── README.md
├── __pycache__
├── config.cpython-37.pyc
├── func_pack.cpython-37.pyc
└── webServer.cpython-37.pyc
├── app
├── __init__.py
├── __pycache__
│ ├── __init__.cpython-37.pyc
│ ├── api.cpython-37.pyc
│ └── routes.cpython-37.pyc
├── api.py
├── routes.py
└── templates
│ ├── base.html
│ └── frontPage.html
├── config.py
├── func_pack.py
├── single_fault_inject.yaml
└── webServer.py
/.flaskenv:
--------------------------------------------------------------------------------
1 | FLASK_APP=webServer.py
--------------------------------------------------------------------------------
/.idea/microFaultInjection.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
177 |
178 |
179 |
180 | cal
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 | true
209 | DEFINITION_ORDER
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 | 1561026242409
307 |
308 |
309 | 1561026242409
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | # Source Image
2 | FROM python:3.7
3 | # Author
4 | MAINTAINER Leon "leontian1024@gmail.com"
5 | # Set working director
6 | WORKDIR /var/app/microFaultInjection
7 | # Add source code from os into container
8 | Add . /var/app/microFaultInjection
9 | # Import packages
10 | RUN pip install Flask
11 | RUN pip install Flask-wtf
12 | RUN pip install flask-bootstrap
13 | # Get Linux Commands
14 | RUN apt-get update
15 | RUN apt-get install -y --allow-unauthenticated stress
16 | RUN apt-get install -y --allow-unauthenticated iperf3
17 | # Expose port
18 | EXPOSE 5000
19 | # Run command
20 | ENTRYPOINT ["python","./webServer.py"]
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 微服务"错误注入Sidecar"使用说明文档
2 | > 作者: 中科院软件所微服务研究项目小组
3 |
4 | > 该项目作者: github.com/XinyaoTian || leontian1024@gmail.com
5 |
6 | ## 项目概述
7 |
8 | 本项目意在构建一个专注于对微服务最小单元进行错误注入的独立服务。
9 |
10 | 将本项目的代码以容器的形式与实际微服务应用部署在同一个微服务单元中,
11 | 通过该模块所提供的 REST API 向其中注入包括"cpu、内存、磁盘和网络"等多种错误,
12 | 对微服务最小单元的资源利用情况进行实验和观测。
13 |
14 | ## 快速开始
15 | 项目根目录下的 single_fault_injection.yaml 可以直接将本应用
16 | 以 Deployment 的形式部署在您的 K8s 或 Istio 上;
17 | 并对外暴露 30050 端口
18 |
19 | >这个 yaml 限制了容器资源最大 CPU 使用率不超过 0.4; 最大使用内存不超过 128M。
20 | >设置这个上限可以帮助您直观地感受到错误的注入。
21 |
22 | ```bash
23 | # 直接通过 yaml 部署于 K8s 或 Istio (K8s 版本 1.13.1 / Istio 1.0.6 通过测试)
24 | kubectl apply -f https://raw.githubusercontent.com/iscas-microservice-team/microFaultInjection/master/single_fault_inject.yaml
25 | ```
26 |
27 | 现在,访问您 K8s 或 Istio 集群的 30050 端口,看到用户使用指导页面,就证明部署成功了。
28 | 接下来,您就可以通过提供的 API 进行各式错误注入了。
29 |
30 | ## 使用方法
31 | >备注: 本"使用方法"亦可在启动服务后,通过服务的 / 或 /usage 这两种 url 进行查看
32 |
33 | 本项目基于 REST API 理念进行设计,故进行错误注入时需使用 POST 方式,
34 | 向指定 url 发送注入信息。
35 |
36 | 错误注入的 POST 请求发送示例如下( **注意改变 IP 与端口号** ):
37 |
38 | 1. 注入 CPU 故障
39 |
40 | ```bash
41 | # fault_type=cpu 指定错误故障类型(此处为 cpu 类型)
42 | # thread_num=4 触发该错误的线程数(此处为 4 个线程)
43 | # duration=15 故障持续时间,单位为秒(此处为 15 秒)
44 | curl -X POST -d 'fault_type=cpu&thread_num=4&duration=15' http://localhost:5000/fault-inject
45 | ```
46 |
47 | 2. 注入内存故障
48 |
49 | ```bash
50 | # fault_type=mem 指定错误故障类型(此处为 mem 类型)
51 | # mem_size=120M 指定内存泄露的数值(此处为 120M ,注意 M 不能省略)
52 | # thread_num=4 触发该错误的线程数(此处为 4 个线程)
53 | # duration=15 故障持续时间,单位为秒(此处为 15 秒)
54 | curl -X POST -d 'fault_type=mem&mem_size=120M&thread_num=4&duration=15' http://localhost:5000/fault-inject
55 | ```
56 |
57 | 3. 注入磁盘故障
58 |
59 | ```bash
60 | # fault_type=disk 指定错误故障类型(此处为 disk 类型)
61 | # io_times=4
62 | # duration=15 故障持续时间,单位为秒(此处为 15 秒)
63 | curl -X POST -d 'fault_type=disk&io_times=4&duration=15' http://localhost:5000/fault-inject
64 | ```
65 |
66 | 4. 注入网络故障
67 |
68 | ```bash
69 | # fault_type=net 指定错误故障类型(此处为 net 类型)
70 | # net_port=100
71 | curl -X POST -d 'fault_type=net&net_port=100' http://localhost:5000/fault-inject
72 | ```
73 |
74 | ## 运行条件
75 |
76 | 本项目基于 Linux Distribution 操作系统的多种命令进行错误注入,
77 | 若想在本地直接运行本项目,请确保满足以下条件:
78 |
79 | 1. 操作系统必须为 Linux Distribution (本项目在 Ubuntu 16.04 系统上通过测试)
80 | 2. 具有 python3.7 运行环境以及相应的 Flask, Flask-wtf,flask-bootstrap 工具库
81 | 3. 安装了 stress 命令工具
82 | 4. 安装了 iperf3 命令工具
83 | 5. 确保设备的 5000 端口未被占用
84 |
85 | 或使用 dockerhub 获取我们封装好的镜像,并在容器内部映射 5000 端口至外部
86 |
87 | ```bash
88 | # 使用 docker 简单测试该应用( docker 版本需高于 18.03-ce )
89 | docker run --rm -it -d --name fault-injection-server -p 5000:5000 xinyaotian/micro-fault-injection:1.0.0
90 | ```
91 |
92 | 同样,你也可以利用本项目根目录下的 Dockerfile 自行进行封装
93 |
94 | 封装命令如下:
95 | ```bash
96 | # 首先需进入该项目的目录 microFaultInjection/ 中, 再运行下面的命令
97 | docker build -t your-docker-name/project-name:1.0 .
98 | ```
99 |
100 | ## Yaml编写示例( 以 Sidecar 形式将本项目部署于微服务中 )
101 |
102 | 本项目的镜像将作为原本微服务应用的 Sidecar 独立部署运行,
103 | 因此在 K8s 环境中其应该与业务应用部署于同一个 Pod 之中。
104 |
105 | 在 K8s 环境下部署和启动的 yaml 如下所示意( Istio 同样可以这样写 ):
106 |
107 | ```yaml
108 |
109 | ---
110 | # 为 fault injection 创建 service 分配端口 #
111 | ---
112 | apiVersion: v1
113 | kind: Service
114 | metadata:
115 | name: your-microapp-with-faultinjection
116 | namespace: default
117 | spec:
118 | selector:
119 | # deployment identifier
120 | # 这个标签要与 deployment 中相对应
121 | app: sidecar-fault-injection
122 | ports:
123 | - protocol: TCP
124 | port: 5000
125 | nodePort: 30050
126 | type: NodePort
127 | ---
128 | # 相应的 deployment 配置( 与原应用配置在一起 )
129 | ---
130 | apiVersion: extensions/v1beta1
131 | kind: Deployment
132 | metadata:
133 | name: your-microapp-with-faultinjection
134 | namespace: default
135 | spec:
136 | replicas: 1
137 | template:
138 | metadata:
139 | labels:
140 | # svc identifier
141 | # 这个标签要与 service 中相对应
142 | app: sidecar-fault-injection
143 | spec:
144 | containers:
145 | # 你原来应用的 container 信息
146 | - name: your-micro-app
147 | image: your-docker-name/project:1.0
148 | imagePullPolicy: IfNotPresent
149 | env:
150 | - name: PATH_VALUE
151 | value: "example"
152 | ports:
153 | - containerPort: 80
154 | # ------------------- #
155 | # Sidecar 错误注入模块的 container
156 | - name: fault-injection-sidecar
157 | image: xinyaotian/micro-fault-injection:1.0.0
158 | imagePullPolicy: IfNotPresent
159 | ports:
160 | - containerPort: 5000
161 | # ------------------- #
162 | ---
163 |
164 | ```
165 |
166 |
--------------------------------------------------------------------------------
/__pycache__/config.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iscas-microservice-team/microFaultInjection/2a786a772076bb94c9d97842f00570a20d6c6eff/__pycache__/config.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/func_pack.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iscas-microservice-team/microFaultInjection/2a786a772076bb94c9d97842f00570a20d6c6eff/__pycache__/func_pack.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/webServer.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iscas-microservice-team/microFaultInjection/2a786a772076bb94c9d97842f00570a20d6c6eff/__pycache__/webServer.cpython-37.pyc
--------------------------------------------------------------------------------
/app/__init__.py:
--------------------------------------------------------------------------------
1 | from flask import Flask
2 | from config import Config
3 | from flask_bootstrap import Bootstrap
4 |
5 | app = Flask(__name__)
6 | app.config.from_object(Config)
7 | bootstrap = Bootstrap(app)
8 |
9 | from app import routes, api
10 |
--------------------------------------------------------------------------------
/app/__pycache__/__init__.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iscas-microservice-team/microFaultInjection/2a786a772076bb94c9d97842f00570a20d6c6eff/app/__pycache__/__init__.cpython-37.pyc
--------------------------------------------------------------------------------
/app/__pycache__/api.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iscas-microservice-team/microFaultInjection/2a786a772076bb94c9d97842f00570a20d6c6eff/app/__pycache__/api.cpython-37.pyc
--------------------------------------------------------------------------------
/app/__pycache__/routes.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iscas-microservice-team/microFaultInjection/2a786a772076bb94c9d97842f00570a20d6c6eff/app/__pycache__/routes.cpython-37.pyc
--------------------------------------------------------------------------------
/app/api.py:
--------------------------------------------------------------------------------
1 | from app import app
2 | from flask import jsonify
3 | from flask import request
4 | from func_pack import fault_injection
5 |
6 |
7 | # API-test GET Method
8 | @app.route('/test-api', methods=['GET'])
9 | def test_get():
10 | data = [
11 | {'test-api': 'API Test Success.'}
12 | ]
13 | return jsonify(data)
14 |
15 |
16 | # Fault-Injection Method
17 | @app.route('/fault-inject', methods=['POST'])
18 | def inject_fault():
19 | fault_type = request.form.get('fault_type')
20 | thread_num = request.form.get('thread_num')
21 | duration = request.form.get('duration')
22 | mem_size = request.form.get('mem_size')
23 | io_times = request.form.get('io_times')
24 | net_port = request.form.get('net_port')
25 | net_flag = request.form.get('net_flag')
26 | # deliver all the args from POST into fault_injection
27 | result = fault_injection(fault_type, thread_num=thread_num, duration=duration, mem_size=mem_size,
28 | io_times=io_times, net_port=net_port, net_flag=net_flag)
29 | if result is not None:
30 | return jsonify(result)
31 | else:
32 | info = [
33 | {'Info': 'Your faults are injecting. Please wait.'}
34 | ]
35 | return jsonify(info)
36 |
--------------------------------------------------------------------------------
/app/routes.py:
--------------------------------------------------------------------------------
1 | from app import app
2 | from flask import render_template
3 |
4 |
5 | @app.route('/')
6 | @app.route('/usage')
7 | def usage():
8 | return render_template('frontPage.html', title='API Usage Guide')
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/templates/base.html:
--------------------------------------------------------------------------------
1 | {% extends 'bootstrap/base.html' %}
2 | {% block title %}
3 | {% if title %}
4 | {{ title }} - Fault Injection
5 | {% else %}
6 | Spirit Connection
7 | {% endif %}
8 | {% endblock %}
9 |
10 | {% block navbar %}
11 |
36 | {% endblock %}
37 |
38 | {% block content %}
39 |
40 | {% with messages = get_flashed_messages() %}
41 | {% if messages %}
42 | {% for message in messages %}
43 |
{{ message }}
44 | {% endfor %}
45 | {% endif %}
46 | {% endwith %}
47 | {# application content needs to be provided in the app_content block #}
48 | {# So, others templates should write about this part #}
49 | {% block app_content %}{% endblock %}
50 |
51 | {% endblock %}
52 |
53 |
--------------------------------------------------------------------------------
/app/templates/frontPage.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block app_content %}
4 |
5 | 使用方法
6 |
7 | 本项目基于 REST API 理念进行设计,故进行错误注入时需使用 POST 方式,
8 | 向指定 url 发送注入信息。
9 | 项目地址: https://github.com/iscas-microservice-team/microFaultInjection
10 |
11 |
12 |
13 | 1. 注入 CPU 故障
14 |
15 |
16 | # fault_type=cpu 指定错误故障类型(此处为 cpu 类型)
17 | # thread_num=4 触发该错误的线程数(此处为 4 个线程)
18 | # duration=15 故障持续时间,单位为秒(此处为 15 秒)
19 | curl -X POST -d 'fault_type=cpu&thread_num=4&duration=15' http://localhost:5000/fault-inject
20 |
21 |
22 |
23 |
24 | 2. 注入内存故障
25 |
26 |
27 | # fault_type=mem 指定错误故障类型(此处为 mem 类型)
28 | # mem_size=120M 指定内存泄露的数值(此处为 120M ,注意 M 不能省略)
29 | # thread_num=4 触发该错误的线程数(此处为 4 个线程)
30 | # duration=15 故障持续时间,单位为秒(此处为 15 秒)
31 | curl -X POST -d 'fault_type=mem&mem_size=120M&thread_num=4&duration=15' http://localhost:5000/fault-inject
32 |
33 |
34 | 3. 注入磁盘故障
35 |
36 |
37 | # fault_type=disk 指定错误故障类型(此处为 disk 类型)
38 | # io_times=4
39 | # duration=15 故障持续时间,单位为秒(此处为 15 秒)
40 | curl -X POST -d 'fault_type=disk&io_times=4&duration=15' http://localhost:5000/fault-inject
41 |
42 |
43 | 4. 注入网络故障
44 |
45 |
46 | # fault_type=net 指定错误故障类型(此处为 net 类型)
47 | # net_port=100
48 | curl -X POST -d 'fault_type=net&net_port=100' http://localhost:5000/fault-inject
49 |
50 |
51 | {% endblock %}
52 |
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | import os
2 | basedir = os.path.abspath(os.path.dirname(__file__))
3 |
4 |
5 | class Config(object):
6 |
7 | SECRET_KEY = os.environ.get('SECRET_KEY') or 'abcdef020301abc8c86f'
8 |
--------------------------------------------------------------------------------
/func_pack.py:
--------------------------------------------------------------------------------
1 | # -*- coding: UTF-8 -*-
2 | import os
3 | import time
4 | import logging
5 |
6 |
7 | # 将薛师兄代码里的数字转变为更加易懂的参数输入
8 | def fault_injection(fault_type, **kwargs):
9 | logging.info("Ready to inject fault.")
10 | # fault_type have 4 types: 'cpu', 'mem', 'disk', 'net'
11 | if fault_type == 'cpu':
12 | print("cpu error injection")
13 | logging.info(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
14 | # CPU Fault has 2 args: thread_num, duration
15 | if 'thread_num' not in kwargs or kwargs['thread_num'] is None:
16 | thread_num = '4'
17 | else:
18 | thread_num = kwargs['thread_num']
19 | if 'duration' not in kwargs or kwargs['duration'] is None:
20 | duration = '15'
21 | else:
22 | duration = kwargs['duration']
23 | # 切分为多进程
24 | pid = os.fork()
25 | # 子进程负责错误注入
26 | if pid == 0:
27 | # using linux command to inject faults.
28 | os.system("stress -c %s -t %s" % (thread_num, duration))
29 | # 父进程负责返回注入结果并继续监听 Server 端口
30 | else:
31 | logging.info("stress -c %s -t %s" % (thread_num, duration))
32 | info = [
33 | {'status': 'success'},
34 | {'fault_type': '%s' % fault_type},
35 | {'description': 'Your arguments of injection are thread_num=%s, duration=%s.' % (thread_num, duration)}
36 | ]
37 | return info
38 |
39 | elif fault_type == 'mem':
40 | logging.info(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
41 | # Memory Fault has 3 args: thread_num, mem_size, duration
42 | if 'thread_num' not in kwargs or kwargs['thread_num'] is None:
43 | thread_num = '4'
44 | else:
45 | thread_num = kwargs['thread_num']
46 | if 'mem_size' not in kwargs or kwargs['mem_size'] is None:
47 | mem_size = '128M'
48 | else:
49 | mem_size = kwargs['mem_size']
50 | if 'duration' not in kwargs or kwargs['duration'] is None:
51 | duration = '15'
52 | else:
53 | duration = kwargs['duration']
54 |
55 | pid = os.fork()
56 | if pid == 0:
57 | os.system("stress --vm %s --vm-bytes %s --vm-keep -t %s" % (thread_num, mem_size, duration))
58 | else:
59 | logging.info("stress --vm %s --vm-bytes %s --vm-keep -t %s" % (thread_num, mem_size, duration))
60 | info = [
61 | {'status': 'success'},
62 | {'fault_type': '%s' % fault_type},
63 | {'description': 'Your arguments of injection are thread_num=%s, mem_size=%s, duration=%s.' % (thread_num, mem_size, duration)}
64 | ]
65 | return info
66 |
67 | # iostat -x -k -d 1
68 | elif fault_type == 'disk':
69 | logging.info(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
70 | # args
71 | if 'io_times' not in kwargs or kwargs['io_times'] is None:
72 | io_times = '4'
73 | else:
74 | io_times = kwargs['io_times']
75 | if 'duration' not in kwargs or kwargs['duration'] is None:
76 | duration = '15'
77 | else:
78 | duration = kwargs['duration']
79 |
80 | pid = os.fork()
81 | if pid == 0:
82 | os.system("stress -i %s -t %s" % (io_times, duration))
83 | else:
84 | logging.info("stress -i %s -t %s" % (io_times, duration))
85 | info = [
86 | {'status': 'success'},
87 | {'fault_type': '%s' % fault_type},
88 | {'description': 'Your arguments of injection are io_times=%s, duration=%s.' % (io_times, duration)}
89 | ]
90 | return info
91 |
92 | elif fault_type == 'net':
93 | logging.info(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
94 | if 'net_port' not in kwargs or kwargs['net_port'] is None:
95 | net_port = '100'
96 | else:
97 | net_port = kwargs['net_port']
98 |
99 | pid = os.fork()
100 | if pid == 0:
101 | os.system("iperf3 -s -p %s" % net_port)
102 | else:
103 | logging.info("iperf3 -s -p %s" % net_port)
104 | info = [
105 | {'status': 'success'},
106 | {'fault_type': '%s' % fault_type},
107 | {'description': 'Your arguments of injection are net_port=%s.' % net_port}
108 | ]
109 | return info
110 |
111 | # 若错误类型不在这4种之内,则返回 None
112 | else:
113 | error = [
114 | {'status': 'error'},
115 | {'description': 'fault_type must in the range of cpu, mem, dish and net. Your fault_type is %s.' % fault_type}
116 | ]
117 | return error
118 |
119 | pass
120 |
121 |
122 | if __name__ == '__main__':
123 | fault_injection('cpu')
124 |
125 |
--------------------------------------------------------------------------------
/single_fault_inject.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | # 为 fault injection 创建 service 分配端口 #
3 | ---
4 | apiVersion: v1
5 | kind: Service
6 | metadata:
7 | name: single-fault-injection
8 | namespace: default
9 | spec:
10 | selector:
11 | # deployment identifier
12 | # 这个标签要与 deployment 中相对应
13 | app: fault-injection
14 | ports:
15 | - protocol: TCP
16 | port: 5000 # 容器内端口为 5000
17 | nodePort: 30050 # 映射至主机的 30050 端口
18 | type: NodePort # 映射方式为 NodePort
19 | ---
20 | # 将该模块作为一个独立的 Pod 在 K8s 上进行部署 #
21 | ---
22 | apiVersion: extensions/v1beta1
23 | kind: Deployment
24 | metadata:
25 | name: single-fault-injection
26 | namespace: default
27 | spec:
28 | replicas: 1
29 | template:
30 | metadata:
31 | labels:
32 | # svc identifier
33 | # 这个标签要与 service 中相对应
34 | app: fault-injection
35 | spec:
36 | containers:
37 | # 错误注入模块的 container
38 | - name: fault-injection-container
39 | image: xinyaotian/micro-fault-injection:1.0.0
40 | imagePullPolicy: IfNotPresent
41 | ports:
42 | - containerPort: 5000
43 | # 该容器的资源限制, 错误注入可使其达到峰值 #
44 | resources:
45 | limits:
46 | cpu: "0.4"
47 | memory: 128Mi
--------------------------------------------------------------------------------
/webServer.py:
--------------------------------------------------------------------------------
1 | from app import app
2 | import logging
3 | logging.basicConfig(level=logging.INFO)
4 |
5 | if __name__ == '__main__':
6 | app.run(host='0.0.0.0', port=5000, debug=False)
7 |
--------------------------------------------------------------------------------