cmd/aws-vpc-cni-init/main.go (140 lines of code) (raw):

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may // not use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file is distributed // on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. // The aws-node initialization package main import ( "os" "github.com/aws/amazon-vpc-cni-k8s/pkg/procsyswrapper" "github.com/aws/amazon-vpc-cni-k8s/utils" "github.com/aws/amazon-vpc-cni-k8s/utils/cp" "github.com/aws/amazon-vpc-cni-k8s/utils/imds" "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/vishvananda/netlink" ) const ( defaultHostCNIBinPath = "/host/opt/cni/bin" metadataLocalIP = "local-ipv4" metadataMAC = "mac" defaultDisableIPv4TcpEarlyDemux = false defaultEnableIPv6 = false defaultEnableIPv6Egress = false envDisableIPv4TcpEarlyDemux = "DISABLE_TCP_EARLY_DEMUX" envEnableIPv6 = "ENABLE_IPv6" envHostCniBinPath = "HOST_CNI_BIN_PATH" envEgressV6 = "ENABLE_V6_EGRESS" ) func getNodePrimaryIF() (string, error) { var primaryIF string primaryMAC, err := imds.GetMetaData("mac") if err != nil { return primaryIF, errors.Wrap(err, "Failed to get primary MAC from IMDS") } log.Infof("Found primaryMAC %s", primaryMAC) links, err := netlink.LinkList() if err != nil { return primaryIF, errors.Wrap(err, "Failed to list links") } for _, link := range links { if link.Attrs().HardwareAddr.String() == primaryMAC { primaryIF = link.Attrs().Name break } } if primaryIF == "" { return primaryIF, errors.Wrap(err, "Failed to retrieve primary IF") } return primaryIF, nil } func configureSystemParams(procSys procsyswrapper.ProcSys, primaryIF string) error { var err error // Configure rp_filter in loose mode entry := "net/ipv4/conf/" + primaryIF + "/rp_filter" err = procSys.Set(entry, "2") if err != nil { return errors.Wrapf(err, "Failed to set rp_filter for %s", primaryIF) } val, _ := procSys.Get(entry) log.Infof("Updated %s to %s", entry, val) // Enable or disable TCP early demux based on environment variable // Note that older kernels may not support tcp_early_demux, so we must first check that it exists. entry = "net/ipv4/tcp_early_demux" if _, err := procSys.Get(entry); err == nil { disableIPv4EarlyDemux := utils.GetBoolAsStringEnvVar(envDisableIPv4TcpEarlyDemux, defaultDisableIPv4TcpEarlyDemux) if disableIPv4EarlyDemux { err = procSys.Set(entry, "0") if err != nil { return errors.Wrap(err, "Failed to disable tcp_early_demux") } } else { err = procSys.Set(entry, "1") if err != nil { return errors.Wrap(err, "Failed to enable tcp_early_demux") } } val, _ = procSys.Get(entry) log.Infof("Updated %s to %s", entry, val) } return nil } func configureIPv6Settings(procSys procsyswrapper.ProcSys, primaryIF string) error { var err error // Enable IPv6 when environment variable is set // Note that IPv6 is not disabled when environment variable is unset. This is omitted to preserve default host semantics. enableIPv6 := utils.GetBoolAsStringEnvVar(envEnableIPv6, defaultEnableIPv6) if enableIPv6 { entry := "net/ipv6/conf/all/disable_ipv6" err = procSys.Set(entry, "0") if err != nil { return errors.Wrap(err, "Failed to set disable_ipv6 to 0") } val, _ := procSys.Get(entry) log.Infof("Updated %s to %s", entry, val) } // Check if IPv6 egress support is enabled in IPv4 cluster. ipv6EgressEnabled := utils.GetBoolAsStringEnvVar(envEgressV6, defaultEnableIPv6Egress) if enableIPv6 || ipv6EgressEnabled { // Enable IPv6 forwarding on all interfaces by default entry := "net/ipv6/conf/all/forwarding" err = procSys.Set(entry, "1") if err != nil { return errors.Wrap(err, "Failed to enable IPv6 forwarding") } val, _ := procSys.Get(entry) log.Infof("Updated %s to %s", entry, val) // For the primary ENI in IPv6, sysctls are set to: // 1. forwarding=1 // 2. accept_ra=2 // 3. accept_redirects=1 entry = "net/ipv6/conf/" + primaryIF + "/accept_ra" err = procSys.Set(entry, "2") if err != nil { return errors.Wrap(err, "Failed to enable IPv6 accept_ra on primary ENI") } val, _ = procSys.Get(entry) log.Infof("Updated %s to %s", entry, val) } return nil } func main() { os.Exit(_main()) } func _main() int { log.Debug("Started Initialization") var err error log.Infof("Copying CNI plugin binaries ...") hostCNIBinPath := utils.GetEnv(envHostCniBinPath, defaultHostCNIBinPath) excludeBins := map[string]bool{"aws-vpc-cni-init": true} // Copy all binaries from workdir to host bin dir except container init binary err = cp.InstallBinariesFromDir(".", hostCNIBinPath, excludeBins) if err != nil { log.WithError(err).Errorf("Failed to install binaries") return 1 } log.Infof("Copied all CNI plugin binaries to %s", hostCNIBinPath) var primaryIF string primaryIF, err = getNodePrimaryIF() if err != nil { log.WithError(err).Errorf("Failed to get primary IF") return 1 } log.Infof("Found primaryIF %s", primaryIF) procSys := procsyswrapper.NewProcSys() err = configureSystemParams(procSys, primaryIF) if err != nil { log.WithError(err).Errorf("Failed to configure system parameters") return 1 } err = configureIPv6Settings(procSys, primaryIF) if err != nil { log.WithError(err).Errorf("Failed to configure IPv6 settings") return 1 } log.Infof("CNI init container done") return 0 }