• Stars
    star
    189
  • Rank 204,649 (Top 5 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created over 6 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Envoy Control Plane for Kubernetes Multi-cluster Ingress

Yggdrasil

Yggdrasil is an Envoy control plane that configures listeners and clusters based off Kubernetes ingresses from multiple Kube Clusters. This allows you to have an envoy cluster acting as a mutli-cluster loadbalancer for Kubernetes. This was something we needed as we wanted our apps to be highly available in the event of a cluster outage but did not want the solution to live inside of Kubernetes itself.

Note: Currently we support versions 1.20.x to 1.26.x of Envoy.
Note: Yggdrasil now uses Go modules to handle dependencies.

Usage

Yggdrasil will watch all Ingresses in each Kubernetes Cluster that you give it via the Kubeconfig flag. Any ingresses that match any of the ingress classes that you have specified will have a listener and cluster created that listens on the same Host as the Host defined in the Ingress object. If you have multiple clusters Yggdrasil will create a cluster address for each Kubernetes cluster your Ingress is in, the address is the address of the ingress loadbalancer.

Joseph Irving has published a blog post which describes our need for and use of Yggdrasil at Uswitch.

Setup

Please see the Getting Started guide for a walkthrough of setting up a simple HTTP service with Yggdrasil and envoy.

The basic setup is to have a cluster of envoy nodes which connect to Yggdrasil via GRPC and get given dynamic listeners and clusters from it. Yggdrasil is set up to talk to each Kubernetes api where it will watch the ingresses for any that are using the ingress class it's watching for.

Yggdrasil Diagram

Your envoy nodes only need a very minimal config where they are simply set up to get dynamic clusters and listeners from Yggdrasil. Example envoy config:

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address: { address: 0.0.0.0, port_value: 9901 }

dynamic_resources:
  lds_config:
    resource_api_version: V3
    api_config_source:
      transport_api_version: V3
      api_type: GRPC
      grpc_services:
      - envoy_grpc:
          cluster_name: xds_cluster
  cds_config:
    resource_api_version: V3
    api_config_source:
      transport_api_version: V3
      api_type: GRPC
      grpc_services:
      - envoy_grpc:
          cluster_name: xds_cluster

static_resources:
  clusters:
  - name: xds_cluster
    connect_timeout: 0.25s
    type: STATIC
    lb_policy: ROUND_ROBIN
    http2_protocol_options: {}
    load_assignment:
      cluster_name: xds_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: yggdrasil
                port_value: 8080

Your ingress set up then looks like this:

Envoy Diagram

Where the envoy nodes are loadbalancing between each cluster for a given ingress.

Health Check

Yggdrasil always configures a path on your Envoy nodes at /yggdrasil/status, this can be used to health check your envoy nodes, it will only return 200 if your nodes have started and been configured by Yggdrasil.

Annotations

Yggdrasil allows for some customisation of the route and cluster config per Ingress through the annotations below.

Name type
yggdrasil.uswitch.com/healthcheck-path string
yggdrasil.uswitch.com/timeout duration
yggdrasil.uswitch.com/retry-on string

Health Check Path

Specifies a path to configure a HTTP health check to. Envoy will not route to clusters that fail health checks.

Timeout

Allows for adjusting the timeout in envoy. Currently this will set the following timeouts to this value:

Retries

Allows overwriting the default retry policy's config.route.v3.RetryPolicy.RetryOn set by the --retry-on flag (default 5xx). Accepts a comma-separated list of retry-on policies.

Example

Below is an example of an ingress with some of the annotations specified

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: example-com
  namespace: default
  annotations:
    yggdrasil.uswitch.com/healthcheck-path: /healthz
    yggdrasil.uswitch.com/timeout: 30s
    yggdrasil.uswitch.com/retry-on: gateway-error,connect-failure
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: example
          servicePort: 80

Dynamic TLS certificates synchronization from Kubernetes secrets

Downstream TLS certificates can be dynamically fetched and updated from Kubernetes secrets configured under ingresses' spec.tls by setting syncSecrets true in Yggdrasil configuration (false by default).

In this mode, only a single certificate may be specified in Yggdrasil configuration. It will be used for hosts with misconfigured or invalid secret.

Note: ECDSA >256 keys are not supported by envoy and will be discarded. See envoyproxy/envoy#10855

Configuration

Yggdrasil can be configured using a config file e.g:

{
  "nodeName": "foo",
  "ingressClasses": ["multi-cluster", "multi-cluster-staging"],
  "syncSecrets": false,
  "certificates": [
    {
      "hosts": ["*.api.com"],
      "cert": "path/to/cert",
      "key": "path/to/key"
    }
  ],
  "clusters": [
    {
      "token": "xxxxxxxxxxxxxxxx",
      "apiServer": "https://cluster1.api.com",
      "ca": "pathto/cluster1/ca"
    },
    {
      "tokenPath": "/path/to/a/token",
      "apiServer": "https://cluster2.api.com",
      "ca": "pathto/cluster2/ca"
    }
  ]
}

The list of certificates will be loaded by Yggdrasil and served to the Envoy nodes by inlining the key pairs. These will then be used to group the ingress into different filter chains, split using hosts.

nodeName is the same node-name that you start your envoy nodes with. The ingressClasses is a list of ingress classes that yggdrasil will watch for. Each cluster represents a different Kubernetes cluster with the token being a service account token for that cluster. ca is the Path to the ca certificate for that cluster.

Metrics

Yggdrasil has a number of Go, gRPC, Prometheus, and Yggdrasil-specific metrics built in which can be reached by cURLing the /metrics path at the health API address/port (default: 8081). See Flags for more information on configuring the health API address/port.

The Yggdrasil-specific metrics which are available from the API are:

Name Description Type
yggdrasil_cluster_updates Number of times the clusters have been updated counter
yggdrasil_clusters Total number of clusters generated gauge
yggdrasil_ingresses Total number of matching ingress objects gauge
yggdrasil_listener_updates Number of times the listener has been updated counter
yggdrasil_virtual_hosts Total number of virtual hosts generated gauge

Flags

--address string                              yggdrasil envoy control plane listen address (default "0.0.0.0:8080")
--ca string                                   trustedCA
--cert string                                 certfile
--config string                               config file
--config-dump                                 Enable config dump endpoint at /configdump on the health-address HTTP server
--debug                                       Log at debug level
--envoy-listener-ipv4-address string          IPv4 address by the envoy proxy to accept incoming connections (default "0.0.0.0")
--envoy-port uint32                           port by the envoy proxy to accept incoming connections (default 10000)
--health-address string                       yggdrasil health API listen address (default "0.0.0.0:8081")
-h, --help                                        help for yggdrasil
--host-selection-retry-attempts int           Number of host selection retry attempts. Set to value >=0 to enable (default -1)
--http-ext-authz-allow-partial-message        When this field is true, Envoy will buffer the message until max_request_bytes is reached (default true)
--http-ext-authz-cluster string               The name of the upstream gRPC cluster
--http-ext-authz-failure-mode-allow           Changes filters behaviour on errors (default true)
--http-ext-authz-max-request-bytes uint32     Sets the maximum size of a message body that the filter will hold in memory (default 8192)
--http-ext-authz-pack-as-bytes                When this field is true, Envoy will send the body as raw bytes.
--http-ext-authz-timeout duration             The timeout for the gRPC request. This is the timeout for a specific request. (default 200ms)
--http-grpc-logger-cluster string             The name of the upstream gRPC cluster
--http-grpc-logger-name string                Name of the access log
--http-grpc-logger-request-headers strings    access logs request headers
--http-grpc-logger-response-headers strings   access logs response headers
--http-grpc-logger-timeout duration           The timeout for the gRPC request (default 200ms)
--ingress-classes strings                     Ingress classes to watch
--key string                                  keyfile
--kube-config stringArray                     Path to kube config
--max-ejection-percentage int32               maximal percentage of hosts ejected via outlier detection. Set to >=0 to activate outlier detection in envoy. (default -1)
--node-name string                            envoy node name
--retry-on string                             default comma-separated list of retry policies (default "5xx")
--upstream-healthcheck-healthy uint32         number of successful healthchecks before the backend is considered healthy (default 3)
--upstream-healthcheck-interval duration      duration of the upstream health check interval (default 10s)
--upstream-healthcheck-timeout duration       timeout of the upstream healthchecks (default 5s)
--upstream-healthcheck-unhealthy uint32       number of failed healthchecks before the backend is considered unhealthy (default 3)
--upstream-port uint32                        port used to connect to the upstream ingresses (default 443)
--use-remote-address                          populates the X-Forwarded-For header with the client address. Set to true when used as edge proxy

More Repositories

1

kiam

Integrate AWS IAM with Kubernetes
Go
1,135
star
2

lambada

A more passionate way to write AWS Lambda functions
Clojure
315
star
3

blueshift

Automate copying data from S3 into Amazon Redshift
Clojure
119
star
4

bifrost

Safely archive data from Apache Kafka to S3 with no Hadoop dependencies :)
Clojure
100
star
5

