in Small Business Environments ( at Belgian scale: 5-150 employees ) Followed the Jedi path and turned to the bright side of life after 2005 Ansible since +/- 18 months No experience with other cfgmgmt tools First upstream commit c o m m i t d a 9 2 c e 7 9 6 b 4 8 e c 8 0 e 3 e a d 1 c f e 9 b c b c 7 1 f 5 f c e 8 0 5 A u t h o r S e r g e v a n G i n d e r a c h t e r D a t e W e d O c t 1 0 1 9 : 3 8 : 3 0 2 0 1 2 + 0 2 0 0 f i x m i s s i n g - - l i m i t i n d o c s s i t e e x a m p l e s
of Belgium http://www.milieuinfo.be: about environmental things Open Source island within the Flemish Government Enterprise upcoming stuff: "cloud" built on Ceph storage and Cloudstack Ansible since Summer 2012
s r c / a n s i b l e / l i b / a n s i b l e $ l s i n v e n t o r y / d i r . p y e x p a n d _ h o s t s . p y g r o u p . p y h o s t . p y i n i . p y _ _ i n i t _ _ . p y s c r i p t . p y v a r s _ p l u g i n s
p a t h . e x i s t s ( h o s t _ l i s t ) : 9 7 i f o s . p a t h . i s d i r ( h o s t _ l i s t ) : 9 8 # E n s u r e b a s e d i r i s i n s i d e t h e d i r e c t o r y 9 9 s e l f . h o s t _ l i s t = o s . p a t h . j o i n ( s e l f . h o s t _ l i s t , " " ) 1 0 0 s e l f . p a r s e r = I n v e n t o r y D i r e c t o r y ( f i l e n a m e = h o s t _ l i s t ) 1 0 1 s e l f . g r o u p s = s e l f . p a r s e r . g r o u p s . v a l u e s ( ) 1 0 2 e l i f u t i l s . i s _ e x e c u t a b l e ( h o s t _ l i s t ) : 1 0 3 s e l f . p a r s e r = I n v e n t o r y S c r i p t ( f i l e n a m e = h o s t _ l i s t ) 1 0 4 s e l f . g r o u p s = s e l f . p a r s e r . g r o u p s . v a l u e s ( ) 1 0 5 e l s e : 1 0 6 s e l f . p a r s e r = I n v e n t o r y P a r s e r ( f i l e n a m e = h o s t _ l i s t ) 1 0 7 s e l f . g r o u p s = s e l f . p a r s e r . g r o u p s . v a l u e s ( ) 1 0 8 1 0 9 u t i l s . p l u g i n s . v a r s _ l o a d e r . a d d _ d i r e c t o r y ( s e l f . b a s e d i r ( ) , w i t h _ s u b d i r = T r u e )
t h . i s d i r ( f u l l p a t h ) : 5 9 p a r s e r = I n v e n t o r y D i r e c t o r y ( f i l e n a m e = f u l l p a t h ) 6 0 e l i f u t i l s . i s _ e x e c u t a b l e ( f u l l p a t h ) : 6 1 p a r s e r = I n v e n t o r y S c r i p t ( f i l e n a m e = f u l l p a t h ) 6 2 e l s e : 6 3 p a r s e r = I n v e n t o r y P a r s e r ( f i l e n a m e = f u l l p a t h ) 6 4 s e l f . p a r s e r s . a p p e n d ( p a r s e r )
e d e f a u l t a n s i b l e ' h o s t s ' f i l e . # U n g r o u p e d h o s t s , s p e c i f y b e f o r e a n y g r o u p h e a d e r s . g r e e n . e x a m p l e . c o m b l u e . e x a m p l e . c o m 1 9 2 . 1 6 8 . 1 0 0 . 1 1 9 2 . 1 6 8 . 1 0 0 . 1 0 # A c o l l e c t i o n o f h o s t s b e l o n g i n g t o t h e ' w e b s e r v e r s ' g r o u p [ w e b s e r v e r s ] a l p h a . e x a m p l e . o r g b e t a . e x a m p l e . o r g 1 9 2 . 1 6 8 . 1 . 1 0 0 1 9 2 . 1 6 8 . 1 . 1 1 0 # A c o l l e c t i o n o f d a t a b a s e s e r v e r s i n t h e ' d b s e r v e r s ' g r o u p [ d b s e r v e r s ] d b 0 1 . i n t r a n e t . m y d o m a i n . n e t d b 0 2 . i n t r a n e t . m y d o m a i n . n e t 1 0 . 2 5 . 1 . 5 6 1 0 . 2 5 . 1 . 5 7
a s e s " : { " h o s t s " : [ " h o s t 1 . e x a m p l e . c o m " , " h o s t 2 . e x a m p l e . c o m " ] , " v a r s " : { " a " : t r u e } } , " w e b s e r v e r s " : [ " h o s t 2 . e x a m p l e . c o m " , " h o s t 3 . e x a m p l e . c o m " ] , " a t l a n t a " : { " h o s t s " : [ " h o s t 1 . e x a m p l e . c o m " , " h o s t 4 . e x a m p l e . c o m " , " h o s t 5 . e x a m p l e . c o m " ] , " v a r s " : { " b " : f a l s e } , " c h i l d r e n " : [ " m a r i e t t a " , " 5 p o i n t s " ] , } , " m a r i e t t a " : [ " h o s t 6 . e x a m p l e . c o m " ] , " 5 p o i n t s " : [ " h o s t 7 . e x a m p l e . c o m " ] " _ m e t a " : { " h o s t v a r s " : { " m o o c o w . e x a m p l e . c o m " : { " a s d f " : 1 2 3 4 } , " l l a m a . e x a m p l e . c o m " : { " a s d f " : 5 6 7 8 } , } } }
g l e g o o g l e / g c a l e n d a r g o o g l e / g c a l e n d a r / b a c k e n d g o o g l e / g c a l e n d a r / b a c k e n d / s t o r a g e 1 g o o g l e / g c a l e n d a r / b a c k e n d / s t o r a g e 2 g o o g l e / g c a l e n d a r / b a c k e n d / s t o r a g e 3 g o o g l e / g c a l e n d a r / f r o n t e n d g o o g l e / g c a l e n d a r / f r o n t e n d / w e b 1 g o o g l e / g c a l e n d a r / f r o n t e n d / w e b 2 g o o g l e / g c a l e n d a r / f r o n t e n d / w e b 3 g o o g l e / g d r i v e g o o g l e / g d r i v e / b a c k e n d g o o g l e / g d r i v e / b a c k e n d / s t o r a g e 1 g o o g l e / g d r i v e / b a c k e n d / s t o r a g e 2 g o o g l e / g d r i v e / b a c k e n d / s t o r a g e 3 g o o g l e / g d r i v e / f r o n t e n d g o o g l e / g d r i v e / f r o n t e n d / w e b 1 g o o g l e / g d r i v e / f r o n t e n d / w e b 2 g o o g l e / g d r i v e / f r o n t e n d / w e b 3 g o o g l e / g m a i l g o o g l e / g m a i l / b a c k e n d g o o g l e / g m a i l / b a c k e n d / s t o r a g e 1 g o o g l e / g m a i l / b a c k e n d / s t o r a g e 2 g o o g l e / g m a i l / b a c k e n d / s t o r a g e 3 g o o g l e / g m a i l / f r o n t e n d g o o g l e / g m a i l / f r o n t e n d / w e b 1 g o o g l e / g m a i l / f r o n t e n d / w e b 2 g o o g l e / g m a i l / f r o n t e n d / w e b 3
o o g l e / n g i n x g o o g l e / n g i n x / w e b 1 g o o g l e / n g i n x / w e b 2 g o o g l e / n g i n x / w e b 3 g o o g l e / t o m c a t g o o g l e / t o m c a t / s t o r a g e 1 g o o g l e / t o m c a t / s t o r a g e 2 g o o g l e / t o m c a t / s t o r a g e 3
on how inventory variables precede each other Because As all things Ansible, KEEP IT SIMPLE, they say. There is only one Empire State Building. One Mona Lisa, etc. Figure out where to define a variable, and do not make it complicated. Remember: Child groups override parent groups, and hosts always override their groups.
IN CHILD GROUPS? Child? Parent? Tree? 3 5 d e f a d d _ c h i l d _ g r o u p ( s e l f , g r o u p ) : 3 6 3 7 i f s e l f = = g r o u p : 3 8 r a i s e E x c e p t i o n ( " c a n n o t a d d g r o u p t o i t s e l f " ) 3 9 4 0 # d o n o t a d d i f i t i s a l r e a d y t h e r e 4 1 i f n o t g r o u p i n s e l f . c h i l d _ g r o u p s : 4 2 s e l f . c h i l d _ g r o u p s . a p p e n d ( g r o u p ) 4 3 g r o u p . d e p t h = m a x ( [ s e l f . d e p t h + 1 , g r o u p . d e p t h ] ) 4 4 g r o u p . p a r e n t _ g r o u p s . a p p e n d ( s e l f ) 4 5 s e l f . c l e a r _ h o s t s _ c a c h e ( ) When we encounter a child group, then "depth" gets a level deeper Deeper == more child is more precedence That *is* some kind of a tree, no?
all virtual machines are tomcat hosts': 'ONE ROLE'} every tomcat app is a two node "cluster" behind a loadbalancer; per app one or more healthchecks per cluster typically 1 application (context), sometimes more 1 big functional application typically == several application clusters applications are part of a project, a project is part of an organisation every application has three instances in each environment ['development', 'testing', 'production'] some applications communicate with other applications through the loadbalancer
t o r y | _ o r g a n i s a t i o n 1 | _ p r o j e c t 1 | _ a p p l i c a t i o n 1 | _ d e v | _ n o d e 1 | _ n o d e 2 | _ t e s t | _ . . | _ p r o d | _ . . | _ a p p l i c a t i o n 2 | _ . . | _ p r o j e c t 2 | _ . . | _ o r g a n i s a t i o n 1 | _ . .
e v e l o p m e n t | _ o r g a n i s a t i o n 1 - d e v | _ a p p l i c a t i o n 1 - d e v | _ t e s t i n g | _ p r o d u c t i o n OR ALSO t o m c a t | _ a p p l i c a t i o n 1 | _ a p p l i c a t i o n 2 < s o m e _ o t h e r _ s e r v e r _ r o l e _ b e s i d e s _ t o m c a t > | _ a p p l i c a t i o n 7 | _ a p p l i c a t i o n 9 < / s o m e _ o t h e r _ s e r v e r _ r o l e _ b e s i d e s _ t o m c a t > lowest groups with nodes are at different levels in different tree's
0 ) . i n f r a ( 1 ) . . r p ( 2 ) . . . r p - v o n e t - o e ( 3 ) . . . r p - v o n e t - o n ( 3 ) . . . r p - v o n e t - p r ( 3 ) . . . r p - i n n e t - o e ( 3 ) . . . r p - i n n e t - o n ( 3 ) . . . r p - i n n e t - p r ( 3 ) . . r p - v o n e t ( 2 ) . . . r p - v o n e t - o n ( 3 ) . . . r p - v o n e t - o e ( 3 ) . . . r p - v o n e t - p r ( 3 ) . . r p - i n n e t ( 2 ) . . . r p - i n n e t - o n ( 3 ) . . . r p - i n n e t - o e ( 3 ) . . . r p - i n n e t - p r ( 3 )
n ( 1 ) . . g e o s e r v e r - d o v p u b ( 2 ) . . g e o s e r v e r - d o v p u b - o e ( 2 ) . . g e o s e r v e r - d o v p u b - o n ( 2 ) . . g e o s e r v e r - d o v p u b - p r ( 2 ) [geoserver-dovpub] is a tomcat application, but is *also* member of the [unison] group (to which a unison role maps) child groups are environment specific subgroups, but they get the the same depth as their parent
app1 app2 t a s k : - c o m m a n d : a 2 e n s i t e { { i t e m } } w i t h _ i t e m s : a p p l i c a t i o n s l i s t applicationslist is defined in the inventory a p p l i c a t i o n s l i s t : - a p p l i c a t i o n 1 - a p p l i c a t i o n 2 more loops? nested loops? with_nested, with_subelements, ..
b l i s h e d a p p s : - n a m e : " w e b " t y p e : " { { d e f a u l t _ a p p t y p e } } " p o r t : 8 0 8 0 l b p o r t : " { { d e f a u l t _ l b p o r t } } " m o n i t o r t y p e : " { { d e f a u l t _ m o n i t o r t y p e } } " q u o r u m : 0 m o n i t o r s : - n a m e : " { { d e f a u l t _ m o n i t o r _ a p p n a m e } } " t y p e : h t t p g e t _ p a t h : " { { d e f a u l t _ g e t _ p a t h } } " p r o t o c o l : " { { d e f a u l t _ p r o t o c o l } } " g e t _ e x t r a : " { { d e f a u l t _ g e t _ e x t r a } } " r e c e i v e : " { { d e f a u l t _ r e c e i v e _ s t r i n g } } "
( . . . p u b l i s h e d a p p s : ) - n a m e : t c p t y p e : t c p p o r t : 1 2 3 4 l b p o r t : 6 0 1 2 3 4 m o n i t o r t y p e : " { { d e f a u l t _ m o n i t o r t y p e } } " q u o r u m : 0 m o n i t o r s : - n a m e : " t c p " t y p e : t c p _ h a l f _ o p e n s e n d : " " r e c e i v e : " "
m o d u l e : . . . n a m e : > { { i t e m . 0 . m o n i t o r n a m e | d e f a u l t ( ' M O N - ' ~ i t e m . 0 . t y p e | d e f a u l t ( d e f a u l t _ a p p t y p e ) | u p p e r ~ ' - ' ~ a p p ~ ( ' - ' ~ i t e m . 0 . n a m e | d e f a u l t ( ' w e b ' ) ) | r e p l a c e ( ' - w e b ' , ' ' ) ~ ( ' - ' ~ i t e m . 1 . n a m e | d e f a u l t ( ' w e b ' ) ) | r e p l a c e ( ' - w e b ' , ' ' ) ~ ' - ' ~ z u i l ) } } s e n d : > { { ' G E T ' ~ i t e m . 1 . g e t _ p a t h ~ ' ' ~ i t e m . 1 . p r o t o c o l | d e f a u l t ( d e f a u l t _ p r o t o c o l ) ~ i t e m . 1 . g e t _ e x t r a | d e f a u l t ( ' ' ) ~ ' \ \ r \ \ n \ \ r \ \ n ' } } r e c e i v e : " { { i t e m . 1 . r e c e i v e | d e f a u l t ( d e f a u l t _ r e c e i v e _ s t r i n g ) } } " p o r t : " { { i t e m . 1 . p o r t | d e f a u l t ( 0 ) } } " w h e n : i t e m . 1 . t y p e i s d e f i n e d a n d i t e m . 1 . t y p e = = ' h t t p ' w i t h _ s u b e l e m e n t s : - p u b l i s h e d a p p s - m o n i t o r s I will need this monitor name again later, but I can't easily definite and keep it in a variable, as it comes from a loop construct
the monitors (healthchecks) to be applied to the pool m o n i t o r s : > { % f o r m o n i n i t e m . m o n i t o r s % } { { ' / C o m m o n / ' ~ i t e m . m o n i t o r n a m e | d e f a u l t ( ' M O N - ' ~ i t e m . t y p e | d e f a u l t ( d e f a u l t _ a p p t y p e ) | u p p e r ~ ' - ' ~ a p p ~ ( ' - ' ~ i t e m . n a m e | d e f a u l t ( ' w e b ' ) ) | r e p l a c e ( ' - w e b ' , ' ' ) | ~ ( ' - ' ~ m o n . n a m e | d e f a u l t ( ' w e b ' ) ) | r e p l a c e ( ' - w e b ' , ' ' ) | ~ ' - ' ~ z u i l ) } } { % i f n o t l o o p . l a s t % } , { % e n d i f % } { % e n d f o r % } w i t h _ i t e m s : p u b l i s h e d a p p s sometimes looping within a jinja2 template gives more power, and more possibilities (and more bugs)
proxies based on previous pools Each application needs access to a set of other applications. == An applications needs the definition of a list of other applictions to get access to Then I need to loop though that list, and then the list of publishedapps for every application... This can possibly go cross-environment...(eg we don't have separate smtp servers per environment, so dev nodes need access to smtp-production) Maybe the list of applications can differ per environment? ... THIS IS GETTING TOO COMPLEX... Or should we NOT automate all things?
stacks, in different environments update default java version: for all dev servers? Keep deployed version for each application in each environment seperately Nice to have = an inventory tool that keeps track of this let's you inherit defaults, but then remember them for particular setup