This post is for people who are getting started with chef-provisioning and want to use it to deploy to AWS. It will take you through creating a couple of machines and deploying a simple application to them. In a future post, I’ll extend this to cover setting up some networking and infrastructure (VPC, subnets, security groups), but this post will assume you are using the default VPC created by AWS.
If you’re just looking to try chef-provisioning and you use Vagrant, you may want start with my other post: Deploying a multi-node application to Vagrant using chef-provisioning.
For an overview of chef-provisioning ( (formerly known as chef-metal), take a look at this Chef-Provisioning: Infrastructure as Code blog post. Also, see the Chef provisioning docs for more details.
Getting setup with chef-provisioning
Chef-provisioning is included in the latest ChefDK (0.3.6 at time of writing). Make sure you have this version or later installed by typing:
chef --version
If not, you can download or upgrade it here.
Create a new Chef repository to explore chef-provisioning:
cd ~
chef generate repo chefprov
We are going to use chef-client in local mode to run our provisioning recipes, so we want to set up a .chef directory that will be used specifically for this repo.
cd ~/chefprov
mkdir .chef
cd .chef
In the .chef directory, create a knife.rb file containing the following:
log_level :info current_dir = File.dirname(__FILE__) node_name "provisioner" client_key "#{current_dir}/dummy.pem" validation_client_name "validator"
Our workstation is going to behave like a chef-client talking to the local-mode server on our workstation, so it needs a node name and a key. The key can be any well-formed key as the local-mode server will not validate it. For example:
ssh-keygen -f dummy.pem
Check the setup is working by performing an empty chef-client run:
chef-client -z
This will perform a local mode chef-client run with no recipes, using the built-in chef-zero server running on port 8889. You should see output similar to:
Starting Chef Client, version 11.18.0 [2015-01-31T16:16:43-06:00] INFO: *** Chef 11.18.0 *** [2015-01-31T16:16:43-06:00] INFO: Chef-client pid: 14113 [2015-01-31T16:16:44-06:00] INFO: Run List is [] [2015-01-31T16:16:44-06:00] INFO: Run List expands to [] [2015-01-31T16:16:44-06:00] INFO: Starting Chef Run for provisioner [2015-01-31T16:16:44-06:00] INFO: Running start handlers [2015-01-31T16:16:44-06:00] INFO: Start handlers complete. [2015-01-31T16:16:44-06:00] INFO: HTTP Request Returned 404 Not Found : Object not found: /reports/nodes/provisioner/runs [2015-01-31T16:16:44-06:00] WARN: Node provisioner has an empty run list. Converging 0 resources [2015-01-31T16:16:44-06:00] INFO: Chef Run complete in 0.032696323 seconds Running handlers: [2015-01-31T16:16:44-06:00] INFO: Running report handlers Running handlers complete [2015-01-31T16:16:44-06:00] INFO: Report handlers complete Chef Client finished, 0/0 resources updated in 1.117898047 seconds
If you’re curious, take a look at the ‘nodes/provisioner.json’ file. This is where the local-mode server stores its node data. You can also run commands like:
knife node show provisioner -z
This command will query the local-mode server and show summary details that it has about your provisioner node (i.e. your workstation).
Preparing the AWS client
To use chef-provisioning, you need to have the AWS CLI client installed. Follow the AWS CLI setup instructions to download and install the client, and to obtain your access keys.
If you are using an existing AWS account, please take appropriate precautions to make sure that you are working in a ‘sandbox’ that minimizes the chance of bad things when you get a script wrong. For example, you might configure your AWS client default to use a region where you do not have existing resources. To do this, edit the ~/.aws/config
file and make sure your selected region is in the default stanza. The following example sets us-west-2 (Oregon) as the default region:
[default] region = us-west-2
Also check that you have the right access keys are configured as default. I prefer to separate these out into the ~/.aws/credentials
file, rather than put them in the config
file:
[default] aws_access_key_id = AMADEUPACCESSKEY aws_secret_access_key = AMadeUPSecreTACcesSKEYXXYyyyZzzZ1234
To make sure the AWS client is working, run the following command:
aws ec2 describe-availability-zones
It should give you a list of availability zones in the region you are using.
If, like me, you are a little more paranoid, you may want to create an IAM user with limited access to resources. I won’t cover this in detail, but below is an example policy that may be useful as a basis to restrict access. Feel free to skip over this to the next section!
"Version": "2012-10-17", "Statement": [ { "Sid": "AllowDescribeAndBasicSetup", "Effect": "Allow", "Action": ["ec2:Describe*", "ec2:ImportKeyPair", "ec2:CreateTags", "ec2:ModifyInstanceAttribute" ], "Resource": "*" }, { "Sid": "AllowInstanceResourceActions", "Effect": "Allow", "Action": ["ec2:RunInstances"], "Resource": [ "arn:aws:ec2:us-west-2:632055226646:instance/*", "arn:aws:ec2:us-west-2:632055226646:network-interface/*", "arn:aws:ec2:us-west-2:632055226646:subnet/*", "arn:aws:ec2:us-west-2:632055226646:key-pair/*", "arn:aws:ec2:us-west-2:632055226646:security-group/*", "arn:aws:ec2:us-west-2:632055226646:volume/*", "arn:aws:ec2:us-west-2::image/ami-*"] }, { "Sid": "AllowOtherInstanceActions", "Effect": "Allow", "Action": [ "ec2:TerminateInstances", "ec2:StopInstances", "ec2:RebootInstances", "ec2:StartInstances"], "Resource": "arn:aws:ec2:us-west-2:632055226646:instance/*" }, { "Sid": "AllowToSeeWhatCantDo", "Effect": "Allow", "Action": [ "sts:DecodeAuthorizationMessage"], "Resource": "*" } ] }
Lines 3-8 allow the user to perform most query operations on any region, import key pairs (see later section on SSH access), and create tags (which is something the chef-provisioning resources like ‘machine’ do by default).
Lines 9-21 only allow the user to create instances and associate them with resources in the us-west-2 region. Lines 22-31 allow the user to manage the instances after creation.
Lines 32-38 are optional but can be useful. If the access policy is too restrictive, you will get a ‘You are not authorized to perform this operation’ message. Sometimes this will include an encoded message which gives you information about what you were not authorized to do. With the above authorization, you can run:
aws sts decode-authorization-message --encoded-message xxxxxxxxxxxxxxxx
Where “xxxxxxxxxxxxxxxx” is the encoded message.
Preparing SSH access into AWS
In order to run chef-client on the instances that you are going to create in AWS, you need to enable SSH access to those instances. There are two main things you need to do:
- Setup a key-pair
- Enable SSH access from your IP address
Setup a key-pair
Use the EC2 console to create a keypair in the region you are using. Download the private key (‘test2_aws.pem’) and save it in ~/.ssh
. Make sure its permissions are read-only:
chmod 400 ~/.ssh/test2_aws.pem
You will also need the public key. You can retrieve this from the private key by running:
ssh-keygen -y -f ~/.ssh/test2_aws.pem > test2_aws.pub
and giving it the name of the file.
If you are using an IAM user without a console logon, generate a keypair using ssh-keygen then import it using the AWS CLI:
aws ec2 import-key-pair --key-name test2_aws --public-key-material file://test2_aws.pub
The ‘file://’ method of loading the file ensures that the key is base64 encoded, which is required to upload a key via the CLI.
Enable SSH access from your IP address
By default, AWS does not enable SSH from external sources into its VPCs. You need to use the EC2 console to allow inbound SSH access from your IP address, by adding a rule to a security group.
This post assumes you can add this rule to the default security group for the default VPC in the region you are using. This will allow immediate access to the machines we will create with chef-provisioning. If you can’t do this, the examples won’t work without some manual intervention – i.e. you will need to add the security group to the created instances before you can run recipes on them.
We also need to let chef-provisioning know about the keys. Add the following to your ./chef/knife.rb
file:
knife[:ssh_user] = "ubuntu" knife[:aws_ssh_key_id] = 'test2_aws' private_keys 'test2_aws' => '/home/christine/.ssh/test2_aws.pem' public_keys 'test2_aws' => '/home/christine/.ssh/test2_aws.pub'
Line 1 is the user name to use when SSH’ing to the instance. For the standard Ubuntu image, this should be ‘ubuntu’. Line 2 specifies which key name to use for AWS, and Lines 3 & 4 setup the locations of the private and public keys.
Enable external access to the application
Our test application requires TCP access on port 3001. Open this port by adding a Custom TCP rule to the security group for the default VPC, allowing access from any IP address (CIDR block ‘0.0.0.0/0’).
The inbound rules should now look something like this:
Creating the AWS instances
Create basic machine provisioning recipe
Our first pass at the chef-provisioning recipes will just create the instances, with nothing on them.
We will create two recipes. The first will set up the AWS-specific details. The second will create the machines.
aws-setup.rb
require 'chef/provisioning/aws_driver' with_driver 'aws' with_machine_options :bootstrap_options => { :key_name => 'test2_aws', :instance_type => 't1.micro', :associate_public_ip_address => true }
Lines 4-8 specify what sort of instances we want to create.
Line 2 tells chef to use the ‘chef-provisioning-aws’ provider. This provider is one of two AWS providers distributed with ChefDK, and is an alternative to the more established chef-provisioning-fog driver. I am using it because of its support for a growing range of other AWS resources (VPCs, security groups, S3, and others). To use the fog driver, replace ‘aws’ with ‘fog:aws’. You may also need to make other changes, for example ‘:instance_type’ is ‘flavor_id’ in the fog driver.
In Line 7, we choose the smallest and cheapest type of instance to experiment with.
Line 8 associates a public IP address with the instance, so that chef can SSH to it.
We are using the default AMI, which is currently Ubuntu 14.04.
The full set of ‘:bootstrap_options’ corresponds to the options listed for the AWS create-instance method.
The second recipe specifies a simple topology with two machines in it:
topo.rb
require 'chef/provisioning' machine 'db' machine 'appserver'
This recipe will create and start the machines, and bootstrap the chef-client onto them.
UPDATE: chef-provisioning-aws 1.2.1 introduces new default AMIs. If the command above fails with:
AWS::EC2::Errors::InvalidParameterCombination: Non-Windows instances with a virtualization type of 'hvm' are currently not supported for this instance type.
then replace t1.micro
with t2.micro
in the above:
with_machine_options :bootstrap_options => { :key_name => 'test2_aws', :instance_type => 't2.micro', :associate_public_ip_address => true }
UPDATE: If the above command fails with:
Unexpected Error: ----------------- ChefZero::ServerNotFound: No socketless chef-zero server on given port 8889
then add the following to each machine resource:
machine 'db' do chef_server( :chef_server_url => 'http://localhost:8889') end machine 'appserver' do chef_server( :chef_server_url => 'http://localhost:8889') end
or add the following in the setup recipe:
with_chef_server "http://localhost:8889"
This problem exists in chefDK 6.0 to 6.2.
Run the recipe
Before proceeding, be aware that you will be charged for the resources that these recipes create. Make sure you delete any instances after you are done. I will tell you how to do that using chef-provisioning, but I advise you to logon to the EC2 console and making sure you have no instances left running when you are done.
To run the recipes, enter:
chef-client -z aws_setup.rb topo.rb
For each of the two machines, you should see the chef-client run create a node, wait for the machine to become connectable (this may take a while), bootstrap the chef-client and perform an empty run.
If you go to the EC2 console, you should see both machines (named ‘db’ and ‘appserver’) are up and running.
Working around SSH issue
If you are trying this with ChefDK 0.3.6 on Ubuntu, you may encounter the following error:
================================================================================ Chef encountered an error attempting to load the node data for "db" ================================================================================ Unexpected Error: ----------------- NoMethodError: undefined method `gsub' for nil:NilClass
This is a known issue with chef-provisioning providing a bad URL for the local-mode server. If you can upgrade to chefDK 0.4.0, this problem has been fixed (but be aware that chefDK 0.4 embeds Chef 12 and not Chef 11).
A workaround for chefDK 0.3.6 is to create the following Gemfile
in your chefprov
directory:
source 'https://rubygems.org' gem 'chef-dk' gem 'chef-provisioning' gem 'chef-provisioning-aws' gem 'net-ssh', '=2.9.1'
and then run chef-client using:
bundle exec chef-client -z aws_setup.rb topo.rb
This will run the chef-client using a previous version of ‘net-ssh’, which avoids the problem.
You will likely need to use ‘bundle exec’ in front of all of the chef-client runs described in this post.
Setup and deploy the Application
Get the application cookbooks
The basic application we will install can be found in the ‘test-repo’ for the ‘knife-topo’ plugin on Github.
First, download the latest release of the knife-topo repository and unzip it.
Then we will use ‘berks vendor’ to assemble the cookbooks we need to deploy this application:
cd knife-topo-0.0.11/test-repo berks vendor cp -R berks-cookbooks/* ~/chefprov/cookbooks
Line 2 uses the Berksfile to assemble all of the necessary cookbooks into the ‘berks-cookbooks’ directory.
Line 3 copies them into our ‘chefprov’ repo, where the local-mode server will look for them when it runs the chef-provisioning recipes.
Extend machine provisioning to include runlists
Now change the topo.rb provisioning recipe as follows:
require 'chef/provisioning' machine 'db' do run_list ['apt','testapp::db'] end machine 'appserver' do run_list ['apt','testapp::appserver'] end
and rerun the chef-client:
chef-client -z aws_setup.rb topo.rb
This time, the chef-client running on the two instances will execute the specified recipes, installing nodejs on ‘appserver’ and mongodb on ‘db’.
Deploy the application
We will now create a third recipe to deploy the application. We could have included this as part of the ‘topo.rb’ recipe, but I chose to make it a separate recipe, so it can be run independently.
Here’s what the recipe looks like:
deploy.rb
require 'chef/provisioning' machine 'appserver' do run_list ['testapp::deploy'] attribute ['testapp', 'user'], 'ubuntu' attribute ['testapp', 'path'], '/var/opt' attribute ['testapp', 'db_location'], lazy { search(:node, "name:db").first['ipaddress'] } end ruby_block "print out public IP" do block do appservernode = search(:node, "name:appserver").first Chef::Log.info("Application can be accessed at http://#{appservernode['ec2']['public_ipv4']}:3001") end end
Line 4 runs the recipe to deploy the application.
Lines 5 to 7 set attributes on the node that customize the test application. For example, Line 7 sets the attribute node[‘testapp’][‘db_location’] to the IP address of the database server, which it looks up using a search for node information stored in the local-mode Chef server (i.e. in the ‘chefprov/nodes’ directory).
In Line 5, ‘lazy’ is used so that the search occurs during the converge phase of the chef-run, not during the compile phase. This is important if the ‘topo.rb’ and ‘deploy.rb’ recipes are run in a single runlist, because the IP address of the database server will only be known after the db machine resource has actually been executed in the converge phase.
Lines 8-13 print out the URL for the application, which uses the public IP address of the application server. This is executed in a ‘ruby_block’ resource so that it occurs in the converge phase once the application server has been created and configured.
Run the chef-client:
chef-client -z aws_setup.rb deploy.rb
At the end of the run, you should see something like:
* ruby_block[print out public IP] action run[2015-01-31T21:28:38-06:00] INFO: Processing ruby_block[print out public IP] action run (@recipe_files::/home/christine/chefprov/deploy.rb line 9) [2015-01-31T21:28:38-06:00] INFO: Application can be accessed at https://54.67.82.204:3001 [2015-01-31T21:28:38-06:00] INFO: ruby_block[print out public IP] called - execute the ruby block print out public IP [2015-01-31T21:28:38-06:00] INFO: Chef Run complete in 21.74813493 seconds Running handlers: [2015-01-31T21:28:38-06:00] INFO: Running report handlers Running handlers complete [2015-01-31T21:28:38-06:00] INFO: Report handlers complete Chef Client finished, 2/2 resources updated in 23.594399737 seconds
Browse to the application URL, and you should see something like:
Congratulations! You have installed a test application using the knife topo plugin. Here are some commands you can run to look at what the plugin did: knife node list knife node show dbserver01 knife node show appserver01 knife node show appserver01 -a normal knife data bag show topologies test1 cat cookbooks/testsys_test1/attributes/softwareversion.rb Go to the knife-topo plugin on Github
Ignore the example commands as we did not use the knife-topo plugin.
Destroy the machines
To destroy the machines, create a recipe:
destroy.rb
require 'chef/provisioning' machine 'db' do :destroy end machine 'appserver' do :destroy end
And run it:
chef-client -z destroy.rb
You should see messages like:
* machine[appserver] action destroy[2015-02-01T09:20:43-06:00] INFO: Processing machine[appserver] action destroy (@recipe_files::/home/christine/chefprov/destroy.rb line 7) - Terminate appserver (i-93a8db50) in us-west-1 ...[2015-02-01T09:20:46-06:00] INFO: Processing chef_node[appserver] action delete (basic_chef_client::block line 26) - delete node appserver at http://localhost:8889[2015-02-01T09:20:46-06:00] INFO: Processing chef_client[appserver] action delete (basic_chef_client::block line 30) [2015-02-01T09:20:46-06:00] INFO: chef_client[appserver] deleted client appserver at http://localhost:8889 - delete client appserver at clients
For both ‘db’ and ‘appserver’. If the run succeeds but you do not see these messages, you may have specified the wrong machine name.
Until you are confident in your scripts, you may want to use the EC2 console to make sure you have terminated the instances (don’t forget to navigate to the right region). You may also want to remove the added rules from the VPC default security group.
Pingback: Chef Provisioning with Microsoft Azure – part 1 – Stuart Preston's blog
How do you specify a VPC id in machine provisioning if there is no default?
LikeLike
You can specify a specific subnet using machine_options bootstrap_options either globally, or on the specific machine resource.
For example:
with_machine_options :bootstrap_options => {
:instance_type => ‘t1.micro’,
:associate_public_ip_address => true,
:subnet => “xxxxxxx”,
:security_group_ids => [ “xxxxx” ]
}
or
machine ‘myinstance’ do
add_machine_options({
:subnet => “xxxxxxx”,
:security_group_ids => [ “xxxxxxxxx” ]
})
In the driver I was using for the original blog post, ‘xxxx’ would have to be a resource name defined in the recipe, so it only really worked when you were also creating the subnet. The chef provisioning gems distributed in ChefDK 0.5.0 RC5 should work with actual existing AWS IDs. Hope that helps.
LikeLike
Thank you for this post, it’s been *very* helpful.
I think that this part:
“chef-client -z deploy.rb”
Needs to be:
“chef-client -z aws-setup.rb deploy.rb”
At least it didn’t work for me otherwise.
LikeLike
Can you brief how to use IAM role with chef provisioner
LikeLike
I’ve not used IAM roles via provisioning enough yet to blog about it yet. From the chef provisioning gitter, it looks like you’re making progress on that. I look forward to reading your blog 🙂
LikeLike
Where is the ssh-user ubuntu hard coded. I am using my AMI with the user centos, but chef-client is trying to connect to the EC2 instance using the user ubuntu. I have updated the the user as ‘centos’ in the knife.rb.
LikeLike
If you’ve already created the instance, chef may be storing the user name in the machine data. Try deleting the machine (e.g. run delete recipe, but also make sure after that it not in the nodes directory in the chef repo) and creating it again.
LikeLike
I have created a new instance with a difference :image_id => “ami-dc1c2b8e” in with machine option but it is still trying to connect with ubuntu. Could you please let me know how can I change the username
LikeLike
This run is working fine for the first time and when I remove the instance from the server and re-initiate it again I am getting empty class error at machine ‘db’ in topo.rb
LikeLike
Are you deleting the instance using the destroy recipe, or deleting the node in Chef using knife? If the latter, chef provisioning keeps additional metadata about the machine, and that could cause errors. Check whether there is data left in the data_bags directory for the db machine. If you’re still having the problem, perhaps you could post or email me more details.
LikeLike
I have deleted the data in the node and now it is working fine And I had another query I have create a key file on ubuntu and provided as key name it is working fine and Now I want to create a linux Instance I have :image_id => “ami-dc1c2b8e” in machine options and :ssh_username => “ec2-user”, in machine_options but it is still trying to connect using ubuntu and failing as it is trying to connect to it using ubuntu@public_ip and getting failed. Could you please suggest me how should I proceed.
LikeLike
I would expect :ssh_username in machine_options to work… possibly its a similar problem where old bootstrap information is stored in the node data – try destroying the machine, checking data bag item is gone, and recreating it. If this is the case, it may be worth raising an issue on github as I’d think the new ssh_username should be picked up from machine_options in this case.
You can also update knife[:ssh_user] = “ec2-user” in the knife.rb file, if you want this to be your default. You may still need to destroy the instance and recreate it for it to pick it up.
LikeLike
Can we pass arguments to the chef-client run in the form of json to override the default attributes in a recipe during run time, I have tried the following command “sudo chef-client -z checking.rb -j file.json” but it doesn’t work. So could you please specify me how to pass the attributes to aws.
LikeLike
What you’re doing should work. I double-checked using the following:
test.json:
test.rb:
Run:
Which includes a
WARN: GOT HI
in the output.LikeLike
Hi Christine Draper,
I would like upload files to amazon AWS S3 buckets from my local repository using chef-provisioning. So could you please provide me a sample code for it.
LikeLike
I’m not aware of any specific resources for pushing to S3. You might just use a normal ‘execute’ resource with the aws commandline, particularly if you are running this from your workstation. May be worth a question to the Chef mailing list
LikeLike
Thank you Christine, It might help me in getting some information.
LikeLike
I have tried the following code to create a machine and assign security groups to it. I have specified port No 22, 80 for both inbound and outbound allowance with cidr_block ‘172.31.0.0/24’ it is able to create the instance but it is unable to assign public IP and unable to connect to the instance. Could you please help me in sorting out this issue. Please find the below code for reference.
machine ‘apache’ do
add_machine_options :ssh_username => ‘ec2-user’,
:bootstrap_options => {
:instance_type => ‘t2.micro’,
:image_id => “ami-12663b7a”,
:subnet => “public-test”,
:security_group_ids => “default_1”,
:associate_public_ip_address => true,
}
recipe ‘java’
end
LikeLike
Some pointers that might help… if I get a chance, I’ll do some experimentation and post an update.
The chef-provisioning-aws driver was updated fairly recently to use V2 of the AWS Ruby API, rather than V1. The V2 API moves associate_public_ip_address from being a top-level attribute, to being on the eth0 network interface:
AWS V2 API Run Instances Option Hash
I believe there was a fix to chef-provisioning-aws so that it should still support the top level attribute, but you might need to update the gem. If that doesn’t work, you might want to open a bug; you might also try specifying an eth0 network interface. As a workaround, you might also change the VPC so that it auto-assigns public IP addresses to instances on creation.
LikeLike
Using chef-provisioning-aws 1.7.0 (the latest), the following works for me:
The backwards compatibility code creates a network interface when it calls the AWS API:
Looking at your example, I think you need to change the security_group_ids into an array i.e. [ “default_1” ]. That might be the cause of your problem.
LikeLike
Thank you Christine Draper.
LikeLike
Hello Christine Draper, I have implemented auto scaling in aws I have provided a machine image as
machine_image ‘apache’ do
machine_options :ssh_username => ‘ec2-user’,
:bootstrap_options => {
:instance_type => ‘t2.micro’,
:image_id => “ami-12663b7a”,
:subnet => “public-test”,
:security_group_ids => “default_1”,
:associate_public_ip_address => true,
}
recipe ‘java’
recipe ‘apache’
end
aws_auto_scaling_group ‘auto-scaling-name’ do
availability_zones [‘us-east-1b’]
desired_capacity 2
min_size 2
max_size 4
launch_configuration ‘config’
end
Here I have 5 concerns
1) It is making use of default security group instead of default_1 but using default_1 as security group while creating instance before creating an image.
2) I would like to register the chef-client with chef-server but when my instance got terminated its chef-client is unable to register and communicate with chef-server
3) services on the auto-scaling node are not getting started automatically like apache.
4) using ubuntu as user instead of ec2-user.
5) I have tried to provide image to machine while is also facing problem with username ubuntu and getting disconnected after the period.
So how should I configure this infrastructure so that my infrastructure will be as per my expectation.
LikeLike
Some thoughts…
1) Try making security_group_ids an array.
2) If you want to register the auto-scaling instances, you need to clean out the /etc/chef/client.pem and node_name in client.rb before taking the image; and then recreate the client.rb with a unique node name on startup in the cluster and run chef-client to bootstrap. I’ve done something like this using CloudFormation and Chef, but not yet with chef provisioning. One approach might be to use /etc/rc0.d script for the cleanup and use launch config user_data for the bootstrap (use the user_data to run a script that you build into the image).
3) The services not starting would suggest a problem with the recipes. Check that they are creating the service properly on a normal ‘machine’… try stopping and starting them, look for errors in httpd log, etc.
4/5) :ssh_username should set the ssh user, but it sounds like it is still picking up the default user. Does it work for normal ‘machine’ resources? Maybe you have hit a bug – hard to tell without seeing some of the output/error messages. You may want to post an issue on github with more specific info.
LikeLike
Hi Christine Draper, thanks for the response I have resolved the first one by specifying with_machine_options and assigned security_group_ids at that place and that handled the situation but I was unable to configure that with machine_image, I will have a look at the second concern and I was sure that my service is working fine in individual machine and fourtha and fifth concerns also got resolved with with_machine_options only. But now I am facing a problem with auto_scaling group in which it is using assigned security group of aws_launch_configuration but I am facing the problem with the subnet it is using the default subnet instead of my subnet specified in aws_launch_configuration or aws_vpc and failing to create an instance specifying that the subnet and security groups belong to different subnets.
aws_launch_configuration ‘config’ do
image “apache_new_auto”
options security_groups: “default_2”,
:subnet => “public-test_1”
end
LikeLike
In the AWS API, it doesnt look like launch_configuration has a subnet option. Looks like you can list subnets in the vpc_zone_identifier option on the autoscaling group (or alternatively list availability_zones). Hope that works!
LikeLike
I have tried availability_zones option but it has no impact the subnet is selecting the availability zone of default means suppose if i specify us-east-1b then it is selecting us-east-1b of default zone not the subnet that I have specified through vpc details in security group.
aws_subnet ‘public-test_1’ do
vpc ‘test-vpc’
availability_zone ‘us-east-1b’
map_public_ip_on_launch true
cidr_block “10.0.0.0/24”
end
aws_auto_scaling_group ‘auto-scaling-name’ do
availability_zones [‘us-east-1b’]
#vpc_zone_identifier [“public-test_1”]
desired_capacity 1
min_size 1
max_size 2
launch_configuration ‘config’
end
I am getting undefined method `vpc_zone_identifier’ for Chef::Resource::AwsAutoScalingGroup error with vpc_zone_identifier.
LikeLike
vpc_zone_identifier would be inside the options hash attribute in the resource
LikeLike
aws_auto_scaling_group ‘auto-scaling-name’ do
availability_zones [‘us-east-1b’]
options :vpc_zone_identifier => [“public-test_1”]
desired_capacity 1
min_size 1
max_size 2
launch_configuration ‘config’
end
The above code is not showing any error but it is still using default security greoup and subnet in specified zone.
LikeLike
I did some experimenting. Seems like aws_autoscaling_group is still using the V1 API, so it is expecting ‘subnets’ in options. This worked for me:
LikeLike
Thanks Christine Draper it resolved the issue.
LikeLike
Do we have any option to get the end point name of the rds instance created, If so could you please specify me how can we get it and could anyone specify me an example for executing a command on rds using machine_execute. Thanks in advance.
LikeLike
You can likely get this using the aws_object method on the resource.
LikeLike
but the problem with aws_object is that end point will create after some time the rds gets created and at that time of access if the end point doesn’t get created how can we get it with sample_rds.aws_object.end_point.
LikeLike
As long as you are using it as an attribute to another resource, you can use lazy { sample_rds.aws_object.end_point } similar to the example for referencing a vpc id. Or you can put it inside a ruby_block resource that evaluates after the rds resource… anything that delays evaluation to convergence time rather than compilation time.
If this doesnt give you what you need, may be worth trying a question either to the Chef mailing list or in the chef-provisioning gitter room – easier to share more about your specific case that way, and more people who may be able to help!
LikeLike
I would like to save the value to a file I have tried with ruby but I am getting id not found error. Can I have a sample code for this.
LikeLike
Here’s an example of the two approaches using a security group:
LikeLike
I have tried rdsinstance.aws_object.end_point, rdsinstance.aws_object.endpoint, rdsinstance.aws_object.endpoint_address and I am getting undefined method .. and for other objects that takes boolean as input is not alllowing it to convert to boolean and returning something like I am trying to get the endpoint of rds. I am following http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/RDS/DBInstance.html#master_username-instance_method as a reference. Could you please share me a reference link where can I get the exact list for accessing the object items like id, endpoint, …
LikeLike
From this code aws_object is a db_instance from the Ruby API. If it’s V2 API, I’d expect ‘endpoint’ to work; if it’s V1 API I’d expect ‘endpoint_address’ to work. I’ve no personal experience with the RDS resource… you may want to try asking in the chef-provisioning gitter.
LikeLike
I want to run the chef-client from a java program and it has started successfully and executing the few resources and getting hanged in the middle and failing to run other resources. I waited for a period of 1 hr but found no progress in running the recipes. Could you please specify me is there any constraints on time limit or some other restrictions in AWS provisioning with chef
LikeLike
I don’t have any experience of running chef-client from a Java program. If the chef-client run works outside of Java, I’d suspect that the Java security model prevents the chef-client from doing everything it needs to, probably related to ssh and port forwarding.
LikeLike
I was unable to assign specific security group to RDS instance with additional_options db_security_groups [‘deault_2’] it is creating RDS without error and using default security group and tried some other like security db_security_group_name, security_group,and some other but none of them worked for me. Could you please let me know which option will assign specified security group.
LikeLike
I’ve not used the RDS instance resource, but looking at the code, these are the options supported in additional_options:
https://github.com/chef/chef-provisioning-aws/blob/master/lib/chef/provider/aws_rds_instance.rb#L9-L13
Doesn’t look like security group is one of them, so it may be missing function. Also looks like code ignores invalid options (Lines 54-65), which would explain why you didnt get an error.
LikeLike
Thanks for your response Christine Draper, now I have resolved this issue Aws provisioning doesn’t have security group option in additional options parameter directlly we have to specify the security group with “vpc_security_group_ids: [security.aws_object.id]” and it worked fine.
LikeLike
Hi Christine, I have created an image and assigned it to auto scaling and it is creating a key while building image but it is not assigning the key to the instances created from auto scaling group. It is not assigning even default key also and I am using the latest gem.
LikeLike
Interesting.. from a quick look at the AWS docs, I can’t find how to assign a security group programmatically when you create a launch config (although you can do it through the UI). Do you know how to do it? That would give us a good clue about how to do it through chef provisioning.
LikeLike
Hi Christine, Could you please respond me back on the above issue.
LikeLike
From
http://docs.aws.amazon.com/sdkforruby/api/Aws/AutoScaling/Types/LaunchConfiguration.html#security_groups-instance_method
it looks like ‘security_groups’ is the options name.
LikeLike
I have assigned security group with the below snippet of code and I had a reference to the following link https://github.com/chef/chef-provisioning-aws/issues/368 and it helped me
security=aws_security_group ‘security_group’ do
vpc ‘vpc’
…..
end
aws_rds_instance “rds-inst” do
engine “mysql”
publicly_accessible true
…….
additional_options(
lazy do
{
vpc_security_group_ids: [security.aws_object.id]
}
end
)
end
LikeLike
Running the below code with machine_options is not adding any storage to my Instance. I would like to add storage to my root directory can I specify the as below or do I need to make any changes.
block_device_mapping: [{
device_name: ‘/dev/xvdf’,
ebs: {
volume_size: 8
}
}]
LikeLike
You are specifying this as bootstrap_options? block_device_mapping will only have an effect when an instance is initially launched.
LikeLike
I can’t see anything obviously wrong. Apologies for asking basic questions: you know you still need to mount and format the drive, this just attaches it?
LikeLike
yes I have specified it as a bootstrap option and I have added the code during the first client run itself. If I specify it outside the block I am getting some error
LikeLike
I am trying to create a new instance using the following code and getting Argument error during the first client run.
machine ‘Sample’ do
add_machine_options :ssh_username => ‘ec2-user’,
:bootstrap_options => {
:instance_type => ‘t2.micro’,
:image_id => “ami-2051294a”,
:associate_public_ip_address => true,
block_device_mapping: [{
device_name: ‘/dev/sda1’,
ebs: {
volume_size: 6, # 1 GB
delete_on_termination: true
}
}]
}
had an error: ArgumentError: unexpected value at params[:block_device_mapping]
could you please let me know what is the exact problem in the code
LikeLike
Try ‘block_device_mappings’
LikeLiked by 1 person
Thanks it resolved my problem.
LikeLike
Why we have error “HTTP Request Returned 404 Not Found: Object not found:” also when I wrote my .rb script then after running the script I had error 404 for chef-zero with many objects being not found?? like aws_vpc
LikeLike
404 means chef-zero was looking for an existing object (e.g. the data bag item it uses to store information about previously created resources such as the aws_vpc) and did not find it. It isn’t always an error – did your actual client run fail? If it did, you’ll likely get more help posting on the Chef discourse https://discourse.chef.io/ as I am not actively working with Chef right now.
LikeLike
I am getting “undefined method `id’ for nil:NilClass” error while executing the machine resource but the image is getting created. At the same time when I implemented action :destroy it is showing me as successful but I was still able to see the machine in running state.
Following is my code
machine ‘a’ do
add_machine_options :ssh_username => ‘ubuntu’,
:bootstrap_options => {
:instance_type => ‘t2.micro’,
:associate_public_ip_address => true,
# :image_id => “ami-2d39803a”,
:availability_zone => ‘us-east-1b’,
}
# action :destroy
end
It would be a great help to me If I can get some assistance.
LikeLike
It sounds like something failed after chef provisioned the instance, but before it had created an entry for it. The destroy then succeeded without doing anything, because Chef did not know about the instance.
LikeLike
Hi, i have this problem, can you help me with this?
chef-client -z aws_setup.rb topo.rb
[2016-10-19T13:38:59-03:00] INFO: Auto-discovered chef repository at /home/nico/Documents/chefdk-provision-demo
[2016-10-19T13:38:59-03:00] INFO: Started chef-zero at chefzero://localhost:8889 with repository at /home/nico/Documents/chefdk-provision-demo
One version per cookbook
[2016-10-19T13:38:59-03:00] INFO: Forking chef instance to converge…
Starting Chef Client, version 12.10.24
[2016-10-19T13:38:59-03:00] INFO: *** Chef 12.10.24 ***
[2016-10-19T13:38:59-03:00] INFO: Platform: x86_64-linux
[2016-10-19T13:38:59-03:00] INFO: Chef-client pid: 19106
[2016-10-19T13:39:00-03:00] INFO: GET /organizations/chef/nodes/provisioner
[2016-10-19T13:39:00-03:00] INFO: Run List is []
[2016-10-19T13:39:00-03:00] INFO: Run List expands to []
[2016-10-19T13:39:00-03:00] INFO: Starting Chef Run for provisioner
[2016-10-19T13:39:00-03:00] INFO: Running start handlers
[2016-10-19T13:39:00-03:00] INFO: Start handlers complete.
[2016-10-19T13:39:00-03:00] INFO: POST /organizations/chef/reports/nodes/provisioner/runs
— POST BODY —
{“action”:”start”,”run_id”:”f6da6c18-b8dd-40ff-b568-fb849f3573eb”,”start_time”:”2016-10-19 13:39:00 -0300″}
— END POST BODY —
[2016-10-19T13:39:00-03:00] INFO: HTTP Request Returned 404 Not Found: Object not found:
resolving cookbooks for run list: []
[2016-10-19T13:39:00-03:00] INFO: POST /organizations/chef/environments/_default/cookbook_versions
— POST BODY —
{“run_list”:[]}
— END POST BODY —
[2016-10-19T13:39:00-03:00] INFO: Loading cookbooks []
Synchronizing Cookbooks:
Installing Cookbook Gems:
Compiling Cookbooks…
Running handlers:
[2016-10-19T13:39:00-03:00] ERROR: Running exception handlers
Running handlers complete
[2016-10-19T13:39:00-03:00] ERROR: Exception handlers complete
Chef Client failed. 0 resources updated in 01 seconds
[2016-10-19T13:39:00-03:00] FATAL: Stacktrace dumped to /home/nico/Documents/chefdk-provision-demo/.chef/local-mode-cache/cache/chef-stacktrace.out
[2016-10-19T13:39:00-03:00] FATAL: Please provide the contents of the stacktrace.out file if you file a bug report
[2016-10-19T13:39:00-03:00] ERROR: could not find recipe file /home/nico/Documents/chefdk-provision-demo/aws_setup.rb
[2016-10-19T13:39:01-03:00] FATAL: Chef::Exceptions::ChildConvergeError: Chef run process exited unsuccessfully (exit code 1)
LikeLike
The error its reporting is that the recipe file (aws_setup.rb) isn’t in the directory it’s expecting (/home/nico/Documents/chefdk-provision-demo/). Move them into that directory, or give full paths to them.
If that doesn’t work, add the following into the chef/knife.rb in the repo directory:
And create an empty cookbooks directory in the repo. It looks like the chef-client is auto-discovering the repo location by looking for a cookbooks dir, which it does if there isn’t a cookbook_path set in the configuration file.
LikeLike
Hi Christine,
Your Instructions:
You will also need the public key. You can retrieve this from the private key by running:
ssh-keygen -y > test2_aws.pub
and giving it the name of the file.
Is this what you mean ?
$ ssh-keygen -y -f id_rsa > test2_aws.pub
Thanks,
Mariano
LikeLike
Thanks, I updated the post
LikeLike