k3s/pkg/agent/flannel/setup.go

176 lines
4.4 KiB
Go
Raw Normal View History

2019-01-01 08:23:01 +00:00
package flannel
import (
"context"
2019-09-03 23:41:54 +00:00
"fmt"
2019-09-06 00:39:18 +00:00
"os"
"path"
2019-01-09 16:54:15 +00:00
"path/filepath"
2019-01-01 08:23:01 +00:00
"strings"
"time"
2019-01-09 16:54:15 +00:00
"github.com/rancher/k3s/pkg/agent/util"
"github.com/rancher/k3s/pkg/daemons/config"
2019-01-01 08:23:01 +00:00
"github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
const (
cniConf = `{
"name":"cbr0",
"cniVersion":"0.3.1",
"plugins":[
{
"type":"flannel",
"delegate":{
2019-08-11 05:50:21 +00:00
"hairpinMode":true,
2019-01-01 08:23:01 +00:00
"forceAddress":true,
"isDefaultGateway":true
}
},
{
"type":"portmap",
"capabilities":{
"portMappings":true
}
}
]
}
`
2019-09-03 23:41:54 +00:00
flannelConf = `{
"Network": "%CIDR%",
"Backend": %backend%
2019-01-01 08:23:01 +00:00
}
`
2019-09-03 23:41:54 +00:00
vxlanBackend = `{
"Type": "vxlan"
}`
ipsecBackend = `{
"Type": "ipsec",
"UDPEncap": true,
"PSK": "%psk%"
}`
wireguardBackend = `{
"Type": "extension",
"PreStartupCommand": "wg genkey | tee privatekey | wg pubkey",
"PostStartupCommand": "export SUBNET_IP=$(echo $SUBNET | cut -d'/' -f 1); ip link del flannel.1 2>/dev/null; echo $PATH >&2; wg-add.sh flannel.1 && wg set flannel.1 listen-port 51820 private-key privatekey && ip addr add $SUBNET_IP/32 dev flannel.1 && ip link set flannel.1 up && ip route add $NETWORK dev flannel.1",
"ShutdownCommand": "ip link del flannel.1",
"SubnetAddCommand": "read PUBLICKEY; wg set flannel.1 peer $PUBLICKEY endpoint $PUBLIC_IP:51820 allowed-ips $SUBNET",
"SubnetRemoveCommand": "read PUBLICKEY; wg set flannel.1 peer $PUBLICKEY remove"
}`
2019-01-01 08:23:01 +00:00
)
2019-09-03 23:41:54 +00:00
func Prepare(ctx context.Context, nodeConfig *config.Node) error {
if err := createCNIConf(nodeConfig.AgentConfig.CNIConfDir); err != nil {
2019-01-09 16:54:15 +00:00
return err
}
2019-09-03 23:41:54 +00:00
return createFlannelConf(nodeConfig)
2019-01-09 16:54:15 +00:00
}
2019-09-03 23:41:54 +00:00
func Run(ctx context.Context, nodeConfig *config.Node) error {
nodeName := nodeConfig.AgentConfig.NodeName
2019-01-01 08:23:01 +00:00
2019-09-03 23:41:54 +00:00
restConfig, err := clientcmd.BuildConfigFromFlags("", nodeConfig.AgentConfig.KubeConfigNode)
2019-01-01 08:23:01 +00:00
if err != nil {
return err
}
client, err := kubernetes.NewForConfig(restConfig)
if err != nil {
return err
}
for {
node, err := client.CoreV1().Nodes().Get(nodeName, metav1.GetOptions{})
if err == nil && node.Spec.PodCIDR != "" {
break
}
if err == nil {
logrus.Infof("waiting for node %s CIDR not assigned yet", nodeName)
} else {
logrus.Infof("waiting for node %s: %v", nodeName, err)
}
time.Sleep(2 * time.Second)
}
2019-01-09 16:54:15 +00:00
go func() {
2019-09-03 23:41:54 +00:00
err := flannel(ctx, nodeConfig.FlannelIface, nodeConfig.FlannelConf, nodeConfig.AgentConfig.KubeConfigNode)
2019-02-28 00:56:21 +00:00
logrus.Fatalf("flannel exited: %v", err)
2019-01-09 16:54:15 +00:00
}()
2019-01-01 08:23:01 +00:00
2019-01-09 16:54:15 +00:00
return err
2019-01-01 08:23:01 +00:00
}
2019-01-09 16:54:15 +00:00
func createCNIConf(dir string) error {
if dir == "" {
return nil
}
p := filepath.Join(dir, "10-flannel.conflist")
return util.WriteFile(p, cniConf)
2019-01-01 08:23:01 +00:00
}
2019-09-03 23:41:54 +00:00
func createFlannelConf(nodeConfig *config.Node) error {
if nodeConfig.FlannelConf == "" {
2019-01-09 16:54:15 +00:00
return nil
}
2019-09-03 23:41:54 +00:00
if nodeConfig.FlannelConfOverride {
logrus.Infof("Using custom flannel conf defined at %s", nodeConfig.FlannelConf)
2019-08-08 05:56:09 +00:00
return nil
}
2019-09-03 23:41:54 +00:00
confJSON := strings.Replace(flannelConf, "%CIDR%", nodeConfig.AgentConfig.ClusterCIDR.String(), -1)
var backendConf string
switch nodeConfig.FlannelBackend {
case config.FlannelBackendVXLAN:
backendConf = vxlanBackend
case config.FlannelBackendIPSEC:
backendConf = strings.Replace(ipsecBackend, "%psk%", nodeConfig.AgentConfig.IPSECPSK, -1)
2019-09-06 00:39:18 +00:00
if err := setupStrongSwan(nodeConfig); err != nil {
return err
}
2019-09-03 23:41:54 +00:00
case config.FlannelBackendWireguard:
backendConf = wireguardBackend
default:
return fmt.Errorf("Cannot configure unknown flannel backend '%s'", nodeConfig.FlannelBackend)
}
confJSON = strings.Replace(confJSON, "%backend%", backendConf, -1)
return util.WriteFile(nodeConfig.FlannelConf, confJSON)
2019-01-01 08:23:01 +00:00
}
2019-09-06 00:39:18 +00:00
func setupStrongSwan(nodeConfig *config.Node) error {
// if data dir env is not set point to root
2019-09-06 00:39:18 +00:00
dataDir := os.Getenv("K3S_DATA_DIR")
if dataDir == "" {
dataDir = "/"
2019-09-06 00:39:18 +00:00
}
dataDir = path.Join(dataDir, "etc", "strongswan")
info, err := os.Lstat(nodeConfig.AgentConfig.StrongSwanDir)
// something exists but is not a symlink, return
if err == nil && info.Mode()&os.ModeSymlink == 0 {
return nil
}
if err == nil {
target, err := os.Readlink(nodeConfig.AgentConfig.StrongSwanDir)
// current link is the same, return
if err == nil && target == dataDir {
return nil
}
}
2019-09-06 00:39:18 +00:00
// clean up strongswan old link
os.Remove(nodeConfig.AgentConfig.StrongSwanDir)
// make new strongswan link
return os.Symlink(dataDir, nodeConfig.AgentConfig.StrongSwanDir)
}