nginx

[TOC]

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
173
174
175
176
177
178
179
180
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
209
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
307
308
309
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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
Nginx:engine X
NGINX is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server. NGINX is known for its high performance, stability, rich feature set, simple configuration, and low resource consumption.(nginx是一个自由的,开源的,高性能的http服务和反向代理。同时也可以是IMAP/POP3反向代理。以他的高性能,高稳定性,丰富的特性设置,简单的配置以及很低的资源消耗而闻名)。
功能特点如下:
http协议:web服务器(类似于httpd)、http reverse proxy(类似于httpd)、imap/pop3 reverse proxy
C10K(10K Connections)超10k的并发连接数。
nginx的衍生版本:Tengine, OpenResty.

Nginx的程序架构:
master/worker:一个master进程,多个worker进程
master:负载加载和分析配置文件、管理worker进程、平滑升级
worker:处理并响应用户请求
缓存相关的进程:
cache loader:载入缓存对象
cache manager:管理缓存对象

特性:异步、事件驱动和非阻塞
并发请求处理:通过kevent/epoll/select,/dev/poll
文件IO:高级IO sendfile,异步,mmap

nginx高度模块:高度模块化,但其模块早期不支持DSO机制;近期版本支持动态装载和卸载;
模块分类:
核心模块:core module
标准模块:
HTTP modules:
Standard HTTP modules
Optional HTTP modules
Mail modules
Stream modules
3rd party modules

nginx的功用:
静态的web资源服务器;(图片服务器,或js/css/html/txt等静态资源服务器)
结合FastCGI/uwSGI/SCGI等协议反代动态资源请求;
http/https协议的反向代理;
imap4/pop3协议的反向代理;
tcp/udp协议的请求转发;

nginx的安装配置:
官方的预制包:
http://nginx.org/packages/centos/7/x86_64/RPMS/
Fedora-EPEL:

编译安装:
# yum install pcre-devel openssl-devel zlib-devel(依赖工具包)
# useradd -r nginx
# ./configure --prefix=/usr/local/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_dav_module --with-http_stub_status_module --with-threads --with-file-aio
# make && make install

