SlideShare a Scribd company logo
Writing Docker
monitoring agent with Go
ainoya
About me
• Naoki Ainoya( ainoya)
• iOS(new!)/Server/Infra engineer
• Swift/Scala/Go/Docker
• Recruit Marketing Partners Co, Ltd.
A tiny deployment pipeline tool
Written in Go
walter-cd/walter
Open source project
Introduction of Fune
• An event emitter triggered by Docker Event API
• The agent process (fune-agent) communicates with docker
daemon via its socket
• https://github.com/ainoya/fune
Docker daemon
Funeagent
ConttainerA
ConttainerB
ConttainerC
Nginx/Redis
vulcand(etcd)
Slack notification etc..
Listens docker
events API
notifies each containers are
created/died/stopped/started
Emits pluggable
actions
Your
arbitrary docker ecosystem
ECS/k8s/fleet/etc..
Docker Host
Deploy containers
Overview of Fune
• Docker Events API provides a lifecycle of container
as JSON format
• create/start/die/stop
Overview of Fune
fune-agent listens these events
Docker daemon
Funeagent
ConttainerA
ConttainerB
ConttainerC
Listens docker
events API
notifies each containers are
created/died/stopped/started
Your
arbitrary docker ecosystem
ECS/k8s/fleet/etc..
Docker Host
Deploy containers
Overview of Fune
fune-agent emits Action

when received Docker events

from event
Docker daemon
Funeagent
ConttainerA
ConttainerB
Nginx/Redis
vulcand(etcd)
Slack notification etc..
Listens docker
events API
notifies each containers are
created/died/stopped/started
Emits pluggable
actions
Your
arbitrary docker ecosystem
ECS/k8s/fleet/etc..
Docker Host
Deploy containers
Overview of Fune
Docker daemon
Funeagent
ConttainerA
ConttainerB
Nginx/Redis
vulcand(etcd)
Slack notification etc..
Listens docker
events API
notifies each containers are
created/died/stopped/started
Emits pluggable
actions
Your
arbitrary docker ecosystem
ECS/k8s/fleet/etc..
Docker Host
Deploy containers
• Action, for example;
• Set/Del a container information to Redis as
FQDN/IP:Port pair for proxy
• Slack notification
• More details are next time :)
Today I talk about:
• Some tips I learned with writing fune
• Studied a lot of stuffs from coreos/etcd
Setup project
• Standard structure for 

working with Godeps correctly
• /src/github.com/ainoya/fune
./${GOPATH}/src
!"" 9fans.net
#   %"" go
!"" code.google.com
#   %"" p
!"" github.com
#   !"" ainoya/fune
#   !"" barakmich
#   !"" coreos etc...
Godeps for the package
dependencies
• Using Godeps once, all dependencies copied into
directory and rewrite import statement
• Then you need Godeps command only if package
dependency is added
import "github.com/fsouza/go-dockerclient"
// after `Godep save -r ./…`
import "github.com/ainoya/fune/Godeps/_workspace/
src/github.com/fsouza/go-dockerclient"
Godeps for the package
dependencies
• All dependencies are included in git repos
• But it makes dirty commit log!!
• Keep off its dirtiness by split commits :)
How about vendor feature in
go1.5?
• go1.5 vendor feature have some problems yet
• ex) go	
  tool	
  "./…" doesn't works well
• https://github.com/golang/go/issues/11659
• See also ) http://deeeet.com/writing/2015/06/26/golang-dependency-
vendoring/
Write tests
• Rerun automatically if files are changed
• rerun is awesome! (but ruby tool gem)
rerun -x -c -d directory1, directory2,...
—pattern '**/*.{go}' -- go test ./...
Be careful about race condition
• Test with "-­‐race" option if you often use goroutine in your code
• "-­‐cpu	
  N" option may reveal race condition you didn't expected
• I use "go	
  test	
  ./…	
  -­‐race	
  -­‐cpu	
  1,2,4" inside test script
WARNING: DATA RACE
Write by goroutine 8:
sync.raceWrite()
/usr/local/Cellar/go/1.5/libexec/src/sync/race.go:41 +0x2e
sync.(*WaitGroup).Wait()
/usr/local/Cellar/go/1.5/libexec/src/sync/waitgroup.go:124 +0xf9
github.com/ainoya/fune/emitter.TestBroadCast()
/Users/ainoya/.go/src/github.com/ainoya/fune/gopath/src/github.com/
ainoya/fune/emitter/emitter_test.go:57 +0x444
testing.tRunner()
/usr/local/Cellar/go/1.5/libexec/src/testing/testing.go:456 +0xdc
Is Go1.5 compilation time
slower than 1.4?
• "go	
  test" obviously takes time much longer
