k8gb-io/k8gb

GeoIP strategy

Opened this issue · 2 comments

Hey, I'm trying to use the geoip strategy with K8GB, but I'm finding some issues.

So far, this is what I've got. I created two different GslB objects, one with round robin strategy and the other with geoip strategy

apiVersion: k8gb.absa.oss/v1beta1
kind: Gslb
metadata:
  name: podinfo
  namespace: podinfo
spec:
  ingress:
    ingressClassName: nginx
    rules:
      - host: liqo.cloud.testanim.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: podinfo
                port:
                  name: http
  strategy:
    type: roundRobin
    splitBrainThresholdSeconds: 300 
    dnsTtlSeconds: 10
---
apiVersion: k8gb.absa.oss/v1beta1
kind: Gslb
metadata:
  name: podinfo-geoip
  namespace: podinfo
spec:
  ingress:
    ingressClassName: nginx
    rules:
      - host: liqogeoip.cloud.testanim.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: podinfo
                port:
                  name: http
  strategy:
    type: geoip
    splitBrainThresholdSeconds: 300 
    dnsTtlSeconds: 10

When running dig @10.171.61.137 -p 30053 liqo.cloud.testanim.com +subnet=10.10.72.146 I get what I'm expecting

; <<>> DiG 9.18.12-0ubuntu0.22.04.1-Ubuntu <<>> @10.171.61.137 -p 30053 liqo.cloud.testanim.com +subnet=10.10.72.146
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37104
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 014499dd2eb4484a01000000646ba17e63e50183e60d9223 (good)
; CLIENT-SUBNET: 10.10.72.146/32/0
;; QUESTION SECTION:
;liqo.cloud.testanim.com.       IN      A

;; ANSWER SECTION:
liqo.cloud.testanim.com. 10     IN      A       10.233.46.163
liqo.cloud.testanim.com. 10     IN      A       10.171.61.252
liqo.cloud.testanim.com. 10     IN      A       10.181.61.250

;; Query time: 89 msec
;; SERVER: 10.171.61.137#30053(10.171.61.137) (UDP)
;; WHEN: Mon May 22 18:07:40 BST 2023
;; MSG SIZE  rcvd: 140

Where the ips 10.233.46.163, 10.171.61.252, 10.181.61.250 are ingress load balancers in different clusters (adc, edc, stg).

However, when querying the geoip host dig @10.171.61.137 -p 30053 liqogeoip.cloud.testanim.com +subnet=10.10.72.146 I get the same ips

; <<>> DiG 9.18.12-0ubuntu0.22.04.1-Ubuntu <<>> @10.171.61.137 -p 30053 liqogeoip.cloud.testanim.com +subnet=10.10.72.146
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47130
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 7e02a912d39f2e3a01000000646ba2a731faf9d08627f0f2 (good)
; CLIENT-SUBNET: 10.10.72.146/32/0
;; QUESTION SECTION:
;liqogeoip.cloud.testanim.com.  IN      A

;; ANSWER SECTION:
liqogeoip.cloud.testanim.com. 10 IN     A       10.171.61.252
liqogeoip.cloud.testanim.com. 10 IN     A       10.233.46.163
liqogeoip.cloud.testanim.com. 10 IN     A       10.181.61.250

;; Query time: 99 msec
;; SERVER: 10.171.61.137#30053(10.171.61.137) (UDP)
;; WHEN: Mon May 22 18:12:37 BST 2023
;; MSG SIZE  rcvd: 145

This is the script I used to create my geoip db

package main

import (
	"log"
	"net"
	"os"

	"github.com/maxmind/mmdbwriter"
	"github.com/maxmind/mmdbwriter/inserter"
	"github.com/maxmind/mmdbwriter/mmdbtype"
)

