Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix(istio): support for ExternalIPs in Istio resources #4094

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/tutorials/istio.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,11 @@ spec:
EOF
```

To get the targets to the extracted DNS names, external-dns is able to gather information from the kubernetes service of the Istio Ingress Gateway.
Please take a look at the [source service documentation](../sources/service.md) for more information on this.

It is also possible to set the targets manually by using the `external-dns.alpha.kubernetes.io/target` annotation on the Istio Ingress Gateway resource or the Istio VirtualService.

#### Access the sample service using `curl`
```bash
$ curl -I http://httpbin.example.com/status/200
Expand Down
5 changes: 5 additions & 0 deletions source/istio_gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,11 @@ func (sc *gatewaySource) targetsFromGateway(ctx context.Context, gateway *networ
continue
}

if len(service.Spec.ExternalIPs) > 0 {
targets = append(targets, service.Spec.ExternalIPs...)
continue
}

for _, lb := range service.Status.LoadBalancer.Ingress {
if lb.IP != "" {
targets = append(targets, lb.IP)
Expand Down
66 changes: 56 additions & 10 deletions source/istio_gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,9 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
title: "no rule.host",
lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
},
},
config: fakeGatewayConfig{
Expand All @@ -350,8 +351,9 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
title: "one empty rule.host",
lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
},
},
config: fakeGatewayConfig{
Expand Down Expand Up @@ -447,6 +449,48 @@ func testEndpointsFromGatewayConfig(t *testing.T) {
},
},
},
{
title: "one rule.host one lb.externalIP",
lbServices: []fakeIngressGatewayService{
{
externalIPs: []string{"8.8.8.8"},
},
},
config: fakeGatewayConfig{
dnsnames: [][]string{
{"foo.bar"},
},
},
expected: []*endpoint.Endpoint{
{
DNSName: "foo.bar",
RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"8.8.8.8"},
},
},
},
{
title: "one rule.host two lb.IP, two lb.Hostname and two lb.externalIP",
lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
},
},
config: fakeGatewayConfig{
dnsnames: [][]string{
{"foo.bar"},
},
},
expected: []*endpoint.Endpoint{
{
DNSName: "foo.bar",
RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"1.1.1.1", "2.2.2.2"},
},
},
},
} {
ti := ti
t.Run(ti.title, func(t *testing.T) {
Expand Down Expand Up @@ -1521,11 +1565,12 @@ func newTestGatewaySource(loadBalancerList []fakeIngressGatewayService, ingressL
}

type fakeIngressGatewayService struct {
ips []string
hostnames []string
namespace string
name string
selector map[string]string
ips []string
hostnames []string
namespace string
name string
selector map[string]string
externalIPs []string
}

func (ig fakeIngressGatewayService) Service() *v1.Service {
Expand All @@ -1540,7 +1585,8 @@ func (ig fakeIngressGatewayService) Service() *v1.Service {
},
},
Spec: v1.ServiceSpec{
Selector: ig.selector,
Selector: ig.selector,
ExternalIPs: ig.externalIPs,
},
}

Expand Down
5 changes: 5 additions & 0 deletions source/istio_virtualservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,11 @@ func (sc *virtualServiceSource) targetsFromGateway(ctx context.Context, gateway
continue
}

if len(service.Spec.ExternalIPs) > 0 {
targets = append(targets, service.Spec.ExternalIPs...)
continue
}

for _, lb := range service.Status.LoadBalancer.Ingress {
if lb.IP != "" {
targets = append(targets, lb.IP)
Expand Down
137 changes: 131 additions & 6 deletions source/istio_virtualservice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,29 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) {
},
},
},
{
title: "one rule.host one lb.externalIPs",
lbServices: []fakeIngressGatewayService{
{
externalIPs: []string{"8.8.8.8"},
},
},
gwconfig: fakeGatewayConfig{
name: "mygw",
dnsnames: [][]string{{"*"}},
},
vsconfig: fakeVirtualServiceConfig{
gateways: []string{"mygw"},
dnsnames: []string{"foo.bar"},
},
expected: []*endpoint.Endpoint{
{
DNSName: "foo.bar",
RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"8.8.8.8"},
},
},
},
{
title: "one rule.host two lb.IP and two lb.Hostname",
lbServices: []fakeIngressGatewayService{
Expand Down Expand Up @@ -479,12 +502,38 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) {
},
},
},
{
title: "one rule.host two lb.IP and two lb.Hostname and two lb.externalIPs",
lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
},
},
gwconfig: fakeGatewayConfig{
name: "mygw",
dnsnames: [][]string{{"*"}},
},
vsconfig: fakeVirtualServiceConfig{
gateways: []string{"mygw"},
dnsnames: []string{"foo.bar"},
},
expected: []*endpoint.Endpoint{
{
DNSName: "foo.bar",
RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"1.1.1.1", "2.2.2.2"},
},
},
},
{
title: "no rule.host",
lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
},
},
gwconfig: fakeGatewayConfig{
Expand All @@ -501,8 +550,9 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) {
title: "no rule.gateway",
lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
},
},
gwconfig: fakeGatewayConfig{
Expand All @@ -519,8 +569,9 @@ func testEndpointsFromVirtualServiceConfig(t *testing.T) {
title: "one empty rule.host",
lbServices: []fakeIngressGatewayService{
{
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
ips: []string{"8.8.8.8", "127.0.0.1"},
hostnames: []string{"elb.com", "alb.com"},
externalIPs: []string{"1.1.1.1", "2.2.2.2"},
},
},
gwconfig: fakeGatewayConfig{
Expand Down Expand Up @@ -844,6 +895,42 @@ func testVirtualServiceEndpoints(t *testing.T) {
},
},
},
{
title: "one virtualservice with two gateways, one ingressgateway loadbalancer service with externalIPs",
lbServices: []fakeIngressGatewayService{
{
namespace: namespace,
externalIPs: []string{"8.8.8.8"},
},
},
gwConfigs: []fakeGatewayConfig{
{
name: "gw1",
namespace: namespace,
dnsnames: [][]string{{"*"}},
},
{
name: "gw2",
namespace: namespace,
dnsnames: [][]string{{"*"}},
},
},
vsConfigs: []fakeVirtualServiceConfig{
{
name: "vs",
namespace: namespace,
gateways: []string{"gw1", "gw2"},
dnsnames: []string{"example.org"},
},
},
expected: []*endpoint.Endpoint{
{
DNSName: "example.org",
RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"8.8.8.8"},
},
},
},
{
title: "two simple virtualservices on different namespaces with the same target gateway, one ingressgateway loadbalancer service",
lbServices: []fakeIngressGatewayService{
Expand Down Expand Up @@ -941,6 +1028,44 @@ func testVirtualServiceEndpoints(t *testing.T) {
},
},
},
{
title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingressgateway loadbalancer service with externalIPs",
targetNamespace: "testing1",
lbServices: []fakeIngressGatewayService{
{
externalIPs: []string{"8.8.8.8"},
namespace: "testing1",
},
},
gwConfigs: []fakeGatewayConfig{
{
name: "fake1",
namespace: "testing1",
dnsnames: [][]string{{"*"}},
},
},
vsConfigs: []fakeVirtualServiceConfig{
{
name: "vs1",
namespace: "testing1",
gateways: []string{"testing1/fake1"},
dnsnames: []string{"example.org"},
},
{
name: "vs2",
namespace: "testing2",
gateways: []string{"testing1/fake1"},
dnsnames: []string{"new.org"},
},
},
expected: []*endpoint.Endpoint{
{
DNSName: "example.org",
RecordType: endpoint.RecordTypeA,
Targets: endpoint.Targets{"8.8.8.8"},
},
},
},
{
title: "two simple virtualservices with one gateway on different namespaces and a target namespace, one ingress",
targetNamespace: "testing1",
Expand Down