-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial ambient dual stack support #51606
Conversation
Skipping CI for Draft Pull Request. |
Ah ok - single stack IPv6 worked in ambient (I think we got at least one successful test) but we still have gotchas/bugs around "things might have more than one IP". (hopefully not too many of those) |
I would rather not use If we have bugs when support for both is enabled, that's probably just A Bug, and not really "support for a feature" we lack. |
TBH I disagree. Its totally different to have 2 IPs vs 1. But also this is a PR not user facing, so we can have the docs folks bikeshed it when the time comes 🙂 |
It is, my point is "the lack of support for more than one IP" is just a bug, especially in a K8S context.
It's fine as long as we have tests for either/or/both - I'm less concerned with users here and more concerned with how the language we use affects how we view the problem. |
/test all |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems safe from an API/upgrade/back-compat perspective.
@@ -193,6 +193,17 @@ func (a *index) constructService(svc *v1.Service, w *Waypoint) *workloadapi.Serv | |||
Mode: workloadapi.LoadBalancing_STRICT, | |||
} | |||
} | |||
ipPolicy := workloadapi.IPFamilies_AUTOMATIC | |||
if len(svc.Spec.IPFamilies) == 2 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems potentially a little brittle, can users do silly things like put v1.IPv4Protocol in the list twice ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No the validation is pretty strict. We could make it more robust anyways though
/retest |
cips = []string{svc.Spec.ClusterIP} | ||
} | ||
for _, cip := range cips { | ||
if cip != "" && cip != v1.ClusterIPNone { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add ut for this function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#51665 adds some basic ones, will make it easier to add new ones. if we can merge that it will help and Ill update this PR with a test
@@ -155,7 +155,20 @@ func (a *index) podWorkloadBuilder( | |||
if (!IsPodRunning(p) && !IsPodPending(p)) || p.Spec.HostNetwork { | |||
return nil | |||
} | |||
podIP, err := netip.ParseAddr(p.Status.PodIP) | |||
k8sPodIPs := p.Status.PodIPs | |||
if len(k8sPodIPs) == 0 && p.Status.PodIP != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question, when Status.PodIPs can be empty? I guess we donot need to check it since have checked Running status before
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is mostly defense in depth against weird Pods, shouldn't really happen. In particular our tests often just set podIp and not PodIps.
But any Pod can be arbitrarily modified by user, so we cannot assume it's valid
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also IIRC the k8s docs say that if PodIPs is non-empty, the first entry in the list is PodIP - they don't declare any guarantees that PodIPs will be non-empty. I think this is mostly for back compat with old K8S versions though. So yeah better to check.
@@ -81,6 +79,20 @@ message Service { | |||
// Note: this applies only to connecting directly to the workload; when waypoints are used, the waypoint's load_balancing | |||
// configuration is used. | |||
LoadBalancing load_balancing = 8; | |||
|
|||
// IP families provides configuration about the IP families this service supports. | |||
IPFamilies ip_families = 9; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this really needed, can infer from addresses
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately for headless services there is no vip. If it wasn't for that I wouldn't have added it probably .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How is headless processed in ztunnel now, it has no ip associated on service.
It should be matched by a workload ip. Since workload has the ip, can we infer from it. Anyway, i am not sure how you want ztunnel to do with dual stack
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is for DNS. The linked ztunnel PR has the ztunnel implementation and tests
169e878
to
cb7bb9f
Compare
@@ -193,6 +193,17 @@ func (a *index) constructService(svc *v1.Service, w *Waypoint) *workloadapi.Serv | |||
Mode: workloadapi.LoadBalancing_STRICT, | |||
} | |||
} | |||
ipFamily := workloadapi.IPFamilies_AUTOMATIC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QQ - are we emulating the k8s ipfamily
or ipfamilypolicy
API here, or both?
It seems like mostly this is just emulating ipfamilypolicy
semantics? Do we plan to hardcode the behavior, or additionally expose ipfamily
style APIs for the relevant resources we have in Istio, to match k8s?
"dualstack" is just two problems AFAICT:
- should you assign more than 1 IP to (some resource with IPs) -> (k8s
ipfamilypolicy
), I think you said we will probably always assign both if V6 enabled. - can you handle more than 1 IP assigned to (some resource with IPs).
- if you can, how do you priority-order the list of IPs on that resource (k8s
ipfamily
ordering semantics)
The only bit we really care about as A Problem is the ordering of that IP list for non-K8S/Istio-only resources, right? Doesn't matter whether that list contains 1 V4 and 1 V6, 2 V4s, or 5 V6s, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ipFamilyPolicy. This is actually mostly about joining two resources (Service and Pod), and which IPs you should join. Since k8s already pre-filters the IPs (and assigns the IPs), its not like we need to do "which IPs do we assign" , etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we need to do that for stuff like SEs eventually, though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We really only need this for headless services selecting pods, which there is no SE equivalent. So I don't think we really do
@@ -155,7 +155,20 @@ func (a *index) podWorkloadBuilder( | |||
if (!IsPodRunning(p) && !IsPodPending(p)) || p.Spec.HostNetwork { | |||
return nil | |||
} | |||
podIP, err := netip.ParseAddr(p.Status.PodIP) | |||
k8sPodIPs := p.Status.PodIPs | |||
if len(k8sPodIPs) == 0 && p.Status.PodIP != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also IIRC the k8s docs say that if PodIPs is non-empty, the first entry in the list is PodIP - they don't declare any guarantees that PodIPs will be non-empty. I think this is mostly for back compat with old K8S versions though. So yeah better to check.
* upstream/master: Cleanup adsc (istio#51678) Initial support for network gateways in ambient krt (istio#51578) kclient: use internal indexes instead of external (istio#51576) Automator: update ztunnel@master in istio/istio@master (istio#51592) Initial ambient dual stack support (istio#51606) ambient: support explicit EndpointSlice endpoints (istio#51591) align the labels in the pull request tpl to the issue's (istio#51641) Automator: update proxy@master in istio/istio@master (istio#51686) Don't reset the jwks refresh ticker on URI fetch errors (istio#51637) ambient: properly mark pod as not ready when it is shutting down (istio#51650)
This has a few changes:
Corresponding ztunnel change: istio/ztunnel#1161