func main() {
	fh, err := os.Create("geoip.mmdb")
	if err != nil {
		log.Fatal(err)
	}
	writer, _ := mmdbwriter.New(
		mmdbwriter.Options{
			DatabaseType: "Test-IP-DB",
			RecordSize:   24,
			IPVersion:    4,
			IncludeReservedNetworks: true,
		},
	)

	adcdata := mmdbtype.Map{
		"datacenter": mmdbtype.String("adc"),
	}

	stgdata := mmdbtype.Map{
		"datacenter": mmdbtype.String("stg"),
	}

	edcdata := mmdbtype.Map{
		"datacenter": mmdbtype.String("edc"),
	}

	_, adcLB, _ := net.ParseCIDR("10.233.46.163/32")
	_, stgLB, _ := net.ParseCIDR("10.171.61.252/32")
	_, edcLB, _ := net.ParseCIDR("10.181.61.250/32")
	
	if err := writer.InsertFunc(adcLB, inserter.TopLevelMergeWith(adcdata)); err != nil {
		log.Fatal(err)
	}
	if err := writer.InsertFunc(stgLB, inserter.TopLevelMergeWith(stgdata)); err != nil {
		log.Fatal(err)
	}
	if err := writer.InsertFunc(edcLB, inserter.TopLevelMergeWith(edcdata)); err != nil {
		log.Fatal(err)
	}

	_, test1, _ := net.ParseCIDR("10.10.0.0/16")
	if err := writer.InsertFunc(test1, inserter.TopLevelMergeWith(adcdata)); err != nil {
		log.Fatal(err)
	}
	_, test2, _ := net.ParseCIDR("10.10.72.146/32")
	if err := writer.InsertFunc(test2, inserter.TopLevelMergeWith(adcdata)); err != nil {
		log.Fatal(err)
	}

	_, err = writer.WriteTo(fh)
	if err != nil {
		log.Fatal(err)
	}
}	

Note that the CIDR range "10.10.0.0/16" (test1) includes my subnet IP "10.10.72.146/32" but I also specifically added it (test2). Based on this, I'm supposed to be getting JUST the adc load balancer (10.233.46.163). Any idea what I could be doing wrong?

Thanks for any suggestion!!

Let me try to summon our geoip strategy creator/guru :) @k0da do you see anything obvious here?

k0da commented

Hey, I'm trying to use the geoip strategy with K8GB, but I'm finding some issues.

So far, this is what I've got. I created two different GslB objects, one with round robin strategy and the other with geoip strategy

apiVersion: k8gb.absa.oss/v1beta1
kind: Gslb
metadata:
  name: podinfo
  namespace: podinfo
spec:
  ingress:
    ingressClassName: nginx
    rules:
      - host: liqo.cloud.testanim.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: podinfo
                port:
                  name: http
  strategy:
    type: roundRobin
    splitBrainThresholdSeconds: 300 
    dnsTtlSeconds: 10
---
apiVersion: k8gb.absa.oss/v1beta1
kind: Gslb
metadata:
  name: podinfo-geoip
  namespace: podinfo
spec:
  ingress:
    ingressClassName: nginx
    rules:
      - host: liqogeoip.cloud.testanim.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: podinfo
                port:
                  name: http
  strategy:
    type: geoip
    splitBrainThresholdSeconds: 300 
    dnsTtlSeconds: 10

When running dig @10.171.61.137 -p 30053 liqo.cloud.testanim.com +subnet=10.10.72.146 I get what I'm expecting

; <<>> DiG 9.18.12-0ubuntu0.22.04.1-Ubuntu <<>> @10.171.61.137 -p 30053 liqo.cloud.testanim.com +subnet=10.10.72.146
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37104
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 014499dd2eb4484a01000000646ba17e63e50183e60d9223 (good)
; CLIENT-SUBNET: 10.10.72.146/32/0
;; QUESTION SECTION:
;liqo.cloud.testanim.com.       IN      A

;; ANSWER SECTION:
liqo.cloud.testanim.com. 10     IN      A       10.233.46.163
liqo.cloud.testanim.com. 10     IN      A       10.171.61.252
liqo.cloud.testanim.com. 10     IN      A       10.181.61.250

