-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
340 lines (185 loc) · 225 KB
/
Copy pathatom.xml
File metadata and controls
340 lines (185 loc) · 225 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>亮随笔</title>
<icon>https://www.gravatar.com/avatar/2d2b00cb24b69a8bf5ea6602caa1de06</icon>
<link href="/atom.xml" rel="self"/>
<link href="http://lu-liang.github.io/"/>
<updated>2019-03-27T08:59:27.000Z</updated>
<id>http://lu-liang.github.io/</id>
<author>
<name>Lu Liang</name>
<email>lu.ll.liang@gmail.com</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>A tour to the runtime of kubeless</title>
<link href="http://lu-liang.github.io/2019/03/25/A-tour-to-the-runtime-of-kubeless/"/>
<id>http://lu-liang.github.io/2019/03/25/A-tour-to-the-runtime-of-kubeless/</id>
<published>2019-03-25T12:18:40.000Z</published>
<updated>2019-03-27T08:59:27.000Z</updated>
<content type="html"><![CDATA[<p>kubeless is a Kubernetes-native serverless framework and it leverages Kubernetes resources to provide auto-scaling, API routing, monitoring, troubleshooting and more.</p><p>By Kubeless, we can use a Custom Resource Definition to create functions as custom kubernetes resources and then run an in-cluster controller watching these custom resources and launching runtimes on-demand.</p><p>In this article, we are focused on the implementation of runtime. Just as the showing of the below chart, Kubeless provides different runtimes for different program languages.</p><img src="/2019/03/25/A-tour-to-the-runtime-of-kubeless/kubeless_design.png" title="kubeless_design.png"><p>According to the programing language, each runtime is really a kind of web server implemented with different web server framework such as <strong>“sinatra”</strong> in ruby, <strong>“bottle”</strong> in python, <strong>“express”</strong> in nodejs and <strong>“com.sun.net.httpserver”</strong> in java. In the runtime server, it defines one handler to wrapper the created function and handles the call from http request.</p><h2 id="Scaffold-in-Runtime"><a href="#Scaffold-in-Runtime" class="headerlink" title="Scaffold in Runtime"></a>Scaffold in Runtime</h2><p>The main steps for the implementation of runtime as follows:</p><ol><li>Load defined function.</li><li>Create one web server.</li><li>Create the custom handler to add performance/statistics hook.</li><li>Wrapper the defined function with the custom handler function to serve http request.</li></ol><p>Let’s look into the details for different runtime.</p><h2 id="Python-Runtime"><a href="#Python-Runtime" class="headerlink" title="Python Runtime"></a><a href="https://github.com/kubeless/runtimes/blob/master/stable/python/kubeless.py" target="_blank" rel="noopener">Python Runtime</a></h2><p>The implementation of python runtime is relatively simple. It’s only involved in one source file “kubeless.py”.</p><p>The following is the analysis to describe the main logic and steps in this kind of runtime. </p><ol><li><p>Use python module <strong>“mod”</strong> to load functions.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">mod = imp.load_source('function',</span><br><span class="line"> '/kubeless/%s.py' % os.getenv('MOD_NAME'))</span><br><span class="line">func = getattr(mod, os.getenv('FUNC_HANDLER'))</span><br></pre></td></tr></table></figure></li><li><p>Define the wrapper function</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">def funcWrap(q, event, c):</span><br><span class="line"> try:</span><br><span class="line"> q.put(func(event, c))</span><br><span class="line"> except Exception as inst:</span><br><span class="line"> q.put(inst)</span><br></pre></td></tr></table></figure></li><li><p>Implement the runtime with python http server module <strong>“bottle”</strong></p></li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"> app = application = bottle.app()</span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line"> import logging</span><br><span class="line"> import sys</span><br><span class="line"> import requestlogger</span><br><span class="line"> loggedapp = requestlogger.WSGILogger(</span><br><span class="line"> app,</span><br><span class="line"> [logging.StreamHandler(stream=sys.stdout)],</span><br><span class="line"> requestlogger.ApacheFormatter())</span><br><span class="line"> bottle.run(loggedapp, server='cherrypy', host='0.0.0.0', port=func_port)</span><br></pre></td></tr></table></figure><ol start="4"><li>With <strong>“bottle”</strong>, implement one handler by the module <strong>“multiprocessing”</strong> to handle the call of function in sub process.<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">with func_hist.labels(method).time():</span><br><span class="line"> q = Queue()</span><br><span class="line"> p = Process(target=funcWrap, args=(q, event, function_context))</span><br><span class="line"> p.start()</span><br><span class="line"> p.join(timeout)</span><br></pre></td></tr></table></figure></li></ol><h2 id="Ruby-Runtime"><a href="#Ruby-Runtime" class="headerlink" title="Ruby Runtime"></a><a href="https://github.com/kubeless/runtimes/blob/master/stable/ruby/kubeless.rb" target="_blank" rel="noopener">Ruby Runtime</a></h2><ol><li><p>Use ruby module <strong>“mod”</strong> to load functions.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">MOD_NAME = ENV['MOD_NAME']</span><br><span class="line">FUNC_HANDLER = ENV['FUNC_HANDLER']</span><br><span class="line">MOD_ROOT_PATH = ENV.fetch('MOD_ROOT_PATH', '/kubeless/')</span><br><span class="line">MOD_PATH = "#{File.join(MOD_ROOT_PATH, MOD_NAME)}.rb"</span><br><span class="line">........</span><br><span class="line">.........</span><br><span class="line">begin</span><br><span class="line"> puts "Loading #{MOD_PATH}"</span><br><span class="line"> mod = Module.new</span><br><span class="line"> mod.module_eval(File.read(MOD_PATH))</span><br><span class="line"> # export the function handler</span><br><span class="line"> mod.module_eval("module_function :#{FUNC_HANDLER}")</span><br></pre></td></tr></table></figure></li><li><p>Define the wrapper function</p></li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">def funcWrapper(mod, t)</span><br><span class="line"> status = Timeout::timeout(t) {</span><br><span class="line"> res = mod.send(FUNC_HANDLER.to_sym, @event, @context)</span><br><span class="line"> }</span><br><span class="line">end</span><br></pre></td></tr></table></figure><ol start="3"><li>Implement the runtime with ruby framework <strong>“sinatra”</strong> and create “get, post” handler functions</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">require 'sinatra'</span><br><span class="line">......</span><br><span class="line">......</span><br><span class="line"></span><br><span class="line">get '/' do</span><br><span class="line"> begin</span><br><span class="line"> funcWrapper(mod, ftimeout)</span><br><span class="line"> rescue Timeout::Error</span><br><span class="line"> status 408</span><br><span class="line"> end</span><br><span class="line">end</span><br><span class="line"></span><br><span class="line">post '/' do</span><br><span class="line"> begin</span><br><span class="line"> funcWrapper(mod, ftimeout)</span><br><span class="line"> rescue Timeout::Error</span><br><span class="line"> status 408</span><br><span class="line"> end</span><br><span class="line">end</span><br></pre></td></tr></table></figure><h2 id="Node-JS-Runtime"><a href="#Node-JS-Runtime" class="headerlink" title="Node JS Runtime"></a><a href="https://github.com/kubeless/runtimes/blob/master/stable/nodejs/kubeless.js" target="_blank" rel="noopener">Node JS Runtime</a></h2><ol><li><p>Define module “./lib/helper”, Create web server and use <strong>“vm.Script”</strong> to load functions.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">const express = require('express');</span><br><span class="line">const helper = require('./lib/helper');</span><br><span class="line">......</span><br><span class="line">......</span><br><span class="line"></span><br><span class="line">const modPath = path.join(modRootPath, `${modName}.js`);</span><br><span class="line">const libPath = path.join(modRootPath, 'node_modules');</span><br><span class="line">const pkgPath = path.join(modRootPath, 'package.json');</span><br><span class="line">const libDeps = helper.readDependencies(pkgPath);</span><br><span class="line">.....</span><br><span class="line">.....</span><br><span class="line">const app = express();</span><br><span class="line">.....</span><br><span class="line">.....</span><br><span class="line">const script = new vm.Script('\nrequire(\'kubeless\')(require(\''+ modPath +'\'));\n', {</span><br><span class="line"> filename: modPath,</span><br><span class="line"> displayErrors: true,</span><br><span class="line">})</span><br></pre></td></tr></table></figure></li><li><p>In handler function, call <strong>“script.runInNewContext”</strong> to serve request.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">const sandbox = Object.assign({}, global, {</span><br><span class="line"> __filename: modPath,</span><br><span class="line"> __dirname: modRootPath,</span><br><span class="line"> module: new Module(modPath, null),</span><br><span class="line"> require: (p) => modRequire(p, req, res, end),</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> try {</span><br><span class="line"> script.runInNewContext(sandbox, { timeout : timeout * 1000 });</span><br><span class="line"> } catch (err) {</span><br></pre></td></tr></table></figure></li></ol><h2 id="Java-Runtime"><a href="#Java-Runtime" class="headerlink" title="Java Runtime"></a><a href="https://github.com/kubeless/runtimes/tree/master/stable/java" target="_blank" rel="noopener">Java Runtime</a></h2><ol><li><p>Define HttpServer and use <strong>“Class.forName”</strong> to load function in java/io/kubeless/Handler.java.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">try {</span><br><span class="line"> HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);</span><br><span class="line"> server.createContext("/", new FunctionHandler());</span><br><span class="line"> server.createContext("/healthz", new HealthHandler());</span><br><span class="line"> server.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(50));</span><br><span class="line"> server.start();</span><br><span class="line"></span><br><span class="line"> Class<?> c = Class.forName("io.kubeless."+className);</span><br><span class="line"> obj = c.newInstance();</span><br><span class="line"> method = c.getMethod(methodName, io.kubeless.Event.class, io.kubeless.Context.class);</span><br><span class="line"> } catch (Exception e) {</span><br></pre></td></tr></table></figure></li><li><p>Handle the http request by static class <strong>“FunctionHandler”</strong></p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">Event event = new Event(requestBody, eventId, eventType, eventTime, eventNamespace);</span><br><span class="line">Context context = new Context(methodName, timeout, runtime, memoryLimit);</span><br><span class="line"></span><br><span class="line">Object returnValue = Handler.method.invoke(Handler.obj, event, context);</span><br><span class="line">String response = (String)returnValue;</span><br><span class="line">logger.info("Response: " + response);</span><br><span class="line">he.sendResponseHeaders(200, response.length());</span><br></pre></td></tr></table></figure></li></ol><h2 id="Go-Runtime"><a href="#Go-Runtime" class="headerlink" title="Go Runtime"></a><a href="https://github.com/kubeless/runtimes/blob/master/stable/golang/kubeless.tpl.go" target="_blank" rel="noopener">Go Runtime</a></h2><ol><li><p>Modify the template to inject function name by <strong>“compile-function.sh”</strong></p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line"></span><br><span class="line">set -e</span><br><span class="line"></span><br><span class="line"># Replace FUNCTION placeholder</span><br><span class="line">sed "s/<<FUNCTION>>/${KUBELESS_FUNC_NAME}/g" $GOPATH/src/controller/kubeless.tpl.go > $GOPATH/src/controller/kubeless.go</span><br><span class="line"># Remove vendored version of kubeless if exists</span><br><span class="line">rm -rf $GOPATH/src/kubeless/vendor/github.com/kubeless/kubeless</span><br><span class="line"># Build command</span><br><span class="line">go build -o $KUBELESS_INSTALL_VOLUME/server $GOPATH/src/controller/kubeless.go > /dev/termination-log 2>&1</span><br></pre></td></tr></table></figure></li><li><p>Implement web server in ProxyUtils by <strong>“net/http”</strong></p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">func main() {</span><br><span class="line">http.HandleFunc("/", handler)</span><br><span class="line">http.HandleFunc("/healthz", health)</span><br><span class="line">http.Handle("/metrics", promhttp.Handler())</span><br><span class="line">proxyUtils.ListenAndServe()</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>Handle http request by function chain <strong>“handler” -> “ProxyUtils” -> “handle”</strong></p></li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">func handle(ctx context.Context, w http.ResponseWriter, r *http.Request) ([]byte, error) {</span><br><span class="line">data, err := ioutil.ReadAll(r.Body)</span><br><span class="line">...</span><br><span class="line"> ...</span><br><span class="line">res, err := kubeless.<<FUNCTION>>(event, funcContext)</span><br><span class="line">return []byte(res), err</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">func handler(w http.ResponseWriter, r *http.Request) {</span><br><span class="line">...</span><br><span class="line"> ...</span><br><span class="line">proxyUtils.Handler(w, r, handle)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to:"></a>Refer to:</h2><ul><li><a href="https://kubeless.io/docs" target="_blank" rel="noopener">https://kubeless.io/docs</a></li><li><a href="https://medium.com/bitnami-perspectives/12-minutes-with-kubeless-and-minikube-da389319bdeb" target="_blank" rel="noopener">https://medium.com/bitnami-perspectives/12-minutes-with-kubeless-and-minikube-da389319bdeb</a></li></ul>]]></content>
<summary type="html">
<p>kubeless is a Kubernetes-native serverless framework and it leverages Kubernetes resources to provide auto-scaling, API routing, monitori
</summary>
<category term="kubeless" scheme="http://lu-liang.github.io/tags/kubeless/"/>
<category term="k8s" scheme="http://lu-liang.github.io/tags/k8s/"/>
<category term="serverless" scheme="http://lu-liang.github.io/tags/serverless/"/>
</entry>
<entry>
<title>How to develop a beat</title>
<link href="http://lu-liang.github.io/2018/12/18/exploit-beat/"/>
<id>http://lu-liang.github.io/2018/12/18/exploit-beat/</id>
<published>2018-12-18T07:04:20.000Z</published>
<updated>2018-12-18T13:17:48.000Z</updated>
<content type="html"><![CDATA[<p>ELK(Elasticsearch, Logstash, Kibana)几乎已经成为cloud上面标准的日志收集及展示解决方案。这里我们探讨一下ELK中的日志收集组件beat的原理,以及如何实现一个定制的beat。</p><h2 id="beat在ELK中的位置"><a href="#beat在ELK中的位置" class="headerlink" title="beat在ELK中的位置"></a>beat在ELK中的位置</h2><p>如下图所示:beat在ELK中用于收集各种数据并且输入到其它component中。<br><img src="/2018/12/18/exploit-beat/ELK.png" title="ELK.png"></p><h2 id="beat组件原理及接口介绍"><a href="#beat组件原理及接口介绍" class="headerlink" title="beat组件原理及接口介绍"></a>beat组件原理及接口介绍</h2><p>beat是以GO开发的一个可执行程序,主要以下有两个部分组成。</p><ul><li>data collect component 收集实际的信息数据.</li><li>publisher 将收集的信息数据通过事件机制发布到elasticsearch。<img src="/2018/12/18/exploit-beat/beat_logic.png" title="beat_logic.png">事件通常通过一个JSON-like object(GO 中的 <strong>map[string] interface{}</strong>)去封装实际收集的信息数据。 publisher 已经被Libbeat实现了,Libbeat 也提供了其它通用的功能例如,配置管理,日志管理等。</li></ul><p>每个自定义的beat需要实现Beater接口, 该接口在libbeat中定义。如下所示,当beat启动后,Run()会一直运行,直到接收到退出信号,调用Stop()退出。<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">type Beater interface {</span><br><span class="line"> // The main event loop. This method should block until signalled to stop by an</span><br><span class="line"> // invocation of the Stop() method.</span><br><span class="line"> Run(b *Beat) error</span><br><span class="line"></span><br><span class="line"> // Stop is invoked to signal that the Run method should finish its execution.</span><br><span class="line"> // It will be invoked at most once.</span><br><span class="line"> Stop()</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>以下代码是本例中custombeat的具体实现。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">package beater</span><br><span class="line"></span><br><span class="line">//import relevant packages of libbeat, so we do not need to worry about configuration, logging etc.</span><br><span class="line"></span><br><span class="line">import (</span><br><span class="line">"fmt"</span><br><span class="line">"time"</span><br><span class="line"></span><br><span class="line">"github.com/elastic/beats/libbeat/beat"</span><br><span class="line">"github.com/elastic/beats/libbeat/common"</span><br><span class="line">"github.com/elastic/beats/libbeat/logp"</span><br><span class="line"></span><br><span class="line">"github.com/luliang/custombeat/config"</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">// Custombeat configuration.</span><br><span class="line">// define the struct for custom beat</span><br><span class="line">// In this struct,</span><br><span class="line">// use pre-imported config.Config and beat.client.</span><br><span class="line">// use channel to receive exit signal. </span><br><span class="line"></span><br><span class="line">type Custombeat struct {</span><br><span class="line">done chan struct{}</span><br><span class="line">config config.Config</span><br><span class="line">client beat.Client</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// New creates an instance of custombeat.</span><br><span class="line">func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) {</span><br><span class="line">c := config.DefaultConfig</span><br><span class="line">if err := cfg.Unpack(&c); err != nil {</span><br><span class="line">return nil, fmt.Errorf("Error reading config file: %v", err)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">bt := &Custombeat{</span><br><span class="line">done: make(chan struct{}),</span><br><span class="line">config: c,</span><br><span class="line">}</span><br><span class="line">return bt, nil</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// Run starts custombeat.</span><br><span class="line">func (bt *Custombeat) Run(b *beat.Beat) error {</span><br><span class="line">logp.Info("custombeat is running! Hit CTRL-C to stop it.")</span><br><span class="line"></span><br><span class="line">var err error</span><br><span class="line"> // use beat.client to connect and publish data.</span><br><span class="line">bt.client, err = b.Publisher.Connect()</span><br><span class="line">if err != nil {</span><br><span class="line">return err</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> // get the time interval from config by using config.Config</span><br><span class="line">ticker := time.NewTicker(bt.config.Period)</span><br><span class="line">counter := 1</span><br><span class="line">for {</span><br><span class="line">select {</span><br><span class="line">case <-bt.done:</span><br><span class="line">return nil</span><br><span class="line">case <-ticker.C:</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> // generate event data</span><br><span class="line">event := beat.Event{</span><br><span class="line">Timestamp: time.Now(),</span><br><span class="line">Fields: common.MapStr{</span><br><span class="line">"type": b.Info.Name,</span><br><span class="line">"counter": counter,</span><br><span class="line">},</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"> // publish event data</span><br><span class="line">bt.client.Publish(event)</span><br><span class="line">logp.Info("Event sent")</span><br><span class="line">counter++</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// Stop stops custombeat.</span><br><span class="line">func (bt *Custombeat) Stop() {</span><br><span class="line">bt.client.Close()</span><br><span class="line">close(bt.done)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="开发自定义beat"><a href="#开发自定义beat" class="headerlink" title="开发自定义beat"></a>开发自定义beat</h2><ol><li><p>Install <strong>python2.7</strong>, <strong>go</strong> and configure <strong>GOPATH</strong></p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ github.com python --version</span><br><span class="line">Python 2.7.11</span><br><span class="line"></span><br><span class="line">➜ github.com go version</span><br><span class="line">go version go1.11 darwin/amd64</span><br><span class="line"></span><br><span class="line">➜ github.com echo $GOPATH</span><br><span class="line">/Users/luliang/git/gobeat</span><br></pre></td></tr></table></figure></li><li><p>Clone <strong>beats</strong> project</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">git clone https://github.com/elastic/beats ${GOPATH}/src/github.com/elastic/beats</span><br></pre></td></tr></table></figure></li><li><p>Generate custom beat with generator <strong>generate.py</strong></p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">python $GOPATH/src/github.com/elastic/beats/script/generate.py</span><br><span class="line"></span><br><span class="line">➜ github.com python $GOPATH/src/github.com/elastic/beats/script/generate.py</span><br><span class="line">Beat Name [Examplebeat]: CustomBeat</span><br><span class="line">Your Github Name [your-github-name]: luliang</span><br><span class="line">Beat Path [github.com/luliang/custombeat]:</span><br><span class="line">Firstname Lastname: Liang Lu</span><br><span class="line"></span><br><span class="line">➜ github.com ls</span><br><span class="line">elastic luliang</span><br><span class="line"></span><br><span class="line">➜ github.com cd luliang</span><br><span class="line">➜ luliang ls</span><br><span class="line">**custombeat**</span><br></pre></td></tr></table></figure></li><li><p>Call “make setup” and “make” to build the custombeat</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ luliang cd custombeat</span><br><span class="line">➜ custombeat make setup</span><br><span class="line"></span><br><span class="line">➜ beater pwd</span><br><span class="line">/Users/luliang/git/gobeat/src/github.com/luliang/custombeat/beater</span><br><span class="line">➜ beater ls</span><br><span class="line">custombeat.go</span><br><span class="line"></span><br><span class="line">➜ custombeat make</span><br></pre></td></tr></table></figure></li></ol><p>如下图所示,customebeat.go 实现了beat接口, 我们需要在这里定义实现自己的逻辑。<br><img src="/2018/12/18/exploit-beat/beat_implementation.png" title="beat_implementation.png"></p><ol start="5"><li>Run and test the custombeat<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$GOPATH/src/github.com/luliang/custombeat -e -d "*"</span><br></pre></td></tr></table></figure></li></ol><h2 id="常见beats如下:"><a href="#常见beats如下:" class="headerlink" title="常见beats如下:"></a>常见beats如下:</h2><table><thead><tr><th>数据类型</th><th>Beat类型</th></tr></thead><tbody><tr><td>Audit data</td><td>Auditbeat<a href="https://www.elastic.co/products/beats/auditbeat" target="_blank" rel="noopener">Auditbeat</a></td></tr><tr><td>Log files</td><td>Filebeat<a href="https://www.elastic.co/products/beats/filebeat" target="_blank" rel="noopener">Filebeat</a></td></tr><tr><td>Cloud data</td><td>Functionbeat<a href="https://www.elastic.co/products/beats/functionbeat" target="_blank" rel="noopener">Functionbeat</a></td></tr><tr><td>Availability</td><td>Heartbeat<a href="https://www.elastic.co/products/beats/heartbeat" target="_blank" rel="noopener">Heartbeat</a></td></tr><tr><td>Systemd journals</td><td>Journalbeat<a href="https://www.elastic.co/downloads/beats/journalbeat" target="_blank" rel="noopener">Journalbeat</a></td></tr><tr><td>Metrics</td><td>Metricbeat<a href="https://www.elastic.co/products/beats/metricbeat" target="_blank" rel="noopener">Metricbeat</a></td></tr><tr><td>Network traffic</td><td>Packetbeat<a href="https://www.elastic.co/products/beats/packetbeat" target="_blank" rel="noopener">Packetbeat</a></td></tr><tr><td>Windows event logs</td><td>Winlogbeat<a href="https://www.elastic.co/products/beats/winlogbeat" target="_blank" rel="noopener">Winlogbeat</a></td></tr></tbody></table>]]></content>
<summary type="html">
<p>ELK(Elasticsearch, Logstash, Kibana)几乎已经成为cloud上面标准的日志收集及展示解决方案。这里我们探讨一下ELK中的日志收集组件beat的原理,以及如何实现一个定制的beat。</p>
<h2 id="beat在ELK中的位置"><a
</summary>
<category term="go" scheme="http://lu-liang.github.io/tags/go/"/>
<category term="ELK" scheme="http://lu-liang.github.io/tags/ELK/"/>
<category term="cloud" scheme="http://lu-liang.github.io/tags/cloud/"/>
</entry>
<entry>
<title>Delve, a better go debugger</title>
<link href="http://lu-liang.github.io/2018/11/22/Go-Debugger-Delve/"/>
<id>http://lu-liang.github.io/2018/11/22/Go-Debugger-Delve/</id>
<published>2018-11-22T07:52:38.000Z</published>
<updated>2018-11-22T09:31:16.000Z</updated>
<content type="html"><![CDATA[<p>Delve is a debugger for the Go programming language. We can debug and explore go program with it easily.</p><h2 id="Installation"><a href="#Installation" class="headerlink" title="Installation"></a>Installation</h2><p>Delve can be installed by “go get”. After the installation, you can find it under $HOME/go. All we need to do is to add the folder “$HOME/go/bin” to $PATH.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">go get -u github.com/derekparker/delve/cmd/dlv</span><br><span class="line">export PATH=$PATH:$HOME/go/bin</span><br></pre></td></tr></table></figure><h2 id="Usage"><a href="#Usage" class="headerlink" title="Usage"></a>Usage</h2><p>The following are 3 ways to debug go program with dlv.</p><ul><li><p>dlv command.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">dlv attach Attach to running process and begin debugging.</span><br><span class="line">dlv connect Connect to a headless debug server.</span><br><span class="line">dlv core Examine a core dump.</span><br><span class="line">dlv debug Compile and begin debugging main package in current directory, or the package specified.</span><br><span class="line">dlv exec Execute a precompiled binary, and begin a debug session.</span><br><span class="line">dlv help Help about any command</span><br><span class="line">dlv run Deprecated command. Use 'debug' instead.</span><br><span class="line">dlv test Compile test binary and begin debugging program.</span><br><span class="line">dlv trace Compile and begin tracing program.</span><br><span class="line">dlv version Prints version</span><br></pre></td></tr></table></figure></li><li><p>dlv api</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># start dlv with --headless at remote and use dlv ui to connect in local.</span><br><span class="line">dlv attach 18707 --headless --api-version=2 --log --listen=9.xx.xx.65:8181</span><br><span class="line"></span><br><span class="line"># start gdlv to connect the remote debug.</span><br><span class="line">➜ gdlv connect 9.xx.xx.65:8181</span><br></pre></td></tr></table></figure></li><li><p>dlv ui<br>There are a lot of editor plugins for dlv ui. You can install them based on this instruction <a href="https://github.com/derekparker/delve/blob/master/Documentation/EditorIntegration.md" target="_blank" rel="noopener">https://github.com/derekparker/delve/blob/master/Documentation/EditorIntegration.md</a>. Here, we take gdlv as example to do introduction. </p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"> # install gdlv with "go get"</span><br><span class="line"> go get -u github.com/aarzilli/gdlv</span><br><span class="line"></span><br><span class="line"> # gdlv usage.</span><br><span class="line"> gdlv connect <address></span><br><span class="line">gdlv debug <program's arguments...></span><br><span class="line">gdlv run <program file> <program's arguments...></span><br><span class="line">gdlv exec <executable> <program's arguments...></span><br><span class="line">gdlv test <testflags...></span><br><span class="line">gdlv attach <pid> [path to executable]</span><br><span class="line">gdlv core <executable> <core file></span><br><span class="line">gdlv reply <trace directory></span><br></pre></td></tr></table></figure></li></ul><img src="/2018/11/22/Go-Debugger-Delve/gdlv.png" title="gdlv"><h2 id="Example"><a href="#Example" class="headerlink" title="Example."></a>Example.</h2><p>The following are some samples to show dlv with the hello_world.</p><h3 id="the-source-code-of-hellow-world"><a href="#the-source-code-of-hellow-world" class="headerlink" title="the source code of hellow_world"></a>the source code of hellow_world</h3><p>To avoid the program exit immediately, we add some sleep time before print the “hello world”.<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">package main</span><br><span class="line"></span><br><span class="line">import (</span><br><span class="line">"fmt"</span><br><span class="line">"time"</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">func main() {</span><br><span class="line">time.Sleep(time.Duration(60)*time.Second)</span><br><span class="line"> fmt.Printf("hello, world\n")</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h3 id="attach-the-program"><a href="#attach-the-program" class="headerlink" title="attach the program"></a>attach the program</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ bin ps -ef|grep hello</span><br><span class="line">root 18192 18133 0 11月21 pts/2 00:00:00 ./hello_world</span><br><span class="line"></span><br><span class="line">➜ bin ./dlv attach 18192</span><br><span class="line">Type 'help' for list of commands.</span><br><span class="line">(dlv)</span><br></pre></td></tr></table></figure><h3 id="show-available-commands"><a href="#show-available-commands" class="headerlink" title="show available commands"></a>show available commands</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">(dlv) help</span><br><span class="line">The following commands are available:</span><br><span class="line"> args ------------------------ Print function arguments.</span><br><span class="line"> break (alias: b) ------------ Sets a breakpoint.</span><br><span class="line"> breakpoints (alias: bp) ----- Print out info for active breakpoints.</span><br><span class="line"> call ------------------------ Resumes process, injecting a function call (EXPERIMENTAL!!!)</span><br><span class="line"> clear ----------------------- Deletes breakpoint.</span><br><span class="line"> clearall -------------------- Deletes multiple breakpoints.</span><br><span class="line"> condition (alias: cond) ----- Set breakpoint condition.</span><br><span class="line"> config ---------------------- Changes configuration parameters.</span><br><span class="line"> continue (alias: c) --------- Run until breakpoint or program termination.</span><br><span class="line"> deferred -------------------- Executes command in the context of a deferred call.</span><br><span class="line"> disassemble (alias: disass) - Disassembler.</span><br><span class="line"> down ------------------------ Move the current frame down.</span><br><span class="line"> edit (alias: ed) ------------ Open where you are in $DELVE_EDITOR or $EDITOR</span><br><span class="line"> exit (alias: quit | q) ------ Exit the debugger.</span><br><span class="line"> frame ----------------------- Set the current frame, or execute command on a different frame.</span><br><span class="line"> funcs ----------------------- Print list of functions.</span><br><span class="line"> goroutine ------------------- Shows or changes current goroutine</span><br><span class="line"> goroutines ------------------ List program goroutines.</span><br><span class="line"> help (alias: h) ------------- Prints the help message.</span><br><span class="line"> list (alias: ls | l) -------- Show source code.</span><br><span class="line"> locals ---------------------- Print local variables.</span><br><span class="line"> next (alias: n) ------------- Step over to next source line.</span><br><span class="line"> on -------------------------- Executes a command when a breakpoint is hit.</span><br><span class="line"> print (alias: p) ------------ Evaluate an expression.</span><br><span class="line"> regs ------------------------ Print contents of CPU registers.</span><br><span class="line"> restart (alias: r) ---------- Restart process.</span><br><span class="line"> set ------------------------- Changes the value of a variable.</span><br><span class="line"> source ---------------------- Executes a file containing a list of delve commands</span><br><span class="line"> sources --------------------- Print list of source files.</span><br><span class="line"> stack (alias: bt) ----------- Print stack trace.</span><br><span class="line"> step (alias: s) ------------- Single step through program.</span><br><span class="line"> step-instruction (alias: si) Single step a single cpu instruction.</span><br><span class="line"> stepout --------------------- Step out of the current function.</span><br><span class="line"> thread (alias: tr) ---------- Switch to the specified thread.</span><br><span class="line"> threads --------------------- Print out info for every traced thread.</span><br><span class="line"> trace (alias: t) ------------ Set tracepoint.</span><br><span class="line"> types ----------------------- Print list of types</span><br><span class="line"> up -------------------------- Move the current frame up.</span><br><span class="line"> vars ------------------------ Print package variables.</span><br><span class="line"> whatis ---------------------- Prints type of an expression.</span><br><span class="line">Type help followed by a command for full documentation.</span><br></pre></td></tr></table></figure><h3 id="show-all-goroutines"><a href="#show-all-goroutines" class="headerlink" title="show all goroutines"></a>show all goroutines</h3><p>The running goroutine is 19.<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">(dlv) goroutines</span><br><span class="line">[5 goroutines]</span><br><span class="line"> Goroutine 1 - User: /usr/lib/golang/src/runtime/time.go:65 time.Sleep (0x4429e0)</span><br><span class="line"> Goroutine 2 - User: /usr/lib/golang/src/runtime/proc.go:288 runtime.gopark (0x428eac)</span><br><span class="line"> Goroutine 17 - User: /usr/lib/golang/src/runtime/proc.go:288 runtime.gopark (0x428eac)</span><br><span class="line"> Goroutine 18 - User: /usr/lib/golang/src/runtime/proc.go:288 runtime.gopark (0x428eac)</span><br><span class="line">* Goroutine 19 - User: /usr/lib/golang/src/runtime/lock_futex.go:227 runtime.notetsleepg (0x40d582)</span><br></pre></td></tr></table></figure></p><h3 id="show-stack-for-specified-goroutine"><a href="#show-stack-for-specified-goroutine" class="headerlink" title="show stack for specified goroutine"></a>show stack for specified goroutine</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">(dlv) goroutine 1 stack</span><br><span class="line">0 0x0000000000428eac in runtime.gopark</span><br><span class="line"> at /usr/lib/golang/src/runtime/proc.go:288</span><br><span class="line">1 0x0000000000428f9e in runtime.goparkunlock</span><br><span class="line"> at /usr/lib/golang/src/runtime/proc.go:293</span><br><span class="line">2 0x00000000004429e0 in time.Sleep</span><br><span class="line"> at /usr/lib/golang/src/runtime/time.go:65</span><br><span class="line">3 0x0000000000489bf0 in main.main</span><br><span class="line"> at /root/tmp/go/hello_world.go:9</span><br><span class="line">4 0x0000000000428a06 in runtime.main</span><br><span class="line"> at /usr/lib/golang/src/runtime/proc.go:195</span><br><span class="line">5 0x0000000000451721 in runtime.goexit</span><br><span class="line"> at /usr/lib/golang/src/runtime/asm_amd64.s:2337</span><br><span class="line"></span><br><span class="line">(dlv) goroutine 2 stack</span><br><span class="line">0 0x0000000000428eac in runtime.gopark</span><br><span class="line"> at /usr/lib/golang/src/runtime/proc.go:288</span><br><span class="line">1 0x0000000000428f9e in runtime.goparkunlock</span><br><span class="line"> at /usr/lib/golang/src/runtime/proc.go:293</span><br><span class="line">2 0x0000000000428ccc in runtime.forcegchelper</span><br><span class="line"> at /usr/lib/golang/src/runtime/proc.go:245</span><br><span class="line">3 0x0000000000451721 in runtime.goexit</span><br><span class="line"> at /usr/lib/golang/src/runtime/asm_amd64.s:2337</span><br><span class="line"></span><br><span class="line">(dlv) goroutine 19 stack</span><br><span class="line">0 0x000000000040d582 in runtime.notetsleepg</span><br><span class="line"> at /usr/lib/golang/src/runtime/lock_futex.go:227</span><br><span class="line">1 0x00000000004431f5 in runtime.timerproc</span><br><span class="line"> at /usr/lib/golang/src/runtime/time.go:216</span><br><span class="line">2 0x0000000000451721 in runtime.goexit</span><br><span class="line"> at /usr/lib/golang/src/runtime/asm_amd64.s:2337</span><br></pre></td></tr></table></figure><h3 id="show-threads"><a href="#show-threads" class="headerlink" title="show threads"></a>show threads</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">(dlv) threads</span><br><span class="line">* Thread 18192 at 0x452bd3 /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 runtime.futex</span><br><span class="line"> Thread 18193 at 0x452bd3 /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 runtime.futex</span><br><span class="line"> Thread 18194 at 0x452bd3 /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 runtime.futex</span><br><span class="line"> Thread 18195 at 0x452bd3 /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 runtime.futex</span><br><span class="line"> Thread 18196 at 0x452bd3 /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 runtime.futex</span><br></pre></td></tr></table></figure><h3 id="list-relevant-source-code"><a href="#list-relevant-source-code" class="headerlink" title="list relevant source code"></a>list relevant source code</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">(dlv) l</span><br><span class="line">> runtime.futex() /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 (PC: 0x452bd3)</span><br><span class="line"> 475:MOVQts+16(FP), R10</span><br><span class="line"> 476:MOVQaddr2+24(FP), R8</span><br><span class="line"> 477:MOVLval3+32(FP), R9</span><br><span class="line"> 478:MOVL$202, AX</span><br><span class="line"> 479:SYSCALL</span><br><span class="line">=> 480:MOVLAX, ret+40(FP)</span><br><span class="line"> 481:RET</span><br><span class="line"> 482:</span><br><span class="line"> 483:// int32 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));</span><br><span class="line"> 484:TEXT runtime·clone(SB),NOSPLIT,$0</span><br><span class="line"> 485:MOVLflags+0(FP), DI</span><br><span class="line">(dlv)</span><br></pre></td></tr></table></figure><h3 id="use-up-down-to-go-through-the-current-frame"><a href="#use-up-down-to-go-through-the-current-frame" class="headerlink" title="use up/down to go through the current frame."></a>use up/down to go through the current frame.</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">(dlv) down</span><br><span class="line">> runtime.futex() /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 (PC: 0x452bd3)</span><br><span class="line">Frame 4: /usr/lib/golang/src/runtime/time.go:216 (PC: 4431f5)</span><br><span class="line"> 211:// At least one timer pending. Sleep until then.</span><br><span class="line"> 212:timers.sleeping = true</span><br><span class="line"> 213:timers.sleepUntil = now + delta</span><br><span class="line"> 214:noteclear(&timers.waitnote)</span><br><span class="line"> 215:unlock(&timers.lock)</span><br><span class="line">=> 216:notetsleepg(&timers.waitnote, delta)</span><br><span class="line"> 217:}</span><br><span class="line"> 218:}</span><br><span class="line"> 219:</span><br><span class="line"> 220:func timejump() *g {</span><br><span class="line"> 221:if faketime == 0 {</span><br><span class="line">(dlv) up</span><br><span class="line">> runtime.futex() /usr/lib/golang/src/runtime/sys_linux_amd64.s:480 (PC: 0x452bd3)</span><br><span class="line">Frame 5: /usr/lib/golang/src/runtime/asm_amd64.s:2337 (PC: 451721)</span><br><span class="line"> 2332:RET</span><br><span class="line"> 2333:</span><br><span class="line"> 2334:// The top-most function running on a goroutine</span><br><span class="line"> 2335:// returns to goexit+PCQuantum.</span><br><span class="line"> 2336:TEXT runtime·goexit(SB),NOSPLIT,$0-0</span><br><span class="line">=>2337:BYTE$0x90// NOP</span><br><span class="line"> 2338:CALLruntime·goexit1(SB)// does not return</span><br><span class="line"> 2339:// traceback from goexit1 must hit code range of goexit</span><br><span class="line"> 2340:BYTE$0x90// NOP</span><br><span class="line"> 2341:</span><br><span class="line"> 2342:TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8</span><br><span class="line">(dlv)</span><br></pre></td></tr></table></figure><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to:"></a>Refer to:</h2><ul><li><a href="https://github.com/derekparker/delve/blob/master/Documentation/installation/linux/install.md" target="_blank" rel="noopener">https://github.com/derekparker/delve/blob/master/Documentation/installation/linux/install.md</a></li><li><a href="https://github.com/derekparker/delve/tree/master/Documentation/usage" target="_blank" rel="noopener">https://github.com/derekparker/delve/tree/master/Documentation/usage</a></li></ul>]]></content>
<summary type="html">
<p>Delve is a debugger for the Go programming language. We can debug and explore go program with it easily.</p>
<h2 id="Installation"><a hre
</summary>
<category term="go" scheme="http://lu-liang.github.io/tags/go/"/>
<category term="delve" scheme="http://lu-liang.github.io/tags/delve/"/>
</entry>
<entry>
<title>Explore go runtime engine</title>
<link href="http://lu-liang.github.io/2018/11/17/Explore-go-runtime-engine/"/>
<id>http://lu-liang.github.io/2018/11/17/Explore-go-runtime-engine/</id>
<published>2018-11-17T12:38:15.000Z</published>
<updated>2018-11-27T09:04:37.000Z</updated>
<content type="html"><![CDATA[<p>Go runtime engine是Go语言中非常有意思的部分。下面我们通过go的hello_world来初步分析,探索一下它的启动顺序及调用函数和源程序文件。</p><h2 id="hello-world-source-code"><a href="#hello-world-source-code" class="headerlink" title="hello_world source code."></a>hello_world source code.</h2><p>This is the source code of hello_world. The change is that we add 1 minute sleep time before printing “hello world”.<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ more hello_world.go</span><br><span class="line">package main</span><br><span class="line"></span><br><span class="line">import (</span><br><span class="line">"fmt"</span><br><span class="line">"time"</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">func main() {</span><br><span class="line">time.Sleep(time.Duration(60)*time.Second)</span><br><span class="line"> fmt.Printf("hello, world\n")</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h2 id="entry-point-of-hello-world"><a href="#entry-point-of-hello-world" class="headerlink" title="entry point of hello_world."></a>entry point of hello_world.</h2><p>Since we compile this program in linux platform. The binary execution of hello_world is ELF format. We can get the entry point with readelf command. The following output shows the entry point is <strong>“0x452590”</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ file ./hello_world</span><br><span class="line">./hello_world: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped</span><br><span class="line"></span><br><span class="line">➜ readelf -h ./hello_world</span><br><span class="line">ELF 头:</span><br><span class="line"> Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00</span><br><span class="line"> 类别: ELF64</span><br><span class="line"> 数据: 2 补码,小端序 (little endian)</span><br><span class="line"> 版本: 1 (current)</span><br><span class="line"> OS/ABI: UNIX - System V</span><br><span class="line"> ABI 版本: 0</span><br><span class="line"> 类型: EXEC (可执行文件)</span><br><span class="line"> 系统架构: Advanced Micro Devices X86-64</span><br><span class="line"> 版本: 0x1</span><br><span class="line"> 入口点地址: 0x452590</span><br><span class="line"> 程序头起点: 64 (bytes into file)</span><br><span class="line"> Start of section headers: 456 (bytes into file)</span><br><span class="line"> 标志: 0x0</span><br><span class="line"> 本头的大小: 64 (字节)</span><br><span class="line"> 程序头大小: 56 (字节)</span><br><span class="line"> Number of program headers: 7</span><br><span class="line"> 节头大小: 64 (字节)</span><br><span class="line"> 节头数量: 23</span><br><span class="line"> 字符串表索引节头: 3</span><br></pre></td></tr></table></figure></p><h2 id="decompile-the-binary-to-asm-to-find-the-sequence-of-execution"><a href="#decompile-the-binary-to-asm-to-find-the-sequence-of-execution" class="headerlink" title="decompile the binary to asm to find the sequence of execution."></a>decompile the binary to asm to find the sequence of execution.</h2><p>At the entry point, we find that the first called function is ‘_rt0_amd64_linux’.<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ readelf -s ./hello_world|grep 452590</span><br><span class="line"> 2185: 0000000000452590 18 FUNC GLOBAL DEFAULT 1 _rt0_amd64_linux</span><br></pre></td></tr></table></figure></p><p>Let’s continue to decompile the binary file with objdump from the entry point. We will find it will call <strong>main</strong> function at <strong>0x4525b0</strong>. The main function will call <strong>runtime.rt0_go</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ objdump -d --start-address=0x452590 ./hello_world |more</span><br><span class="line"></span><br><span class="line">./hello_world: 文件格式 elf64-x86-64</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Disassembly of section .text:</span><br><span class="line"></span><br><span class="line">0000000000452590 <_rt0_amd64_linux>:</span><br><span class="line"> 452590:48 8d 74 24 08 lea 0x8(%rsp),%rsi</span><br><span class="line"> 452595:48 8b 3c 24 mov (%rsp),%rdi</span><br><span class="line"> 452599:48 8d 05 10 00 00 00 lea 0x10(%rip),%rax # 4525b0 <main></span><br><span class="line"> 4525a0:ff e0 jmpq *%rax</span><br><span class="line"> 4525a2:cc int3</span><br><span class="line"> 4525a3:cc int3</span><br><span class="line"> 4525a4:cc int3</span><br><span class="line"> 4525a5:cc int3</span><br><span class="line"> 4525a6:cc int3</span><br><span class="line"> 4525a7:cc int3</span><br><span class="line"> 4525a8:cc int3</span><br><span class="line"> 4525a9:cc int3</span><br><span class="line"> 4525aa:cc int3</span><br><span class="line"> 4525ab:cc int3</span><br><span class="line"> 4525ac:cc int3</span><br><span class="line"> 4525ad:cc int3</span><br><span class="line"> 4525ae:cc int3</span><br><span class="line"> 4525af:cc int3</span><br><span class="line"></span><br><span class="line">00000000004525b0 <main>:</span><br><span class="line"> 4525b0:48 8d 05 c9 c7 ff ff lea -0x3837(%rip),%rax # 44ed80 <runtime.rt0_go></span><br><span class="line"> 4525b7:ff e0 jmpq *%rax</span><br><span class="line"> 4525b9:cc int3</span><br><span class="line"> 4525ba:cc int3</span><br><span class="line"> 4525bb:cc int3</span><br><span class="line"> 4525bc:cc int3</span><br><span class="line"> 4525bd:cc int3</span><br><span class="line"> 4525be:cc int3</span><br><span class="line"> 4525bf:cc int3</span><br></pre></td></tr></table></figure></p><p>Let’s go to 44ed80 to figure out what it did in runtime.rt0_go. By looking into the asm code, we know that it did some runtime checks with hardware and then call the following functions.</p><ul><li>runtime.args (runtime/runtime1.go) –> 将argc,argv设置到static全局变量</li><li>runtime.osinit (runtime/os_linux.go) –> 设置runtime.ncpu</li><li>runtime.schedinit (runtime/proc.go) –> 内存管理初始化,根据GOMAXPROCS设置使用的procs等等</li><li>runtime.newproc (runtime/proc.go) –> 新开个goroutine把runtime.main放到就绪线程队列里面</li><li>runtime.mstart (runtime/proc.go) –> 调用到调度函数schedule执行就绪线程队列中的main协程</li></ul><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ objdump -d --start-address=0x44ed80 ./hello_world |more</span><br><span class="line"></span><br><span class="line">./hello_world: 文件格式 elf64-x86-64</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Disassembly of section .text:</span><br><span class="line"></span><br><span class="line">000000000044ed80 <runtime.rt0_go>:</span><br><span class="line"> 44ed80:48 89 f8 mov %rdi,%rax</span><br><span class="line"> 44ed83:48 89 f3 mov %rsi,%rbx</span><br><span class="line"> 44ed86:48 83 ec 27 sub $0x27,%rsp</span><br><span class="line"> 44ed8a:48 83 e4 f0 and $0xfffffffffffffff0,%rsp</span><br><span class="line"> 44ed8e:48 89 44 24 10 mov %rax,0x10(%rsp)</span><br><span class="line"> 44ed93:48 89 5c 24 18 mov %rbx,0x18(%rsp)</span><br><span class="line"> 44ed98:48 8d 3d c1 fc 0d 00 lea 0xdfcc1(%rip),%rdi # 52ea60 <runtime.g0></span><br><span class="line"> 44ed9f:48 8d 9c 24 68 00 ff lea -0xff98(%rsp),%rbx</span><br><span class="line"> 44eda6:ff</span><br><span class="line"> 44eda7:48 89 5f 10 mov %rbx,0x10(%rdi)</span><br><span class="line"> 44edab:48 89 5f 18 mov %rbx,0x18(%rdi)</span><br><span class="line"> 44edaf:48 89 1f mov %rbx,(%rdi)</span><br><span class="line"> 44edb2:48 89 67 08 mov %rsp,0x8(%rdi)</span><br><span class="line"> 44edb6:31 c0 xor %eax,%eax</span><br><span class="line"> 44edb8:0f a2 cpuid</span><br><span class="line"> 44edba:89 c6 mov %eax,%esi</span><br><span class="line"> 44edbc:83 f8 00 cmp $0x0,%eax</span><br><span class="line"> 44edbf:0f 84 01 01 00 00 je 44eec6 <runtime.rt0_go+0x146></span><br><span class="line"> 44edc5:81 fb 47 65 6e 75 cmp $0x756e6547,%ebx</span><br><span class="line"> 44edcb:75 1e jne 44edeb <runtime.rt0_go+0x6b></span><br><span class="line"> 44edcd:81 fa 69 6e 65 49 cmp $0x49656e69,%edx</span><br><span class="line"> 44edd3:75 16 jne 44edeb <runtime.rt0_go+0x6b></span><br><span class="line"> 44edd5:81 f9 6e 74 65 6c cmp $0x6c65746e,%ecx</span><br><span class="line"> 44eddb:75 0e jne 44edeb <runtime.rt0_go+0x6b></span><br><span class="line"> 44eddd:c6 05 6e da 0f 00 01 movb $0x1,0xfda6e(%rip) # 54c852 <runtime.isIntel></span><br><span class="line"> 44ede4:c6 05 6b da 0f 00 01 movb $0x1,0xfda6b(%rip) # 54c856 <runtime.lfenceBeforeRdtsc></span><br><span class="line"> 44edeb:b8 01 00 00 00 mov $0x1,%eax</span><br><span class="line"> 44edf0:0f a2 cpuid</span><br><span class="line"> 44edf2:89 05 b4 da 0f 00 mov %eax,0xfdab4(%rip) # 54c8ac <runtime.processorVersionInfo></span><br><span class="line"> 44edf8:f7 c2 00 00 00 04 test $0x4000000,%edx</span><br><span class="line"> 44edfe:0f 95 05 5c da 0f 00 setne 0xfda5c(%rip) # 54c861 <runtime.support_sse2></span><br><span class="line"> 44ee05:f7 c1 00 02 00 00 test $0x200,%ecx</span><br><span class="line"> 44ee0b:0f 95 05 52 da 0f 00 setne 0xfda52(%rip) # 54c864 <runtime.support_ssse3></span><br><span class="line"> 44ee12:f7 c1 00 00 08 00 test $0x80000,%ecx</span><br><span class="line"> 44ee18:0f 95 05 43 da 0f 00 setne 0xfda43(%rip) # 54c862 <runtime.support_sse41></span><br><span class="line"> 44ee1f:f7 c1 00 00 10 00 test $0x100000,%ecx</span><br><span class="line"> 44ee25:0f 95 05 37 da 0f 00 setne 0xfda37(%rip) # 54c863 <runtime.support_sse42></span><br><span class="line"> 44ee2c:f7 c1 00 00 80 00 test $0x800000,%ecx</span><br><span class="line"> 44ee32:0f 95 05 27 da 0f 00 setne 0xfda27(%rip) # 54c860 <runtime.support_popcnt></span><br><span class="line"> 44ee39:f7 c1 00 00 00 02 test $0x2000000,%ecx</span><br><span class="line"> 44ee3f:0f 95 05 13 da 0f 00 setne 0xfda13(%rip) # 54c859 <runtime.support_aes></span><br><span class="line"> 44ee46:f7 c1 00 00 00 08 test $0x8000000,%ecx</span><br><span class="line"> 44ee4c:0f 95 05 0c da 0f 00 setne 0xfda0c(%rip) # 54c85f <runtime.support_osxsave></span><br><span class="line"> 44ee53:f7 c1 00 00 00 10 test $0x10000000,%ecx</span><br><span class="line"> 44ee59:0f 95 05 fa d9 0f 00 setne 0xfd9fa(%rip) # 54c85a <runtime.support_avx></span><br><span class="line"> 44ee60:83 fe 07 cmp $0x7,%esi</span><br><span class="line"> 44ee63:7c 3d jl 44eea2 <runtime.rt0_go+0x122></span><br><span class="line"> 44ee65:b8 07 00 00 00 mov $0x7,%eax</span><br><span class="line"> 44ee6a:31 c9 xor %ecx,%ecx</span><br><span class="line"> 44ee6c:0f a2 cpuid</span><br><span class="line"> 44ee6e:f7 c3 08 00 00 00 test $0x8,%ebx</span><br><span class="line"> 44ee74:0f 95 05 e1 d9 0f 00 setne 0xfd9e1(%rip) # 54c85c <runtime.support_bmi1></span><br><span class="line"> 44ee7b:f7 c3 20 00 00 00 test $0x20,%ebx</span><br><span class="line"> 44ee81:0f 95 05 d3 d9 0f 00 setne 0xfd9d3(%rip) # 54c85b <runtime.support_avx2></span><br><span class="line"> 44ee88:f7 c3 00 01 00 00 test $0x100,%ebx</span><br><span class="line"> 44ee8e:0f 95 05 c8 d9 0f 00 setne 0xfd9c8(%rip) # 54c85d <runtime.support_bmi2></span><br><span class="line"> 44ee95:f7 c3 00 02 00 00 test $0x200,%ebx</span><br><span class="line"> 44ee9b:0f 95 05 bc d9 0f 00 setne 0xfd9bc(%rip) # 54c85e <runtime.support_erms></span><br><span class="line"> 44eea2:80 3d b6 d9 0f 00 01 cmpb $0x1,0xfd9b6(%rip) # 54c85f <runtime.support_osxsave></span><br><span class="line"> 44eea9:75 0d jne 44eeb8 <runtime.rt0_go+0x138></span><br><span class="line"> 44eeab:31 c9 xor %ecx,%ecx</span><br><span class="line"> 44eead:0f 01 d0 xgetbv</span><br><span class="line"> 44eeb0:83 e0 06 and $0x6,%eax</span><br><span class="line"> 44eeb3:83 f8 06 cmp $0x6,%eax</span><br><span class="line"> 44eeb6:74 0e je 44eec6 <runtime.rt0_go+0x146></span><br><span class="line"> 44eeb8:c6 05 9b d9 0f 00 00 movb $0x0,0xfd99b(%rip) # 54c85a <runtime.support_avx></span><br><span class="line"> 44eebf:c6 05 95 d9 0f 00 00 movb $0x0,0xfd995(%rip) # 54c85b <runtime.support_avx2></span><br><span class="line"> 44eec6:48 8b 05 5b f3 0d 00 mov 0xdf35b(%rip),%rax # 52e228 <_cgo_init></span><br><span class="line"> 44eecd:48 85 c0 test %rax,%rax</span><br><span class="line"> 44eed0:74 26 je 44eef8 <runtime.rt0_go+0x178></span><br><span class="line"> 44eed2:48 89 f9 mov %rdi,%rcx</span><br><span class="line"> 44eed5:48 8d 35 c4 1b 00 00 lea 0x1bc4(%rip),%rsi # 450aa0 <setg_gcc></span><br><span class="line"> 44eedc:ff d0 callq *%rax</span><br><span class="line"> 44eede:48 8d 0d 7b fb 0d 00 lea 0xdfb7b(%rip),%rcx # 52ea60 <runtime.g0></span><br><span class="line"> 44eee5:48 8b 01 mov (%rcx),%rax</span><br><span class="line"> 44eee8:48 05 70 03 00 00 add $0x370,%rax</span><br><span class="line"> 44eeee:48 89 41 10 mov %rax,0x10(%rcx)</span><br><span class="line"> 44eef2:48 89 41 18 mov %rax,0x18(%rcx)</span><br><span class="line"> 44eef6:eb 2f jmp 44ef27 <runtime.rt0_go+0x1a7></span><br><span class="line"> 44eef8:48 8d 3d e9 00 0e 00 lea 0xe00e9(%rip),%rdi # 52efe8 <runtime.m0+0x88></span><br><span class="line"> 44eeff:e8 8c 3d 00 00 callq 452c90 <runtime.settls></span><br><span class="line"> 44ef04:64 48 c7 04 25 f8 ff movq $0x123,%fs:0xfffffffffffffff8</span><br><span class="line"> 44ef0b:ff ff 23 01 00 00</span><br><span class="line"> 44ef11:48 8b 05 d0 00 0e 00 mov 0xe00d0(%rip),%rax # 52efe8 <runtime.m0+0x88></span><br><span class="line"> 44ef18:48 3d 23 01 00 00 cmp $0x123,%rax</span><br><span class="line"> 44ef1e:74 07 je 44ef27 <runtime.rt0_go+0x1a7></span><br><span class="line"> 44ef20:89 04 25 00 00 00 00 mov %eax,0x0</span><br><span class="line"> 44ef27:48 8d 0d 32 fb 0d 00 lea 0xdfb32(%rip),%rcx # 52ea60 <runtime.g0></span><br><span class="line"> 44ef2e:64 48 89 0c 25 f8 ff mov %rcx,%fs:0xfffffffffffffff8</span><br><span class="line"> 44ef35:ff ff</span><br><span class="line"> 44ef37:48 8d 05 22 00 0e 00 lea 0xe0022(%rip),%rax # 52ef60 <runtime.m0></span><br><span class="line"> 44ef3e:48 89 08 mov %rcx,(%rax)</span><br><span class="line"> 44ef41:48 89 41 30 mov %rax,0x30(%rcx)</span><br><span class="line"> 44ef45:fc cld</span><br><span class="line"> 44ef46:e8 85 68 fe ff callq 4357d0 <runtime.check></span><br><span class="line"> 44ef4b:8b 44 24 10 mov 0x10(%rsp),%eax</span><br><span class="line"> 44ef4f:89 04 24 mov %eax,(%rsp)</span><br><span class="line"> 44ef52:48 8b 44 24 18 mov 0x18(%rsp),%rax</span><br><span class="line"> 44ef57:48 89 44 24 08 mov %rax,0x8(%rsp)</span><br><span class="line"> 44ef5c:e8 6f 62 fe ff callq 4351d0 <runtime.args></span><br><span class="line"> 44ef61:e8 aa 62 fd ff callq 425210 <runtime.osinit></span><br><span class="line"> 44ef66:e8 d5 ac fd ff callq 429c40 <runtime.schedinit></span><br><span class="line"> 44ef6b:48 8d 05 b6 ae 07 00 lea 0x7aeb6(%rip),%rax # 4c9e28 <runtime.mainPC></span><br><span class="line"> 44ef72:50 push %rax</span><br><span class="line"> 44ef73:6a 00 pushq $0x0</span><br><span class="line"> 44ef75:e8 36 14 fe ff callq 4303b0 <runtime.newproc></span><br><span class="line"> 44ef7a:58 pop %rax</span><br><span class="line"> 44ef7b:58 pop %rax</span><br><span class="line"> 44ef7c:e8 7f cb fd ff callq 42bb00 <runtime.mstart></span><br><span class="line"> 44ef81:c7 04 25 f1 00 00 00 movl $0xf1,0xf1</span><br><span class="line"> 44ef88:f1 00 00 00</span><br><span class="line"> 44ef8c:c3 retq</span><br><span class="line"> 44ef8d:cc int3</span><br><span class="line"> 44ef8e:cc int3</span><br><span class="line"> 44ef8f:cc int3</span><br><span class="line"></span><br><span class="line">000000000044ef90 <runtime.asminit>:</span><br><span class="line"> 44ef90:c3 retq</span><br></pre></td></tr></table></figure><p>At the same time, we can use dlv to debug it step by step. with dlv, we can verify the sequence of execution and identify the source files.</p><h3 id="use-dlv-to-debug-‘hello-world’-step-by-step"><a href="#use-dlv-to-debug-‘hello-world’-step-by-step" class="headerlink" title="use dlv to debug ‘hello_world’ step by step."></a>use dlv to debug ‘hello_world’ step by step.</h3><img src="/2018/11/17/Explore-go-runtime-engine/dlv_debug.png" title="dlv_debug"><p>Until now, we get the below tables for the starting of go runtime engine.<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">|---------------------------------------------------|</span><br><span class="line">| Functions | File |</span><br><span class="line">| ------------------------------------------------- |</span><br><span class="line">| 1. _rt0_amd64_linux <---- rt0_linux_amd64.s |</span><br><span class="line">|---------------------------------------------------|</span><br><span class="line">| 2. runtime.rt0_go <---------- asm_amd64.s |</span><br><span class="line">| |_____ stubs.go |</span><br><span class="line">|---------------------------------------------------|</span><br><span class="line">| 3. runtime.args <----------- runtime1.go |</span><br><span class="line">|---------------------------------------------------|</span><br><span class="line">| 4. runtime.osinit <---------- os_linux.go |</span><br><span class="line">|---------------------------------------------------|</span><br><span class="line">| 5. runtime.schedinit <----| | </span><br><span class="line">| runtime.newproc <----|__ /-- proc.go | </span><br><span class="line">| runtime.mstart <----| \-- runtime2.go | </span><br><span class="line">|---------------------------------------------------|</span><br></pre></td></tr></table></figure></p><h2 id="Thoughts"><a href="#Thoughts" class="headerlink" title="Thoughts."></a>Thoughts.</h2><p>如果我们比较一下GO和SPARK的运行引擎,我们就会发现一些有意思的地方。GO和SPAKR虽然一个是编程语言,一个是计算框架, 但是都是为了解决计算瓶颈,并发问题而提出的方案。</p><p>GO是彻底的革命者,通过从编程语言级别上的协程支持及CSP的并发模型,来彻底压榨CPU。尤其是GO的runtime能够监控系统调用,高效的协程调度的确给人眼前一亮,十分惊艳的感觉。在语言的设计上也很大胆,充分揉合了面向过程,面向对象及函数编程的精髓。</p><img src="/2018/11/17/Explore-go-runtime-engine/g_scheduler.png" title="g_scheduler"><p>Spark是一个并行计算框架,也是非常聪明的务实者,通过Scala及Actor并发模型来高效解决大数据计算的问题。同时它也充分利用了JVM及Java world里已存的资源。在运行时调度上是通过分析spark作业,并发的完成作业的task。</p><img src="/2018/11/17/Explore-go-runtime-engine/spark_scheduler.png" title="spark_scheduler"><h2 id="main-function-in-proc-go"><a href="#main-function-in-proc-go" class="headerlink" title="main function in proc.go"></a>main function in proc.go</h2><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">main</span><br><span class="line"> -- getg</span><br><span class="line"> -- systemstack (asm_amd64.s)</span><br><span class="line"> -- newm (sysmon)</span><br><span class="line"> -- allocm</span><br><span class="line"> -- acquirep</span><br><span class="line"> -- wirep</span><br><span class="line"> -- mcommoninit</span><br><span class="line"> -- mpreinit (?)</span><br><span class="line"> -- malg (allocate new g, with a stack)</span><br><span class="line"> -- newm1</span><br><span class="line"> -- funcPC</span><br><span class="line"> -- msanwrite</span><br><span class="line"> -- asmcgocall</span><br><span class="line"> -- newosproc </span><br><span class="line"> -- lockOSThread</span><br><span class="line"> -- dolockOSThread</span><br><span class="line"> -- runtime_init</span><br><span class="line"> -- gcenable</span><br><span class="line"> -- startTemplateThread</span><br><span class="line"> -- newm</span><br><span class="line"> -- cgocall</span><br><span class="line"> -- main_init</span><br><span class="line"> -- unlockOSThread</span><br><span class="line"> -- dounlockOSThread</span><br><span class="line"> -- main_main</span><br><span class="line"> -- racefini</span><br><span class="line"> -- Gosched</span><br><span class="line"> -- checkTimeouts</span><br><span class="line"> -- mcall</span><br><span class="line"> -- gosched_m</span><br><span class="line"> -- traceGoSched</span><br><span class="line"> -- goschedImpl</span><br><span class="line"> -- dumpgstatus</span><br><span class="line"> -- readgstatus</span><br><span class="line"> -- casgstatus</span><br><span class="line"> -- dropg</span><br><span class="line"> -- setMNoWB</span><br><span class="line"> -- setGNoWB</span><br><span class="line"> -- globrunqput</span><br><span class="line"> -- schedule</span><br><span class="line"> -- stoplockedm</span><br><span class="line"> -- releasep</span><br><span class="line"> -- handoffp</span><br><span class="line"> -- runqempty</span><br><span class="line"> -- startm</span><br><span class="line"> -- gcBlackenEnabled</span><br><span class="line"> -- gcMarkWorkAvailable</span><br><span class="line"> -- pidleput</span><br><span class="line"> -- notesleep</span><br><span class="line"> -- acquirep</span><br><span class="line"> -- execute</span><br><span class="line"> -- gogo</span><br><span class="line"> -- procyield</span><br><span class="line"> -- osyield</span><br><span class="line"> -- gopark</span><br></pre></td></tr></table></figure><h2 id="Refer-To"><a href="#Refer-To" class="headerlink" title="Refer To"></a>Refer To</h2><ul><li><a href="https://github.com/cch123/golang-notes/blob/master/assembly.md" target="_blank" rel="noopener">https://github.com/cch123/golang-notes/blob/master/assembly.md</a></li><li><a href="http://doc.cat-v.org/plan_9/4th_edition/papers/asm" target="_blank" rel="noopener">http://doc.cat-v.org/plan_9/4th_edition/papers/asm</a></li></ul>]]></content>
<summary type="html">
<p>Go runtime engine是Go语言中非常有意思的部分。下面我们通过go的hello_world来初步分析,探索一下它的启动顺序及调用函数和源程序文件。</p>
<h2 id="hello-world-source-code"><a href="#hello-wor
</summary>
<category term="go" scheme="http://lu-liang.github.io/tags/go/"/>
<category term="linux" scheme="http://lu-liang.github.io/tags/linux/"/>
</entry>
<entry>
<title>Play with minikube, helm, metallb and istio</title>
<link href="http://lu-liang.github.io/2018/11/05/play-with-minikube/"/>
<id>http://lu-liang.github.io/2018/11/05/play-with-minikube/</id>
<published>2018-11-05T11:57:07.000Z</published>
<updated>2018-11-13T06:52:32.000Z</updated>
<content type="html"><![CDATA[<p>kubernetes是容器世界的主要编排工具。熟悉并掌握kubernetes上的相关技能,在当前云计算领域是必不可少的。本文主要介绍一下如何在mac上安装minikube,并尝试使用helm,metallb及Istio.</p><h2 id="virtual-environment"><a href="#virtual-environment" class="headerlink" title="virtual environment"></a>virtual environment</h2><p>minikube可以支持使用多种虚拟机驱动器,例如:xhyve、VirtualBox、VMwareFusion、hyperV、KVM等。在这里,我们使用virtualBox 去运行虚拟的minikube实例。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">brew cask install virtual box</span><br><span class="line"></span><br><span class="line">## reinstall virtualbox with debug info</span><br><span class="line">## brew cask reinstall --force virtualbox --verbose --debug</span><br></pre></td></tr></table></figure><p>使用brew安装virtualBox的过程中,有可能会遇到与kernel driver相关的错误,通过修改下面的Mac系统设置,再重新安装就能解决。</p><img src="/2018/11/05/play-with-minikube/mac_os_setting.png" title="mac_os_setting.png"><h2 id="minikube"><a href="#minikube" class="headerlink" title="minikube"></a>minikube</h2><ol><li>install minikube<br>和上面安装virtualBox一样,在Mac上,最简单的安装方式就是使用brew去安装minikube.</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># install minikube</span><br><span class="line">brew cask install minikube</span><br></pre></td></tr></table></figure><p>minikube is a kind of one node kubernetes cluster which is installed in one virtual machine. After installing minikube, when you open the virutalbox, you will find the “minikube” vm. At the same time, it also installs “kubectl” command at your mac laptop.</p><img src="/2018/11/05/play-with-minikube/virtualbox_minikube.png" title="virtualbox_minikube.png"><p>This is the architecture of minikube.</p><img src="/2018/11/05/play-with-minikube/minikube_arch.png" title="minikube_arch.png"><p>minikube will install everything on the default folder $HOME/.minikube. You can go to the folder and then dig into the details.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ .minikube pwd</span><br><span class="line">/Users/luliang/.minikube</span><br><span class="line">➜ .minikube ls</span><br><span class="line">addons ca.pem client.key machines proxy-client.key</span><br><span class="line">apiserver.crt cache config profiles</span><br><span class="line">apiserver.key cert.pem files proxy-client-ca.crt</span><br><span class="line">ca.crt certs key.pem proxy-client-ca.key</span><br><span class="line">ca.key client.crt logs proxy-client.crt</span><br></pre></td></tr></table></figure><ol start="2"><li>minikube start<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## start minikube</span><br><span class="line">minikube start</span><br><span class="line"></span><br><span class="line">## show status</span><br><span class="line">➜ minikube status</span><br><span class="line">minikube: Running</span><br><span class="line">cluster: Running</span><br><span class="line">kubectl: Correctly Configured: pointing to minikube-vm at 192.168.99.100</span><br><span class="line"></span><br><span class="line">➜ kubectl config view</span><br><span class="line">apiVersion: v1</span><br><span class="line">clusters:</span><br><span class="line">- cluster:</span><br><span class="line"> certificate-authority: /Users/luliang/.minikube/ca.crt</span><br><span class="line"> server: https://192.168.99.100:8443</span><br><span class="line"> name: minikube</span><br><span class="line">contexts:</span><br><span class="line">- context:</span><br><span class="line"> cluster: minikube</span><br><span class="line"> user: minikube</span><br><span class="line"> name: minikube</span><br><span class="line">current-context: minikube</span><br><span class="line">kind: Config</span><br><span class="line">preferences: {}</span><br><span class="line">users:</span><br><span class="line">- name: minikube</span><br><span class="line"> user:</span><br><span class="line"> client-certificate: /Users/luliang/.minikube/client.crt</span><br><span class="line"> client-key: /Users/luliang/.minikube/client.key</span><br></pre></td></tr></table></figure></li></ol><p>If you encountered the following error during starting minikube, you can try to fix it with the solution below.</p><blockquote><p><strong>Error Message:</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ ~ minikube start</span><br><span class="line">Starting local Kubernetes v1.10.0 cluster...</span><br><span class="line">Starting VM...</span><br><span class="line">Getting VM IP address...</span><br><span class="line">Moving files into cluster...</span><br><span class="line">Setting up certs...</span><br><span class="line">Connecting to cluster...</span><br><span class="line">Setting up kubeconfig...</span><br><span class="line">Starting cluster components...</span><br><span class="line">E0912 17:39:12.486830 17689 start.go:305] Error restarting</span><br><span class="line">cluster: restarting kube-proxy: waiting for kube-proxy to be</span><br><span class="line">up for configmap update: timed out waiting for the condition</span><br><span class="line"></span><br><span class="line">➜ ~ kubectl -n kube-system get pods</span><br><span class="line">NAME READY STATUS RESTARTS AGE</span><br><span class="line">coredns-c4cffd6dc-5q6n2 0/1 CrashLoopBackOff 69 5h</span><br><span class="line">etcd-minikube 1/1 Running 0 4h</span><br><span class="line">kube-addon-manager-minikube 1/1 Running 1 4h</span><br><span class="line">kube-apiserver-minikube 1/1 Running 0 4h</span><br><span class="line">kube-controller-manager-minikube 1/1 Running 0 4h</span><br><span class="line">kube-scheduler-minikube 1/1 Running 1 4h</span><br><span class="line">kubernetes-dashboard-6f4cfc5d87-45dr8 0/1 CrashLoopBackOff 65 5h</span><br><span class="line">storage-provisioner 0/1 CrashLoopBackOff 65 5h</span><br></pre></td></tr></table></figure></p></blockquote><blockquote><p><strong>Solution:</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">1) close the VirtualBox if opened.</span><br><span class="line">2) delete the previous temp files generated.</span><br><span class="line">3) if you are behind the proxy set the proxy.</span><br><span class="line">4) then do the following...</span><br><span class="line"></span><br><span class="line"> $ minikube stop</span><br><span class="line"> $ minikube delete</span><br><span class="line"> $ minikube start</span><br></pre></td></tr></table></figure></p></blockquote><ol start="3"><li><p>deploy hello-world in minikube<br>安装完minikube以后,我们可以在minikube里部署一个hello-world来验证功能。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## There is no pod before deploying hello-world.</span><br><span class="line">➜ ~ kubectl get pods</span><br><span class="line">No resources found.</span><br><span class="line"></span><br><span class="line">➜ ~ kubectl get ns</span><br><span class="line">NAME STATUS AGE</span><br><span class="line">default Active 6m</span><br><span class="line">kube-public Active 6m</span><br><span class="line">kube-system Active 6m</span><br><span class="line"></span><br><span class="line">## run hello-world.</span><br><span class="line">➜ ~ kubectl run hello-minikube --image=k8s.gcr.io/echoserver:1.4 --port=8080</span><br><span class="line">deployment.apps/hello-minikube created</span><br><span class="line"></span><br><span class="line">## check pod of hello-world</span><br><span class="line">➜ ~ kubectl get po</span><br><span class="line">NAME READY STATUS RESTARTS AGE</span><br><span class="line">hello-minikube-6c47c66d8-jks94 0/1 ContainerCreating 0 6s</span><br><span class="line"></span><br><span class="line">## expose its service as NodePort since there is no external load balancer in minikube.</span><br><span class="line">➜ ~ kubectl expose deployment hello-minikube --type=NodePort</span><br><span class="line">service/hello-minikube exposed</span><br><span class="line"></span><br><span class="line">## get the details of the service.</span><br><span class="line">➜ ~ kubectl get svc</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">hello-minikube NodePort 10.98.53.207 <none> 8080:31251/TCP 1m</span><br><span class="line">kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 16m</span><br><span class="line"></span><br><span class="line">## verify it by curl</span><br><span class="line">➜ ~ curl $(minikube service hello-minikube --url)</span><br><span class="line">CLIENT VALUES:</span><br><span class="line">client_address=172.17.0.1</span><br><span class="line">command=GET</span><br><span class="line">real path=/</span><br><span class="line">query=nil</span><br><span class="line">request_version=1.1</span><br><span class="line">request_uri=http://192.168.99.100:8080/</span><br><span class="line"></span><br><span class="line">SERVER VALUES:</span><br><span class="line">server_version=nginx: 1.10.0 - lua: 10001</span><br><span class="line"></span><br><span class="line">HEADERS RECEIVED:</span><br><span class="line">accept=*/*</span><br><span class="line">host=192.168.99.100:31251</span><br><span class="line">user-agent=curl/7.52.1</span><br><span class="line">BODY:</span><br><span class="line">-no body in request-%</span><br></pre></td></tr></table></figure></li><li><p>minikube addons<br>minikube 里有以下的addons,可以通过 <strong>minikube addons enable</strong> 命令直接启用。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ ~ minikube addons list</span><br><span class="line">- addon-manager: enabled</span><br><span class="line">- coredns: enabled</span><br><span class="line">- dashboard: enabled</span><br><span class="line">- default-storageclass: enabled</span><br><span class="line">- efk: disabled</span><br><span class="line">- freshpod: disabled</span><br><span class="line">- heapster: disabled</span><br><span class="line">- ingress: disabled</span><br><span class="line">- kube-dns: disabled</span><br><span class="line">- metrics-server: disabled</span><br><span class="line">- nvidia-driver-installer: disabled</span><br><span class="line">- nvidia-gpu-device-plugin: disabled</span><br><span class="line">- registry: disabled</span><br><span class="line">- registry-creds: disabled</span><br><span class="line">- storage-provisioner: enabled</span><br><span class="line"></span><br><span class="line">➜ ~ minikube addons enable metrics-server</span><br><span class="line">metrics-server was successfully enabled</span><br></pre></td></tr></table></figure></li><li><p>start dashboard</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ ~ minikube dashboard</span><br><span class="line">Opening http://127.0.0.1:61035/api/v1/namespaces/kube-system/services/http:kubernetes-dashboard:/proxy/ in your default browser...</span><br></pre></td></tr></table></figure></li></ol><img src="/2018/11/05/play-with-minikube/minikube_dashboard.png" title="minikube_dashboard.png"><ol start="6"><li>minikube ssh<br>we can login the vm of minikube to look into details or operate it.<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">minikube ssh</span><br><span class="line">➜ istio-1.1.0-snapshot.2 minikube ssh</span><br><span class="line"> _ _</span><br><span class="line"> _ _ ( ) ( )</span><br><span class="line"> ___ ___ (_) ___ (_)| |/') _ _ | |_ __</span><br><span class="line">/' _ ` _ `\| |/' _ `\| || , < ( ) ( )| '_`\ /'__`\</span><br><span class="line">| ( ) ( ) || || ( ) || || |\`\ | (_) || |_) )( ___/</span><br><span class="line">(_) (_) (_)(_)(_) (_)(_)(_) (_)`\___/'(_,__/'`\____)</span><br><span class="line"></span><br><span class="line">$</span><br></pre></td></tr></table></figure></li></ol><h2 id="Helm"><a href="#Helm" class="headerlink" title="Helm"></a>Helm</h2><p>Helm is a kind of application package manager in kubernetes platform. It can be used to list/install/update/delete application easily.</p><p>Helm consists of client “helm” and server “tiller” installed on kubernetes. The following chart is the architecture of helm.<br><img src="/2018/11/05/play-with-minikube/helm_arch.png" title="helm_arch.png"></p><ol><li><p>install helm<br>Like minikube, helm is also installed on $HOME/.helm.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">brew install kubernetes-helm</span><br><span class="line"></span><br><span class="line">➜ .helm pwd</span><br><span class="line">/Users/luliang/.helm</span><br><span class="line">➜ .helm ls</span><br><span class="line">cache plugins repository starters</span><br></pre></td></tr></table></figure></li><li><p>initialize helm and install tiller on minikube</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## check if RBAC is enable.</span><br><span class="line">➜ kubectl api-versions |grep rbac</span><br><span class="line">rbac.authorization.k8s.io/v1</span><br><span class="line">rbac.authorization.k8s.io/v1beta1</span><br><span class="line">rbac.istio.io/v1alpha1</span><br><span class="line"></span><br><span class="line">## create user and role if The RBAC of kubernetes is enabled.</span><br><span class="line"></span><br><span class="line">➜ kubectl apply -f install/kubernetes/helm/helm-service-account.yaml</span><br><span class="line">serviceaccount/tiller created</span><br><span class="line">clusterrolebinding.rbac.authorization.k8s.io/tiller created</span><br><span class="line"></span><br><span class="line">➜ helm init --service-account tiller</span><br><span class="line"></span><br><span class="line">## if it's disabled.</span><br><span class="line">➜ helm init</span><br><span class="line">Creating /Users/luliang/.helm</span><br><span class="line">Creating /Users/luliang/.helm/repository</span><br><span class="line">Creating /Users/luliang/.helm/repository/cache</span><br><span class="line">Creating /Users/luliang/.helm/repository/local</span><br><span class="line">Creating /Users/luliang/.helm/plugins</span><br><span class="line">Creating /Users/luliang/.helm/starters</span><br><span class="line">Creating /Users/luliang/.helm/cache/archive</span><br><span class="line">Creating /Users/luliang/.helm/repository/repositories.yaml</span><br><span class="line">Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com</span><br><span class="line">Adding local repo with URL: http://127.0.0.1:8879/charts</span><br><span class="line">$HELM_HOME has been configured at /Users/luliang/.helm.</span><br><span class="line"></span><br><span class="line">Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.</span><br><span class="line"></span><br><span class="line">Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.</span><br><span class="line">For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation</span><br><span class="line">Happy Helming!</span><br><span class="line"></span><br><span class="line">## list po to check tiller is installed into the cluster</span><br><span class="line">➜ kubectl get po -n kube-system</span><br><span class="line">NAME READY STATUS RESTARTS AGE</span><br><span class="line">coredns-c4cffd6dc-cbqw9 1/1 Running 1 1d</span><br><span class="line">etcd-minikube 1/1 Running 0 41m</span><br><span class="line">kube-addon-manager-minikube 1/1 Running 1 1d</span><br><span class="line">kube-apiserver-minikube 1/1 Running 0 41m</span><br><span class="line">kube-controller-manager-minikube 1/1 Running 0 41m</span><br><span class="line">kube-dns-86f4d74b45-t44f6 3/3 Running 3 1d</span><br><span class="line">kube-proxy-5scqj 1/1 Running 0 40m</span><br><span class="line">kube-scheduler-minikube 1/1 Running 1 1d</span><br><span class="line">kubernetes-dashboard-6f4cfc5d87-jb5rx 1/1 Running 3 1d</span><br><span class="line">metrics-server-85c979995f-n5hdx 1/1 Running 2 1d</span><br><span class="line">storage-provisioner 1/1 Running 3 1d</span><br><span class="line">tiller-deploy-f9b8476d-b4ws9 1/1 Running 0 2m</span><br></pre></td></tr></table></figure></li><li><p>update the repo of helm and then install jenkins</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ helm repo update</span><br><span class="line">Hang tight while we grab the latest from your chart repositories...</span><br><span class="line">...Skip local chart repository</span><br><span class="line">...Successfully got an update from the "stable" chart repository</span><br><span class="line">Update Complete. ⎈ Happy Helming!⎈</span><br><span class="line"></span><br><span class="line">➜ helm search jenkins</span><br><span class="line">NAME CHART VERSIONAPP VERSIONDESCRIPTION</span><br><span class="line">stable/jenkins0.21.0 lts Open source continuous integration server. It s...</span><br><span class="line"></span><br><span class="line">➜ helm install stable/jenkins</span><br><span class="line">NAME: exegetical-manatee</span><br><span class="line">LAST DEPLOYED: Tue Nov 6 20:13:58 2018</span><br><span class="line">NAMESPACE: default</span><br><span class="line">STATUS: DEPLOYED</span><br><span class="line"></span><br><span class="line">RESOURCES:</span><br><span class="line">==> v1/Service</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">exegetical-manatee-jenkins-agent ClusterIP 10.100.233.152 <none> 50000/TCP 0s</span><br><span class="line">exegetical-manatee-jenkins LoadBalancer 10.99.251.83 <pending> 8080:31993/TCP 0s</span><br><span class="line"></span><br><span class="line">==> v1/Deployment</span><br><span class="line">NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE</span><br><span class="line">exegetical-manatee-jenkins 1 1 1 0 0s</span><br><span class="line"></span><br><span class="line">==> v1/Pod(related)</span><br><span class="line">NAME READY STATUS RESTARTS AGE</span><br><span class="line">exegetical-manatee-jenkins-dc7bb4fff-qrkq4 0/1 Pending 0 0s</span><br><span class="line"></span><br><span class="line">==> v1/Secret</span><br><span class="line">NAME TYPE DATA AGE</span><br><span class="line">exegetical-manatee-jenkins Opaque 2 0s</span><br><span class="line"></span><br><span class="line">==> v1/ConfigMap</span><br><span class="line">NAME DATA AGE</span><br><span class="line">exegetical-manatee-jenkins 5 0s</span><br><span class="line">exegetical-manatee-jenkins-tests 1 0s</span><br><span class="line"></span><br><span class="line">==> v1/PersistentVolumeClaim</span><br><span class="line">NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE</span><br><span class="line">exegetical-manatee-jenkins Bound pvc-70b3ad8a-e1bd-11e8-b9ce-0800277f5208 8Gi RWO standard 0s</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">NOTES:</span><br><span class="line">1. Get your 'admin' user password by running:</span><br><span class="line"> printf $(kubectl get secret --namespace default exegetical-manatee-jenkins -o jsonpath="{.data.jenkins-admin-password}" | base64 --decode);echo</span><br><span class="line">2. Get the Jenkins URL to visit by running these commands in the same shell:</span><br><span class="line"> NOTE: It may take a few minutes for the LoadBalancer IP to be available.</span><br><span class="line"> You can watch the status of by running 'kubectl get svc --namespace default -w exegetical-manatee-jenkins'</span><br><span class="line"> export SERVICE_IP=$(kubectl get svc --namespace default exegetical-manatee-jenkins --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")</span><br><span class="line"> echo http://$SERVICE_IP:8080/login</span><br><span class="line"></span><br><span class="line">3. Login with the password from step 1 and the username: admin</span><br><span class="line"></span><br><span class="line">For more information on running Jenkins on Kubernetes, visit:</span><br><span class="line">https://cloud.google.com/solutions/jenkins-on-container-engine</span><br></pre></td></tr></table></figure></li><li><p>verify the jenkins.<br>In order to access to the jenkins service, we have to change the jenkins services from “LoadBalancer” to “NodePort” since we don’t have an external loadbalancer yet. </p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ kubectl get svc --namespace default -w exegetical-manatee-jenkins</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">exegetical-manatee-jenkins LoadBalancer 10.99.251.83 <pending> 8080:31993/TCP 2m</span><br><span class="line">^C% </span><br><span class="line"></span><br><span class="line">➜ kubectl edit svc exegetical-manatee-jenkins</span><br><span class="line">service/exegetical-manatee-jenkins edited</span><br><span class="line"></span><br><span class="line">➜ kubectl get svc --namespace default -w exegetical-manatee-jenkins</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">exegetical-manatee-jenkins NodePort 10.99.251.83 <none> 8080:31993/TCP 5m</span><br><span class="line"></span><br><span class="line">## we also can get the service info by minikube command.</span><br><span class="line">➜ minikube service list</span><br><span class="line">|-------------|----------------------------------|-----------------------------|</span><br><span class="line">| NAMESPACE | NAME | URL |</span><br><span class="line">|-------------|----------------------------------|-----------------------------|</span><br><span class="line">| default | exegetical-manatee-jenkins | http://192.168.99.100:31993 |</span><br><span class="line">| default | exegetical-manatee-jenkins-agent | No node port |</span><br><span class="line">| default | hello-minikube | http://192.168.99.100:31251 |</span><br><span class="line">| default | kubernetes | No node port |</span><br><span class="line">| default | my-nginx | http://192.168.99.100:32370 |</span><br><span class="line">| kube-system | kube-dns | No node port |</span><br><span class="line">| kube-system | kubernetes-dashboard | No node port |</span><br><span class="line">| kube-system | metrics-server | No node port |</span><br><span class="line">| kube-system | tiller-deploy | No node port |</span><br><span class="line">|-------------|----------------------------------|-----------------------------|</span><br></pre></td></tr></table></figure></li></ol><img src="/2018/11/05/play-with-minikube/helm_jenkins.png" title="helm_jenkins.png"><h2 id="Metallb"><a href="#Metallb" class="headerlink" title="Metallb"></a>Metallb</h2><p>Metallb is a new project, open-sourced by Google end of 2017. Its goal is to manage external IPs on k8s bare-metal deployments.</p><p>After installing Metalib, there are one deployment and one daemonset in cluster.</p><ul><li>The metallb-system/controller deployment. This is the cluster-wide controller that handles IP address assignments.</li><li>The metallb-system/speaker daemonset. This is the component that speaks the protocol(s) of your choice to make the services reachable.</li></ul><h3 id="install-Metallb-with-helm"><a href="#install-Metallb-with-helm" class="headerlink" title="install Metallb with helm."></a>install Metallb with helm.</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## The config is not managed by helm.</span><br><span class="line">➜ helm install --name metallb stable/metallb</span><br><span class="line"></span><br><span class="line">## the two pods of metallb are deployed.</span><br><span class="line">➜ kubectl get po</span><br><span class="line">NAME READY STATUS RESTARTS AGE</span><br><span class="line">metallb-controller-5d4c5548f7-t2qfd 1/1 Running 0 2m</span><br><span class="line">metallb-speaker-27dd8 1/1 Running 0 2m</span><br><span class="line"></span><br><span class="line">## install jenkins by helm</span><br><span class="line">➜ helm install --name jenkins stable/jenkins</span><br><span class="line"></span><br><span class="line">## the ip of jenkins service is still pending since there is no config for metallb.</span><br><span class="line">➜ kubectl get svc</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">jenkins LoadBalancer 10.104.220.135 <pending> 8080:31249/TCP 4m</span><br><span class="line">jenkins-agent ClusterIP 10.107.222.223 <none> 50000/TCP 4m</span><br><span class="line">kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d</span><br><span class="line"></span><br><span class="line">## create the config of metallb. Update the ip config based on the settings of DHCP server.</span><br><span class="line">➜ more config-metallb.yml</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: ConfigMap</span><br><span class="line">metadata:</span><br><span class="line"> namespace: default</span><br><span class="line"> name: metallb-config</span><br><span class="line">data:</span><br><span class="line"> config: |</span><br><span class="line"> address-pools:</span><br><span class="line"> - name: default</span><br><span class="line"> protocol: layer2</span><br><span class="line"> addresses:</span><br><span class="line"> - 192.168.99.200-192.168.99.250</span><br><span class="line"></span><br><span class="line">➜ kubectl apply -f config-metallb.yml</span><br><span class="line">configmap/metallb-config created</span><br><span class="line"></span><br><span class="line">## external ip is assigned by metallb.</span><br><span class="line">➜ kubectl get svc</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">jenkins LoadBalancer 10.104.220.135 192.168.99.200 8080:31249/TCP 5m</span><br><span class="line">jenkins-agent ClusterIP 10.107.222.223 <none> 50000/TCP 5m</span><br><span class="line">kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d</span><br></pre></td></tr></table></figure><img src="/2018/11/05/play-with-minikube/virtualbox_minikube_ip_arrange.png" title="virtualbox_minikube_ip_arrange.png"><p>We can verify the jenkins by external ip.<br><img src="/2018/11/05/play-with-minikube/helm_jenkins_external_ip.png" title="helm_jenkins_external_ip.png"></p><h3 id="install-Metallb-without-helm"><a href="#install-Metallb-without-helm" class="headerlink" title="install Metallb without helm"></a>install Metallb without helm</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## install Metallb without helm. ##</span><br><span class="line">kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.2.1/manifests/metallb.yaml</span><br><span class="line"></span><br><span class="line">kubectl get po -n metallb-system</span><br><span class="line"></span><br><span class="line">(on your host) $ cat <<EOF > config-metallb.yml</span><br><span class="line">apiVersion: v1</span><br><span class="line">kind: ConfigMap</span><br><span class="line">metadata:</span><br><span class="line"> namespace: metallb-system</span><br><span class="line"> name: config</span><br><span class="line">data:</span><br><span class="line"> config: |</span><br><span class="line"> address-pools:</span><br><span class="line"> - name: default</span><br><span class="line"> protocol: layer2</span><br><span class="line"> addresses:</span><br><span class="line"> - 192.168.99.240-192.168.99.250 </span><br><span class="line">EOF</span><br><span class="line"></span><br><span class="line">kubectl create -f config-metallb.yml</span><br><span class="line"></span><br><span class="line">## verify Metallb with nginx</span><br><span class="line">kubectl expose deployment nginx --type LoadBalancer</span><br><span class="line"></span><br><span class="line">kubectl get svc nginx</span><br></pre></td></tr></table></figure><h2 id="Istio"><a href="#Istio" class="headerlink" title="Istio"></a>Istio</h2><ol><li><p>Download and setup Istio</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">curl -L https://git.io/getLatestIstio | sh -</span><br><span class="line"></span><br><span class="line"># or download the release and uncompress it by yourself.</span><br><span class="line">wget https://github.com/istio/istio/releases/download/1.1.0-snapshot.2/istio-1.1.0-snapshot.2-osx.tar.gz</span><br><span class="line"></span><br><span class="line">tar -xvzf istio*.tar.gz</span><br><span class="line"></span><br><span class="line">#setup path for istio.</span><br><span class="line">export PATH=/Users/luliang/Tools/istio/istio-1.1.0-snapshot.2/bin:$PATH</span><br></pre></td></tr></table></figure></li><li><p>Install and verify Istio<br>Istio can be installed by kubectl or helm. Here, we will introduce how to use helm to install Istio. By the way, if the version of helm is prior to 2.10, Please create CRDs with kubectl firstly.</p></li></ol><ul><li><p>prerequisites</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/virtualservices.networking.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/destinationrules.networking.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/serviceentries.networking.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/gateways.networking.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/envoyfilters.networking.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/clusterrbacconfigs.rbac.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/policies.authentication.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/meshpolicies.authentication.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/httpapispecbindings.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/httpapispecs.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/quotaspecbindings.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/quotaspecs.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/rules.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/attributemanifests.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/bypasses.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/circonuses.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/deniers.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/fluentds.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/kubernetesenvs.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/listcheckers.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/memquotas.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/noops.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/opas.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/prometheuses.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/rbacs.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/redisquotas.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/servicecontrols.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/signalfxs.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/solarwindses.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/stackdrivers.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/statsds.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/stdios.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/apikeys.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/authorizations.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/checknothings.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/kuberneteses.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/listentries.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/logentries.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/edges.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/metrics.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/quotas.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/reportnothings.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/servicecontrolreports.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/tracespans.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/rbacconfigs.rbac.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/serviceroles.rbac.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/servicerolebindings.rbac.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/adapters.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/instances.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/templates.config.istio.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/handlers.config.istio.io created</span><br><span class="line"></span><br><span class="line">➜ kubectl apply -f install/kubernetes/helm/subcharts/certmanager/templates/crds.yaml</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/clusterissuers.certmanager.k8s.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/issuers.certmanager.k8s.io created</span><br><span class="line">customresourcedefinition.apiextensions.k8s.io/certificates.certmanager.k8s.io created</span><br></pre></td></tr></table></figure></li><li><p>install command:</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">helm install install/kubernetes/helm/istio --name istio --namespace istio-system</span><br><span class="line"></span><br><span class="line">## if we don't install metallb and there is no external loadbalancer. We have to use the following command to install istio.</span><br><span class="line"></span><br><span class="line">helm install install/kubernetes/helm/istio --name istio --namespace istio-system --set gateways.istio-ingressgateway.type=NodePort --set gateways.istio-egressgateway.type=NodePort</span><br></pre></td></tr></table></figure></li><li><p>issues during installation<br>If you encounter the following errors, you can fix it with the solution described below.</p></li></ul><p><strong>issue 1</strong></p><blockquote><p><strong>Error Message:</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ helm install install/kubernetes/helm/istio --name istio --namespace istio-system</span><br><span class="line">Error: found in requirements.yaml, but missing in charts/ directory: sidecarInjectorWebhook, security, ingress, gateways, mixer, nodeagent, pilot, grafana, prometheus, servicegraph, tracing, galley, kiali, certmanager</span><br></pre></td></tr></table></figure></p></blockquote><blockquote><p><strong>Solution:</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">helm dep update install/kubernetes/helm/istio</span><br></pre></td></tr></table></figure></p></blockquote><p><strong>issue 2</strong></p><blockquote><p><strong>Error Message:</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ helm install install/kubernetes/helm/istio --name istio --namespace istio-system</span><br><span class="line"></span><br><span class="line">Error: transport is closing</span><br></pre></td></tr></table></figure></p></blockquote><blockquote><p><strong>Solution:</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## enable port-forwarding in node.</span><br><span class="line">run 'yum install -y socat' on every node can resolve this problem.</span><br><span class="line"></span><br><span class="line">## When call helm, try to use --wait --timeout 600 and --tiller-connection-timeout 600 to fix the problem.</span><br><span class="line">helm install install/kubernetes/helm/istio --name istio --namespace istio-system --wait --timeout 600 --tiller-connection-timeout 600</span><br></pre></td></tr></table></figure></p></blockquote><p><strong>issue 3</strong></p><blockquote><p><strong>Error Message:</strong><br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## check istio version</span><br><span class="line">➜ istioctl version</span><br><span class="line">version.BuildInfo{Version:"1.1.0-snapshot.2", GitRevision:"bd24a62648c07e24ca655c39727aeb0e4761919a", User:"root", Host:"6408abaf1dac", GolangVersion:"go1.10.4", DockerHub:"docker.io/istio", BuildStatus:"Clean"}</span><br><span class="line"></span><br><span class="line">## check the status of istio</span><br><span class="line">➜ kubectl get po -n istio-system</span><br><span class="line">NAME READY STATUS RESTARTS AGE</span><br><span class="line">istio-citadel-78f695c895-bgm9c 1/1 Running 3 13h</span><br><span class="line">istio-egressgateway-5dddcd6df7-f5shm 1/1 Running 3 13h</span><br><span class="line">istio-galley-85fff4bf65-hd7l2 1/1 Running 3 13h</span><br><span class="line">istio-ingressgateway-6d5bc988d7-gmvg2 1/1 Running 3 13h</span><br><span class="line">istio-pilot-5fdf6bdb86-rgq4f 0/2 Pending 0 13h</span><br><span class="line">istio-policy-59df9cf56f-vbznd 2/2 Running 19 13h</span><br><span class="line">istio-security-post-install-pkrtj 0/1 Completed 0 13h</span><br><span class="line">istio-sidecar-injector-5695fdf5b7-lgdbn 1/1 Running 12 13h</span><br><span class="line">istio-telemetry-7d567f4998-7btv8 2/2 Running 24 13h</span><br><span class="line">prometheus-7fcd5846db-8t9v2 1/1 Running 10 13h</span><br><span class="line"></span><br><span class="line">## pilot is still pending, check it and find it's insufficient memory issue.</span><br><span class="line">➜ kubectl describe po -n istio-system istio-pilot-5fdf6bdb86-rgq4f</span><br><span class="line"></span><br><span class="line">Events:</span><br><span class="line"> Type Reason Age From Message</span><br><span class="line"> ---- ------ ---- ---- -------</span><br><span class="line"> Warning FailedScheduling 13h (x37 over 13h) default-scheduler 0/1 nodes are available: 1 Insufficient memory.</span><br><span class="line"> Warning FailedScheduling 12h (x36 over 13h) default-scheduler 0/1 nodes are available: 1 Insufficient memory.</span><br></pre></td></tr></table></figure></p></blockquote><blockquote><p><strong>Solution:</strong></p><ol><li>increase the memory of minikube to 4G by modifying the config.json<br>Another way is to start minikube with –memory parameter<br> “minikube start –memory 4096”</li><li>Edit the deployment of istio-pilot to decrease memory to 1G.</li></ol></blockquote><img src="/2018/11/05/play-with-minikube/istio_pilot_mem.png" title="istio_pilot_mem.png"><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">## increase the memory of minikube to 4G by modifying the config.json</span><br><span class="line">➜ minikube stop</span><br><span class="line"></span><br><span class="line">➜ minikube pwd</span><br><span class="line"> /Users/luliang/.minikube/machines/minikube</span><br><span class="line">➜ minikube more config.json</span><br><span class="line"> {</span><br><span class="line"> "ConfigVersion": 3,</span><br><span class="line"> "Driver": {</span><br><span class="line"> "IPAddress": "192.168.99.100",</span><br><span class="line"> "MachineName": "minikube",</span><br><span class="line"> "SSHUser": "docker",</span><br><span class="line"> "SSHPort": 56365,</span><br><span class="line"> "SSHKeyPath": "/Users/luliang/.minikube/machines/minikube/id_rsa",</span><br><span class="line"> "StorePath": "/Users/luliang/.minikube",</span><br><span class="line"> "SwarmMaster": false,</span><br><span class="line"> "SwarmHost": "",</span><br><span class="line"> "SwarmDiscovery": "",</span><br><span class="line"> "VBoxManager": {},</span><br><span class="line"> "HostInterfaces": {},</span><br><span class="line"> "CPU": 2,</span><br><span class="line"> "Memory": 4096,</span><br><span class="line"></span><br><span class="line">➜ kubectl edit deploy -n istio-system istio-pilot</span><br><span class="line">deployment.extensions/istio-pilot edited</span><br><span class="line"></span><br><span class="line">## Fixed. All of istio components are running.</span><br><span class="line">➜ kubectl get po -n istio-system</span><br><span class="line">NAME READY STATUS RESTARTS AGE</span><br><span class="line">istio-citadel-78f695c895-bgm9c 1/1 Running 4 23h</span><br><span class="line">istio-egressgateway-5dddcd6df7-f5shm 1/1 Running 4 23h</span><br><span class="line">istio-galley-85fff4bf65-hd7l2 1/1 Running 4 23h</span><br><span class="line">istio-ingressgateway-6d5bc988d7-gmvg2 1/1 Running 4 23h</span><br><span class="line">istio-pilot-6c4d876b55-74z7m 2/2 Running 0 10m</span><br><span class="line">istio-policy-59df9cf56f-vbznd 2/2 Running 25 23h</span><br><span class="line">istio-security-post-install-pkrtj 0/1 Completed 0 23h</span><br><span class="line">istio-sidecar-injector-5695fdf5b7-lgdbn 1/1 Running 21 23h</span><br><span class="line">istio-telemetry-7d567f4998-7btv8 2/2 Running 37 23h</span><br><span class="line">prometheus-7fcd5846db-8t9v2 1/1 Running 18 23h</span><br><span class="line"></span><br><span class="line">## check proxy-stauts</span><br><span class="line">➜ kube istioctl proxy-status</span><br><span class="line">Warning! error execing into istio-pilot-6c4d876b55-74z7m/istio-system discovery container: gc 1 @0.247s 2%: 0.15+27+2.0 ms clock, 0.30+0.047/9.5/15+4.0 ms cpu, 4->4->2 MB, 5 MB goal, 2 P</span><br><span class="line">gc 2 @0.294s 3%: 0.016+13+3.0 ms clock, 0.032+0.71/0.24/12+6.1 ms cpu, 4->4->3 MB, 5 MB goal, 2 P</span><br><span class="line"></span><br><span class="line">PROXY CDS LDS EDS RDS PILOT VERSION</span><br><span class="line">istio-egressgateway-5dddcd6df7-f5shm.istio-system SYNCED SYNCED SYNCED (100%) NOT SENT istio-pilot-6c4d876b55-74z7m 1.1.0</span><br><span class="line">istio-ingressgateway-6d5bc988d7-gmvg2.istio-system SYNCED SYNCED SYNCED (100%) NOT SENT istio-pilot-6c4d876b55-74z7m 1.1.0</span><br></pre></td></tr></table></figure><p>There are some addons in istio. You can install and use them directly.</p><ul><li><p>prometheus<br>kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath=’{.items[0].metadata.name}’) 9090:9090<br><a href="http://localhost:9090" target="_blank" rel="noopener">http://localhost:9090</a></p></li><li><p>grafana<br>kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath=’{.items[0].metadata.name}’) 3000:3000<br><a href="http://localhost:3000" target="_blank" rel="noopener">http://localhost:3000</a></p></li><li><p>zipkin<br>kubectl port-forward -n istio-system $(kubectl get pod -n istio-system -l app=zipkin -o jsonpath=’{.items[0].metadata.name}’) 9411:9411<br><a href="http://localhost:9411" target="_blank" rel="noopener">http://localhost:9411</a></p></li><li><p>servicegraph<br>kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=servicegraph -o jsonpath=’{.items[0].metadata.name}’) 8088:8088<br><a href="http://localhost:8088/force/forcegraph.html" target="_blank" rel="noopener">http://localhost:8088/force/forcegraph.html</a><br><a href="http://localhost:8088/dotviz" target="_blank" rel="noopener">http://localhost:8088/dotviz</a><br><a href="http://localhost:8088/dotgraph" target="_blank" rel="noopener">http://localhost:8088/dotgraph</a></p></li></ul><ol start="3"><li>Play with istio samples.</li></ol><ul><li>get ingressgetaway connection info.<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">export GATEWAY_URL=$(kubectl get po -l istio=ingressgateway -n istio-system -o 'jsonpath={.items[0].status.hostIP}'):$(kubectl get svc istio-ingressgateway -n istio-system -o'jsonpath={.spec.ports[0].nodePort}')</span><br><span class="line"></span><br><span class="line">## Since we installed metallb, you also can get it with svc info.</span><br><span class="line">export GATEWAY_URL=192.168.99.201:80</span><br><span class="line"></span><br><span class="line">kubectl get svc -n istio-system</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">istio-citadel ClusterIP 10.108.166.71 <none> 8060/TCP,9093/TCP 1d</span><br><span class="line">istio-egressgateway ClusterIP 10.96.223.142 <none> 80/TCP,443/TCP 1d</span><br><span class="line">istio-galley ClusterIP 10.102.157.176 <none> 443/TCP,9093/TCP,9901/TCP 1d</span><br><span class="line">istio-ingressgateway LoadBalancer 10.96.187.129 192.168.99.201 80:31380/TCP,443:31390/TCP,31400:31400/TCP,15029:31130/TCP,15030:30515/TCP,15031:30093/TCP,15032:30006/TCP 1d</span><br><span class="line">istio-pilot ClusterIP 10.101.2.251 <none> 15010/TCP,15011/TCP,8080/TCP,9093/TCP 1d</span><br><span class="line">istio-policy ClusterIP 10.103.126.65 <none> 9091/TCP,15004/TCP,9093/TCP 1d</span><br><span class="line">istio-sidecar-injector ClusterIP 10.102.18.170 <none> 443/TCP 1d</span><br><span class="line">istio-telemetry ClusterIP 10.103.164.99 <none> 9091/TCP,15004/TCP,9093/TCP,42422/TCP 1d</span><br><span class="line">prometheus ClusterIP 10.109.103.184 <none> 9090/TCP 1d</span><br></pre></td></tr></table></figure></li></ul><p>There are two ways to inject istio-proxy into your applicaton pods. The first method is that we can enable isito-injection for namespace so that all applications will be injected proxy automatically in this namespace. The second is to use istioctl manually to modify pod definition file before installing it.</p><ul><li><p>enable isito-injection for namespace <strong>default</strong></p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">> kubectl label namespace default istio-injection=enabled</span><br></pre></td></tr></table></figure></li><li><p>enable isito-injection by istioctl manually.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ kubectl apply -f <(istioctl kube-inject -f samples/bookinfo/platform/kube/bookinfo.yaml)</span><br><span class="line">service/details created</span><br><span class="line">deployment.extensions/details-v1 created</span><br><span class="line">service/ratings created</span><br><span class="line">deployment.extensions/ratings-v1 created</span><br><span class="line">service/reviews created</span><br><span class="line">deployment.extensions/reviews-v1 created</span><br><span class="line">deployment.extensions/reviews-v2 created</span><br><span class="line">deployment.extensions/reviews-v3 created</span><br><span class="line">service/productpage created</span><br><span class="line">deployment.extensions/productpage-v1 created</span><br><span class="line"></span><br><span class="line">➜ kubectl get svc</span><br><span class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</span><br><span class="line">details ClusterIP 10.96.224.7 <none> 9080/TCP 1m</span><br><span class="line">kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d</span><br><span class="line">productpage ClusterIP 10.105.194.137 <none> 9080/TCP 1m</span><br><span class="line">ratings ClusterIP 10.105.57.93 <none> 9080/TCP 1m</span><br><span class="line">reviews ClusterIP 10.97.20.103 <none> 9080/TCP 1m</span><br><span class="line"></span><br><span class="line">➜ kubectl get deployment</span><br><span class="line">NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE</span><br><span class="line">details-v1 1 0 0 0 1m</span><br><span class="line">intent-wallaby-metallb-controller 1 1 1 1 1d</span><br><span class="line">productpage-v1 1 0 0 0 1m</span><br><span class="line">ratings-v1 1 0 0 0 1m</span><br><span class="line">reviews-v1 1 0 0 0 1m</span><br><span class="line">reviews-v2 1 0 0 0 1m</span><br><span class="line">reviews-v3 1 0 0 0 1m</span><br></pre></td></tr></table></figure></li><li><p>test samples app with curl</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">> export GATEWAY_URL=$(kubectl get po -l istio=ingressgateway -n istio-system -o 'jsonpath={.items[0].status.hostIP}'):$(kubectl get svc istio-ingressgateway -n istio-system -o 'jsonpath={.spec.ports[0].nodePort}')</span><br><span class="line"></span><br><span class="line">And test with curl:</span><br><span class="line">> curl -o /dev/null -s -w "%{http_code}n" http://${GATEWAY_URL}/productpage</span><br><span class="line">200</span><br><span class="line"></span><br><span class="line">With browser, we can go to URL: http://192.168.99.100:9080/productpage</span><br></pre></td></tr></table></figure></li></ul><ol start="4"><li>Delete istio<br>We can delete istio by helm if it’s installed by helm. Otherwise, you have to delete it by yourself.<figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">helm delete --purge istio</span><br><span class="line"></span><br><span class="line"># if there are something left in kubernetes, you can delete the namespace and pod of istio-system to clean up for istio.</span><br><span class="line"></span><br><span class="line">kubectl delete ns istio-system</span><br><span class="line"></span><br><span class="line">kubectl delete po PODAME --force --grace-period=0</span><br></pre></td></tr></table></figure></li></ol><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to:"></a>Refer to:</h2><ul><li><a href="https://developer.apple.com/library/archive/technotes/tn2459/_index.html" target="_blank" rel="noopener">https://developer.apple.com/library/archive/technotes/tn2459/_index.html</a></li><li><a href="https://github.com/kubernetes/minikube/blob/v0.30.0/README.md" target="_blank" rel="noopener">https://github.com/kubernetes/minikube/blob/v0.30.0/README.md</a></li><li><a href="https://stackoverflow.com/questions/52300055/error-restarting-cluster-restarting-kube-proxy-waiting-for-kube-proxy-to-be-up" target="_blank" rel="noopener">https://stackoverflow.com/questions/52300055/error-restarting-cluster-restarting-kube-proxy-waiting-for-kube-proxy-to-be-up</a></li><li><a href="https://docs.helm.sh/using_helm/" target="_blank" rel="noopener">https://docs.helm.sh/using_helm/</a></li><li><a href="https://preliminary.istio.io/docs/setup/kubernetes/helm-install.html" target="_blank" rel="noopener">https://preliminary.istio.io/docs/setup/kubernetes/helm-install.html</a></li><li><a href="https://www.kubernetes.org.cn/3879.html" target="_blank" rel="noopener">https://www.kubernetes.org.cn/3879.html</a></li><li><a href="https://metallb.universe.tf/installation/" target="_blank" rel="noopener">https://metallb.universe.tf/installation/</a></li><li><a href="https://metallb.universe.tf/tutorial/minikube/" target="_blank" rel="noopener">https://metallb.universe.tf/tutorial/minikube/</a></li><li><a href="https://github.com/kubernetes/minikube/blob/master/docs/drivers.md" target="_blank" rel="noopener">https://github.com/kubernetes/minikube/blob/master/docs/drivers.md</a></li></ul>]]></content>
<summary type="html">
<p>kubernetes是容器世界的主要编排工具。熟悉并掌握kubernetes上的相关技能,在当前云计算领域是必不可少的。本文主要介绍一下如何在mac上安装minikube,并尝试使用helm,metallb及Istio.</p>
<h2 id="virtual-enviro
</summary>
<category term="Kubernetes" scheme="http://lu-liang.github.io/categories/Kubernetes/"/>
<category term="minikube" scheme="http://lu-liang.github.io/tags/minikube/"/>
<category term="kubernetes" scheme="http://lu-liang.github.io/tags/kubernetes/"/>
<category term="helm" scheme="http://lu-liang.github.io/tags/helm/"/>
<category term="Istio" scheme="http://lu-liang.github.io/tags/Istio/"/>
<category term="Metallb" scheme="http://lu-liang.github.io/tags/Metallb/"/>
</entry>
<entry>
<title>git与jenkins的集成</title>
<link href="http://lu-liang.github.io/2018/10/17/git-jenkins/"/>
<id>http://lu-liang.github.io/2018/10/17/git-jenkins/</id>
<published>2018-10-17T02:44:46.000Z</published>
<updated>2018-10-21T12:47:41.000Z</updated>
<content type="html"><![CDATA[<p>Git和Jenkins的集成中,主要是在git api, git hooks,git alias, git plugin for Jenkins 及Jenkins API 等中间做文章。下面就来介绍一下这几种集成方法。</p><h2 id="Use-Github-Webhooks"><a href="#Use-Github-Webhooks" class="headerlink" title="Use Github Webhooks"></a>Use Github Webhooks</h2><p>很多的project都是利用github来做源代码管理的。 这里我们就利用github的webhook,通过git的push动作来触发Jenkins job的build。</p><ol><li><p>登陆GitHub设置webhook如下:</p><img src="/2018/10/17/git-jenkins/webhook.png" title="webhook.png"></li><li><p>登陆Jenkins Server设置Github Connection信息:</p><img src="/2018/10/17/git-jenkins/jenkins_github.png" title="jenkins_github.png"></li><li><p>登陆Jenkins Server修改Job触发条件</p><img src="/2018/10/17/git-jenkins/jenkins_trigger.png" title="jenkins_trigger.png"></li></ol><p>上面这种实现方式的特点就是很方便,只需要在网页上面设置几下就可以,但是不够灵活。例如,触发job时无法指定参数等。</p><h2 id="Use-Git-hooks-及-Jenkins-API"><a href="#Use-Git-hooks-及-Jenkins-API" class="headerlink" title="Use Git hooks 及 Jenkins API"></a>Use Git hooks 及 Jenkins API</h2><p>如果project不是部署在GitHub上,上面的方法就无法使用了,怎么办呢? 这里就需要我们可以自己实现git hooks来调用相应的Jenkins API来实现同样的功能。git的钩子有很多,在.git/hooks下就有一些samples,如下图:</p><img src="/2018/10/17/git-jenkins/hooks.png" title="hooks.png"><p>git hooks的具体说明,可以参考最后面列表。 这里使用post-update为例,具体步骤如下:</p><ol><li><p>Copy over your .git directory to your web server</p></li><li><p>On your local copy, modify your .git/config file and add your web server as a remote:</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">[remote "production"]</span><br><span class="line"> url = username@webserver:/path/to/htdocs/.git</span><br></pre></td></tr></table></figure></li><li><p>On the server, replace .git/hooks/post-update with file below:</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">#!/bin/sh</span><br><span class="line">#</span><br><span class="line"># 实现项目的部署脚本或者使用Jenkins remote API调用相关的jenkins job</span><br><span class="line"># 这里使用curl去调用jenkins job</span><br><span class="line">curl "http://xx.xx.xxx:8080/job/test234/buildWithParameters?token=build_token&Param1=dddddd"</span><br></pre></td></tr></table></figure></li><li><p>Add execute access to the file (again, on the server):</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">chmod +x .git/hooks/post-update</span><br></pre></td></tr></table></figure></li><li><p>Now, just locally push to your web server and it should automatically update the working copy:</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">git push production</span><br></pre></td></tr></table></figure></li></ol><h2 id="Use-Git-alias-及-Jenkins-API"><a href="#Use-Git-alias-及-Jenkins-API" class="headerlink" title="Use Git alias 及 Jenkins API"></a>Use Git alias 及 Jenkins API</h2><p>上面的方法需要在git client端和server端进行设置, 好处是可以在server端利用hook做一系列的工作。如果不需要在server端做工作的话,可以使用别名,这样就更加简单。</p><ol><li><p>设置git alias</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ git config alias.xpush '!git push $1 $2 && trigger-jenkins.sh'</span><br><span class="line"># (remember the backslash before the ! if your shell requires it)</span><br><span class="line">This adds the following to your .git/config file:</span><br><span class="line"></span><br><span class="line">[alias]</span><br><span class="line"> xpush = !git push $1 $2 && trigger-jenkins.sh</span><br><span class="line"></span><br><span class="line">-------------------------------</span><br><span class="line"></span><br><span class="line"># trigger-jenkins.sh 脚本如下:</span><br><span class="line"></span><br><span class="line">#!/bin/sh</span><br><span class="line">#</span><br><span class="line">curl "http://xx.xx.xxx:8080/job/test234/buildWithParameters?token=build_token&Param1=dddddd"</span><br></pre></td></tr></table></figure></li><li><p>配置remote trigger</p><img src="/2018/10/17/git-jenkins/remote_trigger.png" title="remote_trigger.png"></li><li><p>使用git alias,触发jenkins job.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ git xpush</span><br><span class="line"></span><br><span class="line">#your changes will be pushed, and then trigger-jenkins.sh will be executed.</span><br></pre></td></tr></table></figure></li></ol><h2 id="Use-Git-API-及-Jenkins-API"><a href="#Use-Git-API-及-Jenkins-API" class="headerlink" title="Use Git API 及 Jenkins API"></a>Use Git API 及 Jenkins API</h2><p>与上述的几种方法相比,使用API是最灵活的;可以根据需求,实现各种定制的功能。Git/Jenkins提供了各种相关编程语言的API,这里以python为例,做个介绍。</p><ol><li><p>GitPython<br>GitPython 是一个用于操作 Git 版本库的 python 包,它提供了一系列的对象模型(库 - Repo、树 - Tree、提交 - Commit等) 用于操作版本库中的相应对象。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">pip install GitPython</span><br><span class="line"></span><br><span class="line">from git import Repo</span><br><span class="line"># 创建版本库对象</span><br><span class="line">repo = git.Repo('./')</span><br><span class="line"></span><br><span class="line"># 版本库是否为空版本库</span><br><span class="line">repo.bare</span><br><span class="line"></span><br><span class="line"># 当前工作区是否干净</span><br><span class="line">repo.is_dirty()</span><br><span class="line"></span><br><span class="line"># 版本库中未跟踪的文件列表</span><br><span class="line">repo.untracked_files</span><br><span class="line"></span><br><span class="line"># 克隆版本库</span><br><span class="line">repo.clone('clone_path')</span><br><span class="line"></span><br><span class="line"># 压缩版本库到 tar 文件</span><br><span class="line">with open('repo.tar', 'wb') as fp:</span><br><span class="line"> repo.archive(fp)</span><br><span class="line"></span><br><span class="line"># 新建分支</span><br><span class="line">repo.create_head('branchname')</span><br><span class="line"></span><br><span class="line"># 查看当前分支</span><br><span class="line">repo.active_branch</span><br><span class="line"></span><br><span class="line"># 获取默认版本库 origin</span><br><span class="line">remote = repo.remote()</span><br><span class="line"></span><br><span class="line"># 从远程版本库拉取分支</span><br><span class="line">remote.pull()</span><br><span class="line"></span><br><span class="line"># 推送本地分支到远程版本库</span><br><span class="line">remote.push()</span><br><span class="line"></span><br><span class="line"># 重命名远程分支</span><br><span class="line"># remote.rename('new_origin')</span><br></pre></td></tr></table></figure></li><li><p>Python-Jenkins<br>python-jenkins 通过Jenkins的REST接口管理Jenkins Server,实现对Jenkins, node, view, job的管理。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># 安装Python-Jenkins</span><br><span class="line">pip install python-jenkins</span><br><span class="line"></span><br><span class="line"># 登陆 Jenkins Server 或者 Server 版本信息</span><br><span class="line">import jenkins</span><br><span class="line"></span><br><span class="line">server = jenkins.Jenkins('http://localhost:8080', username='myuser', password='mypassword')</span><br><span class="line">user = server.get_whoami()</span><br><span class="line">version = server.get_version()</span><br><span class="line">print('Hello %s from Jenkins %s' % (user['fullName'], version))</span><br><span class="line"></span><br><span class="line"># 获取 job列表</span><br><span class="line">jobs = server.get_jobs()</span><br><span class="line">print jobs</span><br><span class="line"></span><br><span class="line"># 获取指定的job</span><br><span class="line">my_job = server.get_job_config('cool-job')</span><br><span class="line">print(my_job) # prints XML configuration</span><br><span class="line"></span><br><span class="line"># 运行job</span><br><span class="line">server.build_job('empty')</span><br><span class="line"></span><br><span class="line"># 关闭job</span><br><span class="line">server.disable_job('empty')</span><br><span class="line"></span><br><span class="line"># 复制job</span><br><span class="line">server.copy_job('empty', 'empty_copy')</span><br><span class="line"></span><br><span class="line"># 激活job</span><br><span class="line">server.enable_job('empty_copy')</span><br><span class="line"></span><br><span class="line"># 重新配置job</span><br><span class="line">server.reconfig_job('empty_copy', jenkins.RECONFIG_XML)</span><br><span class="line"></span><br><span class="line"># 删除job</span><br><span class="line">server.delete_job('empty')</span><br><span class="line">server.delete_job('empty_copy')</span><br><span class="line"></span><br><span class="line"># 配置,运行带参数的job</span><br><span class="line"># build a parameterized job</span><br><span class="line"># requires creating and configuring the api-test job to accept 'param1' & 'param2'</span><br><span class="line">server.build_job('api-test', {'param1': 'test value 1', 'param2': 'test value 2'})</span><br><span class="line">last_build_number = server.get_job_info('api-test')['lastCompletedBuild']['number']</span><br><span class="line">build_info = server.get_build_info('api-test', last_build_number)</span><br><span class="line">print build_info</span><br><span class="line"></span><br><span class="line"># get all jobs from the specific view</span><br><span class="line">jobs = server.get_jobs(view_name='View Name')</span><br><span class="line">print jobs</span><br></pre></td></tr></table></figure></li><li><p>联合使用GitPython及Python-Jenkins实现前面的例子</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">from git import Repo</span><br><span class="line">import jenkins</span><br><span class="line"></span><br><span class="line">repo = git.Repo('./')</span><br><span class="line">remote = repo.remote()</span><br><span class="line">remote.push()</span><br><span class="line"></span><br><span class="line">server = jenkins.Jenkins('http://localhost:8080', username='myuser', password='mypassword')</span><br><span class="line">server.build_job('empty')</span><br></pre></td></tr></table></figure></li></ol><h2 id="Current-git-hooks"><a href="#Current-git-hooks" class="headerlink" title="Current git hooks"></a>Current git hooks</h2><table><thead><tr><th>Hook Name</th><th>Invoked By</th><th>Description</th><th>Parameters (Number and Description)</th></tr></thead><tbody><tr><td>applypatch-msg</td><td>git am</td><td>Can edit the commit message file and is often used to verify or actively format a patch’s message to a project’s standards. A non-zero exit status aborts the commit.</td><td>(1) name of the file containing the proposed commit message</td></tr><tr><td>pre-applypatch</td><td>git am</td><td>This is actually called after the patch is applied, but before the changes are committed. Exiting with a non-zero status will leave the changes in an uncommitted state. Can be used to check the state of the tree before actually committing the changes.</td><td>(none)</td></tr><tr><td>post-applypatch</td><td>git am</td><td>This hook is run after the patch is applied and committed. Because of this, it cannot abort the process, and is mainly used for creating notifications.</td><td>(none)</td></tr><tr><td>pre-commit</td><td>git commit</td><td>This hook is called before obtaining the proposed commit message. Exiting with anything other than zero will abort the commit. It is used to check the commit itself (rather than the message).</td><td>(none)</td></tr><tr><td>prepare-commit-msg</td><td>git commit</td><td>Called after receiving the default commit message, just prior to firing up the commit message editor. A non-zero exit aborts the commit. This is used to edit the message in a way that cannot be suppressed.</td><td>(1 to 3) Name of the file with the commit message, the source of the commit message (message, template, merge, squash, or commit), and the commit SHA-1 (when operating on an existing commit).</td></tr><tr><td>commit-msg</td><td>git commit</td><td>Can be used to adjust the message after it has been edited in order to ensure conformity to a standard or to reject based on any criteria. It can abort the commit if it exits with a non-zero value.</td><td>(1) The file that holds the proposed message.</td></tr><tr><td>post-commit</td><td>git commit</td><td>Called after the actual commit is made. Because of this, it cannot disrupt the commit. It is mainly used to allow notifications.</td><td>(none)</td></tr><tr><td>pre-rebase</td><td>git rebase</td><td>Called when rebasing a branch. Mainly used to halt the rebase if it is not desirable.</td><td>(1 or 2) The upstream from where it was forked, the branch being rebased (not set when rebasing current)</td></tr><tr><td>post-checkout</td><td>git checkout and git clone</td><td>Run when a checkout is called after updating the worktree or after git clone. It is mainly used to verify conditions, display differences, and configure the environment if necessary.</td><td>(3) Ref of the previous HEAD, ref of the new HEAD, flag indicating whether it was a branch checkout (1) or a file checkout (0)</td></tr><tr><td>post-merge</td><td>git merge or git pull</td><td>Called after a merge. Because of this, it cannot abort a merge. Can be used to save or apply permissions or other kinds of data that git does not handle.</td><td>(1) Flag indicating whether the merge was a squash.</td></tr><tr><td>pre-push</td><td>git push</td><td>Called prior to a push to a remote. In addition to the parameters, additional information, separated by a space is passed in through stdin in the form of “<local ref=""> <local sha1=""> <remote ref=""> <remote sha1="">“. Parsing the input can get you additional information that you can use to check. For instance, if the local sha1 is 40 zeros long, the push is a delete and if the remote sha1 is 40 zeros, it is a new branch. This can be used to do many comparisons of the pushed ref to what is currently there. A non-zero exit status aborts the push.</remote></remote></local></local></td><td>(2) Name of the destination remote, location of the destination remote</td></tr><tr><td>pre-receive</td><td>git-receive-pack on the remote repo</td><td>This is called on the remote repo just before updating the pushed refs. A non-zero status will abort the process. Although it receives no parameters, it is passed a string through stdin in the form of “<old-value> <new-value> <ref-name>“ for each ref.</ref-name></new-value></old-value></td><td>(none)</td></tr><tr><td>update</td><td>git-receive-pack on the remote repo</td><td>This is run on the remote repo once for each ref being pushed instead of once for each push. A non-zero status will abort the process. This can be used to make sure all commits are only fast-forward, for instance.</td><td>(3) The name of the ref being updated, the old object name, the new object name</td></tr><tr><td>post-receive</td><td>git-receive-pack on the remote repo</td><td>This is run on the remote when pushing after the all refs have been updated. It does not take parameters, but receives info through stdin in the form of “<old-value> <new-value> <ref-name>“. Because it is called after the updates, it cannot abort the process.</ref-name></new-value></old-value></td><td>(none)</td></tr><tr><td>post-update</td><td>git-receive-pack on the remote repo</td><td>This is run only once after all of the refs have been pushed. It is similar to the post-receive hook in that regard, but does not receive the old or new values. It is used mostly to implement notifications for the pushed refs.</td><td>(?) A parameter for each of the pushed refs containing its name</td></tr><tr><td>pre-auto-gc</td><td>git gc –auto</td><td>Is used to do some checks before automatically cleaning repos.</td><td>(none)</td></tr><tr><td>post-rewrite</td><td>git commit –amend, git-rebase</td><td>This is called when git commands are rewriting already committed data. In addition to the parameters, it receives strings in stdin in the form of “<old-sha1> <new-sha1>“.</new-sha1></old-sha1></td><td>(1) Name of the command that invoked it (amend or rebase)</td></tr></tbody></table><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to"></a>Refer to</h2><ul><li><a href="https://developer.github.com/enterprise/2.14/webhooks/" target="_blank" rel="noopener">https://developer.github.com/enterprise/2.14/webhooks/</a></li><li><a href="https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks" target="_blank" rel="noopener">https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks</a></li><li><a href="https://www.digitalocean.com/community/tutorials/how-to-use-git-hooks-to-automate-development-and-deployment-tasks" target="_blank" rel="noopener">https://www.digitalocean.com/community/tutorials/how-to-use-git-hooks-to-automate-development-and-deployment-tasks</a></li><li><a href="https://stackoverflow.com/questions/279169/deploy-a-project-using-git-push?noredirect=1&lq=1" target="_blank" rel="noopener">https://stackoverflow.com/questions/279169/deploy-a-project-using-git-push?noredirect=1&lq=1</a></li><li><a href="https://www.cnblogs.com/baiyangcao/p/gitpython.html" target="_blank" rel="noopener">https://www.cnblogs.com/baiyangcao/p/gitpython.html</a></li><li><a href="https://github.com/gitpython-developers/GitPython" target="_blank" rel="noopener">https://github.com/gitpython-developers/GitPython</a></li><li><a href="https://python-jenkins.readthedocs.io/en/latest/" target="_blank" rel="noopener">https://python-jenkins.readthedocs.io/en/latest/</a></li></ul>]]></content>
<summary type="html">
<p>Git和Jenkins的集成中,主要是在git api, git hooks,git alias, git plugin for Jenkins 及Jenkins API 等中间做文章。下面就来介绍一下这几种集成方法。</p>
<h2 id="Use-Github-Webh
</summary>
<category term="git" scheme="http://lu-liang.github.io/tags/git/"/>
<category term="jenkins" scheme="http://lu-liang.github.io/tags/jenkins/"/>
</entry>
<entry>
<title>jupyter与spark集成的几种方法</title>
<link href="http://lu-liang.github.io/2018/10/08/jupyter-spark/"/>
<id>http://lu-liang.github.io/2018/10/08/jupyter-spark/</id>
<published>2018-10-08T09:16:40.000Z</published>
<updated>2018-10-09T06:38:46.000Z</updated>
<content type="html"><![CDATA[<p>Jupyter notebook is an popular and excellent tool in data scientists. They can use it to create, verify and share model via their favorite programing language. Spark is a great software to support both batch and real time data analysis in big data area. Especially, it also supports all kinds of algorithms in the component “MLlib”. It will be amazing way to work in an integration environment for both jupyter and spark in machine learning world. Now, we will introduce 4 ways to integrate jupyter and spark.</p><h2 id="Using-toree-which-is-previously-called-“Spark-Kernel”-jupyter-toree"><a href="#Using-toree-which-is-previously-called-“Spark-Kernel”-jupyter-toree" class="headerlink" title="Using toree which is previously called “Spark Kernel”. (jupyter + toree)"></a>Using <strong>toree</strong> which is previously called “Spark Kernel”. (jupyter + toree)</h2><p>When you are plan to use toree to run in jupyter server, you need to know the following limitations.</p><blockquote><ul><li>spark/spark client need to be installed in this server.</li><li>spark-submit is also kicked off at this server.</li></ul></blockquote><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># install spark</span><br><span class="line">https://spark.apache.org/docs/latest/</span><br><span class="line"></span><br><span class="line"># install toree</span><br><span class="line">pip install toree</span><br><span class="line"></span><br><span class="line"># configure toree</span><br><span class="line">jupyter toree install --spark_home=your-spark-home</span><br></pre></td></tr></table></figure><img src="/2018/10/08/jupyter-spark/toree_with_notebook.png" title="toree_with_notebook"><h2 id="Using-sparkmagic-and-livy-jupyter-sparkmagic-livy"><a href="#Using-sparkmagic-and-livy-jupyter-sparkmagic-livy" class="headerlink" title="Using sparkmagic and livy (jupyter + sparkmagic + livy)"></a>Using <strong>sparkmagic</strong> and <strong>livy</strong> (jupyter + sparkmagic + livy)</h2><p>livy is a spark rest server. sparkmagic provides several kernels such as pyspark, pyspark3, sparkr for jupyter notebook by working with livy sever together. With this approach, you may know the following features.</p><blockquote><ul><li>don’t need to install spark-client on juptyer server side</li><li>shift the submitting of spark job from jupyter server side to livy side</li></ul></blockquote><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># install sparkmagic</span><br><span class="line">pip install sparkmagic</span><br><span class="line"></span><br><span class="line"># Make sure that ipywidgets is properly installed.</span><br><span class="line">jupyter nbextension enable --py --sys-prefix widgetsnbextension</span><br><span class="line"></span><br><span class="line"># show where sparkmagic is installed.</span><br><span class="line">pip show sparkmagic</span><br><span class="line"></span><br><span class="line"># (Optional) install wrapper kernerls</span><br><span class="line">jupyter-kernelspec install sparkmagic/kernels/sparkkernel</span><br><span class="line">jupyter-kernelspec install sparkmagic/kernels/pysparkkernel</span><br><span class="line">jupyter-kernelspec install sparkmagic/kernels/pyspark3kernel</span><br><span class="line">jupyter-kernelspec install sparkmagic/kernels/sparkrkernel</span><br><span class="line"></span><br><span class="line"># (Optional) modify sparkmagic configuration file.</span><br><span class="line">~/.sparkmagic/config.json</span><br><span class="line"></span><br><span class="line">https://github.com/jupyter-incubator/sparkmagic/blob/master/sparkmagic/example_config.json</span><br><span class="line"></span><br><span class="line">{</span><br><span class="line"> "kernel_python_credentials" : {</span><br><span class="line"> "username": "",</span><br><span class="line"> "password": "",</span><br><span class="line"> "url": "http://localhost:8998",</span><br><span class="line"> "auth": "None"</span><br><span class="line"> },</span><br><span class="line"></span><br><span class="line"> "kernel_scala_credentials" : {</span><br><span class="line"> "username": "",</span><br><span class="line"> "password": "",</span><br><span class="line"> "url": "http://localhost:8998",</span><br><span class="line"> "auth": "None"</span><br><span class="line"> },</span><br><span class="line"> "kernel_r_credentials": {</span><br><span class="line"> "username": "",</span><br><span class="line"> "password": "",</span><br><span class="line"> "url": "http://localhost:8998"</span><br><span class="line"> },</span><br><span class="line"></span><br><span class="line"> "logging_config": {</span><br><span class="line"> "version": 1,</span><br><span class="line"> "formatters": {</span><br><span class="line"> "magicsFormatter": {</span><br><span class="line"> "format": "%(asctime)s\t%(levelname)s\t%(message)s",</span><br><span class="line"> "datefmt": ""</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> "handlers": {</span><br><span class="line"> "magicsHandler": {</span><br><span class="line"> "class": "hdijupyterutils.filehandler.MagicsFileHandler",</span><br><span class="line"> "formatter": "magicsFormatter",</span><br><span class="line"> "home_path": "~/.sparkmagic"</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> "loggers": {</span><br><span class="line"> "magicsLogger": {</span><br><span class="line"> "handlers": ["magicsHandler"],</span><br><span class="line"> "level": "DEBUG",</span><br><span class="line"> "propagate": 0</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"></span><br><span class="line"> "wait_for_idle_timeout_seconds": 15,</span><br><span class="line"> "livy_session_startup_timeout_seconds": 60,</span><br><span class="line"></span><br><span class="line"> "fatal_error_suggestion": "The code failed because of a fatal error:\n\t{}.\n\nSome things to try:\na) Make sure Spark has enough available resources for Jupyter to create a Spark context.\nb) Contact your Jupyter administrator to make sure the Spark magics library is configured correctly.\nc) Restart the kernel.",</span><br><span class="line"></span><br><span class="line"> "ignore_ssl_errors": false,</span><br><span class="line"></span><br><span class="line"> "session_configs": {</span><br><span class="line"> "driverMemory": "1000M",</span><br><span class="line"> "executorCores": 2</span><br><span class="line"> },</span><br><span class="line"></span><br><span class="line"> "use_auto_viz": true,</span><br><span class="line"> "coerce_dataframe": true,</span><br><span class="line"> "max_results_sql": 2500,</span><br><span class="line"> "pyspark_dataframe_encoding": "utf-8",</span><br><span class="line"></span><br><span class="line"> "heartbeat_refresh_seconds": 30,</span><br><span class="line"> "livy_server_heartbeat_timeout_seconds": 0,</span><br><span class="line"> "heartbeat_retry_seconds": 10,</span><br><span class="line"></span><br><span class="line"> "server_extension_default_kernel_name": "pysparkkernel",</span><br><span class="line"> "custom_headers": {},</span><br><span class="line"></span><br><span class="line"> "retry_policy": "configurable",</span><br><span class="line"> "retry_seconds_to_sleep_list": [0.2, 0.5, 1, 3, 5],</span><br><span class="line"> "configurable_retry_policy_max_retries": 8</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"># (Optional) Enable the server extension so that clusters can be programatically changed:</span><br><span class="line">jupyter serverextension enable --py sparkmagic</span><br></pre></td></tr></table></figure><p>Notebook magic list in sparkmagic<br><img src="/2018/10/08/jupyter-spark/sparkmagic_list.png" title="sparkmagic_list"></p><p>The integration chart for sparkmagic and livy<br><img src="/2018/10/08/jupyter-spark/sparkmagic_livy.png" title="sparkmagic_livy"></p><h2 id="Using-nb2kg-kernelgateway-and-toree-jupyter-nb2kg-kernelgateway-toree"><a href="#Using-nb2kg-kernelgateway-and-toree-jupyter-nb2kg-kernelgateway-toree" class="headerlink" title="Using nb2kg, kernelgateway and toree (jupyter + nb2kg + kernelgateway + toree)"></a>Using <strong>nb2kg</strong>, <strong>kernelgateway</strong> and <strong>toree</strong> (jupyter + nb2kg + kernelgateway + toree)</h2><blockquote><ul><li>spark/spark client need to be installed at kernelgateway side.</li><li>spark-submit is ran at kernelgateway side.</li></ul></blockquote><ol><li><p>Install nb2kg and run notebook server</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># install nb2kg</span><br><span class="line">pip install nb2kg</span><br><span class="line"></span><br><span class="line"># register nb2kg</span><br><span class="line">jupyter serverextension enable --py nb2kg --sys-prefix</span><br><span class="line"></span><br><span class="line"># start jupyter notebook server</span><br><span class="line">export KG_URL=http://kg-host:port</span><br><span class="line">jupyter notebook \</span><br><span class="line"> --NotebookApp.session_manager_class=nb2kg.managers.SessionManager \</span><br><span class="line"> --NotebookApp.kernel_manager_class=nb2kg.managers.RemoteKernelManager \</span><br><span class="line"> --NotebookApp.kernel_spec_manager_class=nb2kg.managers.RemoteKernelSpecManager</span><br><span class="line"></span><br><span class="line"># verify if nb2kg is enable.</span><br><span class="line">jupyter serverextension list</span><br><span class="line"></span><br><span class="line"> nb2kg enabled</span><br><span class="line"> - Validating...</span><br><span class="line"> nb2kg OK</span><br><span class="line"></span><br><span class="line"># uninstall nb2kg</span><br><span class="line">jupyter serverextension disable --py nb2kg --sys-prefix</span><br><span class="line">pip uninstall -y nb2kg</span><br></pre></td></tr></table></figure></li><li><p>Install kernel gateway</p></li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># install from pypi</span><br><span class="line">pip install jupyter_kernel_gateway</span><br><span class="line"></span><br><span class="line"># show all config options</span><br><span class="line">jupyter kernelgateway --help-all</span><br><span class="line"></span><br><span class="line"># run it with default options</span><br><span class="line">jupyter kernelgateway</span><br></pre></td></tr></table></figure><img src="/2018/10/08/jupyter-spark/nb2kg_deploy.png" title="nb2kg_deploy"><ol start="3"><li>Install toree in the server where kernelgatway is installed.<br>The detailed steps, please refer to the previous section.</li></ol><img src="/2018/10/08/jupyter-spark/nb2kg_kg_toree.png" title="nb2kg_kg_toree"><h2 id="Using-nb2kg-kernelgateway-sparkmagic-and-livy-jupyter-nb2kg-kernelgateway-sparkmagic-livy"><a href="#Using-nb2kg-kernelgateway-sparkmagic-and-livy-jupyter-nb2kg-kernelgateway-sparkmagic-livy" class="headerlink" title="Using nb2kg, kernelgateway, sparkmagic and livy (jupyter + nb2kg + kernelgateway + sparkmagic + livy)"></a>Using <strong>nb2kg</strong>, <strong>kernelgateway</strong>, <strong>sparkmagic</strong> and <strong>livy</strong> (jupyter + nb2kg + kernelgateway + sparkmagic + livy)</h2><blockquote><ul><li>do not need to install spark/spark client since we call spark by livy.</li><li>shift the submitting of spark job from kernelgateway side to livy side. </li></ul></blockquote><p>The detailed steps, please refer to the upper sections.</p><img src="/2018/10/08/jupyter-spark/nb2kg_kg_sparkmagic_livy.png" title="nb2kg_kg_sparkmagic_livy"><h2 id="An-step-by-step-example-to-use-toree-in-jupyter"><a href="#An-step-by-step-example-to-use-toree-in-jupyter" class="headerlink" title="An step by step example to use toree in jupyter."></a>An step by step example to use toree in jupyter.</h2><ol><li>Install spark</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">export SPARK_HOME=/Users/luliang/Tools/spark-2.1.1-bin-hadoop2.7</span><br></pre></td></tr></table></figure><ol start="2"><li>Install anaconda which includes jupyter and python.</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># install anacoda</span><br><span class="line">download the image from [anaconda webside](https://www.anaconda.com/download/) based on your os and install it.</span><br><span class="line"></span><br><span class="line"># List current available kernel</span><br><span class="line">jupyter kernelspec list</span><br><span class="line"></span><br><span class="line"># Start notebook</span><br><span class="line">jupyter notebook</span><br></pre></td></tr></table></figure><ol start="3"><li>List all configuration information for jupyter.</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">jupyter --paths</span><br></pre></td></tr></table></figure><ol start="4"><li>Install toree.</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">pip install toree</span><br><span class="line">jupyter toree install --spark_home=your-spark-home</span><br><span class="line"></span><br><span class="line"># Other examples to install toree kernel with different options:</span><br><span class="line"></span><br><span class="line">jupyter toree install --spark_home=/usr/hdp/current/spark2-client --spark_opts='--master=spark://hdpn.xxx.xxx.com:7077' --kernel_name=hdpn_standalone</span><br><span class="line"></span><br><span class="line">jupyter toree install --spark_home=/spark/home/dir</span><br><span class="line">jupyter toree install --spark_opts='--master=local[4] --executor-memory=3G'</span><br><span class="line">jupyter toree install --kernel_name=toree_special</span><br><span class="line">jupyter toree install --toree_opts='--nosparkcontext'</span><br><span class="line">jupyter toree install --interpreters=PySpark,SQL</span><br><span class="line">jupyter toree install --python=python</span><br><span class="line">jupyter toree install --help-all</span><br></pre></td></tr></table></figure><ol start="5"><li>List current available notebook servers.</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">jupyter notebook list</span><br></pre></td></tr></table></figure><ol start="6"><li><p>Generate Configuration File under ~/.jupyter</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># Writing default config to: /Users/luliang/.jupyter/jupyter_notebook_config.py</span><br><span class="line">jupyter-notebook --generate-config</span><br></pre></td></tr></table></figure></li><li><p>(Optional) Generate password and set passwork for notebook</p></li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">产生密码:终端输入ipython </span><br><span class="line">In [1]: from IPython.lib import passwd </span><br><span class="line">In [2]: passwd() </span><br><span class="line">Enter password: </span><br><span class="line">Verify password: </span><br><span class="line">Out[2]: 'sha1:6402ac25a515:2755b924b8bb5bef2475f7918776197e2f972858' </span><br><span class="line"></span><br><span class="line">配置参数: </span><br><span class="line">进入/root/.jupyter/jupyter_notebook_config.py </span><br><span class="line">c.NotebookApp.ip = '*' #启动服务的地址,设置成 ‘*’ 可以从同一网段的其他机器访问到; </span><br><span class="line">c.NotebookApp.open_browser = False #启动 ipython notebook 的时候不会自动打开浏览器; </span><br><span class="line">c.NotebookApp.password = 'sha1:6402ac25a515:2755b924b8bb5bef2475f7918776197e2f972858' # ipython notebook的登陆密码 </span><br><span class="line">c.NotebookApp.port = 6666 #设置访问端口 每次启动ipthon notebook端口会加1</span><br></pre></td></tr></table></figure><ol start="8"><li>(Optional) Configure notebook with https</li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># A self-signed certificate can be generated with openssl.</span><br><span class="line"># This certificate is valid for 365 days with both the key and certificate data written to the same file.</span><br><span class="line"></span><br><span class="line">$ openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mykey.key -out mycert.pem</span><br><span class="line"></span><br><span class="line"># Edit the jupyter_notebook_config.py file in ~/.jupyter to use the certificate.</span><br><span class="line"></span><br><span class="line">c.NotebookApp.certfile = u’/absolute/path/to/your/certificate/mycert.pem’</span><br><span class="line">c.NotebookApp.keyfile = u’/absolute/path/to/your/certificate/mykey.key’</span><br></pre></td></tr></table></figure><ol start="9"><li>Now you can access Jupyter with this url: <a href="https://hdte.xxx.xxx.com:6666/" target="_blank" rel="noopener">https://hdte.xxx.xxx.com:6666/</a></li></ol><p>To avoid chaos, you can refer to this name changing list.</p><hr><ul><li>Spark Kernel (old) ==> Toree (new) </li><li>Ipython (old) ==> jupyter (new) </li></ul><hr><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to"></a>Refer to</h2><ul><li><a href="https://jupyter-kernel-gateway.readthedocs.io/en/latest/getting-started.html" target="_blank" rel="noopener">https://jupyter-kernel-gateway.readthedocs.io/en/latest/getting-started.html</a></li><li><a href="https://github.com/jupyter/kernel_gateway" target="_blank" rel="noopener">https://github.com/jupyter/kernel_gateway</a></li><li><a href="https://github.com/jupyter/nb2kg" target="_blank" rel="noopener">https://github.com/jupyter/nb2kg</a></li><li><a href="https://github.com/apache/incubator-toree" target="_blank" rel="noopener">https://github.com/apache/incubator-toree</a></li><li><a href="http://toree.apache.org/docs/current/user/quick-start/" target="_blank" rel="noopener">http://toree.apache.org/docs/current/user/quick-start/</a></li><li><a href="https://github.com/jupyter-incubator/sparkmagic" target="_blank" rel="noopener">https://github.com/jupyter-incubator/sparkmagic</a></li></ul><p>Two examples for creating a kind of kernel for jupyter notebook.</p><ul><li><a href="https://github.com/takluyver/bash_kernel/blob/0966dc102d7549f5c909c93de633a95b2af9f707/bash_kernel/kernel.py" target="_blank" rel="noopener">https://github.com/takluyver/bash_kernel/blob/0966dc102d7549f5c909c93de633a95b2af9f707/bash_kernel/kernel.py</a></li><li><a href="https://github.com/dsblank/simple_kernel" target="_blank" rel="noopener">https://github.com/dsblank/simple_kernel</a></li></ul>]]></content>
<summary type="html">
<p>Jupyter notebook is an popular and excellent tool in data scientists. They can use it to create, verify and share model via their favorit
</summary>
<category term="jupyter" scheme="http://lu-liang.github.io/tags/jupyter/"/>
<category term="spark" scheme="http://lu-liang.github.io/tags/spark/"/>
</entry>
<entry>
<title>go语言设计中几个有意思的地方。</title>
<link href="http://lu-liang.github.io/2018/10/01/learn-go/"/>
<id>http://lu-liang.github.io/2018/10/01/learn-go/</id>
<published>2018-10-01T12:37:54.000Z</published>
<updated>2018-10-02T15:02:34.000Z</updated>
<content type="html"><![CDATA[<p>go语言的成功是典型实用主义思维的成功。go语言就像是一个面向过程(C),面向对象(JAVA)及函数编程(javascript)的揉合体,充分消化吸取这些编程思想中的最实用点。在go中,我们可以看到,C的结构体和指针,JAVA的接口,及函数编程中函数是一等公民等等特性。下面我们就来浅析一下这些有意思的地方。</p><h2 id="指针的运用。"><a href="#指针的运用。" class="headerlink" title="指针的运用。"></a>指针的运用。</h2><p>C/C++中,最容易出问题,最令人诟病的就是指针。当初在JAVA的设计中为了解决这个问题,就彻底抛弃了指针。虽然go保留了指针,但是go编译器帮助做了优化, 使用起来更加自然。</p><ul><li>编译器帮你进行指针类型的隐式转换</li></ul><p>如下例:通过指针employeeOfTheMonth和操作符. 就像Java一样很自然的设置Position</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">var employeeOfTheMonth *Employee = &dilbert</span><br><span class="line">employeeOfTheMonth.Position += " (proactive team player)"</span><br></pre></td></tr></table></figure><ul><li>调用对象方法时,也一样。</li></ul><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">pptr.Distance(q) 等价于 (*pptr).Distance(q)</span><br></pre></td></tr></table></figure><ul><li>操作指针时,也只是更新内容而不是指针本身。这样就减少了C/C++中使用指针带来的内存问题。</li></ul><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">func incr(p *int) int {</span><br><span class="line">*p++ // 改变指针P指向的变量的值,而不是指针P</span><br><span class="line">return *p</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="函数是一等公民"><a href="#函数是一等公民" class="headerlink" title="函数是一等公民"></a>函数是一等公民</h2><p>函数作为一等公民可以赋值,也可以作为函数的输入输出值。 </p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">func square(n int) int { return n * n }</span><br><span class="line">func negative(n int) int { return -n }</span><br><span class="line">func product(m, n int) int { return m * n }</span><br><span class="line"></span><br><span class="line">f := square</span><br><span class="line">fmt.Println(f(3)) // "9"</span><br><span class="line"></span><br><span class="line">f = negative</span><br><span class="line">fmt.Println(f(3)) // "-3"</span><br><span class="line">fmt.Printf("%T\n", f) // "func(int) int"</span><br><span class="line"></span><br><span class="line">f = product // compile error: can't assign func(int, int) int to func(int) int</span><br></pre></td></tr></table></figure><h2 id="结构体Tag。"><a href="#结构体Tag。" class="headerlink" title="结构体Tag。"></a>结构体Tag。</h2><p>JSON对象几乎是WEB开发中必不可少的,go通过结构体tag可以很自然的在结构体和JSON对象间进行自如转换。<br>例如:下面的代码就通过json.Marshal使得Year转换成JSON对象时的released。另外,如果希望输出的格式有缩进,可以使用json.MarshalInden来代替json.Marshal。<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">// 定义结构体 及 在Year,Color上加Tag</span><br><span class="line">type Movie struct {</span><br><span class="line"> Title string</span><br><span class="line"> Year int `json:"released"`</span><br><span class="line"> Color bool `json:"color,omitempty"`</span><br><span class="line"> Actors []string</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 初始化 movies</span><br><span class="line">var movies = []Movie{</span><br><span class="line"> {Title: "Casablanca", Year: 1942, Color: false,</span><br><span class="line"> Actors: []string{"Humphrey Bogart", "Ingrid Bergman"}},</span><br><span class="line"> {Title: "Cool Hand Luke", Year: 1967, Color: true,</span><br><span class="line"> Actors: []string{"Paul Newman"}},</span><br><span class="line"> {Title: "Bullitt", Year: 1968, Color: true,</span><br><span class="line"> Actors: []string{"Steve McQueen", "Jacqueline Bisset"}},</span><br><span class="line"> // ...</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 转换成json</span><br><span class="line">data, err := json.Marshal(movies)</span><br><span class="line">if err != nil {</span><br><span class="line"> log.Fatalf("JSON marshaling failed: %s", err)</span><br><span class="line">}</span><br><span class="line">fmt.Printf("%s\n", data)</span><br><span class="line"></span><br><span class="line">// 输出结果</span><br><span class="line">[{"Title":"Casablanca","released":1942,"Actors":["Humphrey Bogart","Ingr</span><br><span class="line">id Bergman"]},{"Title":"Cool Hand Luke","released":1967,"color":true,"Ac</span><br><span class="line">tors":["Paul Newman"]},{"Title":"Bullitt","released":1968,"color":true,"</span><br><span class="line">Actors":["Steve McQueen","Jacqueline Bisset"]}]</span><br></pre></td></tr></table></figure></p><h2 id="模版文件使得格式化输出更加丰富"><a href="#模版文件使得格式化输出更加丰富" class="headerlink" title="模版文件使得格式化输出更加丰富"></a>模版文件使得格式化输出更加丰富</h2><p>go中支持text/template和html/template等模版文件,下面的代码就是以text/template为例,来看看如何使用template。</p><ol><li><p>定义模版文件</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">const templ = `{{.TotalCount}} issues:</span><br><span class="line"> {{range .Items}}----------------------------------------</span><br><span class="line"> Number: {{.Number}}</span><br><span class="line"> User: {{.User.Login}}</span><br><span class="line"> Title: {{.Title | printf "%.64s"}}</span><br><span class="line"> Age: {{.CreatedAt | daysAgo}} days</span><br><span class="line">{{end}}`</span><br></pre></td></tr></table></figure></li><li><p>解析模版文件,创建模版对象并注册模版文件中要使用的函数</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">// 定义函数</span><br><span class="line">func daysAgo(t time.Time) int {</span><br><span class="line"> return int(time.Since(t).Hours() / 24)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// call .New .Funcs .Parse</span><br><span class="line">report, err := template.New("report").</span><br><span class="line"> Funcs(template.FuncMap{"daysAgo": daysAgo}).</span><br><span class="line"> Parse(templ)</span><br><span class="line">if err != nil {</span><br><span class="line"> log.Fatal(err)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li><li><p>调用模版对象,进行输出。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">var report = template.Must(template.New("issuelist").</span><br><span class="line"> Funcs(template.FuncMap{"daysAgo": daysAgo}).</span><br><span class="line"> Parse(templ))</span><br><span class="line"></span><br><span class="line">func main() {</span><br><span class="line"> result, err := github.SearchIssues(os.Args[1:])</span><br><span class="line"> if err != nil {</span><br><span class="line"> log.Fatal(err)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> if err := report.Execute(os.Stdout, result); err != nil {</span><br><span class="line"> log.Fatal(err)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ol><h2 id="关注于数据结构及其行为。"><a href="#关注于数据结构及其行为。" class="headerlink" title="关注于数据结构及其行为。"></a>关注于数据结构及其行为。</h2><p>go和Java等面向对象编程语言相比,在面向对象方面进行了简化。 例如:没有访问级别, 没有继承(通过组合来实现继承);go重点关注于数据结构本事及其行为(这里指方法和实现的接口)。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">//通过组合来实现继承的例子</span><br><span class="line"></span><br><span class="line">import "image/color"</span><br><span class="line"></span><br><span class="line">type Point struct{ X, Y float64 }</span><br><span class="line"></span><br><span class="line">type ColoredPoint struct {</span><br><span class="line"> Point</span><br><span class="line"> Color color.RGBA</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">var cp ColoredPoint</span><br><span class="line">cp.X = 1 // <--- assign 1 to cp.Point.X</span><br><span class="line">fmt.Println(cp.Point.X) // "1"</span><br><span class="line">cp.Point.Y = 2</span><br><span class="line">fmt.Println(cp.Y) // "2"</span><br></pre></td></tr></table></figure><h2 id="defer关键字"><a href="#defer关键字" class="headerlink" title="defer关键字"></a>defer关键字</h2><p>defer关键字确保了资源的释放,相当于Java中的finally关键字。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">func Balance() int {</span><br><span class="line">mu.Lock()</span><br><span class="line">defer mu.Unlock()</span><br><span class="line">return balance</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Goroutine和CSP并发模型。"><a href="#Goroutine和CSP并发模型。" class="headerlink" title="Goroutine和CSP并发模型。"></a>Goroutine和CSP并发模型。</h2><p>下面是一个使用goroutine和channel的例子:数据经过channel就像pipeline一样被不同的goroutine处理。# counter -> squarter -> printer</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">func counter(out chan<- int) {</span><br><span class="line"> for x := 0; x < 100; x++ {</span><br><span class="line"> out <- x</span><br><span class="line"> }</span><br><span class="line"> close(out)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">func squarer(out chan<- int, in <-chan int) {</span><br><span class="line"> for v := range in {</span><br><span class="line"> out <- v * v</span><br><span class="line"> }</span><br><span class="line"> close(out)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">func printer(in <-chan int) {</span><br><span class="line"> for v := range in {</span><br><span class="line"> fmt.Println(v)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">func main() {</span><br><span class="line"> naturals := make(chan int)</span><br><span class="line"> squares := make(chan int)</span><br><span class="line"> go counter(naturals)</span><br><span class="line"> go squarer(squares, naturals)</span><br><span class="line"> printer(squares)</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>goroutine 是Go语言中并发的执行单位。从OS的角度来看真正工作的是线程,goroutine和线程的关系如下:</p><p>一个M会对应一个内核线程,一个M也会连接一个上下文P,一个上下文P相当于一个“处理器”,一个上下文连接一个或者多个Goroutine。P(Processor)的数量是在启动时被设置为环境变量GOMAXPROCS的值,或者通过运行时调用函数runtime.GOMAXPROCS()进行设置。Processor数量固定意味着任意时刻只有固定数量的线程在运行go代码。Goroutine中就是我们要执行并发的代码。图中P正在执行的Goroutine为蓝色的;处于待执行状态的Goroutine为灰色的,灰色的Goroutine形成了一个队列runqueues</p><p>三者关系的宏观的图为:<br><img src="/2018/10/01/learn-go/goroutine_scheduler.png" title="go_scheduler"></p><p>go语言在os用户空间中设计了goroutine,通过dynamice stack(一个goroutine 2k-1G) 及上图的 m:n scheduler成功在多核处理器上实现了大量的并发。</p><p>相比较actor模型的并发可以扩展到多个机器上,go是如何支持扩展到多个机器上的呢, channel over rpc, message queue?</p><p>附1,其它语言在协程上的支持如下:<br><img src="/2018/10/01/learn-go/coroutine.jpg" title="coroutine_on_programing"></p><p>附2,Actor和CSP模型:<br><img src="/2018/10/01/learn-go/actor.png" title="ACTOR"></p><img src="/2018/10/01/learn-go/csp.png" title="CSP"><h2 id="性能优化"><a href="#性能优化" class="headerlink" title="性能优化"></a>性能优化</h2><p>go注重性能优化,测试框架中自带了Benchmark测试和性能profile报告.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">import "testing"</span><br><span class="line"></span><br><span class="line">func BenchmarkIsPalindrome(b *testing.B) {</span><br><span class="line"> for i := 0; i < b.N; i++ {</span><br><span class="line"> IsPalindrome("A man, a plan, a canal: Panama")</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">$ go test -cpuprofile=cpu.out</span><br><span class="line">$ go test -blockprofile=block.out</span><br><span class="line">$ go test -memprofile=mem.out</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>go语言的成功是典型实用主义思维的成功。go语言就像是一个面向过程(C),面向对象(JAVA)及函数编程(javascript)的揉合体,充分消化吸取这些编程思想中的最实用点。在go中,我们可以看到,C的结构体和指针,JAVA的接口,及函数编程中函数是一等公民等等特性。下面
</summary>
<category term="go" scheme="http://lu-liang.github.io/tags/go/"/>
</entry>
<entry>
<title>使用Metaparticle在code中直接编码docker/kubernetes是个好主意吗?</title>
<link href="http://lu-liang.github.io/2018/09/29/Metaparticle/"/>
<id>http://lu-liang.github.io/2018/09/29/Metaparticle/</id>
<published>2018-09-29T10:17:00.000Z</published>
<updated>2018-09-29T10:25:47.000Z</updated>
<content type="html"><![CDATA[<p>最近看到一篇文章介绍Metaparticle, 就花了点时间看了看。 吐槽一下, 我个人并不认为类似Metaparticle这类的框架是个好主意。</p><p>Metaparticle提供在code里直接编码生docker image, kubernetes pods等等云组件,期望通过这种方式使程序员能够用本身熟悉的语言来操纵dockerfile, 减少编程时来回切换的工作量。 Metaparticle的原理是通过 annotation 或者 decorate pattern的方式在源码里嵌入docker及kubernetes需要的信息。</p><p>Metaparticle提供了对java, javascript, python, ruby, go and rust 等多种语言的支持。 下面是以python为例,进行代码分析,看看他是如何实现的。</p><ul><li>python usage example:</li></ul><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">from metaparticle import Containerize</span><br><span class="line"></span><br><span class="line">@Containerize(package={'name': 'testcontainer', 'repo': 'brendanburns', 'publish': True})</span><br><span class="line">def main():</span><br><span class="line"> print('hello world')</span><br><span class="line"></span><br><span class="line">if __name__ == '__main__':</span><br><span class="line"> main()</span><br></pre></td></tr></table></figure><ul><li>decorate function source code</li></ul><p>通过write_dockerfile函数来生成docker file, 然后在类Containerize里build/run image.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">def write_dockerfile(package, exec_file):</span><br><span class="line"> if hasattr(package, 'dockerfile') and package.dockerfile is not None:</span><br><span class="line"> shutil.copy(package.dockerfile, 'Dockerfile')</span><br><span class="line"> return</span><br><span class="line"></span><br><span class="line"> copy_files = "\n".join([addFile.render() for addFile in package.additionalFiles])</span><br><span class="line"></span><br><span class="line"> with open('Dockerfile', 'w+t') as f:</span><br><span class="line"> f.write("""FROM python:{version}-alpine</span><br><span class="line">COPY ./ /app/</span><br><span class="line">{copy_files}</span><br><span class="line">RUN pip install --no-cache -r /app/requirements.txt</span><br><span class="line">CMD python -u /app/{exec_file}</span><br><span class="line">""".format(version=package.py_version,</span><br><span class="line"> exec_file=exec_file,</span><br><span class="line">copy_files=copy_files))</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">class Containerize(object):</span><br><span class="line"></span><br><span class="line"> def __init__(self, runtime={}, package={}):</span><br><span class="line"> self.runtime = option.load(option.RuntimeOptions, runtime)</span><br><span class="line"> self.package = option.load(option.PackageOptions, package)</span><br><span class="line"> self.image = "{repo}/{name}:latest".format(</span><br><span class="line"> repo=self.package.repository,</span><br><span class="line"> name=self.package.name</span><br><span class="line"> )</span><br><span class="line"></span><br><span class="line"> self.builder = builder.select(self.package.builder)</span><br><span class="line"> self.runner = runner.select(self.runtime.executor)</span><br><span class="line"></span><br><span class="line"> def __call__(self, func):</span><br><span class="line"> def wrapped(*args, **kwargs):</span><br><span class="line"> if is_in_docker_container():</span><br><span class="line"> return func(*args, **kwargs)</span><br><span class="line"></span><br><span class="line"> exec_file = sys.argv[0]</span><br><span class="line"> slash_ix = exec_file.find('/')</span><br><span class="line"> if slash_ix != -1:</span><br><span class="line"> exec_file = exec_file[slash_ix:]</span><br><span class="line"></span><br><span class="line"> write_dockerfile(self.package, exec_file)</span><br><span class="line"> self.builder.build(self.image)</span><br><span class="line"></span><br><span class="line"> if self.package.publish:</span><br><span class="line"> self.builder.publish(self.image)</span><br><span class="line"></span><br><span class="line"> def signal_handler(signal, frame):</span><br><span class="line"> self.runner.cancel(self.package.name)</span><br><span class="line"> sys.exit(0)</span><br><span class="line"> signal.signal(signal.SIGINT, signal_handler)</span><br><span class="line"></span><br><span class="line"> self.runner.run(self.image, self.package.name, self.runtime)</span><br><span class="line"></span><br><span class="line"> return self.runner.logs(self.package.name)</span><br><span class="line"> return wrapped</span><br></pre></td></tr></table></figure><p>这种Metaparticle方式的问题在于生成docker image的方式太死了而且严重的依赖Metaparticle本身的实现, 而且配置的改动要改code,容易引起问题。我认为解决这个痛点的方式,应该从编译模块入手。例如在对于Java,可以在maven里加入插件来实现直接生成部署docker image。</p><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to:"></a>Refer to:</h2><ul><li><a href="https://metaparticle.io/tutorials/python/" target="_blank" rel="noopener">https://metaparticle.io/tutorials/python/</a></li><li><a href="https://www.infoq.com/articles/metaparticle-pulumi-ballerina?utm_source=articles_about_Containers&utm_medium=link&utm_campaign=Containers" target="_blank" rel="noopener">https://www.infoq.com/articles/metaparticle-pulumi-ballerina?utm_source=articles_about_Containers&utm_medium=link&utm_campaign=Containers</a></li></ul>]]></content>
<summary type="html">
<p>最近看到一篇文章介绍Metaparticle, 就花了点时间看了看。 吐槽一下, 我个人并不认为类似Metaparticle这类的框架是个好主意。</p>
<p>Metaparticle提供在code里直接编码生docker image, kubernetes pods等等
</summary>
<category term="Metaparticle" scheme="http://lu-liang.github.io/tags/Metaparticle/"/>
</entry>
<entry>
<title>通过ssh使用socket5代理访问github</title>
<link href="http://lu-liang.github.io/2018/09/29/ssh-proxy/"/>
<id>http://lu-liang.github.io/2018/09/29/ssh-proxy/</id>
<published>2018-09-29T05:48:53.000Z</published>
<updated>2019-04-23T06:59:53.322Z</updated>
<content type="html"><![CDATA[<p>假设github.com在墙外, 你现在可以通过以下配置方法去访问它。前提是你有一台墙外的机器。至于如何得到一台墙外的机器,这个方法很多,例如可以通过申请云虚拟机器等等,详细步骤就不在这里提了。通过这台机器做代理,你就可以爬墙,自由的放飞自我了。</p><h3 id="Open-ssh-tunnel"><a href="#Open-ssh-tunnel" class="headerlink" title="Open ssh tunnel"></a>Open ssh tunnel</h3><p>The machine “proxyMachine” can visit github.com. We can open one tunnel between your laptop and proxyMachine by the following command.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">ssh -TfnN -D 7070 proxyMachine</span><br></pre></td></tr></table></figure><h3 id="Config-ssh-proxy-for-github"><a href="#Config-ssh-proxy-for-github" class="headerlink" title="Config ssh proxy for github"></a>Config ssh proxy for github</h3><p>Modify ~/.ssh/config to add proxy for github.com.</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">Host github.com</span><br><span class="line"> HostName github.com</span><br><span class="line"> User luliang</span><br><span class="line"> ProxyCommand nc -v -x 127.0.0.1:7070 %h %p</span><br><span class="line"> UseKeychain yes</span><br></pre></td></tr></table></figure><h3 id="Config-http-proxy-for-github"><a href="#Config-http-proxy-for-github" class="headerlink" title="Config http proxy for github"></a>Config http proxy for github</h3><p>If you want to use http proxy. You also need to config git with ‘git config’</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">git config --global http.proxy 'socks5://127.0.0.1:7070'</span><br><span class="line">git config --global https.proxy 'socks5://127.0.0.1:7070'</span><br></pre></td></tr></table></figure><h3 id="Config-socket5-proxy-for-your-browser"><a href="#Config-socket5-proxy-for-your-browser" class="headerlink" title="Config socket5 proxy for your browser."></a>Config socket5 proxy for your browser.</h3><p>There are two ways to config proxy for browser. You can choose one freely.</p><ul><li><p>Setup proxy in system.</p><img src="/2018/09/29/ssh-proxy/system_proxy.png" title="system_proxy.png"></li><li><p>Setup proxy in chrome with plugin “SwitchyOmega”</p><img src="/2018/09/29/ssh-proxy/chrome_proxy.png" title="chrome_proxy"></li></ul><h3 id="Config-socket5-proxy-for-your-terminal-such-as-iterm2"><a href="#Config-socket5-proxy-for-your-terminal-such-as-iterm2" class="headerlink" title="Config socket5 proxy for your terminal such as iterm2."></a>Config socket5 proxy for your terminal such as iterm2.</h3><p>在 .bashrc 或 .zshrc 中设置如下内容<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">alias setproxy="export http_proxy=socks5://127.0.0.1:7070; export https_proxy=$http_proxy"</span><br><span class="line">alias unsetproxy="unset http_proxy; unset https_proxy"</span><br></pre></td></tr></table></figure></p><p>或者手动设置终端代理:<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">export http_proxy="socks5://127.0.0.1:7070"</span><br><span class="line">export https_proxy="socks5://127.0.0.1:7070"</span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>假设github.com在墙外, 你现在可以通过以下配置方法去访问它。前提是你有一台墙外的机器。至于如何得到一台墙外的机器,这个方法很多,例如可以通过申请云虚拟机器等等,详细步骤就不在这里提了。通过这台机器做代理,你就可以爬墙,自由的放飞自我了。</p>
<h3 id="O
</summary>
<category term="Linux" scheme="http://lu-liang.github.io/categories/Linux/"/>
<category term="linux" scheme="http://lu-liang.github.io/tags/linux/"/>
<category term="git" scheme="http://lu-liang.github.io/tags/git/"/>
<category term="ssh" scheme="http://lu-liang.github.io/tags/ssh/"/>
</entry>
<entry>
<title>浅析docker, kubernets规范及实现</title>
<link href="http://lu-liang.github.io/2018/09/28/docker-world/"/>
<id>http://lu-liang.github.io/2018/09/28/docker-world/</id>
<published>2018-09-28T06:05:37.000Z</published>
<updated>2018-09-28T16:00:10.000Z</updated>
<content type="html"><![CDATA[<p>没有规矩,不成方圆, 所有的事物都是有迹可循;在容器的世界里也不例外。现在,我们就从规范入手来简单的梳理一下docker, kubernets。</p><h2 id="开源容器的业界规范"><a href="#开源容器的业界规范" class="headerlink" title="开源容器的业界规范"></a>开源容器的业界规范</h2><p>目前,容器的开源标准是OCI。在介绍OCI之前,我们先聊聊它的前世<a href="https://github.com/appc/spec/" target="_blank" rel="noopener">appc</a>。虽然appc已经不玩了,但是并不意味着它没有意义。OCI规范很多都是从appc那边一脉相承的,所以多看看,了解一下也是很有帮助。</p><h3 id="APPC"><a href="#APPC" class="headerlink" title="APPC"></a>APPC</h3><p><a href="https://github.com/appc/spec/" target="_blank" rel="noopener">The App Container (appc)</a> is an open specification that defines several aspects of how to run applications in containers: an image format, runtime environment, and discovery protocol.</p><p>appc 主要定义了下面三个方面的协议。</p><ol><li>The App Container Image format (ACI)</li><li>The App Container Executor (ACE)</li><li>App Container Image Discovery</li></ol><p>这个规范的实现可以参考下面的产品列表。</p><blockquote><p>Mature implementations of appc</p><ul><li><a href="https://github.com/3ofcoins/jetpack" target="_blank" rel="noopener">Jetpack</a> - FreeBSD/Go</li><li><a href="http://kurma.io" target="_blank" rel="noopener">Kurma</a> - Linux/Go</li><li><a href="https://coreos.com/rkt/" target="_blank" rel="noopener">rkt</a> - Linux/Go -> A security-minded, standards-based container engine</li></ul></blockquote><blockquote><p>Partial implementations of appc</p><ul><li><a href="https://github.com/cdaylward/libappc" target="_blank" rel="noopener">libappc</a> - C++ library</li><li><a href="https://github.com/cdaylward/nosecone" target="_blank" rel="noopener">Nose Cone</a> - Linux/C++</li></ul></blockquote><h3 id="OCI"><a href="#OCI" class="headerlink" title="OCI"></a>OCI</h3><p><a href="https://www.opencontainers.org/" target="_blank" rel="noopener">Open Container Initiative (OCI)</a> is an open governance structure for the express purpose of creating open industry standards around container formats and runtime.</p><p><a href="https://www.opencontainers.org/" target="_blank" rel="noopener">Open Container Initiative (OCI)</a>主要包括下面两个方面:</p><ol><li><a href="https://github.com/opencontainers/image-spec" target="_blank" rel="noopener">OCI Image Format Specification</a> 对应于ACI</li><li><a href="https://github.com/opencontainers/runtime-spec" target="_blank" rel="noopener">OCI Runtime Specification</a> 对应于ACE</li></ol><p>OCI的实现</p><ul><li><a href="https://github.com/opencontainers/runc" target="_blank" rel="noopener">runC</a>, which is donated by Docker Inc and is on the top of <a href="https://github.com/docker/libcontainer" target="_blank" rel="noopener">libcontainer</a>。<br>相对于docker, runC是更加轻量级的运行时,并且支持容器热迁移。 下图为runC的运行原理:<img src="/2018/09/28/docker-world/runC.jpg" title="runC"></li></ul><ul><li><p><a href="https://containerd.io" target="_blank" rel="noopener">containerd</a>. It was initiated by Docker Inc and fully leverages run to meet the OCI. The following is the architecture chart of containerd:</p><img src="/2018/09/28/docker-world/containerd_architecture.png" title="Containerd Architecture"><ul><li>Using plugin <a href="https://github.com/containerd/cri" target="_blank" rel="noopener">cri-containerd</a> to support Kubernetes<img src="/2018/09/28/docker-world/kubelet-cri.png" title="CRI"></li></ul></li></ul><ul><li><a href="https://linuxcontainers.org/lxd/" target="_blank" rel="noopener">LXD</a> which is a next generation system container manager and is built on the top of LXC.</li></ul><p>上面几个实现的互相依赖关系如下:</p><ul><li>containerd –> runC –> libcontainer</li><li>lxd –> lxc</li></ul><h2 id="Kubernetes的接口规范"><a href="#Kubernetes的接口规范" class="headerlink" title="Kubernetes的接口规范"></a>Kubernetes的接口规范</h2><p>Kubernetes 定义了以下的规范,这样可以灵活切换支持不同的runtime engine, virtual network 及 storage。</p><p><strong><a href="https://github.com/kubernetes/kubernetes/blob/242a97307b34076d5d8f5bbeb154fa4d97c9ef1d/docs/devel/container-runtime-interface.md" target="_blank" rel="noopener">CRI: Container Runtime Interface</a></strong> consists of a protofbuf API, specifications/requirements and libraries for container runtimes to integrate with kubelet on a node. </p><p>对于这个runtime规范,目前有以下的实现。这就意味着kubernets的runtime可以有下面的替代:</p><ul><li><a href="https://github.com/kubernetes-incubator/cri-o" target="_blank" rel="noopener">cri-o</a> OCI conformant runtimes.</li><li><a href="https://github.com/kubernetes-incubator/rktlet" target="_blank" rel="noopener">rktlet</a> the rkt container runtime.</li><li><a href="https://github.com/kubernetes/frakti" target="_blank" rel="noopener">frakti</a> hypervisor-based container runtimes.</li><li><a href="https://github.com/kubernetes/kubernetes/tree/release-1.5/pkg/kubelet/dockershim" target="_blank" rel="noopener">docker CRI shim</a> –> Kubernetes default implementation.<img src="/2018/09/28/docker-world/kubelet-cri2.png" title="OverviewOfCRI"><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">[k8s@iml11 ~]$ kubectl version</span><br><span class="line">Client Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.1", GitCommit:"b1b29978270dc22fecc592ac55d903350454310a", GitTreeState:"clean", BuildDate:"2018-07-17T18:53:20Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}</span><br><span class="line">Server Version: version.Info{Major:"1", Minor:"11", GitVersion:"v1.11.1", GitCommit:"b1b29978270dc22fecc592ac55d903350454310a", GitTreeState:"clean", BuildDate:"2018-07-17T18:43:26Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}</span><br><span class="line">[root@iml11 linux-amd64]# ps -ef|grep docker</span><br><span class="line">root 7189 2083 0 Aug03 ? 00:00:06 /usr/bin/docker-containerd-shim-current 3389a4aafa8188545b8f501143ac75344d2558204bcf5823c0fc568ccb775827 /var/run/docker/libcontainerd/3389a4aafa8188545b8f501143ac75344d2558204bcf5823c0fc568ccb775827 /usr/libexec/docker/docker-runc-current</span><br><span class="line">root 22095 2083 0 Aug09 ? 00:00:05 /usr/bin/docker-containerd-shim-current 473e9a6f97817a79091c49a282fe9b4d6db66d1f495ce555fe53078dbc109146 /var/run/docker/libcontainerd/473e9a6f97817a79091c49a282fe9b4d6db66d1f495ce555fe53078dbc109146 /usr/libexec/docker/docker-runc-current</span><br><span class="line">root 22273 2083 0 Aug09 ? 01:20:42 /usr/bin/docker-containerd-shim-current 0e24b9c7dce08d37f951ddb721b6895861a167e7f64ce401f392f34d5defbb47 /var/run/docker/libcontainerd/0e24b9c7dce08d37f951ddb721b6895861a167e7f64ce401f392f34d5defbb47 /usr/libexec/docker/docker-runc-current</span><br></pre></td></tr></table></figure></li></ul><p>如果在配置运行kubernets时,底层运行引擎不使用docker,可以通过cri-containerd进行切换。架构如下图所示:</p><img src="/2018/09/28/docker-world/kubelet_runtime.png" title="dockershimToCri-containerd"><img src="/2018/09/28/docker-world/kubelet-cri-containerd.png" title="OverviewOfCRI-containerd"><p>同样我们可以使用crictl去和container交互。<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">[root@iml11 ~]# crictl -h</span><br><span class="line">NAME:</span><br><span class="line"> crictl - client for CRI</span><br><span class="line"></span><br><span class="line">USAGE:</span><br><span class="line"> crictl [global options] command [command options] [arguments...]</span><br><span class="line"></span><br><span class="line">VERSION:</span><br><span class="line"> 1.11.0</span><br><span class="line"></span><br><span class="line">COMMANDS:</span><br><span class="line"> attach Attach to a running container</span><br><span class="line"> create Create a new container</span><br><span class="line"> exec Run a command in a running container</span><br><span class="line"> version Display runtime version information</span><br><span class="line"> images List images</span><br><span class="line"> inspect Display the status of one or more containers</span><br><span class="line"> inspecti Return the status of one or more images</span><br><span class="line"> inspectp Display the status of one or more pods</span><br><span class="line"> logs Fetch the logs of a container</span><br><span class="line"> port-forward Forward local port to a pod</span><br><span class="line"> ps List containers</span><br><span class="line"> pull Pull an image from a registry</span><br><span class="line"> runp Run a new pod</span><br><span class="line"> rm Remove one or more containers</span><br><span class="line"> rmi Remove one or more images</span><br><span class="line"> rmp Remove one or more pods</span><br><span class="line"> pods List pods</span><br><span class="line"> start Start one or more created containers</span><br><span class="line"> info Display information of the container runtime</span><br><span class="line"> stop Stop one or more running containers</span><br><span class="line"> stopp Stop one or more running pods</span><br><span class="line"> update Update one or more running containers</span><br><span class="line"> config Get and set crictl options</span><br><span class="line"> stats List container(s) resource usage statistics</span><br><span class="line"> completion Output bash shell completion code</span><br><span class="line"> help, h Shows a list of commands or help for one command</span><br><span class="line"></span><br><span class="line">GLOBAL OPTIONS:</span><br><span class="line"> --config value, -c value Location of the client config file (default: "/etc/crictl.yaml") [$CRI_CONFIG_FILE]</span><br><span class="line"> --debug, -D Enable debug mode</span><br><span class="line"> --image-endpoint value, -i value Endpoint of CRI image manager service [$IMAGE_SERVICE_ENDPOINT]</span><br><span class="line"> --runtime-endpoint value, -r value Endpoint of CRI container runtime service (default: "unix:///var/run/dockershim.sock") [$CONTAINER_RUNTIME_ENDPOINT]</span><br><span class="line"> --timeout value, -t value Timeout of connecting to the server (default: 10s)</span><br><span class="line"> --help, -h show help</span><br><span class="line"> --version, -v print the version</span><br><span class="line">[root@iml11 ~]#</span><br></pre></td></tr></table></figure></p><p><strong><a href="https://github.com/containernetworking/cni" target="_blank" rel="noopener">CNI: Container Network Interface</a></strong> is a <a href="https://www.cncf.io/" target="_blank" rel="noopener">Cloud Native Computing Foundation</a> project, consists of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins.</p><p>对于网络层,可以参考下面的第三方实现:</p><table><thead><tr><th>3rd plugins</th><th>More Information</th></tr></thead><tbody><tr><td>Calico</td><td>a layer 3 virtual network</td></tr><tr><td><strong>Weave</strong></td><td>a multi-host Docker network, default in kubernets</td></tr><tr><td>Contiv Networking</td><td>policy networking for various use cases</td></tr><tr><td>SR-IOV</td></tr><tr><td>Cilium</td><td>BPF & XDP for containers</td></tr><tr><td>Infoblox</td><td>enterprise IP address management for containers</td></tr><tr><td>Multus</td><td>a Multi plugin</td></tr><tr><td>Romana</td><td>Layer 3 CNI plugin supporting network policy for Kubernetes</td></tr><tr><td>CNI-Genie</td><td>generic CNI network plugin</td></tr><tr><td>Nuage CNI</td><td>Nuage Networks SDN plugin for network policy kubernetes support</td></tr><tr><td>Silk</td><td>a CNI plugin designed for Cloud Foundry</td></tr><tr><td>Linen</td><td>a CNI plugin designed for overlay networks with Open vSwitch and fit in SDN/OpenFlow network environment</td></tr><tr><td>Vhostuser</td><td>a Dataplane network plugin - Supports OVS-DPDK & VPP</td></tr><tr><td>Amazon ECS CNI Plugins</td><td>a collection of CNI Plugins to configure containers with Amazon EC2 elastic network interfaces (ENIs)</td></tr><tr><td>Bonding CNI</td><td>a Link aggregating plugin to address failover and high availability network</td></tr><tr><td>ovn-kubernetes</td><td>an container network plugin built on Open vSwitch (OVS) and Open Virtual Networking (OVN) with support for both Linux and Windows</td></tr><tr><td>Juniper Contrail / TungstenFabric</td><td>Provides overlay SDN solution, delivering multicloud networking, hybrid cloud networking, simultaneous overlay-underlay support, network policy enforcement, network isolation, service chaining and flexible load balancing</td></tr><tr><td>Knitter</td><td>a CNI plugin supporting multiple networking for Kubernetes</td></tr></tbody></table><p><strong><a href="https://github.com/container-storage-interface/spec/blob/master/spec.md" target="_blank" rel="noopener">CSI: Container Storage Interface</a></strong> will enable storage vendors (SP) to develop a plugin once and have it work across a number of container orchestration (CO) systems.</p><p>对于存储层,目前至少有以下的实现:</p><ul><li>Sample Drivers</li></ul><table><thead><tr><th>Name</th><th>More Information</th></tr></thead><tbody><tr><td>Flexvolume</td><td>Sample</td></tr><tr><td>HostPath</td><td>Only use for a single node tests. See the Example page for Kubernetes-specific instructions.</td></tr><tr><td>In-memory Sample Mock Driver</td><td>The sample mock driver used for csi-sanity</td></tr><tr><td>NFS</td><td>Sample</td></tr><tr><td>VFS Driver</td><td>A CSI plugin that provides a virtual file system.</td></tr></tbody></table><ul><li>Production Drivers</li></ul><table><thead><tr><th>Name</th><th>More Information</th></tr></thead><tbody><tr><td>Cinder</td><td>A Container Storage Interface (CSI) Storage Plug-in for Cinder</td></tr><tr><td>DigitalOcean Block Storage</td><td>A Container Storage Interface (CSI) Driver for DigitalOcean Block Storage</td></tr><tr><td>GCE Persistent Disk</td><td>A Container Storage Interface (CSI) Storage Plugin for Google Compute Engine Persistent Disk</td></tr><tr><td>OpenSDS</td><td>For more information, please visit releases and <a href="https://github.com/opensds/nbp/tree/master/csi" target="_blank" rel="noopener">https://github.com/opensds/nbp/tree/master/csi</a></td></tr><tr><td>Portworx</td><td>CSI implementation is available here which can be used as an example also.</td></tr><tr><td>RBD</td><td>A Container Storage Interface (CSI) Storage RBD Plug-in for Ceph</td></tr><tr><td>CephFS</td><td>A Container Storage Interface (CSI) Storage Plug-in for CephFS</td></tr><tr><td>ScaleIO</td><td>A Container Storage Interface (CSI) Storage Plugin for DellEMC ScaleIO</td></tr><tr><td>vSphere</td><td>A Container Storage Interface (CSI) Storage Plug-in for VMware vSphere</td></tr><tr><td>NetApp</td><td>A Container Storage Interface (CSI) Storage Plug-in for NetApp’s Trident container storage orchestrator</td></tr><tr><td>Ember CSI</td><td>Multi-vendor CSI plugin supporting over 80 storage drivers to provide block and mount storage to Container Orchestration systems.</td></tr><tr><td>Nutanix</td><td>A Container Storage Interface (CSI) Storage Driver for Nutanix</td></tr><tr><td>Quobyte</td><td>A Container Storage Interface (CSI) Plugin for Quobyte</td></tr></tbody></table><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to:"></a>Refer to:</h2><ul><li><a href="https://containerd.io" target="_blank" rel="noopener">https://containerd.io</a></li><li><a href="https://linuxcontainers.org/" target="_blank" rel="noopener">https://linuxcontainers.org/</a></li><li><a href="https://coreos.com/rkt/docs/latest/app-container.html" target="_blank" rel="noopener">https://coreos.com/rkt/docs/latest/app-container.html</a></li><li><a href="https://kubernetes-csi.github.io/docs/Drivers.html" target="_blank" rel="noopener">https://kubernetes-csi.github.io/docs/Drivers.html</a></li><li><a href="http://www.infoq.com/cn/news/2017/02/Docker-Containerd-RunC" target="_blank" rel="noopener">http://www.infoq.com/cn/news/2017/02/Docker-Containerd-RunC</a></li><li><a href="http://dockone.io/article/776" target="_blank" rel="noopener">http://dockone.io/article/776</a></li><li><a href="https://www.infoq.com/presentations/cri-runtime-kubernetes?utm_source=presentations_about_Containers&utm_medium=link&utm_campaign=Containers" target="_blank" rel="noopener">https://www.infoq.com/presentations/cri-runtime-kubernetes?utm_source=presentations_about_Containers&utm_medium=link&utm_campaign=Containers</a></li><li><a href="https://github.com/containernetworking/cni" target="_blank" rel="noopener">https://github.com/containernetworking/cni</a></li></ul>]]></content>
<summary type="html">
<p>没有规矩,不成方圆, 所有的事物都是有迹可循;在容器的世界里也不例外。现在,我们就从规范入手来简单的梳理一下docker, kubernets。</p>
<h2 id="开源容器的业界规范"><a href="#开源容器的业界规范" class="headerlink" t
</summary>
<category term="OCI" scheme="http://lu-liang.github.io/tags/OCI/"/>
<category term="Docker" scheme="http://lu-liang.github.io/tags/Docker/"/>
<category term="Kubernetes" scheme="http://lu-liang.github.io/tags/Kubernetes/"/>
</entry>
<entry>
<title>使用hexo, github搭建个人博客</title>
<link href="http://lu-liang.github.io/2018/09/28/hello-world/"/>
<id>http://lu-liang.github.io/2018/09/28/hello-world/</id>
<published>2018-09-28T01:26:20.000Z</published>
<updated>2018-09-28T01:26:20.000Z</updated>
<content type="html"><![CDATA[<p>This is my first post with Hexo/Github. Welcome to the new world! I hope you can easily get your owned blog ready with this post.</p><p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! To check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p><h2 id="Install-and-setup-hexo-for-your-blog"><a href="#Install-and-setup-hexo-for-your-blog" class="headerlink" title="Install and setup hexo for your blog"></a>Install and setup hexo for your blog</h2><h3 id="搭建系统使用的-npm-node-git-版本信息。"><a href="#搭建系统使用的-npm-node-git-版本信息。" class="headerlink" title="搭建系统使用的 npm, node, git 版本信息。"></a>搭建系统使用的 npm, node, git 版本信息。</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">➜ hexo git --version</span><br><span class="line">git version 2.10.2</span><br><span class="line">➜ hexo npm -v</span><br><span class="line">5.4.2</span><br><span class="line">➜ hexo node -v</span><br><span class="line">v8.8.1</span><br><span class="line">➜ hexo</span><br></pre></td></tr></table></figure><h3 id="Install-hexo-and-hexo-cli"><a href="#Install-hexo-and-hexo-cli" class="headerlink" title="Install hexo and hexo-cli"></a>Install hexo and hexo-cli</h3><p>全局安装hexo和hexo-cli<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">npm install -g hexo</span><br><span class="line">npm install -g hexo-cli</span><br></pre></td></tr></table></figure></p><h3 id="Initial-your-blog-with-hexo"><a href="#Initial-your-blog-with-hexo" class="headerlink" title="Initial your blog with hexo"></a>Initial your blog with hexo</h3><p>使用hexo初始化博客系统<br><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">cd hexo</span><br><span class="line">hexo init</span><br></pre></td></tr></table></figure></p><h3 id="Install-hexo-plugins"><a href="#Install-hexo-plugins" class="headerlink" title="Install hexo plugins"></a>Install hexo plugins</h3><p>Hexo 支持众多的插件。具体设置可以参考<a href="https://hexo.io/zh-cn/docs/deployment.html" target="_blank" rel="noopener">Hexo Deployment</a>。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"># install plugin for deployment</span><br><span class="line"></span><br><span class="line">npm install hexo-deployer-git --save</span><br><span class="line">npm install hexo-deployer-ftpsync --save</span><br><span class="line">npm install hexo-deployer-openshift --save</span><br><span class="line">npm install hexo-deployer-rsync --save</span><br><span class="line">npm install hexo-deployer-heroku --save</span><br><span class="line"></span><br><span class="line"># install plugin for render</span><br><span class="line"></span><br><span class="line">npm install hexo-renderer-marked --save</span><br><span class="line">npm install hexo-renderer-stylus --save</span><br><span class="line"></span><br><span class="line"># install plugin for generator</span><br><span class="line">npm install hexo-generator-index --save</span><br><span class="line">npm install hexo-generator-archive --save</span><br><span class="line">npm install hexo-generator-category --save</span><br><span class="line">npm install hexo-generator-tag --save</span><br><span class="line">npm install hexo-generator-feed --save</span><br><span class="line">npm install hexo-generator-sitemap --save</span><br><span class="line"></span><br><span class="line"># install server module</span><br><span class="line">npm install hexo-server --save</span><br><span class="line"></span><br><span class="line">npm install</span><br><span class="line"># the fix in the issue https://github.com/hexojs/hexo/issues/2682</span><br></pre></td></tr></table></figure><h3 id="Install-theme-and-enable-it"><a href="#Install-theme-and-enable-it" class="headerlink" title="Install theme and enable it"></a>Install theme and enable it</h3><p>Hexo缺省的主题是landscape。这里我们安装使用了另外一个主题Anisina。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">git clone https://github.com/Haojen/hexo-theme-Anisina.git themes/Anisina</span><br><span class="line">cp ./themes/Anisina/_config.yml .</span><br></pre></td></tr></table></figure><h3 id="Generate-static-documents-and-start-local-server-to-preview-them"><a href="#Generate-static-documents-and-start-local-server-to-preview-them" class="headerlink" title="Generate static documents and start local server to preview them."></a>Generate static documents and start local server to preview them.</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">hexo g</span><br><span class="line">hexo s</span><br></pre></td></tr></table></figure><h3 id="Deploy-to-github"><a href="#Deploy-to-github" class="headerlink" title="Deploy to github"></a>Deploy to github</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">hexo d</span><br></pre></td></tr></table></figure><h3 id="Hexo-short-commands"><a href="#Hexo-short-commands" class="headerlink" title="Hexo short commands"></a>Hexo short commands</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">hexo s == hexo server</span><br><span class="line">hexo g == hexo generate</span><br><span class="line">hexo d == hexo deploy</span><br><span class="line">hexo n == hexo new</span><br></pre></td></tr></table></figure><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/server.html" target="_blank" rel="noopener">Server</a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/generating.html" target="_blank" rel="noopener">Generating</a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><figure class="highlight bash"><table><tr><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure><p>More info: <a href="https://hexo.io/docs/deployment.html" target="_blank" rel="noopener">Deployment</a></p><h2 id="Refer-to"><a href="#Refer-to" class="headerlink" title="Refer to:"></a>Refer to:</h2><ul><li><a href="https://hexo.io/zh-cn/" target="_blank" rel="noopener">https://hexo.io/zh-cn/</a></li><li><a href="https://www.zhihu.com/question/20962496" target="_blank" rel="noopener">https://www.zhihu.com/question/20962496</a></li><li><a href="https://www.cnblogs.com/liuxianan/p/build-blog-website-by-hexo-github.html" target="_blank" rel="noopener">https://www.cnblogs.com/liuxianan/p/build-blog-website-by-hexo-github.html</a></li><li><a href="https://github.com/haojen/hexo-theme-Anisina" target="_blank" rel="noopener">https://github.com/haojen/hexo-theme-Anisina</a></li></ul>]]></content>
<summary type="html">
<p>This is my first post with Hexo/Github. Welcome to the new world! I hope you can easily get your owned blog ready with this post.</p>
<p>
</summary>
<category term="hexo" scheme="http://lu-liang.github.io/tags/hexo/"/>
</entry>
</feed>