Skip to content

Commit

Permalink
Merge pull request kubernetes-retired#996 from elemental-lf/cephfs-cl…
Browse files Browse the repository at this point in the history
…uster-dns

cephfs-provisioner: Add cluster DNS resolution for Ceph monitors
  • Loading branch information
k8s-ci-robot authored Oct 16, 2018
2 parents 87f0009 + eeb1bfe commit 1ad6280
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 78 deletions.
26 changes: 25 additions & 1 deletion ceph/cephfs/cephfs-provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ import (
"errors"
"flag"
"fmt"
"net"
"os"
"os/exec"
"strconv"
"strings"

"github.com/golang/glog"
"github.com/kubernetes-incubator/external-storage/lib/controller"
"github.com/kubernetes-incubator/external-storage/lib/util"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/uuid"
Expand Down Expand Up @@ -63,6 +65,8 @@ type cephFSProvisioner struct {
secretNamespace string
// enable PVC quota
enableQuota bool
// cached IP address of cluster DNS service
dnsip string
}

func newCephFSProvisioner(client kubernetes.Interface, id string, secretNamespace string, enableQuota bool) controller.Provisioner {
Expand Down Expand Up @@ -303,10 +307,30 @@ func (p *cephFSProvisioner) parseParameters(parameters map[string]string) (strin
case "cluster":
cluster = v
case "monitors":
// Try to find DNS info in local cluster DNS so that the kubernetes
// host DNS config doesn't have to know about cluster DNS
if p.dnsip == "" {
p.dnsip = util.FindDNSIP(p.client)
}
glog.V(4).Infof("dnsip: %q\n", p.dnsip)
arr := strings.Split(v, ",")
for _, m := range arr {
mon = append(mon, m)
mhost, mport := util.SplitHostPort(m)
if p.dnsip != "" && net.ParseIP(mhost) == nil {
var lookup []string
if lookup, err = util.LookupHost(mhost, p.dnsip); err == nil {
for _, a := range lookup {
glog.V(1).Infof("adding %+v from mon lookup\n", a)
mon = append(mon, util.JoinHostPort(a, mport))
}
} else {
mon = append(mon, util.JoinHostPort(mhost, mport))
}
} else {
mon = append(mon, util.JoinHostPort(mhost, mport))
}
}
glog.V(4).Infof("final monitors list: %v\n", mon)
case "adminid":
adminID = v
case "adminsecretname":
Expand Down
4 changes: 4 additions & 0 deletions ceph/cephfs/deploy/rbac/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ rules:
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "update", "patch"]
- apiGroups: [""]
resources: ["services"]
resourceNames: ["kube-dns","coredns"]
verbs: ["list", "get"]
86 changes: 10 additions & 76 deletions ceph/rbd/pkg/provision/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"github.com/golang/glog"
"github.com/kubernetes-incubator/external-storage/lib/controller"
"github.com/kubernetes-incubator/external-storage/lib/util"
"github.com/miekg/dns"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -190,73 +189,6 @@ func (p *rbdProvisioner) Delete(volume *v1.PersistentVolume) error {
return p.rbdUtil.DeleteImage(image, opts)
}

// Look up the cluster dns service by label "coredns", falling back to "kube-dns" if not found
func findDNSIP(p *rbdProvisioner) (dnsip string) {
// find DNS server address through client API
// cache result in rbdProvisioner
var dnssvc *v1.Service

if p.dnsip == "" {
coredns, err := p.client.CoreV1().Services(metav1.NamespaceSystem).Get("coredns", metav1.GetOptions{})

if err != nil {
glog.Warningf("error getting coredns service: %v. Falling back to kube-dns\n", err)
kubedns, err := p.client.CoreV1().Services(metav1.NamespaceSystem).Get("kube-dns", metav1.GetOptions{})
if err != nil {
glog.Errorf("error getting kube-dns service: %v\n", err)
return ""
}
dnssvc = kubedns
} else {
dnssvc = coredns
}

if len(dnssvc.Spec.ClusterIP) == 0 {
glog.Errorf("DNS service ClusterIP bad\n")
return ""
}

p.dnsip = dnssvc.Spec.ClusterIP
}

return p.dnsip
}

// Look up hostname in dns server serverip.
func lookuphost(hostname string, serverip string) (iplist []string, err error) {
glog.V(4).Infof("lookuphost %q on %q\n", hostname, serverip)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(hostname), dns.TypeA)
in, err := dns.Exchange(m, joinHostPort(serverip, "53"))
if err != nil {
glog.Errorf("dns lookup of %q failed: err %v", hostname, err)
return nil, err
}
for _, a := range in.Answer {
glog.V(4).Infof("lookuphost answer: %v\n", a)
if t, ok := a.(*dns.A); ok {
iplist = append(iplist, t.A.String())
}
}

return iplist, nil
}

func splitHostPort(hostport string) (host, port string) {
host, port, err := net.SplitHostPort(hostport)
if err != nil {
host, port = hostport, ""
}
return host, port
}

func joinHostPort(host, port string) (hostport string) {
if port != "" {
return net.JoinHostPort(host, port)
}
return host
}

func (p *rbdProvisioner) parseParameters(parameters map[string]string) (*rbdProvisionOptions, error) {
// options with default values
opts := &rbdProvisionOptions{
Expand All @@ -276,23 +208,25 @@ func (p *rbdProvisioner) parseParameters(parameters map[string]string) (*rbdProv
case "monitors":
// Try to find DNS info in local cluster DNS so that the kubernetes
// host DNS config doesn't have to know about cluster DNS
dnsip := findDNSIP(p)
glog.V(4).Infof("dnsip: %q\n", dnsip)
if p.dnsip == "" {
p.dnsip = util.FindDNSIP(p.client)
}
glog.V(4).Infof("dnsip: %q\n", p.dnsip)
arr := strings.Split(v, ",")
for _, m := range arr {
mhost, mport := splitHostPort(m)
if dnsip != "" && net.ParseIP(mhost) == nil {
mhost, mport := util.SplitHostPort(m)
if p.dnsip != "" && net.ParseIP(mhost) == nil {
var lookup []string
if lookup, err = lookuphost(mhost, dnsip); err == nil {
if lookup, err = util.LookupHost(mhost, p.dnsip); err == nil {
for _, a := range lookup {
glog.V(1).Infof("adding %+v from mon lookup\n", a)
opts.monitors = append(opts.monitors, joinHostPort(a, mport))
opts.monitors = append(opts.monitors, util.JoinHostPort(a, mport))
}
} else {
opts.monitors = append(opts.monitors, joinHostPort(mhost, mport))
opts.monitors = append(opts.monitors, util.JoinHostPort(mhost, mport))
}
} else {
opts.monitors = append(opts.monitors, joinHostPort(mhost, mport))
opts.monitors = append(opts.monitors, util.JoinHostPort(mhost, mport))
}
}
glog.V(4).Infof("final monitors list: %v\n", opts.monitors)
Expand Down
74 changes: 73 additions & 1 deletion lib/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ limitations under the License.

package util

import "k8s.io/api/core/v1"
import (
"github.com/golang/glog"
"github.com/miekg/dns"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"net"
)

// Common allocation units
const (
Expand Down Expand Up @@ -65,3 +72,68 @@ func AccessModesContainedInAll(indexedModes []v1.PersistentVolumeAccessMode, req
func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool {
return pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock
}

// FindDNSIP looks up the cluster DNS service by label "coredns", falling back to "kube-dns" if not found
func FindDNSIP(client kubernetes.Interface) (dnsip string) {
// find DNS server address through client API
// cache result in rbdProvisioner
var dnssvc *v1.Service

coredns, err := client.CoreV1().Services(metav1.NamespaceSystem).Get("coredns", metav1.GetOptions{})

if err != nil {
glog.Warningf("error getting coredns service: %v. Falling back to kube-dns\n", err)
kubedns, err := client.CoreV1().Services(metav1.NamespaceSystem).Get("kube-dns", metav1.GetOptions{})
if err != nil {
glog.Errorf("error getting kube-dns service: %v\n", err)
return ""
}
dnssvc = kubedns
} else {
dnssvc = coredns
}

if len(dnssvc.Spec.ClusterIP) == 0 {
glog.Errorf("DNS service ClusterIP bad\n")
return ""
}

return dnssvc.Spec.ClusterIP
}

// LookupHost looks up IP addresses of hostname on specified DNS server
func LookupHost(hostname string, serverip string) (iplist []string, err error) {
glog.V(4).Infof("lookuphost %q on %q\n", hostname, serverip)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(hostname), dns.TypeA)
in, err := dns.Exchange(m, JoinHostPort(serverip, "53"))
if err != nil {
glog.Errorf("dns lookup of %q failed: err %v", hostname, err)
return nil, err
}
for _, a := range in.Answer {
glog.V(4).Infof("lookuphost answer: %v\n", a)
if t, ok := a.(*dns.A); ok {
iplist = append(iplist, t.A.String())
}
}

return iplist, nil
}

// SplitHostPort split a string into host and port (port is optional)
func SplitHostPort(hostport string) (host, port string) {
host, port, err := net.SplitHostPort(hostport)
if err != nil {
host, port = hostport, ""
}
return host, port
}

// JoinHostPort joins a hostname and an optional port
func JoinHostPort(host, port string) (hostport string) {
if port != "" {
return net.JoinHostPort(host, port)
}
return host
}

0 comments on commit 1ad6280

Please sign in to comment.