website: intro in progress
This commit is contained in:
parent
8517d0950b
commit
b8b5f15f3a
|
@ -1,125 +0,0 @@
|
||||||
---
|
|
||||||
layout: "intro"
|
|
||||||
page_title: "Run the Agent"
|
|
||||||
sidebar_current: "gettingstarted-agent"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Run the Terraform Agent
|
|
||||||
|
|
||||||
After Terraform is installed, the agent must be run. The agent can either run
|
|
||||||
in a server or client mode. Each datacenter must have at least one server,
|
|
||||||
although 3 or 5 is recommended. A single server deployment is _**highly**_ discouraged
|
|
||||||
as data loss is inevitable in a failure scenario. [This guide](/docs/guides/bootstrapping.html)
|
|
||||||
covers bootstrapping a new datacenter. All other agents run in client mode, which
|
|
||||||
is a very lightweight process that registers services, runs health checks,
|
|
||||||
and forwards queries to servers. The agent must be run for every node that
|
|
||||||
will be part of the cluster.
|
|
||||||
|
|
||||||
## Starting the Agent
|
|
||||||
|
|
||||||
For simplicity, we'll run a single Terraform agent in server mode right now:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform agent -server -bootstrap -data-dir /tmp/consul
|
|
||||||
==> WARNING: Bootstrap mode enabled! Do not enable unless necessary
|
|
||||||
==> WARNING: It is highly recommended to set GOMAXPROCS higher than 1
|
|
||||||
==> Starting Terraform agent...
|
|
||||||
==> Starting Terraform agent RPC...
|
|
||||||
==> Terraform agent running!
|
|
||||||
Node name: 'Armons-MacBook-Air'
|
|
||||||
Datacenter: 'dc1'
|
|
||||||
Server: true (bootstrap: true)
|
|
||||||
Client Addr: 127.0.0.1 (HTTP: 8500, DNS: 8600, RPC: 8400)
|
|
||||||
Cluster Addr: 10.1.10.38 (LAN: 8301, WAN: 8302)
|
|
||||||
|
|
||||||
==> Log data will now stream in as it occurs:
|
|
||||||
|
|
||||||
[INFO] serf: EventMemberJoin: Armons-MacBook-Air.local 10.1.10.38
|
|
||||||
[INFO] raft: Node at 10.1.10.38:8300 [Follower] entering Follower state
|
|
||||||
[INFO] terraform: adding server for datacenter: dc1, addr: 10.1.10.38:8300
|
|
||||||
[ERR] agent: failed to sync remote state: rpc error: No cluster leader
|
|
||||||
[WARN] raft: Heartbeat timeout reached, starting election
|
|
||||||
[INFO] raft: Node at 10.1.10.38:8300 [Candidate] entering Candidate state
|
|
||||||
[INFO] raft: Election won. Tally: 1
|
|
||||||
[INFO] raft: Node at 10.1.10.38:8300 [Leader] entering Leader state
|
|
||||||
[INFO] terraform: cluster leadership acquired
|
|
||||||
[INFO] terraform: New leader elected: Armons-MacBook-Air
|
|
||||||
[INFO] terraform: member 'Armons-MacBook-Air' joined, marking health alive
|
|
||||||
```
|
|
||||||
|
|
||||||
As you can see, the Terraform agent has started and has output some log
|
|
||||||
data. From the log data, you can see that our agent is running in server mode,
|
|
||||||
and has claimed leadership of the cluster. Additionally, the local member has
|
|
||||||
been marked as a healthy member of the cluster.
|
|
||||||
|
|
||||||
<div class="alert alert-block alert-warning">
|
|
||||||
<strong>Note for OS X Users:</strong> Terraform uses your hostname as the
|
|
||||||
default node name. If your hostname contains periods, DNS queries to
|
|
||||||
that node will not work with Terraform. To avoid this, explicitly set
|
|
||||||
the name of your node with the <code>-node</code> flag.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Cluster Members
|
|
||||||
|
|
||||||
If you run `terraform members` in another terminal, you can see the members of
|
|
||||||
the Terraform cluster. You should only see one member (yourself). We'll cover
|
|
||||||
joining clusters in the next section.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform members
|
|
||||||
Armons-MacBook-Air 10.1.10.38:8301 alive role=terraform,dc=dc1,vsn=1,vsn_min=1,vsn_max=1,port=8300,bootstrap=1
|
|
||||||
```
|
|
||||||
|
|
||||||
The output shows our own node, the address it is running on, its
|
|
||||||
health state, and some metadata associated with the node. Some important
|
|
||||||
metadata keys to recognize are the `role` and `dc` keys. These tell you
|
|
||||||
the service name and the datacenter that member is within. These can be
|
|
||||||
used to lookup nodes and services using the DNS interface, which is covered
|
|
||||||
shortly.
|
|
||||||
|
|
||||||
The output from the `members` command is generated based on the
|
|
||||||
[gossip protocol](/docs/internals/gossip.html) and is eventually consistent.
|
|
||||||
For a strongly consistent view of the world, use the
|
|
||||||
[HTTP API](/docs/agent/http.html), which forwards the request to the
|
|
||||||
Terraform servers:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl localhost:8500/v1/catalog/nodes
|
|
||||||
[{"Node":"Armons-MacBook-Air","Address":"10.1.10.38"}]
|
|
||||||
```
|
|
||||||
|
|
||||||
In addition to the HTTP API, the
|
|
||||||
[DNS interface](/docs/agent/dns.html) can be used to query the node. Note
|
|
||||||
that you have to make sure to point your DNS lookups to the Terraform agent's
|
|
||||||
DNS server, which runs on port 8600 by default. The format of the DNS
|
|
||||||
entries (such as "Armons-MacBook-Air.node.terraform") will be covered later.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dig @127.0.0.1 -p 8600 Armons-MacBook-Air.node.terraform
|
|
||||||
...
|
|
||||||
|
|
||||||
;; QUESTION SECTION:
|
|
||||||
;Armons-MacBook-Air.node.terraform. IN A
|
|
||||||
|
|
||||||
;; ANSWER SECTION:
|
|
||||||
Armons-MacBook-Air.node.terraform. 0 IN A 10.1.10.38
|
|
||||||
```
|
|
||||||
|
|
||||||
## Stopping the Agent
|
|
||||||
|
|
||||||
You can use `Ctrl-C` (the interrupt signal) to gracefully halt the agent.
|
|
||||||
After interrupting the agent, you should see it leave the cluster gracefully
|
|
||||||
and shut down.
|
|
||||||
|
|
||||||
By gracefully leaving, Terraform notifies other cluster members that the
|
|
||||||
node _left_. If you had forcibly killed the agent process, other members
|
|
||||||
of the cluster would have detected that the node _failed_. When a member leaves,
|
|
||||||
its services and checks are removed from the catalog. When a member fails,
|
|
||||||
its health is simply marked as critical, but is not removed from the catalog.
|
|
||||||
Terraform will automatically try to reconnect to _failed_ nodes, which allows it
|
|
||||||
to recover from certain network conditions, while _left_ nodes are no longer contacted.
|
|
||||||
|
|
||||||
Additionally, if an agent is operating as a server, a graceful leave is important
|
|
||||||
to avoid causing a potential availability outage affecting the [consensus protocol](/docs/internals/consensus.html).
|
|
||||||
See the [guides section](/docs/guides/index.html) to safely add and remove servers.
|
|
||||||
|
|
|
@ -0,0 +1,203 @@
|
||||||
|
---
|
||||||
|
layout: "intro"
|
||||||
|
page_title: "Build Infrastructure"
|
||||||
|
sidebar_current: "gettingstarted-build"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Build Infrastructure
|
||||||
|
|
||||||
|
With Terraform installed, let's dive right into it and start creating
|
||||||
|
some infrastructure.
|
||||||
|
|
||||||
|
We'll build infrastructure on
|
||||||
|
[AWS](http://aws.amazon.com) for the getting started guide
|
||||||
|
since it is popular and generally understood, but Terraform
|
||||||
|
can [manage many providers](#),
|
||||||
|
including multiple providers in a single configuration.
|
||||||
|
Some examples of this are in the
|
||||||
|
[use cases section](/intro/use-cases.html).
|
||||||
|
|
||||||
|
If you don't have an AWS account,
|
||||||
|
[create one now](http://aws.amazon.com/free/).
|
||||||
|
For the getting started guide, we'll only be using resources
|
||||||
|
which qualify under the AWS
|
||||||
|
[free-tier](http://aws.amazon.com/free/),
|
||||||
|
meaning it will be free.
|
||||||
|
If you already have an AWS account, you may be charged some
|
||||||
|
amount of money, but it shouldn't be more than a few dollars
|
||||||
|
at most.
|
||||||
|
|
||||||
|
<div class="alert alert-block alert-warning">
|
||||||
|
<p>
|
||||||
|
<strong>Note:</strong> If you're not using an account that qualifies
|
||||||
|
under the AWS
|
||||||
|
<a href="http://aws.amazon.com/free/">free-tier</a>,
|
||||||
|
you may be charged to run these examples. The most you should
|
||||||
|
be charged should only be a few dollars, but we're not responsible
|
||||||
|
for any charges that may incur.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The set of files used to describe infrastructure in Terraform is simply
|
||||||
|
known as a Terraform _configuration_. We're going to write our first
|
||||||
|
configuration now to launch a single AWS EC2 instance.
|
||||||
|
|
||||||
|
The format of the configuration files is
|
||||||
|
[documented here](#).
|
||||||
|
Configuration files can
|
||||||
|
[also be JSON](#), but we recommend only using JSON when the
|
||||||
|
configuration is generated by a machine.
|
||||||
|
|
||||||
|
The entire configuration is shown below. We'll go over each part
|
||||||
|
after. Save the contents to a file named `example.tf`. Verify that
|
||||||
|
there are no other `*.tf` files in your directory, since Terraform
|
||||||
|
loads all of them.
|
||||||
|
|
||||||
|
```
|
||||||
|
provider "aws" {
|
||||||
|
access_key = "ACCESS_KEY_HERE"
|
||||||
|
secret_key = "SECRET_KEY_HERE"
|
||||||
|
region = "us-east-1"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "example" {
|
||||||
|
ami = "ami-408c7f28"
|
||||||
|
instance_type = "t1.micro"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace the `ACCESS_KEY_HERE` and `SECRET_KEY_HERE` with your
|
||||||
|
AWS access key and secret key, available from
|
||||||
|
[this page](https://console.aws.amazon.com/iam/home?#security_credential).
|
||||||
|
We're hardcoding them for now, but will extract these into
|
||||||
|
variables later in the getting started guide.
|
||||||
|
|
||||||
|
This is a complete configuration that Terraform is ready to apply.
|
||||||
|
The general structure should be intuitive and straightforward.
|
||||||
|
|
||||||
|
The `provider` block is used to configure the named provider, in
|
||||||
|
our case "aws." A provider is responsible for creating and
|
||||||
|
managing resources. Multiple provider blocks can exist if a
|
||||||
|
Terraform configuration is comprised of multiple providers,
|
||||||
|
which is a common situation.
|
||||||
|
|
||||||
|
The `resource` block defines a resource that exists within
|
||||||
|
the infrastructure. A resource might be a physical component such
|
||||||
|
as an EC2 instance, or it can be a logical resource such as
|
||||||
|
a Heroku applcation.
|
||||||
|
|
||||||
|
The resource block has two strings before opening the block:
|
||||||
|
the resource type and the resource name. In our example, the
|
||||||
|
resource type is "aws\_instance" and the name is "example."
|
||||||
|
The prefix of the type maps to the provider. In our case
|
||||||
|
"aws\_instance" automatically tells Terraform that it is
|
||||||
|
managed by the "aws" provider.
|
||||||
|
|
||||||
|
Within the resource block itself is configuration for that
|
||||||
|
resource. This is dependent on each resource provider and
|
||||||
|
is fully documented within our
|
||||||
|
[providers reference](#). For our EC2 instance, we specify
|
||||||
|
an AMI for Ubuntu, and request a "t1.micro" instance so we
|
||||||
|
qualify under the free tier.
|
||||||
|
|
||||||
|
## Execution Plan
|
||||||
|
|
||||||
|
Next, let's see what Terraform would do if we asked it to
|
||||||
|
apply this configuration. In the same directory as the
|
||||||
|
`example.tf` file you created, run `terraform plan`. You
|
||||||
|
should see output similar to what is copied below. We've
|
||||||
|
truncated some of the output to save space.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform plan
|
||||||
|
...
|
||||||
|
|
||||||
|
+ aws_instance.example
|
||||||
|
ami: "" => "ami-408c7f28"
|
||||||
|
availability_zone: "" => "<computed>"
|
||||||
|
instance_type: "" => "t1.micro"
|
||||||
|
key_name: "" => "<computed>"
|
||||||
|
private_dns: "" => "<computed>"
|
||||||
|
private_ip: "" => "<computed>"
|
||||||
|
public_dns: "" => "<computed>"
|
||||||
|
public_ip: "" => "<computed>"
|
||||||
|
security_groups: "" => "<computed>"
|
||||||
|
subnet_id: "" => "<computed>"
|
||||||
|
```
|
||||||
|
|
||||||
|
`terraform plan` shows what changes Terraform will apply to
|
||||||
|
your infrastructure given the current state of your infrastructure
|
||||||
|
as well as the current contents of your configuration.
|
||||||
|
|
||||||
|
If `terraform plan` failed with an error, read the error message
|
||||||
|
and fix the error that occurred. At this stage, it is probably a
|
||||||
|
syntax error in the configuration.
|
||||||
|
|
||||||
|
The output format is similar to the diff format generated by tools
|
||||||
|
such as Git. The output has a "+" next to "aws\_instance.example",
|
||||||
|
meaning that Terraform will create this resource. Beneath that,
|
||||||
|
it shows the attributes that will be set. When the value it is
|
||||||
|
going to is `<computed>`, it means that the value won't be known
|
||||||
|
until the resource is created.
|
||||||
|
|
||||||
|
## Apply
|
||||||
|
|
||||||
|
The plan looks good, our configuration appears valid, so its time to
|
||||||
|
create real resources. Run `terraform apply` in the same directory
|
||||||
|
as your `example.tf`, and watch it go! It will take a few minutes
|
||||||
|
since Terraform waits for the EC2 instance to become available.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform apply
|
||||||
|
aws_instance.example: Creating...
|
||||||
|
ami: "" => "ami-408c7f28"
|
||||||
|
instance_type: "" => "t1.micro"
|
||||||
|
|
||||||
|
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Done! You can go to the AWS console to prove to yourself that the
|
||||||
|
EC2 instance has been created.
|
||||||
|
|
||||||
|
Terraform also put some state into the `terraform.tfstate` file
|
||||||
|
by default. This state file is extremely important; it maps various
|
||||||
|
resource metadata to actual resource IDs so that Terraform knows
|
||||||
|
what it is managing. This file must be saved and distributed
|
||||||
|
to anyone who might run Terraform. We recommend simply putting it
|
||||||
|
into version control, since it generally isn't too large.
|
||||||
|
|
||||||
|
You can inspect the state using `terraform show`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform show
|
||||||
|
aws_instance.example:
|
||||||
|
id = i-e60900cd
|
||||||
|
ami = ami-408c7f28
|
||||||
|
availability_zone = us-east-1c
|
||||||
|
instance_type = t1.micro
|
||||||
|
key_name =
|
||||||
|
private_dns = domU-12-31-39-12-38-AB.compute-1.internal
|
||||||
|
private_ip = 10.200.59.89
|
||||||
|
public_dns = ec2-54-81-21-192.compute-1.amazonaws.com
|
||||||
|
public_ip = 54.81.21.192
|
||||||
|
security_groups.# = 1
|
||||||
|
security_groups.0 = default
|
||||||
|
subnet_id =
|
||||||
|
```
|
||||||
|
|
||||||
|
You can see that by creating our resource, we've also gathered
|
||||||
|
a lot more metadata about it. This metadata can actually be referenced
|
||||||
|
for other resources or outputs, which will be covered later in
|
||||||
|
the getting started guide.
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
Congratulations! You've built your first infrastructure with Terraform.
|
||||||
|
You've seen the configuration syntax, an example of a basic execution
|
||||||
|
plan, and understand the state file.
|
||||||
|
|
||||||
|
Next, we're going to move on to changing and destroying infrastructure.
|
|
@ -0,0 +1,95 @@
|
||||||
|
---
|
||||||
|
layout: "intro"
|
||||||
|
page_title: "Change Infrastructure"
|
||||||
|
sidebar_current: "gettingstarted-change"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Change Infrastructure
|
||||||
|
|
||||||
|
In the previous page, you created your first infrastructure with
|
||||||
|
Terraform: a single EC2 instance. In this page, we're going to
|
||||||
|
modify that resource, and see how Terraform handles change.
|
||||||
|
|
||||||
|
Infrastructure is continuously evolving, and Terraform was built
|
||||||
|
to help manage and enact that change. As you change Terraform
|
||||||
|
configurations, Terraform builds an execution plan that only
|
||||||
|
modifies what is necessary to reach your desired state.
|
||||||
|
|
||||||
|
By using Terraform to change infrastructure, you can version
|
||||||
|
control not only your configurations but also your state so you
|
||||||
|
can see how the infrastructure evolved over time.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Let's modify the `ami` of our instance. Edit the "aws\_instance.web"
|
||||||
|
resource in your configuration and change it to the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "aws_instance" "example" {
|
||||||
|
ami = "ami-aa7ab6c2"
|
||||||
|
instance_type = "t1.micro"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
We've changed the AMI from being an Ubuntu 14.04 AMI to being
|
||||||
|
an Ubuntu 12.04 AMI. Terraform configurations are meant to be
|
||||||
|
changed like this. You can also completely remove resources
|
||||||
|
and Terraform will know to destroy the old one.
|
||||||
|
|
||||||
|
## Execution Plan
|
||||||
|
|
||||||
|
Let's see what Terraform will do with the change we made.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform plan
|
||||||
|
...
|
||||||
|
|
||||||
|
-/+ aws_instance.example
|
||||||
|
ami: "ami-408c7f28" => "ami-aa7ab6c2" (forces new resource)
|
||||||
|
availability_zone: "us-east-1c" => "<computed>"
|
||||||
|
key_name: "" => "<computed>"
|
||||||
|
private_dns: "domU-12-31-39-12-38-AB.compute-1.internal" => "<computed>"
|
||||||
|
private_ip: "10.200.59.89" => "<computed>"
|
||||||
|
public_dns: "ec2-54-81-21-192.compute-1.amazonaws.com" => "<computed>"
|
||||||
|
public_ip: "54.81.21.192" => "<computed>"
|
||||||
|
security_groups: "" => "<computed>"
|
||||||
|
subnet_id: "" => "<computed>"
|
||||||
|
```
|
||||||
|
|
||||||
|
The prefix "-/+" means that Terraform will destroy and recreate
|
||||||
|
the resource, versus purely updating it in-place. While some attributes
|
||||||
|
can do in-place updates (which are shown with a "~" prefix), AMI
|
||||||
|
changing on EC2 instance requires a new resource. Terraform handles
|
||||||
|
these details for you, and the execution plan makes it clear what
|
||||||
|
Terraform will do.
|
||||||
|
|
||||||
|
Additionally, the plan output shows that the AMI change is what
|
||||||
|
necessitated the creation of a new resource. Using this information,
|
||||||
|
you can tweak your changes to possibly avoid destroy/create updates
|
||||||
|
if you didn't want to do them at this time.
|
||||||
|
|
||||||
|
## Apply
|
||||||
|
|
||||||
|
From the plan, we know what will happen. Let's apply and enact
|
||||||
|
the change.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ terraform apply
|
||||||
|
aws_instance.example: Destroying...
|
||||||
|
aws_instance.example: Modifying...
|
||||||
|
ami: "ami-408c7f28" => "ami-aa7ab6c2"
|
||||||
|
|
||||||
|
Apply complete! Resources: 0 added, 1 changed, 1 destroyed.
|
||||||
|
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
As the plan predicted, Terraform started by destroying our old
|
||||||
|
instance, then creating the new one. You can use `terraform show`
|
||||||
|
again to see the new properties associated with this instance.
|
||||||
|
|
||||||
|
## Next
|
||||||
|
|
||||||
|
You've now seen how easy it is to modify infrastructure with
|
||||||
|
Terraform. Feel free to play around with this more before continuing.
|
||||||
|
In the next section we're going to destroy our infrastructure.
|
|
@ -1,94 +0,0 @@
|
||||||
---
|
|
||||||
layout: "intro"
|
|
||||||
page_title: "Registering Health Checks"
|
|
||||||
sidebar_current: "gettingstarted-checks"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Health Checks
|
|
||||||
|
|
||||||
We've now seen how simple it is to run Terraform, add nodes and services, and
|
|
||||||
query those nodes and services. In this section we will continue by adding
|
|
||||||
health checks to both nodes and services, a critical component of service
|
|
||||||
discovery that prevents using services that are unhealthy.
|
|
||||||
|
|
||||||
This page will build upon the previous page and assumes you have a
|
|
||||||
two node cluster running.
|
|
||||||
|
|
||||||
## Defining Checks
|
|
||||||
|
|
||||||
Similarly to a service, a check can be registered either by providing a
|
|
||||||
[check definition](/docs/agent/checks.html)
|
|
||||||
, or by making the appropriate calls to the
|
|
||||||
[HTTP API](/docs/agent/http.html).
|
|
||||||
|
|
||||||
We will use the check definition, because just like services, definitions
|
|
||||||
are the most common way to setup checks.
|
|
||||||
|
|
||||||
Create two definition files in the Terraform configuration directory of
|
|
||||||
the second node.
|
|
||||||
The first file will add a host-level check, and the second will modify the web
|
|
||||||
service definition to add a service-level check.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ echo '{"check": {"name": "ping", "script": "ping -c1 google.com >/dev/null", "interval": "30s"}}' >/etc/terraform.d/ping.json
|
|
||||||
|
|
||||||
$ echo '{"service": {"name": "web", "tags": ["rails"], "port": 80,
|
|
||||||
"check": {"script": "curl localhost:80 >/dev/null 2>&1", "interval": "10s"}}}' >/etc/terraform.d/web.json
|
|
||||||
```
|
|
||||||
|
|
||||||
The first definition adds a host-level check named "ping". This check runs
|
|
||||||
on a 30 second interval, invoking `ping -c1 google.com`. If the command
|
|
||||||
exits with a non-zero exit code, then the node will be flagged unhealthy.
|
|
||||||
|
|
||||||
The second command modifies the web service and adds a check that uses
|
|
||||||
curl every 10 seconds to verify that the web server is running.
|
|
||||||
|
|
||||||
Restart the second agent, or send a `SIGHUP` to it. We should now see the
|
|
||||||
following log lines:
|
|
||||||
|
|
||||||
```
|
|
||||||
==> Starting Terraform agent...
|
|
||||||
...
|
|
||||||
[INFO] agent: Synced service 'web'
|
|
||||||
[INFO] agent: Synced check 'service:web'
|
|
||||||
[INFO] agent: Synced check 'ping'
|
|
||||||
[WARN] Check 'service:web' is now critical
|
|
||||||
```
|
|
||||||
|
|
||||||
The first few log lines indicate that the agent has synced the new
|
|
||||||
definitions. The last line indicates that the check we added for
|
|
||||||
the `web` service is critical. This is because we're not actually running
|
|
||||||
a web server and the curl test is failing!
|
|
||||||
|
|
||||||
## Checking Health Status
|
|
||||||
|
|
||||||
Now that we've added some simple checks, we can use the HTTP API to check
|
|
||||||
them. First, we can look for any failing checks. You can run this curl
|
|
||||||
on either node:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl http://localhost:8500/v1/health/state/critical
|
|
||||||
[{"Node":"agent-two","CheckID":"service:web","Name":"Service 'web' check","Status":"critical","Notes":"","ServiceID":"web","ServiceName":"web"}]
|
|
||||||
```
|
|
||||||
|
|
||||||
We can see that there is only a single check in the `critical` state, which is
|
|
||||||
our `web` service check.
|
|
||||||
|
|
||||||
Additionally, we can attempt to query the web service using DNS. Terraform
|
|
||||||
will not return any results, since the service is unhealthy:
|
|
||||||
|
|
||||||
```
|
|
||||||
dig @127.0.0.1 -p 8600 web.service.terraform
|
|
||||||
...
|
|
||||||
|
|
||||||
;; QUESTION SECTION:
|
|
||||||
;web.service.terraform. IN A
|
|
||||||
```
|
|
||||||
|
|
||||||
This section should have shown that checks can be easily added. Check definitions
|
|
||||||
can be updated by changing configuration files and sending a `SIGHUP` to the agent.
|
|
||||||
Alternatively the HTTP API can be used to add, remove and modify checks dynamically.
|
|
||||||
The API allows for a "dead man's switch" or [TTL based check](/docs/agent/checks.html).
|
|
||||||
TTL checks can be used to integrate an application more tightly with Terraform, enabling
|
|
||||||
business logic to be evaluated as part of passing a check.
|
|
||||||
|
|
|
@ -6,36 +6,25 @@ sidebar_current: "gettingstarted-install"
|
||||||
|
|
||||||
# Install Terraform
|
# Install Terraform
|
||||||
|
|
||||||
Terraform must first be installed on every node that will be a member of a
|
Terraform must first be installed on your machine. Terraform is distributed
|
||||||
Terraform cluster. To make installation easy, Terraform is distributed as a
|
as a [binary package](/downloads.html) for all supported platforms and
|
||||||
[binary package](/downloads.html) for all supported platforms and
|
architecture. This page will not cover how to compile Terraform from
|
||||||
architectures. This page will not cover how to compile Terraform from
|
|
||||||
source.
|
source.
|
||||||
|
|
||||||
## Installing Terraform
|
## Installing Terraform
|
||||||
|
|
||||||
To install Terraform, find the [appropriate package](/downloads.html) for
|
To install Terraform, find the [appropriate package](/downloads.html) for
|
||||||
your system and download it. Terraform is packaged as a "zip" archive.
|
your system and download it. Terraform is packaged as a zip archive.
|
||||||
|
|
||||||
After downloading Terraform, unzip the package. Copy the `terraform` binary to
|
After downloading Terraform, unzip the package into a directory where
|
||||||
somewhere on the PATH so that it can be executed. On Unix systems,
|
Terraform will be installed. The directory will contain a set of binary
|
||||||
`~/bin` and `/usr/local/bin` are common installation directories,
|
programs, such as `terraform`, `terraform-provider-aws`, etc. The final
|
||||||
depending on if you want to restrict the install to a single user or
|
step is to make sure the directory you installed Terraform to is on the
|
||||||
expose it to the entire system. On Windows systems, you can put it wherever
|
PATH. See
|
||||||
you would like.
|
[this page](http://stackoverflow.com/questions/14637979/how-to-permanently-set-path-on-linux)
|
||||||
|
for instructions on setting the PATH on Linux and Mac.
|
||||||
### OS X
|
[This page](http://stackoverflow.com/questions/1618280/where-can-i-set-path-to-make-exe-on-windows)
|
||||||
|
contains instructions for setting the PATH on Windows.
|
||||||
If you are using [homebrew](http://brew.sh/#install) as a package manager,
|
|
||||||
than you can install terraform as simple as:
|
|
||||||
```
|
|
||||||
brew cask install terraform
|
|
||||||
```
|
|
||||||
|
|
||||||
if you are missing the [cask plugin](http://caskroom.io/) you can install it with:
|
|
||||||
```
|
|
||||||
brew install caskroom/cask/brew-cask
|
|
||||||
```
|
|
||||||
|
|
||||||
## Verifying the Installation
|
## Verifying the Installation
|
||||||
|
|
||||||
|
@ -48,15 +37,13 @@ $ terraform
|
||||||
usage: terraform [--version] [--help] <command> [<args>]
|
usage: terraform [--version] [--help] <command> [<args>]
|
||||||
|
|
||||||
Available commands are:
|
Available commands are:
|
||||||
agent Runs a Terraform agent
|
apply Builds or changes infrastructure
|
||||||
force-leave Forces a member of the cluster to enter the "left" state
|
graph Create a visual graph of Terraform resources
|
||||||
info Provides debugging information for operators
|
output Read an output from a state file
|
||||||
join Tell Terraform agent to join cluster
|
plan Generate and show an execution plan
|
||||||
keygen Generates a new encryption key
|
refresh Update local state file against real resources
|
||||||
leave Gracefully leaves the Terraform cluster and shuts down
|
show Inspect Terraform state or plan
|
||||||
members Lists the members of a Terraform cluster
|
version Prints the Terraform version
|
||||||
monitor Stream logs from a Terraform agent
|
|
||||||
version Prints the Terraform version
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you get an error that `terraform` could not be found, then your PATH
|
If you get an error that `terraform` could not be found, then your PATH
|
||||||
|
|
|
@ -1,121 +0,0 @@
|
||||||
---
|
|
||||||
layout: "intro"
|
|
||||||
page_title: "Terraform Cluster"
|
|
||||||
sidebar_current: "gettingstarted-join"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Terraform Cluster
|
|
||||||
|
|
||||||
By this point, we've started our first agent and registered and queried
|
|
||||||
one or more services on that agent. This showed how easy it is to use
|
|
||||||
Terraform, but didn't show how this could be extended to a scalable production
|
|
||||||
service discovery infrastructure. On this page, we'll create our first
|
|
||||||
real cluster with multiple members.
|
|
||||||
|
|
||||||
When starting a Terraform agent, it begins without knowledge of any other node, and is
|
|
||||||
an isolated cluster of one. To learn about other cluster members, the agent must
|
|
||||||
_join_ an existing cluster. To join an existing cluster, only needs to know
|
|
||||||
about a _single_ existing member. After it joins, the agent will gossip with this
|
|
||||||
member and quickly discover the other members in the cluster. A Terraform
|
|
||||||
agent can join any other agent, it doesn't have to be an agent in server mode.
|
|
||||||
|
|
||||||
## Starting the Agents
|
|
||||||
|
|
||||||
To simulate a more realistic cluster, we are using a two node cluster in
|
|
||||||
Vagrant. The Vagrantfile can be found in the demo section of the repo
|
|
||||||
[here](https://github.com/hashicorp/terraform/tree/master/demo/vagrant-cluster).
|
|
||||||
|
|
||||||
We start the first agent on our first node and also specify a node name.
|
|
||||||
The node name must be unique and is how a machine is uniquely identified.
|
|
||||||
By default it is the hostname of the machine, but we'll manually override it.
|
|
||||||
We are also providing a bind address. This is the address that Terraform listens on,
|
|
||||||
and it *must* be accessible by all other nodes in the cluster. The first node
|
|
||||||
will act as our server in this cluster. We're still not making a cluster
|
|
||||||
of servers.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform agent -server -bootstrap -data-dir /tmp/consul \
|
|
||||||
-node=agent-one -bind=172.20.20.10
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, in another terminal, start the second agent on the new node.
|
|
||||||
This time, we set the bind address to match the IP of the second node
|
|
||||||
as specified in the Vagrantfile. In production, you will generally want
|
|
||||||
to provide a bind address or interface as well.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform agent -data-dir /tmp/consul -node=agent-two -bind=172.20.20.11
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
At this point, you have two Terraform agents running, one server and one client.
|
|
||||||
The two Terraform agents still don't know anything about each other, and are each part of their own
|
|
||||||
clusters (of one member). You can verify this by running `terraform members`
|
|
||||||
against each agent and noting that only one member is a part of each.
|
|
||||||
|
|
||||||
## Joining a Cluster
|
|
||||||
|
|
||||||
Now, let's tell the first agent to join the second agent by running
|
|
||||||
the following command in a new terminal:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform join 172.20.20.11
|
|
||||||
Successfully joined cluster by contacting 1 nodes.
|
|
||||||
```
|
|
||||||
|
|
||||||
You should see some log output in each of the agent logs. If you read
|
|
||||||
carefully, you'll see that they received join information. If you
|
|
||||||
run `terraform members` against each agent, you'll see that both agents now
|
|
||||||
know about each other:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform members
|
|
||||||
agent-one 172.20.20.10:8301 alive role=terraform,dc=dc1,vsn=1,vsn_min=1,vsn_max=1,port=8300,bootstrap=1
|
|
||||||
agent-two 172.20.20.11:8301 alive role=node,dc=dc1,vsn=1,vsn_min=1,vsn_max=1
|
|
||||||
```
|
|
||||||
|
|
||||||
<div class="alert alert-block alert-info">
|
|
||||||
<p><strong>Remember:</strong> To join a cluster, a Terraform agent needs to only
|
|
||||||
learn about <em>one existing member</em>. After joining the cluster, the
|
|
||||||
agents gossip with each other to propagate full membership information.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
In addition to using `terraform join` you can use the `-join` flag on
|
|
||||||
`terraform agent` to join a cluster as part of starting up the agent.
|
|
||||||
|
|
||||||
## Querying Nodes
|
|
||||||
|
|
||||||
Just like querying services, Terraform has an API for querying the
|
|
||||||
nodes themselves. You can do this via the DNS or HTTP API.
|
|
||||||
|
|
||||||
For the DNS API, the structure of the names is `NAME.node.terraform` or
|
|
||||||
`NAME.DATACENTER.node.terraform`. If the datacenter is omitted, Terraform
|
|
||||||
will only search the local datacenter.
|
|
||||||
|
|
||||||
From "agent-one", query "agent-two":
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dig @127.0.0.1 -p 8600 agent-two.node.terraform
|
|
||||||
...
|
|
||||||
|
|
||||||
;; QUESTION SECTION:
|
|
||||||
;agent-two.node.terraform. IN A
|
|
||||||
|
|
||||||
;; ANSWER SECTION:
|
|
||||||
agent-two.node.terraform. 0 IN A 172.20.20.11
|
|
||||||
```
|
|
||||||
|
|
||||||
The ability to look up nodes in addition to services is incredibly
|
|
||||||
useful for system administration tasks. For example, knowing the address
|
|
||||||
of the node to SSH into is as easy as making it part of the Terraform cluster
|
|
||||||
and querying it.
|
|
||||||
|
|
||||||
## Leaving a Cluster
|
|
||||||
|
|
||||||
To leave the cluster, you can either gracefully quit an agent (using
|
|
||||||
`Ctrl-C`) or force kill one of the agents. Gracefully leaving allows
|
|
||||||
the node to transition into the _left_ state, otherwise other nodes
|
|
||||||
will detect it as having _failed_. The difference is covered
|
|
||||||
in more detail [here](/intro/getting-started/agent.html#toc_3).
|
|
|
@ -1,118 +0,0 @@
|
||||||
---
|
|
||||||
layout: "intro"
|
|
||||||
page_title: "Key/Value Data"
|
|
||||||
sidebar_current: "gettingstarted-kv"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Key/Value Data
|
|
||||||
|
|
||||||
In addition to providing service discovery and integrated health checking,
|
|
||||||
Terraform provides an easy to use Key/Value store. This can be used to hold
|
|
||||||
dynamic configuration, assist in service coordination, build leader election,
|
|
||||||
and anything else a developer can think to build. The
|
|
||||||
[HTTP API](/docs/agent/http.html) fully documents the features of the K/V store.
|
|
||||||
|
|
||||||
This page assumes you have at least one Terraform agent already running.
|
|
||||||
|
|
||||||
## Simple Usage
|
|
||||||
|
|
||||||
To demonstrate how simple it is to get started, we will manipulate a few keys
|
|
||||||
in the K/V store.
|
|
||||||
|
|
||||||
Querying the agent we started in a prior page, we can first verify that
|
|
||||||
there are no existing keys in the k/v store:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl -v http://localhost:8500/v1/kv/?recurse
|
|
||||||
* About to connect() to localhost port 8500 (#0)
|
|
||||||
* Trying 127.0.0.1... connected
|
|
||||||
> GET /v1/kv/?recurse HTTP/1.1
|
|
||||||
> User-Agent: curl/7.22.0 (x86_64-pc-linux-gnu) libcurl/7.22.0 OpenSSL/1.0.1 zlib/1.2.3.4 libidn/1.23 librtmp/2.3
|
|
||||||
> Host: localhost:8500
|
|
||||||
> Accept: */*
|
|
||||||
>
|
|
||||||
< HTTP/1.1 404 Not Found
|
|
||||||
< X-Terraform-Index: 1
|
|
||||||
< Date: Fri, 11 Apr 2014 02:10:28 GMT
|
|
||||||
< Content-Length: 0
|
|
||||||
< Content-Type: text/plain; charset=utf-8
|
|
||||||
<
|
|
||||||
* Connection #0 to host localhost left intact
|
|
||||||
* Closing connection #0
|
|
||||||
```
|
|
||||||
|
|
||||||
Since there are no keys, we get a 404 response back.
|
|
||||||
Now, we can put a few example keys:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl -X PUT -d 'test' http://localhost:8500/v1/kv/web/key1
|
|
||||||
true
|
|
||||||
$ curl -X PUT -d 'test' http://localhost:8500/v1/kv/web/key2?flags=42
|
|
||||||
true
|
|
||||||
$ curl -X PUT -d 'test' http://localhost:8500/v1/kv/web/sub/key3
|
|
||||||
true
|
|
||||||
$ curl http://localhost:8500/v1/kv/?recurse
|
|
||||||
[{"CreateIndex":97,"ModifyIndex":97,"Key":"web/key1","Flags":0,"Value":"dGVzdA=="},
|
|
||||||
{"CreateIndex":98,"ModifyIndex":98,"Key":"web/key2","Flags":42,"Value":"dGVzdA=="},
|
|
||||||
{"CreateIndex":99,"ModifyIndex":99,"Key":"web/sub/key3","Flags":0,"Value":"dGVzdA=="}]
|
|
||||||
```
|
|
||||||
|
|
||||||
Here we have created 3 keys, each with the value of "test". Note that the
|
|
||||||
`Value` field returned is base64 encoded to allow non-UTF8
|
|
||||||
characters. For the "web/key2" key, we set a `flag` value of 42. All keys
|
|
||||||
support setting a 64bit integer flag value. This is opaque to Terraform but can
|
|
||||||
be used by clients for any purpose.
|
|
||||||
|
|
||||||
After setting the values, we then issued a GET request to retrieve multiple
|
|
||||||
keys using the `?recurse` parameter.
|
|
||||||
|
|
||||||
You can also fetch a single key just as easily:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl http://localhost:8500/v1/kv/web/key1
|
|
||||||
[{"CreateIndex":97,"ModifyIndex":97,"Key":"web/key1","Flags":0,"Value":"dGVzdA=="}]
|
|
||||||
```
|
|
||||||
|
|
||||||
Deleting keys is simple as well. We can delete a single key by specifying the
|
|
||||||
full path, or we can recursively delete all keys under a root using "?recurse":
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl -X DELETE http://localhost:8500/v1/kv/web/sub?recurse
|
|
||||||
$ curl http://localhost:8500/v1/kv/web?recurse
|
|
||||||
[{"CreateIndex":97,"ModifyIndex":97,"Key":"web/key1","Flags":0,"Value":"dGVzdA=="},
|
|
||||||
{"CreateIndex":98,"ModifyIndex":98,"Key":"web/key2","Flags":42,"Value":"dGVzdA=="}]
|
|
||||||
```
|
|
||||||
|
|
||||||
A key can be updated by setting a new value by issuing the same PUT request.
|
|
||||||
Additionally, Terraform provides a Check-And-Set operation, enabling atomic
|
|
||||||
key updates. This is done by providing the `?cas=` paramter with the last
|
|
||||||
`ModifyIndex` value from the GET request. For example, suppose we wanted
|
|
||||||
to update "web/key1":
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl -X PUT -d 'newval' http://localhost:8500/v1/kv/web/key1?cas=97
|
|
||||||
true
|
|
||||||
$ curl -X PUT -d 'newval' http://localhost:8500/v1/kv/web/key1?cas=97
|
|
||||||
false
|
|
||||||
```
|
|
||||||
|
|
||||||
In this case, the first CAS update succeeds because the last modify time is 97.
|
|
||||||
However the second operation fails because the `ModifyIndex` is no longer 97.
|
|
||||||
|
|
||||||
We can also make use of the `ModifyIndex` to wait for a key's value to change.
|
|
||||||
For example, suppose we wanted to wait for key2 to be modified:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl "http://localhost:8500/v1/kv/web/key2?index=101&wait=5s"
|
|
||||||
[{"CreateIndex":98,"ModifyIndex":101,"Key":"web/key2","Flags":42,"Value":"dGVzdA=="}]
|
|
||||||
```
|
|
||||||
|
|
||||||
By providing "?index=" we are asking to wait until the key has a `ModifyIndex` greater
|
|
||||||
than 101. However the "?wait=5s" parameter restricts the query to at most 5 seconds,
|
|
||||||
returning the current, unchanged value. This can be used to efficiently wait for
|
|
||||||
key modifications. Additionally, this same technique can be used to wait for a list
|
|
||||||
of keys, waiting only until any of the keys has a newer modification time.
|
|
||||||
|
|
||||||
This is only a few example of what the API supports. For full documentation, please
|
|
||||||
reference the [HTTP API](/docs/agent/http.html).
|
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
---
|
|
||||||
layout: "intro"
|
|
||||||
page_title: "Registering Services"
|
|
||||||
sidebar_current: "gettingstarted-services"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Registering Services
|
|
||||||
|
|
||||||
In the previous page, we ran our first agent, saw the cluster members, and
|
|
||||||
queried that node. On this page, we'll register our first service and query
|
|
||||||
that service. We're not yet running a cluster of Terraform agents.
|
|
||||||
|
|
||||||
## Defining a Service
|
|
||||||
|
|
||||||
A service can be registered either by providing a
|
|
||||||
[service definition](/docs/agent/services.html),
|
|
||||||
or by making the appropriate calls to the
|
|
||||||
[HTTP API](/docs/agent/http.html).
|
|
||||||
|
|
||||||
We're going to start by registering a service using a service definition,
|
|
||||||
since this is the most common way that services are registered. We'll be
|
|
||||||
building on what we covered in the
|
|
||||||
[previous page](/intro/getting-started/agent.html).
|
|
||||||
|
|
||||||
First, create a directory for Terraform configurations. A good directory
|
|
||||||
is typically `/etc/terraform.d`. Terraform loads all configuration files in the
|
|
||||||
configuration directory.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ sudo mkdir /etc/terraform.d
|
|
||||||
```
|
|
||||||
|
|
||||||
Next, we'll write a service definition configuration file. We'll
|
|
||||||
pretend we have a service named "web" running on port 80. Additionally,
|
|
||||||
we'll give it some tags, which we can use as additional ways to query
|
|
||||||
it later.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ echo '{"service": {"name": "web", "tags": ["rails"], "port": 80}}' \
|
|
||||||
>/etc/terraform.d/web.json
|
|
||||||
```
|
|
||||||
|
|
||||||
Now, restart the agent we're running, providing the configuration directory:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform agent -server -bootstrap -data-dir /tmp/consul -config-dir /etc/consul.d
|
|
||||||
==> Starting Terraform agent...
|
|
||||||
...
|
|
||||||
[INFO] agent: Synced service 'web'
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll notice in the output that it "synced" the web service. This means
|
|
||||||
that it loaded the information from the configuration.
|
|
||||||
|
|
||||||
If you wanted to register multiple services, you create multiple service
|
|
||||||
definition files in the Terraform configuration directory.
|
|
||||||
|
|
||||||
## Querying Services
|
|
||||||
|
|
||||||
Once the agent is started and the service is synced, we can query that
|
|
||||||
service using either the DNS or HTTP API.
|
|
||||||
|
|
||||||
### DNS API
|
|
||||||
|
|
||||||
Let's first query it using the DNS API. For the DNS API, the DNS name
|
|
||||||
for services is `NAME.service.terraform`. All DNS names are always in the
|
|
||||||
`terraform` namespace. The `service` subdomain on that tells Terraform we're
|
|
||||||
querying services, and the `NAME` is the name of the service. For the
|
|
||||||
web service we registered, that would be `web.service.terraform`:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dig @127.0.0.1 -p 8600 web.service.terraform
|
|
||||||
...
|
|
||||||
|
|
||||||
;; QUESTION SECTION:
|
|
||||||
;web.service.terraform. IN A
|
|
||||||
|
|
||||||
;; ANSWER SECTION:
|
|
||||||
web.service.terraform. 0 IN A 172.20.20.11
|
|
||||||
```
|
|
||||||
|
|
||||||
As you can see, an A record was returned with the IP address of the node that
|
|
||||||
the service is available on. A records can only hold IP addresses. You can
|
|
||||||
also use the DNS API to retrieve the entire address/port pair using SRV
|
|
||||||
records:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dig @127.0.0.1 -p 8600 web.service.terraform SRV
|
|
||||||
...
|
|
||||||
|
|
||||||
;; QUESTION SECTION:
|
|
||||||
;web.service.terraform. IN SRV
|
|
||||||
|
|
||||||
;; ANSWER SECTION:
|
|
||||||
web.service.terraform. 0 IN SRV 1 1 80 agent-one.node.dc1.consul.
|
|
||||||
|
|
||||||
;; ADDITIONAL SECTION:
|
|
||||||
agent-one.node.dc1.terraform. 0 IN A 172.20.20.11
|
|
||||||
```
|
|
||||||
|
|
||||||
The SRV record returned says that the web service is running on port 80
|
|
||||||
and exists on the node `agent-one.node.dc1.terraform.`. An additional section
|
|
||||||
is returned by the DNS with the A record for that node.
|
|
||||||
|
|
||||||
Finally, we can also use the DNS API to filter services by tags. The
|
|
||||||
format for tag-based service queries is `TAG.NAME.service.terraform`. In
|
|
||||||
the example below, we ask Terraform for all web services with the "rails"
|
|
||||||
tag. We get a response since we registered our service with that tag.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ dig @127.0.0.1 -p 8600 rails.web.service.terraform
|
|
||||||
...
|
|
||||||
|
|
||||||
;; QUESTION SECTION:
|
|
||||||
;rails.web.service.terraform. IN A
|
|
||||||
|
|
||||||
;; ANSWER SECTION:
|
|
||||||
rails.web.service.terraform. 0 IN A 172.20.20.11
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTTP API
|
|
||||||
|
|
||||||
In addition to the DNS API, the HTTP API can be used to query services:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ curl http://localhost:8500/v1/catalog/service/web
|
|
||||||
[{"Node":"agent-one","Address":"172.20.20.11","ServiceID":"web","ServiceName":"web","ServiceTags":["rails"],"ServicePort":80}]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Updating Services
|
|
||||||
|
|
||||||
Service definitions can be updated by changing configuration files and
|
|
||||||
sending a `SIGHUP` to the agent. This lets you update services without
|
|
||||||
any downtime or unavailability to service queries.
|
|
||||||
|
|
||||||
Alternatively the HTTP API can be used to add, remove, and modify services
|
|
||||||
dynamically.
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
---
|
|
||||||
layout: "intro"
|
|
||||||
page_title: "Web UI"
|
|
||||||
sidebar_current: "gettingstarted-ui"
|
|
||||||
---
|
|
||||||
|
|
||||||
# Terraform Web UI
|
|
||||||
|
|
||||||
Terraform comes with support for a
|
|
||||||
[beautiful, functional web UI](http://demo.terraform.io) out of the box.
|
|
||||||
This UI can be used for viewing all services and nodes, viewing all
|
|
||||||
health checks and their current status, and for reading and setting
|
|
||||||
key/value data. The UI automatically supports multi-datacenter.
|
|
||||||
|
|
||||||
For ease of deployment, the UI is
|
|
||||||
[distributed](/downloads_web_ui.html)
|
|
||||||
as static HTML and JavaScript.
|
|
||||||
You don't need a separate web server to run the web UI. The Terraform
|
|
||||||
agent itself can be configured to serve the UI.
|
|
||||||
|
|
||||||
## Screenshot and Demo
|
|
||||||
|
|
||||||
You can view a live demo of the Terraform Web UI
|
|
||||||
[here](http://demo.terraform.io).
|
|
||||||
|
|
||||||
While the live demo is able to access data from all datacenters,
|
|
||||||
we've also setup demo endpoints in the specific datacenters:
|
|
||||||
[AMS2](http://ams2.demo.terraform.io) (Amsterdam),
|
|
||||||
[SFO1](http://sfo1.demo.terraform.io) (San Francisco),
|
|
||||||
and [NYC1](http://nyc1.demo.terraform.io) (New York).
|
|
||||||
|
|
||||||
A screenshot of one page of the demo is shown below so you can get an
|
|
||||||
idea of what the web UI is like. Click the screenshot for the full size.
|
|
||||||
|
|
||||||
<div class="center">
|
|
||||||
<a href="/images/terraform_web_ui.png">
|
|
||||||
<img src="/images/terraform_web_ui.png">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Set Up
|
|
||||||
|
|
||||||
To set up the web UI,
|
|
||||||
[download the web UI package](/downloads_web_ui.html)
|
|
||||||
and unzip it to a directory somewhere on the server where the Terraform agent
|
|
||||||
is also being run. Then, just append the `-ui-dir` to the `terraform agent`
|
|
||||||
command pointing to the directory where you unzipped the UI (the
|
|
||||||
directory with the `index.html` file):
|
|
||||||
|
|
||||||
```
|
|
||||||
$ terraform agent -ui-dir /path/to/ui
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
The UI is available at the `/ui` path on the same port as the HTTP API.
|
|
||||||
By default this is `http://localhost:8500/ui`.
|
|
|
@ -13,29 +13,9 @@
|
||||||
<li<%= sidebar_current("vs-other") %>>
|
<li<%= sidebar_current("vs-other") %>>
|
||||||
<a href="/intro/vs/index.html">Terraform vs. Other Software</a>
|
<a href="/intro/vs/index.html">Terraform vs. Other Software</a>
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
<li<%= sidebar_current("vs-other-zk") %>>
|
|
||||||
<a href="/intro/vs/zookeeper.html">ZooKeeper, doozerd, etcd</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li<%= sidebar_current("vs-other-chef") %>>
|
<li<%= sidebar_current("vs-other-chef") %>>
|
||||||
<a href="/intro/vs/chef-puppet.html">Chef, Puppet, etc.</a>
|
<a href="/intro/vs/chef-puppet.html">Chef, Puppet, etc.</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("vs-other-nagios-sensu") %>>
|
|
||||||
<a href="/intro/vs/nagios-sensu.html">Nagios, Sensu</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li<%= sidebar_current("vs-other-skydns") %>>
|
|
||||||
<a href="/intro/vs/skydns.html">SkyDNS</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li<%= sidebar_current("vs-other-smartstack") %>>
|
|
||||||
<a href="/intro/vs/smartstack.html">SmartStack</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li<%= sidebar_current("vs-other-serf") %>>
|
|
||||||
<a href="/intro/vs/serf.html">Serf</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li<%= sidebar_current("vs-other-custom") %>>
|
<li<%= sidebar_current("vs-other-custom") %>>
|
||||||
<a href="/intro/vs/custom.html">Custom Solutions</a>
|
<a href="/intro/vs/custom.html">Custom Solutions</a>
|
||||||
|
@ -50,34 +30,37 @@
|
||||||
<a href="/intro/getting-started/install.html">Install Terraform</a>
|
<a href="/intro/getting-started/install.html">Install Terraform</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("gettingstarted-agent") %>>
|
<li<%= sidebar_current("gettingstarted-build") %>>
|
||||||
<a href="/intro/getting-started/agent.html">Run the Agent</a>
|
<a href="/intro/getting-started/build.html">Build Infrastructure</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("gettingstarted-services") %>>
|
<li<%= sidebar_current("gettingstarted-change") %>>
|
||||||
<a href="/intro/getting-started/services.html">Services</a>
|
<a href="/intro/getting-started/change.html">Change Infrastructure</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("gettingstarted-join") %>>
|
<li<%= sidebar_current("gettingstarted-destroy") %>>
|
||||||
<a href="/intro/getting-started/join.html">Terraform Cluster</a>
|
<a href="/intro/getting-started/destroy.html">Destroy Infrastructure</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("gettingstarted-checks") %>>
|
<li<%= sidebar_current("gettingstarted-outputs") %>>
|
||||||
<a href="/intro/getting-started/checks.html">Health Checks</a>
|
<a href="/intro/getting-started/outputs.html">Output Variables</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("gettingstarted-kv") %>>
|
<li<%= sidebar_current("gettingstarted-deps") %>>
|
||||||
<a href="/intro/getting-started/kv.html">Key/Value Data</a>
|
<a href="/intro/getting-started/dependencies.html">Resource Dependencies</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("gettingstarted-ui") %>>
|
<li<%= sidebar_current("gettingstarted-variables") %>>
|
||||||
<a href="/intro/getting-started/ui.html">Web UI</a>
|
<a href="/intro/getting-started/variables.html">Input Variables</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("gettingstarted-variables") %>>
|
||||||
|
<a href="/intro/getting-started/provisioners.html">Provision</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("gettingstarted-nextsteps") %>>
|
<li<%= sidebar_current("gettingstarted-nextsteps") %>>
|
||||||
<a href="/intro/getting-started/next-steps.html">Next Steps</a>
|
<a href="/intro/getting-started/next-steps.html">Next Steps</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
Loading…
Reference in New Issue