• It's probably because of GoGo compiler
performance

Ref) Performance section of https://golang.org/doc/go1.5
• It should be improved with Go1.6
Channel tips
• coreos/etcd implements a shutdown feature with
using close(channel)
type	
  Server	
  struct	
  {	
  
	
   name	
  	
  	
  	
  string	
  
	
   channel	
  chan	
  struct{}	
  
	
   done	
  	
  	
  	
  chan	
  struct{}	
  
	
   stop	
  	
  	
  	
  chan	
  struct{}	
  
}	
  
func	
  main()	
  {	
  
	
   done	
  :=	
  make(chan	
  struct{})	
  
	
   stop	
  :=	
  make(chan	
  struct{})	
  
	
   s	
  :=	
  &Server{done:	
  done,	
  stop:	
  stop,	
  
hoge:	
  hoge}	
  
	
   go	
  s.run()	
  
	
   s.channel	
  <-­‐	
  struct{}{}	
  
	
   osutil.RegisterInterrputHandler(s.Stop)	
  
	
   <-­‐s.done	
  
}
func	
  (s	
  *Server)	
  run()	
  {	
  
	
   defer	
  func()	
  {	
  close(s.done)	
  }()	
  
	
   for	
  {	
  
	
   	
   select	
  {	
  
	
   	
   case	
  <-­‐s.channel:	
  
	
   	
   	
   fmt.Println("do	
  something")	
  
	
   	
   case	
  <-­‐s.stop:	
  
	
   	
   	
   return	
  
	
   	
   }	
  
	
   }	
  
}	
  
func	
  (s	
  *S)	
  Stop()	
  {	
  
	
   select	
  {	
  
	
   case	
  s.stop	
  <-­‐	
  struct{}{}:	
  
	
   case	
  <-­‐s.done:	
  
	
   	
   return	
  
	
   }	
  
	
   <-­‐s.done	
  
}	
  
Channel tips
• coreos/etcd implements a shutdown feature with
using close(channel)
type	
  Server	
  struct	
  {	
  
	
   name	
  	
  	
  	
  string	
  
	
   channel	
  chan	
  struct{}	
  
	
   done	
  	
  	
  	
  chan	
  struct{}	
  
	
   stop	
  	
  	
  	
  chan	
  struct{}	
  
}	
  
func	
  main()	
  {	
  
	
   done	
  :=	
  make(chan	
  struct{})	
  
	
   stop	
  :=	
  make(chan	
  struct{})	
  
	
   s	
  :=	
  &Server{done:	
  done,	
  stop:	
  stop,	
  
hoge:	
  hoge}	
  
	
   go	
  s.run()	
  
	
   s.channel	
  <-­‐	
  struct{}{}	
  
	
   osutil.RegisterInterrputHandler(s.Stop)	
  
	
   <-­‐s.done	
  
}
func	
  (s	
  *Server)	
  run()	
  {	
  
	
   defer	
  func()	
  {	
  close(s.done)	
  }()	
  
	
   for	
  {	
  
	
   	
   select	
  {	
  
	
   	
   case	
  <-­‐s.channel:	
  
	
   	
   	
   fmt.Println("do	
  something")	
  
	
   	
   case	
  <-­‐s.stop:	
  
	
   	
   	
   return	
  
	
   	
   }	
  
	
   }	
  
}	
  
func	
  (s	
  *S)	
  Stop()	
  {	
  
	
   select	
  {	
  
	
   case	
  s.stop	
  <-­‐	
  struct{}{}:	
  
	
   case	
  <-­‐s.done:	
  
	
   	
   return	
  
	
   }	
  
	
   <-­‐s.done	
  
}	
  
Channel tips
• coreos/etcd implements a shutdown feature with
using close(channel)
type	
  Server	
  struct	
  {	
  
	
   name	
  	
  	
  	
  string	
  
	
   channel	
  chan	
  struct{}	
  
	
   done	
  	
  	
  	
  chan	
  struct{}	
  
	
   stop	
  	
  	
  	
  chan	
  struct{}	
  
}	
  
func	
  main()	
  {	
  
	
   done	
  :=	
  make(chan	
  struct{})	
  
	
   stop	
  :=	
  make(chan	
  struct{})	
  
	
   s	
  :=	
  &Server{done:	
  done,	
  stop:	
  stop,	
  
hoge:	
  hoge}	
  
	
   go	
  s.run()	
  
	
   s.channel	
  <-­‐	
  struct{}{}	
  
	
   osutil.RegisterInterrputHandler(s.stop)	
  
	
   <-­‐s.done	
  
}
func	
  (s	
  *Server)	
  run()	
  {	
  
	
   defer	
  func()	
  {	
  close(s.done)	
  }()	
  
	
   for	
  {	
  
	
   	
   select	
  {	
  
	
   	
   case	
  <-­‐s.channel:	
  
	
   	
   	
   fmt.Println("do	
  something")	
  
	
   	
   case	
  <-­‐s.stop:	
  
	
   	
   	
   return	
  
	
   	
   }	
  
	
   }	
  
}	
  
func	
  (s	
  *S)	
  Stop()	
  {	
  
	
   select	
  {	
  
	
   case	
  s.stop	
  <-­‐	
  struct{}{}:	
  
	
   case	
  <-­‐s.done:	
  
	
   	
   return	
  
	
   }	
  
	
   <-­‐s.done	
  
}	
  
Channel tips
• coreos/etcd implements a shutdown feature with
using close(channel)
type	
  Server	
  struct	
  {	
  
	
   name	
  	
  	
  	
  string	
  
	
   channel	
  chan	
  struct{}	
  
	
   done	
  	
  	
  	
  chan	
  struct{}	
  
	
   stop	
  	
  	
  	
  chan	
  struct{}	
  
}	
  
func	
  main()	
  {	
  
	
   done	
  :=	
  make(chan	
  struct{})	
  
	
   stop	
  :=	
  make(chan	
  struct{})	
  
	
   s	
  :=	
  &Server{done:	
  done,	
  stop:	
  stop,	
  
hoge:	
  hoge}	
  
	
   go	
  s.run()	
  
	
   s.channel	
  <-­‐	
  struct{}{}	
  
	
   osutil.RegisterInterrputHandler(s.Stop)	
  
	
   <-­‐s.done	
  
}
func	
  (s	
  *Server)	
  run()	
  {	
  
	
   defer	
  func()	
  {	
  close(s.done)	
  }()	
  
	
   for	
  {	
  
	
   	
   select	
  {	
  
	
   	
   case	
  <-­‐s.channel:	
  
	
   	
   	
   fmt.Println("do	
  something")	
  
	
   	
   case	
  <-­‐s.stop:	
  
	
   	
   	
   return	
  
	
   	
   }	
  
	
   }	
  
}	
  
func	
  (s	
  *S)	
  Stop()	
  {	
  
	
   select	
  {	
  
	
   case	
  s.stop	
  <-­‐	
  struct{}{}:	
  
	
   case	
  <-­‐s.done:	
  
	
   	
   return	
  
	
   }	
  
	
   <-­‐s.done	
  
}	
  
Channel tips
• coreos/etcd implements a shutdown feature with
using close(channel)
type	
  Server	
  struct	
  {	
  
	
   name	
  	
  	
  	
  string	
  
	
   channel	
  chan	
  struct{}	
  
	
   done	
  	
  	
  	
  chan	
  struct{}	
  
	
   stop	
  	
  	
  	
  chan	
  struct{}	
  
}	
  
func	
  main()	
  {	
  
	
   done	
  :=	
  make(chan	
  struct{})	
  
	
   stop	
  :=	
  make(chan	
  struct{})	
  
	
   s	
  :=	
  &Server{done:	
  done,	
  stop:	
  stop,	
  
hoge:	
  hoge}	
  
	
   go	
  s.run()	
  
	
   s.channel	
  <-­‐	
  struct{}{}	
  
	
   osutil.RegisterInterrputHandler(s.Stop)	
  
	
   <-­‐s.done	
  
}
func	
  (s	
  *Server)	
  run()	
  {	
  
	
   defer	
  func()	
  {	
  close(s.done)	
  }()	
  
	
   for	
  {	
  
	
   	
   select	
  {	
  
	
   	
   case	
  <-­‐s.channel:	
  
	
   	
   	
   fmt.Println("do	
  something")	
  
	
   	
   case	
  <-­‐s.stop:	
  
	
   	
   	
   return	
  
	
   	
   }	
  
	
   }	
  
}	
  
func	
  (s	
  *S)	
  Stop()	
  {	
  
	
   select	
  {	
  
	
   case	
  s.stop	
  <-­‐	
  struct{}{}:	
  
	
   case	
  <-­‐s.done:	
  
	
   	
   return	
  
	
   }	
  
	
   <-­‐s.done	
  
}	
  
Test goroutine easily
"s.done" channel makes testing goroutine easily
//	
  https://github.com/coreos/etcd/blob/master/etcdserver/
server_test.go#L1031	
  
//	
  TestPublishRetry	
  tests	
  that	
  publish	
  will	
  keep	
  retry	
  until	
  success.	
  
func	
  TestPublishRetry(t	
  *testing.T)	
  {	
  
	
   n	
  :=	
  &nodeRecorder{}	
  
	
   srv	
  :=	
  &EtcdServer{	
  
	
   	
   cfg:	
  	
  	
  	
  	
  	
  &ServerConfig{TickMs:	
  1},	
  
	
   	
   r:	
  	
  	
  	
  	
  	
  	
  	
  raftNode{Node:	
  n},	
  
	
   	
   w:	
  	
  	
  	
  	
  	
  	
  	
  &waitRecorder{},	
  
	
   	
   done:	
  	
  	
  	
  	
  make(chan	
  struct{}),	
  
	
   	
   reqIDGen:	
  idutil.NewGenerator(0,	
  time.Time{}),	
  
	
   }	
  
	
   time.AfterFunc(500*time.Microsecond,	
  func()	
  {	
  close(srv.done)	
  })	
  
	
   srv.publish(10	
  *	
  time.Nanosecond)	
  
Run go as Docker container
• Go single binary with "SCRATCH"
• You can run a go stuff inside extremely simple container!
FROM	
  scratch	
  
EXPOSE	
  8080	
  
COPY	
  your-­‐golang-­‐app	
  /app/your-­‐golang-­‐app	
  
ENV	
  PATH=/app:$PATH	
  
ENTRYPOINT	
  ["/app/your-­‐golang-­‐app"]	
  
CMD	
  ["-­‐some-­‐option=haha"]
Round up
• Learned a lot of stuffs from well-knowned products
(coreos/etcd)
• project structure, test, golang-way
See you next kyobashi.*!
• 9/7: kyobashi.dex
• 9/16: potatotips
• ???: kyobashi.???

More Related Content

PDF
Flamingo Training - Hello World
PDF
Goroutines and Channels in practice
PDF
Deconstructing the Functional Web with Clojure
PDF
Introduction to kotlin coroutines
PDF
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
PDF
The Ring programming language version 1.9 book - Part 101 of 210
PDF
Ruby 1.9
PDF
Kotlin Coroutines. Flow is coming
Flamingo Training - Hello World
Goroutines and Channels in practice
Deconstructing the Functional Web with Clojure
Introduction to kotlin coroutines
200819 NAVER TECH CONCERT 03_화려한 코루틴이 내 앱을 감싸네! 코루틴으로 작성해보는 깔끔한 비동기 코드
The Ring programming language version 1.9 book - Part 101 of 210
Ruby 1.9
Kotlin Coroutines. Flow is coming

What's hot (20)

PDF
Utilizing Powerful Extensions for Analytics and Operations
PDF
Higher Order Components and Render Props
PDF
GeeCON 2014 - Functional Programming without Lambdas
PDF
Java/Scala Lab: Руслан Шевченко - Implementation of CSP (Communication Sequen...
PDF
High Performance tDiary
PDF
lldb – Debugger auf Abwegen
PDF
Writing Go(od) Tests (FOSDEM 2020)
PDF
Common mistakes functional java vjug
PDF
Common mistakes functional java | Oracle Code One 2018
PDF
Transducers in JavaScript
PDF
Scu scsi-summary
PDF
Elixir @ Paris.rb
PDF
Flux and InfluxDB 2.0
PDF
Ten common mistakes made with Functional Java JBCNConf18
PPTX
DevOps with Fabric
TXT
Adb instructions
PPTX
JavaScript Event Loop
PPTX
Lua: the world's most infuriating language
PDF
Async data pipelines for client-side JavaScript
PDF
Os Fetterupdated
Utilizing Powerful Extensions for Analytics and Operations
Higher Order Components and Render Props
GeeCON 2014 - Functional Programming without Lambdas
Java/Scala Lab: Руслан Шевченко - Implementation of CSP (Communication Sequen...
High Performance tDiary
lldb – Debugger auf Abwegen
Writing Go(od) Tests (FOSDEM 2020)
Common mistakes functional java vjug
Common mistakes functional java | Oracle Code One 2018
Transducers in JavaScript
Scu scsi-summary
Elixir @ Paris.rb
Flux and InfluxDB 2.0
Ten common mistakes made with Functional Java JBCNConf18
DevOps with Fabric
Adb instructions
JavaScript Event Loop
Lua: the world's most infuriating language
Async data pipelines for client-side JavaScript
Os Fetterupdated
Ad

Viewers also liked (20)

PDF
このあと滅茶苦茶LGTMした
PDF
PDF
Performance Monitoring for Docker Environments - Docker Amsterdam June Meetup
PPTX
Gobotについて
PPTX
Discussing the difference between docker dontainers and virtual machines
ODP
Nagios Conference 2014 - Spenser Reinhardt - Detecting Security Breaches With...
PPTX
Running Netflix OSS on Docker with Nirmata
PPTX
Docker Indy Meetup Monitoring 30-Aug-2016
PDF
Netflix and Containers: Not A Stranger Thing
PDF
Microservices with Netflix OSS and Spring Cloud - Dev Day Orange
PDF
NetflixOSS and ZeroToDocker Talk
PDF
Microservices with Spring Cloud, Netflix OSS and Kubernetes
PDF
Microservices and APIs
PPTX
Real world #microservices with Apache Camel, Fabric8, and OpenShift
PDF
Goだけでモバイルアプリを作る
PPTX
Overseeing Ship's Surveys and Surveyors Globally Using IoT and Docker by Jay ...
PPTX
Learning the Alphabet: A/B, CD and [E-Z] in the Docker Datacenter by Brett Ti...
PDF
Securing the Container Pipeline at Salesforce by Cem Gurkok
PDF
Docker in Production, Look No Hands! by Scott Coulton
PDF
Build Fast, Deploy Fast: Innovating in the Enterprise by Imran Raja and Andy Lim
このあと滅茶苦茶LGTMした
Performance Monitoring for Docker Environments - Docker Amsterdam June Meetup
Gobotについて
Discussing the difference between docker dontainers and virtual machines
Nagios Conference 2014 - Spenser Reinhardt - Detecting Security Breaches With...
Running Netflix OSS on Docker with Nirmata
Docker Indy Meetup Monitoring 30-Aug-2016
Netflix and Containers: Not A Stranger Thing
Microservices with Netflix OSS and Spring Cloud - Dev Day Orange
NetflixOSS and ZeroToDocker Talk
Microservices with Spring Cloud, Netflix OSS and Kubernetes
Microservices and APIs
Real world #microservices with Apache Camel, Fabric8, and OpenShift
Goだけでモバイルアプリを作る
Overseeing Ship's Surveys and Surveyors Globally Using IoT and Docker by Jay ...
Learning the Alphabet: A/B, CD and [E-Z] in the Docker Datacenter by Brett Ti...
Securing the Container Pipeline at Salesforce by Cem Gurkok
Docker in Production, Look No Hands! by Scott Coulton
Build Fast, Deploy Fast: Innovating in the Enterprise by Imran Raja and Andy Lim
Ad

Similar to Writing Docker monitoring agent with Go (20)

PDF
Job Queue in Golang
PPTX
Go Concurrency Patterns
PDF
用 Go 語言打造多台機器 Scale 架構
PDF
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
PDF
こわくないよ❤️ Playframeworkソースコードリーディング入門
KEY
Railsconf2011 deployment tips_for_slideshare
PDF
A deep dive into PEP-3156 and the new asyncio module
PDF
Brad Wood - CommandBox CLI
PDF
Using zone.js
PPTX
Beyond parallelize and collect - Spark Summit East 2016
PPTX
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
PDF
scala-gopher: async implementation of CSP for scala
KEY
Beauty and Power of Go
PDF
ClojureScript loves React, DomCode May 26 2015
PDF
Lego: A brick system build by scala
PPT
Concurrency in go
PDF
Reitit - Clojure/North 2019
PDF
Building a High-Performance Database with Scala, Akka, and Spark
PDF
PDF
Go Web Development
Job Queue in Golang
Go Concurrency Patterns
用 Go 語言打造多台機器 Scale 架構
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
こわくないよ❤️ Playframeworkソースコードリーディング入門
Railsconf2011 deployment tips_for_slideshare
A deep dive into PEP-3156 and the new asyncio module
Brad Wood - CommandBox CLI
Using zone.js
Beyond parallelize and collect - Spark Summit East 2016
NDC Sydney 2019 - Async Demystified -- Karel Zikmund
scala-gopher: async implementation of CSP for scala
Beauty and Power of Go
ClojureScript loves React, DomCode May 26 2015
Lego: A brick system build by scala
Concurrency in go
Reitit - Clojure/North 2019
Building a High-Performance Database with Scala, Akka, and Spark
Go Web Development

Recently uploaded (20)

PDF
How to Migrate SBCGlobal Email to Yahoo Easily
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
history of c programming in notes for students .pptx
PDF
Understanding Forklifts - TECH EHS Solution
PDF
AI in Product Development-omnex systems
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
Introduction to Artificial Intelligence
PPTX
Essential Infomation Tech presentation.pptx
PPTX
Transform Your Business with a Software ERP System
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
ai tools demonstartion for schools and inter college
PPTX
CHAPTER 2 - PM Management and IT Context
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PPTX
L1 - Introduction to python Backend.pptx
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
How to Migrate SBCGlobal Email to Yahoo Easily
Which alternative to Crystal Reports is best for small or large businesses.pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design
history of c programming in notes for students .pptx
Understanding Forklifts - TECH EHS Solution
AI in Product Development-omnex systems
Internet Downloader Manager (IDM) Crack 6.42 Build 41
Introduction to Artificial Intelligence
Essential Infomation Tech presentation.pptx
Transform Your Business with a Software ERP System
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
Odoo Companies in India – Driving Business Transformation.pdf
ai tools demonstartion for schools and inter college
CHAPTER 2 - PM Management and IT Context
VVF-Customer-Presentation2025-Ver1.9.pptx
SAP S4 Hana Brochure 3 (PTS SYSTEMS AND SOLUTIONS)
Upgrade and Innovation Strategies for SAP ERP Customers
L1 - Introduction to python Backend.pptx
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises

Writing Docker monitoring agent with Go

  • 2. About me • Naoki Ainoya( ainoya) • iOS(new!)/Server/Infra engineer • Swift/Scala/Go/Docker • Recruit Marketing Partners Co, Ltd.
  • 3. A tiny deployment pipeline tool Written in Go walter-cd/walter Open source project
  • 4. Introduction of Fune • An event emitter triggered by Docker Event API • The agent process (fune-agent) communicates with docker daemon via its socket • https://github.com/ainoya/fune Docker daemon Funeagent ConttainerA ConttainerB ConttainerC Nginx/Redis vulcand(etcd) Slack notification etc.. Listens docker events API notifies each containers are created/died/stopped/started Emits pluggable actions Your arbitrary docker ecosystem ECS/k8s/fleet/etc.. Docker Host Deploy containers
  • 5. Overview of Fune • Docker Events API provides a lifecycle of container as JSON format • create/start/die/stop
  • 6. Overview of Fune fune-agent listens these events Docker daemon Funeagent ConttainerA ConttainerB ConttainerC Listens docker events API notifies each containers are created/died/stopped/started Your arbitrary docker ecosystem ECS/k8s/fleet/etc.. Docker Host Deploy containers
  • 7. Overview of Fune fune-agent emits Action
 when received Docker events
 from event Docker daemon Funeagent ConttainerA ConttainerB Nginx/Redis vulcand(etcd) Slack notification etc.. Listens docker events API notifies each containers are created/died/stopped/started Emits pluggable actions Your arbitrary docker ecosystem ECS/k8s/fleet/etc.. Docker Host Deploy containers
  • 8. Overview of Fune Docker daemon Funeagent ConttainerA ConttainerB Nginx/Redis vulcand(etcd) Slack notification etc.. Listens docker events API notifies each containers are created/died/stopped/started Emits pluggable actions Your arbitrary docker ecosystem ECS/k8s/fleet/etc.. Docker Host Deploy containers • Action, for example; • Set/Del a container information to Redis as FQDN/IP:Port pair for proxy • Slack notification • More details are next time :)
  • 9. Today I talk about: • Some tips I learned with writing fune • Studied a lot of stuffs from coreos/etcd
  • 10. Setup project • Standard structure for 
 working with Godeps correctly • /src/github.com/ainoya/fune ./${GOPATH}/src !"" 9fans.net #   %"" go !"" code.google.com #   %"" p !"" github.com #   !"" ainoya/fune #   !"" barakmich #   !"" coreos etc...
  • 11. Godeps for the package dependencies • Using Godeps once, all dependencies copied into directory and rewrite import statement • Then you need Godeps command only if package dependency is added import "github.com/fsouza/go-dockerclient" // after `Godep save -r ./…` import "github.com/ainoya/fune/Godeps/_workspace/ src/github.com/fsouza/go-dockerclient"
  • 12. Godeps for the package dependencies • All dependencies are included in git repos • But it makes dirty commit log!! • Keep off its dirtiness by split commits :)
  • 13. How about vendor feature in go1.5? • go1.5 vendor feature have some problems yet • ex) go  tool  "./…" doesn't works well • https://github.com/golang/go/issues/11659 • See also ) http://deeeet.com/writing/2015/06/26/golang-dependency- vendoring/
  • 14. Write tests • Rerun automatically if files are changed • rerun is awesome! (but ruby tool gem) rerun -x -c -d directory1, directory2,... —pattern '**/*.{go}' -- go test ./...
  • 15. Be careful about race condition • Test with "-­‐race" option if you often use goroutine in your code • "-­‐cpu  N" option may reveal race condition you didn't expected • I use "go  test  ./…  -­‐race  -­‐cpu  1,2,4" inside test script WARNING: DATA RACE Write by goroutine 8: sync.raceWrite() /usr/local/Cellar/go/1.5/libexec/src/sync/race.go:41 +0x2e sync.(*WaitGroup).Wait() /usr/local/Cellar/go/1.5/libexec/src/sync/waitgroup.go:124 +0xf9 github.com/ainoya/fune/emitter.TestBroadCast() /Users/ainoya/.go/src/github.com/ainoya/fune/gopath/src/github.com/ ainoya/fune/emitter/emitter_test.go:57 +0x444 testing.tRunner() /usr/local/Cellar/go/1.5/libexec/src/testing/testing.go:456 +0xdc
  • 16. Is Go1.5 compilation time slower than 1.4? • "go  test" obviously takes time much longer • It's probably because of GoGo compiler performance
 Ref) Performance section of https://golang.org/doc/go1.5 • It should be improved with Go1.6
  • 17. Channel tips • coreos/etcd implements a shutdown feature with using close(channel) type  Server  struct  {     name        string     channel  chan  struct{}     done        chan  struct{}     stop        chan  struct{}   }   func  main()  {     done  :=  make(chan  struct{})     stop  :=  make(chan  struct{})     s  :=  &Server{done:  done,  stop:  stop,   hoge:  hoge}     go  s.run()     s.channel  <-­‐  struct{}{}     osutil.RegisterInterrputHandler(s.Stop)     <-­‐s.done   } func  (s  *Server)  run()  {     defer  func()  {  close(s.done)  }()     for  {       select  {       case  <-­‐s.channel:         fmt.Println("do  something")       case  <-­‐s.stop:         return       }     }   }   func  (s  *S)  Stop()  {     select  {     case  s.stop  <-­‐  struct{}{}:     case  <-­‐s.done:       return     }     <-­‐s.done   }  
  • 18. Channel tips • coreos/etcd implements a shutdown feature with using close(channel) type  Server  struct  {     name        string     channel  chan  struct{}     done        chan  struct{}     stop        chan  struct{}   }   func  main()  {     done  :=  make(chan  struct{})     stop  :=  make(chan  struct{})     s  :=  &Server{done:  done,  stop:  stop,   hoge:  hoge}     go  s.run()     s.channel  <-­‐  struct{}{}     osutil.RegisterInterrputHandler(s.Stop)     <-­‐s.done   } func  (s  *Server)  run()  {     defer  func()  {  close(s.done)  }()     for  {       select  {       case  <-­‐s.channel:         fmt.Println("do  something")       case  <-­‐s.stop:         return       }     }   }   func  (s  *S)  Stop()  {     select  {     case  s.stop  <-­‐  struct{}{}:     case  <-­‐s.done:       return     }     <-­‐s.done   }  
  • 19. Channel tips • coreos/etcd implements a shutdown feature with using close(channel) type  Server  struct  {     name        string     channel  chan  struct{}     done        chan  struct{}     stop        chan  struct{}   }   func  main()  {     done  :=  make(chan  struct{})     stop  :=  make(chan  struct{})     s  :=  &Server{done:  done,  stop:  stop,   hoge:  hoge}     go  s.run()     s.channel  <-­‐  struct{}{}     osutil.RegisterInterrputHandler(s.stop)     <-­‐s.done   } func  (s  *Server)  run()  {     defer  func()  {  close(s.done)  }()     for  {       select  {       case  <-­‐s.channel:         fmt.Println("do  something")       case  <-­‐s.stop:         return       }     }   }   func  (s  *S)  Stop()  {     select  {     case  s.stop  <-­‐  struct{}{}:     case  <-­‐s.done:       return     }     <-­‐s.done   }  
  • 20. Channel tips • coreos/etcd implements a shutdown feature with using close(channel) type  Server  struct  {     name        string     channel  chan  struct{}     done        chan  struct{}     stop        chan  struct{}   }   func  main()  {     done  :=  make(chan  struct{})     stop  :=  make(chan  struct{})     s  :=  &Server{done:  done,  stop:  stop,   hoge:  hoge}     go  s.run()     s.channel  <-­‐  struct{}{}     osutil.RegisterInterrputHandler(s.Stop)     <-­‐s.done   } func  (s  *Server)  run()  {     defer  func()  {  close(s.done)  }()     for  {       select  {       case  <-­‐s.channel:         fmt.Println("do  something")       case  <-­‐s.stop:         return       }     }   }   func  (s  *S)  Stop()  {     select  {     case  s.stop  <-­‐  struct{}{}:     case  <-­‐s.done:       return     }     <-­‐s.done   }  
  • 21. Channel tips • coreos/etcd implements a shutdown feature with using close(channel) type  Server  struct  {     name        string     channel  chan  struct{}     done        chan  struct{}     stop        chan  struct{}   }   func  main()  {     done  :=  make(chan  struct{})     stop  :=  make(chan  struct{})     s  :=  &Server{done:  done,  stop:  stop,   hoge:  hoge}     go  s.run()     s.channel  <-­‐  struct{}{}     osutil.RegisterInterrputHandler(s.Stop)     <-­‐s.done   } func  (s  *Server)  run()  {     defer  func()  {  close(s.done)  }()     for  {       select  {       case  <-­‐s.channel:         fmt.Println("do  something")       case  <-­‐s.stop:         return       }     }   }   func  (s  *S)  Stop()  {     select  {     case  s.stop  <-­‐  struct{}{}:     case  <-­‐s.done:       return     }     <-­‐s.done   }  
  • 22. Test goroutine easily "s.done" channel makes testing goroutine easily //  https://github.com/coreos/etcd/blob/master/etcdserver/ server_test.go#L1031   //  TestPublishRetry  tests  that  publish  will  keep  retry  until  success.   func  TestPublishRetry(t  *testing.T)  {     n  :=  &nodeRecorder{}     srv  :=  &EtcdServer{       cfg:            &ServerConfig{TickMs:  1},       r:                raftNode{Node:  n},       w:                &waitRecorder{},       done:          make(chan  struct{}),       reqIDGen:  idutil.NewGenerator(0,  time.Time{}),     }     time.AfterFunc(500*time.Microsecond,  func()  {  close(srv.done)  })     srv.publish(10  *  time.Nanosecond)  
  • 23. Run go as Docker container • Go single binary with "SCRATCH" • You can run a go stuff inside extremely simple container! FROM  scratch   EXPOSE  8080   COPY  your-­‐golang-­‐app  /app/your-­‐golang-­‐app   ENV  PATH=/app:$PATH   ENTRYPOINT  ["/app/your-­‐golang-­‐app"]   CMD  ["-­‐some-­‐option=haha"]
  • 24. Round up • Learned a lot of stuffs from well-knowned products (coreos/etcd) • project structure, test, golang-way
  • 25. See you next kyobashi.*! • 9/7: kyobashi.dex • 9/16: potatotips • ???: kyobashi.???