Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ make setup-local # Install dependencies locally
make test # Run test suite
make test-docker # Run tests in Docker container
make lint # Check code style with StandardRB
make docs-config # Regenerate docs/configuration.md from docs/config-schema.json
make fix # Auto-fix code style issues
make console # Start interactive Ruby console
make clean # Remove generated files
Expand Down Expand Up @@ -65,10 +66,17 @@ This uses the repo's `.venv` for pre-commit. If you already have `pre-commit` on
bundle exec bin/nerve --help

# Validate config
bundle exec bin/nerve -c example/nerve.conf.json --check
bundle exec bin/nerve -c example/nerve.conf.json --check-config

# Run with config (requires ZooKeeper)
bundle exec bin/nerve -c example/nerve.conf.json

# Run with config + CLI overrides
bundle exec bin/nerve \
-c example/nerve.conf.json \
--instance-id my-host \
--prometheus-enabled=true \
--statsd-host statsd.local
```

## Project Structure
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ test-docker: ## Run tests in Docker container
lint: ## Check code style with StandardRB
$(BUNDLE) exec standardrb

.PHONY: docs-config
docs-config: ## Regenerate configuration reference from JSON schema
$(BUNDLE) exec ruby scripts/generate_config_docs.rb

.PHONY: fix
fix: ## Auto-fix code style issues
$(BUNDLE) exec standardrb --fix
Expand Down
80 changes: 9 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,81 +43,19 @@ for your infra/apps.

## Configuration ##

Nerve depends on a single configuration file, in json format.
It is usually called `nerve.conf.json`.
An example config file is available in `example/nerve.conf.json`.
The config file is composed of two main sections:
Nerve builds its effective configuration from three sources:

* `instance_id`: the name nerve will submit when registering services; makes debugging easier
* `heartbeat_path`: a path to a file on disk to touch as nerve makes progress. This allows you to work around https://github.com/zk-ruby/zk/issues/50 by restarting a stuck nerve.
* `services`: the hash (from service name to config) of the services nerve will be monitoring
* `service_conf_dir`: path to a directory in which each json file will be interpreted as a service with the basename of the file minus the .json extension
* Base config file (`--config`)
* Optional overlay config (`--config-overlay`, deep-merged)
* Optional CLI overrides (applied last)

### Services Config ###
Start with `example/nerve.conf.json` for a working baseline.

Each service that nerve will be monitoring is specified in the `services` hash.
The key is the name of the service, and the value is a configuration hash telling nerve how to monitor the service.
The configuration contains the following options:
For the full reference, including merge semantics, precedence, CLI flag scope,
and service/check/reporter fields, see:

* `host`: the default host on which to make service checks; you should make this your *public* ip to ensure your service is publicly accessible
* `port`: the default port for service checks; nerve will report the `host`:`port` combo via your chosen reporter
* `reporter_type`: the mechanism used to report up/down information; depending on the reporter you choose, additional parameters may be required. Defaults to `zookeeper`
* `check_interval`: the frequency with which service checks will be initiated; defaults to `500ms`
* `check_mocked`: whether or not health check is mocked, the host check always returns healthy and report up when the value is true
* `checks`: a list of checks that nerve will perform; if all of the pass, the service will be registered; otherwise, it will be un-registered
* `rate_limiting` (optional): a hash containing the configuration for rate limiting (see 'Rate Limiting' below)
* `weight` (optional): a positive integer weight value which can be used to affect the haproxy backend weighting in synapse.
* `haproxy_server_options` (optional): a string containing any special haproxy server options for this service instance. For example if you wanted to set a service instance as a backup.
* `labels` (optional): an object containing user-defined key-value pairs that describe this service instance. For example, you could label service instances with datacenter information.

#### Rate Limiting ####

Rate limiting is configured in the `rate_limiting` hash. If enabled, rate limiting is done via the [Token-Bucket algorithm](https://en.wikipedia.org/wiki/Token_bucket).
That hash contains the following values:

* `shadow_mode` (optional): shadow mode emits metrics/logs for rate limiting, but does not actually throttle requests (defaults to `true`). Set to `false` to throttle requests.
* `average_rate` (optional): enforced average rate limit for reporting (defaults to `infinity`)
* `max_burst` (optional): enforced maximum burst for reporting (defaults to `infinity`)

#### Zookeeper Reporter ####

If you set your `reporter_type` to `"zookeeper"` you should also set these parameters:

* `zk_hosts`: a list of the zookeeper hosts comprising the [ensemble](https://zookeeper.apache.org/doc/r3.1.2/zookeeperAdmin.html#sc_zkMulitServerSetup) that nerve will submit registration to
* `zk_path`: the path (or [znode](https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html#sc_zkDataModel_znodes)) where the registration will be created; nerve will create the [ephemeral node](https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html#Ephemeral+Nodes) that is the registration as a child of this path
* `use_path_encoding`: flag to turn on path encoding optimization, the canonical config data at host level (e.g. ip, port, az) is encoded using json base64 and written as zk child name, the zk child data will still be written for backward compatibility

#### Etcd Reporter ####

Note: Etcd support is currently experimental!

If you set your `reporter_type` to `"etcd"` you should also set these parameters:

* `etcd_host`: etcd host that nerve will submit registration to
* `etcd_port`: port to connect to etcd.
* `etcd_path`: the path where the registration will be created; nerve will create a node with a 30s ttl that is the registration as a child of this path, and then update it every few seconds

### Checks ###

The core of nerve is a set of service checks.
Each service can define a number of checks, and all of them must pass for the service to be registered.
Although the exact parameters passed to each check are different, all take a number of common arguments:

* `type`: (required) the kind of check; you can see available check types in the `lib/nerve/service_watcher` dir of this repo
* `name`: (optional) a descriptive, human-readable name for the check; it will be auto-generated based on the other parameters if not specified
* `host`: (optional) the host on which the check will be performed; defaults to the `host` of the service to which the check belongs
* `port`: (optional) the port on which the check will be performed; like `host`, it defaults to the `port` of the service
* `timeout`: (optional) maximum time the check can take; defaults to `100ms`
* `rise`: (optional) how many consecutive checks must pass before the check is considered passing; defaults to 1
* `fall`: (optional) how many consecutive checks must fail before the check is considered failing; defaults to 1

#### Custom External Checks ####

If you would like to run a custom check but don't feel like trying to get it merged into this project, there is a mechanism for including external checks thanks to @bakins (airbnb/nerve#36).
Build your custom check as a separate gem and make sure to `bundle install` it on your system.

Ideally, you should name your gem `"nerve-watcher-#{type}"`, as that is what nerve will `require` on boot.
However, if you have a custom name for your gem, you can specify that in the `module` argument to the check.
* [`docs/configuration.md`](docs/configuration.md)
* [`docs/config-schema.json`](docs/config-schema.json)

## Contributing

Expand Down
Loading