Support dns-controller compat mode for pod source

This commit is contained in:
Ole Markus With 2021-04-02 12:12:58 +02:00
parent 7a16ab46fa
commit 73469a0852
4 changed files with 111 additions and 12 deletions

View File

@ -284,7 +284,7 @@ Here's a rough outline on what is to come (subject to change):
- [ ] Ability to replace Kops' [DNS Controller](https://github.com/kubernetes/kops/tree/HEAD/dns-controller) - [ ] Ability to replace Kops' [DNS Controller](https://github.com/kubernetes/kops/tree/HEAD/dns-controller)
- [x] Add support for pod source - [x] Add support for pod source
- [ ] Add support for DNS Controller annotations for pod, ingress, and service sources - [x] Add support for DNS Controller annotations for pod and service sources
- [ ] Add support for kOps gossip provider - [ ] Add support for kOps gossip provider
- [x] Ability to replace Zalando's [Mate](https://github.com/linki/mate) - [x] Ability to replace Zalando's [Mate](https://github.com/linki/mate)
- [x] Ability to replace Molecule Software's [route53-kubernetes](https://github.com/wearemolecule/route53-kubernetes) - [x] Ability to replace Molecule Software's [route53-kubernetes](https://github.com/wearemolecule/route53-kubernetes)

View File

@ -34,14 +34,15 @@ import (
) )
type podSource struct { type podSource struct {
client kubernetes.Interface client kubernetes.Interface
namespace string namespace string
podInformer coreinformers.PodInformer podInformer coreinformers.PodInformer
nodeInformer coreinformers.NodeInformer nodeInformer coreinformers.NodeInformer
compatibility string
} }
// NewPodSource creates a new podSource with the given config. // NewPodSource creates a new podSource with the given config.
func NewPodSource(kubeClient kubernetes.Interface, namespace string) (Source, error) { func NewPodSource(kubeClient kubernetes.Interface, namespace string, compatibility string) (Source, error) {
informerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, 0, kubeinformers.WithNamespace(namespace)) informerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClient, 0, kubeinformers.WithNamespace(namespace))
podInformer := informerFactory.Core().V1().Pods() podInformer := informerFactory.Core().V1().Pods()
nodeInformer := informerFactory.Core().V1().Nodes() nodeInformer := informerFactory.Core().V1().Nodes()
@ -71,10 +72,11 @@ func NewPodSource(kubeClient kubernetes.Interface, namespace string) (Source, er
} }
return &podSource{ return &podSource{
client: kubeClient, client: kubeClient,
podInformer: podInformer, podInformer: podInformer,
nodeInformer: nodeInformer, nodeInformer: nodeInformer,
namespace: namespace, namespace: namespace,
compatibility: compatibility,
}, nil }, nil
} }
@ -114,6 +116,28 @@ func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error
} }
} }
} }
if ps.compatibility == "dns-controller" {
if domain, ok := pod.Annotations[dnsControllerInternalHostnameAnnotationKey]; ok {
if _, ok := domains[domain]; !ok {
domains[domain] = []string{}
}
domains[domain] = append(domains[domain], pod.Status.PodIP)
}
if domain, ok := pod.Annotations[dnsControllerHostnameAnnotationKey]; ok {
if _, ok := domains[domain]; !ok {
domains[domain] = []string{}
}
node, _ := ps.nodeInformer.Lister().Get(pod.Spec.NodeName)
for _, address := range node.Status.Addresses {
if address.Type == corev1.NodeExternalIP {
domains[domain] = append(domains[domain], address.Address)
}
}
}
}
} }
endpoints := []*endpoint.Endpoint{} endpoints := []*endpoint.Endpoint{}
for domain, targets := range domains { for domain, targets := range domains {

View File

@ -32,6 +32,7 @@ func TestPodSource(t *testing.T) {
for _, tc := range []struct { for _, tc := range []struct {
title string title string
targetNamespace string targetNamespace string
compatibility string
expected []*endpoint.Endpoint expected []*endpoint.Endpoint
expectError bool expectError bool
nodes []*corev1.Node nodes []*corev1.Node
@ -40,6 +41,7 @@ func TestPodSource(t *testing.T) {
{ {
"create records based on pod's external and internal IPs", "create records based on pod's external and internal IPs",
"", "",
"",
[]*endpoint.Endpoint{ []*endpoint.Endpoint{
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA}, {DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA}, {DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
@ -106,9 +108,80 @@ func TestPodSource(t *testing.T) {
}, },
}, },
}, },
{
"create records based on pod's external and internal IPs using DNS Controller annotations",
"",
"dns-controller",
[]*endpoint.Endpoint{
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1", "54.10.11.2"}, RecordType: endpoint.RecordTypeA},
{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1", "10.0.1.2"}, RecordType: endpoint.RecordTypeA},
},
false,
[]*corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-node1",
},
Status: corev1.NodeStatus{
Addresses: []corev1.NodeAddress{
{Type: corev1.NodeExternalIP, Address: "54.10.11.1"},
{Type: corev1.NodeInternalIP, Address: "10.0.1.1"},
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-node2",
},
Status: corev1.NodeStatus{
Addresses: []corev1.NodeAddress{
{Type: corev1.NodeExternalIP, Address: "54.10.11.2"},
{Type: corev1.NodeInternalIP, Address: "10.0.1.2"},
},
},
},
},
[]*corev1.Pod{
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-pod1",
Namespace: "kube-system",
Annotations: map[string]string{
dnsControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
dnsControllerHostnameAnnotationKey: "a.foo.example.org",
},
},
Spec: corev1.PodSpec{
HostNetwork: true,
NodeName: "my-node1",
},
Status: corev1.PodStatus{
PodIP: "10.0.1.1",
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "my-pod2",
Namespace: "kube-system",
Annotations: map[string]string{
dnsControllerInternalHostnameAnnotationKey: "internal.a.foo.example.org",
dnsControllerHostnameAnnotationKey: "a.foo.example.org",
},
},
Spec: corev1.PodSpec{
HostNetwork: true,
NodeName: "my-node2",
},
Status: corev1.PodStatus{
PodIP: "10.0.1.2",
},
},
},
},
{ {
"create multiple records", "create multiple records",
"", "",
"",
[]*endpoint.Endpoint{ []*endpoint.Endpoint{
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA}, {DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
{DNSName: "b.foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA}, {DNSName: "b.foo.example.org", Targets: endpoint.Targets{"54.10.11.2"}, RecordType: endpoint.RecordTypeA},
@ -176,6 +249,7 @@ func TestPodSource(t *testing.T) {
{ {
"pods with hostNetwore=false should be ignored", "pods with hostNetwore=false should be ignored",
"", "",
"",
[]*endpoint.Endpoint{ []*endpoint.Endpoint{
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA}, {DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA}, {DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA},
@ -245,6 +319,7 @@ func TestPodSource(t *testing.T) {
{ {
"only watch a given namespace", "only watch a given namespace",
"kube-system", "kube-system",
"",
[]*endpoint.Endpoint{ []*endpoint.Endpoint{
{DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA}, {DNSName: "a.foo.example.org", Targets: endpoint.Targets{"54.10.11.1"}, RecordType: endpoint.RecordTypeA},
{DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA}, {DNSName: "internal.a.foo.example.org", Targets: endpoint.Targets{"10.0.1.1"}, RecordType: endpoint.RecordTypeA},
@ -332,7 +407,7 @@ func TestPodSource(t *testing.T) {
} }
} }
client, err := NewPodSource(kubernetes, tc.targetNamespace) client, err := NewPodSource(kubernetes, tc.targetNamespace, tc.compatibility)
require.NoError(t, err) require.NoError(t, err)
endpoints, err := client.Endpoints(ctx) endpoints, err := client.Endpoints(ctx)

View File

@ -193,7 +193,7 @@ func BuildWithConfig(source string, p ClientGenerator, cfg *Config) (Source, err
if err != nil { if err != nil {
return nil, err return nil, err
} }
return NewPodSource(client, cfg.Namespace) return NewPodSource(client, cfg.Namespace, cfg.Compatibility)
case "istio-gateway": case "istio-gateway":
kubernetesClient, err := p.KubeClient() kubernetesClient, err := p.KubeClient()
if err != nil { if err != nil {