配置:
配置文件的组成部分:
主配置文件:/etc/nginx/nginx.conf
include /etc/nginx/conf.d/*.conf
fastcgi, uwsgi,scgi等协议相关的配置文件
mime.types:支持的mime类型

主配置文件的配置指令:
directive value [value2 ...];

注意:
(1) 指令必须以分号结尾;
(2) 支持使用配置变量;
内建变量:由Nginx模块引入,可直接引用;所有的内建变量可在ngx_http_core_module 模块说明文档的 Embedded Variables 部分找到
自定义变量:由用户使用set命令定义;
set variable_name value;
引用变量:$variable_name

主配置文件结构:
main block:主配置段,也即全局配置段;
event { ... }:事件驱动相关的配置;
http { ... }:http/https 协议相关的配置段;
mail { ... }:邮件工具的配置段;
stream { ... }:TCP udp 相关


http协议相关的配置结构
http {
...
...:各server的公共配置
server {
...
}:每个server用于定义一个虚拟主机;
server {
...
server_name
root
alias
location [OPERATOR] URL {
...
if CONDITION {
...
}
}
}
}

main配置段常见的配置指令:
分类:
正常运行必备的配置
优化性能相关的配置
用于调试及定位问题相关的配置
事件驱动相关的配置

正常 运行必备的配置:
1、user
Syntax: user user [group];
Default: user nobody nobody;
Context: main

Defines user and group credentials used by worker processes. If group is omitted, a group whose name equals that of user is used.

2、pid /PATH/TO/PID_FILE;
指定存储nginx主进程进程号码的文件路径;

3、include file | mask;
指明包含进来的其它配置文件片断;

4、load_module file;
指明要装载的动态模块;

性能优化相关的配置:
1、worker_processes number | auto;
worker进程的数量;通常应该为当前主机的cpu的物理核心数;

2、worker_cpu_affinity cpumask ...;
worker_cpu_affinity auto [cpumask];

CPU MASK:
00000001:0号CPU
00000010:1号CPU
... ...
3、worker_priority number;
指定worker进程的nice值,设定worker进程优先级;[-20,20]

4、worker_rlimit_nofile number;
worker进程所能够打开的文件数量上限;

调试、定位问题:
1、daemon on|off;
是否以守护进程方式运行Nignx;

2、master_process on|off;
是否以master/worker模型运行nginx;默认为on;

3、error_log file [level];

事件驱动相关的配置:
events {
...
}

1、worker_connections number;
每个worker进程所能够打开的最大并发连接数数量;

worker_processes * worker_connections

2、use method;
指明并发连接请求的处理方法;

use epoll;

3、accept_mutex on | off;
处理新的连接请求的方法;on意味着由各worker轮流处理新请求,Off意味着每个新请求的到达都会通知所有的worker进程;

Nginx配置:
http协议的相关配置:
http {
... ...
server {
...
server_name
root
location [OPERATOR] /uri/ {
...
}
}
server {
...
}
}

与套接字相关的配置:

1、server { ... }
配置一个虚拟主机;

server {
listen address[:PORT]|PORT;
server_name SERVER_NAME;
root /PATH/TO/DOCUMENT_ROOT;
}

2、listen PORT|address[:port]|unix:/PATH/TO/SOCKET_FILE
listen address[:port] [default_server] [ssl] [http2 | spdy] [backlog=number] [rcvbuf=size] [sndbuf=size]

default_server:设定为默认虚拟主机;
ssl:限制仅能够通过ssl连接提供服务;
backlog=number:后援队列长度;
rcvbuf=size:接收缓冲区大小;
sndbuf=size:发送缓冲区大小;

3、server_name name ...;
指明虚拟主机的主机名称;后可跟多个由空白字符分隔的字符串;
支持*通配任意长度的任意字符;server_name *.magedu.com www.magedu.*
支持~起始的字符做正则表达式模式匹配;server_name ~^www\d+\.magedu\.com$

匹配机制:
(1) 首先是字符串精确匹配;
(2) 左侧*通配符;
(3) 右侧*通配符;
(4) 正则表达式;

练习:定义四个虚拟主机,混合使用三种类型的虚拟主机;
仅开放给来自于本地网络中的主机访问;

4、tcp_nodelay on | off;
在keepalived模式下的连接是否启用TCP_NODELAY选项;

5、sendfile on | off;
是否启用sendfile功能;

定义路径相关的配置:
6、root path;
设置web资源路径映射;用于指明用户请求的url所对应的本地文件系统上的文档所在目录路径;可用的位置:http, server, location, if in location;

7、location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }

在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;ngnix会根据用户请求的URI来检查定义的所有location,并找出一个最佳匹配,而后应用其配置;

=:对URI做精确匹配;例如, http://www.magedu.com/, http://www.magedu.com/index.html
location = / {
...
}
~:对URI做正则表达式模式匹配,区分字符大小写;
~*:对URI做正则表达式模式匹配,不区分字符大小写;
^~:对URI的左半部分做匹配检查,不区分字符大小写;
不带符号:匹配起始于此uri的所有的url;

匹配优先级:=, ^~, ~/~*,不带符号;

root /vhosts/www/htdocs/
http://www.magedu.com/index.html --> /vhosts/www/htdocs/index.html

server {
root /vhosts/www/htdocs/

location /admin/ {
root /webapps/app1/data/
}
}

8、alias path;
定义路径别名,文档映射的另一种机制;仅能用于location上下文;

注意:location中使用root指令和alias指令的意义不同;
(a) root,给定的路径对应于location中的/uri/左侧的/;
(b) alias,给定的路径对应于location中的/uri/右侧的/;

9、index file ...;
默认资源;http, server, location;

10、error_page code ... [=[response]] uri;
Defines the URI that will be shown for the specified errors.

11、try_files file ... uri;

定义客户端请求的相关配置

12、keepalive_timeout timeout [header_timeout];
设定保持连接的超时时长,0表示禁止长连接;默认为75s;

13、keepalive_requests number;
在一次长连接上所允许请求的资源的最大数量,默认为100;

14、keepalive_disable none | browser ...;
对哪种浏览器禁用长连接;

15、send_timeout time;
向客户端发送响应报文的超时时长,此处,是指两次写操作之间的间隔时长;

16、client_body_buffer_size size;
用于接收客户端请求报文的body部分的缓冲区大小;默认为16k;超出此大小时,其将被暂存到磁盘上的由client_body_temp_path指令所定义的位置;

17、client_body_temp_path path [level1 [level2 [level3]]];
设定用于存储客户端请求报文的body部分的临时存储路径及子目录结构和数量;

16进制的数字;

client_body_temp_path path /var/tmp/client_body 1 2 2

对客户端进行限制的相关配置:
18、limit_rate rate;
限制响应给客户端的传输速率,单位是bytes/second,0表示无限制;

19、limit_except method ... { ... }
限制对指定的请求方法之外的其它方法的使用客户端;

limit_except GET {
allow 192.168.1.0/24;
deny all;
}

文件操作优化的配置
20、aio on | off | threads[=pool];
是否启用aio功能;

21、directio size | off;
在Linux主机启用O_DIRECT标记,此处意味文件大于等于给定的大小时使用,例如directio 4m;

22、open_file_cache off;
open_file_cache max=N [inactive=time];
nginx可以缓存以下三种信息:
(1) 文件的描述符、文件大小和最近一次的修改时间;
(2) 打开的目录结构;
(3) 没有找到的或者没有权限访问的文件的相关信息;

max=N:可缓存的缓存项上限;达到上限后会使用LRU算法实现缓存管理;

inactive=time:缓存项的非活动时长,在此处指定的时长内未被命中的或命中的次数少于open_file_cache_min_uses指令所指定的次数的缓存项即为非活动项;

23、open_file_cache_valid time;
缓存项有效性的检查频率;默认为60s;

24、open_file_cache_min_uses number;
在open_file_cache指令的inactive参数指定的时长内,至少应该被命中多少次方可被归类为活动项;

25、open_file_cache_errors on | off;
是否缓存查找时发生错误的文件一类的信息;

ngx_http_access_module模块:
实现基于ip的访问控制功能

26、allow address | CIDR | unix: | all;
27、deny address | CIDR | unix: | all;

http, server, location, limit_except

ngx_http_auth_basic_module模块
实现基于用户的访问控制,使用basic机制进行用户认证;

28、auth_basic string | off;
29、auth_basic_user_file file;

location /admin/ {
alias /webapps/app1/data/;
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.ngxpasswd;
}

注意:htpasswd命令由httpd-tools所提供;

ngx_http_stub_status_module模块
用于输出nginx的基本状态信息;

Active connections: 291
server accepts handled requests
16630948 16630948 31070465
Reading: 6 Writing: 179 Waiting: 106

Active connections: 活动状态的连接数;
accepts:已经接受的客户端请求的总数;
handled:已经处理完成的客户端请求的总数;
requests:客户端发来的总的请求数;
Reading:处于读取客户端请求报文首部的连接的连接数;
Writing:处于向客户端发送响应报文过程中的连接数;
Waiting:处于等待客户端发出请求的空闲连接数;

30、stub_status;

配置示例:
location /basic_status {
stub_status;
}

ngx_http_log_module模块
the ngx_http_log_module module writes request logs in the specified format.

31、log_format name string ...;
string可以使用nginx核心模块及其它模块内嵌的变量;

课外作业:为nginx定义使用类似于httpd的combined格式的访问日志;

32、access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;

访问日志文件路径,格式及相关的缓冲的配置;
buffer=size
flush=time

33、open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
open_log_file_cache off;
缓存各日志文件相关的元数据信息;

max:缓存的最大文件描述符数量;
min_uses:在inactive指定的时长内访问大于等于此值方可被当作活动项;
inactive:非活动时长;
valid:验正缓存中各缓存项是否为活动项的时间间隔;

ngx_http_gzip_module:
The ngx_http_gzip_module module is a filter that compresses responses using the “gzip” method. This often helps to reduce the size of transmitted data by half or even more.

1、gzip on | off;
Enables or disables gzipping of responses.

2、gzip_comp_level level;
Sets a gzip compression level of a response. Acceptable values are in the range from 1 to 9.

3、 gzip_disable regex ...;
Disables gzipping of responses for requests with “User-Agent” header fields matching any of the specified regular expressions.

4、 gzip_min_length length;
启用压缩功能的响应报文大小阈值;

5、gzip_buffers number size;
支持实现压缩功能时为其配置的缓冲区数量及每个缓存区的大小;

6、gzip_proxied off | expired | no-cache | no-store | private | no_last_modified | no_etag | auth | any ...;
nginx作为代理服务器接收到从被代理服务器发送的响应报文后,在何种条件下启用压缩功能的;
off:对代理的请求不启用
no-cache, no-store,private:表示从被代理服务器收到的响应报文首部的Cache-Control的值为此三者中任何一个,则启用压缩功能;

7、gzip_types mime-type ...;
压缩过滤器,仅对此处设定的MIME类型的内容启用压缩功能;

示例:
gzip on;
gzip_comp_level 6;
gzip_min_length 64;
gzip_proxied any;
gzip_types text/xml text/css application/javascript;

ngx_http_ssl_module模块:

1、 ssl on | off;
Enables the HTTPS protocol for the given virtual server.

2、ssl_certificate file;
当前虚拟主机使用PEM格式的证书文件;

3、ssl_certificate_key file;
当前虚拟主机上与其证书匹配的私钥文件;

4、ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
支持ssl协议版本,默认为后三个;

5、ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
builtin[:size]:使用OpenSSL内建的缓存,此缓存为每worker进程私有;

[shared:name:size]:在各worker之间使用一个共享的缓存;

6、ssl_session_timeout time;
客户端一侧的连接可以复用ssl session cache中缓存 的ssl参数的有效时长;

配置示例:
server {
listen 443 ssl;
server_name www.magedu.com;
root /vhosts/ssl/htdocs;
ssl on;
ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;
ssl_session_cache shared:sslcache:20m;
}

ngx_http_rewrite_module模块:

The ngx_http_rewrite_module module is used to change request URI using PCRE regular expressions, return redirects, and conditionally select configurations.

bbs.magedu.com/ --> www.magedu.com/bbs/, http://www.magedu.com/ --> https://www.magedu.com/
http://www.magedu.com/login.php;username=tom --> http://www.magedu.com/tom/


将用户请求的URI基于regex所描述的模式进行检查,而后完成替换;

1、rewrite regex replacement [flag]
将用户请求的URI基于regex所描述的模式进行检查,匹配到时将其替换为replacement指定的新的URI;

注意:如果在同一级配置块中存在多个rewrite规则,那么会自下而下逐个检查;被某条件规则替换完成后,会重新一轮的替换检查,因此,隐含有循环机制;[flag]所表示的标志位用于控制此循环机制;

如果replacement是以http://或https://开头,则替换结果会直接以重向返回给客户端;
301:永久重定向;

[flag]:
last:重写完成后停止对当前URI在当前location中后续的其它重写操作,而后对新的URI启动新一轮重写检查;提前重启新一轮循环;
break:重写完成后停止对当前URI在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环;
redirect:重写完成后以临时重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;不能以http://或https://开头;
permanent:重写完成后以永久重定向方式直接返回重写后生成的新URI给客户端,由客户端重新发起请求;

2、return
return code [text];
return code URL;
return URL;

Stops processing and returns the specified code to a client.

3、 rewrite_log on | off;
是否开启重写日志;

4、 if (condition) { ... }
引入一个新的配置上下文 ;条件满足时,执行配置块中的配置指令;server, location;

condition:
比较操作符:
==
!=
~:模式匹配,区分字符大小写;
~*:模式匹配,不区分字符大小写;
!~:模式不匹配,区分字符大小写;
!~*:模式不匹配,不区分字符大小写;
文件及目录存在性判断:
-e, !-e
-f, !-f
-d, !-d
-x, !-x

5、set $variable value;
用户自定义变量 ;

ngx_http_referer_module模块:
The ngx_http_referer_module module is used to block access to a site for requests with invalid values in the “Referer” header field.

1、valid_referers none | blocked | server_names | string ...;
定义referer首部的合法可用值;

none:请求报文首部没有referer首部;
blocked:请求报文的referer首部没有值;
server_names:参数,其可以有值作为主机名或主机名模式;
arbitrary_string:直接字符串,但可使用*作通配符;
regular expression:被指定的正则表达式模式匹配到的字符串;要使用~打头,例如 ~.*\.magedu\.com;

配置示例:
valid_referers none block server_names *.magedu.com *.mageedu.com magedu.* mageedu.* ~\.magedu\.;

if($invalid_referer) {
return 403;
}


ngx_http_proxy_module模块:

The ngx_http_proxy_module module allows passing requests to another server.(该模块可以是实现请求转发功能)

1、proxy_pass URL;
Context: location, if in location, limit_except

注意:proxy_pass后面的路径不带uri时,其会将location的uri传递给后端主机;

server {
...
server_name HOSTNAME;
location /uri/ {
proxy http://host[:port];
}
...
}

http://HOSTNAME/uri --> http://host/uri

proxy_pass后面的路径是一个uri时,其会将location的uri替换为proxy_pass的uri;

server {
...
server_name HOSTNAME;
location /uri/ {
proxy http://host/new_uri/;
}
...
}

http://HOSTNAME/uri/ --> http://host/new_uri/

如果location定义其uri时使用了正则表达式的模式,则proxy_pass之后必须不能使用uri; 用户请求时传递的uri将直接附加代理到的服务的之后;

server {
...
server_name HOSTNAME;
location ~|~* /uri/ {
proxy http://host;
}
...
}

http://HOSTNAME/uri/ --> http://host/uri/;

2、proxy_set_header field value;
设定发往后端主机的请求报文的请求首部的值;Context: http, server, location

proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

3、proxy_cache_path
定义可用于proxy功能的缓存;Context: http

proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

4、proxy_cache zone | off;
指明要调用的缓存,或关闭缓存机制;Context: http, server, location

5、 proxy_cache_key string;
缓存中用于“键”的内容;

默认值:proxy_cache_key $scheme$proxy_host$request_uri;

6、proxy_cache_valid [code ...] time;
定义对特定响应码的响应内容的缓存时长;

定义在http{...}中;
proxy_cache_path /var/cache/nginx/proxy_cache levels=1:1:1 keys_zone=pxycache:20m max_size=1g;

定义在需要调用缓存功能的配置段,例如server{...};
proxy_cache pxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 1h;
proxy_cache_valid any 1m;

7、proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...;

Determines in which cases a stale cached response can be used when an error occurs during communication with the proxied server.(当与代理服务器通信错误时,应该返回那种结果给客户端)

8、proxy_cache_methods GET | HEAD | POST ...;
If the client request method is listed in this directive then the response will be cached. “GET” and “HEAD” methods are always added to the list, though it is recommended to specify them explicitly. 设定允许客户端请求的方式,get和head默认都会有

9、proxy_hide_header field;
By default, nginx does not pass the header fields “Date”, “Server”, “X-Pad”, and “X-Accel-...” from the response of a proxied server to a client. The proxy_hide_header directive sets additional fields that will not be passed.设置隐藏服务器返回给客户端的报文的头部信息,

10、proxy_connect_timeout time;
Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds.链接超时时间默认为60s;

ngx_http_headers_module模块
The ngx_http_headers_module module allows adding the “Expires” and “Cache-Control” header fields, and arbitrary fields, to a response header.

向由代理服务器响应给客户端的响应报文添加自定义首部,或修改指定首部的值;

1、add_header name value [always];
添加自定义首部;可用上下文:http, server, location, if in location

add_header X-Via $server_addr;
add_header X-Accel $server_name;

2、expires [modified] time;
expires epoch | max | off;

用于定义Expire或Cache-Control首部的值;



ngx_http_fastcgi_module模块:

The ngx_http_fastcgi_module module allows passing requests to a FastCGI server.

1、fastcgi_pass address;
address为fastcgi server的地址; location, if in location;

2、fastcgi_index name;
fastcgi默认的主页资源;

3、fastcgi_param parameter value [if_not_empty];
Sets a parameter that should be passed to the FastCGI server. The value can contain text, variables, and their combination.

配置示例1:
前提:配置好fpm server和mariadb-server服务;
location ~* \.php$ {
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}

配置示例2:通过/pm_status和/ping来获取fpm server状态信息;
location ~* ^/(pm_status|ping)$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
}

4、fastcgi_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

定义fastcgi的缓存;缓存位置为磁盘上的文件系统,由path所指定路径来定义;

levels=levels:缓存目录的层级数量,以及每一级的目录数量;levels=ONE:TWO:THREE
leves=1:2:2
keys_zone=name:size
k/v映射的内存空间的名称及大小
inactive=time
非活动时长
max_size=size
磁盘上用于缓存数据的缓存空间上限

5、fastcgi_cache zone | off;
调用指定的缓存空间来缓存数据;http, server, location

6、fastcgi_cache_key string;
定义用作缓存项的key的字符串;

7、fastcgi_cache_methods GET | HEAD | POST ...;
为哪些请求方法使用缓存;

8、fastcgi_cache_min_uses number;
缓存空间中的缓存项在inactive定义的非活动时间内至少要被访问到此处所指定的次数方可被认作活动项;

9、fastcgi_cache_valid [code ...] time;
不同的响应码各自的缓存时长;

示例:
http {
...
fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2:1 keys_zone=fcgi:20m inactive=120s;
...
server {
...
location ~* \.php$ {
...
fastcgi_cache fcgi;
fastcgi_cache_key $request_uri;
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;
...
}
...
}
...
}

10、fastcgi_keep_conn on | off;
By default, a FastCGI server will close a connection right after sending the response. However, when this directive is set to the value on, nginx will instruct a FastCGI server to keep connections open.



博客作业:以上所有内容;
练习:实现lnmp,提供多个虚拟主机;
(1) http, 提供wordpress;
(2) https, 提供pma;



ngx_http_upstream_module模块
The ngx_http_upstream_module module is used to define groups of servers that can be referenced by the proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, and memcached_pass directives.

1、upstream name { ... }
定义后端服务器组,会引入一个新的上下文;Context: http

upstream httpdsrvs {
server ...
server...
...
}

2、server address [parameters];
在upstream上下文中server成员,以及相关的参数;Context: upstream

address的表示格式:
unix:/PATH/TO/SOME_SOCK_FILE
IP[:PORT]
HOSTNAME[:PORT]

parameters:
weight=number
权重,默认为1;
max_fails=number
失败尝试最大次数;超出此处指定的次数时,server将被标记为不可用;
fail_timeout=time
设置将服务器标记为不可用状态的超时时长;
max_conns
当前的服务器的最大并发连接数;
backup
将服务器标记为“备用”,即所有服务器均不可用时此服务器才启用;
down
标记为“不可用”;

3、least_conn;
最少连接调度算法,当server拥有不同的权重时其为wlc;

4、 ip_hash;
源地址hash调度方法;能够将来自同一个源IP地址的请求始终发往同一个upstream server;

5、hash key [consistent];
基于指定的key的hash表来实现对请求的调度,此处的key可以直接文本、变量或二者的组合;

作用:将请求分类,同一类请求将发往同一个upstream server;
consistent:参数,指定使用一致性hash算法;
If the consistent parameter is specified the ketama consistent hashing method will be used instead.

示例:
hash $request_uri consistent;
hash $remote_addr;

6、keepalive connections;
为每个worker进程保留的空闲的长连接数量;


(8) health_check [parameters];
定义对后端主机的健康状态检测机制;只能用于location上下文;

可用参数:
interval=time:检测频率,默认为每隔5秒钟;
fails=number:判断服务器状态转为失败需要检测的次数;
passes=number:判断服务器状态转为成功需要检测的次数;
uri=uri:判断其健康与否时使用的uri;
match=name:基于指定的match来衡量检测结果的成败;
port=number:使用独立的端口进行检测;

仅Nginx Plus有效;

7、 least_conn;
最少连接调度算法; 当server拥有不同的权重时为wlc;

8、 least_time header | last_byte;
最短平均响应时长和最少连接;
header:response_header;
last_byte: full_response;

仅Nginx Plus有效;

9、 match name { ... }
Defines the named test set used to verify responses to health check requests.
定义衡量某检测结果是否为成功的衡量机制;

专用指令:
status:期望的响应码;
status CODE
status ! CODE
...
header:基于响应报文的首部进行判断
header HEADER=VALUE
header HEADER ~ VALUE
...
body:基于响应报文的内容进行判断
body ~ "PATTERN"
body !~ "PATTERN"

仅Nginx Plus有效;


nginx的其它的二次发行版:
tengine
OpenResty

ngx_stream_core_module模块
模拟反代基于tcp或udp的服务连接,即工作于传输层的反代或调度器;

1、 stream { ... }
定义stream相关的服务;Context:main

stream {
upstream sshsrvs {
server 192.168.22.2:22;
server 192.168.22.3:22;
least_conn;
hash $remote_addr consistent;
}

server {
listen 10.1.0.6:22022;
proxy_pass sshsrvs;
}
}

2、 listen
listen address:port [ssl] [udp] [proxy_protocol] [backlog=number] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];

Linux网页缓存之varnish

[TOC]

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
173
174
175
176
177
178
179
180
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
209
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
307
308
309
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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
程序的运行具有局部性特征:
时间局部性:一个数据被访问过之后,可能很快会被再次访问
空间局部性:一个数据被访问时,其周边的数据也有可能被访问到

cache:命中

热区:局部性;
时效性:
缓存空间耗尽:LRU
过期:缓存清理

缓存命中率:hit/(hit+miss)
(0,1)
页面命中率:基于页面数量进行衡量
字节命中率:基于页面的体积进行衡量

缓存与否:
私有数据:private,private cache;
公共数据:public, public or private cache;

Cache-related Headers Fields
The most important caching header fields are:

Expires:过期时间;
Expires:Thu, 22 Oct 2026 06:34:30 GMT
Cache-Control

Etag
If-None-Match

Last-Modified
If-Modified-Since

Vary
Age

缓存有效性判断机制:
过期时间:Expires
HTTP/1.0
Expires
HTTP/1.1
Cache-Control: maxage=
Cache-Control: s-maxage=
条件式请求:
Last-Modified/If-Modified-Since
Etag/If-None-Match

Expires:Thu, 13 Aug 2026 02:05:12 GMT
Cache-Control:max-age=315360000
ETag:"1ec5-502264e2ae4c0"
Last-Modified:Wed, 03 Sep 2014 10:00:27 GMT

缓存层级:
私有缓存:用户代理附带的本地缓存机制;
公共缓存:反向代理服务器的缓存功能;

User-Agent <--> private cache <--> public cache <--> public cache 2 <--> Original Server

请求报文用于通知缓存服务如何使用缓存响应请求:
cache-request-directive =
"no-cache",
| "no-store"
| "max-age" "=" delta-seconds
| "max-stale" [ "=" delta-seconds ]
| "min-fresh" "=" delta-seconds
| "no-transform"
| "only-if-cached"
| cache-extension

响应报文用于通知缓存服务器如何存储上级服务器响应的内容:
cache-response-directive =
"public"
| "private" [ "=" <"> 1#field-name <"> ]
| "no-cache" [ "=" <"> 1#field-name <"> ],可缓存,但响应给客户端之前需要revalidation;
| "no-store" ,不允许存储响应内容于缓存中;
| "no-transform"
| "must-revalidate"
| "proxy-revalidate"
| "max-age" "=" delta-seconds
| "s-maxage" "=" delta-seconds
| cache-extension

开源解决方案:
squid:
varnish:

varnish官方站点: http://www.varnish-cache.org/
Community
Enterprise

This is Varnish Cache, a high-performance HTTP accelerator.

程序架构:
Manager进程
Cacher进程,包含多种类型的线程:
accept, worker, expiry, ...
shared memory log:
统计数据:计数器;
日志区域:日志记录;
varnishlog, varnishncsa, varnishstat...

配置接口:VCL
Varnish Configuration Language,
vcl complier --> c complier --> shared object


varnish的程序环境:
/etc/varnish/varnish.params: 配置varnish服务进程的工作特性,例如监听的地址和端口,缓存机制;
/etc/varnish/default.vcl:配置各Child/Cache线程的缓存工作属性;
主程序:
/usr/sbin/varnishd
CLI interface:
/usr/bin/varnishadm
Shared Memory Log交互工具:
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtop
测试工具程序:
/usr/bin/varnishtest
VCL配置文件重载程序:
/usr/sbin/varnish_reload_vcl
Systemd Unit File:
/usr/lib/systemd/system/varnish.service
varnish服务
/usr/lib/systemd/system/varnishlog.service
/usr/lib/systemd/system/varnishncsa.service
日志持久的服务;

varnish的缓存存储机制( Storage Types):
-s [name=]type[,options]

・ malloc[,size]
内存存储,[,size]用于定义空间大小;重启后所有缓存项失效;
・ file[,path[,size[,granularity]]]
文件存储,黑盒;重启后所有缓存项失效;
・ persistent,path,size
文件存储,黑盒;重启后所有缓存项有效;实验;

varnish程序的选项:
程序选项:/etc/varnish/varnish.params文件
-a address[:port][,address[:port][...],默认为6081端口;
-T address[:port],默认为6082端口;
-s [name=]type[,options],定义缓存存储机制;
-u user
-g group
-f config:VCL配置文件;
-F:运行于前台;
...
运行时参数:/etc/varnish/varnish.params文件, DEAMON_OPTS
DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"

-p param=value:设定运行参数及其值; 可重复使用多次;
-r param[,param...]: 设定指定的参数为只读状态;

重载vcl配置文件:
~ ]# varnish_reload_vcl

varnishadm
-S /etc/varnish/secret -T [ADDRESS:]PORT

help [<command>]
ping [<timestamp>]
auth <response>
quit
banner
status
start
stop
vcl.load <configname> <filename>
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>
vcl.discard <configname>
vcl.list
param.show [-l] [<param>]
param.set <param> <value>
panic.show
panic.clear
storage.list
vcl.show [-v] <configname>
backend.list [<backend_expression>]
backend.set_health <backend_expression> <state>
ban <field> <operator> <arg> [&& <field> <oper> <arg>]...
ban.list

配置文件相关:
vcl.list
vcl.load:装载,加载并编译;
vcl.use:激活;
vcl.discard:删除;
vcl.show [-v] <configname>:查看指定的配置文件的详细信息;

运行时参数:
param.show -l:显示列表;
param.show <PARAM>
param.set <PARAM> <VALUE>

缓存存储:
storage.list

后端服务器:
backend.list

VCL:
”域“专有类型的配置语言;

state engine:状态引擎;

VCL有多个状态引擎,状态之间存在相关性,但状态引擎彼此间互相隔离;每个状态引擎可使用return(x)指明关联至哪个下一级引擎;每个状态引擎对应于vcl文件中的一个配置段,即为subroutine

vcl_hash --> return(hit) --> vcl_hit

Client Side:
vcl_recv, vcl_pass, vcl_hit, vcl_miss, vcl_pipe, vcl_purge, vcl_synth, vcl_deliver

vcl_recv:
hash:vcl_hash
pass: vcl_pass
pipe: vcl_pipe
synth: vcl_synth
purge: vcl_hash --> vcl_purge

vcl_hash:
lookup:
hit: vcl_hit
miss: vcl_miss
pass, hit_for_pass: vcl_pass
purge: vcl_purge

Backend Side:
vcl_backend_fetch, vcl_backend_response, vcl_backend_error

两个特殊的引擎:
vcl_init:在处理任何请求之前要执行的vcl代码:主要用于初始化VMODs;
vcl_fini:所有的请求都已经结束,在vcl配置被丢弃时调用;主要用于清理VMODs;

vcl的语法格式:
(1) VCL files start with vcl 4.0;
(2) //, # and /* foo */ for comments;
(3) Subroutines are declared with the sub keyword; 例如sub vcl_recv { ...};
(4) No loops, state-limited variables(受限于引擎的内建变量);
(5) Terminating statements with a keyword for next action as argument of the return() function, i.e.: return(action);用于实现状态引擎转换;
(6) Domain-specific;

