-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
3003 lines (2515 loc) · 216 KB
/
Copy pathatom.xml
File metadata and controls
3003 lines (2515 loc) · 216 KB
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
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Sean's Blog]]></title>
<link href="http://seanguo.github.io/atom.xml" rel="self"/>
<link href="http://seanguo.github.io/"/>
<updated>2017-05-28T21:03:34+08:00</updated>
<id>http://seanguo.github.io/</id>
<author>
<name><![CDATA[Sean Guo]]></name>
<email><![CDATA[seanguo85@qq.com]]></email>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Shell+Ruby]]></title>
<link href="http://seanguo.github.io/blog/2017/05/28/shell-plus-ruby/"/>
<updated>2017-05-28T20:25:34+08:00</updated>
<id>http://seanguo.github.io/blog/2017/05/28/shell-plus-ruby</id>
<content type="html"><![CDATA[<p>最近公司产品的新特性开发的不是那么多了,所以自己有时间闲下来偿还一下以前欠下的技术债。公司的发版流程是自己一步步实现出来的,整体结构是由一个个的shell脚本来实现的。把发版的每一个步骤拆分为独立的一个个脚本,这样流程变化了可以通过脚本组合的变化来适应变化。毕竟能够维持不变的东西永远是<strong>变化</strong>。</p>
<p>以前的问题是由于当时开发的紧迫性,加上自己对脚本的不太重视,导致开发的这些脚本整体结构还算好,但是就是里面会有很多重复的常量在里面。这里的常量就是要发版的各个组件的名字,由于目前产品组件的不确定性,经常会添加或者删除一个组件,目前的缺点就是添加或者删除一个组件的时候需要更改多个脚本,违背了SPOT原则,会很容易遗落下本应同步修改的脚本。</p>
<p>这次自己有时间了决定把这些常量提取出去作为一个配置文件单独存在,思路是简单而直接的,但是由于shell脚本的局限性,把组件名字提出去还算可行,但是我想要对每个组件加上单独的其他配置的话好像比较绕。以以下脚本为例来说:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="k">for </span>repo in <span class="s2">"COM_A COM_B COM_C"</span>
</span><span class='line'><span class="k">do</span>
</span><span class='line'><span class="k"> </span><span class="nb">cd</span> <span class="nv">$repo</span>
</span><span class='line'> <span class="k">if</span> <span class="o">[</span> <span class="nv">$repo</span> <span class="o">==</span> <span class="s2">"COM_B"</span>
</span><span class='line'> <span class="nb">cd </span>modules
</span><span class='line'> <span class="k">fi</span>
</span><span class='line'><span class="k"> </span>mvn <span class="nv">setVersion</span><span class="o">=</span><span class="nv">$newVersion</span>
</span><span class='line'><span class="k">done</span>
</span></code></pre></td></tr></table></div></figure>
<p>这个脚本是迭代每个组件,然后去修改pom.xml里面的version改为要发版的version,问题有的组件的parent的pom.xml没在根目录下,需要切换到对应的目录才能进行操作。</p>
<p>我们可以很容易就把 “COM_A COM_B COM_C” 提取出去, 例如:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nb">export </span><span class="nv">all_repos</span><span class="o">=</span><span class="s2">"COM_A COM_B COM_C"</span>
</span></code></pre></td></tr></table></div></figure>
<p>这样脚本就变成了</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="k">for </span>repo in <span class="nv">$all_repos</span>
</span><span class='line'><span class="k">do</span>
</span><span class='line'><span class="k"> </span><span class="nb">cd</span> <span class="nv">$repo</span>
</span><span class='line'> <span class="k">if</span> <span class="o">[</span> <span class="nv">$repo</span> <span class="o">==</span> <span class="s2">"oneRepo"</span>
</span><span class='line'> <span class="nb">cd </span>modules
</span><span class='line'> <span class="k">fi</span>
</span><span class='line'><span class="k"> </span>mvn versions:set -DnewVersion<span class="o">=</span><span class="nv">$newVersion</span>
</span><span class='line'><span class="k">done</span>
</span></code></pre></td></tr></table></div></figure>
<p>问题是这个modules目录怎么配置出去,想过这样去做:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nb">export </span><span class="nv">COM_B_pom_path</span><span class="o">=</span>modules
</span></code></pre></td></tr></table></div></figure>
<p>但是问题是这只是一个配置而已,因为发版流程还涉及到其他的目录,像我们的组件用的Chef的cookbook来配置安装,所以我还要配置这个cookbook的路径,然后我们的cookbook用的test kitchen来测试,所以还要配置test kitchen的测试文件所在的路径,这样会有很多export,可读性和可维护性都很差。</p>
<p>根据以往的经验,所有复杂的问题理论上都可以经过抽象或者添加中间层的方式来简化实现。这里我想到了用Ruby来生成shell需要的export全局变量,然后既然用到Ruby了很自然的配置文件就用到了YAML。这种配置文件既简洁又保持了很好的可读性。下面就是就是yaml关于这次修改的部分样例:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="o">---</span>
</span><span class='line'><span class="n">components</span>
</span><span class='line'> <span class="no">COM_A</span>
</span><span class='line'> <span class="ss">pom</span><span class="p">:</span> <span class="sr">/</span>
</span><span class='line'><span class="sr"> cookbook: cookbook</span>
</span><span class='line'><span class="sr"> test_kitchen: /</span>
</span><span class='line'> <span class="no">COM_B</span>
</span><span class='line'> <span class="ss">pom</span><span class="p">:</span> <span class="n">modules</span>
</span><span class='line'> <span class="ss">cookbook</span><span class="p">:</span> <span class="n">cookbook</span>
</span><span class='line'> <span class="n">test_kitchen</span><span class="p">:</span> <span class="sr">/</span>
</span><span class='line'><span class="sr"> COM_C</span>
</span><span class='line'><span class="sr"> pom: /</span>
</span><span class='line'> <span class="ss">cookbook</span><span class="p">:</span> <span class="n">cookbook</span>
</span><span class='line'> <span class="n">test_kitchen</span><span class="p">:</span> <span class="sr">/</span>
</span><span class='line'><span class="sr">...</span>
</span></code></pre></td></tr></table></div></figure>
<p>这样我们可以很容易的实现一段Ruby代码来生成这个shell的环境文件:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
</pre></td><td class='code'><pre><code class='yaml'><span class='line'><span class="l-Scalar-Plain">require "yaml"</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">def all_repo_list(yaml)</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">return yaml.keys.join(" ")</span>
</span><span class='line'><span class="l-Scalar-Plain">end</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">def all_cookbook_dirs(yaml)</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">all_dir_for(yaml, "cookbook")</span>
</span><span class='line'><span class="l-Scalar-Plain">end</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">def all_pom_dirs(yaml)</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">all_dir_for(yaml, "pom")</span>
</span><span class='line'><span class="l-Scalar-Plain">end</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">def all_test_kitchen_dirs(yaml)</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">all_dir_for(yaml, "test_kitchen")</span>
</span><span class='line'><span class="l-Scalar-Plain">end</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">def all_dir_for(yaml, type)</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">dirs = []</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">yaml.each do |k, v|</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">next if v.nil? || v[type].nil?</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">subfolder = v[type]</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">dirs << "#{k}#{subfolder}"</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">end</span>
</span><span class='line'><span class="err"> </span><span class="l-Scalar-Plain">dirs.join(" ")</span>
</span><span class='line'><span class="l-Scalar-Plain">end</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">current_dir = File.dirname(__FILE__)</span>
</span><span class='line'><span class="l-Scalar-Plain">yaml = YAML.load_file("#{current_dir}/config.yml")</span>
</span><span class='line'><span class="l-Scalar-Plain">all_components = yaml["components"]</span>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">text = []</span>
</span><span class='line'><span class="l-Scalar-Plain">text << "export all_repos=\"#{all_repo_list(all_components)}\""</span>
</span><span class='line'><span class="l-Scalar-Plain">text << "export all_cookbook_dirs=\"#{all_cookbook_dirs(all_components)}\""</span>
</span><span class='line'><span class="l-Scalar-Plain">text << "export all_pom_dirs=\"#{all_pom_dirs(all_components)}\""</span>
</span><span class='line'><span class="l-Scalar-Plain">text << "export all_test_kitchen_dirs=\"#{all_test_kitchen_dirs(all_components)}\""</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="l-Scalar-Plain">File.open("#{current_dir}/config", "w") {|file| file.write(text.join("\n")) }</span><span class="err"> </span>
</span></code></pre></td></tr></table></div></figure>
<p>然后在脚本执行前source一下这个生成的文件<strong>config</strong>即可。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[SIP Headers]]></title>
<link href="http://seanguo.github.io/blog/2017/04/23/sip-headers/"/>
<updated>2017-04-23T19:45:06+08:00</updated>
<id>http://seanguo.github.io/blog/2017/04/23/sip-headers</id>
<content type="html"><![CDATA[<h2>引言</h2>
<p>SIP协议的设计很多参考了已有的HTTP协议,例如都是用的文本,验证用户相关的header和content-type和body的设计。这里主要说一下SIP独有的这些header,其中对路由相关的header又是重点要说的。</p>
<h2>From和To</h2>
<p>这两个header是作为标识存在的,对协议本身的路由来说不起什么作用。在实际电话呼叫中会标识主叫方和被叫方。其中的tag参数被选用来标识session。除了这两个tag参数外,session的标识还要用到另外一个header: Call-ID的值。下面是<a href="https://tools.ietf.org/html/rfc3261">RFC3261</a>里面的一个例子:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>From: "Bob" <sips:bob@biloxi.com> ;tag=a48s
</span><span class='line'>From: sip:+12125551212@phone2net.com;tag=887s
</span><span class='line'>From: Anonymous <sip:c8oqz84zk7z@privacy.org>;tag=hyh8
</span><span class='line'>
</span><span class='line'>To: Carol <sip:carol@chicago.com></span></code></pre></td></tr></table></div></figure>
<p>可以看到这两个header里可以包含一个用来描述这个URI的display name。在呼叫中这个就会用来标识呼叫的主被叫的名字。</p>
<p>From和To在一侧的请求和响应里是一致的,但是和呼叫另一侧发过来的请求是相反的。</p>
<h2>Contact</h2>
<p>这个header用来标识session内这个UA期望对方request发送到的地址。在一个Invite发起的session中,一般会包含在Invite和对应的响应里。它所表示的地址就是session内ACK,Bye,re-Invite等发送到这个UA的地址。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>Contact: <sip:pc33.atlanta.com></span></code></pre></td></tr></table></div></figure>
<h2>Via</h2>
<p>上面讲的Contact是为request指示地址,而Via是为request对应的response来指示地址的。它是在request被发送的时候添加的,而对方收到请求之后会把响应发给这个header标示的地址。如果涉及到NAT或者防火墙之类的,这个发送方添加的地址和接收方收到的源地址不同的情况。这种情况下协议添加了个received的参数来标示实际收到的request是从哪发来的。这样保证了response能原路发送回request发送方。RFC3261中介绍了这种情况下的一个例子:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>INVITE sip:bob@Biloxi.com SIP/2.0
</span><span class='line'>Via: SIP/2.0/UDP bobspc.biloxi.com:5060</span></code></pre></td></tr></table></div></figure>
<p>这个request的接收方发现它的源地址是和via里面的地址不一样的,所以就在里面加上了received参数来标示实际的源地址:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>INVITE sip:bob@Biloxi.com SIP/2.0
</span><span class='line'>Via: SIP/2.0/UDP bobspc.biloxi.com:5060;received=192.0.2.4</span></code></pre></td></tr></table></div></figure>
<p>Via里面还有个重要的参数branch来标示这个request对应的transaction。</p>
<h2>Request-Uri</h2>
<p>这个准确来说不是一个header,因为它是request第一行里请求类型后面的URI。它是用来标识请求要发向的地址的,因为我们前面说了To header不决定路由。</p>
<h2>Route和Record-Route</h2>
<p>在没有Proxy的情况下只要一个Request-Uri就能把request路由到目的地了,但是实际情况是request总要经过一些Proxy来达到目的地。所以我们还要用Route来标示请求中间经过的节点。当Proxy收到请求后发现top Route是自己的地址就会去掉转发给下一个目的地。如果这个Proxy配置成Record Route的,就会在请求中加入Record-Route这个header,这个header的加入就表示session内的其他请求也会经过这个节点。所以Record-Route是保存在session内的状态,它和Contact共同决定了session内请求的路由路径。</p>
<figure class='code'><figcaption><span>Simple Proxy </span></figcaption>
<div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>+---------+ +-----------+ +-----------+
</span><span class='line'>| | | | | |
</span><span class='line'>|UA-Caller| | Proxy | | UA-Callee |
</span><span class='line'>+----+----+ +-----+-----+ +-----+-----+
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> +-------------------------> |
</span><span class='line'> |INVITE sip:callee@192.168.1.7 |
</span><span class='line'> |Route: sip:192.168.1.5 |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | +-------------------------->
</span><span class='line'> | | INVITE sip:callee@192.168.1.7
</span><span class='line'> | | Record-Route: sip:192.168.1.5
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | <--------------------------+
</span><span class='line'> | | SIP/2.0 200 OK |
</span><span class='line'> | | Record-Route: sip:192.168.1.5
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> <-------------------------+ |
</span><span class='line'> | SIP/2.0 200OK | |
</span><span class='line'> | Record-Route: sip:192.168.1.5 |
</span><span class='line'> | + |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> +-------------------------> |
</span><span class='line'> | BYE sip:callee@192.168.1.5 |
</span><span class='line'> | Route: sip:192.168.1.5| |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | +-------------------------->
</span><span class='line'> | | BYE sip:callee@192.168.1.5
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> | | |
</span><span class='line'> + + +</span></code></pre></td></tr></table></div></figure>
<p>这里的Record-Route通过INVITE传给了UA-Callee,并通过200OK返回给了UA-Caller,保证了后续的BYE(UA-Callee发起的也是一样)必须经过Proxy才能到对方。</p>
<p>如果request需要经过多个Proxy,就有可能会有多个Record-Route。这个Record-Route的添加也是按顺序添加到request里的,这样保证消息能够按初始request的路径来路由。</p>
<p>如果这个Proxy正好部署在网络边界上(多网卡机器),有可能UA-Caller这侧是一个网段而UA-Callee成了另一个网段,或者两侧使用的transport不同。这样由于Record-Route是共享给两侧使用的,这就会造成一侧的消息发不到Proxy。因为Record-Route没有像Via那样可以加个received的参数来揭示源地址。</p>
<p><a href="https://tools.ietf.org/html/rfc5658">RFC5658</a>通过添加两个Record-Route来巧妙的解决了这个问题。可以直接参考那个RFC里面的这个例子:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
</pre></td><td class='code'><pre><code class=''><span class='line'> UA1 Proxy "P1" UA2
</span><span class='line'> (IPv4) (IPv4/IPv6) (IPv6)
</span><span class='line'> | | |
</span><span class='line'> | F1 INVITE | |
</span><span class='line'> |------------------->| F2 INVITE |
</span><span class='line'> | |------------------->|
</span><span class='line'> | 100 Trying | |
</span><span class='line'> |<-------------------| |
</span><span class='line'> | | F3 200 OK |
</span><span class='line'> | F4 200 OK |<-------------------|
</span><span class='line'> |<-------------------| |
</span><span class='line'> | | |
</span><span class='line'> | F5 ACK | |
</span><span class='line'> |------------------->| F6 ACK |
</span><span class='line'> | |------------------->|
</span><span class='line'> | | |
</span><span class='line'> | | F7 BYE |
</span><span class='line'> | F8 BYE |<-------------------|
</span><span class='line'> |<-------------------| |
</span><span class='line'>
</span><span class='line'> Figure 2: IPv4 to IPv6 Multi-Homed Proxy Illustration
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> F1 INVITE UA1 -> P1 (192.0.2.254:5060)
</span><span class='line'>
</span><span class='line'> INVITE sip:bob@biloxi.example.com SIP/2.0
</span><span class='line'> Route: <sip:192.0.2.254:5060;lr>
</span><span class='line'> From: Alice <sip:alice@atlanta.example.com>;tag=1234
</span><span class='line'> To: Bob <sip:bob@biloxi.example.com>
</span><span class='line'> Contact: <sip:alice@192.0.2.1>
</span><span class='line'>
</span><span class='line'> F2 INVITE P1 (2001:db8::1) -> UA2
</span><span class='line'>
</span><span class='line'> INVITE sip:bob@biloxi.example.com SIP/2.0
</span><span class='line'> Record-Route: <sip:[2001:db8::1];lr>
</span><span class='line'> Record-Route: <sip:192.0.2.254:5060;lr>
</span><span class='line'> From: Alice <sip:alice@atlanta.example.com>;tag=1234
</span><span class='line'> To: Bob <sip:bob@biloxi.example.com>
</span><span class='line'> Contact: <sip:alice@192.0.2.1>
</span><span class='line'>
</span><span class='line'> Dialog State at UA2:
</span><span class='line'> Local URI = sip:bob@biloxi.example.com
</span><span class='line'> Remote URI = sip:alice@atlanta.example.com
</span><span class='line'> Remote target = sip:alice@192.0.2.1
</span><span class='line'> Route Set = sip:[2001:db8::1];lr
</span><span class='line'> sip:192.0.2.254:5060:lr
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> F3 200 OK UA2 -> P1 (2001:db8::1)
</span><span class='line'>
</span><span class='line'> SIP/2.0 200 OK
</span><span class='line'> Record-Route: <sip:[2001:db8::1];lr>
</span><span class='line'> Record-Route: <sip:192.0.2.254:5060;lr>
</span><span class='line'> From: Alice <sip:alice@atlanta.example.com>;tag=1234
</span><span class='line'> To: Bob <sip:bob@biloxi.example.com>;tag=4567
</span><span class='line'> Contact: <sip:bob@[2001:db8::33]>
</span><span class='line'>
</span><span class='line'> F4 200 OK P1 -> UA1
</span><span class='line'>
</span><span class='line'> SIP/2.0 200 OK
</span><span class='line'> Record-Route: <sip:[2001:db8::1];lr>
</span><span class='line'> Record-Route: <sip:192.0.2.254:5060;lr>
</span><span class='line'> From: Alice <sip:alice@atlanta.example.com>;tag=1234
</span><span class='line'> To: Bob <sip:bob@biloxi.example.com>;tag=4567
</span><span class='line'> Contact: <sip:bob@[2001:db8::33]>
</span><span class='line'>
</span><span class='line'> Dialog State at UA1:
</span><span class='line'> Local URI = sip:alice@atlanta.example.com
</span><span class='line'> Remote URI = sip:bob@biloxi.example.com
</span><span class='line'> Remote target = sip:bob@[2001:db8::33]
</span><span class='line'> Route Set = sip:192.0.2.254:5060:lr
</span><span class='line'> sip:[2001:db8::1];lr
</span><span class='line'>
</span><span class='line'> F5 ACK UA1 -> P1 (192.0.2.254:5060)
</span><span class='line'>
</span><span class='line'> ACK sip:bob@[2001:db8::33] SIP/2.0
</span><span class='line'> Route: <sip:192.0.2.254:5060:lr>
</span><span class='line'> Route: <sip:[2001:db8::1];lr>
</span><span class='line'> From: Alice <sip:alice@atlanta.example.com>;tag=1234
</span><span class='line'> To: Bob <sip:bob@biloxi.example.com>;tag=4567
</span><span class='line'>
</span><span class='line'> F6 ACK P1 (2001:db8::1) -> UA2
</span><span class='line'>
</span><span class='line'> ACK sip:bob@[2001:db8::33] SIP/2.0
</span><span class='line'> From: Alice <sip:alice@atlanta.example.com>;tag=1234
</span><span class='line'> To: Bob <sip:bob@biloxi.example.com>;tag=4567
</span><span class='line'> (both Route headers have been removed by the proxy)
</span><span class='line'>
</span><span class='line'> F7 BYE UA2 -> P1 (2001:db8::1)
</span><span class='line'>
</span><span class='line'> BYE sip:alice@192.0.2.1 SIP/2.0
</span><span class='line'> Route: <sip:[2001:db8::1];lr>
</span><span class='line'> Route: <sip:192.0.2.254:5060:lr>
</span><span class='line'> From: Bob <sip:bob@biloxi.example.com>;tag=4567
</span><span class='line'> To: Alice <sip:alice@atlanta.example.com>;tag=1234
</span><span class='line'>
</span><span class='line'>
</span><span class='line'> F8 BYE P1 (192.0.2.254:5060) -> UA1
</span><span class='line'>
</span><span class='line'> BYE sip:alice@192.0.2.1 SIP/2.0
</span><span class='line'> From: Bob <sip:bob@biloxi.example.com>;tag=4567
</span><span class='line'> To: Alice <sip:alice@atlanta.example.com>;tag=1234
</span></code></pre></td></tr></table></div></figure>
<p>里面是用的ipv4和ipv6举的例子,不同网段或者transport的是类似的。</p>
<h2>CSeq</h2>
<p>这个表示了会话(session)内的消息的顺序,呼叫两侧的CSeq号是分别维护的。</p>
<p>好了这篇到这告一段落了。其他的header比较简单了,可以查看RFC得到明确的意义。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Vagrant+Chef]]></title>
<link href="http://seanguo.github.io/blog/2017/03/12/vagrant-plus-chef/"/>
<updated>2017-03-12T19:32:51+08:00</updated>
<id>http://seanguo.github.io/blog/2017/03/12/vagrant-plus-chef</id>
<content type="html"><![CDATA[<h2>引言</h2>
<p>前面我介绍了Chef的环境搭建和简单的cookbook的创建执行,也介绍了如果用Vagrant来快速搭建一台虚拟机。但是所有的东西都停留在hello world的阶段,这篇文章就是结合这两个生产力工具来搭建一组<del>可以实际使用</del>用来做rails开发的server。</p>
<h2>Chef Provisioning</h2>
<p>我们知道Vagrant包含多种不同类型的provisioner,而Chef就是其中内置的一种,所以我们是可以直接使用的。这里我们用到的是chef_solo, Chef Solo是Chef Client的单机版,运行不依赖于Chef Server。</p>
<p>第一步我们要下载我们需要安装的组件的cookbook,这里我们会用到第三方的cookbook,因为在<a href="https://supermarket.chef.io/cookbooks/">社区</a>里已经有很多成熟的cookbook了。但是手工下载的方式不太方便,这里我们用到cookbook的依赖管理的工具: <a href="https://docs.chef.io/berkshelf.html">Berkshelf</a>。它和Ruby的gem管理文件Gemfile语法类似,它的配置文件是Berksfile。我们在当前文件夹(我这里是<strong>vagrant_test</strong>)创建一个空的Berksfile。chef-dk里面已经包含Berkshelf的命令行工具了,对应的命令是<strong>berks</strong>, 但是Vagrant想要用Berkshelf的时候我们还要装个插件来实现,可以用下面的命令来安装最新Berkshelf的插件。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>vagrant plugin install vagrant-berkshelf
</span></code></pre></td></tr></table></div></figure>
<p>然后编辑Berksfile加上如下两行:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">source</span> <span class="s1">'https://supermarket.chef.io'</span>
</span><span class='line'>
</span><span class='line'><span class="n">cookbook</span> <span class="s1">'rails'</span><span class="p">,</span> <span class="s1">'~> 0.9.2'</span>
</span></code></pre></td></tr></table></div></figure>
<p>source语句指定了去supermarket.chef.io搜索下载cookbook, 第二行声明我们依赖于一个叫rails的cookbook,version为0.9.2,关于version的语法可以<a href="https://docs.chef.io/config_rb_metadata.html#cookbook-version-constraints">戳这里</a>。</p>
<p>我们接着创建一个新的Vagrantfile, 这里我们打算创建两个虚拟机,一个作为rails的主server,另一个用来安装mysql。我们先看第一台虚拟机的配置:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># -*- mode: ruby -*-</span>
</span><span class='line'><span class="c1"># vi: set ft=ruby :</span>
</span><span class='line'>
</span><span class='line'><span class="no">Vagrant</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span><span class="s2">"2"</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">#base box for all machines</span>
</span><span class='line'> <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">box</span> <span class="o">=</span> <span class="s2">"bento/centos-6.7"</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">#define a VM named rails</span>
</span><span class='line'> <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">define</span> <span class="s2">"rails"</span> <span class="k">do</span> <span class="o">|</span><span class="n">rails</span><span class="o">|</span>
</span><span class='line'>
</span><span class='line'> <span class="n">rails</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provider</span> <span class="s2">"virtualbox"</span> <span class="k">do</span> <span class="o">|</span><span class="n">v</span><span class="p">,</span> <span class="n">override</span><span class="o">|</span>
</span><span class='line'> <span class="n">v</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">"rails"</span>
</span><span class='line'> <span class="n">override</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:private_network</span><span class="p">,</span> <span class="ss">ip</span><span class="p">:</span> <span class="s2">"192.168.50.20"</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">#configure chef provisoning per VM</span>
</span><span class='line'> <span class="n">rails</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provision</span> <span class="s2">"shell"</span><span class="p">,</span> <span class="ss">inline</span><span class="p">:</span> <span class="s2">"yum -y groupinstall 'Development Tools'"</span>
</span><span class='line'>
</span><span class='line'> <span class="n">rails</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provision</span> <span class="s2">"chef_solo"</span> <span class="k">do</span> <span class="o">|</span><span class="n">chef</span><span class="o">|</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">node_name</span> <span class="o">=</span> <span class="s2">"rails"</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="ss">:debug</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">json</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"run_list"</span> <span class="o">=></span> <span class="o">[</span><span class="s2">"rails"</span><span class="o">]</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>然后我们启动这台rails虚拟机,多虚拟机配置的启动需要指定虚拟机的名字,要不就是默认全部启动。</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>vagrant up rails
</span></code></pre></td></tr></table></div></figure>
<p>这块儿由于是第一次启动这个虚拟机,它会首先下载需要的cookbook,然后映射到虚拟机里,启动虚拟机之后会首先下载安装Chef,这个过程很耗时间。</p>
<p>这里定义了两个provisioning,一个是用sh安装Rails依赖的开发工具包。另一个是利用rails这个cookbook来配置Rails的环境。
我这块遇到了在墙内会超时的问题。科学上网后解决了但是还是很耗时间,主要是下载Chef的安装包费时间。我们可以在其装好了chef和dev tools之后把这个box存起来作为以后的base box。命令如下:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>vagrant package --base rails
</span><span class='line'>vagrant box add mybase package.box
</span></code></pre></td></tr></table></div></figure>
<p>安装完box之后可以用下面的命令查看是否安装成功:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>vagrant box list
</span><span class='line'>bento/centos-6.7 <span class="o">(</span>virtualbox, 2.2.7<span class="o">)</span>
</span><span class='line'>mybase <span class="o">(</span>virtualbox, 0<span class="o">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>以后就可以用mybase作为box的name来复用已经下载安装好Chef和dev tools的box。</p>
<p>安装成功后我们可以用如下命令登录进去:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>vagrant ssh rails
</span></code></pre></td></tr></table></div></figure>
<p>然后我们定义另外一个虚拟机用来安装mysql,这里我们取名为mysql:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">define</span> <span class="s2">"mysql"</span> <span class="k">do</span> <span class="o">|</span><span class="n">mysql</span><span class="o">|</span>
</span><span class='line'>
</span><span class='line'> <span class="n">mysql</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provider</span> <span class="s2">"virtualbox"</span> <span class="k">do</span> <span class="o">|</span><span class="n">v</span><span class="p">,</span> <span class="n">override</span><span class="o">|</span>
</span><span class='line'> <span class="n">v</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">"mysql"</span>
</span><span class='line'> <span class="n">override</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:private_network</span><span class="p">,</span> <span class="ss">ip</span><span class="p">:</span> <span class="s2">"192.168.50.21"</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">mysql</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provision</span> <span class="s2">"chef_solo"</span> <span class="k">do</span> <span class="o">|</span><span class="n">chef</span><span class="o">|</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">node_name</span> <span class="o">=</span> <span class="s2">"mysql"</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="ss">:debug</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">json</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"run_list"</span> <span class="o">=></span> <span class="o">[</span><span class="s2">"vagrant_chef::mysql"</span><span class="o">]</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'> <span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>因为对这个cookbook的调用不能直接通过runlist,需要在recipe里调用它的resource来进行,我们需要把当前目录变成一个cookbook。一个cookbook的最小因素就是一个用来自描述的metadata.rb</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">name</span> <span class="s2">"vagrant_chef"</span>
</span><span class='line'><span class="n">maintainer</span> <span class="s2">"YOUR_NAME"</span>
</span><span class='line'><span class="n">maintainer_email</span> <span class="s2">"YOUR_EMAIL"</span>
</span><span class='line'><span class="n">license</span> <span class="s2">"All rights reserved"</span>
</span><span class='line'><span class="n">description</span> <span class="s2">"Installs/Configures mysql server"</span>
</span><span class='line'><span class="n">version</span> <span class="s2">"0.0.1"</span>
</span><span class='line'>
</span><span class='line'><span class="n">depends</span> <span class="s2">"mysql"</span>
</span></code></pre></td></tr></table></div></figure>
<p>这里我们还要加上对mysql的依赖,只有这样才能保证使用mysql的resource之前对mysql的依赖都全部被加载好。然后我们需要在Berksfile里指定mysql的cookbook版本,这样Berkshelf插件才会把这个新依赖的cookbook抓下来:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">source</span> <span class="s1">'https://supermarket.chef.io'</span>
</span><span class='line'><span class="n">metadata</span>
</span><span class='line'>
</span><span class='line'><span class="n">cookbook</span> <span class="s1">'rails'</span><span class="p">,</span> <span class="s1">'~> 0.9.2'</span>
</span><span class='line'>
</span><span class='line'><span class="n">cookbook</span> <span class="s1">'mysql'</span><span class="p">,</span> <span class="s1">'~> 8.2.0'</span>
</span></code></pre></td></tr></table></div></figure>
<p>我们还加上了一行metadata,表示我们解析当前目录的metadata.rb, 把当前这个cookbook也加载进来。然后我们创建一个receipes文件夹,创建一个mysql.rb:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">mysql_service</span> <span class="s1">'mysql'</span> <span class="k">do</span>
</span><span class='line'> <span class="n">port</span> <span class="s1">'3306'</span>
</span><span class='line'> <span class="n">version</span> <span class="s1">'5.5'</span>
</span><span class='line'> <span class="n">initial_root_password</span> <span class="s1">'change me'</span>
</span><span class='line'> <span class="n">action</span> <span class="o">[</span><span class="ss">:create</span><span class="p">,</span> <span class="ss">:start</span><span class="o">]</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
<p>这个Recipe用来安装设置mysql, 可以看到上面我们中对虚拟机的provisioning的配置里可以通过把<strong>vagrant_chef::mysql</strong>加到runlist来实现对这个Recipe的调用。
所有都做好我们可以调用</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>vagrant up mysql
</span></code></pre></td></tr></table></div></figure>
<p>这样mysql这个虚拟机也会被创建设置好。</p>
<p>本来就想写个vagrant+chef的教程,结果大部分时间花在调试这两个别人写的cookbook。终于还是放弃了,所以这个教程的Chef安装部分是跑不起来的,仅供参考。但是其中你也能学到多个虚拟机的配置,组网,如何在Vagrant使用Chef, Berkshelf这些东西。</p>
<p>完整的Vagrantfile如下:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="c1"># -*- mode: ruby -*-</span>
</span><span class='line'><span class="c1"># vi: set ft=ruby :</span>
</span><span class='line'>
</span><span class='line'><span class="no">Vagrant</span><span class="o">.</span><span class="n">configure</span><span class="p">(</span><span class="s2">"2"</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">#base box for all machines</span>
</span><span class='line'> <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">box</span> <span class="o">=</span> <span class="s2">"bento/centos-6.7"</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">#define a VM named rails</span>
</span><span class='line'> <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">define</span> <span class="s2">"rails"</span> <span class="k">do</span> <span class="o">|</span><span class="n">rails</span><span class="o">|</span>
</span><span class='line'>
</span><span class='line'> <span class="n">rails</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provider</span> <span class="s2">"virtualbox"</span> <span class="k">do</span> <span class="o">|</span><span class="n">v</span><span class="p">,</span> <span class="n">override</span><span class="o">|</span>
</span><span class='line'> <span class="n">v</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">"rails"</span>
</span><span class='line'> <span class="n">override</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:private_network</span><span class="p">,</span> <span class="ss">ip</span><span class="p">:</span> <span class="s2">"192.168.50.20"</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="c1">#configure chef provisoning per VM</span>
</span><span class='line'> <span class="n">rails</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provision</span> <span class="s2">"shell"</span><span class="p">,</span> <span class="ss">inline</span><span class="p">:</span> <span class="s2">"yum -y groupinstall 'Development Tools'"</span>
</span><span class='line'>
</span><span class='line'> <span class="n">rails</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provision</span> <span class="s2">"chef_solo"</span> <span class="k">do</span> <span class="o">|</span><span class="n">chef</span><span class="o">|</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">node_name</span> <span class="o">=</span> <span class="s2">"rails"</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="ss">:debug</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">json</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"run_list"</span> <span class="o">=></span> <span class="o">[</span><span class="s2">"rails"</span><span class="o">]</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">config</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">define</span> <span class="s2">"mysql"</span> <span class="k">do</span> <span class="o">|</span><span class="n">mysql</span><span class="o">|</span>
</span><span class='line'>
</span><span class='line'> <span class="n">mysql</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provider</span> <span class="s2">"virtualbox"</span> <span class="k">do</span> <span class="o">|</span><span class="n">v</span><span class="p">,</span> <span class="n">override</span><span class="o">|</span>
</span><span class='line'> <span class="n">v</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="s2">"mysql"</span>
</span><span class='line'> <span class="n">override</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">network</span> <span class="ss">:private_network</span><span class="p">,</span> <span class="ss">ip</span><span class="p">:</span> <span class="s2">"192.168.50.21"</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">mysql</span><span class="o">.</span><span class="n">vm</span><span class="o">.</span><span class="n">provision</span> <span class="s2">"chef_solo"</span> <span class="k">do</span> <span class="o">|</span><span class="n">chef</span><span class="o">|</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">node_name</span> <span class="o">=</span> <span class="s2">"mysql"</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">log_level</span> <span class="o">=</span> <span class="ss">:debug</span>
</span><span class='line'> <span class="n">chef</span><span class="o">.</span><span class="n">json</span> <span class="o">=</span> <span class="p">{</span>
</span><span class='line'> <span class="s2">"run_list"</span> <span class="o">=></span> <span class="o">[</span><span class="s2">"vagrant_chef::mysql"</span><span class="o">]</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Chef 介绍 Part1 Setup]]></title>
<link href="http://seanguo.github.io/blog/2017/02/17/chefjie-shao/"/>
<updated>2017-02-17T20:20:59+08:00</updated>
<id>http://seanguo.github.io/blog/2017/02/17/chefjie-shao</id>
<content type="html"><![CDATA[<h2>引言</h2>
<p>Chef是一个自动化部署的工具。它的思想是“Infrastructure as code”, 所以整个DevOps流程下来都是代码,都可以保存在代码仓库里面。像Chef之类的工具出现之前,简单部署的话就是手工来了,像Java的web应用手工部署个War包或者改个配置文件什么的,高级点的可能会写个shell脚本来自动化。但是当需要管理的机器增多或者配置项增多,或者不同的机器要求不一样的配置的话,就力不从心了。Chef出现之后,这样的难题就迎刃而解了。</p>
<p>Chef的实现是用的Ruby,所以它的配置脚本也是基于Ruby的, 所以想要学好Chef也需要了解一下Ruby的基本语法,如果想要扩展,定制,增加自己的Chef库的话,还是需要仔细学习一下Ruby才行。这导致Chef陡峭的学习曲线,了解个皮毛很容易,但是想要深入了解,诊断问题的话需要做很多功课才可以。</p>
<p>想要学好,我们先搭环境,在应用中学习是最有成效的。</p>
<h2>安装</h2>
<p>Chef安装很简单,就去下载一个叫做<a href="https://downloads.chef.io/">Chef DK</a>的包安装就可以了。这个会把Chef全家桶装好,里面开发测试用的所有工具都包含了。</p>
<p>安装完后可以运行下面的命令检查一下</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>➜ ~ chef-solo -v
</span><span class='line'>Chef: 12.17.44
</span></code></pre></td></tr></table></div></figure>
<h2>第一个程序</h2>
<p>我们可以通过下面的命令来创建我们的第一个Chef程序(它叫Cookbook)</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">chef</span> <span class="n">generate</span> <span class="n">cookbook</span> <span class="n">sample1</span>
</span></code></pre></td></tr></table></div></figure>
<p>下面是这个cookbook的目录结构:</p>
<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>.
</span><span class='line'>├── Berksfile
</span><span class='line'>├── README.md
</span><span class='line'>├── chefignore
</span><span class='line'>├── metadata.rb
</span><span class='line'>├── recipes
</span><span class='line'>│ └── default.rb
</span><span class='line'>├── spec
</span><span class='line'>│ ├── spec_helper.rb
</span><span class='line'>│ └── unit
</span><span class='line'>│ └── recipes
</span><span class='line'>│ └── default_spec.rb
</span><span class='line'>├── <span class="nb">test</span>
</span><span class='line'>│ └── smoke
</span><span class='line'>│ └── default
</span><span class='line'>│ └── default_test.rb
</span></code></pre></td></tr></table></div></figure>
<p>简单来说Chef的运行是顺序执行一个一个的Resource,Chef在Ruby语法的基础上封装了自己的DSL来把经常用到的命令,配置文件的管理等抽象成一个个的Resource。这些Resource根据需求顺序放在Chef的脚本里(它叫Recipe)就可以执行了。所以Chef的入口是Recipe,下面是一个简单的例子。</p>