mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-12-24 11:51:13 +08:00
finish dns service on unix
This commit is contained in:
@@ -9,21 +9,20 @@ import (
|
|||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"kubevpn/remote"
|
||||||
|
"kubevpn/util"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Dns(clientset *kubernetes.Clientset) error {
|
func Dns(ip string) error {
|
||||||
var dnsIP string
|
|
||||||
var err error
|
var err error
|
||||||
if dnsIP, err = GetDNSIp(clientset); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = os.MkdirAll(filepath.Join("/", "etc", "resolver"), fs.ModePerm); err != nil {
|
if err = os.MkdirAll(filepath.Join("/", "etc", "resolver"), fs.ModePerm); err != nil {
|
||||||
log.Error(err)
|
log.Error(err)
|
||||||
}
|
}
|
||||||
filename := filepath.Join("/", "etc", "resolver", "local")
|
filename := filepath.Join("/", "etc", "resolver", "local")
|
||||||
fileContent := "nameserver " + dnsIP
|
fileContent := "nameserver " + ip
|
||||||
return ioutil.WriteFile(filename, []byte(fileContent), fs.ModePerm)
|
return ioutil.WriteFile(filename, []byte(fileContent), fs.ModePerm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,3 +38,14 @@ func GetDNSIp(clientset *kubernetes.Clientset) (string, error) {
|
|||||||
}
|
}
|
||||||
return serviceList.Items[0].Spec.ClusterIP, nil
|
return serviceList.Items[0].Spec.ClusterIP, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetDNSServiceIpFromPod(clientset *kubernetes.Clientset, restclient *rest.RESTClient, config *rest.Config, podName, namespace string) string {
|
||||||
|
//if ip, err := GetDNSIp(clientset); err == nil && len(ip) != 0 {
|
||||||
|
// return ip
|
||||||
|
//}
|
||||||
|
if ip, err := util.Shell(clientset, restclient, config, remote.TrafficManager, namespace, "cat /etc/resolv.conf | grep nameserver | awk '{print$2}'"); err == nil && len(ip) != 0 {
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
log.Fatal("this should not happened")
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
47
pkg/main.go
47
pkg/main.go
@@ -6,44 +6,47 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
restclient "k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/clientcmd"
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
"k8s.io/client-go/util/homedir"
|
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||||
"kubevpn/dns"
|
"kubevpn/dns"
|
||||||
"kubevpn/exe"
|
"kubevpn/exe"
|
||||||
"kubevpn/remote"
|
"kubevpn/remote"
|
||||||
|
"kubevpn/util"
|
||||||
"net"
|
"net"
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
baseCfg = &baseConfig{}
|
baseCfg = &baseConfig{}
|
||||||
namespace string
|
namespace string
|
||||||
clientset *kubernetes.Clientset
|
clientset *kubernetes.Clientset
|
||||||
config *restclient.Config
|
restclient *rest.RESTClient
|
||||||
name string
|
config *rest.Config
|
||||||
|
name string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
var err error
|
var err error
|
||||||
clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
|
configFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()
|
||||||
&clientcmd.ClientConfigLoadingRules{
|
configFlags.KubeConfig = &clientcmd.RecommendedHomeFile
|
||||||
ExplicitPath: filepath.Join(homedir.HomeDir(), clientcmd.RecommendedHomeDir, clientcmd.RecommendedFileName),
|
f := cmdutil.NewFactory(cmdutil.NewMatchVersionFlags(configFlags))
|
||||||
},
|
|
||||||
nil,
|
if config, err = f.ToRESTConfig(); err != nil {
|
||||||
)
|
|
||||||
config, err = clientConfig.ClientConfig()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
clientset, err = kubernetes.NewForConfig(config)
|
if restclient, err = rest.RESTClientFor(config); err != nil {
|
||||||
if err != nil {
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if clientset, err = kubernetes.NewForConfig(config); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if namespace, _, err = f.ToRawKubeConfigLoader().Namespace(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
namespace, _, _ = clientConfig.Namespace()
|
|
||||||
|
|
||||||
k8sCIDR, err := getCIDR(clientset, namespace)
|
k8sCIDR, err := getCIDR(clientset, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -80,7 +83,7 @@ func main() {
|
|||||||
readyChan := make(chan struct{})
|
readyChan := make(chan struct{})
|
||||||
stop := make(chan struct{})
|
stop := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
err := PortForwardPod(config,
|
err := util.PortForwardPod(config,
|
||||||
clientset,
|
clientset,
|
||||||
name,
|
name,
|
||||||
namespace,
|
namespace,
|
||||||
@@ -94,8 +97,8 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
<-readyChan
|
<-readyChan
|
||||||
log.Info("port forward ready")
|
log.Info("port forward ready")
|
||||||
|
dnsServiceIp := dns.GetDNSServiceIpFromPod(clientset, restclient, config, remote.TrafficManager, namespace)
|
||||||
if err := dns.Dns(clientset); err != nil {
|
if err := dns.Dns(dnsServiceIp); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
} else {
|
} else {
|
||||||
log.Info("dns service ok")
|
log.Info("dns service ok")
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package main
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/moby/term"
|
dockerterm "github.com/moby/term"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"io"
|
||||||
v12 "k8s.io/api/autoscaling/v1"
|
v12 "k8s.io/api/autoscaling/v1"
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
@@ -22,11 +23,11 @@ import (
|
|||||||
clientgowatch "k8s.io/client-go/tools/watch"
|
clientgowatch "k8s.io/client-go/tools/watch"
|
||||||
"k8s.io/client-go/transport/spdy"
|
"k8s.io/client-go/transport/spdy"
|
||||||
"k8s.io/client-go/util/retry"
|
"k8s.io/client-go/util/retry"
|
||||||
"k8s.io/kubectl/pkg/cmd/util"
|
"k8s.io/kubectl/pkg/cmd/exec"
|
||||||
term2 "k8s.io/kubectl/pkg/util/term"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -152,95 +153,58 @@ func ScaleDeploymentReplicasTo(options *kubernetes.Clientset, name, namespace st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type shellOptions interface {
|
func Shell(clientset *kubernetes.Clientset, restclient *rest.RESTClient, config *rest.Config, podName, namespace, cmd string) (string, error) {
|
||||||
GetNamespace() string
|
pod, err := clientset.CoreV1().Pods(namespace).Get(context.Background(), podName, metav1.GetOptions{})
|
||||||
GetDeployment() string
|
|
||||||
GetLocalDir() string
|
|
||||||
GetRemoteDir() string
|
|
||||||
GetKubeconfig() string
|
|
||||||
}
|
|
||||||
|
|
||||||
func Shell(client *kubernetes.Clientset, options shellOptions) error {
|
|
||||||
deployment, err2 := client.AppsV1().Deployments(options.GetNamespace()).
|
|
||||||
Get(context.TODO(), options.GetDeployment(), metav1.GetOptions{})
|
|
||||||
if err2 != nil {
|
|
||||||
log.Error(err2)
|
|
||||||
}
|
|
||||||
labelMap, _ := metav1.LabelSelectorAsMap(deployment.Spec.Selector)
|
|
||||||
pods, err := client.CoreV1().Pods(options.GetNamespace()).
|
|
||||||
List(context.TODO(), metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("get kubedev pod error: %v", err)
|
return "", err
|
||||||
}
|
}
|
||||||
if len(pods.Items) <= 0 {
|
if pod.Status.Phase == v1.PodSucceeded || pod.Status.Phase == v1.PodFailed {
|
||||||
log.Warnf("this should not happened, pods items length: %d", len(pods.Items))
|
err = fmt.Errorf("cannot exec into a container in a completed pod; current phase is %s", pod.Status.Phase)
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
index := -1
|
containerName := pod.Spec.Containers[0].Name
|
||||||
for i, pod := range pods.Items {
|
stdin, stdout, stderr := dockerterm.StdStreams()
|
||||||
if pod.Status.Phase == v1.PodRunning {
|
|
||||||
index = i
|
stdoutBuf := bytes.NewBuffer(nil)
|
||||||
break
|
stdout = io.MultiWriter(stdout, stdoutBuf)
|
||||||
}
|
StreamOptions := exec.StreamOptions{
|
||||||
|
Namespace: namespace,
|
||||||
|
PodName: podName,
|
||||||
|
ContainerName: containerName,
|
||||||
|
IOStreams: genericclioptions.IOStreams{In: stdin, Out: stdout, ErrOut: stderr},
|
||||||
}
|
}
|
||||||
if index < 0 {
|
Executor := &exec.DefaultRemoteExecutor{}
|
||||||
return fmt.Errorf("cannot exec into a container in a completed pod; current phase is %s", pods.Items[0].Status.Phase)
|
// ensure we can recover the terminal while attached
|
||||||
}
|
tt := StreamOptions.SetupTTY()
|
||||||
stdin, stdout, stderr := term.StdStreams()
|
|
||||||
tty := term2.TTY{
|
var sizeQueue remotecommand.TerminalSizeQueue
|
||||||
Out: stdout,
|
if tt.Raw {
|
||||||
In: stdin,
|
// this call spawns a goroutine to monitor/update the terminal size
|
||||||
Raw: true,
|
sizeQueue = tt.MonitorSize(tt.GetSize())
|
||||||
}
|
|
||||||
if !tty.IsTerminalIn() {
|
// unset p.Err if it was previously set because both stdout and stderr go over p.Out when tty is
|
||||||
log.Error("Unable to use a TTY - input is not a terminal or the right kind of file")
|
// true
|
||||||
}
|
StreamOptions.ErrOut = nil
|
||||||
var terminalSizeQueue remotecommand.TerminalSizeQueue
|
|
||||||
if tty.Raw {
|
|
||||||
terminalSizeQueue = tty.MonitorSize(tty.GetSize())
|
|
||||||
}
|
|
||||||
f := func() error {
|
|
||||||
configFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()
|
|
||||||
kubeconfig := options.GetKubeconfig()
|
|
||||||
configFlags.KubeConfig = &kubeconfig
|
|
||||||
namespace := options.GetNamespace()
|
|
||||||
configFlags.Namespace = &namespace
|
|
||||||
f := util.NewFactory(util.NewMatchVersionFlags(configFlags))
|
|
||||||
config, _ := f.ToRESTConfig()
|
|
||||||
restClient, err := rest.RESTClientFor(config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
req := restClient.Post().
|
|
||||||
Resource("pods").
|
|
||||||
Name(pods.Items[index].Name).
|
|
||||||
Namespace(options.GetNamespace()).
|
|
||||||
SubResource("exec").
|
|
||||||
VersionedParams(
|
|
||||||
&v1.PodExecOptions{
|
|
||||||
Container: pods.Items[index].Spec.Containers[0].Name,
|
|
||||||
Command: []string{"sh", "-c", "(bash||sh)"},
|
|
||||||
Stdin: true,
|
|
||||||
Stdout: true,
|
|
||||||
Stderr: true,
|
|
||||||
TTY: true,
|
|
||||||
},
|
|
||||||
scheme.ParameterCodec,
|
|
||||||
)
|
|
||||||
executor, err := remotecommand.NewSPDYExecutor(config, "POST", req.URL())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return executor.Stream(remotecommand.StreamOptions{
|
|
||||||
Stdin: tty.In,
|
|
||||||
Stdout: tty.Out,
|
|
||||||
Stderr: stderr,
|
|
||||||
Tty: true,
|
|
||||||
TerminalSizeQueue: terminalSizeQueue,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = tty.Safe(f); err != nil {
|
fn := func() error {
|
||||||
return err
|
req := restclient.Post().
|
||||||
|
Resource("pods").
|
||||||
|
Name(pod.Name).
|
||||||
|
Namespace(pod.Namespace).
|
||||||
|
SubResource("exec")
|
||||||
|
req.VersionedParams(&v1.PodExecOptions{
|
||||||
|
Container: containerName,
|
||||||
|
Command: []string{"sh", "-c", cmd},
|
||||||
|
Stdin: StreamOptions.Stdin,
|
||||||
|
Stdout: StreamOptions.Out != nil,
|
||||||
|
Stderr: StreamOptions.ErrOut != nil,
|
||||||
|
TTY: tt.Raw,
|
||||||
|
}, scheme.ParameterCodec)
|
||||||
|
return Executor.Execute("POST", req.URL(), config, StreamOptions.In, StreamOptions.Out, StreamOptions.ErrOut, tt.Raw, sizeQueue)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
err = tt.Safe(fn)
|
||||||
|
return strings.TrimRight(stdoutBuf.String(), "\n"), err
|
||||||
}
|
}
|
||||||
51
util/util_test.go
Normal file
51
util/util_test.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"k8s.io/kubectl/pkg/cmd/util"
|
||||||
|
"kubevpn/remote"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
namespace string
|
||||||
|
clientset *kubernetes.Clientset
|
||||||
|
restclient *rest.RESTClient
|
||||||
|
config *rest.Config
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShell(t *testing.T) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
configFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()
|
||||||
|
configFlags.KubeConfig = &clientcmd.RecommendedHomeFile
|
||||||
|
f := util.NewFactory(util.NewMatchVersionFlags(configFlags))
|
||||||
|
|
||||||
|
if config, err = f.ToRESTConfig(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if restclient, err = rest.RESTClientFor(config); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if clientset, err = kubernetes.NewForConfig(config); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if namespace, _, err = f.ToRawKubeConfigLoader().Namespace(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := Shell(clientset, restclient, config, remote.TrafficManager, namespace, "cat /etc/resolv.conf | grep nameserver | awk '{print$2}'")
|
||||||
|
serviceList, err := clientset.CoreV1().Services(v1.NamespaceSystem).List(context.Background(), v1.ListOptions{
|
||||||
|
FieldSelector: fields.OneTermEqualSelector("metadata.name", "kube-dns").String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
fmt.Println(out == serviceList.Items[0].Spec.ClusterIP)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user