The VCL Finite State Machine
(1) Each request is processed separately;
(2) Each request is independent from others at any given time;
(3) States are related, but isolated;
(4) return(action); exits one state and instructs Varnish to proceed to the next state;
(5) Built-in VCL code is always present and appended below your own VCL;

三类主要语法:
sub subroutine {
...
}

if CONDITION {
...
} else {
...
}

return(), hash_data()

VCL Built-in Functions and Keywords
函数:
regsub(str, regex, sub)
regsuball(str, regex, sub)
ban(boolean expression)
hash_data(input)
synthetic(str)

Keywords:
call subroutine, return(action),new,set,unset

操作符:
==, !=, ~, >, >=, <, <=
逻辑操作符:&&, ||, !
变量赋值:=

举例:obj.hits
if (obj.hits>0) {
set resp.http.X-Cache = "HIT via " + server.ip;
} else {
set resp.http.X-Cache = "MISS via " + server.ip;
}


变量类型:
内建变量:
req.*:request,表示由客户端发来的请求报文相关;
req.http.*
req.http.User-Agent, req.http.Referer, ...
bereq.*:由varnish发往BE主机的httpd请求相关;
bereq.http.*
beresp.*:由BE主机响应给varnish的响应报文相关;
beresp.http.*
resp.*:由varnish响应给client相关;
obj.*:存储在缓存空间中的缓存对象的属性;只读;

常用变量:
bereq.*, req.*:
bereq.http.HEADERS
bereq.request:请求方法;
bereq.url:请求的url;
bereq.proto:请求的协议版本;
bereq.backend:指明要调用的后端主机;

req.http.Cookie:客户端的请求报文中Cookie首部的值;
req.http.User-Agent ~ "chrome"


beresp.*, resp.*:
beresp.http.HEADERS
beresp.status:响应的状态码;
reresp.proto:协议版本;
beresp.backend.name:BE主机的主机名;
beresp.ttl:BE主机响应的内容的余下的可缓存时长;

obj.*
obj.hits:此对象从缓存中命中的次数;
obj.ttl:对象的ttl值

server.*
server.ip
server.hostname
client.*
client.ip

用户自定义:
set
unset

示例1:强制对某类资源的请求不检查缓存:
vcl_recv {
if (req.url ~ "(?i)^/(login|admin)") {
return(pass);
}
}

示例2:对于特定类型的资源,例如公开的图片等,取消其私有标识,并强行设定其可以由varnish缓存的时长;
if (beresp.http.cache-control !~ "s-maxage") {
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
unset beresp.http.Set-Cookie;
set beresp.ttl = 3600s;
}
}

缓存对象的修剪:purge, ban
(1) 能执行purge操作
sub vcl_purge {
return (synth(200,"Purged"));
}

