Merge pull request #5457 from DanHam/examples-docs

Some fixes and changes for latest example docs
This commit is contained in:
SwampDragons 2017-10-16 12:07:41 -07:00 committed by GitHub
commit adcda2ca02
1 changed files with 225 additions and 93 deletions

View File

@ -12,7 +12,7 @@ description: |-
# Build an Image # Build an Image
With Packer installed, let's just dive right into it and build our first image. With Packer installed, let's just dive right into it and build our first image.
Our first image will be an [Amazon EC2 AMI](https://aws.amazon.com/ec2/) Our first image will be an [Amazon EC2 AMI](https://aws.amazon.com/ec2/).
This is just an example. Packer can create images for [many platforms][platforms]. This is just an example. Packer can create images for [many platforms][platforms].
If you don't have an AWS account, [create one now](https://aws.amazon.com/free/). If you don't have an AWS account, [create one now](https://aws.amazon.com/free/).
@ -201,7 +201,7 @@ how to validate and build templates into machine images.
## Some more examples: ## Some more examples:
### Another Linux Example, with provisioners: ### Another GNU/Linux Example, with provisioners:
Create a file named `welcome.txt` and add the following: Create a file named `welcome.txt` and add the following:
``` ```
@ -210,9 +210,10 @@ WELCOME TO PACKER!
Create a file named `example.sh` and add the following: Create a file named `example.sh` and add the following:
```
```bash
#!/bin/bash #!/bin/bash
echo "hello echo "hello"
``` ```
Set your access key and id as environment variables, so we don't need to pass Set your access key and id as environment variables, so we don't need to pass
@ -225,7 +226,7 @@ export AWS_SECRET_ACCESS_KEY=MYSECRETACCESSKEY
Now save the following text in a file named `firstrun.json`: Now save the following text in a file named `firstrun.json`:
``` ```json
{ {
"variables": { "variables": {
"aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
@ -317,29 +318,75 @@ amazon-ebs output will be in this color.
==> amazon-ebs: Waiting for AMI to become ready... ==> amazon-ebs: Waiting for AMI to become ready...
``` ```
### A windows example ### A Windows Example
Note that this uses a larger instance. You will be charged for it. Also keep As with the GNU/Linux example above, should you decide to follow along and
in mind that using windows AMIs incurs a fee that you don't get when you use build an AMI from the example template, provided you qualify for free tier
linux AMIs. usage, you should not be charged for actually building the AMI.
However, please note that you will be charged for storage of the snapshot
associated with any AMI that you create.
If you wish to avoid further charges, follow the steps in the [Managing the
Image](/intro/getting-started/build-image.html#managing-the-image) section
above to deregister the created AMI and delete the associated snapshot once
you're done.
You'll need to have a boostrapping file to enable ssh or winrm; here's a basic Again, in this example, we are making use of an existing AMI available from
example of that file. the Amazon marketplace as the *source* or starting point for building our
own AMI. In brief, Packer will spin up the source AMI, connect to it and then
run whatever commands or scripts we've configured in our build template to
customize the image. Finally, when all is done, Packer will wrap the whole
customized package up into a brand new AMI that will be available from the
[AWS AMI management page](
https://console.aws.amazon.com/ec2/home?region=us-east-1#s=Images). Any
instances we subsequently create from this AMI will have our all of our
customizations baked in. This is the core benefit we are looking to
achieve from using the [Amazon EBS builder](/docs/builders/amazon-ebs.html)
in this example.
``` Now, all this sounds simple enough right? Well, actually it turns out we
# set administrator password need to put in just a *bit* more effort to get things working as we'd like...
Here's the issue: Out of the box, the instance created from our source AMI
is not configured to allow Packer to connect to it. So how do we fix it so
that Packer can connect in and customize our instance?
Well, it turns out that Amazon provides a mechanism that allows us to run a
set of *pre-supplied* commands within the instance shortly after the instance
starts. Even better, Packer is aware of this mechanism. This gives us the
ability to supply Packer with the commands required to configure the instance
for a remote connection *in advance*. Once the commands are run, Packer
will be able to connect directly in to the instance and make the
customizations we need.
Here's a basic example of a file that will configure the instance to allow
Packer to connect in over WinRM. As you will see, we will tell Packer about
our intentions by referencing this file and the commands within it from
within the `"builders"` section of our
[build template](/docs/templates/index.html) that we will create later.
Note the `<powershell>` and `</powershell>` tags at the top and bottom of
the file. These tags tell Amazon we'd like to run the enclosed code with
PowerShell. You can also use `<script></script>` tags to enclose any commands
that you would normally run in a Command Prompt window. See
[Running Commands on Your Windows Instance at Launch](
http://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-user-data.html)
for more info about what's going on behind the scenes here.
```powershell
<powershell>
# Set administrator password
net user Administrator SuperS3cr3t! net user Administrator SuperS3cr3t!
wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE wmic useraccount where "name='Administrator'" set PasswordExpires=FALSE
# First, make sure WinRM doesn't run and can't be connected to # First, make sure WinRM can't be connected to
netsh advfirewall firewall add rule name="WinRM" protocol=TCP dir=in localport=5985 action=block netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new enable=yes action=block
net stop winrm
# turn off PowerShell execution policy restrictions # Delete any existing WinRM listeners
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope LocalMachine winrm delete winrm/config/listener?Address=*+Transport=HTTP 2>$Null
winrm delete winrm/config/listener?Address=*+Transport=HTTPS 2>$Null
# configure WinRM # Create a new WinRM listener and configure
winrm quickconfig -q winrm create winrm/config/listener?Address=*+Transport=HTTP
winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}' winrm set winrm/config/winrs '@{MaxMemoryPerShellMB="0"}'
winrm set winrm/config '@{MaxTimeoutms="7200000"}' winrm set winrm/config '@{MaxTimeoutms="7200000"}'
winrm set winrm/config/service '@{AllowUnencrypted="true"}' winrm set winrm/config/service '@{AllowUnencrypted="true"}'
@ -347,42 +394,93 @@ winrm set winrm/config/service '@{MaxConcurrentOperationsPerUser="12000"}'
winrm set winrm/config/service/auth '@{Basic="true"}' winrm set winrm/config/service/auth '@{Basic="true"}'
winrm set winrm/config/client/auth '@{Basic="true"}' winrm set winrm/config/client/auth '@{Basic="true"}'
net stop winrm # Configure UAC to allow privilege elevation in remote shells
set-service winrm -startupType automatic $Key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System'
$Setting = 'LocalAccountTokenFilterPolicy'
Set-ItemProperty -Path $Key -Name $Setting -Value 1 -Force
# Finally, allow WinRM connections and start the service # Configure and restart the WinRM Service; Enable the required firewall exception
netsh advfirewall firewall set rule name="WinRM" new action=allow Stop-Service -Name WinRM
net start winrm Set-Service -Name WinRM -StartupType Automatic
netsh advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new action=allow localip=any remoteip=any
Start-Service -Name WinRM
</powershell>
``` ```
Save the above code in a file named `bootstrap_win.txt`. Save the above code in a file named `bootstrap_win.txt`.
The example config below shows the two different ways of using the powershell -> **A quick aside/warning:**
provisioner: `inline` and `script`. Windows administrators in the know might be wondering why we haven't simply
used a `winrm quickconfig -q` command in the script above, as this would
*automatically* set up all of the required elements necessary for connecting
over WinRM. Why all the extra effort to configure things manually?
Well, long and short, use of the `winrm quickconfig -q` command can sometimes
cause the Packer build to fail shortly after the WinRM connection is
established. How?
1. Among other things, as well as setting up the listener for WinRM, the
quickconfig command also configures the firewall to allow management messages
to be sent over HTTP.
2. This undoes the previous command in the script that configured the
firewall to prevent this access.
3. The upshot is that the system is configured and ready to accept WinRM
connections earlier than intended.
4. If Packer establishes its WinRM connection immediately after execution of
the 'winrm quickconfig -q' command, the later commands within the script that
restart the WinRM service will unceremoniously pull the rug out from under
the connection.
5. While Packer does *a lot* to ensure the stability of its connection in to
your instance, this sort of abuse can prove to be too much and *may* cause
your Packer build to stall irrecoverably or fail!
Now we've got the business of getting Packer connected to our instance
taken care of, let's get on with the *real* reason we're doing all this,
which is actually configuring and customizing the instance. Again, we do this
with [Provisioners](/docs/provisioners/index.html).
The example config below shows the two different ways of using the [PowerShell
provisioner](/docs/provisioners/powershell.html): `inline` and `script`.
The first example, `inline`, allows you to provide short snippets of code, and The first example, `inline`, allows you to provide short snippets of code, and
will create the script file for you. The second example allows you to run more will create the script file for you. The second example allows you to run more
complex code by providing the path to a script to run on the guest vm. complex code by providing the path to a script to run on the guest VM.
Here's an example of a `sample_script.ps1` that will work with the environment Here's an example of a `sample_script.ps1` that will work with the environment
variables we will set in our packer config; copy the contents into your own variables we will set in our build template; copy the contents into your own
`sample_script.ps1` and provide the path to it in your packer config: `sample_script.ps1` and provide the path to it in your build template:
``` ```powershell
Write-Output("PACKER_BUILD_NAME is automatically set for you,) Write-Host "PACKER_BUILD_NAME is automatically set for you, " -NoNewline
Write-Output("or you can set it in your builder variables; ) Write-Host "or you can set it in your builder variables; " -NoNewline
Write-Output("the default for this builder is: " + $Env:PACKER_BUILD_NAME ) Write-Host "The default for this builder is:" $Env:PACKER_BUILD_NAME
Write-Output("Remember that escaping variables in powershell requires backticks: )
Write-Output("for example, VAR1 from our config is " + $Env:VAR1 ) Write-Host "Use backticks as the escape character when required in powershell:"
Write-Output("Likewise, VAR2 is " + $Env:VAR2 ) Write-Host "For example, VAR1 from our config is:" $Env:VAR1
Write-Output("and VAR3 is " + $Env:VAR3 ) Write-Host "Likewise, VAR2 is:" $Env:VAR2
Write-Host "Finally, VAR3 is:" $Env:VAR3
``` ```
Next you need to create a packer config that will use this bootstrap file. See Finally, we need to create the actual [build template](
the example below, which contains examples of using source_ami_filter for /docs/templates/index.html).
windows in addition to the powershell and windows-restart provisioners: Remember, this template is the core configuration file that Packer uses to
understand what you want to build, and how you want to build it.
``` As mentioned earlier, the specific builder we are using in this example
is the [Amazon EBS builder](/docs/builders/amazon-ebs.html).
The template below demonstrates use of the [`source_ami_filter`](
/docs/builders/amazon-ebs.html#source_ami_filter) configuration option
available within the builder for automatically selecting the *latest*
suitable source Windows AMI provided by Amazon.
We also use the `user_data_file` configuration option provided by the builder
to reference the bootstrap file we created earlier. As you will recall, our
bootstrap file contained all the commands we needed to supply in advance of
actually spinning up the instance, so that later on, our instance is
configured to allow Packer to connect in to it.
The `"provisioners"` section of the template demonstrates use of the
[powershell](/docs/provisioners/powershell.html) and
[windows-restart](/docs/provisioners/windows-restart.html) provisioners to
customize and control the build process:
```json
{ {
"variables": { "variables": {
"aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}", "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
@ -394,12 +492,12 @@ windows in addition to the powershell and windows-restart provisioners:
"type": "amazon-ebs", "type": "amazon-ebs",
"access_key": "{{ user `aws_access_key` }}", "access_key": "{{ user `aws_access_key` }}",
"secret_key": "{{ user `aws_secret_key` }}", "secret_key": "{{ user `aws_secret_key` }}",
"region": "us-east-1", "region": "{{ user `region` }}",
"instance_type": "m3.medium", "instance_type": "t2.micro",
"source_ami_filter": { "source_ami_filter": {
"filters": { "filters": {
"virtualization-type": "hvm", "virtualization-type": "hvm",
"name": "*WindowsServer2012R2*", "name": "*Windows_Server-2012-R2*English-64Bit-Base*",
"root-device-type": "ebs" "root-device-type": "ebs"
}, },
"most_recent": true, "most_recent": true,
@ -410,12 +508,13 @@ windows in addition to the powershell and windows-restart provisioners:
"communicator": "winrm", "communicator": "winrm",
"winrm_username": "Administrator", "winrm_username": "Administrator",
"winrm_password": "SuperS3cr3t!" "winrm_password": "SuperS3cr3t!"
}], }
],
"provisioners": [ "provisioners": [
{ {
"type": "powershell", "type": "powershell",
"environment_vars": ["DEVOPS_LIFE_IMPROVER=PACKER"], "environment_vars": ["DEVOPS_LIFE_IMPROVER=PACKER"],
"inline": "Write-Output(\"HELLO NEW USER; WELCOME TO $Env:DEVOPS_LIFE_IMPROVER\")" "inline": "Write-Host \"HELLO NEW USER; WELCOME TO $Env:DEVOPS_LIFE_IMPROVER\""
}, },
{ {
"type": "windows-restart" "type": "windows-restart"
@ -433,45 +532,57 @@ windows in addition to the powershell and windows-restart provisioners:
} }
``` ```
Then `packer build firstrun.json` Save the build template as `firstrun.json`.
Next we need to set things up so that Packer is able to access and use our
AWS account. Set your access key and id as environment variables, so we
don't need to pass them in through the command line:
```
export AWS_ACCESS_KEY_ID=MYACCESSKEYID
export AWS_SECRET_ACCESS_KEY=MYSECRETACCESSKEY
```
Finally, we can create our new AMI by running `packer build firstrun.json`
You should see output like this: You should see output like this:
``` ```
amazon-ebs output will be in this color. amazon-ebs output will be in this color.
==> amazon-ebs: Prevalidating AMI Name: packer-demo-1507234504 ==> amazon-ebs: Prevalidating AMI Name: packer-demo-1507933843
amazon-ebs: Found Image ID: ami-d79776ad amazon-ebs: Found Image ID: ami-23d93c59
==> amazon-ebs: Creating temporary keypair: packer_59d692c8-81f9-6a15-2502-0ca730980bed ==> amazon-ebs: Creating temporary keypair: packer_59e13e94-203a-1bca-5327-bebf0d5ad15a
==> amazon-ebs: Creating temporary security group for this instance: packer_59d692f0-dd01-6879-d8f8-7765327f5365 ==> amazon-ebs: Creating temporary security group for this instance: packer_59e13ea9-3220-8dab-29c0-ed7f71e221a1
==> amazon-ebs: Authorizing access to port 5985 on the temporary security group... ==> amazon-ebs: Authorizing access to port 5985 from 0.0.0.0/0 in the temporary security group...
==> amazon-ebs: Launching a source AWS instance... ==> amazon-ebs: Launching a source AWS instance...
==> amazon-ebs: Adding tags to source instance ==> amazon-ebs: Adding tags to source instance
amazon-ebs: Adding tag: "Name": "Packer Builder" amazon-ebs: Adding tag: "Name": "Packer Builder"
amazon-ebs: Instance ID: i-04467596029d0a2ff amazon-ebs: Instance ID: i-0349406ac85f02166
==> amazon-ebs: Waiting for instance (i-04467596029d0a2ff) to become ready... ==> amazon-ebs: Waiting for instance (i-0349406ac85f02166) to become ready...
==> amazon-ebs: Skipping waiting for password since WinRM password set... ==> amazon-ebs: Skipping waiting for password since WinRM password set...
==> amazon-ebs: Waiting for WinRM to become available... ==> amazon-ebs: Waiting for WinRM to become available...
amazon-ebs: WinRM connected. amazon-ebs: WinRM connected.
==> amazon-ebs: Connected to WinRM! ==> amazon-ebs: Connected to WinRM!
==> amazon-ebs: Provisioning with Powershell... ==> amazon-ebs: Provisioning with Powershell...
==> amazon-ebs: Provisioning with powershell script: /var/folders/8t/0yb5q0_x6mb2jldqq_vjn3lr0000gn/T/packer-powershell-provisioner079851514 ==> amazon-ebs: Provisioning with powershell script: /var/folders/15/d0f7gdg13rnd1cxp7tgmr55c0000gn/T/packer-powershell-provisioner175214995
amazon-ebs: HELLO NEW USER; WELCOME TO PACKER amazon-ebs: HELLO NEW USER; WELCOME TO PACKER
==> amazon-ebs: Restarting Machine ==> amazon-ebs: Restarting Machine
==> amazon-ebs: Waiting for machine to restart... ==> amazon-ebs: Waiting for machine to restart...
amazon-ebs: WIN-164614OO21O restarted. amazon-ebs: WIN-TEM0TDL751M restarted.
==> amazon-ebs: Machine successfully restarted, moving on ==> amazon-ebs: Machine successfully restarted, moving on
==> amazon-ebs: Provisioning with Powershell... ==> amazon-ebs: Provisioning with Powershell...
==> amazon-ebs: Provisioning with powershell script: ./scripts/sample_script.ps1 ==> amazon-ebs: Provisioning with powershell script: ./sample_script.ps1
amazon-ebs: PACKER_BUILD_NAME is automatically set for you, or you can set it in your builder variables; the default for this builder is: amazon-ebs amazon-ebs: PACKER_BUILD_NAME is automatically set for you, or you can set it in your builder variables; The default for this builder is: amazon-ebs
amazon-ebs: Remember that escaping variables in powershell requires backticks; for example VAR1 from our config is A$Dollar amazon-ebs: Use backticks as the escape character when required in powershell:
amazon-ebs: Likewise, VAR2 is A`Backtick amazon-ebs: For example, VAR1 from our config is: A$Dollar
amazon-ebs: and VAR3 is A'SingleQuote amazon-ebs: Likewise, VAR2 is: A`Backtick
amazon-ebs: Finally, VAR3 is: A'SingleQuote
==> amazon-ebs: Stopping the source instance... ==> amazon-ebs: Stopping the source instance...
amazon-ebs: Stopping instance, attempt 1 amazon-ebs: Stopping instance, attempt 1
==> amazon-ebs: Waiting for the instance to stop... ==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Creating the AMI: packer-demo-1507234504 ==> amazon-ebs: Creating the AMI: packer-demo-1507933843
amazon-ebs: AMI: ami-2970b753 amazon-ebs: AMI: ami-100fc56a
==> amazon-ebs: Waiting for AMI to become ready... ==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Terminating the source AWS instance... ==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: Cleaning up any extra volumes... ==> amazon-ebs: Cleaning up any extra volumes...
@ -482,10 +593,31 @@ Build 'amazon-ebs' finished.
==> Builds finished. The artifacts of successful builds are: ==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs: AMIs were created: --> amazon-ebs: AMIs were created:
us-east-1: ami-2970b753 us-east-1: ami-100fc56a
``` ```
And if you navigate to your EC2 dashboard you should see your shiny new AMI. And if you navigate to your EC2 dashboard you should see your shiny new AMI
listed in the main window of the Images -> AMIs section.
Why stop there though?
As you'll see, with one simple change to the template above, it's
just as easy to create your own Windows 2008 or Windows 2016 AMIs. Just
set the value for the name field within `source_ami_filter` as required:
For Windows 2008 SP2:
```
"name": "*Windows_Server-2008-SP2*English-64Bit-Base*",
```
For Windows 2016:
```
"name": "*Windows_Server-2016-English-Full-Base*",
```
The bootstrapping and sample provisioning should work the same across all
Windows server versions.
[platforms]: /docs/builders/index.html [platforms]: /docs/builders/index.html