Skip to content

Commit af8ec36

Browse files
committed
Merge tag '1.27.2' into sync-istio-1-27-2
2 parents 748dd8f + 9e5b7fb commit af8ec36

File tree

122 files changed

+2151
-443
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+2151
-443
lines changed

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "istio build-tools",
3-
"image": "gcr.io/istio-testing/build-tools:release-1.27-56a42ed008b9070d88166dbec82e798d9eca43de",
3+
"image": "gcr.io/istio-testing/build-tools:release-1.27-0ef669e3326567c47323402f8af247931fce234f",
44
"privileged": true,
55
"remoteEnv": {
66
"USE_GKE_GCLOUD_AUTH_PLUGIN": "True",

Makefile.core.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ endif
4949
export VERSION
5050

5151
# Base version of Istio image to use
52-
BASE_VERSION ?= 1.27-2025-07-30T19-02-15
52+
BASE_VERSION ?= 1.27-2025-10-02T19-02-00
5353
ISTIO_BASE_REGISTRY ?= gcr.io/istio-release
5454

5555
export GO111MODULE ?= on

cni/pkg/cmd/root.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,25 +132,27 @@ var rootCmd = &cobra.Command{
132132
// if it is, we do NOT remove the plugin, and do
133133
// NOT do ambient watch server cleanup
134134
defer func() {
135-
var isUpgrade bool
135+
var shouldStopCleanup bool
136136
if cfg.InstallConfig.AmbientDisableSafeUpgrade {
137137
log.Info("Ambient node agent safe upgrade explicitly disabled via env")
138-
isUpgrade = false
138+
shouldStopCleanup = false
139139
} else {
140-
isUpgrade = ambientAgent.ShouldStopForUpgrade("istio-cni", nodeagent.PodNamespace)
140+
shouldStopCleanup = ambientAgent.ShouldStopCleanup("istio-cni", nodeagent.PodNamespace, cfg.InstallConfig.IstioOwnedCNIConfig)
141141
}
142-
log.Infof("Ambient node agent shutting down - is upgrade shutdown? %t", isUpgrade)
142+
log.Infof("Ambient node agent shutting down - should stop cleanup? %t", shouldStopCleanup)
143+
144+
// TODO(jaellio) - do we want to add support for a partial cleanup
143145
// if we are doing an "upgrade shutdown", then
144146
// we do NOT want to remove/cleanup the CNI plugin.
145147
//
146148
// This is important - we want it to remain in place to "stall"
147149
// new ambient-enabled pods while our replacement spins up.
148-
if !isUpgrade {
150+
if !shouldStopCleanup {
149151
if cleanErr := installer.Cleanup(); cleanErr != nil {
150152
log.Error(cleanErr.Error())
151153
}
152154
}
153-
ambientAgent.Stop(isUpgrade)
155+
ambientAgent.Stop(shouldStopCleanup)
154156
}()
155157

156158
ambientAgent.Start()

cni/pkg/iptables/iptables.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,14 @@ func NewIptablesConfigurator(
145145

146146
ipt6Ver, err := hostDeps.DetectIptablesVersion(true)
147147
if err != nil {
148-
return err
148+
if hostCfg.EnableIPv6 {
149+
return err
150+
}
151+
log.Warnf("Failed to detect a working ip6tables binary; continuing because IPv6 support is disabled (ENABLE_INBOUND_IPV6=false): %v", err)
152+
ipt6Ver = dep.IptablesVersion{}
153+
} else {
154+
log.Debugf("found iptables v6 binary: %+v", ipt6Ver)
149155
}
150-
log.Debugf("found iptables v6 binary: %+v", iptVer)
151156

152157
configurator.ipt6V = ipt6Ver
153158
return nil
@@ -489,7 +494,9 @@ func (cfg *IptablesConfigurator) executeCommands(log *istiolog.Scope, iptablesBu
489494
log.Info("Removing guardrails")
490495
guardrailsCleanup := iptablesBuilder.BuildCleanupGuardrails()
491496
_ = cfg.executeIptablesCommands(log, &cfg.iptV, guardrailsCleanup)
492-
_ = cfg.executeIptablesCommands(log, &cfg.ipt6V, guardrailsCleanup)
497+
if cfg.cfg.EnableIPv6 {
498+
_ = cfg.executeIptablesCommands(log, &cfg.ipt6V, guardrailsCleanup)
499+
}
493500
}
494501
}()
495502
residueExists, deltaExists := iptablescapture.VerifyIptablesState(log, cfg.ext, iptablesBuilder, &cfg.iptV, &cfg.ipt6V)
@@ -503,9 +510,13 @@ func (cfg *IptablesConfigurator) executeCommands(log *istiolog.Scope, iptablesBu
503510
log.Info("Setting up guardrails")
504511
guardrailsCleanup := iptablesBuilder.BuildCleanupGuardrails()
505512
guardrailsRules := iptablesBuilder.BuildGuardrails()
506-
for _, ver := range []*dep.IptablesVersion{&cfg.iptV, &cfg.ipt6V} {
507-
cfg.tryExecuteIptablesCommands(log, ver, guardrailsCleanup)
508-
if err := cfg.executeIptablesCommands(log, ver, guardrailsRules); err != nil {
513+
iptVersions := []dep.IptablesVersion{cfg.iptV}
514+
if cfg.cfg.EnableIPv6 {
515+
iptVersions = append(iptVersions, cfg.ipt6V)
516+
}
517+
for _, ver := range iptVersions {
518+
cfg.tryExecuteIptablesCommands(log, &ver, guardrailsCleanup)
519+
if err := cfg.executeIptablesCommands(log, &ver, guardrailsRules); err != nil {
509520
return err
510521
}
511522
guardrails = true
@@ -514,7 +525,9 @@ func (cfg *IptablesConfigurator) executeCommands(log *istiolog.Scope, iptablesBu
514525
// Remove old iptables
515526
log.Info("Performing cleanup of existing iptables")
516527
cfg.tryExecuteIptablesCommands(log, &cfg.iptV, iptablesBuilder.BuildCleanupV4())
517-
cfg.tryExecuteIptablesCommands(log, &cfg.ipt6V, iptablesBuilder.BuildCleanupV6())
528+
if cfg.cfg.EnableIPv6 {
529+
cfg.tryExecuteIptablesCommands(log, &cfg.ipt6V, iptablesBuilder.BuildCleanupV6())
530+
}
518531

519532
// Remove leftovers from non-matching istio iptables cfg
520533
if cfg.cfg.Reconcile {
@@ -540,7 +553,7 @@ func (cfg *IptablesConfigurator) cleanupIstioLeftovers(log *istiolog.Scope, ext
540553
iptV *dep.IptablesVersion, ipt6V *dep.IptablesVersion,
541554
) {
542555
for _, ipVer := range []*dep.IptablesVersion{iptV, ipt6V} {
543-
if ipVer == nil {
556+
if ipVer.DetectedBinary == "" {
544557
continue
545558
}
546559
output, err := ext.Run(log, true, iptablesconstants.IPTablesSave, ipVer, nil)

cni/pkg/iptables/iptables_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"istio.io/istio/cni/pkg/scopes"
2424
testutil "istio.io/istio/pilot/test/util"
25+
"istio.io/istio/pkg/test/util/assert"
2526
dep "istio.io/istio/tools/istio-iptables/pkg/dependencies"
2627
)
2728

@@ -47,6 +48,23 @@ func TestIptablesPodOverrides(t *testing.T) {
4748
}
4849
}
4950

51+
func TestIPv6NotAvailable(t *testing.T) {
52+
setup(t)
53+
cfg := constructTestConfig()
54+
ext := &dep.DependenciesStub{
55+
ForceIPv6DetectionFail: true,
56+
}
57+
58+
// Istio shouldn't fail if we're working with IPv4 interfaces only, and ip6tables is unavailable.
59+
cfg.EnableIPv6 = false
60+
_, _, err := NewIptablesConfigurator(cfg, cfg, ext, ext, EmptyNlDeps())
61+
assert.NoError(t, err)
62+
63+
cfg.EnableIPv6 = true
64+
_, _, err = NewIptablesConfigurator(cfg, cfg, ext, ext, EmptyNlDeps())
65+
assert.Error(t, err)
66+
}
67+
5068
func TestIptablesHostRules(t *testing.T) {
5169
cases := GetCommonHostTestCases()
5270

cni/pkg/nodeagent/server.go

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ import (
2121
"sync/atomic"
2222
"time"
2323

24+
"github.com/cenkalti/backoff/v4"
2425
corev1 "k8s.io/api/core/v1"
26+
"k8s.io/apimachinery/pkg/api/errors"
2527
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2628
"k8s.io/client-go/rest"
2729

@@ -31,7 +33,10 @@ import (
3133

3234
const defaultZTunnelKeepAliveCheckInterval = 5 * time.Second
3335

34-
var log = scopes.CNIAgent
36+
var (
37+
log = scopes.CNIAgent
38+
tokenWaitBackoff = time.Second
39+
)
3540

3641
type MeshDataplane interface {
3742
// MUST be called first, (even before Start()).
@@ -119,18 +124,47 @@ func (s *Server) Stop(skipCleanup bool) {
119124
s.dataplane.Stop(skipCleanup)
120125
}
121126

122-
func (s *Server) ShouldStopForUpgrade(selfName, selfNamespace string) bool {
127+
// ShouldStopCleanup of istio-cni config and binary when upgrading or on node reboot
128+
func (s *Server) ShouldStopCleanup(selfName, selfNamespace string, istioOwnedCNIConfig bool) bool {
123129
dsName := fmt.Sprintf("%s-node", selfName)
124-
cniDS, err := s.kubeClient.Kube().AppsV1().DaemonSets(selfNamespace).Get(context.Background(), dsName, metav1.GetOptions{})
125-
log.Debugf("Daemonset %s has deletion timestamp?: %+v", dsName, cniDS.DeletionTimestamp)
126-
if err == nil && cniDS != nil && cniDS.DeletionTimestamp == nil {
127-
log.Infof("terminating, but parent DS %s is still present, this is an upgrade, leaving plugin in place", dsName)
128-
return true
130+
shouldStopCleanup := false
131+
var numRetries uint64
132+
// use different defaults when using an istio owned CNI config file
133+
if istioOwnedCNIConfig {
134+
shouldStopCleanup = true
135+
numRetries = 2
129136
}
130-
131-
// If the DS is gone, it's definitely not an upgrade, so carry on like normal.
132-
log.Infof("parent DS %s is gone or marked for deletion, this is not an upgrade, shutting down normally %s", dsName, err)
133-
return false
137+
err := backoff.Retry(
138+
func() error {
139+
cniDS, err := s.kubeClient.Kube().AppsV1().DaemonSets(selfNamespace).Get(context.Background(), dsName, metav1.GetOptions{})
140+
141+
if err == nil && cniDS != nil && cniDS.DeletionTimestamp == nil {
142+
log.Infof("terminating, but parent DaemonSet %s is still present, this is an upgrade or a node reboot, leaving plugin in place", dsName)
143+
shouldStopCleanup = true
144+
return nil
145+
}
146+
if errors.IsNotFound(err) || (cniDS != nil && cniDS.DeletionTimestamp != nil) {
147+
// If the DS is gone, or marked for deletion, this is not an upgrade.
148+
// We can safely shut down the plugin.
149+
log.Infof("parent DaemonSet %s is not found or marked for deletion, this is not an upgrade, shutting down normally", dsName)
150+
shouldStopCleanup = false
151+
return nil
152+
}
153+
if errors.IsUnauthorized(err) {
154+
log.Infof("permission to get parent DaemonSet %s has been revoked manually or due to uninstall, this is not an upgrade, "+
155+
"shutting down normally", dsName)
156+
shouldStopCleanup = false
157+
return nil
158+
}
159+
log.Infof("failed to get parent DS %s, retrying: %v", dsName, err)
160+
return err
161+
},
162+
// Limiting retries to 3 so other shutdown tasks can complete before the graceful shutdown period ends
163+
backoff.WithMaxRetries(backoff.NewConstantBackOff(tokenWaitBackoff), numRetries))
164+
if err != nil {
165+
log.Infof("failed to get parent DaemonSet %s, returning %t: %v", dsName, shouldStopCleanup, err)
166+
}
167+
return shouldStopCleanup
134168
}
135169

136170
// buildKubeClient creates the kube client

cni/pkg/plugin/plugin.go

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -164,23 +164,26 @@ func CmdAdd(args *skel.CmdArgs) (err error) {
164164
return err
165165
}
166166

167+
// Preemptively check if the pod is a CNI pod.
168+
// It is possible that the kubeconfig is not available if it hasn't been written yet
169+
// by the CNI pod or it is invalid which cause the CNI pod to be unable to start if
170+
// on the creation of a new K8s client. We preemptively check if the pod is a CNI pod
171+
// to avoid a deadlock on the kubeconfig when the k8s client is unnecessary to process
172+
// the CNI add event for the CNI pod itself.
173+
if conf.AmbientEnabled {
174+
k8sArgs := K8sArgs{}
175+
if err := types.LoadArgs(args.Args, &k8sArgs); err != nil {
176+
return fmt.Errorf("failed to load args: %v", err)
177+
}
178+
if isCNIPod(conf, &k8sArgs) {
179+
// If we are in a degraded state and this is our own agent pod, skip
180+
return pluginResponse(conf)
181+
}
182+
}
183+
167184
// Create a kube client
168185
client, err := newK8sClient(*conf)
169-
// If creation of a kube client fails, check if the pod is a CNI pod.
170-
// It is possible that the kubeconfig is not available if it hasn't been written yet
171-
// by the CNI pod which could be unable to start if we failed here. We skip this
172-
// failure for the CNI pod to avoid a deadlock.
173186
if err != nil {
174-
if conf.AmbientEnabled {
175-
k8sArgs := K8sArgs{}
176-
if err := types.LoadArgs(args.Args, &k8sArgs); err != nil {
177-
return fmt.Errorf("failed to load args after failed attempt to get client: %v", err)
178-
}
179-
if isCNIPod(conf, &k8sArgs) {
180-
// If we are in a degraded state and this is our own agent pod, skip
181-
return pluginResponse(conf)
182-
}
183-
}
184187
return fmt.Errorf("failed to createNewK8sClient: %v", err)
185188
}
186189

@@ -404,6 +407,6 @@ func isCNIPod(conf *Config, k8sArgs *K8sArgs) bool {
404407
log.Infof("in a degraded state and %v looks like our own agent pod, skipping", k8sArgs.K8S_POD_NAME)
405408
return true
406409
}
407-
log.Warnf("not a CNI pod, podName: %s, podNamespace: %s", k8sArgs.K8S_POD_NAME, k8sArgs.K8S_POD_NAMESPACE)
410+
log.Warnf("not a CNI pod, podName: %s, podNamespace: %s, conf pod namespace: %s", k8sArgs.K8S_POD_NAME, k8sArgs.K8S_POD_NAMESPACE, conf.PodNamespace)
408411
return false
409412
}

cni/pkg/plugin/sidecar_redirect.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -275,18 +275,20 @@ func NewRedirect(pi *PodInfo) (*Redirect, error) {
275275
return nil, fmt.Errorf("annotation value error for value %s; annotationFound = %t: %v",
276276
"excludeInterfaces", isFound, valErr)
277277
}
278-
// kubeVirtInterfaces is deprecated, so check it first, but prefer`reroute-virtual-interfaces`
279-
// if both are defined.
280-
isFound, redir.rerouteVirtualInterfaces, valErr = getAnnotationOrDefault("kubevirtInterfaces", pi.Annotations)
281-
if valErr != nil {
282-
return nil, fmt.Errorf("annotation value error for value %s; annotationFound = %t: %v",
283-
"kubevirtInterfaces", isFound, valErr)
284-
}
278+
// kubeVirtInterfaces is deprecated, so prefer`reroute-virtual-interfaces` if both are defined.
285279
isFound, redir.rerouteVirtualInterfaces, valErr = getAnnotationOrDefault("reroute-virtual-interfaces", pi.Annotations)
286280
if valErr != nil {
287281
return nil, fmt.Errorf("annotation value error for value %s; annotationFound = %t: %v",
288282
"reroute-virtual-interfaces", isFound, valErr)
289283
}
284+
// Only check deprecated kubevirtInterfaces if reroute-virtual-interfaces was not found
285+
if !isFound {
286+
isFound, redir.rerouteVirtualInterfaces, valErr = getAnnotationOrDefault("kubevirtInterfaces", pi.Annotations)
287+
if valErr != nil {
288+
return nil, fmt.Errorf("annotation value error for value %s; annotationFound = %t: %v",
289+
"kubevirtInterfaces", isFound, valErr)
290+
}
291+
}
290292
if v, found := pi.ProxyEnvironments["ISTIO_META_DNS_CAPTURE"]; found {
291293
// parse and set the bool value of dnsRedirect
292294
redir.dnsRedirect, valErr = strconv.ParseBool(v)

common/.commonfiles.sha

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e00505c43a460ae40f8a26e1a1d62ffebb68d918
1+
cb5e4cb5a36094ef48591f380a797be5442b80ae

common/scripts/setup_env.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ fi
7575
TOOLS_REGISTRY_PROVIDER=${TOOLS_REGISTRY_PROVIDER:-gcr.io}
7676
PROJECT_ID=${PROJECT_ID:-istio-testing}
7777
if [[ "${IMAGE_VERSION:-}" == "" ]]; then
78-
IMAGE_VERSION=release-1.27-56a42ed008b9070d88166dbec82e798d9eca43de
78+
IMAGE_VERSION=release-1.27-0ef669e3326567c47323402f8af247931fce234f
7979
fi
8080
if [[ "${IMAGE_NAME:-}" == "" ]]; then
8181
IMAGE_NAME=build-tools

0 commit comments

Comments
 (0)