(2) 何时执行purge操作
sub vcl_recv {
if (req.method == "PURGE") {
return(purge);
}
...
}

添加此类请求的访问控制法则:
acl purgers {
"127.0.0.0"/8;
"10.1.0.0"/16;
}

sub vcl_recv {
if (req.method == "PURGE") {
if (!client.ip ~ purgers) {
return(synth(405,"Purging not allowed for " + client.ip));
}
return(purge);
}
...
}

如何设定使用多个后端主机:
backend default {
.host = "172.16.100.6";
.port = "80";
}

backend appsrv {
.host = "172.16.100.7";
.port = "80";
}

sub vcl_recv {
if (req.url ~ "(?i)\.php$") {
set req.backend_hint = appsrv;
} else {
set req.backend_hint = default;
}

...
}

Director:
varnish module;
使用前需要导入:
import director;

示例:
import directors; # load the directors

backend server1 {
.host =
.port =
}
backend server2 {
.host =
.port =
}

sub vcl_init {
new GROUP_NAME = directors.round_robin();
GROUP_NAME.add_backend(server1);
GROUP_NAME.add_backend(server2);
}

sub vcl_recv {
# send all traffic to the bar director:
set req.backend_hint = GROUP_NAME.backend();
}

BE Health Check:
backend BE_NAME {
.host =
.port =
.probe = {
.url=
.timeout=
.interval=
.window=
.threshhold=
}
}

.probe:定义健康状态检测方法;
.url:检测时请求的URL,默认为”/";
.request:发出的具体请求;
.request =
"GET /.healthtest.html HTTP/1.1"
"Host: www.magedu.com"
"Connection: close"
.window:基于最近的多少次检查来判断其健康状态;
.threshhold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
.interval:检测频度;
.timeout:超时时长;
.expected_response:期望的响应码,默认为200;

健康状态检测的配置方式:
(1) probe PB_NAME = { }
backend NAME = {
.probe = PB_NAME;
...
}

(2) backend NAME {
.probe = {
...
}
}

示例:
probe check {
.url = "/.healthcheck.html";
.window = 5;
.threshold = 4;
.interval = 2s;
.timeout = 1s;
}

backend default {
.host = "10.1.0.68";
.port = "80";
.probe = check;
}

backend appsrv {
.host = "10.1.0.69";
.port = "80";
.probe = check;
}


varnish的运行时参数:
线程模型:
cache-worker
cache-main
ban lurker
acceptor:
epoll/kqueue:
...

线程相关的参数:
在线程池内部,其每一个请求由一个线程来处理; 其worker线程的最大数决定了varnish的并发响应能力;

thread_pools:Number of worker thread pools. 最好小于或等于CPU核心数量;
thread_pool_max:The maximum number of worker threads in each pool. 每线程池的最大线程数;
thread_pool_min:The minimum number of worker threads in each pool. 额外意义为“最大空闲线程数”;

最大并发连接数=thread_pools * thread_pool_max

thread_pool_timeout:Thread idle threshold. Threads in excess of thread_pool_min, which have been idle for at least this long, will be destroyed.
thread_pool_add_delay:Wait at least this long after creating a thread.
thread_pool_destroy_delay:Wait this long after destroying a thread.

设置方式:
vcl.param
param.set

永久有效的方法:
varnish.params
DEAMON_OPTS="-p PARAM1=VALUE -p PARAM2=VALUE"

varnish日志区域:
shared memory log
计数器
日志信息

1、varnishstat - Varnish Cache statistics
-1
-1 -f FILED_NAME
-l:可用于-f选项指定的字段名称列表;

MAIN.cache_hit
MAIN.cache_miss

# varnishstat -1 -f MAIN.cache_hit -f MAIN.cache_miss

2、varnishtop - Varnish log entry ranking
-1 Instead of a continously updated display, print the statistics once and exit.
-i taglist,可以同时使用多个-i选项,也可以一个选项跟上多个标签;
-I <[taglist:]regex>
-x taglist:排除列表
-X <[taglist:]regex>

3、varnishlog - Display Varnish logs

4、 varnishncsa - Display Varnish logs in Apache / NCSA combined log format

内建函数:
hash_data():指明哈希计算的数据;减少差异,以提升命中率;
regsub(str,regex,sub):把str中被regex第一次匹配到字符串替换为sub;主要用于URL Rewrite
regsuball(str,regex,sub):把str中被regex每一次匹配到字符串均替换为sub;
return():
ban(expression)
ban_url(regex):Bans所有的其URL可以被此处的regex匹配到的缓存对象;
synth(status,"STRING"):purge操作;


总结:
varnish: state engine, vcl
varnish 4.0:
vcl_init
vcl_recv
vcl_hash
vcl_hit
vcl_pass
vcl_miss
vcl_pipe
vcl_waiting
vcl_purge
vcl_purge
vcl_deliver
vcl_synth
vcl_fini

vcl_backend_fetch
vcl_backend_response
vcl_backend_error

sub VCL_STATE_ENGINE
backend BE_NAME {}
probe PB_NAME {}
acl ACL_NAME {}

博客作业:以上所有内容;
课外实践:(1) zabbix监控varnish业务指标;
(2) ansible实现varnish快速部署;
(3) 两个lamp部署wordpress,用Nginx反代,做压测;nginx后部署varnish缓存,调整vcl,多次压测;

ab, http_load, webbench, seige, jmeter, loadrunner,...

Linux系统高可用之HA-Cluster

[TOC]

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
173
174
175
176
177
178
179
180
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
209
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
307
308
309
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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563

HA Cluster:

集群类型:LB(lvs/nginx(http/upstream, stream/upstream))、HA、HP

SPoF: Single Point of Failure

系统可用性的公式:A=MTBF/(MTBF+MTTR)
(0,1), 95%
几个9(指标): 99%, ..., 99.999%,99.9999%;
99%: %1, 99.9%, 0.1%

系统故障:
硬件故障:设计缺陷、wear out、自然灾害、……
软件故障:设计缺陷、

提升系统高用性的解决方案之降低MTTR:

手段:冗余(redundant)

active/passive(主备),active/active(双主)
active --> HEARTBEAT --> passive
active <--> HEARTBEAT <--> active

高可用的是“服务”:
HA nginx service:
vip/nginx process[/shared storage]

资源:组成一个高可用服务的“组件”;

(1) passive node的数量?
(2) 资源切换?

shared storage:
NAS:文件共享服务器;
SAN:存储区域网络,块级别的共享;

Network partition:网络分区
隔离设备:
node:STONITH = Shooting The Other Node In The Head
资源:fence

quorum:
with quorum: > total/2
without quorum: <= total/2

TWO nodes Cluster?
辅助设备:ping node, quorum disk;

Failover:故障切换,即某资源的主节点故障时,将资源转移至其它节点的操作;
Failback:故障移回,即某资源的主节点故障后重新修改上线后,将转移至其它节点的资源重新切回的过程;

HA Cluster实现方案:
vrrp协议的实现
keepalived
ais:完备HA集群
RHCS(cman)
heartbeat
corosync

keepalived:

vrrp协议:Virtual Redundant Routing Protocol
术语:
虚拟路由器:Virtual Router
虚拟路由器标识:VRID(0-255)
物理路由器:
master:主设备
backup:备用设备
priority:优先级
VIP:Virtual IP
VMAC:Virutal MAC (00-00-5e-00-01-VRID)

通告:心跳,优先级等;周期性;

抢占式,非抢占式;

安全工作:
认证:
无认证
简单字符认证
MD5

工作模式:
主/备:单虚拟路径器;
主/主:主/备(虚拟路径器1),备/主(虚拟路径器2)

keepalived:
vrrp协议的软件实现,原生设计的目的为了高可用ipvs服务:
vrrp协议完成地址流动;
为vip地址所在的节点生成ipvs规则(在配置文件中预先定义);
为ipvs集群的各RS做健康状态检测;
基于脚本调用接口通过执行脚本完成脚本中定义的功能,进而影响集群事务;

组件:
核心组件:
vrrp stack
ipvs wrapper
checkers
控制组件:配置文件分析器
IO复用器
内存管理组件

HA Cluster的配置前提:
(1) 各节点时间必须同步;
ntp, chrony
(2) 确保iptables及selinux不会成为阻碍;
(3) 各节点之间可通过主机名互相通信(对KA并非必须);
建议使用/etc/hosts文件实现;
(4) 各节点之间的root用户可以基于密钥认证的ssh服务完成互相通信;(并非必须)

keepalived安装配置:
CentOS 6.4+

程序环境:
主配置文件:/etc/keepalived/keepalived.conf
主程序文件:/usr/sbin/keepalived
Unit File:keepalived.service
Unit File的环境配置文件:/etc/sysconfig/keepalived

配置文件组件部分:
TOP HIERACHY
GLOBAL CONFIGURATION
Global definitions
Static routes/addresses
VRRPD CONFIGURATION
VRRP synchronization group(s):vrrp同步组;
VRRP instance(s):每个vrrp instance即一个vrrp路由器;
LVS CONFIGURATION
Virtual server group(s)
Virtual server(s):ipvs集群的vs和rs;

单主配置示例:
! Configuration File for keepalived

global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node1
vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
state BACKUP
interface eno16777736
virtual_router_id 14
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 571f97b2
}
virtual_ipaddress {
10.1.0.91/16 dev eno16777736
}
}


配置语法:
配置虚拟路由器:
vrrp_instance <STRING> {
....
}

专用参数:
state MASTER|BACKUP:当前节点在此虚拟路由器上的初始状态;只能有一个是MASTER,余下的都应该为BACKUP;
interface IFACE_NAME:绑定为当前虚拟路由器使用的物理接口;
virtual_router_id VRID:当前虚拟路由器的惟一标识,范围是0-255;
priority 100:当前主机在此虚拟路径器中的优先级;范围1-254;
advert_int 1:vrrp通告的时间间隔;
authentication {
auth_type AH|PASS
auth_pass <PASSWORD>
}
virtual_ipaddress {
<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE> label <LABEL>
192.168.200.17/24 dev eth1
192.168.200.18/24 dev eth2 label eth2:1
}
track_interface {
eth0
eth1
...
}
配置要监控的网络接口,一旦接口出现故障,则转为FAULT状态;
nopreempt:定义工作模式为非抢占模式;
preempt_delay 300:抢占式模式下,节点上线后触发新选举操作的延迟时长;

定义通知脚本:
notify_master <STRING>|<QUOTED-STRING>:当前节点成为主节点时触发的脚本;
notify_backup <STRING>|<QUOTED-STRING>:当前节点转为备节点时触发的脚本;
notify_fault <STRING>|<QUOTED-STRING>:当前节点转为“失败”状态时触发的脚本;

notify <STRING>|<QUOTED-STRING>:通用格式的通知触发机制,一个脚本可完成以上三种状态的转换时的通知;

双主模型示例:
! Configuration File for keepalived

global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node1
vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
state MASTER
interface eno16777736
virtual_router_id 14
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 571f97b2
}
virtual_ipaddress {
10.1.0.91/16 dev eno16777736
}
}

vrrp_instance VI_2 {
state BACKUP
interface eno16777736
virtual_router_id 15
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass 578f07b2
}
virtual_ipaddress {
10.1.0.92/16 dev eno16777736
}
}



示例通知脚本:
#!/bin/bash
#
contact='root@localhost'

notify() {
mailsubject="$(hostname) to be $1, vip floating"
mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
echo "$mailbody" | mail -s "$mailsubject" $contact
}

case $1 in
master)
notify master
;;
backup)
notify backup
;;
fault)
notify fault
;;
*)
echo "Usage: $(basename $0) {master|backup|fault}"
exit 1
;;
esac

