├── .gitattributes
├── .gitignore
├── .machine
├── .gitignore
└── env
├── apps
├── .editorconfig
├── .gitignore
├── src
│ ├── Consumer
│ │ ├── Job.cs
│ │ ├── consumer.nomad
│ │ ├── Consumer.csproj
│ │ ├── Configuration.cs
│ │ └── Program.cs
│ └── Producer
│ │ ├── Job.cs
│ │ ├── Producer.csproj
│ │ ├── Program.cs
│ │ └── Configuration.cs
└── Apps.sln
├── rabbit
├── build.sh
├── rabbitmq.conf
├── Dockerfile
└── rabbit.nomad
├── scripts
├── build.sh
└── host.sh
├── vagrantfile
├── LICENSE
├── readme.md
└── box
└── common.sh
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.sh eol=lf
2 | *.conf eol=lf
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vagrant/
2 | .artifacts/
3 | .vscode/
--------------------------------------------------------------------------------
/.machine/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 | !env
--------------------------------------------------------------------------------
/apps/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 | indent_size = 4
3 | indent_style = tab
4 |
--------------------------------------------------------------------------------
/rabbit/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | docker build -t rabbitmq:consul .
4 |
5 |
--------------------------------------------------------------------------------
/apps/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | obj/
3 | .idea/
4 | .build/
5 |
6 | *.user
7 | *.zip
8 |
--------------------------------------------------------------------------------
/apps/src/Consumer/Job.cs:
--------------------------------------------------------------------------------
1 | namespace Jobs
2 | {
3 | public class Job
4 | {
5 | public int Sequence { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/.machine/env:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | export NOMAD_ADDR=http://one.karhu.xyz:4646
4 | export VAULT_ADDR=http://one.karhu.xyz:8200
5 |
--------------------------------------------------------------------------------
/apps/src/Producer/Job.cs:
--------------------------------------------------------------------------------
1 | namespace Jobs
2 | {
3 | public class Job
4 | {
5 | public int Sequence { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/rabbit/rabbitmq.conf:
--------------------------------------------------------------------------------
1 | cluster_formation.peer_discovery_backend = rabbit_peer_discovery_consul
2 | cluster_formation.consul.svc_addr_auto = true
3 |
--------------------------------------------------------------------------------
/rabbit/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM rabbitmq:management-alpine
2 | COPY rabbitmq.conf /etc/rabbitmq
3 | RUN rabbitmq-plugins enable --offline rabbitmq_peer_discovery_consul
4 |
--------------------------------------------------------------------------------
/apps/src/Producer/Producer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 | latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/apps/src/Consumer/consumer.nomad:
--------------------------------------------------------------------------------
1 | job "consumer" {
2 | datacenters = ["dc1"]
3 | type = "service"
4 |
5 | group "consumers" {
6 | count = 1
7 |
8 | task "consumer" {
9 | driver = "exec"
10 |
11 | config {
12 | command = "/usr/bin/dotnet"
13 | args = [
14 | "local/Consumer.dll"
15 | ]
16 | }
17 |
18 | artifact {
19 | source = "http://artifacts.service.consul:3000/Consumer.zip"
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/scripts/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | output_dir=".artifacts"
4 |
5 | mkdir -p "$output_dir"
6 | rm -rf $output_dir/*.zip
7 |
8 | pushd apps
9 |
10 | find ./src -iname "*.csproj" | while read project_path; do
11 |
12 | project_name=$(basename "$project_path" .csproj)
13 |
14 | dotnet publish "$project_path" --output "bin/$project_name"
15 |
16 | publish_path="./bin/$project_name"
17 | output_zip="../$output_dir/$project_name.zip"
18 |
19 | 7z a "$output_zip" "$publish_path/*" > /dev/null
20 |
21 | done
22 |
23 | popd
24 |
--------------------------------------------------------------------------------
/vagrantfile:
--------------------------------------------------------------------------------
1 | Vagrant.configure(2) do |config|
2 | config.vm.box = "local/hashibox"
3 |
4 | config.vm.provider "hyperv" do |h, override|
5 | h.memory = "1024"
6 | h.linked_clone = true
7 |
8 | override.vm.network "public_network", bridge: "Default Switch"
9 | end
10 |
11 | config.vm.provider "libvirt" do |lv, override|
12 | lv.memory = 1024
13 | override.vm.synced_folder "./", "/vagrant", type: 'nfs'
14 | end
15 |
16 | config.vm.define "one" do |n1|
17 | n1.vm.hostname = "one"
18 | end
19 |
20 | config.vm.define "two" do |n2|
21 | n2.vm.hostname = "two"
22 | end
23 |
24 | config.vm.define "three" do |n3|
25 | n3.vm.hostname = "three"
26 | end
27 |
28 | config.vm.provision "shell", privileged: true, path: './box/common.sh'
29 |
30 | end
31 |
--------------------------------------------------------------------------------
/apps/src/Consumer/Consumer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 | latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/apps/src/Consumer/Configuration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading.Tasks;
3 | using Consul;
4 |
5 | namespace Consumer
6 | {
7 | public class Configuration : IDisposable
8 | {
9 | private static readonly Random Random = new Random();
10 | private readonly ConsulClient _consul;
11 |
12 | public Configuration()
13 | {
14 | _consul = new ConsulClient();
15 | }
16 |
17 | public async Task GetRabbitBroker()
18 | {
19 | var service = await GetService("rabbitmq", "amqp");
20 |
21 | var builder = new UriBuilder
22 | {
23 | Scheme = "rabbitmq",
24 | Host = service.Address,
25 | Port = service.ServicePort
26 | };
27 |
28 | return builder.Uri;
29 | }
30 |
31 | private async Task GetService(string serviceName, string tag = null)
32 | {
33 | var service = await _consul.Catalog.Service(serviceName, tag);
34 | var index = Random.Next(0, service.Response.Length - 1);
35 |
36 | return service.Response[index];
37 | }
38 |
39 | public void Dispose()
40 | {
41 | _consul.Dispose();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/apps/src/Producer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using Jobs;
5 | using MassTransit;
6 |
7 | namespace Producer
8 | {
9 | class Program
10 | {
11 | public static async Task Main(string[] args)
12 | {
13 | var config = new Configuration();
14 | var broker = await config.GetRabbitBroker();
15 |
16 | var bus = Bus.Factory.CreateUsingRabbitMq(c =>
17 | {
18 | c.Host(broker, r =>
19 | {
20 | r.Username("admin");
21 | r.Password("admin");
22 | });
23 | });
24 |
25 | await bus.StartAsync();
26 |
27 | var total = args
28 | .Where(x => int.TryParse(x, out _))
29 | .Select(int.Parse)
30 | .DefaultIfEmpty(1000)
31 | .First();
32 |
33 | Console.WriteLine($"Publishing {total} jobs...");
34 |
35 | for (var i = 0; i < total; i++)
36 | await bus.Publish(
37 | new Job { Sequence = i },
38 | context => context.MessageId = Guid.NewGuid()
39 | );
40 |
41 | await bus.StopAsync();
42 | config.Dispose();
43 |
44 | Console.WriteLine("Done");
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/apps/src/Producer/Configuration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using Consul;
5 |
6 | namespace Producer
7 | {
8 | public class Configuration : IDisposable
9 | {
10 | private static readonly Random Random = new Random();
11 | private readonly ConsulClient _consul;
12 |
13 | public Configuration()
14 | {
15 | _consul = new ConsulClient();
16 | }
17 |
18 | public async Task GetRabbitBroker()
19 | {
20 | var service = await GetService("rabbitmq", "amqp");
21 |
22 | var builder = new UriBuilder
23 | {
24 | Scheme = "rabbitmq",
25 | Host = service.Address,
26 | Port = service.ServicePort
27 | };
28 |
29 | return builder.Uri;
30 | }
31 |
32 | private async Task GetService(string serviceName, string tag = null)
33 | {
34 | var service = await _consul.Catalog.Service(serviceName, tag);
35 | var instance = service.Response[Random.Next(0, service.Response.Length - 1)];
36 |
37 | return instance;
38 | }
39 |
40 | public void Dispose()
41 | {
42 | _consul.Dispose();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Andy Davies
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Nomad Demo
2 |
3 | Repository to go with my talk on [Nomad: Kubernetes without the Complexity](https://andydote.co.uk/presentations/index.html?nomad).
4 |
5 | ## Tooling
6 |
7 | Required:
8 | * Hyper-v - You can adapt the `Vagrantfile`s to other virtualisation tools if you want
9 | * [Vagrant](https://www.vagrantup.com/) - for the VMs
10 | * [Nomad](https://www.nomadproject.io/) - to interact with the cluster
11 | * Bash - gitbash is fine
12 |
13 | Optionals:
14 | * [Consul](https://www.consul.io) - run a consul node on your local machine to host other services
15 | * Tmux - just makes running one of the scripts easier
16 |
17 | ## Setup
18 |
19 | 1. start the cluster
20 | ```shell
21 | ./scripts/init.sh # or make sure there is a host_ip file at repo root with your host machine ip in it
22 | vagrant up
23 | ```
24 | 1. Run all the demo junk
25 | * if you have tmux:
26 | ```shell
27 | ./scripts/demo.sh
28 | ```
29 | * if you don't, run a separate shell for each of these:
30 | * `./scripts/consul.sh`
31 | * `./scripts/host.sh`
32 | 1. in a shell (as admin on windows), run this:
33 | ```shell
34 | export NOMAD_ADDR="http://$(cat server_ip):4646"
35 | nomad status
36 | ```
37 | You can now run jobs:
38 | ```shell
39 | nomad job run rabbit/rabbit.nomad
40 | ```
41 |
42 |
43 | Good Luck!
44 |
--------------------------------------------------------------------------------
/apps/src/Consumer/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Jobs;
5 | using MassTransit;
6 | using Microsoft.Extensions.Configuration;
7 |
8 | namespace Consumer
9 | {
10 | class Program
11 | {
12 | private static Random Random = new Random();
13 |
14 | public static async Task Main(string[] args)
15 | {
16 | var config = new Configuration();
17 | var broker = await config.GetRabbitBroker();
18 |
19 | var bus = Bus.Factory.CreateUsingRabbitMq(c =>
20 | {
21 | var host = c.Host(broker, r =>
22 | {
23 | r.Username("admin");
24 | r.Password("admin");
25 | });
26 |
27 | c.ReceiveEndpoint(host, "Jobs", ep => ep.Handler(OnJob));
28 | });
29 |
30 | await bus.StartAsync();
31 |
32 | WaitForCancel();
33 |
34 | await bus.StopAsync();
35 | config.Dispose();
36 | }
37 |
38 | private static async Task OnJob(ConsumeContext context)
39 | {
40 | var duration = TimeSpan.FromSeconds(Random.Next(0, 5));
41 |
42 | await Task.Delay(duration);
43 |
44 | Console.WriteLine($"Processing {context.Message.Sequence} took {duration.TotalSeconds} seconds");
45 | }
46 |
47 | private static void WaitForCancel()
48 | {
49 | var pause = new ManualResetEvent(false);
50 | Console.WriteLine("Press Ctrl+C to exit");
51 |
52 | Console.CancelKeyPress += (sender, e) =>
53 | {
54 | Console.WriteLine("Shutting down...");
55 | e.Cancel = true;
56 | pause.Set();
57 | };
58 |
59 | pause.WaitOne();
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/rabbit/rabbit.nomad:
--------------------------------------------------------------------------------
1 | job "rabbit" {
2 |
3 | datacenters = ["dc1"]
4 | type = "service"
5 |
6 | group "cluster" {
7 | count = 1
8 |
9 | update {
10 | max_parallel = 1
11 | }
12 |
13 | migrate {
14 | max_parallel = 1
15 | health_check = "checks"
16 | min_healthy_time = "5s"
17 | healthy_deadline = "30s"
18 | }
19 |
20 | task "rabbit" {
21 | driver = "docker"
22 |
23 | config {
24 | image = "registry.service.consul:5000/pondidum/rabbitmq:consul"
25 | hostname = "${attr.unique.hostname}"
26 | port_map {
27 | amqp = 5672
28 | ui = 15672
29 | discovery = 4369
30 | clustering = 25672
31 | }
32 | }
33 |
34 | vault {
35 | policies = ["rabbit"]
36 | }
37 |
38 | env {
39 | CONSUL_HOST = "${attr.unique.network.ip-address}"
40 | CONSUL_SVC_PORT = "${NOMAD_HOST_PORT_amqp}"
41 | CONSUL_SVC_TAGS = "amqp"
42 | }
43 |
44 | template {
45 | data = < Configuring host containers"
6 | # machine_ip=$(ip route get 1 | awk '{print $(NF-2);exit}')
7 | machine_ip=$(ip addr show docker0 | awk '$1 == "inet" {gsub(/\/.*$/, "", $2); print $2}')
8 | echo " HostIP: $machine_ip"
9 |
10 | echo " Running Consul"
11 | docker run -d --rm \
12 | --name nomad-consul \
13 | --net=host \
14 | -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true}' \
15 | consul agent -bind="$machine_ip" -retry-join="one.karhu.xyz"
16 |
17 | echo " Running docker registry"
18 | docker run -d --rm \
19 | --name nomad-registry \
20 | -p 5000:5000 \
21 | registry:latest
22 |
23 | echo " Running http artifacts server"
24 | docker run -d --rm \
25 | --name nomad-artifacts \
26 | -p 3000:3000 \
27 | -e 'PORT=3000' \
28 | -v "$PWD/.artifacts:/web" \
29 | halverneus/static-file-server:latest
30 |
31 | echo "==> Pusing rabbitmq:consul to docker registry"
32 | docker tag rabbitmq:consul localhost:5000/pondidum/rabbitmq:consul
33 | docker push localhost:5000/pondidum/rabbitmq:consul
34 |
35 | echo "==> Registering services into Consul"
36 |
37 | echo " http artifacts host"
38 | curl --silent \
39 | --request PUT \
40 | --url http://localhost:8500/v1/agent/service/register \
41 | --header 'content-type: application/json' \
42 | --data '{ "ID": "artifacts", "Name": "artifacts", "Port": 3000 }'
43 |
44 | echo " docker registry"
45 | curl --silent \
46 | --request PUT \
47 | --url http://localhost:8500/v1/agent/service/register \
48 | --header 'content-type: application/json' \
49 | --data '{ "ID": "registry", "Name": "registry", "Port": 5000 }'
50 |
51 | echo "==> Consul Status"
52 |
53 | consul members
54 |
55 | source .machine/one
56 |
57 | echo "==> Writing into Vault"
58 |
59 | vault secrets enable -path=secret -version=2 kv
60 |
61 | echo 'path "secret/data/rabbit" {
62 | capabilities = ["read"]
63 | }' | vault policy write rabbit -
64 |
65 | vault kv put secret/rabbit \
66 | cookie="$(cat /proc/sys/kernel/random/uuid)" \
67 | admin_user="admin" \
68 | admin_pass="admin"
69 |
70 | echo "==> Done."
71 |
--------------------------------------------------------------------------------
/apps/Apps.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{615CF37F-0D4A-40AA-8BC2-BAC6B06461DA}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Consumer", "src\Consumer\Consumer.csproj", "{2076C05B-11FF-4B9D-9DB6-51942A51B3A4}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Producer", "src\Producer\Producer.csproj", "{81515672-2893-4F57-B362-D6F909174B10}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Debug|x64 = Debug|x64
16 | Debug|x86 = Debug|x86
17 | Release|Any CPU = Release|Any CPU
18 | Release|x64 = Release|x64
19 | Release|x86 = Release|x86
20 | EndGlobalSection
21 | GlobalSection(SolutionProperties) = preSolution
22 | HideSolutionNode = FALSE
23 | EndGlobalSection
24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
25 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Debug|x64.ActiveCfg = Debug|Any CPU
28 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Debug|x64.Build.0 = Debug|Any CPU
29 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Debug|x86.ActiveCfg = Debug|Any CPU
30 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Debug|x86.Build.0 = Debug|Any CPU
31 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
32 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Release|Any CPU.Build.0 = Release|Any CPU
33 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Release|x64.ActiveCfg = Release|Any CPU
34 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Release|x64.Build.0 = Release|Any CPU
35 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Release|x86.ActiveCfg = Release|Any CPU
36 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4}.Release|x86.Build.0 = Release|Any CPU
37 | {81515672-2893-4F57-B362-D6F909174B10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
38 | {81515672-2893-4F57-B362-D6F909174B10}.Debug|Any CPU.Build.0 = Debug|Any CPU
39 | {81515672-2893-4F57-B362-D6F909174B10}.Debug|x64.ActiveCfg = Debug|Any CPU
40 | {81515672-2893-4F57-B362-D6F909174B10}.Debug|x64.Build.0 = Debug|Any CPU
41 | {81515672-2893-4F57-B362-D6F909174B10}.Debug|x86.ActiveCfg = Debug|Any CPU
42 | {81515672-2893-4F57-B362-D6F909174B10}.Debug|x86.Build.0 = Debug|Any CPU
43 | {81515672-2893-4F57-B362-D6F909174B10}.Release|Any CPU.ActiveCfg = Release|Any CPU
44 | {81515672-2893-4F57-B362-D6F909174B10}.Release|Any CPU.Build.0 = Release|Any CPU
45 | {81515672-2893-4F57-B362-D6F909174B10}.Release|x64.ActiveCfg = Release|Any CPU
46 | {81515672-2893-4F57-B362-D6F909174B10}.Release|x64.Build.0 = Release|Any CPU
47 | {81515672-2893-4F57-B362-D6F909174B10}.Release|x86.ActiveCfg = Release|Any CPU
48 | {81515672-2893-4F57-B362-D6F909174B10}.Release|x86.Build.0 = Release|Any CPU
49 | EndGlobalSection
50 | GlobalSection(NestedProjects) = preSolution
51 | {2076C05B-11FF-4B9D-9DB6-51942A51B3A4} = {615CF37F-0D4A-40AA-8BC2-BAC6B06461DA}
52 | {81515672-2893-4F57-B362-D6F909174B10} = {615CF37F-0D4A-40AA-8BC2-BAC6B06461DA}
53 | EndGlobalSection
54 | EndGlobal
55 |
--------------------------------------------------------------------------------
/box/common.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | echo "==> Configuring Consul"
4 | (
5 | cat <<-EOF
6 | {
7 | "data_dir": "/var/consul",
8 | "client_addr": "127.0.0.1 {{ GetInterfaceIP \"eth0\" }}",
9 | "bind_addr": "{{ GetInterfaceIP \"eth0\" }}",
10 | "ui": true,
11 | "server": true,
12 | "bootstrap_expect": 3,
13 | "retry_join": [ "one.karhu.xyz", "two.karhu.xyz", "three.karhu.xyz" ],
14 | "connect": {
15 | "enabled": true
16 | }
17 | }
18 | EOF
19 | ) | tee /etc/consul/consul.json
20 |
21 | rc-update add consul
22 | rc-service consul start
23 |
24 | sleep 2 # allow agent to start
25 |
26 | echo " waiting for cluster to form"
27 | while [ "$(consul operator raft list-peers | grep -c leader)" != "1" ]; do
28 | sleep 1
29 | done
30 |
31 | echo " Done"
32 |
33 | echo "==> Configuring Vault"
34 |
35 | (
36 | cat < /tmp/vault_init 2>/dev/null";
63 | then
64 | echo " Initialised Vault"
65 | init_json=$(cat /tmp/vault_init)
66 | consul kv put vagrant/init "$init_json"
67 | else
68 | echo " Already initialised"
69 | sleep 2s
70 | init_json=$(consul kv get vagrant/init)
71 | fi
72 |
73 | root_token=$(echo "$init_json" | jq -r .root_token)
74 | unseal_key=$(echo "$init_json" | jq -r .unseal_keys_b64[0])
75 |
76 | echo " Root Token: $root_token"
77 | echo " Unseal Key: $unseal_key"
78 |
79 | vault operator unseal "$unseal_key"
80 |
81 | echo " Vault Unsealed"
82 |
83 | echo "==> Configuring Nomad"
84 |
85 | export VAULT_TOKEN="$root_token"
86 | escaped_token=$(echo "$root_token" | sed -e 's/[\/&]/\\&/g')
87 |
88 | (
89 | cat <<-EOF
90 | data_dir = "/var/nomad"
91 |
92 | client {
93 | enabled = true
94 | }
95 |
96 | server {
97 | enabled = true
98 | bootstrap_expect = 3
99 | }
100 |
101 | vault {
102 | enabled = true
103 | address = "http://vault.service.consul:8200"
104 | token = "$escaped_token"
105 | }
106 | EOF
107 | ) | tee /etc/nomad/nomad.hcl
108 |
109 | rc-update add nomad
110 | rc-service nomad start
111 |
112 | echo " Nomad started"
113 |
114 | echo "==> Configuring Docker"
115 |
116 | echo '
117 | {
118 | "insecure-registries": [
119 | "registry.service.consul:5000"
120 | ],
121 | "dns": [
122 | "192.168.121.1"
123 | ]
124 | }' | tee /etc/docker/daemon.json
125 |
126 | rc-service docker restart
127 |
128 | echo "==> Exporting machine info"
129 |
130 | rm -f "/vagrant/.machine/$HOSTNAME"
131 | echo "export VAULT_ADDR=http://$HOSTNAME.karhu.xyz:8200" >> "/vagrant/.machine/$HOSTNAME"
132 | echo "export VAULT_TOKEN=$root_token" >> "/vagrant/.machine/$HOSTNAME"
133 | echo "export VAULT_UNSEAL=$unseal_key" >> "/vagrant/.machine/$HOSTNAME"
134 | echo "export NOMAD_ADDR=http://$HOSTNAME.karhu.xyz:8200" >> "/vagrant/.machine/$HOSTNAME"
135 |
--------------------------------------------------------------------------------