- From: "Jason J. W. Williams" <
>
- To: Alex Soto <
>
- Cc: Noah Kantrowitz <
>, "
" <
>, "
" <
>
- Subject: [chef] Re: [chef-dev] Re: The future of the database and application cookbooks
- Date: Tue, 30 Aug 2011 23:12:05 -0600
I would agree with Alex. Trying to force MySQL, Redis and Riak (as examples)
into the same generic DB cookbook abstraction will turn into a cookbook that
in theory works universally, but in practice works well for no one, it seems
to me. ...for the same reasons that trying to force a MySQL data
model onto Riak will fail. These are fundamentally different systems, with
only superficial similarities.
-J
Sent via iPhone
Is your email Premiere?
On Aug 30, 2011, at 22:26, Alex Soto
<
>
wrote:
>
Thanks for the opportunity to discuss, always a good thing to hear
>
different opinions.
>
>
As an engineer I totally understand the desire to DRY up these common
>
patterns, but IMO these multi-stack/generic cookbooks add complexity to the
>
cookbook and pull in lots of dependencies I don't use, cluttering up my
>
cookbook repo.
>
>
I see this being similar to the 'rails' database agnosticism of the
>
migrations dsl. I've only used it once, and that was due to engineering
>
curiosity of how well it worked using sqlite locally and a 'real' db in
>
production. In practice, there has always been something that forced me to
>
go outside the dsl and run db specific DDL. So in my experience you really
>
don't utilize this particular db agnosticism feature once you pick a stack,
>
but it adds lot's of engineering effort for the feature implementor to
>
cover all the variations in platforms.
>
>
With databases' in particular, each vendor has their peculiarities, so I
>
see lot's of rat holes in a single cookbook that covers different databases
>
and deployment patterns. I understand that's the reason for providers, but
>
I think the engineering effort is better spent getting a kick-ass db
>
specific cookbook versus a superficial cookbook that kinda/sorta works
>
across db's.
>
>
Alex
>
>
>
On Aug 30, 2011, at 7:39 PM, Noah Kantrowitz wrote:
>
>
> As some people have noticed from my musings on IRC and elsewhere, I have
>
> embarked on a (probably long overdue) overhaul of the application and
>
> database cookbooks. This is largely orthogonal (for now) with the recent
>
> LWRPs added to the database cookbook, though in the end they would be
>
> removed. What follows is a set of syntax ideas for where I think this
>
> should head. Not all of this is implemented, but you can see what is in my
>
> cookbooks branch https://github.com/coderanger/cookbooks/tree/COOK-634.
>
>
>
> Database clusters
>
> =================
>
>
>
> In the new LWRP hierarchy the top level resource is a database_cluster.
>
> This defines an abstract model of a single-master-multi-slave cluster
>
> setup. Within a cluster is one or more database_servers, each of which
>
> defines a single type of database service (MySQL, Postgres, Redis,
>
> Cassandra, etc) mapped on to the containing cluster. In general I would
>
> expect most clusters to only contain a single database_server block, but
>
> this isn't required and if you have a beefy primary box for, say, both
>
> Postgres and Redis and wanted to have both use the same backup machine you
>
> could put those both in the same cluster definition. Within a
>
> database_server you can define database and users, though this isn't
>
> needed for all types of servers and the exact implementation of what those
>
> two constructs do is left up the backend plugin implementing the specified
>
> server type.
>
>
>
> With all that laying down the model, lets look at some syntax:
>
>
>
> database_cluster "prod"
>
> master_role "prod_database_master"
>
> slave_role "prod_database_slave"
>
>
>
> database_server do
>
> type :mysql
>
> database "prod" do
>
> engine "innodb"
>
> end
>
> user "myuser" do
>
> password "xxx"
>
> grant do
>
> select "prod"
>
> insert "prod"
>
> update "prod"
>
> end
>
> end
>
> end
>
>
>
> database_server do
>
> type :redis
>
> end
>
> end
>
>
>
> This will create a cluster running a MySQL server with one database named
>
> prod and a Redis server (in the case of Redis there are no specific tuning
>
> params we need to worry about so far). This example shows a very verbose
>
> form of the desired syntax, below is an equivalent version using some more
>
> sugar and allowing for sane defaults:
>
>
>
> database_cluster "prod"
>
> mysql do
>
> database do
>
> engine "innodb"
>
> end
>
> user "myuser" do
>
> password "xxx"
>
> grant "prod" do
>
> select
>
> insert
>
> update
>
> end
>
> end
>
> end
>
>
>
> redis
>
> end
>
>
>
> You can also pass Hashes to database and user instead of blocks if you
>
> want to feed them from an external data source (such as a data bag):
>
>
>
> database_cluster "prod"
>
> mysql do
>
> database "prod", {:engine => "innodb"}
>
> user "myuser", {:password => "xxx", :grant => {:select => "prod, ...}}
>
> end
>
>
>
> redis
>
> end
>
>
>
> As mentioned before, the actual implementation can choose how to handle
>
> databases and users. In the above examples, if you added any to the redis
>
> section it would simply be a no-op (or maybe a runtime error?). Also as a
>
> structural piece, database and user definitions will only ever be
>
> processed on the database master (are there databases where this isn't the
>
> case and slaves should create users and such too?). The individual
>
> backends for this would live in the cookbook for that program, so the
>
> database cookbook would only hold the core infrastructure and plumbing to
>
> run things. The idea is that this resource block would be placed somewhere
>
> central and assigned to all servers so they can use it for reference (see
>
> below in the app cookbook section). Only nodes with the master or slave
>
> role would actually do anything. As a special case if the system detects
>
> that the master role actually doesn't exist it will run in a degraded mode
>
> assuming a single-node cluster (so obviously the current node is the
>
> master).
>
>
>
> The database cookbook would also grow an associated knife-database plugin
>
> to handle replication setup/teardown as for some databases you have to
>
> perform an out-of-band data sync before attaching the slave.
>
>
>
> Seen in isolation, does this seem suitable flexible to cover most needs? I
>
> am mostly familiar with SQL databases and a few smaller NoSQL products, so
>
> for the greater NoSQL world is this still a viable model?
>
>
>
>
>
> Application deployment
>
> ======================
>
>
>
> The model for the application LWRPs is generally simpler in terms of data,
>
> but is also more callback-driven. The top-level application resource just
>
> contains the central data used for all applications, and then any
>
> framework or platform specific bits are contained in sub-resources similar
>
> to the database_server arrangement. Below is an example of deploying the
>
> Radiant CMS:
>
>
>
> application "radiant" do
>
> path "/srv/radiant"
>
> owner "nobody"
>
> group "nogroup"
>
> repository "git://github.com/radiant/radiant.git"
>
> revision "master"
>
> packages ["libxml2-dev", "libxslt1-dev", "libsqlite3-dev"]
>
> migrate true
>
>
>
> rails do
>
> gems "bundler" => nil, "RedCloth" => "4.2.3"
>
> database :mysql => "radiant_production" do
>
> user "radiant"
>
> reconnect true
>
> encoding "utf8"
>
> end
>
> migration_command "bundle exec rake db:migrate"
>
> end
>
>
>
> unicorn do
>
> port 8000
>
> end
>
> end
>
>
>
> The global data maps very directly to fields in the existing application
>
> data bags, except that they are not Hashes indexed by environment name. In
>
> the rails sub-resource you see that again things mostly map to the data
>
> bag. The biggest exception is the database section which doesn't actually
>
> state any information about the database. Instead things are looked up by
>
> reference to the information in the database resource. It would still be
>
> possible to specify all information manually if you aren't using the
>
> database cookbook.
>
>
>
> Application backends define actions as callbacks more or less, to provide
>
> code to execute at different points during the deploy process. The current
>
> callbacks are :before_compile, :before_deploy, :before_migrate,
>
> :before_symlink, :before_restart, and :after_restart. The last 4 just map
>
> to the existing callbacks in the deploy resource system. before_compile
>
> takes place as the first thing when the application resource executes (so
>
> when the provider is compiled), while before_deploy takes place during the
>
> execute phase in the provider, but after the main application folder
>
> structure is created.
>
>
>
> The plan is to convert all the existing application cookbook recipes into
>
> a small wrapper just piping data bags into this LWRP structure, so they
>
> should continue to work as they always have.
>
>
>
> So, what do people think? Is this a step in the right direction for
>
> application deployment? Do you like the idea but what a different syntax
>
> for it? Are there big, glaring use cases I've missed?
>
>
>
> --Noah Kantrowitz
>
>
>
>
>
>
>
> tl;dr Application deployment with Chef is going to be awesome!
>
>
>
Archive powered by MHonArc 2.6.16.