;; Query time: 89 msec
;; SERVER: 10.171.61.137#30053(10.171.61.137) (UDP)
;; WHEN: Mon May 22 18:07:40 BST 2023
;; MSG SIZE  rcvd: 140

Where the ips 10.233.46.163, 10.171.61.252, 10.181.61.250 are ingress load balancers in different clusters (adc, edc, stg).

However, when querying the geoip host dig @10.171.61.137 -p 30053 liqogeoip.cloud.testanim.com +subnet=10.10.72.146 I get the same ips

; <<>> DiG 9.18.12-0ubuntu0.22.04.1-Ubuntu <<>> @10.171.61.137 -p 30053 liqogeoip.cloud.testanim.com +subnet=10.10.72.146
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47130
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 7e02a912d39f2e3a01000000646ba2a731faf9d08627f0f2 (good)
; CLIENT-SUBNET: 10.10.72.146/32/0
;; QUESTION SECTION:
;liqogeoip.cloud.testanim.com.  IN      A

;; ANSWER SECTION:
liqogeoip.cloud.testanim.com. 10 IN     A       10.171.61.252
liqogeoip.cloud.testanim.com. 10 IN     A       10.233.46.163
liqogeoip.cloud.testanim.com. 10 IN     A       10.181.61.250

;; Query time: 99 msec
;; SERVER: 10.171.61.137#30053(10.171.61.137) (UDP)
;; WHEN: Mon May 22 18:12:37 BST 2023
;; MSG SIZE  rcvd: 145

This is the script I used to create my geoip db

package main

import (
	"log"
	"net"
	"os"

	"github.com/maxmind/mmdbwriter"
	"github.com/maxmind/mmdbwriter/inserter"
	"github.com/maxmind/mmdbwriter/mmdbtype"
)

func main() {
	fh, err := os.Create("geoip.mmdb")
	if err != nil {
		log.Fatal(err)
	}
	writer, _ := mmdbwriter.New(
		mmdbwriter.Options{
			DatabaseType: "Test-IP-DB",
			RecordSize:   24,
			IPVersion:    4,
			IncludeReservedNetworks: true,
		},
	)

	adcdata := mmdbtype.Map{
		"datacenter": mmdbtype.String("adc"),
	}

	stgdata := mmdbtype.Map{
		"datacenter": mmdbtype.String("stg"),
	}

	edcdata := mmdbtype.Map{
		"datacenter": mmdbtype.String("edc"),
	}

	_, adcLB, _ := net.ParseCIDR("10.233.46.163/32")
	_, stgLB, _ := net.ParseCIDR("10.171.61.252/32")
	_, edcLB, _ := net.ParseCIDR("10.181.61.250/32")
	
	if err := writer.InsertFunc(adcLB, inserter.TopLevelMergeWith(adcdata)); err != nil {
		log.Fatal(err)
	}
	if err := writer.InsertFunc(stgLB, inserter.TopLevelMergeWith(stgdata)); err != nil {
		log.Fatal(err)
	}
	if err := writer.InsertFunc(edcLB, inserter.TopLevelMergeWith(edcdata)); err != nil {
		log.Fatal(err)
	}

	_, test1, _ := net.ParseCIDR("10.10.0.0/16")
	if err := writer.InsertFunc(test1, inserter.TopLevelMergeWith(adcdata)); err != nil {
		log.Fatal(err)
	}
	_, test2, _ := net.ParseCIDR("10.10.72.146/32")
	if err := writer.InsertFunc(test2, inserter.TopLevelMergeWith(adcdata)); err != nil {
		log.Fatal(err)
	}

	_, err = writer.WriteTo(fh)
	if err != nil {
		log.Fatal(err)
	}
}	

Note that the CIDR range "10.10.0.0/16" (test1) includes my subnet IP "10.10.72.146/32" but I also specifically added it (test2). Based on this, I'm supposed to be getting JUST the adc load balancer (10.233.46.163). Any idea what I could be doing wrong?

Thanks for any suggestion!!

Could you please paste your dnsenpoint objects from application namespace?