脚本的调用方法:
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"

虚拟服务器:
配置参数:
virtual_server IP port |
virtual_server fwmark int
{
...
real_server {
...
}
...
}

常用参数:
delay_loop <INT>:服务轮询的时间间隔;
lb_algo rr|wrr|lc|wlc|lblc|sh|dh:定义调度方法;
lb_kind NAT|DR|TUN:集群的类型;
persistence_timeout <INT>:持久连接时长;
protocol TCP:服务协议,仅支持TCP;
sorry_server <IPADDR> <PORT>:备用服务器地址;
real_server <IPADDR> <PORT>
{
weight <INT>
notify_up <STRING>|<QUOTED-STRING>
notify_down <STRING>|<QUOTED-STRING>
HTTP_GET|SSL_GET|TCP_CHECK|SMTP_CHECK|MISC_CHECK { ... }:定义当前主机的健康状态检测方法;
}

HTTP_GET|SSL_GET:应用层检测

HTTP_GET|SSL_GET {
url {
path <URL_PATH>:定义要监控的URL;
status_code <INT>:判断上述检测机制为健康状态的响应码;
digest <STRING>:判断上述检测机制为健康状态的响应的内容的校验码;
}
nb_get_retry <INT>:重试次数;
delay_before_retry <INT>:重试之前的延迟时长;
connect_ip <IP ADDRESS>:向当前RS的哪个IP地址发起健康状态检测请求
connect_port <PORT>:向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS>:发出健康状态检测请求时使用的源地址;
bind_port <PORT>:发出健康状态检测请求时使用的源端口;
connect_timeout <INTEGER>:连接请求的超时时长;
}

TCP_CHECK {
connect_ip <IP ADDRESS>:向当前RS的哪个IP地址发起健康状态检测请求
connect_port <PORT>:向当前RS的哪个PORT发起健康状态检测请求
bindto <IP ADDRESS>:发出健康状态检测请求时使用的源地址;
bind_port <PORT>:发出健康状态检测请求时使用的源端口;
connect_timeout <INTEGER>:连接请求的超时时长;
}

高可用的ipvs集群示例:
! Configuration File for keepalived

global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node1
vrrp_mcast_group4 224.0.100.19
}

vrrp_instance VI_1 {
state MASTER
interface eno16777736
virtual_router_id 14
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 571f97b2
}
virtual_ipaddress {
10.1.0.93/16 dev eno16777736
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}

virtual_server 10.1.0.93 80 {
delay_loop 3
lb_algo rr
lb_kind DR
protocol TCP

sorry_server 127.0.0.1 80

real_server 10.1.0.69 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
real_server 10.1.0.71 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 1
nb_get_retry 3
delay_before_retry 1
}
}
}


博客作业:第一部分
双主模式的lvs集群,拓扑、实现过程;

配置示例(一个节点):

! Configuration File for keepalived

global_defs {
notification_email {
root@localhost
}
notification_email_from kaadmin@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node1
vrrp_mcast_group4 224.0.100.67
}

vrrp_instance VI_1 {
state MASTER
interface eno16777736
virtual_router_id 44
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass f1bf7fde
}
virtual_ipaddress {
172.16.0.80/16 dev eno16777736 label eno16777736:0
}
track_interface {
eno16777736
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}

vrrp_instance VI_2 {
state BACKUP
interface eno16777736
virtual_router_id 45
priority 98
advert_int 1
authentication {
auth_type PASS
auth_pass f2bf7ade
}
virtual_ipaddress {
172.16.0.90/16 dev eno16777736 label eno16777736:1
}
track_interface {
eno16777736
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}

virtual_server fwmark 3 {
delay_loop 2
lb_algo rr
lb_kind DR
nat_mask 255.255.0.0
protocol TCP
sorry_server 127.0.0.1 80

real_server 172.16.0.69 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 2
nb_get_retry 3
delay_before_retry 3
}
}
real_server 172.16.0.6 80 {
weight 1
HTTP_GET {
url {
path /
status_code 200
}
connect_timeout 2
nb_get_retry 3
delay_before_retry 3
}
}
}









keepalived调用外部的辅助脚本进行资源监控,并根据监控的结果状态能实现优先动态调整;
分两步:(1) 先定义一个脚本;(2) 调用此脚本;
vrrp_script <SCRIPT_NAME> {
script ""
interval INT
weight -INT
}

track_script {
SCRIPT_NAME_1
SCRIPT_NAME_2
...
}

示例:高可用nginx服务

! Configuration File for keepalived

global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id node1
vrrp_mcast_group4 224.0.100.19
}

vrrp_script chk_down {
script "[[ -f /etc/keepalived/down ]] && exit 1 || exit 0"
interval 1
weight -5
}

vrrp_script chk_nginx {
script "killall -0 nginx && exit 0 || exit 1"
interval 1
weight -5
}

vrrp_instance VI_1 {
state MASTER
interface eno16777736
virtual_router_id 14
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 571f97b2
}
virtual_ipaddress {
10.1.0.93/16 dev eno16777736
}
track_script {
chk_down
chk_nginx
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}

博客作业:以上所有内容;

Linux安全策略之tcp_wrapper

[TOC]

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

库文件:libwrap.so,tcp包装器;

判断一个服务程序是否能够由tcp_wrapper进行访问控制的方法:
(1) 动态链接至libwrap.so库;
ldd /PATH/TO/PROGRAM
libwrap.so
(2) 静态编译libwrap.so库文件至程序中:
strings /PATH/TO/PGRGRAM
hosts_access

配置文件:/etc/hosts.allow, /etc/hosts.deny

See 'man 5 hosts_options' and 'man 5 hosts_access' for information on rule syntax.

配置文件语法:
daemon_list : client_list[ : option : option ...]

daemon_list:程序文件名称列表
(1) 单个应用程序文件名;
(2) 程序文件名列表,以逗号分隔;
(3) ALL:所有受tcp_wrapper控制的应用程序文件;

client_list:
(1) 单个IP地址或主机名;
(2) 网络地址:n.n.n.n/m.m.m.m,n.n.n.;
(3) 内建的ACL:
ALL:所有客户端主机;
LOCAL:Matches any host whose name does not contain a dot character.
UNKNOWN
KNOWN
PARANOID

OPERATORS:
EXCEPT
list1 EXCEPT list2 EXCEPT list3

sshd: 172.16. EXCEPT 172.16.100. EXCEPT 172.16.100.68

[ : option : option ...]

deny:拒绝,主要用于hosts.allow文件中定义“拒绝”规则;
allow:允许,主要用于hosts.deny文件中定义”允许“规则;

spawn:生成,发起,触发执行用户指定的任意命令,此处通常用于记录日志;

vsftpd: 172.16. : spawn /bin/echo $(date) login attempt from %c to %s >> /var/log/tcp_wrapper.log

练习:仅开放本机的sshd服务给172.16.0.0/16网络中除了172.16.0.0/24网络中的主机之外的所有主机,但允许172.16.0.200访问; 每次的用户访问都要记录于日志文件中;

Linux负载均衡之lvs-dr模式

[TOC]

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
lvs-dr:
dr模型中,各主机上均需要配置VIP,解决地址冲突的方式有三种:
(1) 在前端网关做静态绑定;
(2) 在各RS使用arptables;
(3) 在各RS修改内核参数,来限制arp响应和通告的级别;
限制响应级别:arp_ignore
0:默认值,表示可使用本地任意接口上配置的任意地址进行响应;
1: 仅在请求的目标IP配置在本地主机的接收到请求报文接口上时,才给予响应;
限制通告级别:arp_announce
0:默认值,把本机上的所有接口的所有信息向每个接口上的网络进行通告;
1:尽量避免向非直接连接网络进行通告;
2:必须避免向非本网络通告;




RS的预配置脚本:
#!/bin/bash
#
vip=10.1.0.5
mask='255.255.255.255'

case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

ifconfig lo:0 $vip netmask $mask broadcast $vip up
route add -host $vip dev lo:0//当发往本机的请求报文目标地址为 vip 的时候,本机的响应报文从lo:o应答
;;
stop)
ifconfig lo:0 down

echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce

;;
*)
echo "Usage $(basename $0) start|stop"
exit 1
;;
esac

VS
ifconfig eno16777736:0 172.16.0.50 netmask 255.255.255.255 broadcast 172.16.0.50 up
vip=172.16.0.50

VS的配置脚本:
#!/bin/bash
#
vip='10.1.0.5'
iface='eno16777736:0'
mask='255.255.255.255'
port='80'
rs1='10.1.0.7'
rs2='10.1.0.8'
scheduler='wrr'
type='-g'

case $1 in
start)
ifconfig $iface $vip netmask $mask broadcast $vip up
iptables -F

ipvsadm -A -t ${vip}:${port} -s $scheduler
ipvsadm -a -t ${vip}:${port} -r ${rs1} $type -w 1
ipvsadm -a -t ${vip}:${port} -r ${rs2} $type -w 1
;;
stop)
ipvsadm -C
ifconfig $iface down
;;
*)
echo "Usage $(basename $0) start|stop"
exit 1
;;
esac

课外扩展作业:vip与dip/rip不在同一网段的实验环境设计及配置实现;

博客作业:lvs的详细应用
讲清楚类型、调度方法;并且给出nat和dr类型的设计拓扑及具体实现;

Linux负载均衡之lvs

[TOC]

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
173
174
175
176
177
178
179
180
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
209
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
307
308
309
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
单台主机的处理能力是有限的,一台主机同时处理500个动态网页请求已经是极限了。这里有两种方法提升处理性能,一,定制高性能的计算机(Scale UP),众所周知计算机硬件设计成本极其高,性能每提高10%成本就要增加一倍,这也是intel被称为挤牙膏公司的原因,不是其研发能力不行而是计算机硬件性能提升的难度太大,这个方法貌似不可行。二,使用两台主机处理业务,这就会引来一个问题怎么把请求分发到多个主机(Scale Out),这里我们引入了负载均衡器。
使用负载均衡有两个方法,一是采用商用负载均衡硬件的,这个方法是最好的方法,能上硬件一定不要使用软件,又是硬件同样的问题也是价格,只要是涉及到基础设施的服务一定要使用。一方面是硬件的稳定性,比软件好很多,虽然软件可维护性和拓展性比较好,但是对于一些金融公司,他们玩的就是公信力和大众信心,每个故障都是竞争对手拆台的理由,一旦故障硬件背锅,理赔。常用的硬件F5的Big-IP,Citrix的Netscaler,A10的A10
另一种是采用软件负载均衡,只要考虑成本使用负载均衡软件就对了,它的性能比硬件也不会差别太大,并且灵活。
在做负载均衡的时候,我们在7层模型的哪一层做负载均衡,ip层基于主机做负载均衡粒度太大可用性太差基本不使用,更低的层基本上没有价值了,tcp层的话我们就可以把不同服务的请求采取不同的方式负载均衡,应用层的话我们可以根据具体协议拆包分析后负载均衡,既然涉及到拆开数据包,那处理的数据量就会大大增加,那么对计算机性能要求也越高,性能就越差,并且负载均衡器的通用性也越差。
传输层:lvs,nginx:(stream),haproxy:(mode tcp)
应用层:
http:nginx, httpd, haproxy(mode http)
fastcgi:nginx, httpd
mysql:mysql-proxy

Linux Cluster:
Cluster:计算机集合,为解决某个特定问题组合起来形成的单个系统;

Linux Cluster类型:
LB:Load Balancing,负载均衡;
HA:High Availiablity,高可用;
A=MTBF/(MTBF+MTTR),MTBF:mean time bettween failure,平均工作时长或者平均故障间隔时间。MTTR:mean time to restoration/repair,平局修复时长
(0,1):90%, 95%, 99%, 99.5%, 99.9%, 99.99%, 99.999%, 99.9999%
HP:High Performance,高性能;