vault-creds

Sidecar container for requesting dynamic Vault database secrets
Go
86
star
6

nidhogg

Kubernetes Node taints based on Daemonset Pods
Go
73
star
7

terrafying

A small ruby dsl for terraform.
Ruby
58
star
8

torus-pong

A massive multiplayer online take on the arcade classic, written as a part of Clojure Cup 2013
Clojure
50
star
9

speculate

A library that transforms clojure.spec
Clojure
44
star
10

klint

A 'realtime' kubernetes resource linter
Go
41
star
11

sqs-autoscaler-controller

Kubernetes controller for scaling Deployments based on AWS SQS queue length
Go
31
star
12

serverless-hooks-plugin

A plugin to run arbitrary commands on any lifecycle event in serverless
JavaScript
30
star
13

vault-webhook

Kubernetes Mutating Webhook to inject Vault-Creds Sidecar into pods
Go
26
star
14

baldr-old-dead

Pure and light binary records
Clojure
23
star
15

surtr

AWS Kubernetes Node Terminator
Go
22
star
16

heimdall

Generate PrometheusRule CRDs from Ingress annotations and Go templates
Go
22
star
17

big-replicate

Replicates data between Google Cloud BigQuery projects
Clojure
21
star
18

journald-forwarder

Forward systemd journals to Loggly
Go
21
star
19

