inject: don't expand opaque port ranges (#10827)

Currently, the proxy injector will expand lists of opaque port ranges
into lists of individual port numbers. This is because the proxy has
historically not accepted port ranges in the
`LINKERD2_PROXY_INBOUND_PORTS_DISABLE_PROTOCOL_DETECTION` environment
variable. However, when very large ranges are used, the size of the
injected manifest can be quite large, since each individual port number
in a range must be listed separately.

Proxy PR linkerd/linkerd2-proxy#2395 changed the proxy to accept ranges
as well as individual port numbers in the opaque ports environment
variable, and this change was included in the latest proxy release
(v2.200.0). This means that the proxy-injector no longer needs to expand
large port ranges into individual port numbers, and can now simply
forward the list of ranges to the proxy. This branch changes the proxy
injector to do this, resolving issues with manifest size due to large
port ranges.

Closes #9803
This commit is contained in:
Eliza Weisman 2023-04-27 11:27:40 -07:00 committed by GitHub
parent 2367eea473
commit 34df5aa606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 31 deletions

View File

@ -257,10 +257,7 @@ func (et *endpointTranslator) sendClientAdd(set watcher.AddressSet) {
err error
)
if address.Pod != nil {
opaquePorts, err = getAnnotatedOpaquePorts(address.Pod, et.defaultOpaquePorts)
if err != nil {
et.log.Errorf("failed to get opaque ports for pod %s/%s: %s", address.Pod.Namespace, address.Pod.Name, err)
}
opaquePorts = getAnnotatedOpaquePorts(address.Pod, et.defaultOpaquePorts)
wa, err = createWeightedAddr(address, opaquePorts, et.enableH2Upgrade, et.identityTrustDomain, et.controllerNS, et.log)
} else {
var authOverride *pb.AuthorityOverride

View File

@ -412,12 +412,9 @@ func (s *server) subscribeToEndpointProfile(
log = log.WithField("ip", address.IP)
}
opaquePorts, err := getAnnotatedOpaquePorts(address.Pod, s.defaultOpaquePorts)
if err != nil {
return fmt.Errorf("failed to get opaque ports for pod: %w", err)
}
opaquePorts := getAnnotatedOpaquePorts(address.Pod, s.defaultOpaquePorts)
var endpoint *pb.WeightedAddr
endpoint, err = s.createEndpoint(*address, opaquePorts)
endpoint, err := s.createEndpoint(*address, opaquePorts)
if err != nil {
return fmt.Errorf("failed to create endpoint: %w", err)
}
@ -784,25 +781,23 @@ func hasSuffix(slice []string, suffix []string) bool {
return true
}
func getAnnotatedOpaquePorts(pod *corev1.Pod, defaultPorts map[uint32]struct{}) (map[uint32]struct{}, error) {
func getAnnotatedOpaquePorts(pod *corev1.Pod, defaultPorts map[uint32]struct{}) map[uint32]struct{} {
if pod == nil {
return defaultPorts, nil
return defaultPorts
}
annotation, ok := pod.Annotations[labels.ProxyOpaquePortsAnnotation]
if !ok {
return defaultPorts, nil
return defaultPorts
}
opaquePorts := make(map[uint32]struct{})
if annotation != "" {
for _, portStr := range util.ParseContainerOpaquePorts(annotation, pod.Spec.Containers) {
port, err := strconv.ParseUint(portStr, 10, 32)
if err != nil {
return nil, err
for _, pr := range util.ParseContainerOpaquePorts(annotation, pod.Spec.Containers) {
for _, port := range pr.Ports() {
opaquePorts[uint32(port)] = struct{}{}
}
opaquePorts[uint32(port)] = struct{}{}
}
}
return opaquePorts, nil
return opaquePorts
}
func getPodSkippedInboundPortsAnnotations(pod *corev1.Pod) (map[uint32]struct{}, error) {

View File

@ -1051,8 +1051,15 @@ func (conf *ResourceConfig) applyAnnotationOverrides(values *l5dcharts.Values) {
}
if override, ok := annotations[k8s.ProxyOpaquePortsAnnotation]; ok {
opaquePortsStrs := util.ParseContainerOpaquePorts(override, conf.pod.spec.Containers)
values.Proxy.OpaquePorts = strings.Join(opaquePortsStrs, ",")
var opaquePorts strings.Builder
for _, pr := range util.ParseContainerOpaquePorts(override, conf.pod.spec.Containers) {
if opaquePorts.Len() > 0 {
opaquePorts.WriteRune(',')
}
opaquePorts.WriteString(pr.ToString())
}
values.Proxy.OpaquePorts = opaquePorts.String()
}
if override, ok := annotations[k8s.DebugImageAnnotation]; ok {

View File

@ -114,7 +114,7 @@ func TestGetOverriddenValues(t *testing.T) {
values.Proxy.RequireIdentityOnInboundPorts = "8888,9999"
values.Proxy.OutboundConnectTimeout = "6000ms"
values.Proxy.InboundConnectTimeout = "600ms"
values.Proxy.OpaquePorts = "4320,4321,4322,4323,4324,4325,3306"
values.Proxy.OpaquePorts = "4320-4325,3306"
values.Proxy.Await = true
values.Proxy.AccessLog = "apache"
values.Proxy.ShutdownGracePeriod = "30000ms"
@ -201,7 +201,7 @@ func TestGetOverriddenValues(t *testing.T) {
values.ProxyInit.IgnoreOutboundPorts = "8079,8080"
values.Proxy.OutboundConnectTimeout = "6000ms"
values.Proxy.InboundConnectTimeout = "600ms"
values.Proxy.OpaquePorts = "4320,4321,4322,4323,4324,4325,3306"
values.Proxy.OpaquePorts = "4320-4325,3306"
values.Proxy.Await = true
values.Proxy.AccessLog = "apache"
values.Proxy.IsIngress = true

View File

@ -1,7 +1,6 @@
package util
import (
"strconv"
"strings"
log "github.com/sirupsen/logrus"
@ -29,25 +28,23 @@ func ParsePorts(portsString string) (map[uint32]struct{}, error) {
return opaquePorts, nil
}
// ParseContainerOpaquePorts parses the opaque ports annotation into a list of ports;
// this includes converting port ranges into separate ports and named ports
// ParseContainerOpaquePorts parses the opaque ports annotation into a list of
// port ranges, including validating port ranges and converting named ports
// into their port number equivalents.
func ParseContainerOpaquePorts(override string, containers []corev1.Container) []string {
func ParseContainerOpaquePorts(override string, containers []corev1.Container) []PortRange {
portRanges := GetPortRanges(override)
var values []string
var values []PortRange
for _, pr := range portRanges {
port, named := isNamed(pr, containers)
if named {
values = append(values, strconv.Itoa(int(port)))
values = append(values, PortRange{UpperBound: int(port), LowerBound: int(port)})
} else {
pr, err := ParsePortRange(pr)
if err != nil {
log.Warnf("Invalid port range [%v]: %s", pr, err)
continue
}
for i := pr.LowerBound; i <= pr.UpperBound; i++ {
values = append(values, strconv.Itoa(i))
}
values = append(values, pr)
}
}
return values

View File

@ -51,3 +51,20 @@ func ParsePortRange(portRange string) (PortRange, error) {
func isPort(port int) bool {
return 0 <= port && port <= 65535
}
// Ports returns an array of all the ports contained by this range.
func (pr PortRange) Ports() []uint16 {
var ports []uint16
for i := pr.LowerBound; i <= pr.UpperBound; i++ {
ports = append(ports, uint16(i))
}
return ports
}
func (pr PortRange) ToString() string {
if pr.LowerBound == pr.UpperBound {
return strconv.Itoa(pr.LowerBound)
}
return fmt.Sprintf("%d-%d", pr.LowerBound, pr.UpperBound)
}