分布式系统:
分布式存储
分布式计算

系统扩展方式:
Scale UP:向上扩展
Scale Out:向外扩展,增加计算机数量,也就形成了集群

LB Cluster:

LB Cluster的实现:
硬件:
F5 Big-IP
Citrix Netscaler
A10 A10
软件:
lvs:Linux Virtual Server
nginx
haproxy
ats:apache traffic server
perlbal
pound

基于工作的协议层次划分:
传输层(通用):(DPORT)
lvs:
nginx:(stream)
haproxy:(mode tcp)
应用层(专用):(自定义的请求模型分类)
proxy sferver:
http:nginx, httpd, haproxy(mode http), ...
fastcgi:nginx, httpd, ...
mysql:mysql-proxy, ...
...

站点指标:
PV:Page View
UV:Unique Vistor
IP:

会话保持:
(1) session sticky
Source IP
Cookie
(2) session replication;
session cluster
(3) session server

lvs:Linux Virtual Server 作者:章文嵩;alibaba --> didi
VS: Virtual Server
RS: Real Server

lvs: ipvsadm/ipvs 类似于 iptables/netfilter
ipvsadm:用户空间的命令行工具,规则管理器,用于管理集群服务及RealServer;
ipvs:工作于内核空间的netfilter的INPUT钩子之上的框架;

lvs集群类型中的术语:
vs:Virtual Server, Director, Dispatcher, Balancer
rs:Real Server, upstream server, backend server
CIP:Client IP, VIP: Virtual serve IP, RIP: Real server IP, DIP: Director IP
CIP <--> VIP == DIP <--> RIP

lvs集群的类型:
lvs-nat:修改请求报文的目标IP;多目标IP的DNAT;
lvs-dr:操纵封装新的MAC地址;
lvs-tun:在原请求IP报文之外新加一个IP首部;
lvs-fullnat:修改请求报文的源和目标IP;

lvs-nat:
多目标IP的DNAT,通过将请求报文中的目标地址和目标端口修改为某挑出的RS的RIP和PORT实现转发;

(1)RIP和DIP必须在同一个IP网络,且应该使用私网地址;RS的网关要指向DIP;
(2)请求报文和响应报文都必须经由Director转发;Director易于成为系统瓶颈;
(3)支持端口映射,可修改请求报文的目标PORT;
(4)vs必须是Linux系统,rs可以是任意系统;

lvs-dr:
Direct Routing,直接路由;

通过为请求报文重新封装一个MAC首部进行转发,源MAC是DIP所在的接口的MAC,目标MAC是某挑选出的RS的RIP所在接口的MAC地址;源IP/PORT,以及目标IP/PORT均保持不变;

Director和各RS都得配置使用VIP;

(1) 确保前端路由器将目标IP为VIP的请求报文发往Director:
(a) 在前端网关做静态绑定;
(b) 在RS上使用arptables;
(c) 在RS上修改内核参数以限制arp通告及应答级别;
arp_announce
arp_ignore
(2) RS的RIP可以使用私网地址,也可以是公网地址;RIP与DIP在同一IP网络;RIP的网关不能指向DIP,以确保响应报文不会经由Director;
(3) RS跟Director要在同一个物理网络;
(4) 请求报文要经由Director,但响应不能经由Director,而是由RS直接发往Client;
(5) 不支持端口映射;

lvs-tun:
转发方式:不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而在原IP报文之外再封装一个IP首部(源IP是DIP,目标IP是RIP),将报文发往挑选出的目标RS;RS直接响应给客户端(源IP是VIP,目标IP是CIP);

(1) DIP, VIP, RIP都应该是公网地址;
(2) RS的网关不能,也不可能指向DIP;
(3) 请求报文要经由Director,但响应不能经由Director;
(4) 不支持端口映射;
(5) RS的OS得支持隧道功能;

lvs-fullnat:
通过同时修改请求报文的源IP地址和目标IP地址进行转发;
CIP --> DIP
VIP --> RIP

(1) VIP是公网地址,RIP和DIP是私网地址,且通常不在同一IP网络;因此,RIP的网关一般不会指向DIP;
(2) RS收到的请求报文源地址是DIP,因此,只需响应给DIP;但Director还要将其发往Client;
(3) 请求和响应报文都经由Director;
(4) 支持端口映射;

注意:此类型默认不支持;


总结:
lvs-nat, lvs-fullnat:请求和响应报文都经由Director;
lvs-nat:RIP的网关要指向DIP;
lvs-fullnat:RIP和DIP未必在同一IP网络,但要能通信;
lvs-dr, lvs-tun:请求报文要经由Director,但响应报文由RS直接发往Client;
lvs-dr:通过封装新的MAC首部实现,通过MAC网络转发;
lvs-tun:通过在原IP报文之外封装新的IP报文实现转发,支持远距离通信;

ipvs scheduler:
根据其调度时是否考虑各RS当前的负载状态,可分为静态方法和动态方法两种:

静态方法:仅根据算法本身进行调度;
RR:roundrobin,轮询;
WRR:Weighted RR,加权轮询;
SH:Source Hashing,实现session sticy,源IP地址hash;将来自于同一个IP地址的请求始终发往第一次挑中的RS,从而实现会话绑定;
DH:Destination Hashing;目标地址哈希,将发往同一个目标地址的请求始终转发至第一次挑中的RS,典型使用场景是正向代理缓存场景中的负载均衡;

动态方法:主要根据每RS当前的负载状态及调度算法进行调度;
Overhead=

LC:least connections 选中最少连接数的RS服务器
Overhead=activeconns*256+inactiveconns
WLC:Weighted LC 默认调度方法
Overhead=(activeconns*256+inactiveconns)/weight
SED:Shortest Expection Delay 最短期望延迟,
Overhead=(activeconns+1)*256/weight
NQ:Never Queue 永不排队,权重小的不会空闲

LBLC:Locality-Based LC,动态的DH算法;
LBLCR:LBLC with Replication,带复制功能的LBLC;

ipvsadm/ipvs:
ipvs:
~]# grep -i -C 10 "ipvs" /boot/config-VERSION-RELEASE.x86_64

支持的协议:TCP, UDP, AH, ESP, AH_ESP, SCTP;

ipvs集群:
集群服务
服务上的RS

ipvsadm:
程序包:ipvsadm
Unit File: ipvsadm.service
主程序:/usr/sbin/ipvsadm
规则保存工具:/usr/sbin/ipvsadm-save
规则重载工具:/usr/sbin/ipvsadm-restore
配置文件:/etc/sysconfig/ipvsadm-config


ipvsadm命令:
核心功能:
集群服务管理:增、删、改;
集群服务的RS管理:增、删、改;
查看:

ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags]
ipvsadm -D -t|u|f service-address
ipvsadm -C
ipvsadm -R
ipvsadm -S [-n]
ipvsadm -a|e -t|u|f service-address -r server-address [options]
ipvsadm -d -t|u|f service-address -r server-address
ipvsadm -L|l [options]
ipvsadm -Z [-t|u|f service-address]

管理集群服务:增、改、删;
增、改:
ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]]

删:
ipvsadm -D -t|u|f service-address

service-address:
-t|u|f:
-t: TCP协议的端口,VIP:TCP_PORT
-u: TCP协议的端口,VIP:UDP_PORT
-f:firewall MARK,是一个数字;

[-s scheduler]:指定集群的调度算法,默认为wlc;

管理集群上的RS:增、改、删;
增、改:
ipvsadm -a|e -t|u|f service-address -r server-address [-g|i|m] [-w weight]

删:
ipvsadm -d -t|u|f service-address -r server-address

server-address:
rip[:port]

选项:
lvs类型:
-g: gateway, dr类型
-i: ipip, tun类型
-m: masquerade, nat类型

-w weight:权重;

清空定义的所有内容:
ipvsadm -C

查看:
ipvsadm -L|l [options]
--numeric, -n:numeric output of addresses and ports
--exact:expand numbers (display exact values)

--connection, -c:output of current IPVS connections
--stats:output of statistics information
--rate :output of rate information

保存和重载:
ipvsadm -S = ipvsadm-save
ipvsadm -R = ipvsadm-restore

负载均衡集群设计时要注意的问题:
(1) 是否需要会话保持;
(2) 是否需要共享存储;
共享存储:NAS, SAN, DS(分布式存储)
数据同步:
课外作业:rsync+inotify实现数据同步

lvs-nat:

设计要点:
(1) RIP与DIP在同一IP网络, RIP的网关要指向DIP;
(2) 支持端口映射;
(3) Director要打开核心转发功能;

ipvsadm -A -t 172.16.252.127:80 -s rr // -s rr 课不写 默认为wlc
ipvsadm -a -t 172.16.252.127:80 -r 192.168.0.5:80 -m //[-w weight_num]
ipvsadm -a -t 172.16.252.127:80 -r 192.168.0.6:80 -m //[-w weight_num]
ipvsadm -L
echo 1 > /proc/sys/net/ipv4/ip_forward 转发功能打开

ifconfig eth0 192.168.191.131/24
route add default gw 192.168.191.1

测试:
for i in {1..10} ; do curl 172.16.252.127 ; done

实践作业(博客):负载均衡一个php应用(wordpress);
测试:(1) 是否需要会话保持;(2) 是否需要共享存储;

Demo:
lvs-dr:

dr模型中,各主机上均需要配置VIP,解决地址冲突的方式有三种:
(1) 在前端网关做静态绑定;
(2) 在各RS使用arptables;
(3) 在各RS修改内核参数,来限制arp响应和通告的级别;
限制响应级别:arp_ignore
0:默认值,表示可使用本地任意接口上配置的任意地址进行响应;
1: 仅在请求的目标IP配置在本地主机的接收到请求报文接口上时,才给予响应;
限制通告级别:arp_announce
0:默认值,把本机上的所有接口的所有信息向每个接口上的网络进行通告;
1:尽量避免向非直接连接网络进行通告;
2:必须避免向非本网络通告;



RS的预配置脚本:
#!/bin/bash
#
vip=10.1.0.5
mask='255.255.255.255'

case $1 in
start)
echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

ifconfig lo:0 $vip netmask $mask broadcast $vip up
route add -host $vip dev lo:0
;;
stop)
ifconfig lo:0 down

echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce
echo 0 > /proc/sys/net/ipv4/conf/lo/arp_announce

;;
*)
echo "Usage $(basename $0) start|stop"
exit 1
;;
esac

VS的配置脚本:
#!/bin/bash
#
vip='10.1.0.5'
iface='eno16777736:0'
mask='255.255.255.255'
port='80'
rs1='10.1.0.7'
rs2='10.1.0.8'
scheduler='wrr'
type='-g'

case $1 in
start)
ifconfig $iface $vip netmask $mask broadcast $vip up
iptables -F

ipvsadm -A -t ${vip}:${port} -s $scheduler
ipvsadm -a -t ${vip}:${port} -r ${rs1} $type -w 1
ipvsadm -a -t ${vip}:${port} -r ${rs2} $type -w 1
;;
stop)
ipvsadm -C
ifconfig $iface down
;;
*)
echo "Usage $(basename $0) start|stop"
exit 1
;;
esac

课外扩展作业:vip与dip/rip不在同一网段的实验环境设计及配置实现;

博客作业:lvs的详细应用
讲清楚类型、调度方法;并且给出nat和dr类型的设计拓扑及具体实现;

FWM:FireWall Mark
netfilter:
target: MARK, This target is used to set the Netfilter mark value associated with the packet.

--set-mark value

借助于防火墙标记来分类报文,而后基于标记定义集群服务;可将多个不同的应用使用同一个集群服务进行调度;

