Skip to content
This repository has been archived by the owner on Jul 1, 2023. It is now read-only.

Refactor for initial release #5

Merged
merged 12 commits into from
Apr 22, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ ARG BASE_IMAGE
ARG RIGGING_IMAGE

#
# Use a tempoary ubuntu container to get/build the wg cli
# Use a temporary ubuntu container to get/build the wg cli
#
FROM ${WIREGUARD_IMAGE} as wireguard
ADD assets/docker/wireguard/wireguard_ubuntu_wireguard.gpg /etc/apt/trusted.gpg.d/wireguard_ubuntu_wireguard.gpg
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Wormhole is a simple [CNI plugin](https://github.com/containernetworking/cni) de

[WireGuard](https://www.wireguard.com) is a fascinating Fast, Modern, Secure VPN tunnel, that has been gaining significant praise from security experts, and is currently proposed for inclusion within the linux kernel.

Wormhole uses wireguard to create a simple and secure high performance encrypted overlay network for kubernetes clusters, that is easy to manage and troubleshoot.
Wormhole uses WireGuard to create a simple and secure high performance encrypted overlay network for kubernetes clusters, that is easy to manage and troubleshoot.

Wormhole does not implement network policy, instead we recommend to use [calico](https://github.com/projectcalico/calico) or [kube-router](https://github.com/cloudnativelabs/kube-router) as network policy controllers.

Expand All @@ -16,7 +16,7 @@ The Gravitational Wormhole project is currently considered experimental, and has
## Getting Started

### System Requirements
knisbet marked this conversation as resolved.
Show resolved Hide resolved
1. [Wireguard](https://www.wireguard.com/install/) is installed on each node in you're cluster.
1. [WireGuard](https://www.wireguard.com/install/) is installed on each node in you're cluster.
2. A Kubernetes cluster with IPAM enabled (--pod-network-cidr= when using kubeadm based install)

### Install
Expand Down
2 changes: 1 addition & 1 deletion build.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (Build) BuildContainer() error {

type Test mg.Namespace

// All runs all defined test
// All runs all defined tests
func (Test) All() error {
mg.Deps(Test.Unit, Test.Lint)
return nil
Expand Down
26 changes: 18 additions & 8 deletions cmd/wormhole/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
"os/signal"
"syscall"

"github.com/sirupsen/logrus"

"github.com/magefile/mage/sh"

"github.com/gravitational/trace"
Expand Down Expand Up @@ -122,34 +124,42 @@ func runController(cmd *cobra.Command, args []string) error {
return trace.Wrap(err)
}

logger := logrus.New()
if debug {
logger.SetLevel(logrus.DebugLevel)
}

c, err := controller.New(controller.Config{
knisbet marked this conversation as resolved.
Show resolved Hide resolved
NodeName: nodeName,
Namespace: namespace,
OverlayCIDR: overlayCIDR,
NodeCIDR: nodeCIDR,
Port: port,
ListenPort: port,
WireguardIface: wireguardIface,
BridgeIface: bridgeIface,
KubeconfigPath: kubeconfigPath,
Endpoint: endpoint,
EnableDebug: debug,
})
}, logger)
if err != nil {
return trace.Wrap(err)
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

go func() {
signalC := make(chan os.Signal, 1)
signal.Notify(signalC, os.Interrupt, syscall.SIGTERM)

<-signalC
cancel()
}()

err = c.Run(ctx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand, Run is blocking - then watching for signals below is not working as expected - something needs to run in a goroutune.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, it originally worked differently and I missed the change. What i've done is move the signal handling to a separate routine, and cancels the context.

if err != nil {
if err != nil && trace.Unwrap(err) != context.Canceled {
return trace.Wrap(err)
}

signalC := make(chan os.Signal, 2)
signal.Notify(signalC, os.Interrupt, syscall.SIGTERM)

<-signalC
return nil
}

Expand Down
6 changes: 0 additions & 6 deletions docs/gravity-wormhole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: wgnodes.wormhole.gravitational.io
spec:
group: wormhole.gravitational.io
Expand Down Expand Up @@ -32,16 +31,12 @@ metadata:
name: wormhole
namespace: wormhole
spec:
allowPrivilegeEscalation: false
allowedCapabilities: ["NET_ADMIN"]
hostPID: false
fsGroup:
rule: RunAsAny
hostNetwork: false
hostPorts:
- max: 65535
min: 1024
privileged: false
runAsUser:
rule: RunAsAny
seLinux:
Expand Down Expand Up @@ -184,7 +179,6 @@ spec:
fieldRef:
fieldPath: metadata.namespace
securityContext:
privileged: false
readOnlyRootFilesystem: true
capabilities:
add: ["NET_ADMIN"]
Expand Down
8 changes: 1 addition & 7 deletions docs/kube-wormhole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
creationTimestamp: null
name: wgnodes.wormhole.gravitational.io
spec:
group: wormhole.gravitational.io
Expand Down Expand Up @@ -32,16 +31,12 @@ metadata:
name: wormhole
namespace: wormhole
spec:
allowPrivilegeEscalation: false
allowedCapabilities: ["NET_ADMIN"]
hostPID: false
fsGroup:
rule: RunAsAny
hostNetwork: false
hostPorts:
- max: 65535
min: 1024
privileged: false
runAsUser:
rule: RunAsAny
seLinux:
Expand Down Expand Up @@ -204,7 +199,7 @@ spec:
# Run a wormhole container on each node
# Configures wireguard / CNI on each node
- name: wormhole
image: quay.io/gravitational/wormhole-dev:0.0.1-5-g672d3a7-dirty
image: quay.io/gravitational/wormhole-dev:0.0.1-9-g696cc34-dirty
command:
- /wormhole
args:
Expand All @@ -219,7 +214,6 @@ spec:
fieldRef:
fieldPath: metadata.namespace
securityContext:
privileged: false
readOnlyRootFilesystem: true
capabilities:
add: ["NET_ADMIN"]
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/wormhole.gravitational.io/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ limitations under the License.
package wormholegravitationalio
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a common package naming pattern used for Kubernetes 3rd party APIs? Reads weird.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I believe this is a required format / path structure to match the CRD group name as a path (wormhole.gravitational.io)


const (
// GroupName is the kubernetes CRD group name for this object
GroupName = "wormhole.gravitational.io"
knisbet marked this conversation as resolved.
Show resolved Hide resolved
)
10 changes: 7 additions & 3 deletions pkg/apis/wormhole.gravitational.io/v1beta1/wgnode_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ type WgnodeSpec struct {

// WgnodeStatus defines the observed state of Wgnode
type WgnodeStatus struct {
Port int `json:"port"`
// Port is the port to connect to wireguard on this host
Port int `json:"port"`
// PublicKey is the public key of the wireguard node
PublicKey string `json:"public_key"`
NodeCIDR string `json:"node_cidr"`
Endpoint string `json:"endpoint"`
// NodeCIDR is the IP address range in CIDR format assigned to this node
NodeCIDR string `json:"node_cidr"`
// Endpoint is the IP address to connect to this node
Endpoint string `json:"endpoint"`
}

// +genclient
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/cni.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ func (d *controller) configureCNI() error {
// Investigate what MTU setting to use. There are a few things to consider:
// - 65535 is the maximum mtu that can be set on a bridge
// - This depends significantly, on how the linux kernel represents packets as they pass between
// network namespaces and through the linux bridge. If they'rerepresented as ethernet packets,
// network namespaces and through the linux bridge. If they're represented as ethernet packets,
// a large mtu should allow pod-to-pod within a host to be more efficient
// - Wireguard implements it's own segmentation, and indicates to the linux kernel that it supports
// - Wireguard implements its own segmentation, and indicates to the linux kernel that it supports
// generic segmentation offload (https://www.wireguard.com/papers/wireguard.pdf section 7.1). If
// the bridge MTU plays into this, again, having a large mtu should be more efficient for pod-to-pod
// traffic between hosts.
Expand Down
50 changes: 20 additions & 30 deletions pkg/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ type Config struct {
// NodeCIDR is the IP network in CIDR format assigned to this node
NodeCIDR string

// Port is the external port wireguard should listen on between hosts
Port int
// ListenPort is the external port wireguard should listen on between hosts
ListenPort int

// WireguardIface is the name of the wireguard interface for encrypted node to node traffic
WireguardIface string
Expand All @@ -63,9 +63,6 @@ type Config struct {
// Endpoint is the networking address that is available for routing between all wireguard nodes
// In general this should be the same as the AdvertiseIP Address of the node
Endpoint string

// EnableDebug enable debug logging
EnableDebug bool
}

type Controller interface {
Expand All @@ -84,6 +81,9 @@ type controller struct {
// ipamInfo is IPAM info about the node
ipamInfo *ipamInfo

//overlayCidr is the IP network for the entire overlay network
overlayCIDR net.IPNet

// wireguardInterface is a controller for managing / updating our wireguard interface
wireguardInterface wireguard.Interface

Expand All @@ -93,19 +93,13 @@ type controller struct {
secretController cache.Controller
secretLister listers.SecretLister

errC chan error
resyncC chan interface{}
}

func New(config Config) (Controller, error) {
logger := logrus.New()
if config.EnableDebug {
logger.SetLevel(logrus.DebugLevel)
}
func New(config Config, logger logrus.FieldLogger) (Controller, error) {
controller := &controller{
FieldLogger: logger,
config: config,
errC: make(chan error, 1),
resyncC: make(chan interface{}, 1),
}

Expand Down Expand Up @@ -149,11 +143,16 @@ func (d *controller) init() error {

if d.config.OverlayCIDR == "" {
d.Info("Attempting to detect overlay network address range.")
err = d.detectOverlayCidr()
err = d.detectOverlayCIDR()
if err != nil {
return trace.Wrap(err)
}
}
_, overlayNetwork, err := net.ParseCIDR(d.config.OverlayCIDR)
if err != nil {
return trace.Wrap(err)
}
d.overlayCIDR = *overlayNetwork

if d.config.NodeCIDR == "" {
d.Info("Attempting to detect node network address range")
Expand All @@ -179,7 +178,7 @@ func (d *controller) init() error {
func (d *controller) Run(ctx context.Context) error {
d.Info("Running wormhole controller.")
d.Info(" Node Name: ", d.config.NodeName)
d.Info(" Port: ", d.config.Port)
d.Info(" Port: ", d.config.ListenPort)
d.Info(" Overlay Network: ", d.config.OverlayCIDR)
d.Info(" Node Network: ", d.config.NodeCIDR)
d.Info(" Wireguard Interface Name: ", d.config.WireguardIface)
Expand All @@ -204,19 +203,14 @@ func (d *controller) Run(ctx context.Context) error {
return trace.Wrap(err)
}

_, overlayNetwork, err := net.ParseCIDR(d.config.OverlayCIDR)
if err != nil {
return trace.Wrap(err)
}
d.wireguardInterface, err = wireguard.New(wireguard.Config{
InterfaceName: d.config.WireguardIface,
IP: d.ipamInfo.wireguardAddr,
Port: d.config.Port,
ListenPort: d.config.ListenPort,
OverlayNetworks: []net.IPNet{
*overlayNetwork,
d.overlayCIDR,
},
EnableDebug: d.config.EnableDebug,
})
}, d.FieldLogger)
if err != nil {
return trace.Wrap(err)
}
Expand Down Expand Up @@ -261,19 +255,15 @@ func (d *controller) run(ctx context.Context) error {
select {
case <-ctx.Done():
return trace.Wrap(ctx.Err())
case err := <-d.errC:
return trace.Wrap(err)
case <-d.resyncC:
d.resync()
err := d.updatePeerSecrets(false)
err := d.resync()
if err != nil {
d.WithError(err).Warn("Failed to update peer secrets")
return trace.Wrap(err)
}
case <-syncTimer.C:
d.resync()
err := d.updatePeerSecrets(false)
err := d.resync()
if err != nil {
d.WithError(err).Warn("Failed to update peer secrets")
return trace.Wrap(err)
}
}
}
Expand Down
9 changes: 5 additions & 4 deletions pkg/controller/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,13 @@ func (d *controller) detectIPAM() error {
}
}

switch {
case internalIP != nil:
d.config.Endpoint = internalIP.String()
case externalIP != nil:
if externalIP != nil {
d.config.Endpoint = externalIP.String()
}
// internalIP takes precedence since we're connecting internally
if internalIP != nil {
d.config.Endpoint = internalIP.String()
}
}

return nil
Expand Down
13 changes: 6 additions & 7 deletions pkg/controller/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (c *controller) publishNodeInfo() error {
Name: c.config.NodeName,
},
Status: v1beta1.WgnodeStatus{
Port: c.config.Port,
Port: c.config.ListenPort,
PublicKey: c.wireguardInterface.PublicKey(),
NodeCIDR: c.config.NodeCIDR,
Endpoint: c.config.Endpoint,
Expand All @@ -87,7 +87,7 @@ func (c *controller) publishNodeInfo() error {
return trace.Wrap(err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rigging.ConvertError can map from kubernetes to trace error types.

}

node.Status.Port = c.config.Port
node.Status.Port = c.config.ListenPort
node.Status.PublicKey = c.wireguardInterface.PublicKey()
node.Status.NodeCIDR = c.config.NodeCIDR
node.Status.Endpoint = c.config.Endpoint
Expand Down Expand Up @@ -198,7 +198,7 @@ func (c *controller) waitForControllerSync(ctx context.Context) error {

}

func (c *controller) resync() {
func (c *controller) resync() error {
c.Debug("Re-sync triggered")

err := backoff.Retry(func() error {
Expand All @@ -213,11 +213,10 @@ func (c *controller) resync() {
Clock: backoff.SystemClock,
})
if err != nil {
c.WithError(err).Warn("Failed to re-sync with wireguard")
if c.errC != nil {
c.errC <- trace.Wrap(err)
}
return trace.Wrap(err)
}

return trace.Wrap(c.updatePeerSecrets(false))
}

func (c *controller) syncWithWireguard() error {
Expand Down
Loading