ironfan 3.1.3 → 3.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,189 @@
1
+ # Ironfan Core Concepts
2
+
3
+ <a name="TOC"></a>
4
+ * [Build your architecture from clusters of cooperating machines](#clusters)
5
+ * [Decoupled *Components* connect](#components)
6
+ * [Components *Announce* their capabilities](#announcements)
7
+ * [Announcements enable *Service Discovery*](#discovery)
8
+ * [Components announce cross-cutting *Aspects*](#aspects)
9
+ * [Aspects enable zero-conf *Amenities*](#amenities) -
10
+ * [Announcements effectively define a component's *Contract*](#contract) -
11
+ * [Contracts enable zero-conf *specification testing*](#specs) t
12
+ * [Specs + monitoring enable zero-conf *integration testing*](#ci) t
13
+ * [Systems *Bind* to provisioned resources](#binding) t
14
+ * [Binding declarations enable *Reasource Sharing*](#resource-sharing)
15
+
16
+ <a name="overview"></a>
17
+ ### Overview
18
+
19
+ Ironfan is your system diagram come to life. In ironfan, you use Chef to assemble and configure components on each machine. Ironfan assembles those machines into clusters -- a group of machines united to provide an important service. For example, at Infochimps one cluster of machines serves the webpages for infochimps.com; another consists only of elasticsearch machines to power our API; and yet another to run the lightweight goliath proxies that implement our API. Our data scientists are able to spin up and shut down terabyte-scale hadoop clusters in minutes. All this is supported by an Ops team of one -- who spends most of his time hacking on Ironfan.
20
+
21
+ The powerful abstractions provided by Chef and Ironfan enables an autowiring system diagram, inevitable best practices in the form of "amenities", and a readable, testable contract for each component in the stack.
22
+
23
+ <a name="clusters"></a><a name="facets"></a>
24
+ ### Clusters and Facets
25
+
26
+ A `cluster`, as mentioned, groups a set of machines around a common purpose. Within that cluster, you define `facet`s: a set of servers with identical components (and nearly identical configuration).
27
+
28
+ For example, a typical web stack cluster might have these facets:
29
+
30
+ * `webnode`s: nginx reverse-proxies requests to a pool of unicorns running Rails
31
+ * `mysql`: one or many MySQL servers, with attached persistent storage
32
+ * `qmaster`s: a redis DB and resque front end to distribute batch-processing tasks
33
+ * `qworkers`s: resque worker processes
34
+
35
+ <a name="components"></a>
36
+ ### Components
37
+
38
+ As you can see, the details of a machine largely follow from the list its `component`s: `mysql_server`, `resque_dashboard`, and so forth. What's a component? If you would draw it in a box on your system diagram, want to discover it from elsewhere, or it it forms part of the contract for your machine, it's a component.
39
+
40
+ Some systems have more than one component: the `ganglia` monitoring system has a component named `agent` to gather operating metrics, and a component named `master` to aggregate those metrics.
41
+
42
+ Those examples all describe daemon processes that listen on ports, but component is more general that that -- it's any isolatable piece of functionality that is interesting to an outside consumer. Here is a set of example systems we'll refer to repeatedly:
43
+
44
+ * *Ganglia*, a distributed system monitoring tool. The `agent` components gather and exchange system metrics, and the `master` component aggregates them. A basic setup would run the `master` component on a single machine, and the `agent` component on many machines (including the master). In order to work, the master must discover all agents, and each agent must discover the master.
45
+
46
+ * *Elasticsearch* is a powerful distributed document database. A basic setup runs a single `server` component on each machine. Elasticsearch handles discovery, but needs a stable subset of them to declare as discovery `seed`s.
47
+
48
+ * *Nginx* is a fast, lightweight webserver (similar to apache). Its `server` component can proxy web requests for one or many web apps. Those apps register a `site` component, which defines the receiving address (public/private/local), how the app connects to nginx (socket, port, files).
49
+
50
+ * *Pig* is a Big Data analysis tool that works with Hadoop, Elasticsearch and more. It provides an executable, and imports jars from hadoop, elasticsearch and others.
51
+
52
+ <a name="announcements"></a>
53
+ ### Components *Announce* their capabilities
54
+
55
+ Notice the recurring patterns: *capabilities* (serve webpages, execute script, send metrics, answer queries), *handles* (ip+port, jars, swarm), *aspects* (ports, daemons, logs, files, dashboards).
56
+
57
+ The Silverware cookbook lets your services `announce` their capabilities and `discover` other resources.
58
+
59
+ Chef cookbooks describe the related components that form a system. You should always have a recipe, separate from the `default` recipe, that clearly corresponds to the component: the `ganglia` cookbook has `master` and `agent` recipes; the `pig` cookbook has `install_from_package` and `install_from_release` recipes. Those recipes are grouped together into Chef roles that encapsulate the component: the `elasticsearch_server` role calls the recipes to install the software, start the daemon process, and write the config files, each in the correct order.
60
+
61
+ Cookbooks do *not* bake in assumptions about their scale or about the machine their on. The same Elasticsearch cookbook can deploy a tiny little search box to sit next to a web app, or one server in a distributed terabyte scale database.
62
+
63
+ <a name="discovery"></a>
64
+ ### Announcements enable *Service Discovery*
65
+
66
+ The `discover` and `discover_all` connect decoupled components. Your systems
67
+
68
+ * Don't care whether the discovered components are on the same machine, different machines, or a remote data center.
69
+ * Don't care about the number of underlying machines -- the whole thing might run on your laptop while developing, across a handful of nodes in staging, and on dozens of nodes in production.
70
+ * Don't necessarily care about the actual system -- your load balancer doesn't care whether it's nginx or apache or anything else, it just wants to discover the correct set of `webnode`s.
71
+
72
+ <a name="aspects"></a>
73
+ ### Components announce cross-cutting *Aspects*
74
+
75
+ Besides the component's capabilities, the announcement also describes its aspects: cross-cutting attributes common to many components.
76
+
77
+ * **log**: write data to a log file.
78
+ * **daemon**: long-running process. Can specify run state, resource bounds, etc.
79
+ * **port**: serves data over a port. Can specify the protocol, performance expectations, etc.
80
+ * **dashboard**: HTML, JMX, etc -- internal component metrics and control
81
+ * **executable**: executes scripts
82
+ * **export**: libraries, `jar`s, `conf` files, etc
83
+ * **consumes**: registered whenever you `discover` another component
84
+
85
+ <a name="amenities"></a>
86
+ ### Aspects enable zero-conf *Amenities*
87
+
88
+ Typically, consumers discover their provider, and the provider is unconcerned with which consumers it attends to. Ironfan lets you invert this pattern: decoupled `amenities` find components they can cater to.
89
+
90
+ * A log aspect would enable the following amenities
91
+ - `logrotated` to intelligently manage its logs
92
+ - `flume` to archive logs to a predictable location
93
+ - If the log is known to be an apache web log, a flume decorator can track rate and duration of requests and errors.
94
+ * A port aspect would enable
95
+ - zeroconf configuration of firewall and security groups
96
+ - remote monitors to regularly pinging the port for uptime and latency
97
+ - and pings the interfaces that it should *not* appear on to ensure the firewall is in place?
98
+
99
+ <a name="contracts"></a>
100
+ ### Announcements effectively define a component's *Contract*
101
+
102
+ The announcements that components make don’t just facilitate discovery. In a larger sense, they describe the external contract for the component.
103
+
104
+ When `nginx` announces that it listens on `node[:nginx][:http_port] = 80`, it is promising a capability (namely, that http requests to that port return certain results). When elasticsearch announces that it runs the `elasticsearch` daemon, it promised that the daemon will be running, with the right privileges, and not consuming more than its fair share of resources.
105
+
106
+ <a name="specs"></a>
107
+ ### Contracts enable zero-conf *Specification Testing*
108
+
109
+
110
+
111
+ * A daemon aspect
112
+ - implies a process should be running
113
+ - owned by the right user
114
+ - with a stable PID
115
+ - and live within defined memory bounds
116
+ * A log aspect
117
+ - should be open and receiving content from the process
118
+ - should contain lines showing successful startup (and not contain lines matching an error).
119
+ * A dashboard/JMX/metrics aspect:
120
+ - actual configuration settings as read out of the running app should match those drawn from the node attributes. No more finding out a setting was overridden by some hidden config file.
121
+ - should have a healthy heartbeat and status
122
+
123
+ [Ironfan-CI](http://github.com/infochimps-labs/ironfan-ci) uses the announcement to create a suite of detailed [Cucumber](http://cukes.info) (via [Cuken](https://github.com/hedgehog/cuken)) feature tests that document and enforce the machine's contract. You're not limited to just the zeroconf tests: it's easy to drop in additional cucumber specs.
124
+
125
+ Ironfan-CI is young -- it's for the tenacious zealot only -- but is the subject of current work and developing fast.
126
+
127
+ <a name="ci"></a>
128
+ ### Specs + Monitoring enable zero-conf *Full-stack Testing*
129
+
130
+ You can now look at monitoring as the equivalent of a full-stack continuous integration test suite. The same announcement that Ironfan-CI maps into cucumber statements can as well drive your favorite monitoring suite (or more likely, the monitoring suite you hate the least).
131
+
132
+ The Ironfan Enterprise product ships with Zabbix, which is actually pretty loveable -- even moreso when you don't have to perform fiddly repeated template definitions.
133
+
134
+ <a name="binding"></a>
135
+ ### Systems *Bind* to provisioned resources
136
+
137
+ Components should adapt to their machine, but be largely unaware of its defaul arrangement. One common anti-pattern we see in many cookbooks is to place data at some application-specific absolute path, to assume a certain layout of volumes.
138
+
139
+ When my grandmother comes to visit, she quite reasonably asks for a room with a comfortable bed and a short climb. This means that at my apartment, she stays in the main bedroom and I use the couch. At my brother's house, she stays in the downstairs guest room, while my brother and sister-in-law stay in their bedroom.
140
+
141
+ Suppose Grandmom instead always chose 'the master bedroom on the first floor' no matter how the house was set up. At my apartment, she'd find herself in the parking garage. At my brother's house, she'd find herself in a crowded bed and uninvited from returning to visit.
142
+
143
+ Similarly, the well-mannered cookbook does not hard-code a large data directory onto the root partition. The root drive is the private domain of the operating system; typically, there's a large and comfortably-appointed volume just for it to use. On the other hand, hard-coding a location of `/mnt/external2` will end in tears if I'm testing the cookbook on my laptop, where no such drive exists.
144
+
145
+ The solution is to request for volumes by their characteristics, and defer to the machine's best effort in meeting that request.
146
+
147
+ # Data striped across all persistent dirs
148
+ volume_dirs('foo.datanode.data') do
149
+ type :persistent, :bulk, :fallback
150
+ selects :all
151
+ mode "0700"
152
+ end
153
+
154
+ # Scratch space for indexing, striped across all scratch dirs
155
+ volume_dirs('foo.indexer.journal') do
156
+ type :fast, local, :bulk, :fallback
157
+ selects :first
158
+ mode "0755"
159
+ end
160
+
161
+ Another example of this is binding to a network interface. Unfortunately most cookbooks choose the primary address; most of ours choose the 'private' interface if any and fall back to the primary.
162
+
163
+ The right pattern here is
164
+ * provisioners tag resources
165
+ * cookbooks to request the best match to their purpose
166
+ * at the cookbook's option, if no good match is found use a fallback or raise an exception
167
+
168
+ <a name="resource-sharing"></a>
169
+ ### Binding declarations enable *Resource Sharing*
170
+
171
+ Resource sharing is yet another place where an assertive announcement can enable best practices.
172
+
173
+ Right now, most java-based components hard-code a default JVM heap size. This can lead to a situation where a component shows up on a 16GB machine with 1GB heap allocated, or where five components show up on a 0.7GB machine each with 1GB allocated.
174
+
175
+ We instead deserve a deft but highly predictable way to apportion resources (disks, ram, etc). Nothing that gets in the way of explicit tuning, but one which gives a reasonable result in the default case.
176
+
177
+ The Hadoop cookbook has an initial stab at this, but for the most part Resource Sharing is on the roadmap but not yet in place.
178
+
179
+
180
+ __________________________________________________________________________
181
+
182
+ ### Learn More
183
+
184
+ [Aspect-Oriented Programming](http://en.wikipedia.org/wiki/Aspect-oriented_programming): The Ironfan concept of `aspects` as cross-cutting concerns is taken from AOP. Amenities don't correspond precisely to join cuts etc., so don't take the analogy too far. (Or perhaps instead help us understand how to take the analogy the rest of the way.)
185
+
186
+
187
+ Ironfan's primary models form a component-based approach to building a [Service-Oriented Architecture](http://msdn.microsoft.com/en-us/library/aa480021.aspx). Model examples of a modern SOA include the [Netflix API](http://www.slideshare.net/danieljacobson/the-futureofnetflixapi) (see [also](http://techblog.netflix.com/2011/12/making-netflix-api-more-resilient.html)) and [Postrank](http://www.igvita.com/2011/03/08/goliath-non-blocking-ruby-19-web-server/) (see [also](http://www.igvita.com/2010/01/28/cluster-monitoring-with-ganglia-ruby/)).
188
+
189
+
@@ -1,3 +1,3 @@
1
1
 
2
- Please see the {homebase}/cookbooks/volumes/README.md
2
+ Please see the [README from the volumes cookbook](https://github.com/infochimps-labs/ironfan-pantry/blob/master/cookbooks/volumes/README.md) for more information.
3
3
 
@@ -0,0 +1,36 @@
1
+
2
+ Examples of concerns that tend to be crosscutting include:
3
+
4
+ Synchronization -- (declare an action dependency, trigger, event)
5
+ Real-time constraints
6
+ Feature interaction
7
+ Memory management
8
+ - data checks
9
+ - feature checks
10
+ * security
11
+ - firewall rules
12
+ - access control
13
+ Logging
14
+ Monitoring
15
+ Business rules
16
+ Tuning
17
+ Refactor pivot
18
+
19
+
20
+ AOP:
21
+
22
+ - Scattered (1:n) / Tangled (n:1)
23
+ - join point: hook
24
+ - point cut: matches join points
25
+ - advice: behavior evoked at point cut
26
+
27
+ * Interception
28
+ - Interjection of advice, at least around methods.
29
+ * Introduction
30
+ - Enhancing with new (orthogonal!) state and behavior .
31
+ * Inspection
32
+ - Access to meta-information that may be exploited by pointcuts or
33
+ advice.
34
+ * Modularization
35
+ - Encapsulate as aspects.
36
+
@@ -27,6 +27,43 @@ Most cookbooks have some set of the following
27
27
  * register a minidash dashboard
28
28
  * trigger start (or restart) of service
29
29
 
30
+ ## Proposal:
31
+
32
+ kill `role`s, in favor of `stack`s.
33
+
34
+ A runlist is assembled in the following phases:
35
+
36
+ * `initial` configuration
37
+ * `before_install`
38
+ - `account`
39
+ * `install`
40
+ - `plugin` install
41
+ - `directories`
42
+ * `announcement`
43
+ - `service` definition
44
+ - `discovery`
45
+ * `commit`
46
+ - `config_files`: write config files to disk
47
+ * `finalize`
48
+ * `launch`
49
+
50
+ As you can see, most layers have semantic names (`plugin`, `user`, etc); if you name your recipe correctly, they will be assigned to the correct phase. Otherwise, you can attach them explicitly to a semantic or non-semantic phase.
51
+
52
+ elasticsearch_datanode component:
53
+
54
+ elasticsearch::default # initial
55
+ elasticsearch::install_from_release #install phase
56
+ elasticsearch::plugins # plugin phase
57
+
58
+ elasticsearch::server # service definition; includes announcement
59
+ elasticsearch::config_files # config_files; includes discovery
60
+
61
+ I'm not clear on how much the phases should be strictly broken out into one-recipe-per-phase.
62
+
63
+ It's also possible to instead define a chef resource that let you defer a block to a given phase from within a callback. It would be similar to a ruby block, but have more explicit timing. This may involve jacking around inside Chef, something we've avoided to now.
64
+
65
+ __________________________________________________________________________
66
+
30
67
  Run List is
31
68
 
32
69
  [role[systemwide], role[chef_client], role[ssh], role[nfs_client],
@@ -1,4 +1,7 @@
1
1
 
2
+ property :color, :type => Integer
3
+ property :color, :type => String
4
+ property :color, :type => Pathname
2
5
 
3
6
  * is a subclass of extlib's `Mash` (Hash with indifferent access).
4
7
  - in the
@@ -35,14 +38,65 @@ __________________________________________________________________________
35
38
  ### setter/getter/block
36
39
 
37
40
 
38
- * `self.foo` -- returns value of foo
39
- * `self.get(:foo)` -- sets foo to val
40
- * `self.foo(val)` -- sets foo to val
41
- * `self.set(:foo, val)` -- sets foo to val
42
- * `self.foo ||= val` -- sets foo to val if foo is unset, `false` or `nil`
43
- * `self.default(:foo, val)` -- sets foo to val if foo is unset
44
- * `self.unset(:foo)` -- unsets foo
45
-
41
+ * `obj.foo` -- returns value of foo
42
+ * `obj.foo(val)` -- sets foo to val; val must not be `nil`
43
+ * `obj.unset(:foo)` -- unsets foo
44
+
45
+ want:
46
+
47
+ * `obj.foo ||= val` -- sets foo to val if foo is unset, `false` or `nil`
48
+ * `obj.default(:foo, val)` -- sets foo to val if foo is unset
49
+
50
+ provisionally, these are `protected`:
51
+
52
+ * `obj.get(:foo)` -- returns value of foo
53
+ * `obj.set(:foo, val)` -- sets foo to val
54
+
55
+ ### how hash-like is this?
56
+
57
+
58
+
59
+ * obj.deep_get(:foo, :bar, :baz) #
60
+ * obj.deep_set(:foo, :bar, :baz, val) # sets foo bar baz.
61
+ - where property has a type, it uses that type
62
+ - otherwise it uses Mash, and calls [] on it
63
+
64
+
65
+ * TD votes NO on magic recursive hash behavior
66
+
67
+ * `obj[:foo]`
68
+ * `obj[:foo] = val`
69
+ * `obj[:foo][:bar][:baz]` -- when this has a value
70
+ * `obj[:foo][:bar][:baz]` -- when some or all of those have never been set?
71
+ * `obj[:foo][:bar][:baz] = 1` -- when `obj[:foo]` has never been set
72
+ * `obj[:foo][:bar][:baz] = 1` -- when `obj[:foo]` has never been set
73
+ * `obj[:foo][:bar][:baz] ||= 1` -- **hard** ?I think?
74
+
75
+ * `obj[:foo]` -- nil
76
+ * `obj[:foo][:bar]` -- raise
77
+ * `obj[:foo][:bar] = 3` --
78
+ - now obj[:foo][:bar] is 3
79
+ - and obj[:foo] is a ?dsl_object?? but
80
+
81
+ `obj[:foo][:bar]`
82
+
83
+ Suppose `obj[:foo]` is set to a
84
+
85
+ Seems clear these should do the right thing:
86
+
87
+ * `obj.merge`
88
+ * `obj.reverse_merge`
89
+ * `obj.keys`
90
+ * `obj.values`
91
+ * ... and a few more
92
+
93
+ Also:
94
+
95
+ * `obj.to_a`?
96
+ * `obj.each`?
97
+ * other crazy Enumerable properties?
98
+
99
+
46
100
  ### collection attributes
47
101
 
48
102
 
@@ -52,4 +106,4 @@ __________________________________________________________________________
52
106
  ### nested objects
53
107
 
54
108
 
55
- ### type co
109
+ ### type co
@@ -0,0 +1,102 @@
1
+ Ironfan Homebase Layout
2
+ =======================
3
+
4
+ Your Chef Homebase contains several directories, and each contains a README.md file describing its purpose and use in greater detail.
5
+
6
+ This directory structure came out of a *lot* of trial and error, and is working very well where many others didn't. This homebase makes it easy to pull in third-party pantries (cookbook collections) and track upstream changes without being locked in.
7
+
8
+ ## Main Directories
9
+
10
+ The main assets you'll use are:
11
+
12
+ * `clusters/` - Clusters fully describe your machines, from its construction ('an 8-core machine on the Amazon EC2 cloud') to its roles ('install Cassandra, Ganglia for monitoring, and silverware to manage its logs and firewall').
13
+ * `cookbooks/` - Cookbooks you download or create. Cookbooks install components, for example `cassandra` or `java`.
14
+ * `roles/` - Roles organize cookbooks and attribute overrides to describe the specific composition of your system. For example, you install Cassandra attaching the `cassandra_server` role to your machine. (.rb or .json files)
15
+
16
+ These folders hold supporting files. You're less likely to visit here regularly.
17
+
18
+ * `knife/` - Chef and cloud configuration, and their myriad attendant credentials.
19
+ * `environments/` - Organization-wide attribute values. (.json or .rb files)
20
+ * `data_bags/` - Data bags are an occasionally-useful alternative to node metadata for distributing information to your machines. (.json files)
21
+ * `certificates/` - SSL certificates generated by `rake ssl_cert` live here.
22
+ * `tasks/` - Rake tasks for common administrative tasks.
23
+ * `vendor/` - cookbooks are checked out to `vendor`; symlinks in the `cookbooks/` directory select which ones will be deployed to chef server. The vendor directory comes with the Ironfan, Opscode and (should you be a lucky customer) Ironfan Enterprise chef pantries.
24
+ * `notes/` - a submoduled copy of the [ironfan wiki](http://github.com/infochimps-labs/ironfan/wiki`
25
+
26
+ ## Directory setup
27
+
28
+ The core structure of the homebase is as follows ("├─*" means "git submodule'd"):
29
+
30
+ homebase
31
+ ├── clusters - cluster definition files
32
+ │ └── ( clusters )
33
+ ├── cookbooks - symlinks to cookbooks
34
+ │ ├── @vendor/ironfan-pantry/cookbooks/...
35
+ │ ├── @vendor/opscode/cookbooks/...
36
+ │ └── @vendor/org-pantry/cookbooks/...
37
+ ├── environments - environment definition files
38
+ │ └── ( environments )
39
+ ├── data_bags - symlinks to data_bags
40
+ │ ├── @vendor/ironfan-pantry/roles/...
41
+ │ └── @vendor/org-pantry/roles/...
42
+ ├── roles - symlinks to roles
43
+ │ ├── @vendor/ironfan-pantry/roles/...
44
+ │ └── @vendor/org-pantry/roles/...
45
+ ├── vendor
46
+ │ ├─* ironfan-pantry - git submodule of https://github.com/infochimps-labs/ironfan-pantry
47
+ │ │ ├── cookbooks
48
+ │ │ ├── data_bags
49
+ │ │ ├── roles
50
+ │ │ └── tasks
51
+ │ ├─* ironfan-enterprise - git submodule of ironfan-enterprise, if you're a lucky customer
52
+ │ │ ├── cookbooks
53
+ │ │ ├── data_bags
54
+ │ │ ├── roles
55
+ │ │ └── tasks
56
+ │ ├── opscode
57
+ │ │ └─* cookbooks - git submodule of https://github.com/infochimps-labs/opscode_cookbooks; itself a closely-tracked fork of https://github.com/opscode/cookbooks
58
+ │ └── org-pantry - organization specific roles, cookbooks, etc.
59
+ │ ├── cookbooks
60
+ │ ├── data_bags
61
+ │ ├── roles
62
+ │ └── tasks
63
+ ├── knife - credentials (see below)
64
+ ├── certificates
65
+ ├── config
66
+ ├─* notes
67
+ ├── tasks
68
+ └── vagrants - vagrant files (when using ironfan-ci)
69
+
70
+ The `vendor/opscode/cookbooks` and `vendor/ironfan-pantry` directories are actually [git submodules](http://help.github.com/submodules/). This makes it easy to track upstream changes in each collection while still maintaining your own modifications.
71
+
72
+ We recommend you place your cookbooks in `vendor/org-pantry`. If you have cookbooks &c from other pantries that have significant changes, you can duplicate it into this `vendor/org-pantry` and simply change the symlink in homebase/cookbooks/.
73
+
74
+ ## Knife dir setup
75
+
76
+ We recommend you version your credentials directory separately from your homebase. You will want to place it under version control, but you should not place it into a central git repository -- this holds the keys to the kingdom.
77
+
78
+ We exclude the chef user key (`(user).pem`) and user-specific knife settings (`knife-user-(user).rb`) from the repo as well. Each user has their own revokable client key, and their own cloud credentials set, and those live nowhere but their own computers.
79
+
80
+ knife/
81
+ ├── knife.rb
82
+ ├── credentials -> (organization)-credentials
83
+ ├── (organization)-credentials
84
+ │ ├── knife-org.rb - org-specific stuff, and cloud assets (elastic IPs, AMI image ids, etc)
85
+ │ ├── (user).pem - your chef client key *GITIGNORED*
86
+ │ ├── knife-user-(user).rb - your user-specific knife customizations *GITIGNORED*
87
+ │ ├── (organization)-validator.pem- chef validator key, used to create client keys
88
+ │ ├── client_keys
89
+ │ │ └── (transient client keys) - you can delete these at will; only useful if you're debugging a bad bootstrap
90
+ │ ├── ec2_keys
91
+ │ │ └── (transient client keys) - ssh keys for cloud machines (in EC2 parlance, the private half of your keypair)
92
+ │ ├── certificates
93
+ │ ├── data_bag_keys
94
+ │ └── ec2_certs
95
+ ├── bootstrap - knife cluster bootstrap scripts
96
+ ├── plugins
97
+ │ └── knife
98
+ │ └── (knife plugins) - knife plugins
99
+ └── .gitignore - make sure not to version the secret/user-specific stuff (*-keypairs, *-credentials.rb, knife-user-*.rb)
100
+
101
+
102
+ (You can safely ignore the directories above that aren't annotated; they're useful in certain advanced contexts but not immediately)
@@ -0,0 +1,18 @@
1
+ # Ironfan Knife Commands
2
+
3
+ Available cluster subcommands: (for details, `knife SUB-COMMAND --help`)
4
+
5
+ knife cluster list (options) - show available clusters
6
+ knife cluster bootstrap CLUSTER-[FACET-[INDEXES]] (options) - bootstrap all servers described by given cluster slice
7
+ knife cluster kick CLUSTER-[FACET-[INDEXES]] (options) - start a run of chef-client on each server, tailing the logs and exiting when the run completes.
8
+ knife cluster kill CLUSTER-[FACET-[INDEXES]] (options) - kill all servers described by given cluster slice
9
+ knife cluster launch CLUSTER-[FACET-[INDEXES]] (options) - Creates chef node and chef apiclient, pre-populates chef node, and instantiates in parallel their cloud machines. With --bootstrap flag, will ssh in to machines as they become ready and launch the bootstrap process
10
+ knife cluster proxy CLUSTER-[FACET-[INDEXES]] (options) - Runs the ssh command to open a SOCKS proxy to the given host, and writes a PAC (automatic proxy config) file to /tmp/ironfan_proxy-YOURNAME.pac. Only the first host is used, even if multiple match.
11
+ knife cluster show CLUSTER-[FACET-[INDEXES]] (options) - a helpful display of cluster's cloud and chef state
12
+ knife cluster ssh CLUSTER-[FACET-[INDEXES]] COMMAND (options) - run an interactive ssh session, or execuse the given command, across a cluster slice
13
+ knife cluster start CLUSTER-[FACET-[INDEXES]] (options) - start all servers described by given cluster slice
14
+ knife cluster stop CLUSTER-[FACET-[INDEXES]] (options) - stop all servers described by given cluster slice
15
+ knife cluster sync CLUSTER-[FACET-[INDEXES]] (options) - Update chef server and cloud machines with current cluster definition
16
+ knife cluster vagrant CMD CLUSTER-[FACET-[INDEXES]] (options) - runs the given command against a vagrant environment created from your cluster definition. EARLY, use at your own risk
17
+
18
+
Binary file
Binary file
@@ -0,0 +1,14 @@
1
+
2
+ ## Philosophy
3
+
4
+ Some general principles of how we use chef.
5
+
6
+ * *Chef server is never the repository of truth* -- it only mirrors the truth. A file is tangible and immediate to access.
7
+ * Specifically, we want truth to live in the git repo, and be enforced by the chef server. This means that everything is versioned, documented and exchangeable. *There is no truth but git, and chef is its messenger*.
8
+ * *Systems, services and significant modifications cluster should be obvious from the `clusters` file*. I don't want to have to bounce around nine different files to find out which thing installed a redis:server. The existence of anything that opens a port should be obvious when I look at the cluster file.
9
+ * *Roles define systems, clusters assemble systems into a machine*.
10
+ - For example, a resque worker queue has a redis, a webserver and some config files -- your cluster should invoke a @whatever_queue@ role, and the @whatever_queue@ role should include recipes for the component services.
11
+ - the existence of anything that opens a port _or_ runs as a service should be obvious when I look at the roles file.
12
+ * *include_recipe considered harmful* Do NOT use include_recipe for anything that a) provides a service, b) launches a daemon or c) is interesting in any way. (so: @include_recipe java@ yes; @include_recipe iptables@ no.) You should note the dependency in the metadata.rb. This seems weird, but the breaking behavior is purposeful: it makes you explicitly state all dependencies.
13
+ * It's nice when *machines are in full control of their destiny*. Their initial setup (elastic IP, attaching a drive) is often best enforced externally. However, machines should be able independently assert things like load balancer registration which may change at any point in their lifetime.
14
+ * It's even nicer, though, to have *full idempotency from the command line*: I can at any time push truth from the git repo to the chef server and know that it will take hold.
File without changes