打标记方法(在Director主机):
# iptables -t mangle -A PREROUTING -d $vip -p $proto --dport $port -j MARK --set-mark NUMBER

基于标记定义集群服务:
# ipvsadm -A -f NUMBER [options]

lvs persistence:持久连接

持久连接模板:实现无论使用任何调度算法,在一段时间内,能够实现将来自同一个地址的请求始终发往同一个RS;

ipvsadm -A|E -t|u|f service-address [-s scheduler] [-p [timeout]]

port Affinity:
每端口持久:每个端口对应定义为一个集群服务,每集群服务单独调度;
每防火墙标记持久:基于防火墙标记定义集群服务;可实现将多个端口上的应用统一调度,即所谓的port Affinity;
每客户端持久:基于0端口定义集群服务,即将客户端对所有应用的请求统统调度至后端主机,必须定义为持久模式;

保存及重载规则:
保存:建议保存至/etc/sysconfig/ipvsadm
ipvsadm-save > /PATH/TO/IPVSADM_FILE
ipvsadm -S > /PATH/TO/IPVSADM_FILE
systemctl stop ipvsadm.service

重载:
ipvsadm-restore < /PATH/FROM/IPVSADM_FILE
ipvsadm -R < /PATH/FROM/IPVSADM_FILE
systemctl restart ipvsadm.service

考虑:
(1) Director不可用,整个系统将不可用;SPoF
解决方案:高可用
keepalived
heartbeat/corosync
(2) 某RS不可用时,Director依然会调度请求至此RS;
解决方案:对各RS的健康状态做检查,失败时禁用,成功时启用;
keepalived
heartbeat/corosync, ldirectord
检测方式:
(a) 网络层检测;
(b) 传输层检测,端口探测;
(c) 应用层检测,请求某关键资源;

ok --> failure
failure --> ok

ldirectord:
Daemon to monitor remote services and control Linux Virtual Server. ldirectord is a daemon to monitor and administer real servers in a cluster of load balanced virtual servers. ldirectord typically is started from heartbeat but can also be run from the command line.

配置示例:
checktimeout=3
checkinterval=1
fallback=127.0.0.1:80
autoreload=yes
logfile="/var/log/ldirectord.log"
quiescent=no
virtual=5
real=172.16.0.7:80 gate 2
real=172.16.0.8:80 gate 1
fallback=127.0.0.1:80 gate
service=http
scheduler=wrr
checktype=negotiate
checkport=80
request="index.html"
receive="CentOS"

补充:共享存储
NAS:Network Attached Storage
nfs/cifs
文件系统接口
SAN:Storage Area Network
“块”接口

CentOS 7 PXE 无盘系统配置说明

PXE无盘工作站系统是指由一台或多台“系统服务器”和多台“PXE客户端(无盘工作站)”通过 交换机 相连组成的局域网系统。

xitong.png

系统服务器:通过DHCP+TFTP+NFS服务向无盘工作站提供系统支持

  · DHCP服务:向PXE客户端分发IP地址、子网掩码、网关等,并指定启动引导文件所在服务器(TFTP服务器)的地址和PXE启动文件(pxelinux.0)

  · TFTP服务:向PXE客户端传输PXE启动文件、PXE引导配置文件、linux内核vmlinuz,以及系统启动文件initrd.img

  · NFS服务:向PXE客户端发布工作站的系统(整个根目录“/”的克隆);为了避免磁盘IO资源的冲突,建议将克隆的系统部署在存储服务器上

PXE客户端:PXE客户端无需硬盘,只需要一块支持PXE启动的网卡,将“网卡启动”设置为首选

操作系统
CentOS 7.2
软件环境
tftp-server-5.2-12.el7.x86_64 向无盘工作站传输系统启动文件等
nfs-utils-1.3.0-0.21.el7.x86_64 共享发布工作站系统
syslinux-4.05-12.el7.x86_64 提供引导程序”pxelinux.0”
dhcp-4.2.5-42.el7.centos.x86_64 提供DHCP 服务;指定TFTP 地址及PXE 启动文件
dracut-033-359.el7.x86_64 用来制作启动initrd 镜像
dracut-network-033-359.el7.x86_64 依赖包,否则将导致PXE无法启动

首先,克隆好工作站的系统模板

配置之前关掉防火墙和selinux

1
2
3
4
5
6
7
8
9
10
systemctl stop firewalld  #我还是比较习惯用iptables 所以关掉了 firewalld
systemctl disable firewalld
iptables -F #清空防火墙策略,如果之前有布置防火墙策略的需要查看下是否真要清空
iptables -vnL #查看filter防火墙策略

setenforce 0 #临时关闭selinux,重启后失效
vim /etc/sysconfig/selinux
SELINUX=disabled #关闭selinux,重启后生效


\1. 创建工作站系统模板的存放目录(/nodiskos/workstation)和启动引导文件存放目录(/nodiskos/tftpboot)

1
2
3
mkdir /nodiskos                               # 系统模板+启动文件存放目录
mkdir /nodiskos/tftpboot # 工作站系统启动文件存放目录
mkdir /nodiskos/workstation # 工作站系统模板存放目录

\2. 使用rsync 工具将整个”/“目录拷贝到/nodiskos/workstation 目录下,去除不需要的文件目录

1
2
rsync -av --exclude='/proc' --exclude='/sys' --exclude='/tmp' --exclude='/var/tmp' --exclude='/etc/mtab' --exclude='/nodiskos' /* /nodiskos/workstation

注意:在此处如果你有临时用的U盘或者移动硬盘之类的,先umount掉,否则会吧里面的内容一并拷贝到/nodiskos/workstation。很耗费时间,而且也没有用。

\3. 重新创建临时数据等目录,还原系统模板的目录结构,同时清除掉本机的主机名和IP配置

1
2
3
4
5
cd /nodiskos/workstation
mkdir proc sys tmp var/tmp
rm -f /nodiskos/workstation/etc/hostname
rm -f /nodiskos/workstation/etc/sysconfig/network-scripts/ifcfg-enp*

4.调整系统模板的设备挂载配置文件/nodiskos/workstation/etc/fstab:删除所有的本地存储设备挂载信息(如:/和/boot);添加系统模板的挂载信息。IP(192.168.199.162)是你的服务端

1
2
192.168.199.162:/nodiskos/workstation  /  nfs    defaults      0 0

5.将整个工作站系统模板打包备份到系统服务器的/opt 目录下,以作备用

1
2
cd /nodiskos
tar -cvf /opt/workstation.tar workstation

准备好工作站启动引导需要的文件

\1. 安装syslinux 和dracut 软件包

1
yum install syslinux dracut dracut-network

\2. 拷贝PXE启动文件(由syslinux 程序提供)

1
cp /usr/share/syslinux/pxelinux.0 /nodiskos/tftpboot

\3. 拷贝用linux内核文件vmlinuz

1
cp /boot/vmlinuz-3.10.0-327.el7.x86_64 /nodiskos/tftpboot

\4. 创建用于系统启动 镜像文件initrd.img

1
2
3
4
5
dracut initrd-3.10.0-327.el7.x86_64.img 3.10.0-327.el7.x86_64  
# 通用的做法是dracut initrd-`uname -r`.img `uname -r`
# 我在CentOS 7 上使用这种方法没有成功,还花费了我大量时间去排查错误,所以我使用的是镜像系统/image/pxeboot/initrd.img 改下名字就 可以了
chmod 644 initrd-3.10.0-327.el7.x86_64.img
mv initrd-3.10.0-327.el7.x86_64.img /nodiskos/tftpboot
5. 在/nodiskos/tftpboot/**pxelinux.cfg**/目录下创建默认的PXE引导配置文件"**default**"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# prompt 0 表示工作站立即启动,1 表示工作站等待选择
# kernel 指定内核文件
# append 后面的加下划线的是一行内容,不能换行!!!
# append 附加参数值解释说明:
# initrd= 指定用于引导的initrd 镜像文件
# root= 指定工作站系统的nfs 路径
# selinux= 设置selinux 开关,0 表示关闭,1 表示开启,默认为1
# rw 设置工作站系统为可读写
# nomodeset 这个参数是配合后面的vga=参数一起使用,设置分辨率
# vga= 这个参数值是设置分辨率,0x 表示十六进制,0314 表示800*600 16 位色
# 文件内容如下:

default auto
label auto
prompt 0
kernel vmlinuz-3.10.0-327.el7.x86_64
append initrd=initrd-3.10.0-327.el7.x86_64.img root=nfs:192.168.199.162:/nodiskos/workstation selinux=0 ip=dhcp rw nomodeset vga=0x0314
# 这里rw 需要斟酌考虑,如果你是给多个客户端使用,又怎会让他随便写数据呢(export文档中的也是如此)

\6. 最后,/disklessboot/tftpboot 目录下应该有下列几个文件/目录:

pxelinux.0 PXE 引导文件 (由第2 步创建)
pxelinux.cfg/default 默认的引导配置文件 (由第5 步创建)
initrd-3.10.0-327.el7.x86_64.img 用于引导的initrd 镜像文件 (由第4 步创建)
vmlinuz-3.10.0-327.el7.x86_64 用于引导的内核文件 (由第3 步创建)

配置DHCP服务

\1. 安装DHCP 服务软件包

1
yum install dhcp

\2. 编辑配置文件/etc/dhcp/dhcpd.conf

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
# dhcpd.conf 部分参数说明:
# default-lease-time # 指定确认租赁时长,单位为秒,-1 表示无限制
# max-lease-time # 指定最大租赁时长
# authritative # 拒绝不正确的IP 地址的要求
# subnet netmask {} # 设置dhcp 区域
# range # 提供动态分配IP 的范围;若所有工作站都是绑定的固定IP,可删除此配置
# option routers # 设置网关/路由器地址,多个地址用逗号隔开;若不想让客户端上网,可删除此配置
# domain-name-servers # 设置DNS,若不想让客户端上网,可删除此配置;多个地址用逗号隔开
# next-server # 告知工作站TFTP 服务器的地址,TFTP 服务提供启动引导
# filename # 告知工作站PXE 引导程序名
# host XXX {} # 此处是根据工作站的MAC 地址绑定固定的IP 地址,前提是知道MAC 地址
# hardware ethernet # 工作站的MAC 地址,一定要小写
# fixed-address # 绑定固定的IP 地址,和range 的不会有冲突,优先以它为主
# 配置内容如下:

ddns-update-style none;
ignore client-updates;
default-lease-time -1;
max-lease-time -1;
authritative;

subnet 192.168.199.0 netmask 255.255.255.0 {
range 192.168.199.100 192.168.199.200;
option routers 192.168.199.254;
option domain-name-servers 114.114.114.114,8.8.8.8;
next-server 192.168.199.162;
filename "pxelinux.0";

#下面是给指定mac地址分配指定IP的
host node1 {
hardware ethernet 12:34:56:78:ab:cd;
fixed-address 172.16.10.11;
}

}

\3. 重启DHCP服务,且将DHCP服务设置成开机自启

1
2
3
systemctl start dhcpd
systemctl enable dhcpd
systemctl status dhcpd

配置TFTP服务

\1. 安装TFTP 服务软件包

1
yum install tftp-server

\2. 编辑配置/etc/xinetd.d/tftp,只需更改如下2 处:

1
2
3
4
5
6
7
8
9
10
# and to start the installation process for some operating systems.
service tftp
{
  ...... ........
  server_args = -s /nodiskos/tftpboot
# 改成启动文件的存放目录(如果不修改此项,上面所有配在/nodiskos/tftpboot目录中的都要配在/var/lib/tftpboot目录下)
  Disable = no
# 将yes 改成no,以激活此服务
  ...... ........
}