ustyle

A living styleguide and pattern library by uSwitch.
Smarty
19
star
20

syslogger

Forwards syslog messages to Kafka
Go
16
star
21

koa-core

🎾 Core libraries and example project of how to use @uswitch/koa libraries
JavaScript
16
star
22

ej

a tool to convert from EDN to JSON
Haskell
16
star
23

opencensus-clojure

Clojure
15
star
24

transducers-workshop

Transducers workshop slides and labs
Clojure
15
star
25

incident-app

Incident Management Slack Bot
Ruby
13
star
26

analytij

Clojure client library to interact with the Google Analytics API
Clojure
12
star
27

bqshift

Export data from Redshift to BigQuery
Go
12
star
28

hermod

The Messenger of the Gods
Go
11
star
29

clj-rad

Clojure wrapper of Netflix Surus Robust Anomaly Detection
Clojure
9
star
30

k8s-podmon

A service to monitor failing jobs and pods
Go
9
star
31

loglet

Forward journald log messages to Kafka
Go
8
star
32

adworj

Clojure library to make it easier to interact with Google AdWords
Clojure
8
star
33

rest-client-logger

Adds logging of RestClient requests to the Rails debug log
Ruby
7
star
34

ustyle-react

uStyle + React for the people.
JavaScript
7
star
35

node-problem-detector

Custom plugins for node-problem-detector used in uSwitch
Shell
7
star
36

ssi-loader

Webpack ssi loader
JavaScript
7
star
37

kf

kafka follow
Go
6
star
38

dagr

runs programs every day (in Norse mythology, Dagr is day personified)
Go
6
star
39

etcd-experiment

An experiment in zero downtime clojure app deployments using etcd
Clojure
6
star
40

koa-access

💀DEPRECATED 👌A Koa middleware for reporting JSON access logs
JavaScript
6
star
41

vault-tokens

Generates Vault tokens for a User based off their AD groups
Go
5
star
42

ontology

Ruby
4
star
43

fsnotify

Cross-platform file system notifications for Go. https://fsnotify.org
Go
4
star
44

elastic-log-lag

Calculates the log lag on Elasticsearch indexes
Go
3
star
45

terraform-provider-segment

A Terraform provider to manage Segment resources via code.
Go
3
star
46

terrafying-components

Ruby
3
star
47

blueshift-riemann-metrics

Riemann metric publishing for Blueshift
Clojure
3
star
48

kubernetes-google-auth

Go
2
star
49

log4-clj-layout

Clojure
2
star
50

labs-window-functions

Provides a docker environment for playing with window functions in PostgreSQL
Shell
2
star
51

rack-ssi

Rack middleware for SSI processing, based on nginx HttpSsiModule
Ruby
2
star
52

terraform-aws-to-gcp-vpn

Creates infrastructure in AWS and GCP for HA VPNs between the two.
HCL
2
star
53

fads

Clojure
1
star
54

browser-tools

Suite of favelets, chrome extensions, audits and snippets to help test and debug the uSwitch website in the browser.
JavaScript
1
star
55

trustyle

React components with style
TypeScript
1
star
56

hypermq

Hypermedia (AtomPub like) message queue
Clojure
1
star
57

rabbitmq-worker

A small wrapper around the Langohr RabbitMQ client
Clojure
1
star
58

fed-convert

Converts Kubernetes resource files into Federated resources
Go
1
star
59

bdcat

decode baldr files in Go
Go
1
star
60

ontology-ui

JavaScript
1
star
61

stdout-fs

Python
1
star
62

instance-signals

Go
1
star
63

riemann-redis-info

Ruby
1
star
64

baldrcat

Tool to print contents of .baldr archives on S3
Clojure
1
star
65

uswitch-academy

Stuff related to courses, internal training and logistic thereof.
JavaScript
1
star
66

airship-aio-ticketing

composite github action for ticketing
1
star
67

bqstream

Stream newline-delimited JSON into BigQuery from STDIN
Go
1
star
68

ookla-netgauge-server

Docker image definition for Ookla Netgauge Server
1
star
69

dockerfiles-etcd-srv-bootstrap

etcd and helper script to do DNS/SRV discovery
Python
1
star