mirror of
https://github.com/kubenetworks/kubevpn.git
synced 2025-10-06 15:57:01 +08:00
feat: support dev docker in docker (dind)
This commit is contained in:
130
README.md
130
README.md
@@ -251,9 +251,10 @@ dns service ok
|
|||||||
Hello world!%
|
Hello world!%
|
||||||
```
|
```
|
||||||
|
|
||||||
### 本地进入开发模式
|
### Dev mode in local
|
||||||
|
|
||||||
将 Kubernetes pod 运行在本地的 Docker 容器中,同时配合 service mesh, 拦截带有制定 header 的流量到本地,或者所有的流量到本地
|
Run the Kubernetes pod in the local Docker container, and cooperate with the service mesh to intercept the traffic with
|
||||||
|
the specified header to the local, or all the traffic to the local.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
➜ ~ kubevpn dev deployment/authors -n kube-system --headers a=1 -p 9080:9080 -p 80:80
|
➜ ~ kubevpn dev deployment/authors -n kube-system --headers a=1 -p 9080:9080 -p 80:80
|
||||||
@@ -323,6 +324,131 @@ de9e2f8ab57d nginx:latest "/docker-entrypoint.…" 5 seconds
|
|||||||
➜ ~
|
➜ ~
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to specify the image to start the container locally, you can use the parameter `--docker-image`. When the
|
||||||
|
image does not exist locally, it will be pulled from the corresponding mirror warehouse. If you want to specify startup
|
||||||
|
parameters, you can use `--entrypoint` parameter, replace it with the command you want to execute, such
|
||||||
|
as `--entrypoint "tail -f /dev/null"`, for more parameters, see `kubevpn dev --help`.
|
||||||
|
|
||||||
|
Notice:
|
||||||
|
***If you want to start the development mode locally using Docker in Docker (DinD), since the program will read and
|
||||||
|
write the `/tmp` directory, you need to manually add the parameter `-v /tmp:/tmp` (outer docker) and other thing is you
|
||||||
|
need to special
|
||||||
|
parameter `--parent-container` (inner docker) for sharing network and pid ***
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run -it --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v /Users/naison/.kube/config:/root/.kube/config naison/kubevpn:v1.1.21
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
➜ ~ docker run -it --privileged -c authors -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v /Users/naison/.kube/vke:/root/.kube/config -v /Users/naison/Desktop/kubevpn/bin:/app naison/kubevpn:v1.1.21
|
||||||
|
root@4d0c3c4eae2b:/# hostname
|
||||||
|
4d0c3c4eae2b
|
||||||
|
root@4d0c3c4eae2b:/# kubevpn dev deployment/authors -n kube-system --image naison/kubevpn:v1.1.21 --headers user=naison --parent-container 4d0c3c4eae2b --entrypoint "tail -f /dev/null"
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
Warn: Use sudo to execute command kubevpn can not use user env KUBECONFIG.
|
||||||
|
Because of sudo user env and user env are different.
|
||||||
|
Current env KUBECONFIG value:
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
got cidr from cache
|
||||||
|
traffic manager not exist, try to create it...
|
||||||
|
pod [kubevpn-traffic-manager] status is Pending
|
||||||
|
Container Reason Message
|
||||||
|
|
||||||
|
pod [kubevpn-traffic-manager] status is Pending
|
||||||
|
Container Reason Message
|
||||||
|
control-plane ContainerCreating
|
||||||
|
vpn ContainerCreating
|
||||||
|
webhook ContainerCreating
|
||||||
|
|
||||||
|
pod [kubevpn-traffic-manager] status is Running
|
||||||
|
Container Reason Message
|
||||||
|
control-plane ContainerRunning
|
||||||
|
vpn ContainerRunning
|
||||||
|
webhook ContainerRunning
|
||||||
|
|
||||||
|
update ref count successfully
|
||||||
|
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
|
||||||
|
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
|
||||||
|
deployment "authors" successfully rolled out
|
||||||
|
port forward ready
|
||||||
|
tunnel connected
|
||||||
|
dns service ok
|
||||||
|
tar: removing leading '/' from member names
|
||||||
|
/tmp/3122262358661539581:/var/run/secrets/kubernetes.io/serviceaccount
|
||||||
|
tar: Removing leading `/' from member names
|
||||||
|
tar: Removing leading `/' from hard link targets
|
||||||
|
/tmp/7677066538742627822:/var/run/secrets/kubernetes.io/serviceaccount
|
||||||
|
latest: Pulling from naison/authors
|
||||||
|
Digest: sha256:2e7b2d6a4c6143cde888fcdb70ba091d533e11de70e13e151adff7510a5d52d4
|
||||||
|
Status: Downloaded newer image for naison/authors:latest
|
||||||
|
Created container: authors_kube-system_kubevpn_c68e4
|
||||||
|
Wait container authors_kube-system_kubevpn_c68e4 to be running...
|
||||||
|
Container authors_kube-system_kubevpn_c68e4 is running now
|
||||||
|
Created container: nginx_kube-system_kubevpn_c68e7
|
||||||
|
Wait container nginx_kube-system_kubevpn_c68e7 to be running...
|
||||||
|
Container nginx_kube-system_kubevpn_c68e7 is running now
|
||||||
|
/opt/microservices # ps -ef
|
||||||
|
PID USER TIME COMMAND
|
||||||
|
1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash
|
||||||
|
60 root 0:07 {kubevpn} /usr/bin/qemu-x86_64 kubevpn kubevpn dev deployment/authors -n kube-system --image naison/kubevpn:v1.1.21 --headers user=naison --parent
|
||||||
|
73 root 0:00 {tail} /usr/bin/qemu-x86_64 /usr/bin/tail tail -f /dev/null
|
||||||
|
80 root 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
92 root 0:00 {sh} /usr/bin/qemu-x86_64 /bin/sh /bin/sh
|
||||||
|
156 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
158 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
160 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
162 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
164 root 0:00 ps -ef
|
||||||
|
/opt/microservices # ls
|
||||||
|
app
|
||||||
|
/opt/microservices # apk add curl
|
||||||
|
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
|
||||||
|
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
|
||||||
|
(1/4) Installing brotli-libs (1.0.9-r5)
|
||||||
|
(2/4) Installing nghttp2-libs (1.43.0-r0)
|
||||||
|
(3/4) Installing libcurl (7.79.1-r5)
|
||||||
|
(4/4) Installing curl (7.79.1-r5)
|
||||||
|
Executing busybox-1.33.1-r3.trigger
|
||||||
|
OK: 8 MiB in 19 packages
|
||||||
|
/opt/microservices # curl localhost:80
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Welcome to nginx!</title>
|
||||||
|
<style>
|
||||||
|
html { color-scheme: light dark; }
|
||||||
|
body { width: 35em; margin: 0 auto;
|
||||||
|
font-family: Tahoma, Verdana, Arial, sans-serif; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Welcome to nginx!</h1>
|
||||||
|
<p>If you see this page, the nginx web server is successfully installed and
|
||||||
|
working. Further configuration is required.</p>
|
||||||
|
|
||||||
|
<p>For online documentation and support please refer to
|
||||||
|
<a href="http://nginx.org/">nginx.org</a>.<br/>
|
||||||
|
Commercial support is available at
|
||||||
|
<a href="http://nginx.com/">nginx.com</a>.</p>
|
||||||
|
|
||||||
|
<p><em>Thank you for using nginx.</em></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
/opt/microservices # ls
|
||||||
|
app
|
||||||
|
/opt/microservices # exit
|
||||||
|
prepare to exit, cleaning up
|
||||||
|
update ref count successfully
|
||||||
|
ref-count is zero, prepare to clean up resource
|
||||||
|
clean up successful
|
||||||
|
root@4d0c3c4eae2b:/# exit
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
### Multiple Protocol
|
### Multiple Protocol
|
||||||
|
|
||||||
- TCP
|
- TCP
|
||||||
|
123
README_ZH.md
123
README_ZH.md
@@ -251,7 +251,7 @@ Hello world!%
|
|||||||
|
|
||||||
### 本地进入开发模式
|
### 本地进入开发模式
|
||||||
|
|
||||||
将 Kubernetes pod 运行在本地的 Docker 容器中,同时配合 service mesh, 拦截带有制定 header 的流量到本地,或者所有的流量到本地
|
将 Kubernetes pod 运行在本地的 Docker 容器中,同时配合 service mesh, 拦截带有制定 header 的流量到本地,或者所有的流量到本地。这个开发模式依赖于本地 Docker .
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
➜ ~ kubevpn dev deployment/authors -n kube-system --headers a=1 -p 9080:9080 -p 80:80
|
➜ ~ kubevpn dev deployment/authors -n kube-system --headers a=1 -p 9080:9080 -p 80:80
|
||||||
@@ -319,6 +319,127 @@ de9e2f8ab57d nginx:latest "/docker-entrypoint.…" 5 seconds
|
|||||||
➜ ~
|
➜ ~
|
||||||
```
|
```
|
||||||
|
|
||||||
|
如果你想指定在本地启动容器的镜像, 可以使用参数 `--docker-image`, 当本地不存在该镜像时, 会从对应的镜像仓库拉取。如果你想指定启动参数,可以使用 `--entrypoint`
|
||||||
|
参数,替换为你想要执行的命令,比如 `--entrypoint "tail -f /dev/null"`, 更多使用参数,请参见 `kubevpn dev --help`.
|
||||||
|
|
||||||
|
注意:
|
||||||
|
***如果你想在本地使用 Docker in Docker (DinD) 的方式启动开发模式, 由于程序会读写 `/tmp` 目录,您需要手动添加参数 `-v /tmp:/tmp`, 还有一点需要注意, 如果使用 DinD
|
||||||
|
模式,为了共享容器网络和 pid, 还需要指定参数 `--parent-container` ***
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker run -it --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v /Users/naison/.kube/config:/root/.kube/config naison/kubevpn:v1.1.21
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
➜ ~ docker run -it --privileged -c authors -v /var/run/docker.sock:/var/run/docker.sock -v /tmp:/tmp -v /Users/naison/.kube/config:/root/.kube/config naison/kubevpn:v1.1.21
|
||||||
|
root@4d0c3c4eae2b:/# hostname
|
||||||
|
4d0c3c4eae2b
|
||||||
|
root@4d0c3c4eae2b:/# kubevpn dev deployment/authors -n kube-system --image naison/kubevpn:v1.1.21 --headers user=naison --parent-container 4d0c3c4eae2b --entrypoint "tail -f /dev/null"
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
Warn: Use sudo to execute command kubevpn can not use user env KUBECONFIG.
|
||||||
|
Because of sudo user env and user env are different.
|
||||||
|
Current env KUBECONFIG value:
|
||||||
|
----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
got cidr from cache
|
||||||
|
traffic manager not exist, try to create it...
|
||||||
|
pod [kubevpn-traffic-manager] status is Pending
|
||||||
|
Container Reason Message
|
||||||
|
|
||||||
|
pod [kubevpn-traffic-manager] status is Pending
|
||||||
|
Container Reason Message
|
||||||
|
control-plane ContainerCreating
|
||||||
|
vpn ContainerCreating
|
||||||
|
webhook ContainerCreating
|
||||||
|
|
||||||
|
pod [kubevpn-traffic-manager] status is Running
|
||||||
|
Container Reason Message
|
||||||
|
control-plane ContainerRunning
|
||||||
|
vpn ContainerRunning
|
||||||
|
webhook ContainerRunning
|
||||||
|
|
||||||
|
update ref count successfully
|
||||||
|
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
|
||||||
|
Waiting for deployment "authors" rollout to finish: 1 old replicas are pending termination...
|
||||||
|
deployment "authors" successfully rolled out
|
||||||
|
port forward ready
|
||||||
|
tunnel connected
|
||||||
|
dns service ok
|
||||||
|
tar: removing leading '/' from member names
|
||||||
|
/tmp/3122262358661539581:/var/run/secrets/kubernetes.io/serviceaccount
|
||||||
|
tar: Removing leading `/' from member names
|
||||||
|
tar: Removing leading `/' from hard link targets
|
||||||
|
/tmp/7677066538742627822:/var/run/secrets/kubernetes.io/serviceaccount
|
||||||
|
latest: Pulling from naison/authors
|
||||||
|
Digest: sha256:2e7b2d6a4c6143cde888fcdb70ba091d533e11de70e13e151adff7510a5d52d4
|
||||||
|
Status: Downloaded newer image for naison/authors:latest
|
||||||
|
Created container: authors_kube-system_kubevpn_c68e4
|
||||||
|
Wait container authors_kube-system_kubevpn_c68e4 to be running...
|
||||||
|
Container authors_kube-system_kubevpn_c68e4 is running now
|
||||||
|
Created container: nginx_kube-system_kubevpn_c68e7
|
||||||
|
Wait container nginx_kube-system_kubevpn_c68e7 to be running...
|
||||||
|
Container nginx_kube-system_kubevpn_c68e7 is running now
|
||||||
|
/opt/microservices # ps -ef
|
||||||
|
PID USER TIME COMMAND
|
||||||
|
1 root 0:00 {bash} /usr/bin/qemu-x86_64 /bin/bash /bin/bash
|
||||||
|
60 root 0:07 {kubevpn} /usr/bin/qemu-x86_64 kubevpn kubevpn dev deployment/authors -n kube-system --image naison/kubevpn:v1.1.21 --headers user=naison --parent
|
||||||
|
73 root 0:00 {tail} /usr/bin/qemu-x86_64 /usr/bin/tail tail -f /dev/null
|
||||||
|
80 root 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
92 root 0:00 {sh} /usr/bin/qemu-x86_64 /bin/sh /bin/sh
|
||||||
|
156 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
158 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
160 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
162 101 0:00 {nginx} /usr/bin/qemu-x86_64 /usr/sbin/nginx nginx -g daemon off;
|
||||||
|
164 root 0:00 ps -ef
|
||||||
|
/opt/microservices # ls
|
||||||
|
app
|
||||||
|
/opt/microservices # apk add curl
|
||||||
|
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
|
||||||
|
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
|
||||||
|
(1/4) Installing brotli-libs (1.0.9-r5)
|
||||||
|
(2/4) Installing nghttp2-libs (1.43.0-r0)
|
||||||
|
(3/4) Installing libcurl (7.79.1-r5)
|
||||||
|
(4/4) Installing curl (7.79.1-r5)
|
||||||
|
Executing busybox-1.33.1-r3.trigger
|
||||||
|
OK: 8 MiB in 19 packages
|
||||||
|
/opt/microservices # curl localhost:80
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Welcome to nginx!</title>
|
||||||
|
<style>
|
||||||
|
html { color-scheme: light dark; }
|
||||||
|
body { width: 35em; margin: 0 auto;
|
||||||
|
font-family: Tahoma, Verdana, Arial, sans-serif; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Welcome to nginx!</h1>
|
||||||
|
<p>If you see this page, the nginx web server is successfully installed and
|
||||||
|
working. Further configuration is required.</p>
|
||||||
|
|
||||||
|
<p>For online documentation and support please refer to
|
||||||
|
<a href="http://nginx.org/">nginx.org</a>.<br/>
|
||||||
|
Commercial support is available at
|
||||||
|
<a href="http://nginx.com/">nginx.com</a>.</p>
|
||||||
|
|
||||||
|
<p><em>Thank you for using nginx.</em></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
/opt/microservices # ls
|
||||||
|
app
|
||||||
|
/opt/microservices # exit
|
||||||
|
prepare to exit, cleaning up
|
||||||
|
update ref count successfully
|
||||||
|
ref-count is zero, prepare to clean up resource
|
||||||
|
clean up successful
|
||||||
|
root@4d0c3c4eae2b:/# exit
|
||||||
|
exit
|
||||||
|
```
|
||||||
|
|
||||||
### 支持多种协议
|
### 支持多种协议
|
||||||
|
|
||||||
- TCP
|
- TCP
|
||||||
|
@@ -2,6 +2,7 @@ package cmds
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/docker/cli/cli"
|
"github.com/docker/cli/cli"
|
||||||
"github.com/docker/cli/opts"
|
"github.com/docker/cli/opts"
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"k8s.io/client-go/util/retry"
|
"k8s.io/client-go/util/retry"
|
||||||
@@ -68,6 +70,24 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
|
|||||||
Workloads: []string{devOptions.Workload},
|
Workloads: []string{devOptions.Workload},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if devOptions.ParentContainer != "" {
|
||||||
|
client, _, err := dev.GetClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var inspect types.ContainerJSON
|
||||||
|
inspect, err = client.ContainerInspect(context.Background(), devOptions.ParentContainer)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if inspect.State == nil {
|
||||||
|
return fmt.Errorf("can not get container status, please make contianer name is valid")
|
||||||
|
}
|
||||||
|
if !inspect.State.Running {
|
||||||
|
return fmt.Errorf("container %s status is %s, expect is running, please make sure your outer docker name is correct", devOptions.ParentContainer, inspect.State.Status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := connect.InitClient(f); err != nil {
|
if err := connect.InitClient(f); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -123,6 +143,7 @@ func CmdDev(f cmdutil.Factory) *cobra.Command {
|
|||||||
|
|
||||||
// docker options
|
// docker options
|
||||||
cmd.Flags().Var(&devOptions.ExtraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)")
|
cmd.Flags().Var(&devOptions.ExtraHosts, "add-host", "Add a custom host-to-IP mapping (host:ip)")
|
||||||
|
cmd.Flags().StringVar(&devOptions.ParentContainer, "parent-container", "", "Parent container name if running in Docker (Docker in Docker)")
|
||||||
cmd.Flags().VarP(&devOptions.Volumes, "volume", "v", "Bind mount a volume")
|
cmd.Flags().VarP(&devOptions.Volumes, "volume", "v", "Bind mount a volume")
|
||||||
cmd.Flags().Var(&devOptions.Mounts, "mount", "Attach a filesystem mount to the container")
|
cmd.Flags().Var(&devOptions.Mounts, "mount", "Attach a filesystem mount to the container")
|
||||||
cmd.Flags().Var(&devOptions.Expose, "expose", "Expose a port or a range of ports")
|
cmd.Flags().Var(&devOptions.Expose, "expose", "Expose a port or a range of ports")
|
||||||
|
@@ -211,24 +211,27 @@ func GetVolume(ctx context.Context, f util.Factory, ns, pod string) (map[string]
|
|||||||
if volumeMount.MountPath == "/tmp" {
|
if volumeMount.MountPath == "/tmp" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
join := filepath.Join(os.TempDir(), strconv.Itoa(rand.Int()))
|
join := filepath.Join(os.TempDir(), strconv.Itoa(rand.Int()))
|
||||||
err = os.MkdirAll(join, 0755)
|
err = os.MkdirAll(join, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if volumeMount.SubPath != "" {
|
||||||
|
join = filepath.Join(join, volumeMount.SubPath)
|
||||||
|
}
|
||||||
// pod-namespace/pod-name:path
|
// pod-namespace/pod-name:path
|
||||||
remotePath := fmt.Sprintf("%s/%s:%s", ns, pod, volumeMount.MountPath)
|
remotePath := fmt.Sprintf("%s/%s:%s", ns, pod, volumeMount.MountPath)
|
||||||
stdIn, stdOut, stdErr := dockerterm.StdStreams()
|
stdIn, stdOut, stdErr := dockerterm.StdStreams()
|
||||||
copyOptions := cp.NewCopyOptions(genericclioptions.IOStreams{In: stdIn, Out: stdOut, ErrOut: stdErr})
|
copyOptions := cp.NewCopyOptions(genericclioptions.IOStreams{In: stdIn, Out: stdOut, ErrOut: stdErr})
|
||||||
copyOptions.Container = c.Name
|
copyOptions.Container = c.Name
|
||||||
|
copyOptions.MaxTries = 10
|
||||||
err = copyOptions.Complete(f, &cobra.Command{}, []string{remotePath, join})
|
err = copyOptions.Complete(f, &cobra.Command{}, []string{remotePath, join})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = copyOptions.Run()
|
err = copyOptions.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "Can not download volume %s path %s, ignore...", volumeMount.Name, volumeMount.MountPath)
|
_, _ = fmt.Fprintf(os.Stderr, "Can not download volume %s path %s, err: %v, ignore...\n", volumeMount.Name, volumeMount.MountPath, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
m = append(m, mount.Mount{
|
m = append(m, mount.Mount{
|
||||||
|
@@ -35,16 +35,17 @@ type Options struct {
|
|||||||
// docker options
|
// docker options
|
||||||
Platform string
|
Platform string
|
||||||
//Pull string // always, missing, never
|
//Pull string // always, missing, never
|
||||||
PublishAll bool
|
PublishAll bool
|
||||||
Entrypoint string
|
Entrypoint string
|
||||||
DockerImage string
|
DockerImage string
|
||||||
Publish opts.ListOpts
|
Publish opts.ListOpts
|
||||||
Expose opts.ListOpts
|
Expose opts.ListOpts
|
||||||
ExtraHosts opts.ListOpts
|
ExtraHosts opts.ListOpts
|
||||||
Env opts.ListOpts
|
ParentContainer string
|
||||||
Mounts opts.MountOpt
|
Env opts.ListOpts
|
||||||
Volumes opts.ListOpts
|
Mounts opts.MountOpt
|
||||||
VolumeDriver string
|
Volumes opts.ListOpts
|
||||||
|
VolumeDriver string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d Options) Main(ctx context.Context) error {
|
func (d Options) Main(ctx context.Context) error {
|
||||||
@@ -103,21 +104,42 @@ func (d Options) Main(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
var dockerCli *command.DockerCli
|
||||||
|
_, dockerCli, err = GetClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if d.ParentContainer != "" {
|
||||||
|
for _, config := range list[:] {
|
||||||
|
// remove expose port
|
||||||
|
config.config.ExposedPorts = nil
|
||||||
|
config.hostConfig.NetworkMode = containertypes.NetworkMode("container:" + d.ParentContainer)
|
||||||
|
config.hostConfig.PidMode = containertypes.PidMode("container:" + d.ParentContainer)
|
||||||
|
config.hostConfig.PortBindings = nil
|
||||||
|
|
||||||
// skip first
|
// remove dns
|
||||||
for _, config := range list[1:] {
|
config.hostConfig.DNS = nil
|
||||||
// remove expose port
|
config.hostConfig.DNSOptions = nil
|
||||||
config.config.ExposedPorts = nil
|
config.hostConfig.DNSSearch = nil
|
||||||
config.hostConfig.NetworkMode = containertypes.NetworkMode("container:" + list[0].containerName)
|
config.hostConfig.PublishAllPorts = false
|
||||||
config.hostConfig.PidMode = containertypes.PidMode("container:" + list[0].containerName)
|
config.config.Hostname = ""
|
||||||
config.hostConfig.PortBindings = nil
|
}
|
||||||
|
} else {
|
||||||
|
// skip first
|
||||||
|
for _, config := range list[1:] {
|
||||||
|
// remove expose port
|
||||||
|
config.config.ExposedPorts = nil
|
||||||
|
config.hostConfig.NetworkMode = containertypes.NetworkMode("container:" + list[0].containerName)
|
||||||
|
config.hostConfig.PidMode = containertypes.PidMode("container:" + list[0].containerName)
|
||||||
|
config.hostConfig.PortBindings = nil
|
||||||
|
|
||||||
// remove dns
|
// remove dns
|
||||||
config.hostConfig.DNS = nil
|
config.hostConfig.DNS = nil
|
||||||
config.hostConfig.DNSOptions = nil
|
config.hostConfig.DNSOptions = nil
|
||||||
config.hostConfig.DNSSearch = nil
|
config.hostConfig.DNSSearch = nil
|
||||||
config.hostConfig.PublishAllPorts = false
|
config.hostConfig.PublishAllPorts = false
|
||||||
config.config.Hostname = ""
|
config.config.Hostname = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.RollbackFuncList = append(handler.RollbackFuncList, func() {
|
handler.RollbackFuncList = append(handler.RollbackFuncList, func() {
|
||||||
@@ -127,11 +149,7 @@ func (d Options) Main(ctx context.Context) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, cli, err := GetClient()
|
return terminal(list[0].containerName, dockerCli)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return terminal(list[0].containerName, cli)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Run []*RunConfig
|
type Run []*RunConfig
|
||||||
|
@@ -50,7 +50,7 @@ func run(ctx context.Context, runConfig *RunConfig, cli *client.Client) (err err
|
|||||||
}
|
}
|
||||||
readCloser, err = cli.ImagePull(ctx, config.Image, types.ImagePullOptions{Platform: plat})
|
readCloser, err = cli.ImagePull(ctx, config.Image, types.ImagePullOptions{Platform: plat})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("can not pull image %s, err: %s, please make sure image is exist and can be pulled from local", config.Image, err)
|
||||||
}
|
}
|
||||||
defer readCloser.Close()
|
defer readCloser.Close()
|
||||||
_, stdout, _ := dockerterm.StdStreams()
|
_, stdout, _ := dockerterm.StdStreams()
|
||||||
@@ -64,7 +64,7 @@ func run(ctx context.Context, runConfig *RunConfig, cli *client.Client) (err err
|
|||||||
var create typescommand.CreateResponse
|
var create typescommand.CreateResponse
|
||||||
create, err = cli.ContainerCreate(ctx, config, hostConfig, networkConfig, platform, name)
|
create, err = cli.ContainerCreate(ctx, config, hostConfig, networkConfig, platform, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("failed to create container %s, err: %s", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("Created container: %s", name)
|
log.Infof("Created container: %s", name)
|
||||||
|
@@ -4,9 +4,14 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/docker/libnetwork/resolvconf"
|
||||||
miekgdns "github.com/miekg/dns"
|
miekgdns "github.com/miekg/dns"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@@ -42,16 +47,55 @@ func SetupDNS(clientConfig *miekgdns.ClientConfig, _ []string) error {
|
|||||||
}...)
|
}...)
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("cmd: %s, output: %s, error: %v\n", cmd.Args, string(output), err)
|
log.Debugf("failed to exec cmd: %s, message: %s, ignore", strings.Join(cmd.Args, " "), string(output))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
||||||
|
readFile, err := os.ReadFile(filename)
|
||||||
|
if err == nil {
|
||||||
|
resolvConf, err := miekgdns.ClientConfigFromReader(bytes.NewBufferString(string(readFile)))
|
||||||
|
if err == nil {
|
||||||
|
if len(resolvConf.Servers) != 0 {
|
||||||
|
clientConfig.Servers = append(clientConfig.Servers, resolvConf.Servers...)
|
||||||
|
}
|
||||||
|
if len(resolvConf.Search) != 0 {
|
||||||
|
clientConfig.Search = append(clientConfig.Search, resolvConf.Search...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return WriteResolvConf(*clientConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancelDNS() {
|
func CancelDNS() {
|
||||||
updateHosts("")
|
updateHosts("")
|
||||||
|
|
||||||
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
||||||
|
_ = os.Rename(getBackupFilename(filename), filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHostFile() string {
|
func GetHostFile() string {
|
||||||
return "/etc/hosts"
|
return "/etc/hosts"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func WriteResolvConf(config miekgdns.ClientConfig) error {
|
||||||
|
var options []string
|
||||||
|
if config.Ndots != 0 {
|
||||||
|
options = append(options, fmt.Sprintf("ndots:%d", config.Ndots))
|
||||||
|
}
|
||||||
|
if config.Attempts != 0 {
|
||||||
|
options = append(options, fmt.Sprintf("attempts:%d", config.Attempts))
|
||||||
|
}
|
||||||
|
if config.Timeout != 0 {
|
||||||
|
options = append(options, fmt.Sprintf("timeout:%d", config.Timeout))
|
||||||
|
}
|
||||||
|
|
||||||
|
filename := filepath.Join("/", "etc", "resolv.conf")
|
||||||
|
_ = os.Rename(filename, getBackupFilename(filename))
|
||||||
|
_, err := resolvconf.Build(filename, config.Servers, config.Search, options)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBackupFilename(filename string) string {
|
||||||
|
return filename + ".kubevpn_backup"
|
||||||
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/docker/libnetwork/resolvconf"
|
||||||
miekgdns "github.com/miekg/dns"
|
miekgdns "github.com/miekg/dns"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -178,3 +179,17 @@ func TestFix(t *testing.T) {
|
|||||||
println(s)
|
println(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestName(t *testing.T) {
|
||||||
|
temp, _ := os.CreateTemp("", "")
|
||||||
|
temp.Close()
|
||||||
|
println(temp.Name())
|
||||||
|
_, err := resolvconf.Build(temp.Name(), []string{"10.233.0.3", "10.233.97.159", "10.233.122.162"}, []string{
|
||||||
|
"vke-system.svc.cluster.local",
|
||||||
|
"svc.cluster.local",
|
||||||
|
"cluster.local",
|
||||||
|
}, []string{"ndots:5", "timeout:5"})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user