\3. TFTP 服务是通过xinetd 工具管理的,因此需要通过xinetd 启动、停止、重启等

1
2
3
systemctl start xinetd
systemctl status xinetd
systemctl enable xinetd

• 配置NFS服务

\1. 安装NFS 服务软件包

1
yum install nfs-utils rpcbind

\2. 编辑配置文件/etc/exports,添加如下内容:

1
2
# 这一行是配置默认的工作站系统目录
/nodiskos/workstation  192.168.199.0/24(rw,async,no_root_squash)

\3. 重启NFS服务,且将NFS服务设置成开机自启

1
2
3
4
5
6
systemctl start rpcbind.socket 
systemctl start rpcbind.service
systemctl status rpcbind.service
systemctl status rpcbind.socket
systemctl start nfs-server
systemctl status nfs-server

\4. 至此,所有配置都已完成了。最后检查下DHCP、TFTP、NFS这3个服务是否都已启动,是否都已设置成开机自启,将所有PXE客户端的启动项设置成首选网卡启动,然后就启动PXE客户端了。

参考资料 http://www.bkjia.com/Linuxjc/1121652.html

补充:关于主机名

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
chmod +x /nodiskos/workstation/etc/rc.local
vim /nodiskos/workstation/etc/rc.local

eth0_name=enp129s0f0
ib_name=ib0
node1_mac="0c:c4:7a:85:3b:04"
node2_mac="0c:c4:7a:86:77:d6"
node3_mac="0c:c4:7a:82:c6:18"
node4_mac="0c:c4:7a:e0:75:72"
node5_mac=
node6_mac=
node7_mac="0c:c4:7a:82:c5:d8"
address=`ip a |grep -A 1 $eth0_name |grep link/ether|sed 's/[ ][ ]*/ /' |cut -d" " -f3`
case $address in

$node1_mac)
ip addr add 172.16.20.11/24 dev $ib_name
hostname node1
;;
$node2_mac)
ip addr add 172.16.20.12/24 dev $ib_name
hostname node2
;;
$node3_mac)
ip addr add 172.16.20.13/24 dev $ib_name
hostname node3
;;
$node4_mac)
ip addr add 172.16.20.14/24 dev $ib_name
hostname node4
;;
$node5_mac)
ip addr add 172.16.20.15/24 dev $ib_name
hostname node5
;;
$node6_mac)
ip addr add 172.16.20.16/24 dev $ib_name
hostname node6
;;
$node7_mac)
ip addr add 172.16.20.17/24 dev $ib_name
hostname node7
;;

*)

;;
esac

PXE配置文档

[TOC]

目前所做为测试,即在虚拟机上的测试。先简单介绍一下整体环境,两台centos7.2系统,7-2-a(安装vsftp tftp)和7-2-b(安装dhcp服务)

在7-2-a ip:192.168.199.149 的操作:

1
2
3
4
5
systemctl stop firewalld 
setenforce 0
yum install -y vsftpd tftp-server syslinux
cp -a /misc/cd/* /var/ftp
cp /root/anaconda-ks.cfg /var/ftp/ks.cfg

//这里ks.cfg需要根据自己需求简单修改配置,后面会说明用system-config-kickstart 如何配置ks.cfg

内容修改如下

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
#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# Install OS instead of upgrade
install
# Keyboard layouts
keyboard 'us'
# Root password
rootpw --iscrypted $1$gfl.Vz5t$mqzEhPMYDiANGwDB8gj/E/
# System timezone
timezone Asia/Shanghai
user --name=superman --password=$6$cq8y5jAZQCGd4muD$8G7zz.fpZFK3rI0AA7dyAxeD2B3mIjgu1HY/yeOm.PdsYHAYsD77K8uXTjbEPvJs9z7M6s0TECr6FtL2Bc5to/ --iscrypted --gecos="superman" #为服务器添加一个用户
# Use network installation
url --url="ftp://192.168.199.149"
# System language
lang en_US
# Firewall configuration
firewall --disabled
# System authorization information
auth --useshadow --passalgo=sha512
# Use text mode install
text
firstboot --enable
# SELinux configuration
selinux --disabled

# Network information
network --bootproto=dhcp --device=eno16777736 --ipv6=auto --activate
network --hostname=7-2-test

# Reboot after installation
reboot
# System bootloader configuration
bootloader --location=mbr --boot-drive=sda
# Partition clearing information
clearpart --all --initlabel
# Disk partitioning information
part / --fstype="xfs" --size=12040
part /boot --fstype="xfs" --size=10240
part /home --fstype="xfs" --size=10240
part /var --fstype="xfs" --size=20480
part /usr --fstype="xfs" --size=10240
part /tmp --fstype="xfs" --size=10240

%packages
@^minimal
@core
@ftp-server

%end

配置tftp-server

1
2
3
4
5
6
7
8
cp /usr/share/syslinux/pxelinux.0 /var/lib/tftpboot
mkdir /var/lib/tftpboot/pxelinux.cfg
cp /misc/cd/isolinux/isolinux.cfg /var/lib/tftpboot/pxelinux.cfg/default
cp /misc/cd/images/pxeboot/{vmlinuz,initrd.img} /var/lib/tftpboot/
cp /misc/cd/isolinux/{vesamenu.c32,boot.msg,splash.png} /var/lib/tftpboot/
vim /var/lib/tftpboot/pxelinux.cfg/default


default中 很多不需要修改,需要修改的部分如下

1
2
3
4
5
6
label linux
menu label ^Install CentOS 7 minimal
menu default
kernel vmlinuz
append initrd=initrd.img inst.stage2=ftp://192.168.199.149/ inst.ks=ftp://192.168.199.149/ks.cfg

label可以有多个,但是只能有一个label是menu default

启动服务

1
2
3
4
5
systemctl start vsftpd
systemctl start tftp.socket
systemctl start tftp.service #如果是开启了守护进程,则需要启动xinetd
ss -tunlp #通过端口简单查看服务是否启动

在7-2-b ip:192.168.199.158 的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
yum install -y dhcp
vim /etc/dhcp/dhcpd.conf
#
# DHCP Server Configuration file.
# see /usr/share/doc/dhcp*/dhcpd.conf.example
# see dhcpd.conf(5) man page
#
option domain-name-servers 192.168.199.1;

default-lease-time 60000;
max-lease-time 720000;

log-facility local7;

subnet 192.168.199.0 netmask 255.255.255.0 {
range 192.168.199.230 192.168.199.249;
option routers 192.168.199.1;
next-server 192.168.199.149;#这里的ip就是tftpd所在ip
filename "pxelinux.0";
}

systemctl start dhcpd

kickstart 生成ks.cfg

1
2
3
4
5
yum install -y system-config-kickstart.noarch

system-config-kickstart /var/ftp/ks.cfg #这个代表在原有基础上进行修改
system-config-kickstart #这个代表从头自己创建
运行之后按照如下配置即可

kickstart1.png

perform isntallation in text mode 代表使用 文本(非图形化)模式,默认为图形化模式 安装系统

kickstart2.png

获取安装包可以有多种方式这里使用ftp,ftp server 对应自己的ftp服务地址,directory对应在ftp下的哪个目录

kickstart3.png

磁盘分区可以根据需求修改,配置好了之后也可以在ks.cfg上进行再次修改

kickstart5.png

kickstart7.png

这里千万注意,为什么这里没有。这是centos 7 上的一个bug,在这里必须把yum原名称修改为development才会出现,(如果是有什么其他原因的,明白为什么的,麻烦告诉我,我只知道怎么改可以避免这个问题)

development.png

kickstart9.png

所有一切配置好了之后,就可以打开新机 看看能否自动安装系统了。

常见问题总结:

tftp问题.png

ftp问题.png

出现这个问题代表是tftp服务出错,获取到了ip(dhcp工作正常),第一个没有连接上tftp,第二个没有没有获取到pxelinux.0。可以从tftp入手差错。

停留.png

这里出现一个问题,ks.cfg吧所需要的都配好了,但是走到这里就停下来了。下面显示we won’t touch your disk until you click begin installation 但是begin installation却是灰色的,不能选中。

在图片中随便点开一个配置图片,不用修改任何东西,点出来就可以继续往下走了,但是这样就需要人工干预了,没有实现自动化安装。目前是由于什么原因导致的尚不知晓,后续如果有找到原因再来补充。

最后我在ks.cfg部分把运行模式改成了text,同时增加和删减了部分参数之后就可以了。

ok.png

Linux程序包的编译安装

[TOC]

在有些源代码程序没有被编译成rpm的时候,或者其他人写了一个源代码程序,要把它安装在服务器上要怎么做呢?
那就需要对源代码进行编译安装了。
C代码编译安装三步骤:

1、./configure:
    (1)通过选项传递参数,指定启用特性、安装路径等;执行时会参考用户的指定以及makefile.in文件生成makefile
    (2) 检查依赖到的外部环境,如依赖的软件包
2、make:根据makefile文件,构建应用程序
3、make install:复制文件到相应路径

开发工具:

autoconf: 生成configure脚本
automake:生成Makefile.in
注意:安装前查看INSTALL,README

例子:

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
下面就以编译安装HTTP服务为例进行说明:
首先要 获取到HTTP源代码,此处通过FTP获取
yum install lftp 安装FTP--源代码获取工具
ftp://172.16.0.1/pub/Sources/sources/httpd/httpd-2.2.29.tar.bz2 --下载源代码
tar xvf httpd-2.2.29.tar.bz2 --解压源代码--> 得到http-2.2.29 目录
由于要用到autoconf和automake工具 因此可以安装 工具包
yum groupinstall "Development Tools"
安装工具安装好了之后进入http目录执行 ./configure命令,注意这个命令要指定该软件安装的程序所在目录,以及配置文件所在目录。所以执行./configure命令之前要先看一下目录下的INSTALL、README两个文件
http服务中--prefix=程序安装目录 --sysconfdir=配置文件目录 如果不加这两个选项,是有默认安装路径的。在man帮助中有,接下来执行:
./configure --prefix=/usr/local/huyuhttp --sysconfdir=/etc/huyuhttp/
make 和 make install
这样呢其实已经安装完了http服务,但是此时http还没有启动,帮助文档还不能方便查看,调用的库也不行,共享库有哪些也不知道,所以要进行接下来的配置。
1、在/etc/profile.d/目录下创建一个以.sh结尾的文件,修改path变量,加入http二进制程序路径,这样就可以不用加路径直接执行http程序了。
vim /etc/profile.d/huyuhttp.sh
PATH=$PATH:/usr/local/huyuhttp/bin
. /etc/profile.d/huyuhttp.sh 刷新path变量值
2、添加man手册,可以方便查看帮助
vim /etc/man_db.conf /usr/local/huyuhttp/man
3、添加lib图文件目录
vim /etc/ld.so.conf.d/huyuhttp.conf /usr/local/huyuhttp/lib
ldconfig 刷新库文件缓存
4、添加头文件,这里只需要在include的目录中加入http的include目录链接即可
ln -s /usr/local/huyuhttp/include/ /usr/include/huyuhttp
5、关闭防火墙
iptables -F
6、开启http
apachectl start
7、查看端口是否打开
netstat -ant 查看80
8、测试查看网页
links ip
curl ip

dd命令制作U盘启动

[TOC]

1
2
3
4
5
6
7
1、插入U盘,df -h查看U盘文件系统挂载情况,然后使用umount /dev/sdb*卸载U盘文件系统;

2、执行命令:sudo mkfs.vfat -I /dev/sdb格式化U盘为FAT格式;

3、dd if=*/*.iso   of=/dev/sdb  bs=4M  (数据块大小,每个数据块只能存一个文件的数据)

4、执行sync,同步缓存中的数据至U盘;